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 1/4] unwinder: New base address based dwfl_report_elf_baseaddr


Hi,

dependent on all the patches listed in:
	Pending patches ping
	https://lists.fedorahosted.org/pipermail/elfutils-devel/2012-November/002742.html

present in:
	jankratochvil/forunwind-baseaddr
but this branch is not suitable for merge as it is unclear in which form get
checked in the patches above.  The branch is usable only for "git checkout",
neither diff nor merge should be done on it.


Current dwfl_report_elf function has parameter "GElf_Addr base" but it means
bias, not the base address.  Some applications (such as Linux kernel perf)
cannot easily find out the bias but they know the base address.
I tried to implement it without this function but I could not.


Thanks,
Jan



libdwfl/
2012-11-13  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* dwfl_report_elf.c (__libdwfl_report_elf): Add parameter base_is_bias.
	Set BASE_IS_BIAS to true for ET_EXEC and ET_CORE.  Provide alternative
	setup of START and BIAS if !BASE_IS_BIAS.  Set END from BIAS, not BASE.
	(dwfl_report_elf): Rename to ...
	(__libdwfl_report_elf_open): ... here.  Add parameter base_is_bias,
	pass it to __libdwfl_report_elf.
	(dwfl_report_elf, dwfl_report_elf_baseaddr): New wrappers.
	* libdwfl.h (dwfl_report_elf_baseaddr): New declaration.
	* libdwflP.h (__libdwfl_report_elf): Add parameter base_is_bias.  
	* offline.c (process_elf): Pass true as base_is_bias to
	__libdwfl_report_elf.

diff --git a/libdwfl/dwfl_report_elf.c b/libdwfl/dwfl_report_elf.c
index d706170..7a6970e 100644
--- a/libdwfl/dwfl_report_elf.c
+++ b/libdwfl/dwfl_report_elf.c
@@ -41,7 +41,8 @@
 Dwfl_Module *
 internal_function
 __libdwfl_report_elf (Dwfl *dwfl, const char *name, const char *file_name,
-		      int fd, Elf *elf, GElf_Addr base, bool sanity)
+		      int fd, Elf *elf, GElf_Addr base, bool base_is_bias,
+		      bool sanity)
 {
   GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem);
   if (ehdr == NULL)
@@ -166,6 +167,7 @@ __libdwfl_report_elf (Dwfl *dwfl, const char *name, const char *file_name,
     case ET_CORE:
       /* An assigned base address is meaningless for these.  */
       base = 0;
+      base_is_bias = true;
 
     case ET_DYN:
     default:;
@@ -181,11 +183,19 @@ __libdwfl_report_elf (Dwfl *dwfl, const char *name, const char *file_name,
 	    {
 	      vaddr = ph->p_vaddr & -ph->p_align;
 	      address_sync = ph->p_vaddr + ph->p_memsz;
-	      start = base + vaddr;
 	      break;
 	    }
 	}
-      bias = base;
+      if (base_is_bias)
+	{
+	  start = base + vaddr;
+	  bias = base;
+	}
+      else
+	{
+	  start = base;
+	  bias = base - vaddr;
+	}
 
       for (size_t i = phnum; i-- > 0;)
 	{
@@ -195,7 +205,7 @@ __libdwfl_report_elf (Dwfl *dwfl, const char *name, const char *file_name,
 	  if (ph->p_type == PT_LOAD
 	      && ph->p_vaddr + ph->p_memsz > 0)
 	    {
-	      end = base + (ph->p_vaddr + ph->p_memsz);
+	      end = bias + (ph->p_vaddr + ph->p_memsz);
 	      break;
 	    }
 	}
@@ -246,8 +256,9 @@ __libdwfl_report_elf (Dwfl *dwfl, const char *name, const char *file_name,
 }
 
 Dwfl_Module *
-dwfl_report_elf (Dwfl *dwfl, const char *name,
-		 const char *file_name, int fd, GElf_Addr base)
+internal_function
+__libdwfl_report_elf_open (Dwfl *dwfl, const char *name, const char *file_name,
+			   int fd, GElf_Addr base, bool base_is_bias)
 {
   bool closefd = false;
   if (fd < 0)
@@ -270,7 +281,7 @@ dwfl_report_elf (Dwfl *dwfl, const char *name,
     }
 
   Dwfl_Module *mod = __libdwfl_report_elf (dwfl, name, file_name,
-					   fd, elf, base, true);
+					   fd, elf, base, base_is_bias, true);
   if (mod == NULL)
     {
       elf_end (elf);
@@ -280,4 +291,19 @@ dwfl_report_elf (Dwfl *dwfl, const char *name,
 
   return mod;
 }
+
+Dwfl_Module *
+dwfl_report_elf (Dwfl *dwfl, const char *name,
+		 const char *file_name, int fd, GElf_Addr base)
+{
+  return __libdwfl_report_elf_open (dwfl, name, file_name, fd, base, true);
+}
 INTDEF (dwfl_report_elf)
+
+Dwfl_Module *
+dwfl_report_elf_baseaddr (Dwfl *dwfl, const char *name,
+			  const char *file_name, int fd, GElf_Addr base)
+{
+  return __libdwfl_report_elf_open (dwfl, name, file_name, fd, base, false);
+}
+INTDEF (dwfl_report_elf_baseaddr)
diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h
index 8498c0c..a2ab824 100644
--- a/libdwfl/libdwfl.h
+++ b/libdwfl/libdwfl.h
@@ -146,6 +146,13 @@ extern Dwfl_Module *dwfl_report_elf (Dwfl *dwfl, const char *name,
 				     const char *file_name, int fd,
 				     GElf_Addr base);
 
+/* See dwfl_report_elf except that BASE is the page-aligned absolute VMA
+   address where the ELF file should start.  Any possible file prelinking of
+   the disk file is compensated.  */
+extern Dwfl_Module *dwfl_report_elf_baseaddr (Dwfl *dwfl, const char *name,
+					      const char *file_name, int fd,
+					      GElf_Addr base);
+
 /* Similar, but report the module for offline use.  All ET_EXEC files
    being reported must be reported before any relocatable objects.
    If this is used, dwfl_report_module and dwfl_report_elf may not be
diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h
index ca8be2f..e5e638c 100644
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -353,7 +353,8 @@ extern int __libdwfl_crc32_file (int fd, uint32_t *resp) attribute_hidden;
    Consumes ELF on success, not on failure.  */
 extern Dwfl_Module *__libdwfl_report_elf (Dwfl *dwfl, const char *name,
 					  const char *file_name, int fd,
-					  Elf *elf, GElf_Addr base, bool sanity)
+					  Elf *elf, GElf_Addr base,
+					  bool base_is_bias, bool sanity)
   internal_function;
 
 /* Meat of dwfl_report_offline.  */
diff --git a/libdwfl/offline.c b/libdwfl/offline.c
index 26a6bd6..28d2782 100644
--- a/libdwfl/offline.c
+++ b/libdwfl/offline.c
@@ -127,7 +127,8 @@ process_elf (Dwfl *dwfl, const char *name, const char *file_name, int fd,
 	     Elf *elf)
 {
   Dwfl_Module *mod = __libdwfl_report_elf (dwfl, name, file_name, fd, elf,
-					   dwfl->offline_next_address, false);
+					   dwfl->offline_next_address, true,
+					   false);
   if (mod != NULL)
     {
       /* If this is an ET_EXEC file with fixed addresses, the address range

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