This is the mail archive of the frysk@sourceware.org mailing list for the frysk 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]

Make libunwind a little bit more 64bit safe


Hi,

One of the issues we had with libunwind for 32-on-64 unwinding was that
there are some parts that need access to local 64bit memory, but defined
an unw_word_t as wide as the target (32 bit). This patch makes it so
that for those parts we now use an address space that is indexed of a
64bit pointer (passed as arg to the accessor methods). And gets rid of
the MAP_32BIT hacks we had.

When we push this upstream, we should do the same for the libunwind
ptrace backend to show why it is useful. But I didn't want to spend too
much time on that now since we don't use it in frysk.

frysk-imports/libunwind/ChangeLog
2007-11-28  Mark Wielaard  <mwielaard@redhat.com>
 
    * src/mi/Gget_unwind_table.c (unw_get_unwind_table): Make addr a
    char *, pass addr as arg to dwarf_read functions, make
    local_access_mem use arg as base address for start indexed reads.

frysk-sys/lib/unwind/ChangeLog
2007-11-29  Mark Wielaard  <mwielaard@redhat.com>

    * cni/ElfImage.cxx: Don't define MAP_32BIT.
    (mapElfImage): Don't use MAP_32BIT.
    * cni/UnwindH.hxx: Don't define MAP_32BIT.
    (createElfImageFromVDSO):  Don't use MAP_32BIT.

Tested by also running all -arch 32 tests on a 64bit system (and also
straight make check on x86 and x86_64).

It would be nicer if we didn't need to feed an elfimage to libunwind and
libunwind didn't try to do the elf parsing itself here. But when we feed
it debug_frame info we will have the table come not from the inferior
memory directly anyway, so for now it is useful (although ideally
libunwind would just accept a pointer or addressspace reference to the
debug_frame or debug_info table and use that).

Cheers,

