Skip to content

Commit b1306da

Browse files
[compiler-rt] Fix frame numbering for unparsable frames. (llvm#148278)
This can happen when JIT code is run, and we can't symbolize those frames, but they should remain numbered in the stack. An example spidermonkey trace: ``` #0 0x564ac90fb80f (/builds/worker/dist/bin/js+0x240e80f) (BuildId: 5d053c76aad4cfbd08259f8832e7ac78bbeeab58) #1 0x564ac9223a64 (/builds/worker/dist/bin/js+0x2536a64) (BuildId: 5d053c76aad4cfbd08259f8832e7ac78bbeeab58) #2 0x564ac922316f (/builds/worker/dist/bin/js+0x253616f) (BuildId: 5d053c76aad4cfbd08259f8832e7ac78bbeeab58) #3 0x564ac9eac032 (/builds/worker/dist/bin/js+0x31bf032) (BuildId: 5d053c76aad4cfbd08259f8832e7ac78bbeeab58) llvm#4 0x0dec477ca22e (<unknown module>) ``` Without this change, the following symbolization is output: ``` #0 0x55a6d72f980f in MOZ_CrashSequence /builds/worker/workspace/obj-build/dist/include/mozilla/Assertions.h:248:3 #1 0x55a6d72f980f in Crash(JSContext*, unsigned int, JS::Value*) /builds/worker/checkouts/gecko/js/src/shell/js.cpp:4223:5 #2 0x55a6d7421a64 in CallJSNative(JSContext*, bool (*)(JSContext*, unsigned int, JS::Value*), js::CallReason, JS::CallArgs const&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:501:13 #3 0x55a6d742116f in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:597:12 llvm#4 0x55a6d80aa032 in js::jit::DoCallFallback(JSContext*, js::jit::BaselineFrame*, js::jit::ICFallbackStub*, unsigned int, JS::Value*, JS::MutableHandle<JS::Value>) /builds/worker/checkouts/gecko/js/src/jit/BaselineIC.cpp:1705:10 llvm#4 0x2c803bd8f22e (<unknown module>) ``` The last frame has a duplicate number. With this change the numbering is correct: ``` #0 0x5620c58ec80f in MOZ_CrashSequence /builds/worker/workspace/obj-build/dist/include/mozilla/Assertions.h:248:3 #1 0x5620c58ec80f in Crash(JSContext*, unsigned int, JS::Value*) /builds/worker/checkouts/gecko/js/src/shell/js.cpp:4223:5 #2 0x5620c5a14a64 in CallJSNative(JSContext*, bool (*)(JSContext*, unsigned int, JS::Value*), js::CallReason, JS::CallArgs const&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:501:13 #3 0x5620c5a1416f in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:597:12 llvm#4 0x5620c669d032 in js::jit::DoCallFallback(JSContext*, js::jit::BaselineFrame*, js::jit::ICFallbackStub*, unsigned int, JS::Value*, JS::MutableHandle<JS::Value>) /builds/worker/checkouts/gecko/js/src/jit/BaselineIC.cpp:1705:10 llvm#5 0x349f24c7022e (<unknown module>) ```
1 parent fd7f69b commit b1306da

File tree

2 files changed

+21
-14
lines changed

2 files changed

+21
-14
lines changed

compiler-rt/lib/asan/scripts/asan_symbolize.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -507,20 +507,29 @@ def symbolize_address(self, addr, binary, offset, arch):
507507
assert result
508508
return result
509509

510-
def get_symbolized_lines(self, symbolized_lines, inc_frame_counter=True):
510+
def get_symbolized_lines(self, symbolized_lines):
511511
if not symbolized_lines:
512-
if inc_frame_counter:
513-
self.frame_no += 1
514-
return [self.current_line]
515-
else:
516-
assert inc_frame_counter
517-
result = []
518-
for symbolized_frame in symbolized_lines:
519-
result.append(
520-
" #%s %s" % (str(self.frame_no), symbolized_frame.rstrip())
512+
# If it is an unparsable frame, but contains a frame counter and address
513+
# replace the frame counter so the stack is still consistent.
514+
unknown_stack_frame_format = r"^( *#([0-9]+) +)(0x[0-9a-f]+) +.*"
515+
match = re.match(unknown_stack_frame_format, self.current_line)
516+
if match:
517+
rewritten_line = (
518+
self.current_line[: match.start(2)]
519+
+ str(self.frame_no)
520+
+ self.current_line[match.end(2) :]
521521
)
522522
self.frame_no += 1
523-
return result
523+
return [rewritten_line]
524+
# Not a frame line so don't increment the frame counter.
525+
return [self.current_line]
526+
result = []
527+
for symbolized_frame in symbolized_lines:
528+
result.append(
529+
" #%s %s" % (str(self.frame_no), symbolized_frame.rstrip())
530+
)
531+
self.frame_no += 1
532+
return result
524533

525534
def process_logfile(self):
526535
self.frame_no = 0
@@ -546,8 +555,7 @@ def process_line_posix(self, line):
546555
match = re.match(stack_trace_line_format, line)
547556
if not match:
548557
logging.debug('Line "{}" does not match regex'.format(line))
549-
# Not a frame line so don't increment the frame counter.
550-
return self.get_symbolized_lines(None, inc_frame_counter=False)
558+
return self.get_symbolized_lines(None)
551559
logging.debug(line)
552560
_, frameno_str, addr, binary, offset = match.groups()
553561

compiler-rt/test/asan/TestCases/Posix/asan_symbolize_script/anon_wrong_frame_number.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
// UNSUPPORTED: aarch64
66
// UNSUPPORTED: darwin
77
// UNSUPPORTED: ios
8-
// XFAIL: *
98

109
// RUN: %clangxx_asan -O0 -g %s -o %t
1110
// RUN: %env_asan_opts=symbolize=0 not %run %t DUMMY_ARG > %t.asan_report 2>&1

0 commit comments

Comments
 (0)