Skip to content

Commit 1009d92

Browse files
committed
Find tailcall frames before inline frames
A customer reported a failure to unwind in a certain core dump. A lengthy investigation showed that the problem came from the interaction between the tailcall and inline frame sniffers. Normally, the regular DWARF unwinder may discover a chain of tail calls ending in the current frame. In this case, it sets a member on the dwarf2_frame_cache object, so that a subsequent call into the tailcall sniffer will create the tailcall frames. However, in this scenario, what happened is that the DWARF unwinder did find tailcall frames -- but then the PC of the first such frame was recognized and claimed by the inline frame sniffer. This then caused unwinding to go astray further up the stack. This patch fixes the problem by arranging for the tailcall sniffer to be called before the inline sniffer. This way, if a DWARF frame has tailcall information, the tailcalls will always be processed first. This is safe to do, because the tailcall sniffer can only claim a frame if the previous frame did in fact find this information. (So, for example, if no DWARF frame is ever found, then this sniffer will never trigger.) This patch also partially reverts: commit 1ec56e8 Author: Pedro Alves <palves@redhat.com> Date: Fri Nov 22 13:17:46 2013 +0000 Eliminate dwarf2_frame_cache recursion, don't unwind from the dwarf2 sniffer (move dwarf2_tailcall_sniffer_first elsewhere). That patch moved the call to dwarf2_tailcall_sniffer_first out of dwarf2_frame_cache, and into dwarf2_frame_prev_register. However, in this situation, this is too late -- by the time dwarf2_frame_prev_register is called, the frame in question is already recognized by the inline frame sniffer. Rather than fully revert that patch, though, this just arranges to call dwarf2_tailcall_sniffer_first from dwarf2_frame_cache -- which is called shortly after the DWARF frame sniffer succeeds, via compute_frame_id. I don't know how to write a test case for this. gdb/ChangeLog 2020-03-03 Tom Tromey <tromey@adacore.com> * dwarf2/frame.c (struct dwarf2_frame_cache) <checked_tailcall_bottom, entry_cfa_sp_offset, entry_cfa_sp_offset_p>: Remove members. (dwarf2_frame_cache): Call dwarf2_tailcall_sniffer_first. (dwarf2_frame_prev_register): Don't call dwarf2_tailcall_sniffer_first. (dwarf2_append_unwinders): Don't append tailcall unwinder. * frame-unwind.c (add_unwinder): New fuction. (frame_unwind_init): Use it. Add tailcall unwinder.
1 parent 89725b0 commit 1009d92

File tree

3 files changed

+47
-32
lines changed

3 files changed

+47
-32
lines changed

gdb/ChangeLog

+12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
2020-03-03 Tom Tromey <tromey@adacore.com>
2+
3+
* dwarf2/frame.c (struct dwarf2_frame_cache)
4+
<checked_tailcall_bottom, entry_cfa_sp_offset,
5+
entry_cfa_sp_offset_p>: Remove members.
6+
(dwarf2_frame_cache): Call dwarf2_tailcall_sniffer_first.
7+
(dwarf2_frame_prev_register): Don't call
8+
dwarf2_tailcall_sniffer_first.
9+
(dwarf2_append_unwinders): Don't append tailcall unwinder.
10+
* frame-unwind.c (add_unwinder): New fuction.
11+
(frame_unwind_init): Use it. Add tailcall unwinder.
12+
113
2020-03-03 Andrew Burgess <andrew.burgess@embecosm.com>
214
Alok Kumar Sharma <AlokKumar.Sharma@amd.com>
315

gdb/dwarf2/frame.c

+8-26
Original file line numberDiff line numberDiff line change
@@ -959,22 +959,12 @@ struct dwarf2_frame_cache
959959
/* The .text offset. */
960960
CORE_ADDR text_offset;
961961

962-
/* True if we already checked whether this frame is the bottom frame
963-
of a virtual tail call frame chain. */
964-
int checked_tailcall_bottom;
965-
966962
/* If not NULL then this frame is the bottom frame of a TAILCALL_FRAME
967963
sequence. If NULL then it is a normal case with no TAILCALL_FRAME
968964
involved. Non-bottom frames of a virtual tail call frames chain use
969965
dwarf2_tailcall_frame_unwind unwinder so this field does not apply for
970966
them. */
971967
void *tailcall_cache;
972-
973-
/* The number of bytes to subtract from TAILCALL_FRAME frames frame
974-
base to get the SP, to simulate the return address pushed on the
975-
stack. */
976-
LONGEST entry_cfa_sp_offset;
977-
int entry_cfa_sp_offset_p;
978968
};
979969

