Skip to content

Commit d479798

Browse files
committed
Profile: fix identification of block ends
If the unwinder got an ip=1, we think that is a valid frame and try to keep going, but we store ip=0. It is not a valid frame, so stop going. Replaces #42308 Fixes #42292
1 parent f5ce7c4 commit d479798

File tree

2 files changed

+15
-4
lines changed

2 files changed

+15
-4
lines changed

src/stackwalk.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,13 @@ static int jl_unw_stepn(bt_cursor_t *cursor, jl_bt_element_t *bt_data, size_t *b
102102
// But sometimes the external unwinder doesn't check that.
103103
have_more_frames = 0;
104104
}
105+
if (return_ip == 0) {
106+
// The return address is clearly wrong, and while the unwinder
107+
// might try to continue (by popping another stack frame), that
108+
// likely won't work well, and it'll confuse the stack frame
109+
// separator detection logic (double-NULL).
110+
have_more_frames = 0;
111+
}
105112
if (skip > 0) {
106113
skip--;
107114
from_signal_handler = 0;
@@ -141,8 +148,9 @@ static int jl_unw_stepn(bt_cursor_t *cursor, jl_bt_element_t *bt_data, size_t *b
141148
if (!from_signal_handler)
142149
call_ip -= 1; // normal frame
143150
from_signal_handler = 0;
144-
if (call_ip == JL_BT_NON_PTR_ENTRY) {
151+
if (call_ip == JL_BT_NON_PTR_ENTRY || call_ip == 0) {
145152
// Never leave special marker in the bt data as it can corrupt the GC.
153+
have_more_frames = 0;
146154
call_ip = 0;
147155
}
148156
jl_bt_element_t *bt_entry = bt_data + n;

stdlib/Profile/src/Profile.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,9 +291,12 @@ end
291291

292292
function is_block_end(data, i)
293293
i < nmeta + 1 && return false
294-
# 32-bit linux has been seen to have rogue NULL ips, so we use two to indicate block end, where the 2nd is the
295-
# actual end index
296-
return data[i] == 0 && data[i - 1] == 0
294+
# 32-bit linux has been seen to have rogue NULL ips, so we use two to
295+
# indicate block end, where the 2nd is the actual end index.
296+
# and we could have (though very unlikely):
297+
# 1:<stack><metadata><null><null><NULL><metadata><null><null>:end
298+
# and we want to ignore the triple NULL (which is an ip).
299+
return data[i] == 0 && data[i - 1] == 0 && data[i - 2] != 0
297300
end
298301

299302
"""

0 commit comments

Comments
 (0)