Skip to content

Commit

Permalink
Use the first stack in a sanitizer log
Browse files Browse the repository at this point in the history
  • Loading branch information
tysmith committed Oct 26, 2023
1 parent 9cf25f7 commit 2c97c89
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 33 deletions.
54 changes: 27 additions & 27 deletions grizzly/common/stack_hasher.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
# These entries pad out the stack and make bucketing more difficult
IGNORED_FRAMES = (
"core::panicking::",
"mozglue_static::panic_hook::",
"mozglue_static::panic_hook",
"rust_begin_unwind",
"RustMozCrash",
"std::panicking::",
Expand Down Expand Up @@ -347,9 +347,11 @@ def from_text(cls, input_text, major_depth=MAJOR_DEPTH, parse_mode=None):
input_txt is the data to parse the trace from.
"""

frames = []
prev_line = None
for line in reversed(input_text.split("\n")):
# collection of parsed stacks
stacks = []
# current stack
current = []
for line in input_text.split("\n"):
line = line.rstrip()
if not line:
# skip empty lines
Expand All @@ -369,30 +371,28 @@ def from_text(cls, input_text, major_depth=MAJOR_DEPTH, parse_mode=None):
assert frame.mode == parse_mode

if frame.stack_line is not None:
stack_line = int(frame.stack_line)
# check if we've found a different stack in the data
if prev_line is not None and prev_line <= stack_line:
# check for new stack
if int(frame.stack_line) == 0 and current:
stacks.append(current)
current = []
# check for out of order frames
elif (
current
and current[-1].stack_line
and int(frame.stack_line) <= int(current[-1].stack_line)
):
LOG.debug("scrambled logs?")
break
frames.insert(0, frame)
if stack_line < 1:
break
prev_line = stack_line
else:
frames.insert(0, frame)

# sanity check
if frames and prev_line is not None:
# assuming the first frame is 0
if int(frames[0].stack_line) != 0:
LOG.warning("First stack frame is %s not 0", frames[0].stack_line)
if int(frames[-1].stack_line) != len(frames) - 1:
LOG.warning(
"Missing frames? Last frame is %s, expected %d (frames-1)",
frames[-1].stack_line,
len(frames) - 1,
)

return cls(frames=frames, major_depth=major_depth)
current.append(frame)
stacks.append(current)
LOG.debug("stacks detected: %d", sum(1 for x in stacks if x))

# select stack to use
if parse_mode == Mode.SANITIZER:
current = stacks[0]
else:
current = stacks[-1]
return cls(frames=current, major_depth=major_depth)

@property
def height_limit(self):
Expand Down
32 changes: 26 additions & 6 deletions grizzly/common/test_stack_hasher.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,20 @@ def test_stack_07():


def test_stack_08():
"""test creating a Stack by calling from_text() with text containing 2 stacks"""
"""test creating a Stack by calling from_text() with text multiple stacks"""
input_txt = (
""
" #0 0x0bad0bad in bad::frame0(nsA*, nsB*) /aa/a.cpp:12:1\n"
" #1 0x0bad0bad in bad::frame1(mz::d::EE*, int) /aa/a.cpp:12:1\n"
"=================================================================\n"
"==5540==ERROR: AddressSanitizer: ...\n"
" #0 0x1badf00d in good::frame0(nsA*, nsB*) /aa/a.cpp:12:1\n"
" #1 0xdeadbeef in good::frame1(mz::d::EE*, int) /aa/a.cpp:12:1\n"
" #1 0xdeadbeef in good::frame1(mz::d::EE*, int) /aa/a.cpp:12:1\n\n"
"0x12876 is located 1024 bytes after 4096-byte region [0x12876,0x12876)\n"
"freed by thread T5 here:\n"
" #0 0x0bad0bad in bad::frame0(nsA*, nsB*) /aa/a.cpp:12:1\n"
" #1 0x0bad0bad in bad::frame1(mz::d::EE*, int) /aa/a.cpp:12:1\n\n"
"0x12876 is located 1024 bytes after 4096-byte region [0x12876,0x12876)\n"
"previously allocated by thread T0 here:\n"
" #0 0x0bad0bad in bad::frame0(nsA*, nsB*) /aa/a.cpp:12:1\n"
" #1 0x0bad0bad in bad::frame1(mz::d::EE*, int) /aa/a.cpp:12:1\n\n"
)
stack = Stack.from_text(input_txt)
assert len(stack.frames) == 2
Expand Down Expand Up @@ -309,7 +316,7 @@ def test_stack_16():
" #2 0x0001233 in stack_1c() test/a.cpp:34\n"
)
assert len(stack.frames) == 2
assert stack.frames[0].function == "stack_1b"
assert stack.frames[0].function == "stack_1a"
assert stack.frames[0].mode == Mode.SANITIZER


Expand Down Expand Up @@ -474,6 +481,19 @@ def test_sanitizer_stackframe_09():
assert frame.mode == Mode.SANITIZER


def test_sanitizer_stackframe_10():
"""test creating a StackFrame from a line with build id"""
frame = StackFrame.from_line(
" #0 0x7f76d25b7fc0 (/usr/lib/x86_64-linux-gnu/dri/swrast_dri.so+0x704fc0) "
"(BuildId: d04a40e4062a8d444ff6f23d4fe768215b2e32c7)"
)
assert frame.stack_line == "0"
assert frame.function is None
assert frame.location == "swrast_dri.so"
assert frame.offset == "0x704fc0"
assert frame.mode == Mode.SANITIZER


def test_gdb_stackframe_01():
"""test creating a StackFrame from a GDB line with symbols"""
frame = StackFrame.from_line(
Expand Down

0 comments on commit 2c97c89

Please sign in to comment.