aboutsummaryrefslogtreecommitdiff
path: root/gdb/dwarf2-frame.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/dwarf2-frame.c')
-rw-r--r--gdb/dwarf2-frame.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index a11aac9..6b81dff 100644
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -70,6 +70,9 @@ struct dwarf2_cie
/* True if a 'z' augmentation existed. */
unsigned char saw_z_augmentation;
+ /* True if an 'S' augmentation existed. */
+ unsigned char signal_frame;
+
struct dwarf2_cie *next;
};
@@ -1053,15 +1056,17 @@ dwarf2_frame_sniffer (struct frame_info *next_frame)
function. frame_pc_unwind(), for a no-return next function, can
end up returning something past the end of this function's body. */
CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame);
- if (!dwarf2_frame_find_fde (&block_addr))
+ struct dwarf2_fde *fde = dwarf2_frame_find_fde (&block_addr);
+ if (!fde)
return NULL;
/* On some targets, signal trampolines may have unwind information.
We need to recognize them so that we set the frame type
correctly. */
- if (dwarf2_frame_signal_frame_p (get_frame_arch (next_frame),
- next_frame))
+ if (fde->cie->signal_frame
+ || dwarf2_frame_signal_frame_p (get_frame_arch (next_frame),
+ next_frame))
return &dwarf2_signal_frame_unwind;
return &dwarf2_frame_unwind;
@@ -1521,6 +1526,10 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p)
depends on the target address size. */
cie->encoding = DW_EH_PE_absptr;
+ /* We'll determine the final value later, but we need to
+ initialize it conservatively. */
+ cie->signal_frame = 0;
+
/* Check version number. */
cie_version = read_1_byte (unit->abfd, buf);
if (cie_version != 1 && cie_version != 3)
@@ -1604,6 +1613,17 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p)
augmentation++;
}
+ /* "S" indicates a signal frame, such that the return
+ address must not be decremented to locate the call frame
+ info for the previous frame; it might even be the first
+ instruction of a function, so decrementing it would take
+ us to a different function. */
+ else if (*augmentation == 'S')
+ {
+ cie->signal_frame = 1;
+ augmentation++;
+ }
+
/* Otherwise we have an unknown augmentation.
Bail out unless we saw a 'z' prefix. */
else