lijiang1489 at 163 dot com
2018-06-14 03:25:35 UTC
https://sourceware.org/bugzilla/show_bug.cgi?id=23287
Bug ID: 23287
Summary: function: inline_frame_this_id
assert(frame_id_p(*this_id)) occured
Product: gdb
Version: 8.1
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: backtrace
Assignee: unassigned at sourceware dot org
Reporter: lijiang1489 at 163 dot com
Target Milestone: ---
Hi, all
There is a case that a program_A is running on a physical board. When
program_A running to exit, it left a situation:
Insn at PC is : br itself (like a while (1))
Value of LR is : LR == PC (equal)
The next time, i tried to start gdb with "gdb program_B" and connect the target
board with command"tar remote xxx". When i tried to backtrace here, gdb assert
failed at "inline_frame_this_id: assert(frame_id_p(*this_id)".
why? I have found out that:
1. PC at program_B is a normal PC, it has a normal frame
2. (PC-4) is a inline function
When backtrace,:
1. gdb get frame of level 0 is a normal frame.
2. gdb tried to get level 1, PC of level 1 is gotten from LR, which is equal
to the current PC。 inline_frame_sniffer get "this_pc" is equal (PC - 1) (gotten
from "get_frame_address_in_block", this_frame's type is inline and next_frame
is normal)
3. in inline_frame_sniffer: gdb get block_for_pc(PC -1), it gets a inline
function at (PC-4) actually.
4. gdb recognizes level 1 as a inline frame
when computing frame_id of level 1:
5. in inline_frame_this_id: *this_id =
get_frame_id(get_prev_frame_always(this_frame));,
get_prev_frame_always(this_frame) returns NULL, because it gets a frame which
is equal to level 0.
6. get_frame_id returns null_frame_id, then gdb_assert(frame_id_p(this_id))
failed.
------------------------------------------------------------------------
level 0 is a normal frame
level 1 is a inline frame
level 2 is a normal frame which is equal to level 0
it is a exception situation here actually.
-------------------------------------------------------------------------
In this case, i think gdb should stop to unwinding prev frame when analysing
level 1 (if inline_frame_this_id has a gdb_assert there ) rather than asserted
failed。
--------------------------------------------------------------------------
I tried to add some checking at inline_frame_sniffer before "return 1" like:
if (frame_relative_leve (this_frame) == 1)
{
//get_prev_frame_real is writton by me
struct frame_info *prev_frame = get_prev_frame_real (this_frame);
next_frame = get_next_frame (this_frame);
if (prev_frame
&& (this_pc % 2)
&& (get_frame_pc (next_frame) == get_frame_pc (prev_frame))
&& (get_frame_type (prev_frame) == NORMAL_FRAME))
return 0;
}
// get_prev_frame_real
struct frame_info *
get_prev_frame_real (struct frame_info *this_frame)
{
struct frame_info *prev_frame;
struct cleanup *prev_frame_cleanup;
prev_frame = get_prev_frame_raw (this_frame);
if (prev_frame == NULL)
return NULL;
prev_frame_cleanup = make_cleanup (remove_prev_frame. this_frame);
if (prev_frame->unwind == NULL)
frame_unwind_find_by_frame (prev_frame, &prev_frame->prologue_cache);
discard_cleanups (prev_frame_cleanup);
return prev_frame;
}
//--------
it really can solve this case, but it is not a good solution,
Bug ID: 23287
Summary: function: inline_frame_this_id
assert(frame_id_p(*this_id)) occured
Product: gdb
Version: 8.1
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: backtrace
Assignee: unassigned at sourceware dot org
Reporter: lijiang1489 at 163 dot com
Target Milestone: ---
Hi, all
There is a case that a program_A is running on a physical board. When
program_A running to exit, it left a situation:
Insn at PC is : br itself (like a while (1))
Value of LR is : LR == PC (equal)
The next time, i tried to start gdb with "gdb program_B" and connect the target
board with command"tar remote xxx". When i tried to backtrace here, gdb assert
failed at "inline_frame_this_id: assert(frame_id_p(*this_id)".
why? I have found out that:
1. PC at program_B is a normal PC, it has a normal frame
2. (PC-4) is a inline function
When backtrace,:
1. gdb get frame of level 0 is a normal frame.
2. gdb tried to get level 1, PC of level 1 is gotten from LR, which is equal
to the current PC。 inline_frame_sniffer get "this_pc" is equal (PC - 1) (gotten
from "get_frame_address_in_block", this_frame's type is inline and next_frame
is normal)
3. in inline_frame_sniffer: gdb get block_for_pc(PC -1), it gets a inline
function at (PC-4) actually.
4. gdb recognizes level 1 as a inline frame
when computing frame_id of level 1:
5. in inline_frame_this_id: *this_id =
get_frame_id(get_prev_frame_always(this_frame));,
get_prev_frame_always(this_frame) returns NULL, because it gets a frame which
is equal to level 0.
6. get_frame_id returns null_frame_id, then gdb_assert(frame_id_p(this_id))
failed.
------------------------------------------------------------------------
level 0 is a normal frame
level 1 is a inline frame
level 2 is a normal frame which is equal to level 0
it is a exception situation here actually.
-------------------------------------------------------------------------
In this case, i think gdb should stop to unwinding prev frame when analysing
level 1 (if inline_frame_this_id has a gdb_assert there ) rather than asserted
failed。
--------------------------------------------------------------------------
I tried to add some checking at inline_frame_sniffer before "return 1" like:
if (frame_relative_leve (this_frame) == 1)
{
//get_prev_frame_real is writton by me
struct frame_info *prev_frame = get_prev_frame_real (this_frame);
next_frame = get_next_frame (this_frame);
if (prev_frame
&& (this_pc % 2)
&& (get_frame_pc (next_frame) == get_frame_pc (prev_frame))
&& (get_frame_type (prev_frame) == NORMAL_FRAME))
return 0;
}
// get_prev_frame_real
struct frame_info *
get_prev_frame_real (struct frame_info *this_frame)
{
struct frame_info *prev_frame;
struct cleanup *prev_frame_cleanup;
prev_frame = get_prev_frame_raw (this_frame);
if (prev_frame == NULL)
return NULL;
prev_frame_cleanup = make_cleanup (remove_prev_frame. this_frame);
if (prev_frame->unwind == NULL)
frame_unwind_find_by_frame (prev_frame, &prev_frame->prologue_cache);
discard_cleanups (prev_frame_cleanup);
return prev_frame;
}
//--------
it really can solve this case, but it is not a good solution,
--
You are receiving this mail because:
You are on the CC list for the bug.
You are receiving this mail because:
You are on the CC list for the bug.