Skip to content
This repository was archived by the owner on May 21, 2019. It is now read-only.

Commit a1f6419

Browse files
committed
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 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@247642 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 0e0eb19 commit a1f6419

File tree

3 files changed

+62
-26
lines changed

3 files changed

+62
-26
lines changed

lib/asan/scripts/asan_symbolize.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,13 @@ def __init__(self, binary):
135135
super(Addr2LineSymbolizer, self).__init__()
136136
self.binary = binary
137137
self.pipe = self.open_addr2line()
138+
self.output_terminator = -1
138139

139140
def open_addr2line(self):
140141
addr2line_tool = 'addr2line'
141142
if binutils_prefix:
142143
addr2line_tool = binutils_prefix + addr2line_tool
143-
cmd = [addr2line_tool, '-f']
144+
cmd = [addr2line_tool, '-fi']
144145
if demangle:
145146
cmd += ['--demangle']
146147
cmd += ['-e', self.binary]
@@ -153,16 +154,23 @@ def symbolize(self, addr, binary, offset):
153154
"""Overrides Symbolizer.symbolize."""
154155
if self.binary != binary:
155156
return None
157+
lines = []
156158
try:
157159
print >> self.pipe.stdin, offset
158-
function_name = self.pipe.stdout.readline().rstrip()
159-
file_name = self.pipe.stdout.readline().rstrip()
160+
print >> self.pipe.stdin, self.output_terminator
161+
is_first_frame = True
162+
while True:
163+
function_name = self.pipe.stdout.readline().rstrip()
164+
file_name = self.pipe.stdout.readline().rstrip()
165+
if is_first_frame:
166+
is_first_frame = False
167+
elif function_name == '??':
168+
assert file_name == '??:0'
169+
break
170+
lines.append((function_name, file_name));
160171
except Exception:
161-
function_name = ''
162-
file_name = ''
163-
file_name = fix_filename(file_name)
164-
return ['%s in %s %s' % (addr, function_name, file_name)]
165-
172+
lines.append(('??', '??:0'))
173+
return ['%s in %s %s' % (addr, function, fix_filename(file)) for (function, file) in lines]
166174

167175
class UnbufferedLineConverter(object):
168176
"""

lib/sanitizer_common/sanitizer_symbolizer_internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,11 @@ class SymbolizerProcess {
8888
UNIMPLEMENTED();
8989
}
9090

91+
virtual bool ReadFromSymbolizer(char *buffer, uptr max_length);
92+
9193
private:
9294
bool Restart();
9395
const char *SendCommandImpl(const char *command);
94-
bool ReadFromSymbolizer(char *buffer, uptr max_length);
9596
bool WriteToSymbolizer(const char *buffer, uptr length);
9697
bool StartSymbolizerSubprocess();
9798

lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -194,30 +194,54 @@ class Addr2LineProcess : public SymbolizerProcess {
194194
const char *module_name() const { return module_name_; }
195195

196196
private:
197-
bool ReachedEndOfOutput(const char *buffer, uptr length) const override {
198-
// Output should consist of two lines.
199-
int num_lines = 0;
200-
for (uptr i = 0; i < length; ++i) {
201-
if (buffer[i] == '\n')
202-
num_lines++;
203-
if (num_lines >= 2)
204-
return true;
205-
}
206-
return false;
207-
}
208-
209197
void GetArgV(const char *path_to_binary,
210198
const char *(&argv)[kArgVMax]) const override {
211199
int i = 0;
212200
argv[i++] = path_to_binary;
213-
argv[i++] = "-Cfe";
201+
argv[i++] = "-iCfe";
214202
argv[i++] = module_name_;
215203
argv[i++] = nullptr;
216204
}
217205

206+
bool ReachedEndOfOutput(const char *buffer, uptr length) const override;
207+
208+
bool ReadFromSymbolizer(char *buffer, uptr max_length) override {
209+
if (!SymbolizerProcess::ReadFromSymbolizer(buffer, max_length))
210+
return false;
211+
// We should cut out output_terminator_ at the end of given buffer,
212+
// appended by addr2line to mark the end of its meaningful output.
213+
// We cannot scan buffer from it's beginning, because it is legal for it
214+
// to start with output_terminator_ in case given offset is invalid. So,
215+
// scanning from second character.
216+
char *garbage = internal_strstr(buffer + 1, output_terminator_);
217+
// This should never be NULL since buffer must end up with
218+
// output_terminator_.
219+
CHECK(garbage);
220+
// Trim the buffer.
221+
garbage[0] = '\0';
222+
return true;
223+
}
224+
218225
const char *module_name_; // Owned, leaked.
226+
static const char output_terminator_[];
219227
};
220228

229+
const char Addr2LineProcess::output_terminator_[] = "??\n??:0\n";
230+
231+
bool Addr2LineProcess::ReachedEndOfOutput(const char *buffer,
232+
uptr length) const {
233+
const size_t kTerminatorLen = sizeof(output_terminator_) - 1;
234+
// Skip, if we read just kTerminatorLen bytes, because Addr2Line output
235+
// should consist at least of two pairs of lines:
236+
// 1. First one, corresponding to given offset to be symbolized
237+
// (may be equal to output_terminator_, if offset is not valid).
238+
// 2. Second one for output_terminator_, itself to mark the end of output.
239+
if (length <= kTerminatorLen) return false;
240+
// Addr2Line output should end up with output_terminator_.
241+
return !internal_memcmp(buffer + length - kTerminatorLen,
242+
output_terminator_, kTerminatorLen);
243+
}
244+
221245
class Addr2LinePool : public SymbolizerTool {
222246
public:
223247
explicit Addr2LinePool(const char *addr2line_path,
@@ -254,15 +278,18 @@ class Addr2LinePool : public SymbolizerTool {
254278
addr2line_pool_.push_back(addr2line);
255279
}
256280
CHECK_EQ(0, internal_strcmp(module_name, addr2line->module_name()));
257-
char buffer_[kBufferSize];
258-
internal_snprintf(buffer_, kBufferSize, "0x%zx\n", module_offset);
259-
return addr2line->SendCommand(buffer_);
281+
char buffer[kBufferSize];
282+
internal_snprintf(buffer, kBufferSize, "0x%zx\n0x%zx\n",
283+
module_offset, dummy_address_);
284+
return addr2line->SendCommand(buffer);
260285
}
261286

262-
static const uptr kBufferSize = 32;
287+
static const uptr kBufferSize = 64;
263288
const char *addr2line_path_;
264289
LowLevelAllocator *allocator_;
265290
InternalMmapVector<Addr2LineProcess*> addr2line_pool_;
291+
static const uptr dummy_address_ =
292+
FIRST_32_SECOND_64(UINT32_MAX, UINT64_MAX);
266293
};
267294

268295
#if SANITIZER_SUPPORTS_WEAK_HOOKS

0 commit comments

Comments
 (0)