[gdb] Fix gdb.dwarf2/amd64-entry-value-param.exp with -fPIE/-pie When running gdb.dwarf2/amd64-entry-value-param.exp with target board unix/-fPIE/-pie, we get: ... FAIL: gdb.arch/amd64-entry-value-param.exp: call 1: p y ... The problem is that read_call_site_scope attempts to put relocated addresses in cu->call_site_htab, for both the pc field: ... baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); ... pc = attr_value_as_address (attr) + baseaddr; pc = gdbarch_adjust_dwarf2_addr (gdbarch, pc); ... call_site->pc = pc; ... and the target field: ... lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr); SET_FIELD_PHYSADDR (call_site->target, lowpc); ... but fails to do so because it is called before objfile_relocate, making baseaddr 0. Fix this by eliminating baseaddr from read_call_site_scope, and handling the relocation offset at the use sites in call_site_for_pc and call_site_to_target_addr. Tested on x86_64-linux, both with and without -fPIE/-pie. gdb/ChangeLog: 2019-08-09 Tom de Vries PR gdb/24892 * objfiles.c (relocate_text_addr): New function. * objfiles.h (relocate_text_addr): Declare. * block.c (call_site_for_pc): Substract relocation offset before finding pc in COMPUNIT_CALL_SITE_HTAB. * dwarf2loc.c (call_site_to_target_addr): Add relocation offset to FIELD_STATIC_PHYSADDR (call_site->target). * dwarf2read.c (read_call_site_scope): Eliminate baseaddr. --- gdb/block.c | 12 +++++++++++- gdb/dwarf2loc.c | 7 ++++++- gdb/dwarf2read.c | 7 ++----- gdb/objfiles.c | 11 +++++++++++ gdb/objfiles.h | 5 +++++ 5 files changed, 35 insertions(+), 7 deletions(-) diff --git a/gdb/block.c b/gdb/block.c index 5c6faa8504..3113980259 100644 --- a/gdb/block.c +++ b/gdb/block.c @@ -226,7 +226,17 @@ call_site_for_pc (struct gdbarch *gdbarch, CORE_ADDR pc) cust = find_pc_compunit_symtab (pc - 1); if (cust != NULL && COMPUNIT_CALL_SITE_HTAB (cust) != NULL) - slot = htab_find_slot (COMPUNIT_CALL_SITE_HTAB (cust), &pc, NO_INSERT); + { + struct obj_section *sec; + sec = find_pc_section (pc); + if (sec != NULL) + { + CORE_ADDR pc_unrelocated = pc - obj_section_offset (sec); + slot = htab_find_slot (COMPUNIT_CALL_SITE_HTAB (cust), + &pc_unrelocated, NO_INSERT); + } + } + if (slot == NULL) { diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 63643cb45d..de8573f6d9 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -855,7 +855,12 @@ call_site_to_target_addr (struct gdbarch *call_site_gdbarch, } case FIELD_LOC_KIND_PHYSADDR: - return FIELD_STATIC_PHYSADDR (call_site->target); + { + CORE_ADDR addr = FIELD_STATIC_PHYSADDR (call_site->target); + struct objfile *objfile + = call_site->per_cu->dwarf2_per_objfile->objfile; + return relocate_text_addr (addr, objfile); + } default: internal_error (__FILE__, __LINE__, _("invalid call site target kind")); diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index de9755f6ce..6a8218dc61 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -13868,7 +13868,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) return; } pc = attr_value_as_address (attr) + baseaddr; - pc = gdbarch_adjust_dwarf2_addr (gdbarch, pc); + pc = gdbarch_adjust_dwarf2_addr (gdbarch, pc) - baseaddr; if (cu->call_site_htab == NULL) cu->call_site_htab = htab_create_alloc_ex (16, core_addr_hash, core_addr_eq, @@ -14019,10 +14019,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) "low pc, for referencing DIE %s [in module %s]"), sect_offset_str (die->sect_off), objfile_name (objfile)); else - { - lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr); - SET_FIELD_PHYSADDR (call_site->target, lowpc); - } + SET_FIELD_PHYSADDR (call_site->target, lowpc); } } else diff --git a/gdb/objfiles.c b/gdb/objfiles.c index 7cbcbbd01b..18d9540849 100644 --- a/gdb/objfiles.c +++ b/gdb/objfiles.c @@ -1493,3 +1493,14 @@ objfile_flavour_name (struct objfile *objfile) return bfd_flavour_name (bfd_get_flavour (objfile->obfd)); return NULL; } + +/* See objfiles.h. */ + +CORE_ADDR +relocate_text_addr (CORE_ADDR addr, struct objfile *objfile) +{ + CORE_ADDR baseaddr + = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + struct gdbarch *gdbarch = get_objfile_arch (objfile); + return gdbarch_adjust_dwarf2_addr (gdbarch, addr + baseaddr); +} diff --git a/gdb/objfiles.h b/gdb/objfiles.h index 239aba2c2a..a86bf3b5f9 100644 --- a/gdb/objfiles.h +++ b/gdb/objfiles.h @@ -789,4 +789,9 @@ extern void objfile_register_static_link extern const struct dynamic_prop *objfile_lookup_static_link (struct objfile *objfile, const struct block *block); +/* Given an unrelocated address ADDR belonging to the text section of OBJFILE, + return the relocated address. */ + +extern CORE_ADDR relocate_text_addr (CORE_ADDR addr, struct objfile *objfile); + #endif /* !defined (OBJFILES_H) */