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 = -1 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,22 @@ """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 + is_first_frame = True + while True: + function_name = self.pipe.stdout.readline().rstrip() + file_name = self.pipe.stdout.readline().rstrip() + if is_first_frame: + is_first_frame = False + elif function_name.startswith('??') and file_name.startswith('??:0'): + 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, line, fix_filename(file)) for (line, file) in lines] class UnbufferedLineConverter(object): """ Index: lib/sanitizer_common/sanitizer_symbolizer_internal.h =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer_internal.h +++ lib/sanitizer_common/sanitizer_symbolizer_internal.h @@ -88,6 +88,10 @@ UNIMPLEMENTED(); } + virtual void TrimOutputBuffer(char *buffer, const uptr read_len) { + buffer[read_len] = '\0'; + } + private: bool Restart(); const char *SendCommandImpl(const char *command); Index: lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc +++ lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc @@ -409,7 +409,7 @@ if (ReachedEndOfOutput(buffer, read_len)) break; } - buffer[read_len] = '\0'; + TrimOutputBuffer(buffer, read_len); return true; } 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,13 +195,19 @@ 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; + const size_t terminator_len = sizeof(output_terminator_) - 1; + // Skip, if we red just TERMINATOR_LEN bytes, because Addr2Line output + // should consist at least of two pairs of lines: + // 1. First one, corresponding to given offset to be symbolized + // (may be equal to OUTPUT_TERMINATOR_ if offset is not valid). + // 2. Second one for OUTPUT_TERMINATOR_ itself to mark the end of output. + if (length == terminator_len) return false; + // Addr2Line output should end up with OUTPUT_TERMINATOR_. + bool is_terminated = !internal_memcmp(buffer + length - terminator_len, + output_terminator_, terminator_len); + if (is_terminated) { + effective_length = length - terminator_len; + return true; } return false; } @@ -210,14 +216,23 @@ 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; } + void TrimOutputBuffer(char *buffer, const uptr read_len) override { + buffer[effective_length] = '\0'; + } + const char *module_name_; // Owned, leaked. + static size_t effective_length; + static const char output_terminator_[9]; }; +const char Addr2LineProcess::output_terminator_[] = "??\n??:0\n"; +size_t Addr2LineProcess::effective_length; + class Addr2LinePool : public SymbolizerTool { public: explicit Addr2LinePool(const char *addr2line_path, @@ -255,7 +270,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\n%zx\n", + module_offset, output_terminator_); return addr2line->SendCommand(buffer_); } @@ -263,6 +279,8 @@ const char *addr2line_path_; LowLevelAllocator *allocator_; InternalMmapVector addr2line_pool_; + static const uptr output_terminator_ = + FIRST_32_SECOND_64(UINT32_MAX, UINT64_MAX); }; #if SANITIZER_SUPPORTS_WEAK_HOOKS