This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch 2/2] Fix core files for re-prelink-ed files


Hi Mark,

this problem happens on RHEL-5 as it has no build-id.  On build-id system the
files get re-aligned correctly.

That is if you generate core file, re-prelink you system (which happens
nightly) and try to load the core file some shared libraries may no longer
load at their right place.

It happens even during "make check" for jankratochvil/unwindx86 which I am not
sure why now.  But the code was clearly wrong wrt prelink anyway.

Fortunately link_map->l_ld is absolute address so one can recompute new l_addr
according to it, ignoring former link_map->l_addr.

There is no test case, though.


Thanks,
Jan

libdwfl/
2013-11-01  Jan Kratochvil  <jan.kratochvil@redhat.com>

	Fix core files for re-prelink-ed files.
	* core-file.c (dynamic_vaddr_get): New function.
	(dwfl_core_file_report): New variable file_dynamic_vaddr.  Call
	dynamic_vaddr_get instead of using L_ADDR.
	* libdwflP.h (struct r_debug_info_module): Remove field l_addr.
	* link_map.c (report_r_debug): Do not initialize l_addr.

--- a/libdwfl/core-file.c
+++ b/libdwfl/core-file.c
@@ -397,6 +397,27 @@ clear_r_debug_info (struct r_debug_info *r_debug_info)
     }
 }
 
+static bool
+dynamic_vaddr_get (Elf *elf, GElf_Addr *vaddrp)
+{
+  size_t phnum;
+  if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
+    return false;
+  for (size_t i = 0; i < phnum; ++i)
+    {
+      GElf_Phdr phdr_mem;
+      GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
+      if (unlikely (phdr == NULL))
+	return false;
+      if (phdr->p_type == PT_DYNAMIC)
+	{
+	  *vaddrp = phdr->p_vaddr;
+	  return true;
+	}
+    }
+  return false;
+}
+
 int
 dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable)
 {
@@ -503,9 +524,13 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable)
     {
       if (module->elf == NULL)
 	continue;
+      GElf_Addr file_dynamic_vaddr;
+      if (! dynamic_vaddr_get (module->elf, &file_dynamic_vaddr))
+	continue;
       Dwfl_Module *mod;
       mod = __libdwfl_report_elf (dwfl, basename (module->name), module->name,
-				  module->fd, module->elf, module->l_addr,
+				  module->fd, module->elf,
+				  module->l_ld - file_dynamic_vaddr,
 				  true, true);
       if (mod == NULL)
 	continue;
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -467,7 +467,7 @@ struct r_debug_info_module
   /* FD is -1 iff ELF is NULL.  */
   int fd;
   Elf *elf;
-  GElf_Addr l_addr, l_ld;
+  GElf_Addr l_ld;
   /* START and END are both zero if not valid.  */
   GElf_Addr start, end;
   bool disk_file_has_build_id;
--- a/libdwfl/link_map.c
+++ b/libdwfl/link_map.c
@@ -369,7 +369,6 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
 	    return release_buffer (result);
 	  r_debug_info_module->fd = -1;
 	  r_debug_info_module->elf = NULL;
-	  r_debug_info_module->l_addr = l_addr;
 	  r_debug_info_module->l_ld = l_ld;
 	  r_debug_info_module->start = 0;
 	  r_debug_info_module->end = 0;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]