diff options
author | Alexandre Oliva <aoliva@redhat.com> | 2006-05-28 05:56:20 +0000 |
---|---|---|
committer | Alexandre Oliva <aoliva@redhat.com> | 2006-05-28 05:56:20 +0000 |
commit | 56c987f6063485c5c588dc27dbf1b3ddce3b0200 (patch) | |
tree | d91dc1832710ea2a64c60ec74b79acc266fa7def /gdb/dwarf2-frame.c | |
parent | f8fdc8504199983f6ab2c203cfbb45094040ef46 (diff) | |
download | gdb-56c987f6063485c5c588dc27dbf1b3ddce3b0200.zip gdb-56c987f6063485c5c588dc27dbf1b3ddce3b0200.tar.gz gdb-56c987f6063485c5c588dc27dbf1b3ddce3b0200.tar.bz2 |
* dwarf2-frame.c (struct dwarf2_cie): Add signal_frame field.
(dwarf2_frame_sniffer): Use it.
(decode_frame_entry_1): Set it according to augmentation "S".
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 |