X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fdwarf2-frame.c;h=baa47c9438980c36c665fc899fc89fd44bf2b06e;hb=8cd0e5e93145699736a370b271ff03f3f41670b0;hp=3c8f0a101840573549b0f3605b167d7c47328ff0;hpb=85102364b2d1845fe9ae7d70096671a3ea4bccf3;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c index 3c8f0a1018..baa47c9438 100644 --- a/gdb/dwarf2-frame.c +++ b/gdb/dwarf2-frame.c @@ -1,6 +1,6 @@ /* Frame unwinder for frames with DWARF Call Frame Information. - Copyright (C) 2003-2019 Free Software Foundation, Inc. + Copyright (C) 2003-2020 Free Software Foundation, Inc. Contributed by Mark Kettenis. @@ -39,10 +39,14 @@ #include "ax.h" #include "dwarf2loc.h" #include "dwarf2-frame-tailcall.h" +#include "gdbsupport/gdb_binary_search.h" #if GDB_SELF_TEST #include "gdbsupport/selftest.h" #include "selftest-arch.h" #endif +#include + +#include struct comp_unit; @@ -98,11 +102,9 @@ struct dwarf2_cie unsigned char segment_size; }; -struct dwarf2_cie_table -{ - int num_entries; - struct dwarf2_cie **entries; -}; +/* The CIE table is used to find CIEs during parsing, but then + discarded. It maps from the CIE's offset to the CIE. */ +typedef std::unordered_map dwarf2_cie_table; /* Frame Description Entry (FDE). */ @@ -382,8 +384,7 @@ execute_cfa_program (struct dwarf2_fde *fde, const gdb_byte *insn_ptr, fde->cie->ptr_size, insn_ptr, &bytes_read, fde->initial_location); /* Apply the objfile offset for relocatable objects. */ - fs->pc += ANOFFSET (fde->cie->unit->objfile->section_offsets, - SECT_OFF_TEXT (fde->cie->unit->objfile)); + fs->pc += fde->cie->unit->objfile->section_offsets[SECT_OFF_TEXT (fde->cie->unit->objfile)]; insn_ptr += bytes_read; break; @@ -1342,7 +1343,7 @@ dwarf2_frame_sniffer (const struct frame_unwind *self, if (!dwarf2_frame_unwinders_enabled_p) return 0; - /* Grab an address that is guarenteed to reside somewhere within the + /* Grab an address that is guaranteed to reside somewhere within the function. get_frame_pc(), with a no-return next function, can end up returning something past the end of this function's body. If the frame we're sniffing for is a signal frame whose start @@ -1641,64 +1642,22 @@ read_encoded_value (struct comp_unit *unit, gdb_byte encoding, } -static int -bsearch_cie_cmp (const void *key, const void *element) -{ - ULONGEST cie_pointer = *(ULONGEST *) key; - struct dwarf2_cie *cie = *(struct dwarf2_cie **) element; - - if (cie_pointer == cie->cie_pointer) - return 0; - - return (cie_pointer < cie->cie_pointer) ? -1 : 1; -} - /* Find CIE with the given CIE_POINTER in CIE_TABLE. */ static struct dwarf2_cie * -find_cie (struct dwarf2_cie_table *cie_table, ULONGEST cie_pointer) +find_cie (const dwarf2_cie_table &cie_table, ULONGEST cie_pointer) { - struct dwarf2_cie **p_cie; - - /* The C standard (ISO/IEC 9899:TC2) requires the BASE argument to - bsearch be non-NULL. */ - if (cie_table->entries == NULL) - { - gdb_assert (cie_table->num_entries == 0); - return NULL; - } - - p_cie = ((struct dwarf2_cie **) - bsearch (&cie_pointer, cie_table->entries, cie_table->num_entries, - sizeof (cie_table->entries[0]), bsearch_cie_cmp)); - if (p_cie != NULL) - return *p_cie; + auto iter = cie_table.find (cie_pointer); + if (iter != cie_table.end ()) + return iter->second; return NULL; } -/* Add a pointer to new CIE to the CIE_TABLE, allocating space for it. */ -static void -add_cie (struct dwarf2_cie_table *cie_table, struct dwarf2_cie *cie) -{ - const int n = cie_table->num_entries; - - gdb_assert (n < 1 - || cie_table->entries[n - 1]->cie_pointer < cie->cie_pointer); - - cie_table->entries - = XRESIZEVEC (struct dwarf2_cie *, cie_table->entries, n + 1); - cie_table->entries[n] = cie; - cie_table->num_entries = n + 1; -} - -static int -bsearch_fde_cmp (const void *key, const void *element) +static inline int +bsearch_fde_cmp (const dwarf2_fde *fde, CORE_ADDR seek_pc) { - CORE_ADDR seek_pc = *(CORE_ADDR *) key; - struct dwarf2_fde *fde = *(struct dwarf2_fde **) element; - - if (seek_pc < fde->initial_location) + if (fde->initial_location + fde->address_range <= seek_pc) return -1; - if (seek_pc < fde->initial_location + fde->address_range) + if (fde->initial_location <= seek_pc) return 0; return 1; } @@ -1712,7 +1671,6 @@ dwarf2_frame_find_fde (CORE_ADDR *pc, CORE_ADDR *out_offset) for (objfile *objfile : current_program_space->objfiles ()) { struct dwarf2_fde_table *fde_table; - struct dwarf2_fde **p_fde; CORE_ADDR offset; CORE_ADDR seek_pc; @@ -1727,23 +1685,22 @@ dwarf2_frame_find_fde (CORE_ADDR *pc, CORE_ADDR *out_offset) if (fde_table->num_entries == 0) continue; - gdb_assert (objfile->section_offsets); - offset = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + gdb_assert (!objfile->section_offsets.empty ()); + offset = objfile->section_offsets[SECT_OFF_TEXT (objfile)]; gdb_assert (fde_table->num_entries > 0); if (*pc < offset + fde_table->entries[0]->initial_location) continue; seek_pc = *pc - offset; - p_fde = ((struct dwarf2_fde **) - bsearch (&seek_pc, fde_table->entries, fde_table->num_entries, - sizeof (fde_table->entries[0]), bsearch_fde_cmp)); - if (p_fde != NULL) + auto end = fde_table->entries + fde_table->num_entries; + auto it = gdb::binary_search (fde_table->entries, end, seek_pc, bsearch_fde_cmp); + if (it != end) { - *pc = (*p_fde)->initial_location + offset; + *pc = (*it)->initial_location + offset; if (out_offset) *out_offset = offset; - return *p_fde; + return *it; } } return NULL; @@ -1778,7 +1735,7 @@ enum eh_frame_type static const gdb_byte *decode_frame_entry (struct comp_unit *unit, const gdb_byte *start, int eh_frame_p, - struct dwarf2_cie_table *cie_table, + dwarf2_cie_table &cie_table, struct dwarf2_fde_table *fde_table, enum eh_frame_type entry_type); @@ -1788,7 +1745,7 @@ static const gdb_byte *decode_frame_entry (struct comp_unit *unit, static const gdb_byte * decode_frame_entry_1 (struct comp_unit *unit, const gdb_byte *start, int eh_frame_p, - struct dwarf2_cie_table *cie_table, + dwarf2_cie_table &cie_table, struct dwarf2_fde_table *fde_table, enum eh_frame_type entry_type) { @@ -2007,7 +1964,7 @@ decode_frame_entry_1 (struct comp_unit *unit, const gdb_byte *start, cie->end = end; cie->unit = unit; - add_cie (cie_table, cie); + cie_table[cie->cie_pointer] = cie; } else { @@ -2090,7 +2047,7 @@ decode_frame_entry_1 (struct comp_unit *unit, const gdb_byte *start, static const gdb_byte * decode_frame_entry (struct comp_unit *unit, const gdb_byte *start, int eh_frame_p, - struct dwarf2_cie_table *cie_table, + dwarf2_cie_table &cie_table, struct dwarf2_fde_table *fde_table, enum eh_frame_type entry_type) { @@ -2181,25 +2138,22 @@ Corrupt data in %s:%s; align 8 workaround apparently succeeded"), return ret; } -static int -qsort_fde_cmp (const void *a, const void *b) +static bool +fde_is_less_than (const dwarf2_fde *aa, const dwarf2_fde *bb) { - struct dwarf2_fde *aa = *(struct dwarf2_fde **)a; - struct dwarf2_fde *bb = *(struct dwarf2_fde **)b; - if (aa->initial_location == bb->initial_location) { if (aa->address_range != bb->address_range && aa->eh_frame_p == 0 && bb->eh_frame_p == 0) /* Linker bug, e.g. gold/10400. Work around it by keeping stable sort order. */ - return (a < b) ? -1 : 1; + return aa < bb; else /* Put eh_frame entries after debug_frame ones. */ - return aa->eh_frame_p - bb->eh_frame_p; + return aa->eh_frame_p < bb->eh_frame_p; } - return (aa->initial_location < bb->initial_location) ? -1 : 1; + return aa->initial_location < bb->initial_location; } void @@ -2207,13 +2161,10 @@ dwarf2_build_frame_info (struct objfile *objfile) { struct comp_unit *unit; const gdb_byte *frame_ptr; - struct dwarf2_cie_table cie_table; + dwarf2_cie_table cie_table; struct dwarf2_fde_table fde_table; struct dwarf2_fde_table *fde_table2; - cie_table.num_entries = 0; - cie_table.entries = NULL; - fde_table.num_entries = 0; fde_table.entries = NULL; @@ -2255,7 +2206,7 @@ dwarf2_build_frame_info (struct objfile *objfile) frame_ptr = unit->dwarf_frame_buffer; while (frame_ptr < unit->dwarf_frame_buffer + unit->dwarf_frame_size) frame_ptr = decode_frame_entry (unit, frame_ptr, 1, - &cie_table, &fde_table, + cie_table, &fde_table, EH_CIE_OR_FDE_TYPE_ID); } @@ -2270,16 +2221,10 @@ dwarf2_build_frame_info (struct objfile *objfile) fde_table.entries = NULL; fde_table.num_entries = 0; } - /* The cie_table is discarded by the next if. */ + /* The cie_table is discarded below. */ } - if (cie_table.num_entries != 0) - { - /* Reinit cie_table: debug_frame has different CIEs. */ - xfree (cie_table.entries); - cie_table.num_entries = 0; - cie_table.entries = NULL; - } + cie_table.clear (); } } @@ -2296,7 +2241,7 @@ dwarf2_build_frame_info (struct objfile *objfile) frame_ptr = unit->dwarf_frame_buffer; while (frame_ptr < unit->dwarf_frame_buffer + unit->dwarf_frame_size) frame_ptr = decode_frame_entry (unit, frame_ptr, 0, - &cie_table, &fde_table, + cie_table, &fde_table, EH_CIE_OR_FDE_TYPE_ID); } catch (const gdb_exception_error &e) @@ -2320,18 +2265,9 @@ dwarf2_build_frame_info (struct objfile *objfile) } } fde_table.num_entries = num_old_fde_entries; - /* The cie_table is discarded by the next if. */ } } - /* Discard the cie_table, it is no longer needed. */ - if (cie_table.num_entries != 0) - { - xfree (cie_table.entries); - cie_table.entries = NULL; /* Paranoia. */ - cie_table.num_entries = 0; /* Paranoia. */ - } - /* Copy fde_table to obstack: it is needed at runtime. */ fde_table2 = XOBNEW (&objfile->objfile_obstack, struct dwarf2_fde_table); @@ -2347,8 +2283,8 @@ dwarf2_build_frame_info (struct objfile *objfile) int i; /* Prepare FDE table for lookups. */ - qsort (fde_table.entries, fde_table.num_entries, - sizeof (fde_table.entries[0]), qsort_fde_cmp); + std::sort (fde_table.entries, fde_table.entries + fde_table.num_entries, + fde_is_less_than); /* Check for leftovers from --gc-sections. The GNU linker sets the relevant symbols to zero, but doesn't zero the FDE *end*