Index: lib/asan/scripts/asan_symbolize.py =================================================================== --- lib/asan/scripts/asan_symbolize.py +++ lib/asan/scripts/asan_symbolize.py @@ -135,12 +135,13 @@ super(Addr2LineSymbolizer, self).__init__() self.binary = binary self.pipe = self.open_addr2line() + self.output_terminator = "0xffffffffffffffff" def open_addr2line(self): addr2line_tool = 'addr2line' if binutils_prefix: addr2line_tool = binutils_prefix + addr2line_tool - cmd = [addr2line_tool, '-f'] + cmd = [addr2line_tool, '-fi'] if demangle: cmd += ['--demangle'] cmd += ['-e', self.binary] @@ -153,16 +154,21 @@ """Overrides Symbolizer.symbolize.""" if self.binary != binary: return None + lines = [] try: print >> self.pipe.stdin, offset - function_name = self.pipe.stdout.readline().rstrip() - file_name = self.pipe.stdout.readline().rstrip() + print >> self.pipe.stdin, self.output_terminator + result = [] + frame = 0 + while True: + function_name = self.pipe.stdout.readline().rstrip() + file_name = self.pipe.stdout.readline().rstrip() + if function_name.startswith('??'): + break + lines.append((function_name, file_name)); except Exception: - function_name = '' - file_name = '' - file_name = fix_filename(file_name) - return ['%s in %s %s' % (addr, function_name, file_name)] - + lines.append(('??', '??:?')) + return ['%s in %s %s' % (addr, frame[0], fix_filename(frame[1])) for frame in lines] class UnbufferedLineConverter(object): """ Index: lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc +++ lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc @@ -195,29 +195,32 @@ private: bool ReachedEndOfOutput(const char *buffer, uptr length) const override { - // Output should consist of two lines. - int num_lines = 0; - for (uptr i = 0; i < length; ++i) { - if (buffer[i] == '\n') - num_lines++; - if (num_lines >= 2) - return true; - } - return false; + const int terminator_size = sizeof(output_terminator_) - 1; + // Skip, if we red just the OUTPUT_TERMINATOR_, because we should also read + // Addr2Line output, corresponding to dummy 0xffffffffffffffff offset. + if (length == terminator_size && + !internal_memcmp(buffer, output_terminator_, terminator_size)) + return false; + // Addr2Line output should end up with OUTPUT_TERMINATOR_. + return !internal_memcmp(buffer + length - terminator_size, + output_terminator_, terminator_size); } void GetArgV(const char *path_to_binary, const char *(&argv)[kArgVMax]) const override { int i = 0; argv[i++] = path_to_binary; - argv[i++] = "-Cfe"; + argv[i++] = "-iCfe"; argv[i++] = module_name_; argv[i++] = nullptr; } const char *module_name_; // Owned, leaked. + static const char output_terminator_[9]; }; +const char Addr2LineProcess::output_terminator_[9] = "??\n??:0\n"; + class Addr2LinePool : public SymbolizerTool { public: explicit Addr2LinePool(const char *addr2line_path, @@ -228,6 +231,8 @@ bool SymbolizePC(uptr addr, SymbolizedStack *stack) override { if (const char *buf = SendCommand(stack->info.module, stack->info.module_offset)) { + char *garbage = internal_strstr(buf, output_terminator_); + if (garbage && garbage != buf) garbage[0] = '\0'; ParseSymbolizePCOutput(buf, stack); return true; } @@ -255,7 +260,8 @@ } CHECK_EQ(0, internal_strcmp(module_name, addr2line->module_name())); char buffer_[kBufferSize]; - internal_snprintf(buffer_, kBufferSize, "0x%zx\n", module_offset); + internal_snprintf(buffer_, kBufferSize, "0x%zx\n0xffffffffffffffff\n", + module_offset); return addr2line->SendCommand(buffer_); } @@ -263,8 +269,11 @@ const char *addr2line_path_; LowLevelAllocator *allocator_; InternalMmapVector addr2line_pool_; + static const char output_terminator_[9]; }; +const char Addr2LinePool::output_terminator_[9] = "??\n??:0\n"; + #if SANITIZER_SUPPORTS_WEAK_HOOKS extern "C" { SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE