[compiler-rt] r247642 - Support inline functions symbolization in Addr2Line symbolizer.
Alexey Samsonov via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 14 16:56:43 PDT 2015
Author: samsonov
Date: Mon Sep 14 18:56:42 2015
New Revision: 247642
URL: http://llvm.org/viewvc/llvm-project?rev=247642&view=rev
Log:
Support inline functions symbolization in Addr2Line symbolizer.
Patch by Maxim Ostapenko!
Summary:
Right now, Addr2Line symbolizer in asan_symbolize.py doesn't support inline functions symbolization. This might be a useful feature for using ASan on embedded systems.
Test results:
$ cat test.c
static inline void FooBarBaz() {
__sanitizer_print_stack_trace();
}
int main() {
FooBarBaz();
return 0;
}
$ clang test.c -fsanitize=address -g -O2 -o test.x && ./test.x &> /tmp/test.log
$ ./projects/compiler-rt/lib/asan/scripts/asan_symbolize.py -l /tmp/test.log
#0 0x42095e in __sanitizer_print_stack_trace _asan_rtl_
#1 0x4cec07 in FooBarBaz /home/max/build/llvm/asan/test.c:4
#2 0x4cec07 in main /home/max/build/llvm/asan/test.c:8
#3 0x7f89f0891ec4 in __libc_start_main /build/buildd/eglibc-2.19/csu/libc-start.c:287
Reviewers: glider, samsonov
Subscribers: jevinskie, llvm-commits, ygribov
Differential Revision: http://reviews.llvm.org/D12153
Modified:
compiler-rt/trunk/lib/asan/scripts/asan_symbolize.py
compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_internal.h
compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
Modified: compiler-rt/trunk/lib/asan/scripts/asan_symbolize.py
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/scripts/asan_symbolize.py?rev=247642&r1=247641&r2=247642&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/scripts/asan_symbolize.py (original)
+++ compiler-rt/trunk/lib/asan/scripts/asan_symbolize.py Mon Sep 14 18:56:42 2015
@@ -135,12 +135,13 @@ class Addr2LineSymbolizer(Symbolizer):
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,23 @@ class Addr2LineSymbolizer(Symbolizer):
"""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 == '??':
+ assert file_name == '??: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(('??', '??:0'))
+ return ['%s in %s %s' % (addr, function, fix_filename(file)) for (function, file) in lines]
class UnbufferedLineConverter(object):
"""
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_internal.h?rev=247642&r1=247641&r2=247642&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_internal.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_internal.h Mon Sep 14 18:56:42 2015
@@ -88,10 +88,11 @@ class SymbolizerProcess {
UNIMPLEMENTED();
}
+ virtual bool ReadFromSymbolizer(char *buffer, uptr max_length);
+
private:
bool Restart();
const char *SendCommandImpl(const char *command);
- bool ReadFromSymbolizer(char *buffer, uptr max_length);
bool WriteToSymbolizer(const char *buffer, uptr length);
bool StartSymbolizerSubprocess();
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc?rev=247642&r1=247641&r2=247642&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc Mon Sep 14 18:56:42 2015
@@ -194,30 +194,54 @@ class Addr2LineProcess : public Symboliz
const char *module_name() const { return module_name_; }
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;
- }
-
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;
}
+ bool ReachedEndOfOutput(const char *buffer, uptr length) const override;
+
+ bool ReadFromSymbolizer(char *buffer, uptr max_length) override {
+ if (!SymbolizerProcess::ReadFromSymbolizer(buffer, max_length))
+ return false;
+ // We should cut out output_terminator_ at the end of given buffer,
+ // appended by addr2line to mark the end of its meaningful output.
+ // We cannot scan buffer from it's beginning, because it is legal for it
+ // to start with output_terminator_ in case given offset is invalid. So,
+ // scanning from second character.
+ char *garbage = internal_strstr(buffer + 1, output_terminator_);
+ // This should never be NULL since buffer must end up with
+ // output_terminator_.
+ CHECK(garbage);
+ // Trim the buffer.
+ garbage[0] = '\0';
+ return true;
+ }
+
const char *module_name_; // Owned, leaked.
+ static const char output_terminator_[];
};
+const char Addr2LineProcess::output_terminator_[] = "??\n??:0\n";
+
+bool Addr2LineProcess::ReachedEndOfOutput(const char *buffer,
+ uptr length) const {
+ const size_t kTerminatorLen = sizeof(output_terminator_) - 1;
+ // Skip, if we read just kTerminatorLen 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 <= kTerminatorLen) return false;
+ // Addr2Line output should end up with output_terminator_.
+ return !internal_memcmp(buffer + length - kTerminatorLen,
+ output_terminator_, kTerminatorLen);
+}
+
class Addr2LinePool : public SymbolizerTool {
public:
explicit Addr2LinePool(const char *addr2line_path,
@@ -254,15 +278,18 @@ class Addr2LinePool : public SymbolizerT
addr2line_pool_.push_back(addr2line);
}
CHECK_EQ(0, internal_strcmp(module_name, addr2line->module_name()));
- char buffer_[kBufferSize];
- internal_snprintf(buffer_, kBufferSize, "0x%zx\n", module_offset);
- return addr2line->SendCommand(buffer_);
+ char buffer[kBufferSize];
+ internal_snprintf(buffer, kBufferSize, "0x%zx\n0x%zx\n",
+ module_offset, dummy_address_);
+ return addr2line->SendCommand(buffer);
}
- static const uptr kBufferSize = 32;
+ static const uptr kBufferSize = 64;
const char *addr2line_path_;
LowLevelAllocator *allocator_;
InternalMmapVector<Addr2LineProcess*> addr2line_pool_;
+ static const uptr dummy_address_ =
+ FIRST_32_SECOND_64(UINT32_MAX, UINT64_MAX);
};
#if SANITIZER_SUPPORTS_WEAK_HOOKS
More information about the llvm-commits
mailing list