OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 #===- lib/asan/scripts/asan_symbolize.py -----------------------------------===# | 2 #===- lib/asan/scripts/asan_symbolize.py -----------------------------------===# |
3 # | 3 # |
4 # The LLVM Compiler Infrastructure | 4 # The LLVM Compiler Infrastructure |
5 # | 5 # |
6 # This file is distributed under the University of Illinois Open Source | 6 # This file is distributed under the University of Illinois Open Source |
7 # License. See LICENSE.TXT for details. | 7 # License. See LICENSE.TXT for details. |
8 # | 8 # |
9 #===------------------------------------------------------------------------===# | 9 #===------------------------------------------------------------------------===# |
10 import bisect | 10 import bisect |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 | 324 |
325 class SymbolizationLoop(object): | 325 class SymbolizationLoop(object): |
326 def __init__(self, binary_name_filter=None): | 326 def __init__(self, binary_name_filter=None): |
327 # Used by clients who may want to supply a different binary name. | 327 # Used by clients who may want to supply a different binary name. |
328 # E.g. in Chrome several binaries may share a single .dSYM. | 328 # E.g. in Chrome several binaries may share a single .dSYM. |
329 self.binary_name_filter = binary_name_filter | 329 self.binary_name_filter = binary_name_filter |
330 self.system = os.uname()[0] | 330 self.system = os.uname()[0] |
331 if self.system not in ['Linux', 'Darwin']: | 331 if self.system not in ['Linux', 'Darwin']: |
332 raise Exception('Unknown system') | 332 raise Exception('Unknown system') |
333 self.llvm_symbolizer = None | 333 self.llvm_symbolizer = None |
| 334 self.frame_no = 0 |
334 | 335 |
335 def symbolize_address(self, addr, binary, offset): | 336 def symbolize_address(self, addr, binary, offset): |
336 # Initialize llvm-symbolizer lazily. | 337 # Initialize llvm-symbolizer lazily. |
337 if not self.llvm_symbolizer: | 338 if not self.llvm_symbolizer: |
338 self.llvm_symbolizer = LLVMSymbolizerFactory(self.system, addr) | 339 self.llvm_symbolizer = LLVMSymbolizerFactory(self.system, addr) |
339 # Use the chain of symbolizers: | 340 # Use the chain of symbolizers: |
340 # Breakpad symbolizer -> LLVM symbolizer -> addr2line/atos | 341 # Breakpad symbolizer -> LLVM symbolizer -> addr2line/atos |
341 # (fall back to next symbolizer if the previous one fails). | 342 # (fall back to next symbolizer if the previous one fails). |
342 if not binary in symbolizers: | 343 if not binary in symbolizers: |
343 symbolizers[binary] = ChainSymbolizer( | 344 symbolizers[binary] = ChainSymbolizer( |
344 [BreakpadSymbolizerFactory(binary), self.llvm_symbolizer]) | 345 [BreakpadSymbolizerFactory(binary), self.llvm_symbolizer]) |
345 result = symbolizers[binary].symbolize(addr, binary, offset) | 346 result = symbolizers[binary].symbolize(addr, binary, offset) |
346 if result is None: | 347 if result is None: |
347 # Initialize system symbolizer only if other symbolizers failed. | 348 # Initialize system symbolizer only if other symbolizers failed. |
348 symbolizers[binary].append_symbolizer( | 349 symbolizers[binary].append_symbolizer( |
349 SystemSymbolizerFactory(self.system, addr, binary)) | 350 SystemSymbolizerFactory(self.system, addr, binary)) |
350 result = symbolizers[binary].symbolize(addr, binary, offset) | 351 result = symbolizers[binary].symbolize(addr, binary, offset) |
351 # The system symbolizer must produce some result. | 352 # The system symbolizer must produce some result. |
352 assert result | 353 assert result |
353 return result | 354 return result |
354 | 355 |
355 def print_symbolized_lines(self, symbolized_lines): | 356 def get_symbolized_lines(self, symbolized_lines): |
356 if not symbolized_lines: | 357 if not symbolized_lines: |
357 print self.current_line | 358 return [self.current_line] |
358 else: | 359 else: |
| 360 result = [] |
359 for symbolized_frame in symbolized_lines: | 361 for symbolized_frame in symbolized_lines: |
360 print ' #' + str(self.frame_no) + ' ' + symbolized_frame.rstrip() | 362 result.append(' #%s %s' % (str(self.frame_no), symbolized_frame.rstri
p())) |
361 self.frame_no += 1 | 363 self.frame_no += 1 |
| 364 return result |
362 | 365 |
363 def process_stdin(self): | 366 def process_stdin(self): |
364 self.frame_no = 0 | 367 self.frame_no = 0 |
365 while True: | 368 while True: |
366 line = sys.stdin.readline() | 369 line = sys.stdin.readline() |
367 if not line: | 370 if not line: |
368 break | 371 break |
369 self.current_line = line.rstrip() | 372 processed = self.process_line(line) |
370 #0 0x7f6e35cf2e45 (/blah/foo.so+0x11fe45) | 373 print ''.join(processed) |
371 stack_trace_line_format = ( | 374 |
372 '^( *#([0-9]+) *)(0x[0-9a-f]+) *\((.*)\+(0x[0-9a-f]+)\)') | 375 def process_line(self, line): |
373 match = re.match(stack_trace_line_format, line) | 376 self.current_line = line.rstrip() |
374 if not match: | 377 #0 0x7f6e35cf2e45 (/blah/foo.so+0x11fe45) |
375 print self.current_line | 378 stack_trace_line_format = ( |
376 continue | 379 '^( *#([0-9]+) *)(0x[0-9a-f]+) *\((.*)\+(0x[0-9a-f]+)\)') |
377 if DEBUG: | 380 match = re.match(stack_trace_line_format, line) |
378 print line | 381 if not match: |
379 _, frameno_str, addr, binary, offset = match.groups() | 382 return [self.current_line] |
380 if frameno_str == '0': | 383 if DEBUG: |
381 # Assume that frame #0 is the first frame of new stack trace. | 384 print line |
382 self.frame_no = 0 | 385 _, frameno_str, addr, binary, offset = match.groups() |
383 original_binary = binary | 386 if frameno_str == '0': |
384 if self.binary_name_filter: | 387 # Assume that frame #0 is the first frame of new stack trace. |
385 binary = self.binary_name_filter(binary) | 388 self.frame_no = 0 |
386 symbolized_line = self.symbolize_address(addr, binary, offset) | 389 original_binary = binary |
387 if not symbolized_line: | 390 if self.binary_name_filter: |
388 if original_binary != binary: | 391 binary = self.binary_name_filter(binary) |
389 symbolized_line = self.symbolize_address(addr, binary, offset) | 392 symbolized_line = self.symbolize_address(addr, binary, offset) |
390 self.print_symbolized_lines(symbolized_line) | 393 if not symbolized_line: |
| 394 if original_binary != binary: |
| 395 symbolized_line = self.symbolize_address(addr, binary, offset) |
| 396 return self.get_symbolized_lines(symbolized_line) |
391 | 397 |
392 | 398 |
393 if __name__ == '__main__': | 399 if __name__ == '__main__': |
394 opts, args = getopt.getopt(sys.argv[1:], "d", ["demangle"]) | 400 opts, args = getopt.getopt(sys.argv[1:], "d", ["demangle"]) |
395 for o, a in opts: | 401 for o, a in opts: |
396 if o in ("-d", "--demangle"): | 402 if o in ("-d", "--demangle"): |
397 demangle = True; | 403 demangle = True; |
398 loop = SymbolizationLoop() | 404 loop = SymbolizationLoop() |
399 loop.process_stdin() | 405 loop.process_stdin() |
OLD | NEW |