980970
static struct dwarf2_frame_cache *
@@ -1037,6 +1027,8 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache)
10371027
in an address that's within the range of FDE locations. This
10381028
is due to the possibility of the function occupying non-contiguous
10391029
ranges. */
1030+
LONGEST entry_cfa_sp_offset;
1031+
int entry_cfa_sp_offset_p = 0;
10401032
if (get_frame_func_if_available (this_frame, &entry_pc)
10411033
&& fde->initial_location <= entry_pc
10421034
&& entry_pc < fde->initial_location + fde->address_range)
@@ -1049,8 +1041,8 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache)
10491041
&& (dwarf_reg_to_regnum (gdbarch, fs.regs.cfa_reg)
10501042
== gdbarch_sp_regnum (gdbarch)))
10511043
{
1052-
cache->entry_cfa_sp_offset = fs.regs.cfa_offset;
1053-
cache->entry_cfa_sp_offset_p = 1;
1044+
entry_cfa_sp_offset = fs.regs.cfa_offset;
1045+
entry_cfa_sp_offset_p = 1;
10541046
}
10551047
}
10561048
else
@@ -1195,6 +1187,10 @@ incomplete CFI data; unspecified registers (e.g., %s) at %s"),
11951187
&& fs.regs.reg[fs.retaddr_column].how == DWARF2_FRAME_REG_UNDEFINED)
11961188
cache->undefined_retaddr = 1;
11971189

1190+
dwarf2_tailcall_sniffer_first (this_frame, &cache->tailcall_cache,
1191+
(entry_cfa_sp_offset_p
1192+
? &entry_cfa_sp_offset : NULL));
1193+
11981194
return cache;
11991195
}
12001196

@@ -1239,16 +1235,6 @@ dwarf2_frame_prev_register (struct frame_info *this_frame, void **this_cache,
12391235
CORE_ADDR addr;
12401236
int realnum;
12411237

1242-
/* Check whether THIS_FRAME is the bottom frame of a virtual tail
1243-
call frame chain. */
1244-
if (!cache->checked_tailcall_bottom)
1245-
{
1246-
cache->checked_tailcall_bottom = 1;
1247-
dwarf2_tailcall_sniffer_first (this_frame, &cache->tailcall_cache,
1248-
(cache->entry_cfa_sp_offset_p
1249-
? &cache->entry_cfa_sp_offset : NULL));
1250-
}
1251-
12521238
/* Non-bottom frames of a virtual tail call frames chain use
12531239
dwarf2_tailcall_frame_unwind unwinder so this code does not apply for
12541240
them. If dwarf2_tailcall_prev_register_first does not have specific value
@@ -1410,10 +1396,6 @@ static const struct frame_unwind dwarf2_signal_frame_unwind =
14101396
void
14111397
dwarf2_append_unwinders (struct gdbarch *gdbarch)
14121398
{
1413-
/* TAILCALL_FRAME must be first to find the record by
1414-
dwarf2_tailcall_sniffer_first. */
1415-
frame_unwind_append_unwinder (gdbarch, &dwarf2_tailcall_frame_unwind);
1416-
14171399
frame_unwind_append_unwinder (gdbarch, &dwarf2_frame_unwind);
14181400
frame_unwind_append_unwinder (gdbarch, &dwarf2_signal_frame_unwind);
14191401
}

gdb/frame-unwind.c

+27-6
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "gdb_obstack.h"
2828
#include "target.h"
2929
#include "gdbarch.h"
30+
#include "dwarf2/frame-tailcall.h"
3031

3132
static struct gdbarch_data *frame_unwind_data;
3233

@@ -43,6 +44,18 @@ struct frame_unwind_table
4344
struct frame_unwind_table_entry **osabi_head;
4445
};
4546

47+
/* A helper function to add an unwinder to a list. LINK says where to
48+
install the new unwinder. The new link is returned. */
49+
50+
static struct frame_unwind_table_entry **
51+
add_unwinder (struct obstack *obstack, const struct frame_unwind *unwinder,
52+
struct frame_unwind_table_entry **link)
53+
{
54+
*link = OBSTACK_ZALLOC (obstack, struct frame_unwind_table_entry);
55+
(*link)->unwinder = unwinder;
56+
return &(*link)->next;
57+
}
58+
4659
static void *
4760
frame_unwind_init (struct obstack *obstack)
4861
{
@@ -51,13 +64,21 @@ frame_unwind_init (struct obstack *obstack)
5164

5265
/* Start the table out with a few default sniffers. OSABI code
5366
can't override this. */
54-
table->list = OBSTACK_ZALLOC (obstack, struct frame_unwind_table_entry);
55-
table->list->unwinder = &dummy_frame_unwind;
56-
table->list->next = OBSTACK_ZALLOC (obstack,
57-
struct frame_unwind_table_entry);
58-
table->list->next->unwinder = &inline_frame_unwind;
67+
struct frame_unwind_table_entry **link = &table->list;
68+
69+
link = add_unwinder (obstack, &dummy_frame_unwind, link);
70+
/* The DWARF tailcall sniffer must come before the inline sniffer.
71+
Otherwise, we can end up in a situation where a DWARF frame finds
72+
tailcall information, but then the inline sniffer claims a frame
73+
before the tailcall sniffer, resulting in confusion. This is
74+
safe to do always because the tailcall sniffer can only ever be
75+
activated if the newer frame was created using the DWARF
76+
unwinder, and it also found tailcall information. */
77+
link = add_unwinder (obstack, &dwarf2_tailcall_frame_unwind, link);
78+
link = add_unwinder (obstack, &inline_frame_unwind, link);
79+
5980
/* The insertion point for OSABI sniffers. */
60-
table->osabi_head = &table->list->next->next;
81+
table->osabi_head = link;
6182
return table;
6283
}
6384

0 commit comments

Comments
 (0)