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.inline_frames_depth = 10 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] @@ -155,13 +156,24 @@ return None try: print >> self.pipe.stdin, offset - function_name = self.pipe.stdout.readline().rstrip() - file_name = self.pipe.stdout.readline().rstrip() + print >> self.pipe.stdin, "0xbadbadbad" + result = [] + lines = [] + frame = 0 + while frame < self.inline_frames_depth: + 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)); + ++frame except Exception: - function_name = '' - file_name = '' - file_name = fix_filename(file_name) - return ['%s in %s %s' % (addr, function_name, file_name)] + lines = (('??', '??:?')) + for frame in lines: + function_name = frame[0] + file_name = fix_filename(frame[1]) + result.append('%s in %s %s' % (addr, function_name, file_name)) + return result 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 @@ -75,7 +75,7 @@ const char *SendCommand(const char *command); protected: - virtual bool ReachedEndOfOutput(const char *buffer, uptr length) const { + virtual uptr GetEffectiveLenOfOutput(const char *buffer, uptr length) const { UNIMPLEMENTED(); } Index: lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc +++ lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc @@ -199,10 +199,10 @@ explicit LLVMSymbolizerProcess(const char *path) : SymbolizerProcess(path) {} private: - bool ReachedEndOfOutput(const char *buffer, uptr length) const override { + uptr GetEffectiveLenOfOutput(const char *buffer, uptr length) const override { // Empty line marks the end of llvm-symbolizer output. return length >= 2 && buffer[length - 1] == '\n' && - buffer[length - 2] == '\n'; + buffer[length - 2] == '\n' ? length : 0; } void GetArgV(const char *path_to_binary, @@ -395,6 +395,7 @@ if (max_length == 0) return true; uptr read_len = 0; + uptr effective_len = 0; while (true) { uptr just_read = 0; bool success = ReadFromFile(input_fd_, buffer + read_len, @@ -406,10 +407,11 @@ return false; } read_len += just_read; - if (ReachedEndOfOutput(buffer, read_len)) + effective_len = GetEffectiveLenOfOutput(buffer, read_len); + if (effective_len) break; } - buffer[read_len] = '\0'; + buffer[effective_len] = '\0'; return true; } Index: lib/sanitizer_common/sanitizer_symbolizer_mac.cc =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer_mac.cc +++ lib/sanitizer_common/sanitizer_symbolizer_mac.cc @@ -51,8 +51,8 @@ } private: - bool ReachedEndOfOutput(const char *buffer, uptr length) const override { - return (length >= 1 && buffer[length - 1] == '\n'); + uptr GetEffectiveLenOfOutput(const char *buffer, uptr length) const override { + return (length >= 1 && buffer[length - 1] == '\n') ? length : 0; } void GetArgV(const char *path_to_binary, 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 @@ -194,23 +194,26 @@ const char *module_name() const { return module_name_; } private: - bool ReachedEndOfOutput(const char *buffer, uptr length) const override { - // Output should consist of two lines. + uptr GetEffectiveLenOfOutput(const char *buffer, uptr length) const override { + // Output should consist at least of two lines. We pass 0xbadbadbad to the + // of addr2line to indicate end of meaningful output. int num_lines = 0; + uptr len = 0; for (uptr i = 0; i < length; ++i) { if (buffer[i] == '\n') num_lines++; - if (num_lines >= 2) - return true; + if ((num_lines >= 2) && (buffer[i] == '?')) + return len - 1; + ++len; } - return false; + return 0; } 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; } @@ -255,7 +258,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\n0xbadbadbad\n", + module_offset); return addr2line->SendCommand(buffer_); }