Index: compiler-rt/trunk/lib/asan/scripts/asan_symbolize.py =================================================================== --- compiler-rt/trunk/lib/asan/scripts/asan_symbolize.py +++ compiler-rt/trunk/lib/asan/scripts/asan_symbolize.py @@ -383,6 +383,7 @@ self.dsym_hints = set([]) self.frame_no = 0 self.process_line = self.process_line_posix + self.using_module_map = plugin_proxy.has_plugin(ModuleMapPlugIn.get_name()) def symbolize_address(self, addr, binary, offset, arch): # On non-Darwin (i.e. on platforms without .dSYM debug info) always use @@ -451,14 +452,26 @@ def process_line_posix(self, line): self.current_line = line.rstrip() - #0 0x7f6e35cf2e45 (/blah/foo.so+0x11fe45) + # Unsymbolicated: + # #0 0x7f6e35cf2e45 (/blah/foo.so+0x11fe45) + # Partially symbolicated: + # #0 0x7f6e35cf2e45 in foo (foo.so+0x11fe45) + # NOTE: We have to very liberal with symbol + # names in the regex because it could be an + # Objective-C or C++ demangled name. stack_trace_line_format = ( - '^( *#([0-9]+) *)(0x[0-9a-f]+) *\((.*)\+(0x[0-9a-f]+)\)') + '^( *#([0-9]+) *)(0x[0-9a-f]+) *(?:in *.+)? *\((.*)\+(0x[0-9a-f]+)\)') match = re.match(stack_trace_line_format, line) if not match: return [self.current_line] logging.debug(line) _, frameno_str, addr, binary, offset = match.groups() + if not self.using_module_map and not os.path.isabs(binary): + # Do not try to symbolicate if the binary is just the module file name + # and a module map is unavailable. + # FIXME(dliew): This is currently necessary for reports on Darwin that are + # partially symbolicated by `atos`. + return [self.current_line] arch = "" # Arch can be embedded in the filename, e.g.: "libabc.dylib:x86_64h" colon_pos = binary.rfind(":") Index: compiler-rt/trunk/test/asan/TestCases/Darwin/asan-symbolize-partial-report-with-module-map.cc =================================================================== --- compiler-rt/trunk/test/asan/TestCases/Darwin/asan-symbolize-partial-report-with-module-map.cc +++ compiler-rt/trunk/test/asan/TestCases/Darwin/asan-symbolize-partial-report-with-module-map.cc @@ -0,0 +1,54 @@ +// When `external_symbolizer_path` is empty on Darwin we fallback on using +// dladdr as the symbolizer which means we get the symbol name +// but no source location. The current implementation also doesn't try to +// change the module name so we end up with the full name so we actually don't +// need the module map here. + +// RUN: %clangxx_asan -O0 -g %s -o %t.executable +// RUN: %env_asan_opts=symbolize=1,print_module_map=0,external_symbolizer_path= not %run %t.executable > %t2.log 2>&1 +// RUN: FileCheck -input-file=%t2.log -check-prefix=CHECK-PS %s +// RUN: %asan_symbolize --force-system-symbolizer < %t2.log > %t2.fully_symbolized +// RUN: FileCheck -input-file=%t2.fully_symbolized -check-prefix=CHECK-FS %s + +// Due a quirk in the way atos reports module names we have to use the module +// map here, otherwise we don't know what the full path to the module is. + +// FIXME(dliew): We currently have to use module map for this test due to the atos +// symbolizer changing the module name from an absolute path to just the file name. +// rdar://problem/49784442 +// +// Simulate partial symbolication (can happen with %L specifier) by printing +// out %L's fallback which will print the module name and offset instead of a +// source location. +// RUN: %clangxx_asan -O0 -g %s -o %t2.executable +// RUN: %env_asan_opts=symbolize=1,print_module_map=1,stack_trace_format='" #%%n %%p %%F %%M"' not %run %t.executable > %t2.log 2>&1 +// RUN: FileCheck -input-file=%t2.log -check-prefix=CHECK-PS %s +// Now try to full symbolicate using the module map. +// RUN: %asan_symbolize --module-map %t2.log --force-system-symbolizer < %t2.log > %t2.fully_symbolized +// RUN: FileCheck -input-file=%t2.fully_symbolized -check-prefix=CHECK-FS %s + +#include + +// Partially symbolicated back-trace where symbol is available but +// source location is not and instead module name and offset are +// printed. +// CHECK-PS: WRITE of size 4 +// CHECK-PS: #0 0x{{.+}} in foo ({{.+}}.executable:{{.+}}+0x{{.+}}) +// CHECK-PS: #1 0x{{.+}} in main ({{.+}}.executable:{{.+}}+0x{{.+}}) + +// CHECK-FS: WRITE of size 4 + +extern "C" void foo(int* a) { + // CHECK-FS: #0 0x{{.+}} in foo {{.*}}asan-symbolize-partial-report-with-module-map.cc:[[@LINE+1]] + *a = 5; +} + +int main() { + int* a = (int*) malloc(sizeof(int)); + if (!a) + return 0; + free(a); + // CHECK-FS: #1 0x{{.+}} in main {{.*}}asan-symbolize-partial-report-with-module-map.cc:[[@LINE+1]] + foo(a); + return 0; +}