From 685083a6281c9e4c5ee3e4ce4e9423a6e88a1ef4 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Tue, 29 Jun 2010 17:17:39 -0700 Subject: [PATCH] Disable libdwfl relocation of debug sections --- libdw/ChangeLog | 3 ++ libdw/dwarf_lineaddr.c | 1 + libdw/libdwP.h | 1 + libdw/relocate.c | 3 +- libdwfl/ChangeLog | 16 +++++++ libdwfl/derelocate.c | 4 +- libdwfl/dwfl_lineinfo.c | 11 ++++- libdwfl/dwfl_module_getdwarf.c | 40 +++------------- libdwfl/dwfl_module_getelf.c | 6 +-- libdwfl/libdwflP.h | 11 ++--- libdwfl/relocate.c | 84 +++++++++++++++++----------------- tests/ChangeLog | 4 ++ tests/line2addr.c | 7 ++- 13 files changed, 98 insertions(+), 93 deletions(-) diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 023621f49..0d1854c6f 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,5 +1,8 @@ 2010-06-29 Roland McGrath + * dwarf_lineaddr.c: Add INTDEF. + * libdwP.h: Add INTDECL. + * dwarf_getsrc_relocatable.c: New file. * Makefile.am (libdw_a_SOURCES): Add it. * libdw.h: Declare it. diff --git a/libdw/dwarf_lineaddr.c b/libdw/dwarf_lineaddr.c index 1e0b32343..a1dc6ec68 100644 --- a/libdw/dwarf_lineaddr.c +++ b/libdw/dwarf_lineaddr.c @@ -77,3 +77,4 @@ dwarf_lineaddr (Dwarf_Line *line, Dwarf_Addr *addrp) return __libdw_relocate_shndx (line->cu->dbg, reloc[idx * 2 + 1], line->addr, addrp); } +INTDEF (dwarf_lineaddr) diff --git a/libdw/libdwP.h b/libdw/libdwP.h index 3633a28af..8d0cb6ad2 100644 --- a/libdw/libdwP.h +++ b/libdw/libdwP.h @@ -684,6 +684,7 @@ INTDECL (dwarf_hasattr) INTDECL (dwarf_haschildren) INTDECL (dwarf_haspc) INTDECL (dwarf_highpc) +INTDECL (dwarf_lineaddr) INTDECL (dwarf_lowpc) INTDECL (dwarf_nextcu) INTDECL (dwarf_next_unit) diff --git a/libdw/relocate.c b/libdw/relocate.c index 03671ce44..a7ee6b750 100644 --- a/libdw/relocate.c +++ b/libdw/relocate.c @@ -84,7 +84,8 @@ __libdw_relocate_begin (Dwarf *dbg, Elf_Scn *relscn[IDX_last], bool incomplete) GElf_Shdr *shdr; shdr = gelf_getshdr (scn, &shdr_mem); assert (shdr == &shdr_mem); - if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) + if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) + && shdr->sh_size != 0) for (size_t i = 0; i < IDX_last; ++i) if (relscn[i] == NULL && dbg->sectiondata[i] != NULL && (((Elf_Data_Scn * ) dbg->sectiondata[i])->s->index diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index e71e33d67..38cf62a08 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,19 @@ +2010-06-29 Roland McGrath + + * dwfl_lineinfo.c: Use dwarf_lineaddr. + + * relocate.c (relocate_section): Remove PARTIAL flag argument. + Reverse sense of DEBUGSCN flag: if set, skip if target section + is a debugging section. + (__libdwfl_relocate): Update caller. Remove flag argument. + (__libdwfl_relocate_section): Likewise. + * libdwflP.h: Update decls. + * dwfl_module_getelf.c: Update caller. + * dwfl_module_getdwarf.c: Likewise. + + * dwfl_module_getdwarf.c (load_dw): Don't relocate here. + Instead, hook into MOD->dw->relocate after dwarf_begin_elf. + 2010-06-21 Roland McGrath * open.c (__libdw_open_file): Close the fd when it's already mapped. diff --git a/libdwfl/derelocate.c b/libdwfl/derelocate.c index 56ba25af2..ee869e061 100644 --- a/libdwfl/derelocate.c +++ b/libdwfl/derelocate.c @@ -1,5 +1,5 @@ /* Recover relocatibility for addresses computed from debug information. - Copyright (C) 2005-2009 Red Hat, Inc. + Copyright (C) 2005-2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -396,7 +396,7 @@ dwfl_module_address_section (Dwfl_Module *mod, Dwarf_Addr *address, Elf_Scn *tscn = mod->reloc_info->refs[idx].scn; Elf_Scn *relocscn = mod->reloc_info->refs[idx].relocs; Dwfl_Error result = __libdwfl_relocate_section (mod, mod->main.elf, - relocscn, tscn, true); + relocscn, tscn); if (likely (result == DWFL_E_NOERROR)) mod->reloc_info->refs[idx].relocs = NULL; else diff --git a/libdwfl/dwfl_lineinfo.c b/libdwfl/dwfl_lineinfo.c index 920a2de9c..877648286 100644 --- a/libdwfl/dwfl_lineinfo.c +++ b/libdwfl/dwfl_lineinfo.c @@ -58,10 +58,17 @@ dwfl_lineinfo (Dwfl_Line *line, Dwarf_Addr *addr, int *linep, int *colp, return NULL; struct dwfl_cu *cu = dwfl_linecu (line); - const Dwarf_Line *info = &cu->die.cu->lines->info[line->idx]; + Dwarf_Line *info = &cu->die.cu->lines->info[line->idx]; if (addr != NULL) - *addr = info->addr + cu->mod->debug.bias; + { + if (INTUSE(dwarf_lineaddr) (info, addr)) + { + __libdwfl_seterrno (DWFL_E_LIBDW); + return NULL; + } + *addr += cu->mod->debug.bias; + } if (linep != NULL) *linep = info->line; if (colp != NULL) diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c index 41ed0730e..42d817a4e 100644 --- a/libdwfl/dwfl_module_getdwarf.c +++ b/libdwfl/dwfl_module_getdwarf.c @@ -669,38 +669,6 @@ __libdwfl_module_getebl (Dwfl_Module *mod) static Dwfl_Error load_dw (Dwfl_Module *mod, struct dwfl_file *debugfile) { - if (mod->e_type == ET_REL && !debugfile->relocated) - { - const Dwfl_Callbacks *const cb = mod->dwfl->callbacks; - - /* The debugging sections have to be relocated. */ - if (cb->section_address == NULL) - return DWFL_E_NOREL; - - Dwfl_Error error = __libdwfl_module_getebl (mod); - if (error != DWFL_E_NOERROR) - return error; - - find_symtab (mod); - Dwfl_Error result = mod->symerr; - if (result == DWFL_E_NOERROR) - result = __libdwfl_relocate (mod, debugfile->elf, true); - if (result != DWFL_E_NOERROR) - return result; - - /* Don't keep the file descriptors around. */ - if (mod->main.fd != -1 && elf_cntl (mod->main.elf, ELF_C_FDREAD) == 0) - { - close (mod->main.fd); - mod->main.fd = -1; - } - if (debugfile->fd != -1 && elf_cntl (debugfile->elf, ELF_C_FDREAD) == 0) - { - close (debugfile->fd); - debugfile->fd = -1; - } - } - mod->dw = INTUSE(dwarf_begin_elf) (debugfile->elf, DWARF_C_READ, NULL); if (mod->dw == NULL) { @@ -708,6 +676,12 @@ load_dw (Dwfl_Module *mod, struct dwfl_file *debugfile) return err == DWARF_E_NO_DWARF ? DWFL_E_NO_DWARF : DWFL_E (LIBDW, err); } + if (mod->dw->relocate != NULL) + { + assert (mod->e_type == ET_REL); + // mod->dw->relocate->dwflmod = mod; + } + /* Until we have iterated through all CU's, we might do lazy lookups. */ mod->lazycu = 1; @@ -779,7 +753,7 @@ dwfl_module_getdwarf (Dwfl_Module *mod, Dwarf_Addr *bias) { mod->debug.relocated = true; if (mod->debug.elf != mod->main.elf) - (void) __libdwfl_relocate (mod, mod->debug.elf, false); + (void) __libdwfl_relocate (mod, mod->debug.elf); } *bias = mod->debug.bias; diff --git a/libdwfl/dwfl_module_getelf.c b/libdwfl/dwfl_module_getelf.c index 6414a9d3b..aa66c2cd2 100644 --- a/libdwfl/dwfl_module_getelf.c +++ b/libdwfl/dwfl_module_getelf.c @@ -1,5 +1,5 @@ /* Find debugging and symbol information for a module in libdwfl. - Copyright (C) 2009 Red Hat, Inc. + Copyright (C) 2009-2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -66,14 +66,14 @@ dwfl_module_getelf (Dwfl_Module *mod, GElf_Addr *loadbase) mod->main.relocated = true; if (likely (__libdwfl_module_getebl (mod) == DWFL_E_NOERROR)) { - (void) __libdwfl_relocate (mod, mod->main.elf, false); + (void) __libdwfl_relocate (mod, mod->main.elf); if (mod->debug.elf == mod->main.elf) mod->debug.relocated = true; else if (mod->debug.elf != NULL && ! mod->debug.relocated) { mod->debug.relocated = true; - (void) __libdwfl_relocate (mod, mod->debug.elf, false); + (void) __libdwfl_relocate (mod, mod->debug.elf); } } } diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h index e4c7e7c82..504b0fb1c 100644 --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h @@ -251,21 +251,18 @@ extern void __libdwfl_module_free (Dwfl_Module *mod) internal_function; /* Find the main ELF file, update MOD->elferr and/or MOD->main.elf. */ extern void __libdwfl_getelf (Dwfl_Module *mod) internal_function; -/* Process relocations in debugging sections in an ET_REL file. +/* Process relocations in non-debugging sections in an ET_REL file. FILE must be opened with ELF_C_READ_MMAP_PRIVATE or ELF_C_READ, to make it possible to relocate the data in place (or ELF_C_RDWR or ELF_C_RDWR_MMAP if you intend to modify the Elf file on disk). After - this, dwarf_begin_elf on FILE will read the relocated data. - - When DEBUG is false, apply partial relocation to all sections. */ -extern Dwfl_Error __libdwfl_relocate (Dwfl_Module *mod, Elf *file, bool debug) + this, libelf calls on FILE will read the relocated data. */ +extern Dwfl_Error __libdwfl_relocate (Dwfl_Module *mod, Elf *file) internal_function; /* Process (simple) relocations in arbitrary section TSCN of an ET_REL file. RELOCSCN is SHT_REL or SHT_RELA and TSCN is its sh_info target section. */ extern Dwfl_Error __libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated, - Elf_Scn *relocscn, Elf_Scn *tscn, - bool partial) + Elf_Scn *relocscn, Elf_Scn *tscn); internal_function; /* Adjust *VALUE from section-relative to absolute. diff --git a/libdwfl/relocate.c b/libdwfl/relocate.c index cb64fa26e..0313749a1 100644 --- a/libdwfl/relocate.c +++ b/libdwfl/relocate.c @@ -298,7 +298,7 @@ static Dwfl_Error relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr, size_t shstrndx, struct reloc_symtab_cache *reloc_symtab, Elf_Scn *scn, GElf_Shdr *shdr, - Elf_Scn *tscn, bool debugscn, bool partial) + Elf_Scn *tscn, bool check_debugscn) { /* First, fetch the name of the section these relocations apply to. */ GElf_Shdr tshdr_mem; @@ -311,9 +311,9 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr, /* No contents to relocate. */ return DWFL_E_NOERROR; - if (debugscn && ! ebl_debugscn_p (mod->ebl, tname)) - /* This relocation section is not for a debugging section. - Nothing to do here. */ + if (check_debugscn && ebl_debugscn_p (mod->ebl, tname)) + /* This relocation section is for a debugging section. We don't touch + these here, since libdw proper already handles them lazily. */ return DWFL_E_NOERROR; /* Fetch the section data that needs the relocations applied. */ @@ -454,23 +454,22 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr, GELF_R_TYPE (r->r_info), GELF_R_SYM (r->r_info)); check_badreltype (); - if (partial) - switch (result) - { - case DWFL_E_NOERROR: - /* We applied the relocation. Elide it. */ - memset (&rel_mem, 0, sizeof rel_mem); - gelf_update_rel (reldata, relidx, &rel_mem); - ++complete; - break; - case DWFL_E_BADRELTYPE: - case DWFL_E_RELUNDEF: - /* We couldn't handle this relocation. Skip it. */ - result = DWFL_E_NOERROR; - break; - default: - break; - } + switch (result) + { + case DWFL_E_NOERROR: + /* We applied the relocation. Elide it. */ + memset (&rel_mem, 0, sizeof rel_mem); + gelf_update_rel (reldata, relidx, &rel_mem); + ++complete; + break; + case DWFL_E_BADRELTYPE: + case DWFL_E_RELUNDEF: + /* We couldn't handle this relocation. Skip it. */ + result = DWFL_E_NOERROR; + break; + default: + break; + } } else for (size_t relidx = 0; !result && relidx < nrels; ++relidx) @@ -483,28 +482,27 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr, GELF_R_TYPE (r->r_info), GELF_R_SYM (r->r_info)); check_badreltype (); - if (partial) - switch (result) - { - case DWFL_E_NOERROR: - /* We applied the relocation. Elide it. */ - memset (&rela_mem, 0, sizeof rela_mem); - gelf_update_rela (reldata, relidx, &rela_mem); - ++complete; - break; - case DWFL_E_BADRELTYPE: - case DWFL_E_RELUNDEF: - /* We couldn't handle this relocation. Skip it. */ - result = DWFL_E_NOERROR; - break; - default: - break; - } + switch (result) + { + case DWFL_E_NOERROR: + /* We applied the relocation. Elide it. */ + memset (&rela_mem, 0, sizeof rela_mem); + gelf_update_rela (reldata, relidx, &rela_mem); + ++complete; + break; + case DWFL_E_BADRELTYPE: + case DWFL_E_RELUNDEF: + /* We couldn't handle this relocation. Skip it. */ + result = DWFL_E_NOERROR; + break; + default: + break; + } } if (likely (result == DWFL_E_NOERROR)) { - if (!partial || complete == nrels) + if (complete == nrels) /* Mark this relocation section as being empty now that we have done its work. This affects unstrip -R, so e.g. it emits an empty .rela.debug_info along with a .debug_info that has @@ -553,7 +551,7 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr, Dwfl_Error internal_function -__libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile, bool debug) +__libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile) { assert (mod->e_type == ET_REL); @@ -589,7 +587,7 @@ __libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile, bool debug) else result = relocate_section (mod, debugfile, ehdr, d_shstrndx, &reloc_symtab, scn, shdr, tscn, - debug, !debug); + true); } } @@ -599,7 +597,7 @@ __libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile, bool debug) Dwfl_Error internal_function __libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated, - Elf_Scn *relocscn, Elf_Scn *tscn, bool partial) + Elf_Scn *relocscn, Elf_Scn *tscn) { GElf_Ehdr ehdr_mem; GElf_Shdr shdr_mem; @@ -615,5 +613,5 @@ __libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated, gelf_getehdr (relocated, &ehdr_mem), shstrndx, &reloc_symtab, relocscn, gelf_getshdr (relocscn, &shdr_mem), - tscn, false, partial)); + tscn, false)); } diff --git a/tests/ChangeLog b/tests/ChangeLog index 0176fb495..91ae9912a 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,7 @@ +2010-06-29 Roland McGrath + + * line2addr.c (handle_module): Diagnose dwfl_lineinfo failure. + 2010-06-04 Roland McGrath * run-unstrip-test.sh: Also test modifying the file in place. diff --git a/tests/line2addr.c b/tests/line2addr.c index 5630da3c4..aef129561 100644 --- a/tests/line2addr.c +++ b/tests/line2addr.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2005 Red Hat, Inc. +/* Test program translating source lines into addresses. + Copyright (C) 2005-2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -92,7 +93,9 @@ handle_module (Dwfl_Module *mod __attribute__ ((unused)), int line = a->line, col = 0; const char *file = dwfl_lineinfo (lines[inner], &addr, &line, &col, NULL, NULL); - if (file != NULL) + if (file == NULL) + printf ("%s => dwfl_lineinfo: %s\n", a->arg, dwfl_errmsg (-1)); + else { printf ("%s -> ", a->arg); print_address (mod, addr); -- 2.47.2