From: Omar Sandoval <osan...@fb.com> Currently, __libdwfl_relocate_value doesn't distinguish between unloaded sections and sections loaded at address zero. This has a few consequences:
* relocate.c attempts relocation on unloaded sections when we don't have anything meaningful to relocate against. * derelocate.c matches addresses which happen to be less than the sh_size of an unloaded section, which can lead to confusing results from dwfl_module_relocate_address and __libdwfl_find_section_ndx. * find_elf_build_id returns an invalid non-zero address if the build ID note is not loaded. Let's return a new error, DWFL_E_NOT_LOADED, from __libdwfl_relocate_value if the section is not loaded that callers can handle appropriately. Signed-off-by: Omar Sandoval <osan...@fb.com> --- libdwfl/ChangeLog | 8 ++++++++ libdwfl/dwfl_module_getsym.c | 3 ++- libdwfl/libdwflP.h | 3 ++- libdwfl/relocate.c | 9 ++++++--- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index b6b427d4..b00ac8d6 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,11 @@ +2019-12-11 Omar Sandoval <osan...@fb.com> + + * libdwflP.h: Add new NOT_LOADED DWFL_ERROR. + * relocate.c (__libdwfl_relocate_value): Return + DWFL_E_NOT_LOADED if section is not loaded. + (relocate): Handle DWFL_E_NOT_LOADED. + * dwfl_module_getsym: Ignore DWFL_E_NOT_LOADED. + 2019-12-05 Mark Wielaard <m...@klomp.org> * linux-kernel-modules.c (find_kernel_elf): Also try to find diff --git a/libdwfl/dwfl_module_getsym.c b/libdwfl/dwfl_module_getsym.c index 8de9a3eb..d75588b2 100644 --- a/libdwfl/dwfl_module_getsym.c +++ b/libdwfl/dwfl_module_getsym.c @@ -165,7 +165,8 @@ __libdwfl_getsym (Dwfl_Module *mod, int ndx, GElf_Sym *sym, GElf_Addr *addr, Dwfl_Error result = __libdwfl_relocate_value (mod, elf, &symshstrndx, shndx, &st_value); - if (unlikely (result != DWFL_E_NOERROR)) + if (unlikely (result != DWFL_E_NOERROR + && result != DWFL_E_NOT_LOADED)) { __libdwfl_seterrno (result); return NULL; diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h index f631f946..6c10eddc 100644 --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h @@ -90,7 +90,8 @@ typedef struct Dwfl_Process Dwfl_Process; DWFL_ERROR (NO_ATTACH_STATE, N_("Dwfl has no attached state")) \ DWFL_ERROR (NO_UNWIND, N_("Unwinding not supported for this architecture")) \ DWFL_ERROR (INVALID_ARGUMENT, N_("Invalid argument")) \ - DWFL_ERROR (NO_CORE_FILE, N_("Not an ET_CORE ELF file")) + DWFL_ERROR (NO_CORE_FILE, N_("Not an ET_CORE ELF file")) \ + DWFL_ERROR (NOT_LOADED, N_("Not loaded")) #define DWFL_ERROR(name, text) DWFL_E_##name, typedef enum { DWFL_ERRORS DWFL_E_NUM } Dwfl_Error; diff --git a/libdwfl/relocate.c b/libdwfl/relocate.c index 88b5211d..5c9c08f3 100644 --- a/libdwfl/relocate.c +++ b/libdwfl/relocate.c @@ -73,9 +73,8 @@ __libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf, size_t *shstrndx, return CBFAIL; if (refshdr->sh_addr == (Dwarf_Addr) -1l) - /* The callback indicated this section wasn't really loaded but we - don't really care. */ - refshdr->sh_addr = 0; /* Make no adjustment below. */ + /* The callback indicated this section wasn't loaded. */ + return DWFL_E_NOT_LOADED; /* Update the in-core file's section header to show the final load address (or unloadedness). This serves as a cache, @@ -361,6 +360,8 @@ relocate (Dwfl_Module * const mod, GElf_Word shndx; Dwfl_Error error = relocate_getsym (mod, relocated, reloc_symtab, symndx, &sym, &shndx); + if (error == DWFL_E_NOT_LOADED) + return DWFL_E_NOERROR; if (unlikely (error != DWFL_E_NOERROR)) return error; @@ -368,6 +369,8 @@ relocate (Dwfl_Module * const mod, { /* Maybe we can figure it out anyway. */ error = resolve_symbol (mod, reloc_symtab, &sym, shndx); + if (error == DWFL_E_NOT_LOADED) + return DWFL_E_NOERROR; if (error != DWFL_E_NOERROR && !(error == DWFL_E_RELUNDEF && shndx == SHN_COMMON)) return error; -- 2.24.0