Remove gcc tools from script.

Replace all references to gcc tools with llvm tools. This change still
uses c++filt until llvm-cxxfilt is put in the prebuilts.

Test: Ran a backtrace through this script and the old script and verified
Test: no major differences.
Test: Ran unittests for symbol.py and stack_core.py.
Change-Id: Ic31c1a0707dae11c5037f9637943cd7932badf46
diff --git a/scripts/symbol.py b/scripts/symbol.py
index e6560e4..6f0d493 100755
--- a/scripts/symbol.py
+++ b/scripts/symbol.py
@@ -56,6 +56,7 @@
 # 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.
 _SYMBOL_INFORMATION_ADDR2LINE_CACHE = {}
@@ -139,38 +140,21 @@
   """Return a fully-qualified path to the specified tool"""
   if not toolchain:
     toolchain = FindToolchain()
-  return glob.glob(os.path.join(toolchain, "*-" + tool))[0]
+  return os.path.join(toolchain, tool)
 
 
 def FindToolchain():
   """Returns the toolchain matching ARCH."""
+
   global _CACHED_TOOLCHAIN, _CACHED_TOOLCHAIN_ARCH
   if _CACHED_TOOLCHAIN is not None and _CACHED_TOOLCHAIN_ARCH == ARCH:
     return _CACHED_TOOLCHAIN
 
-  # We use slightly different names from GCC, and there's only one toolchain
-  # for x86/x86_64. Note that these are the names of the top-level directory
-  # rather than the _different_ names used lower down the directory hierarchy!
-  gcc_dir = ARCH
-  if gcc_dir == "arm64":
-    gcc_dir = "aarch64"
-  elif gcc_dir == "mips64":
-    gcc_dir = "mips"
-  elif gcc_dir == "x86_64":
-    gcc_dir = "x86"
+  llvm_binutils_dir = ANDROID_BUILD_TOP + "/prebuilts/clang/host/linux-x86/llvm-binutils-stable/";
+  if not os.path.exists(llvm_binutils_dir):
+    raise Exception("Could not find llvm tool chain directory %s" % (llvm_binutils_dir))
 
-  os_name = platform.system().lower();
-
-  available_toolchains = glob.glob("%s/prebuilts/gcc/%s-x86/%s/*-linux-*/bin/" % (ANDROID_BUILD_TOP, os_name, gcc_dir))
-  if len(available_toolchains) == 0:
-    raise Exception("Could not find tool chain for %s" % (ARCH))
-
-  toolchain = sorted(available_toolchains)[-1]
-
-  if not os.path.exists(ToolPath("addr2line", toolchain)):
-    raise Exception("No addr2line for %s" % (toolchain))
-
-  _CACHED_TOOLCHAIN = toolchain
+  _CACHED_TOOLCHAIN = llvm_binutils_dir
   _CACHED_TOOLCHAIN_ARCH = ARCH
   print("Using %s toolchain from: %s" % (_CACHED_TOOLCHAIN_ARCH, _CACHED_TOOLCHAIN))
   return _CACHED_TOOLCHAIN
@@ -222,7 +206,7 @@
   if not lib:
     return None
 
-  addr_to_line = CallAddr2LineForSet(lib, unique_addrs)
+  addr_to_line = CallLlvmSymbolizerForSet(lib, unique_addrs)
   if not addr_to_line:
     return None
 
@@ -247,7 +231,7 @@
   return result
 
 
-def CallAddr2LineForSet(lib, unique_addrs):
+def CallLlvmSymbolizerForSet(lib, unique_addrs):
   """Look up line and symbol information for a set of addresses.
 
   Args:
@@ -298,8 +282,8 @@
   if os.path.isdir(symbols):
     return None
 
-  cmd = [ToolPath("addr2line"), "--functions", "--inlines",
-      "--demangle", "--exe=" + symbols]
+  cmd = [ToolPath("llvm-symbolizer"), "--functions", "--inlines",
+      "--demangle", "--obj=" + symbols, "--output-style=GNU"]
   child = _PIPE_ADDR2LINE_CACHE.GetProcess(cmd)
 
   for addr in addrs:
@@ -310,18 +294,14 @@
       first = True
       while True:
         symbol = child.stdout.readline().strip()
-        if symbol == "??":
-          symbol = None
-        location = child.stdout.readline().strip()
-        if location == "??:0" or location == "??:?":
-          location = None
-        if symbol is None and location is None:
+        if not symbol:
           break
+        location = child.stdout.readline().strip()
         records.append((symbol, location))
         if first:
           # Write a blank line as a sentinel so we know when to stop
           # reading inlines from the output.
-          # The blank line will cause addr2line to emit "??\n??:0\n".
+          # The blank line will cause llvm-symbolizer to emit a blank line.
           child.stdin.write("\n")
           first = False
     except IOError as e:
@@ -391,7 +371,7 @@
 
   start_addr_dec = str(StripPC(int(addrs[0], 16)))
   stop_addr_dec = str(StripPC(int(addrs[-1], 16)) + 8)
-  cmd = [ToolPath("objdump"),
+  cmd = [ToolPath("llvm-objdump"),
          "--section=.text",
          "--demangle",
          "--disassemble",
@@ -455,7 +435,17 @@
   if mangled_symbol in _SYMBOL_DEMANGLING_CACHE:
     return _SYMBOL_DEMANGLING_CACHE[mangled_symbol]
 
-  cmd = [ToolPath("c++filt")]
+  # TODO: Replace with llvm-cxxfilt when available.
+  global _CACHED_CXX_FILT
+  if not _CACHED_CXX_FILT:
+    os_name = platform.system().lower()
+    toolchains = glob.glob("%s/prebuilts/gcc/%s-*/host/*-linux-*/bin/*c++filt" %
+                           (ANDROID_BUILD_TOP, os_name))
+    if not toolchains:
+      raise Exception("Could not find gcc c++filt tool")
+    _CACHED_CXX_FILT = sorted(toolchains)[-1]
+
+  cmd = [_CACHED_CXX_FILT]
   process = _PIPE_CPPFILT_CACHE.GetProcess(cmd)
   process.stdin.write(mangled_symbol)
   process.stdin.write("\n")