From 907fc2026807534a7c2772aac13ab8ab0b42aa92 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Fri, 16 May 2008 12:58:49 +0000 Subject: [PATCH] gdb/ 2008-05-15 Pedro Alves Ulrich Weigand * minsyms.c (lookup_minimal_symbol_by_pc_name): New function. * symtab.h (lookup_minimal_symbol_by_pc_name): Add prototype. * symtab.c (fixup_section): Remove prototype. Add ADDR parameter; use it instead of ginfo->value.address. Look up minimal symbol by address and name. Assume OBJFILE is non-NULL. (fixup_symbol_section): Ensure we always have an objfile to look into. Extract and pass to fixup_section the symbol's address that will match the minimal symbol's address. (fixup_psymbol_section): Likewise. (find_pc_sect_psymtab): Fall back to non-addrmap case when debugging overlays and the addrmap returned the wrong section. * dwarf2read.c (var_decode_location): Set SYMBOL_CLASS before calling fixup_symbol_section. gdb/testsuite/ 2008-05-15 Pedro Alves * gdb.base/fixsection.exp: New file. * gdb.base/fixsection0.c: New file. * gdb.base/fixsection1.c: New file. --- gdb/ChangeLog | 20 +++++++ gdb/dwarf2read.c | 2 +- gdb/minsyms.c | 35 +++++++++++ gdb/symtab.c | 84 ++++++++++++++++++++++----- gdb/symtab.h | 3 + gdb/testsuite/ChangeLog | 6 ++ gdb/testsuite/gdb.base/fixsection.c | 35 +++++++++++ gdb/testsuite/gdb.base/fixsection.exp | 71 ++++++++++++++++++++++ gdb/testsuite/gdb.base/fixsectshr.c | 10 ++++ 9 files changed, 252 insertions(+), 14 deletions(-) create mode 100644 gdb/testsuite/gdb.base/fixsection.c create mode 100644 gdb/testsuite/gdb.base/fixsection.exp create mode 100644 gdb/testsuite/gdb.base/fixsectshr.c diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 8d3aea66f18..3168fc30fa6 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,23 @@ +2008-05-16 Pedro Alves + Ulrich Weigand + + * minsyms.c (lookup_minimal_symbol_by_pc_name): New function. + * symtab.h (lookup_minimal_symbol_by_pc_name): Add prototype. + + * symtab.c (fixup_section): Remove prototype. Add ADDR parameter; + use it instead of ginfo->value.address. Look up minimal symbol by + address and name. Assume OBJFILE is non-NULL. + (fixup_symbol_section): Ensure we always have an objfile to look + into. Extract and pass to fixup_section the symbol's address that + will match the minimal symbol's address. + (fixup_psymbol_section): Likewise. + + (find_pc_sect_psymtab): Fall back to non-addrmap case when debugging + overlays and the addrmap returned the wrong section. + + * dwarf2read.c (var_decode_location): Set SYMBOL_CLASS before + calling fixup_symbol_section. + 2008-05-16 Ulrich Weigand * minsyms.c: Include "target.h". diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 4f1cb1e3296..67b734f1447 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -7323,10 +7323,10 @@ var_decode_location (struct attribute *attr, struct symbol *sym, SYMBOL_VALUE_ADDRESS (sym) = read_address (objfile->obfd, DW_BLOCK (attr)->data + 1, cu, &dummy); + SYMBOL_CLASS (sym) = LOC_STATIC; fixup_symbol_section (sym, objfile); SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets, SYMBOL_SECTION (sym)); - SYMBOL_CLASS (sym) = LOC_STATIC; return; } diff --git a/gdb/minsyms.c b/gdb/minsyms.c index ca9ba9a6715..59febf295e9 100644 --- a/gdb/minsyms.c +++ b/gdb/minsyms.c @@ -331,6 +331,41 @@ lookup_minimal_symbol_text (const char *name, struct objfile *objf) return NULL; } +/* Look through all the current minimal symbol tables and find the + first minimal symbol that matches NAME and PC. If OBJF is non-NULL, + limit the search to that objfile. Returns a pointer to the minimal + symbol that matches, or NULL if no match is found. */ + +struct minimal_symbol * +lookup_minimal_symbol_by_pc_name (CORE_ADDR pc, const char *name, + struct objfile *objf) +{ + struct objfile *objfile; + struct minimal_symbol *msymbol; + + unsigned int hash = msymbol_hash (name) % MINIMAL_SYMBOL_HASH_SIZE; + + for (objfile = object_files; + objfile != NULL; + objfile = objfile->next) + { + if (objf == NULL || objf == objfile + || objf->separate_debug_objfile == objfile) + { + for (msymbol = objfile->msymbol_hash[hash]; + msymbol != NULL; + msymbol = msymbol->hash_next) + { + if (SYMBOL_VALUE_ADDRESS (msymbol) == pc + && strcmp (SYMBOL_LINKAGE_NAME (msymbol), name) == 0) + return msymbol; + } + } + } + + return NULL; +} + /* Look through all the current minimal symbol tables and find the first minimal symbol that matches NAME and is a solib trampoline. If OBJF is non-NULL, limit the search to that objfile. Returns a diff --git a/gdb/symtab.c b/gdb/symtab.c index 3d4389ebf17..33efe129239 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -110,8 +110,6 @@ struct symbol *lookup_symbol_aux_psymtabs (int block_index, const domain_enum domain, struct symtab **symtab); -static void fixup_section (struct general_symbol_info *, struct objfile *); - static int file_matches (char *, char **, int); static void print_symbol_info (domain_enum, @@ -878,6 +876,23 @@ find_pc_sect_psymtab (CORE_ADDR pc, asection *section) pst = addrmap_find (objfile->psymtabs_addrmap, pc); if (pst != NULL) { + /* FIXME: addrmaps currently do not handle overlayed sections, + so fall back to the non-addrmap case if we're debugging + overlays and the addrmap returned the wrong section. */ + if (overlay_debugging && msymbol && section) + { + struct partial_symbol *p; + /* NOTE: This assumes that every psymbol has a + corresponding msymbol, which is not necessarily + true; the debug info might be much richer than the + object's symbol table. */ + p = find_pc_sect_psymbol (pst, pc, section); + if (!p + || SYMBOL_VALUE_ADDRESS (p) + != SYMBOL_VALUE_ADDRESS (msymbol)) + continue; + } + /* We do not try to call FIND_PC_SECT_PSYMTAB_CLOSER as PSYMTABS_ADDRMAP we used has already the best 1-byte granularity and FIND_PC_SECT_PSYMTAB_CLOSER may mislead us into @@ -1010,23 +1025,23 @@ find_pc_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc) out of the minimal symbols and stash that in the debug symbol. */ static void -fixup_section (struct general_symbol_info *ginfo, struct objfile *objfile) +fixup_section (struct general_symbol_info *ginfo, + CORE_ADDR addr, struct objfile *objfile) { struct minimal_symbol *msym; - msym = lookup_minimal_symbol (ginfo->name, NULL, objfile); /* First, check whether a minimal symbol with the same name exists and points to the same address. The address check is required e.g. on PowerPC64, where the minimal symbol for a function will point to the function descriptor, while the debug symbol will point to the actual function code. */ - if (msym - && SYMBOL_VALUE_ADDRESS (msym) == ginfo->value.address) + msym = lookup_minimal_symbol_by_pc_name (addr, ginfo->name, objfile); + if (msym) { ginfo->bfd_section = SYMBOL_BFD_SECTION (msym); ginfo->section = SYMBOL_SECTION (msym); } - else if (objfile) + else { /* Static, function-local variables do appear in the linker (minimal) symbols, but are frequently given names that won't @@ -1064,11 +1079,7 @@ fixup_section (struct general_symbol_info *ginfo, struct objfile *objfile) this reason, we still attempt a lookup by name prior to doing a search of the section table. */ - CORE_ADDR addr; struct obj_section *s; - - addr = ginfo->value.address; - ALL_OBJFILE_OSECTIONS (objfile, s) { int idx = s->the_bfd_section->index; @@ -1087,13 +1098,42 @@ fixup_section (struct general_symbol_info *ginfo, struct objfile *objfile) struct symbol * fixup_symbol_section (struct symbol *sym, struct objfile *objfile) { + CORE_ADDR addr; + if (!sym) return NULL; if (SYMBOL_BFD_SECTION (sym)) return sym; - fixup_section (&sym->ginfo, objfile); + /* We either have an OBJFILE, or we can get at it from the sym's + symtab. Anything else is a bug. */ + gdb_assert (objfile || SYMBOL_SYMTAB (sym)); + + if (objfile == NULL) + objfile = SYMBOL_SYMTAB (sym)->objfile; + + /* We should have an objfile by now. */ + gdb_assert (objfile); + + switch (SYMBOL_CLASS (sym)) + { + case LOC_STATIC: + case LOC_LABEL: + case LOC_INDIRECT: + addr = SYMBOL_VALUE_ADDRESS (sym); + break; + case LOC_BLOCK: + addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)); + break; + + default: + /* Nothing else will be listed in the minsyms -- no use looking + it up. */ + return sym; + } + + fixup_section (&sym->ginfo, addr, objfile); return sym; } @@ -1101,13 +1141,31 @@ fixup_symbol_section (struct symbol *sym, struct objfile *objfile) struct partial_symbol * fixup_psymbol_section (struct partial_symbol *psym, struct objfile *objfile) { + CORE_ADDR addr; + if (!psym) return NULL; if (SYMBOL_BFD_SECTION (psym)) return psym; - fixup_section (&psym->ginfo, objfile); + gdb_assert (objfile); + + switch (SYMBOL_CLASS (psym)) + { + case LOC_STATIC: + case LOC_LABEL: + case LOC_INDIRECT: + case LOC_BLOCK: + addr = SYMBOL_VALUE_ADDRESS (psym); + break; + default: + /* Nothing else will be listed in the minsyms -- no use looking + it up. */ + return psym; + } + + fixup_section (&psym->ginfo, addr, objfile); return psym; } diff --git a/gdb/symtab.h b/gdb/symtab.h index ef8cade3a2e..37ce3f4d612 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -1183,6 +1183,9 @@ struct minimal_symbol *lookup_minimal_symbol_solib_trampoline (const char *, struct objfile *); +extern struct minimal_symbol *lookup_minimal_symbol_by_pc_name + (CORE_ADDR, const char *, struct objfile *); + extern struct minimal_symbol *lookup_minimal_symbol_by_pc (CORE_ADDR); extern struct minimal_symbol *lookup_minimal_symbol_by_pc_section (CORE_ADDR, diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 682cf008f4a..0158acc1e0d 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2008-05-16 Pedro Alves + + * gdb.base/fixsection.exp: New file. + * gdb.base/fixsection0.c: New file. + * gdb.base/fixsection1.c: New file. + 2008-05-16 Ulrich Weigand * gdb.base/annota1.exp: Accept printf@... in place of printf. diff --git a/gdb/testsuite/gdb.base/fixsection.c b/gdb/testsuite/gdb.base/fixsection.c new file mode 100644 index 00000000000..ed0c77b6b68 --- /dev/null +++ b/gdb/testsuite/gdb.base/fixsection.c @@ -0,0 +1,35 @@ +/* Copyright (C) 2008 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + This file was written by Pedro Alves (pedro@codesourcery.com). */ + +#include +#include + +extern FILE *force_static_fun (void); + +static void * +static_fun (void *arg) +{ + return NULL; +} + +int +main (int argc, char **argv) +{ + static_fun (NULL); + force_static_fun (); + return 0; +} diff --git a/gdb/testsuite/gdb.base/fixsection.exp b/gdb/testsuite/gdb.base/fixsection.exp new file mode 100644 index 00000000000..8954adcd05b --- /dev/null +++ b/gdb/testsuite/gdb.base/fixsection.exp @@ -0,0 +1,71 @@ +# Copyright (C) 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +if {[skip_shlib_tests]} { + return 0 +} + +set testfile "fixsection" +set srcfile ${srcdir}/${subdir}/${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +set libfile "fixsectshr" +set libsrc ${srcdir}/${subdir}/${libfile}.c +set lib_sl ${objdir}/${subdir}/${libfile}.sl + +set lib_opts [list debug nowarnings] +set exec_opts [list debug nowarnings shlib=$lib_sl] + +if [get_compiler_info ${binfile}] { + return -1 +} + +if { [gdb_compile_shlib $libsrc $lib_sl $lib_opts] != "" + || [gdb_compile $srcfile $binfile executable $exec_opts] != ""} { + untested "Could not compile either $libsrc or $srcfile." + return -1 +} + +# Start with a fresh gdb. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} +gdb_load_shlibs ${lib_sl} + +if ![runto_main] then { + fail "Can't run to main" + return 1; +} + +# +# set breakpoint at static function static_fun +# +gdb_test "break static_fun" \ + "Breakpoint.*at.* file .*${srcfile}, line.*" \ + "breakpoint at static_fun" + +# +# exit gdb +# +gdb_exit diff --git a/gdb/testsuite/gdb.base/fixsectshr.c b/gdb/testsuite/gdb.base/fixsectshr.c new file mode 100644 index 00000000000..8470826bdd1 --- /dev/null +++ b/gdb/testsuite/gdb.base/fixsectshr.c @@ -0,0 +1,10 @@ +#include +#include + +static FILE *static_fun = NULL; + +FILE * +force_static_fun (void) +{ + return static_fun; +} -- 2.39.5