[PATCH] D65322: [asan_symbolize] Avoid blocking when llvm-symbolizer is installed as addr2line

Alexander Richardson via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 26 01:30:31 PDT 2019


arichardson created this revision.
arichardson added reviewers: kcc, eugenis, glider, samsonov.
Herald added subscribers: llvm-commits, Sanitizers, kubamracek.
Herald added projects: Sanitizers, LLVM.

Currently, llvm-symbolizer will print -1 when presented with -1 and not
print a second line. In that case we will block for ever trying to read
the file name. This also happens for non-existent files, in which case GNU
addr2line exits immediate, but llvm-symbolizer does not (see
https://llvm.org/PR42754). While touching these lines, I also added some
more debug logging to help diagnose this and potential future issues.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D65322

Files:
  compiler-rt/lib/asan/scripts/asan_symbolize.py
  compiler-rt/test/asan/TestCases/Posix/asan-symbolize-bad-path.cc


Index: compiler-rt/test/asan/TestCases/Posix/asan-symbolize-bad-path.cc
===================================================================
--- compiler-rt/test/asan/TestCases/Posix/asan-symbolize-bad-path.cc
+++ compiler-rt/test/asan/TestCases/Posix/asan-symbolize-bad-path.cc
@@ -1,4 +1,15 @@
 // Test that asan_symbolize does not hang when provided with an non-existing
 // path.
-// RUN: echo '#0 0xabcdabcd (%t/bad/path+0x1234)' | %asan_symbolize | FileCheck %s
-// CHECK: #0 0xabcdabcd
+// RUN: echo '#0 0xabcdabcd (%t/bad/path+0x1234)' | %asan_symbolize | FileCheck %s -check-prefix CHECK-BAD-FILE
+// CHECK-BAD-FILE: #0 0xabcdabcd in ?? ??:0
+// CHECK-BAD-FILE-EMPTY:
+
+// Also test that asan_symbolize doesn't assert on an invalid address with a valid file:
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: echo '#0 0xabcdabcd (%t+0x0)' | %asan_symbolize | FileCheck %s -check-prefix CHECK-BAD-ADDR
+// CHECK-BAD-ADDR: #0 0xabcdabcd in ??
+// CHECK-BAD-ADDR-EMPTY:
+
+int main() {
+  return 0;
+}
Index: compiler-rt/lib/asan/scripts/asan_symbolize.py
===================================================================
--- compiler-rt/lib/asan/scripts/asan_symbolize.py
+++ compiler-rt/lib/asan/scripts/asan_symbolize.py
@@ -27,6 +27,7 @@
 import re
 import subprocess
 import sys
+from distutils.spawn import find_executable
 
 symbolizers = {}
 demangle = False
@@ -153,6 +154,7 @@
     addr2line_tool = 'addr2line'
     if binutils_prefix:
       addr2line_tool = binutils_prefix + addr2line_tool
+    logging.debug('addr2line binary is %s' % find_executable(addr2line_tool))
     cmd = [addr2line_tool, '-fi']
     if demangle:
       cmd += ['--demangle']
@@ -174,14 +176,34 @@
       is_first_frame = True
       while True:
         function_name = self.pipe.stdout.readline().rstrip()
+        logging.debug("read function_name='%s' from addr2line" % function_name)
+        # If llvm-symbolizer is installed as addr2line, older versions of
+        # llvm-symbolizer will print -1 when presented with -1 and not print
+        # a second line. In that case we will block for ever trying to read the
+        # file name. This also happens for non-existent files, in which case GNU
+        # addr2line exits immediate, but llvm-symbolizer does not (see
+        # https://llvm.org/PR42754).
+        if function_name == '-1':
+          logging.debug("got function '-1' -> no more input")
+          break
         file_name = self.pipe.stdout.readline().rstrip()
+        logging.debug("read file_name='%s' from addr2line" % file_name)
         if is_first_frame:
           is_first_frame = False
-        elif function_name in ['', '??']:
-          assert file_name == function_name
+        elif function_name == '??':
+          assert file_name == '??:0', file_name
+          logging.debug("got function '??' -> no more input")
+          break
+        elif not function_name:
+          assert not file_name, file_name
+          logging.debug("got empty function name -> no more input")
           break
         lines.append((function_name, file_name));
-    except Exception:
+    except BrokenPipeError:
+      logging.debug("got broken pipe, addr2line returncode=%d" % self.pipe.poll())
+      lines.append(('??', '??:0'))
+    except Exception as e:
+      logging.debug("got unknown exception communication with addr2line", exc_info=e)
       lines.append(('??', '??:0'))
     return ['%s in %s %s' % (addr, function, fix_filename(file)) for (function, file) in lines]
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D65322.211891.patch
Type: text/x-patch
Size: 3503 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190726/92644114/attachment.bin>


More information about the llvm-commits mailing list