Mark
diff --git a/frysk-imports/libunwind/src/mi/Gget_unwind_table.c b/frysk-imports/libunwind/src/mi/Gget_unwind_table.c
index 3f71bb3..2acb947 100644
--- a/frysk-imports/libunwind/src/mi/Gget_unwind_table.c
+++ b/frysk-imports/libunwind/src/mi/Gget_unwind_table.c
@@ -32,7 +32,8 @@ unw_get_unwind_table(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
 {
 	Debug(99, "Entering get_unwind_table\n");
 	Elf_W(Phdr) *phdr, *ptxt = NULL, *peh_hdr = NULL, *pdyn = NULL;
-	unw_word_t addr, eh_frame_start, fde_count, load_base;
+	unw_word_t eh_frame_start, fde_count, load_base;
+	char *addr;
 	struct dwarf_eh_frame_hdr *hdr;	
 	Elf_W(Ehdr) *ehdr;
 	int i, ret;
@@ -110,7 +111,7 @@ unw_get_unwind_table(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
 
 	Debug(99, "EH_VERSION is correct\n");
 
-  addr = (unw_word_t) (hdr + 1);
+  addr = hdr + 1;
   Debug (99, "Got addr\n");
   /* Fill in a dummy proc_info structure.  We just need to fill in
      enough to ensure that dwarf_read_encoded_pointer() can do it's
@@ -122,45 +123,48 @@ unw_get_unwind_table(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
 
   Debug(99, "set pi gp\n");
 
-
-//The following is a dummy local address space used by dwarf_read_encoded_pointer.
+// The following is a local address space memory accessor used by
+// dwarf_read_encoded_pointer.  The arg pointer is the base address,
+// addr is the offset from the base address.
   int 
   local_access_mem (unw_addr_space_t as, unw_word_t addr,
-		unw_word_t *val, int write, void *arg) 
+		    unw_word_t *val, int write, void *arg) 
   {
-  	Debug(99, "entering local_access_mem, reading addr: 0x%lx into: %p\n", 
-  	(long) addr, val);
-	if (write)
-    	{
-     	  Debug (16, "mem[%x] <- %x\n", addr, *val);
-          *(unw_word_t *) addr = *val;
-    	}
-  	else
-    	{
-          *val = *(unw_word_t *) addr;
-          Debug (16, "mem[%x] -> %x\n", addr, *val);
-    	}
-    	Debug(99, "leaving local_access_mem\n");
-  	return 0;
+    Debug(99, "entering local_access_mem, reading addr: 0x%lx into: %p\n", 
+	  (long) addr, val);
+    if (write)
+      {
+	// Writing is not supported
+	return -UNW_EINVAL;
+      }
+    else
+      {
+	*val = *(unw_word_t *) (addr + (char *) arg);
+	Debug (16, "mem[%x] -> %x\n", (addr + (char *) arg), *val);
+      }
+    Debug(99, "leaving local_access_mem\n");
+    return 0;
   }
   
-  unw_accessors_t temp_local_accessors = {NULL, NULL, NULL, local_access_mem, 
-  					  NULL, NULL,	NULL, NULL, NULL};
-  unw_addr_space_t temp_local_addr_space 
-  	= unw_create_addr_space(&temp_local_accessors, 0);
+  unw_accessors_t local_accessors = {NULL, NULL, NULL, local_access_mem, 
+				     NULL, NULL, NULL, NULL, NULL};
+  unw_addr_space_t local_addr_space
+    = unw_create_addr_space(&local_accessors, 0);
+
+  unw_word_t start = 0;
   	
    /* (Optionally) read eh_frame_ptr: */
-  if ((ret = dwarf_read_encoded_pointer (temp_local_addr_space, &temp_local_accessors,
-					 &addr, hdr->eh_frame_ptr_enc, pi,
-					 &eh_frame_start, NULL)) < 0)
+  if ((ret = dwarf_read_encoded_pointer (local_addr_space, &local_accessors,
+					 &start, hdr->eh_frame_ptr_enc, pi,
+					 &eh_frame_start, addr)) < 0)
     return -1;
     
   Debug(99, "read eh_frame_start: 0x%lx\n", (long) eh_frame_start);
 
   /* (Optionally) read fde_count: */
-  if ((ret = dwarf_read_encoded_pointer (temp_local_addr_space, &temp_local_accessors,
-					 &addr, hdr->fde_count_enc, pi,
-					 &fde_count, NULL)) < 0)
+  if ((ret = dwarf_read_encoded_pointer (local_addr_space, &local_accessors,
+					 &start, hdr->fde_count_enc, pi,
+					 &fde_count, addr)) < 0)
     return -1;
 
   Debug(99, "read fde_count: 0x%lx\n", (long) fde_count);
@@ -169,7 +173,9 @@ unw_get_unwind_table(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
       return -1;
     }
     
-    load_base = segbase - ptxt->p_vaddr;
+  addr += start;
+
+  load_base = segbase - ptxt->p_vaddr;
 
   di_cache.start_ip = segbase;
   di_cache.end_ip = di_cache.start_ip + ptxt->p_memsz;
diff --git a/frysk-sys/lib/unwind/cni/ElfImage.cxx b/frysk-sys/lib/unwind/cni/ElfImage.cxx
index bda8e25..d521643 100644
--- a/frysk-sys/lib/unwind/cni/ElfImage.cxx
+++ b/frysk-sys/lib/unwind/cni/ElfImage.cxx
@@ -48,10 +48,6 @@
 
 #include "lib/unwind/ElfImage.h"
 
-#ifndef MAP_32BIT
-#define MAP_32BIT 0
-#endif
-
 lib::unwind::ElfImage*
 lib::unwind::ElfImage::mapElfImage(jstring elfImageName, jlong segbase, jlong hi,
                                    jlong mapoff)
@@ -77,8 +73,7 @@ lib::unwind::ElfImage::mapElfImage(jstring elfImageName, jlong segbase, jlong hi
     }
 
   size = stat.st_size;
-  image = mmap (NULL, size, PROT_READ, MAP_PRIVATE | MAP_32BIT, fd, 0);
-
+  image = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
 
   close (fd);
   if (image == MAP_FAILED)
diff --git a/frysk-sys/lib/unwind/cni/UnwindH.hxx b/frysk-sys/lib/unwind/cni/UnwindH.hxx
index 77a24cf..7be5254 100644
--- a/frysk-sys/lib/unwind/cni/UnwindH.hxx
+++ b/frysk-sys/lib/unwind/cni/UnwindH.hxx
@@ -77,10 +77,6 @@
 # define MAX_VDSO_SIZE ((size_t) sysconf (_SC_PAGESIZE))
 #endif
 
-#ifndef MAP_32BIT
-# define MAP_32BIT 0
-#endif
-
 static lib::unwind::AddressSpace*
 addressSpace(void* arg)
 {
@@ -477,7 +473,7 @@ lib::unwind::TARGET::createElfImageFromVDSO(lib::unwind::AddressSpace* addressSp
   logFine(this, logger, "checked magic size");
 
   image = mmap (0, size, PROT_READ | PROT_WRITE,
-                MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
+                MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
   if (image == MAP_FAILED)
     return new lib::unwind::ElfImage((jint) -1);
 

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