Merge "Collect libc++ headers that have no file name extensions"
diff --git a/scripts/aday b/scripts/aday
index 3d97809..f4479b4 100755
--- a/scripts/aday
+++ b/scripts/aday
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 import datetime
 import sys
 
@@ -8,7 +8,7 @@
     day = int(build[3:5])
 
     month = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.index(letter) * 3
-    year = 2009 + (month / 12)
+    year = 2009 + (month // 12)
     month %= 12
 
     return datetime.date(year, month + 1, 1) + datetime.timedelta(days=day - 1)
@@ -18,4 +18,4 @@
     if len(sys.argv) != 2:
         sys.exit('usage: aday BUILD_NUMBER')
 
-    print build_to_date(sys.argv[1])
+    print(build_to_date(sys.argv[1]))
diff --git a/scripts/architecture.py b/scripts/architecture.py
deleted file mode 100644
index f239250..0000000
--- a/scripts/architecture.py
+++ /dev/null
@@ -1,58 +0,0 @@
-"""Abstraction layer for different ABIs."""
-
-import re
-import symbol
-
-def UnpackLittleEndian(word):
-  """Split a hexadecimal string in little endian order."""
-  return [word[x:x+2] for x in range(len(word) - 2, -2, -2)]
-
-
-ASSEMBLE = 'as'
-DISASSEMBLE = 'objdump'
-LINK = 'ld'
-UNPACK = 'unpack'
-
-OPTIONS = {
-    'x86': {
-        ASSEMBLE: ['--32'],
-        LINK: ['-melf_i386']
-    }
-}
-
-
-class Architecture(object):
-  """Creates an architecture abstraction for a given ABI.
-
-  Args:
-    name: The abi name, as represented in a tombstone.
-  """
-
-  def __init__(self, name):
-    symbol.ARCH = name
-    self.toolchain = symbol.FindToolchain()
-    self.options = OPTIONS.get(name, {})
-
-  def Assemble(self, args):
-    """Generates an assembler command, appending the given args."""
-    return [symbol.ToolPath(ASSEMBLE)] + self.options.get(ASSEMBLE, []) + args
-
-  def Link(self, args):
-    """Generates a link command, appending the given args."""
-    return [symbol.ToolPath(LINK)] + self.options.get(LINK, []) + args
-
-  def Disassemble(self, args):
-    """Generates a disassemble command, appending the given args."""
-    return ([symbol.ToolPath(DISASSEMBLE)] + self.options.get(DISASSEMBLE, []) +
-            args)
-
-  def WordToBytes(self, word):
-    """Unpacks a hexadecimal string in the architecture's byte order.
-
-    Args:
-      word: A string representing a hexadecimal value.
-
-    Returns:
-      An array of hexadecimal byte values.
-    """
-    return self.options.get(UNPACK, UnpackLittleEndian)(word)
diff --git a/scripts/cargo2android.py b/scripts/cargo2android.py
index ce6096d..4875e7a 100755
--- a/scripts/cargo2android.py
+++ b/scripts/cargo2android.py
@@ -1778,7 +1778,7 @@
   parser.add_argument(
       '--product-available',
       action='store_true',
-      default=False,
+      default=True,
       help='Mark the main library as product_available.')
   parser.add_argument(
       '--recovery-available',
@@ -1788,7 +1788,7 @@
   parser.add_argument(
       '--vendor-available',
       action='store_true',
-      default=False,
+      default=True,
       help='Mark the main library as vendor_available.')
   parser.add_argument(
       '--vendor-ramdisk-available',
diff --git a/scripts/example_crashes.py b/scripts/example_crashes.py
index 5d4751c..f386dfd 100755
--- a/scripts/example_crashes.py
+++ b/scripts/example_crashes.py
@@ -84,59 +84,6 @@
     #07 pc 0000000000014e90  /system/lib64/libc.so (__start_thread+16)
 """
 
-mips = """
-Build fingerprint: 'Android/aosp_mips/generic_mips:4.4.3.43.43.43/AOSP/enh06302258:eng/test-keys'
-Revision: '0'
-ABI: 'mips'
-pid: 958, tid: 960, name: crasher  >>> crasher <<<
-signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
- zr 00000000  at 802babc0  v0 00000000  v1 77b99dd0
- a0 000003be  a1 000003c0  a2 00000006  a3 00000000
- t0 00000000  t1 9e7f5440  t2 00000020  t3 ffffff18
- t4 77a9c000  t5 00000001  t6 00000000  t7 00000000
- s0 000003c0  s1 77b99dd8  s2 00000000  s3 00000006
- s4 77db2028  s5 000003be  s6 77c39fa8  s7 77b99dd0
- t8 00000000  t9 77c89e80  k0 00000000  k1 00000000
- gp 77cce350  sp 77b99c78  s8 77db2020  ra 77c3b48c
- hi 00000000  lo 00000008 bva 7fff7008 epc 77c89e94
-
-backtrace:
-    #00 pc 00067e94  /system/lib/libc.so (tgkill+20)
-    #01 pc 0001948c  /system/lib/libc.so (pthread_kill+244)
-    #02 pc 0001b0e8  /system/lib/libc.so (raise+60)
-    #03 pc 00012908  /system/lib/libc.so (abort+104)
-    #04 pc 000012a4  /system/xbin/crasher
-    #05 pc 00018008  /system/lib/libc.so (__pthread_start(void*)+96)
-    #06 pc 00013198  /system/lib/libc.so (__start_thread+36)
-"""
-
-mips64 = """
-Build fingerprint: 'Android/aosp_mips64/generic_mips64:5.1.51/AOSP/agampe05040015:userdebug/test-keys'
-Revision: '1'
-ABI: 'mips64'
-pid: 342, tid: 342, name: crasher64  >>> crasher64 <<<
-signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
- zr 0000000000000000  at 0000000000000001  v0 0000000000000000  v1 000000ffec1c6528
- a0 0000000000000156  a1 0000000000000156  a2 0000000000000006  a3 0000000000000000
- a4 000000000000ffff  a5 fffffffffffffffc  a6 0000000000000000  a7 0000000000000001
- t0 0000000000000001  t1 0000000000000000  t2 0000000000000001  t3 0000000000000001
- s0 0000000000000002  s1 000000ffec1c6538  s2 000000ffec1c6478  s3 0000000000000006
- s4 0000000000100000  s5 000000fff1d44f98  s6 000000fff186c488  s7 0000000000000000
- t8 ffffffffffff0000  t9 000000ffec01c2a0  k0 0000000000000000  k1 0000000000000000
- gp 000000ffec0a6680  sp 000000ffff8c7150  s8 0000000000100206  ra 000000ffec016684
- hi 0000000000000000  lo 0000000000000000 bva 000000ffffffe010 epc 000000ffec01c2a8
-
-backtrace:
-    #00 pc 00000000000832a8  /system/lib64/libc.so (tgkill+8)
-    #01 pc 000000000007d684  /system/lib64/libc.so (pthread_kill+116)
-    #02 pc 000000000002dd78  /system/lib64/libc.so (raise+56)
-    #03 pc 000000000002684c  /system/lib64/libc.so (abort+92)
-    #04 pc 000000000000199c  /system/xbin/crasher64
-    #05 pc 000000000002595c  /system/lib64/libc.so (__libc_init+140)
-    #06 pc 0000000000000fd4  /system/xbin/crasher64
-    #07 pc 0000000000000f80  /system/xbin/crasher64
-"""
-
 x86 = """
 Build fingerprint: 'Android/aosp_x86_64/generic_x86_64:4.4.3.43.43.43/AOSP/enh06302258:eng/test-keys'
 Revision: '0'
@@ -184,6 +131,31 @@
     #08 pc 00000000000138f5  /system/lib64/libc.so (__bionic_clone+53)
 """
 
+riscv64 = """
+Build fingerprint: 'generic/aosp_riscv64/vsoc_riscv64:4.4.3.43.43.43/AOSP/eng.prasha.20230307.172954:eng/test-keys'
+Revision: '0'
+ABI: 'riscv64'
+pid: 794, tid: 794, name: crasher64  >>> crasher64 <<<
+signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
+    gp  ffffffff81dabe60  tp  00ffffff1aae0050  t0  000000000002ba76  t1  00ffffff140d598c
+    t2  00000000d82989b1  t3  00ffffff1407e570  t4  00ffffff1ac2d000  t5  0000000000000018
+    t6  0000000000000018  s0  000000000000031a  s1  000000000000031a  s2  ffffffffffffffff
+    s3  00ffffffca72dd20  s4  0000000000000000  s5  00fffff499ead378  s6  00fffff469ea7b90
+    s7  00aaaaaba6d2b2c8  s8  00fffff5fa3a1588  s9  0000000000000000  s10 0000000000000000
+    s11 0000000000000000  a0  0000000000000000  a1  000000000000031a  a2  0000000000000006
+    a3  00ffffffca72da00  a4  0000000000000000  a5  000000007fffffff  a6  000000007fffffff
+    a7  00000000000000f0
+    pc  00ffffff1407e582  ra  00ffffff140811d2  sp  00ffffffca72d9d0
+
+backtrace:
+      #00 pc 0000000000049582  /apex/com.android.runtime/lib64/bionic/libc.so (syscall+18)
+      #01 pc 000000000004c1ce  /apex/com.android.runtime/lib64/bionic/libc.so (abort+98)
+      #02 pc 0000000000004012  /system/bin/crasher64 (maybe_abort+40)
+      #03 pc 000000000000457c  /system/bin/crasher64 (do_action+966)
+      #04 pc 0000000000005528  /system/bin/crasher64 (main+78)
+      #05 pc 0000000000047cd4  /apex/com.android.runtime/lib64/bionic/libc.so (__libc_init+80)
+"""
+
 libmemunreachable = """
  Unreachable memory
   48 bytes in 2 unreachable allocations
diff --git a/scripts/stack b/scripts/stack
index 70bc3fb..2e83ff2 100755
--- a/scripts/stack
+++ b/scripts/stack
@@ -44,7 +44,10 @@
 
   args = parser.parse_args()
   if args.arch:
-    symbol.ARCH = args.arch
+    if args.arch == "arm" or args.arch == "x86":
+      symbol.ARCH_IS_32BIT = True
+    else:
+      symbol.ARCH_IS_32BIT = False
   if args.symbols_dir:
     symbol.SYMBOLS_DIR = args.symbols_dir
   if args.symbols_zip:
@@ -56,10 +59,11 @@
   symbol.VERBOSE = args.verbose
   if args.file == '-':
     print("Reading native crash info from stdin")
+    sys.stdin.reconfigure(errors='ignore')
     f = sys.stdin
   else:
     print("Searching for native crashes in %s" % args.file)
-    f = open(args.file, "r")
+    f = open(args.file, "r", errors='ignore')
 
   lines = f.readlines()
   f.close()
diff --git a/scripts/stack_core.py b/scripts/stack_core.py
index 831eb7d..021617a 100755
--- a/scripts/stack_core.py
+++ b/scripts/stack_core.py
@@ -65,10 +65,9 @@
   register_names = {
     "arm": "r0|r1|r2|r3|r4|r5|r6|r7|r8|r9|sl|fp|ip|sp|lr|pc|cpsr",
     "arm64": "x0|x1|x2|x3|x4|x5|x6|x7|x8|x9|x10|x11|x12|x13|x14|x15|x16|x17|x18|x19|x20|x21|x22|x23|x24|x25|x26|x27|x28|x29|x30|sp|pc|pstate",
-    "mips": "zr|at|v0|v1|a0|a1|a2|a3|t0|t1|t2|t3|t4|t5|t6|t7|s0|s1|s2|s3|s4|s5|s6|s7|t8|t9|k0|k1|gp|sp|s8|ra|hi|lo|bva|epc",
-    "mips64": "zr|at|v0|v1|a0|a1|a2|a3|a4|a5|a6|a7|t0|t1|t2|t3|s0|s1|s2|s3|s4|s5|s6|s7|t8|t9|k0|k1|gp|sp|s8|ra|hi|lo|bva|epc",
     "x86": "eax|ebx|ecx|edx|esi|edi|x?cs|x?ds|x?es|x?fs|x?ss|eip|ebp|esp|flags",
     "x86_64": "rax|rbx|rcx|rdx|rsi|rdi|r8|r9|r10|r11|r12|r13|r14|r15|cs|ss|rip|rbp|rsp|eflags",
+    "riscv64": "ra|sp|gp|tp|t0|t1|t2|s0|s1|a0|a1|a2|a3|a4|a5|a6|a7|s2|s3|s4|s5|s6|s7|s8|s9|s10|s11|t3|t4|t5|t6|pc",
   }
 
   # We use the "file" command line tool to extract BuildId from ELF files.
@@ -77,15 +76,14 @@
                               r"Build ID:\s*(?P<build_id>[0-9a-f]+)",
                               flags=re.DOTALL)
 
-  def UpdateAbiRegexes(self):
-    if symbol.ARCH == "arm64" or symbol.ARCH == "mips64" or symbol.ARCH == "x86_64":
-      self.width = "{16}"
-      self.spacing = "        "
-    else:
+  def UpdateBitnessRegexes(self):
+    if symbol.ARCH_IS_32BIT:
       self.width = "{8}"
       self.spacing = ""
-
-    self.register_line = re.compile("(([ ]*\\b(" + self.register_names[symbol.ARCH] + ")\\b +[0-9a-f]" + self.width + "){2,5})")
+    else:
+      self.width = "{16}"
+      self.spacing = "        "
+    self.register_line = re.compile("    (([ ]*\\b(\S*)\\b +[0-9a-f]" + self.width + "){1,5}$)")
 
     # Note that both trace and value line matching allow for variable amounts of
     # whitespace (e.g. \t). This is because the we want to allow for the stack
@@ -184,9 +182,9 @@
   def ConvertTrace(self, lines):
     lines = [self.CleanLine(line) for line in lines]
     try:
-      if not symbol.ARCH:
-        symbol.SetAbi(lines)
-      self.UpdateAbiRegexes()
+      if symbol.ARCH_IS_32BIT is None:
+        symbol.SetBitness(lines)
+      self.UpdateBitnessRegexes()
       for line in lines:
         self.ProcessLine(line)
       self.PrintOutput(self.trace_lines, self.value_lines)
@@ -372,11 +370,11 @@
     test_name = lib.rsplit("/", 1)[-1]
     test_dir = "/data/nativetest"
     test_dir_bitness = ""
-    if symbol.ARCH.endswith("64"):
+    if symbol.ARCH_IS_32BIT:
+      bitness = "32"
+    else:
       bitness = "64"
       test_dir_bitness = "64"
-    else:
-      bitness = "32"
 
     # Unfortunately, the location of the real symbol file is not
     # standardized, so we need to go hunting for it.
@@ -541,7 +539,7 @@
           if nest_count > 0:
             nest_count = nest_count - 1
             arrow = "v------>"
-            if symbol.ARCH == "arm64" or symbol.ARCH == "mips64" or symbol.ARCH == "x86_64":
+            if not symbol.ARCH_IS_32BIT:
               arrow = "v-------------->"
             self.trace_lines.append((arrow, source_symbol, source_location))
           else:
@@ -584,8 +582,12 @@
   def assert_register_matches(self, abi, example_crash, stupid_pattern):
     tc = TraceConverter()
     lines = example_crash.split('\n')
-    symbol.SetAbi(lines)
-    tc.UpdateAbiRegexes()
+    symbol.SetBitness(lines)
+    tc.UpdateBitnessRegexes()
+    if symbol.ARCH_IS_32BIT:
+      print("32 Bit Arch")
+    else:
+      print("64 Bit Arch")
     for line in lines:
       tc.ProcessLine(line)
       is_register = (re.search(stupid_pattern, line) is not None)
@@ -594,16 +596,10 @@
     tc.PrintOutput(tc.trace_lines, tc.value_lines)
 
   def test_arm_registers(self):
-    self.assert_register_matches("arm", example_crashes.arm, '\\b(r0|r4|r8|ip)\\b')
+    self.assert_register_matches("arm", example_crashes.arm, '\\b(r0|r4|r8|ip|scr)\\b')
 
   def test_arm64_registers(self):
-    self.assert_register_matches("arm64", example_crashes.arm64, '\\b(x0|x4|x8|x12|x16|x20|x24|x28|sp)\\b')
-
-  def test_mips_registers(self):
-    self.assert_register_matches("mips", example_crashes.mips, '\\b(zr|a0|t0|t4|s0|s4|t8|gp|hi)\\b')
-
-  def test_mips64_registers(self):
-    self.assert_register_matches("mips64", example_crashes.mips64, '\\b(zr|a0|a4|t0|s0|s4|t8|gp|hi)\\b')
+    self.assert_register_matches("arm64", example_crashes.arm64, '\\b(x0|x4|x8|x12|x16|x20|x24|x28|sp|v[1-3]?[0-9])\\b')
 
   def test_x86_registers(self):
     self.assert_register_matches("x86", example_crashes.x86, '\\b(eax|esi|xcs|eip)\\b')
@@ -611,15 +607,17 @@
   def test_x86_64_registers(self):
     self.assert_register_matches("x86_64", example_crashes.x86_64, '\\b(rax|rsi|r8|r12|cs|rip)\\b')
 
+  def test_riscv64_registers(self):
+    self.assert_register_matches("riscv64", example_crashes.riscv64, '\\b(gp|t2|t6|s3|s7|s11|a3|a7|sp)\\b')
+
 class LibmemunreachablePatternTests(unittest.TestCase):
   def test_libmemunreachable(self):
     tc = TraceConverter()
     lines = example_crashes.libmemunreachable.split('\n')
 
-    symbol.SetAbi(lines)
-    self.assertEqual(symbol.ARCH, "arm")
-
-    tc.UpdateAbiRegexes()
+    symbol.SetBitness(lines)
+    self.assertTrue(symbol.ARCH_IS_32BIT)
+    tc.UpdateBitnessRegexes()
     header_lines = 0
     trace_lines = 0
     for line in lines:
@@ -639,8 +637,8 @@
   def test_long_asan_crash(self):
     tc = TraceConverter()
     lines = example_crashes.long_asan_crash.splitlines()
-    symbol.SetAbi(lines)
-    tc.UpdateAbiRegexes()
+    symbol.SetBitness(lines)
+    tc.UpdateBitnessRegexes()
     # Test by making sure trace_line_count is monotonically non-decreasing. If the stack trace
     # is split, a separator is printed and trace_lines is flushed.
     trace_line_count = 0
@@ -656,8 +654,8 @@
 class ValueLinesTest(unittest.TestCase):
   def test_value_line_skipped(self):
     tc = TraceConverter()
-    symbol.SetAbi(["ABI: 'arm'"])
-    tc.UpdateAbiRegexes()
+    symbol.ARCH_IS_32BIT = True
+    tc.UpdateBitnessRegexes()
     tc.ProcessLine("    12345678  00001000  .")
     self.assertEqual([], tc.value_lines)
 
diff --git a/scripts/symbol.py b/scripts/symbol.py
index 0a255e8..bfdc29e 100755
--- a/scripts/symbol.py
+++ b/scripts/symbol.py
@@ -58,13 +58,12 @@
 
 SYMBOLS_DIR = FindSymbolsDir()
 
-ARCH = None
+ARCH_IS_32BIT = None
 
 VERBOSE = False
 
 # These are private. Do not access them from other modules.
 _CACHED_TOOLCHAIN = None
-_CACHED_TOOLCHAIN_ARCH = None
 _CACHED_CXX_FILT = None
 
 # Caches for symbolized information.
@@ -147,18 +146,18 @@
 
 def ToolPath(tool, toolchain=None):
   """Return a fully-qualified path to the specified tool, or just the tool if it's on PATH """
-  if shutil.which(tool) is not None:
-      return tool
+  if shutil.which(tool):
+    return tool
   if not toolchain:
     toolchain = FindToolchain()
   return os.path.join(toolchain, tool)
 
 
 def FindToolchain():
-  """Returns the toolchain matching ARCH."""
+  """Returns the toolchain."""
 
-  global _CACHED_TOOLCHAIN, _CACHED_TOOLCHAIN_ARCH
-  if _CACHED_TOOLCHAIN is not None and _CACHED_TOOLCHAIN_ARCH == ARCH:
+  global _CACHED_TOOLCHAIN
+  if _CACHED_TOOLCHAIN:
     return _CACHED_TOOLCHAIN
 
   llvm_binutils_dir = ANDROID_BUILD_TOP + "/prebuilts/clang/host/linux-x86/llvm-binutils-stable/";
@@ -166,8 +165,7 @@
     raise Exception("Could not find llvm tool chain directory %s" % (llvm_binutils_dir))
 
   _CACHED_TOOLCHAIN = llvm_binutils_dir
-  _CACHED_TOOLCHAIN_ARCH = ARCH
-  print("Using", _CACHED_TOOLCHAIN_ARCH, "toolchain from:", _CACHED_TOOLCHAIN)
+  print("Using toolchain from:", _CACHED_TOOLCHAIN)
   return _CACHED_TOOLCHAIN
 
 
@@ -324,21 +322,6 @@
   return result
 
 
-def StripPC(addr):
-  """Strips the Thumb bit a program counter address when appropriate.
-
-  Args:
-    addr: the program counter address
-
-  Returns:
-    The stripped program counter address.
-  """
-  global ARCH
-  if ARCH == "arm":
-    return addr & ~1
-  return addr
-
-
 def CallObjdumpForSet(lib, unique_addrs):
   """Use objdump to find out the names of the containing functions.
 
@@ -381,8 +364,8 @@
     if not os.path.exists(symbols):
       return None
 
-  start_addr_dec = str(StripPC(int(addrs[0], 16)))
-  stop_addr_dec = str(StripPC(int(addrs[-1], 16)) + 8)
+  start_addr_dec = str(int(addrs[0], 16))
+  stop_addr_dec = str(int(addrs[-1], 16) + 8)
   cmd = [ToolPath("llvm-objdump"),
          "--section=.text",
          "--demangle",
@@ -431,7 +414,7 @@
       addr = components.group(1)
       target_addr = addrs[addr_index]
       i_addr = int(addr, 16)
-      i_target = StripPC(int(target_addr, 16))
+      i_target = int(target_addr, 16)
       if i_addr == i_target:
         result[target_addr] = (current_symbol, i_target - current_symbol_addr)
         addr_cache[target_addr] = result[target_addr]
@@ -517,268 +500,64 @@
 
   return result.strip()
 
-def GetAbiFromToolchain(toolchain_var, bits):
-  toolchain = os.environ.get(toolchain_var)
-  if not toolchain:
-    return None
+def SetBitness(lines):
+  global ARCH_IS_32BIT
 
-  toolchain_match = re.search("\/(aarch64|arm|mips|x86)\/", toolchain)
-  if toolchain_match:
-    abi = toolchain_match.group(1)
-    if abi == "aarch64":
-      return "arm64"
-    elif bits == 64:
-      if abi == "x86":
-        return "x86_64"
-      elif abi == "mips":
-        return "mips64"
-    return abi
-  return None
-
-def Get32BitArch():
-  # Check for ANDROID_TOOLCHAIN_2ND_ARCH first, if set, use that.
-  # If not try ANDROID_TOOLCHAIN to find the arch.
-  # If this is not set, then default to arm.
-  arch = GetAbiFromToolchain("ANDROID_TOOLCHAIN_2ND_ARCH", 32)
-  if not arch:
-    arch = GetAbiFromToolchain("ANDROID_TOOLCHAIN", 32)
-    if not arch:
-      return "arm"
-  return arch
-
-def Get64BitArch():
-  # Check for ANDROID_TOOLCHAIN, if it is set, we can figure out the
-  # arch this way. If this is not set, then default to arm64.
-  arch = GetAbiFromToolchain("ANDROID_TOOLCHAIN", 64)
-  if not arch:
-    return "arm64"
-  return arch
-
-def SetAbi(lines):
-  global ARCH
-
-  abi_line = re.compile("ABI: \'(.*)\'")
   trace_line = re.compile("\#[0-9]+[ \t]+..[ \t]+([0-9a-f]{8}|[0-9a-f]{16})([ \t]+|$)")
   asan_trace_line = re.compile("\#[0-9]+[ \t]+0x([0-9a-f]+)[ \t]+")
 
-  ARCH = None
+  ARCH_IS_32BIT = False
   for line in lines:
-    abi_match = abi_line.search(line)
-    if abi_match:
-      ARCH = abi_match.group(1)
-      break
     trace_match = trace_line.search(line)
     if trace_match:
       # Try to guess the arch, we know the bitness.
       if len(trace_match.group(1)) == 16:
-        ARCH = Get64BitArch()
+        ARCH_IS_32BIT = False
       else:
-        ARCH = Get32BitArch()
+        ARCH_IS_32BIT = True
       break
     asan_trace_match = asan_trace_line.search(line)
     if asan_trace_match:
       # We might be able to guess the bitness by the length of the address.
       if len(asan_trace_match.group(1)) > 8:
-        ARCH = Get64BitArch()
+        ARCH_IS_32BIT = False
         # We know for a fact this is 64 bit, so we are done.
         break
       else:
-        ARCH = Get32BitArch()
         # This might be 32 bit, or just a small address. Keep going in this
         # case, but if we couldn't figure anything else out, go with 32 bit.
-  if not ARCH:
-    raise Exception("Could not determine arch from input, use --arch=XXX to specify it")
-
-
-class FindToolchainTests(unittest.TestCase):
-  def assert_toolchain_found(self, abi):
-    global ARCH
-    ARCH = abi
-    FindToolchain() # Will throw on failure.
-
-  @unittest.skipIf(ANDROID_BUILD_TOP == '.', 'Test only supported in an Android tree.')
-  def test_toolchains_found(self):
-    self.assert_toolchain_found("arm")
-    self.assert_toolchain_found("arm64")
-    self.assert_toolchain_found("mips")
-    self.assert_toolchain_found("x86")
-    self.assert_toolchain_found("x86_64")
+        ARCH_IS_32BIT = True
 
 class FindClangDirTests(unittest.TestCase):
   @unittest.skipIf(ANDROID_BUILD_TOP == '.', 'Test only supported in an Android tree.')
   def test_clang_dir_found(self):
     self.assertIsNotNone(FindClangDir())
 
-class SetArchTests(unittest.TestCase):
-  def test_abi_check(self):
-    global ARCH
+class SetBitnessTests(unittest.TestCase):
+  def test_32bit_check(self):
+    global ARCH_IS_32BIT
 
-    SetAbi(["ABI: 'arm'"])
-    self.assertEqual(ARCH, "arm")
-    SetAbi(["ABI: 'arm64'"])
-    self.assertEqual(ARCH, "arm64")
+    SetBitness(["#00 pc 000374e0"])
+    self.assertTrue(ARCH_IS_32BIT)
 
-    SetAbi(["ABI: 'mips'"])
-    self.assertEqual(ARCH, "mips")
-    SetAbi(["ABI: 'mips64'"])
-    self.assertEqual(ARCH, "mips64")
+  def test_64bit_check(self):
+    global ARCH_IS_32BIT
 
-    SetAbi(["ABI: 'x86'"])
-    self.assertEqual(ARCH, "x86")
-    SetAbi(["ABI: 'x86_64'"])
-    self.assertEqual(ARCH, "x86_64")
-
-  def test_32bit_trace_line_toolchain(self):
-    global ARCH
-
-    os.environ.clear()
-    os.environ["ANDROID_TOOLCHAIN"] = "linux-x86/arm/arm-linux-androideabi-4.9/bin"
-    SetAbi(["#00 pc 000374e0"])
-    self.assertEqual(ARCH, "arm")
-
-    os.environ.clear()
-    os.environ["ANDROID_TOOLCHAIN"] = "linux-x86/mips/arm-linux-androideabi-4.9/bin"
-    SetAbi(["#00 pc 000374e0"])
-    self.assertEqual(ARCH, "mips")
-
-    os.environ.clear()
-    os.environ["ANDROID_TOOLCHAIN"] = "linux-x86/x86/arm-linux-androideabi-4.9/bin"
-    SetAbi(["#00 pc 000374e0"])
-    self.assertEqual(ARCH, "x86")
-
-  def test_32bit_trace_line_toolchain_2nd(self):
-    global ARCH
-
-    os.environ.clear()
-    os.environ["ANDROID_TOOLCHAIN_2ND_ARCH"] = "linux-x86/arm/arm-linux-androideabi-4.9/bin"
-    os.environ["ANDROID_TOOLCHAIN_ARCH"] = "linux-x86/aarch64/aarch64-linux-android-4.9/bin"
-    SetAbi(["#00 pc 000374e0"])
-    self.assertEqual(ARCH, "arm")
-
-    os.environ.clear()
-    os.environ["ANDROID_TOOLCHAIN_2ND_ARCH"] = "linux-x86/mips/mips-linux-androideabi-4.9/bin"
-    os.environ["ANDROID_TOOLCHAIN"] = "linux-x86/unknown/unknown-linux-androideabi-4.9/bin"
-    SetAbi(["#00 pc 000374e0"])
-    self.assertEqual(ARCH, "mips")
-
-    os.environ.clear()
-    os.environ["ANDROID_TOOLCHAIN_2ND_ARCH"] = "linux-x86/x86/x86-linux-androideabi-4.9/bin"
-    os.environ["ANDROID_TOOLCHAIN"] = "linux-x86/unknown/unknown-linux-androideabi-4.9/bin"
-    SetAbi(["#00 pc 000374e0"])
-    self.assertEqual(ARCH, "x86")
-
-  def test_64bit_trace_line_toolchain(self):
-    global ARCH
-
-    os.environ.clear()
-    os.environ["ANDROID_TOOLCHAIN"] = "linux-x86/aarch/aarch-linux-androideabi-4.9/bin"
-    SetAbi(["#00 pc 00000000000374e0"])
-    self.assertEqual(ARCH, "arm64")
-
-    os.environ.clear()
-    os.environ["ANDROID_TOOLCHAIN"] = "linux-x86/mips/arm-linux-androideabi-4.9/bin"
-    SetAbi(["#00 pc 00000000000374e0"])
-    self.assertEqual(ARCH, "mips64")
-
-    os.environ.clear()
-    os.environ["ANDROID_TOOLCHAIN"] = "linux-x86/x86/arm-linux-androideabi-4.9/bin"
-    SetAbi(["#00 pc 00000000000374e0"])
-    self.assertEqual(ARCH, "x86_64")
-
-  def test_trace_default_abis(self):
-    global ARCH
-
-    os.environ.clear()
-    SetAbi(["#00 pc 000374e0"])
-    self.assertEqual(ARCH, "arm")
-    SetAbi(["#00 pc 00000000000374e0"])
-    self.assertEqual(ARCH, "arm64")
+    SetBitness(["#00 pc 00000000000374e0"])
+    self.assertFalse(ARCH_IS_32BIT)
 
   def test_32bit_asan_trace_line_toolchain(self):
-    global ARCH
+    global ARCH_IS_32BIT
 
-    os.environ.clear()
-    os.environ["ANDROID_TOOLCHAIN"] = "linux-x86/arm/arm-linux-androideabi-4.9/bin"
-    SetAbi(["#10 0xb5eeba5d  (/system/vendor/lib/egl/libGLESv1_CM_adreno.so+0xfa5d)"])
-    self.assertEqual(ARCH, "arm")
-
-    os.environ.clear()
-    os.environ["ANDROID_TOOLCHAIN"] = "linux-x86/mips/arm-linux-androideabi-4.9/bin"
-    SetAbi(["#10 0xb5eeba5d  (/system/vendor/lib/egl/libGLESv1_CM_adreno.so+0xfa5d)"])
-    self.assertEqual(ARCH, "mips")
-
-    os.environ.clear()
-    os.environ["ANDROID_TOOLCHAIN"] = "linux-x86/x86/arm-linux-androideabi-4.9/bin"
-    SetAbi(["#10 0xb5eeba5d  (/system/vendor/lib/egl/libGLESv1_CM_adreno.so+0xfa5d)"])
-    self.assertEqual(ARCH, "x86")
-
-  def test_32bit_asan_trace_line_toolchain_2nd(self):
-    global ARCH
-
-    os.environ.clear()
-    os.environ["ANDROID_TOOLCHAIN_2ND_ARCH"] = "linux-x86/arm/arm-linux-androideabi-4.9/bin"
-    os.environ["ANDROID_TOOLCHAIN_ARCH"] = "linux-x86/aarch64/aarch64-linux-android-4.9/bin"
-    SetAbi(["#3 0xae1725b5  (/system/vendor/lib/libllvm-glnext.so+0x6435b5)"])
-    self.assertEqual(ARCH, "arm")
-
-    os.environ.clear()
-    os.environ["ANDROID_TOOLCHAIN_2ND_ARCH"] = "linux-x86/mips/mips-linux-androideabi-4.9/bin"
-    os.environ["ANDROID_TOOLCHAIN"] = "linux-x86/unknown/unknown-linux-androideabi-4.9/bin"
-    SetAbi(["#3 0xae1725b5  (/system/vendor/lib/libllvm-glnext.so+0x6435b5)"])
-    self.assertEqual(ARCH, "mips")
-
-    os.environ.clear()
-    os.environ["ANDROID_TOOLCHAIN_2ND_ARCH"] = "linux-x86/x86/x86-linux-androideabi-4.9/bin"
-    os.environ["ANDROID_TOOLCHAIN"] = "linux-x86/unknown/unknown-linux-androideabi-4.9/bin"
-    SetAbi(["#3 0xae1725b5  (/system/vendor/lib/libllvm-glnext.so+0x6435b5)"])
-    self.assertEqual(ARCH, "x86")
+    SetBitness(["#10 0xb5eeba5d  (/system/vendor/lib/egl/libGLESv1_CM_adreno.so+0xfa5d)"])
+    self.assertTrue(ARCH_IS_32BIT)
 
   def test_64bit_asan_trace_line_toolchain(self):
-    global ARCH
+    global ARCH_IS_32BIT
 
-    os.environ.clear()
-    os.environ["ANDROID_TOOLCHAIN"] = "linux-x86/aarch/aarch-linux-androideabi-4.9/bin"
-    SetAbi(["#0 0x11b35d33bf  (/system/lib/libclang_rt.asan-arm-android.so+0x823bf)"])
-    self.assertEqual(ARCH, "arm64")
-
-    os.environ.clear()
-    os.environ["ANDROID_TOOLCHAIN"] = "linux-x86/mips/arm-linux-androideabi-4.9/bin"
-    SetAbi(["#1 0x11b35d33bf  (/system/lib/libclang_rt.asan-arm-android.so+0x823bf)"])
-    self.assertEqual(ARCH, "mips64")
-
-    os.environ.clear()
-    os.environ["ANDROID_TOOLCHAIN"] = "linux-x86/x86/arm-linux-androideabi-4.9/bin"
-    SetAbi(["#12 0x11b35d33bf  (/system/lib/libclang_rt.asan-arm-android.so+0x823bf)"])
-    self.assertEqual(ARCH, "x86_64")
-
-    # Verify that if an address that might be 32 bit comes first, that
-    # encountering a 64 bit address returns a 64 bit abi.
-    ARCH = None
-    os.environ.clear()
-    os.environ["ANDROID_TOOLCHAIN"] = "linux-x86/x86/arm-linux-androideabi-4.9/bin"
-    SetAbi(["#12 0x5d33bf  (/system/lib/libclang_rt.asan-arm-android.so+0x823bf)",
-            "#12 0x11b35d33bf  (/system/lib/libclang_rt.asan-arm-android.so+0x823bf)"])
-    self.assertEqual(ARCH, "x86_64")
-
-  def test_asan_trace_default_abis(self):
-    global ARCH
-
-    os.environ.clear()
-    SetAbi(["#4 0x1234349ab  (/system/vendor/lib/libllvm-glnext.so+0x64fc4f)"])
-    self.assertEqual(ARCH, "arm64")
-    SetAbi(["#1 0xae17ec4f  (/system/vendor/lib/libllvm-glnext.so+0x64fc4f)"])
-    self.assertEqual(ARCH, "arm")
-
-  def test_no_abi(self):
-    global ARCH
-
-    # Python2 vs Python3 compatibility: Python3 warns on Regexp deprecation, but Regex
-    #                                   does not provide that name.
-    if not hasattr(unittest.TestCase, 'assertRaisesRegex'):
-      unittest.TestCase.assertRaisesRegex = getattr(unittest.TestCase, 'assertRaisesRegexp')
-    self.assertRaisesRegex(Exception,
-                           "Could not determine arch from input, use --arch=XXX to specify it",
-                           SetAbi, [])
+    SetBitness(["#12 0x5d33bf  (/system/lib/libclang_rt.asan-arm-android.so+0x823bf)",
+                "#12 0x11b35d33bf  (/system/lib/libclang_rt.asan-arm-android.so+0x823bf)"])
+    self.assertFalse(ARCH_IS_32BIT)
 
 class FormatSymbolWithoutParametersTests(unittest.TestCase):
   def test_c(self):