[PATCH 1/4] libdwfl: return error from __libdwfl_relocate_value for unloaded sections

Omar Sandoval osandov@osandov.com
Thu Dec 12 01:30:00 GMT 2019


From: Omar Sandoval <osandov@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 <osandov@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  <osandov@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  <mark@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



More information about the Elfutils-devel mailing list