mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-28 18:10:46 +00:00
Fix backtrace limit stopping on inline frame
If you have set up a backtrace limit, and the backtrace stops
because of this in an inline frame with arguments, you get an
assertion failure:
```
(gdb) bt
(gdb) set backtrace limit 2
(gdb) bt
C:/src/repos/binutils-gdb.git/gdb/frame.c:3346: internal-error: reinflate: Assertion `m_cached_level >= -1' failed.
```
And if this one is fixed, there is another one as well:
```
(gdb) bt
C:/src/repos/binutils-gdb.git/gdb/dwarf2/loc.c:1160: internal-error: dwarf_expr_reg_to_entry_parameter: Assertion `frame != NULL' failed.
```
The reason for both of them is this kind of loop:
```
while (get_frame_type (frame) == INLINE_FRAME)
frame = get_prev_frame (frame);
```
Since get_prev_frame respects the backtrace limit, it will return
NULL, and from there on you can't continue.
This changes these loops to use get_prev_frame_always instead, so
you always get a non-inline frame in the end.
With this backtrace works:
```
(gdb) bt
(gdb)
```
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29865
Approved-By: Andrew Burgess <aburgess@redhat.com>
This commit is contained in:
@@ -1423,7 +1423,7 @@ dwarf2_frame_cfa (frame_info_ptr this_frame)
|
||||
_("cfa not available for record btrace target"));
|
||||
|
||||
while (get_frame_type (this_frame) == INLINE_FRAME)
|
||||
this_frame = get_prev_frame (this_frame);
|
||||
this_frame = get_prev_frame_always (this_frame);
|
||||
if (get_frame_unwind_stop_reason (this_frame) == UNWIND_UNAVAILABLE)
|
||||
throw_error (NOT_AVAILABLE_ERROR,
|
||||
_("can't compute CFA for this frame: "
|
||||
|
||||
@@ -1155,7 +1155,7 @@ dwarf_expr_reg_to_entry_parameter (frame_info_ptr frame,
|
||||
|
||||
while (get_frame_type (frame) == INLINE_FRAME)
|
||||
{
|
||||
frame = get_prev_frame (frame);
|
||||
frame = get_prev_frame_always (frame);
|
||||
gdb_assert (frame != NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,15 +28,15 @@ volatile int result;
|
||||
|
||||
void bar(void);
|
||||
|
||||
inline ATTR int func1(void)
|
||||
inline ATTR int func1(int s)
|
||||
{
|
||||
bar ();
|
||||
return x * y;
|
||||
return x * y + s;
|
||||
}
|
||||
|
||||
inline ATTR int func2(void)
|
||||
{
|
||||
return x * func1 ();
|
||||
return x * func1 (1);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
@@ -47,7 +47,7 @@ int main (void)
|
||||
y = 8;
|
||||
bar ();
|
||||
|
||||
val = func1 ();
|
||||
val = func1 (2);
|
||||
result = val;
|
||||
|
||||
val = func2 ();
|
||||
|
||||
@@ -65,3 +65,4 @@ gdb_test "up" "#1 .*func1.*" "up from bar (4)"
|
||||
gdb_test "info frame" ".*in func1.*" "info frame still works"
|
||||
# Verify the user visible limit works as expected.
|
||||
gdb_test "up" "Initial frame selected; you cannot go up." "up hits limit"
|
||||
gdb_test "backtrace" "#0 bar.*#1 .*func1.*" "backtrace hits limit"
|
||||
|
||||
Reference in New Issue
Block a user