diff options
Diffstat (limited to 'gdb/dwarf2-frame.c')
-rw-r--r-- | gdb/dwarf2-frame.c | 26 |
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 |