b6004ce
--- elfutils-0.137/libdwfl/ChangeLog
b6004ce
+++ elfutils-0.137/libdwfl/ChangeLog
9d47a05
@@ -1,3 +1,17 @@
9d47a05
+2008-09-29  Roland McGrath  <roland@redhat.com>
9d47a05
+
9d47a05
+	* segment.c (insert): Must realloc DWFL->lookup_module here too.
9d47a05
+	(dwfl_report_segment): Clear DWFL->lookup_module before insert calls.
9d47a05
+
b6004ce
+2008-08-28  Roland McGrath  <roland@redhat.com>
b6004ce
+
b6004ce
+	* segment.c (reify_segments): Fix last change.
b6004ce
+
b6004ce
+2008-08-27  Roland McGrath  <roland@redhat.com>
b6004ce
+
b6004ce
+	* linux-proc-maps.c (read_proc_memory): Return 0 for EINVAL or EPERM
b6004ce
+	failure from pread64.
b6004ce
+
b6004ce
 2008-08-26  Roland McGrath  <roland@redhat.com>
b6004ce
 
b6004ce
 	* segment.c (reify_segments): Insert a trailing segment for a module
b6004ce
--- elfutils-0.137/libdwfl/linux-proc-maps.c
b6004ce
+++ elfutils-0.137/libdwfl/linux-proc-maps.c
b6004ce
@@ -267,6 +267,9 @@ read_proc_memory (void *arg, void *data,
b6004ce
 {
b6004ce
   const int fd = *(const int *) arg;
b6004ce
   ssize_t nread = pread64 (fd, data, maxread, (off64_t) address);
b6004ce
+  /* Some kernels don't actually let us do this read, ignore those errors.  */
b6004ce
+  if (nread < 0 && (errno == EINVAL || errno == EPERM))
b6004ce
+    return 0;
b6004ce
   if (nread > 0 && (size_t) nread < minread)
b6004ce
     nread = 0;
b6004ce
   return nread;
b6004ce
--- elfutils-0.137/libdwfl/segment.c
b6004ce
+++ elfutils-0.137/libdwfl/segment.c
9d47a05
@@ -83,12 +83,26 @@ insert (Dwfl *dwfl, size_t i, GElf_Addr 
9d47a05
       int *nsegndx = realloc (dwfl->lookup_segndx, sizeof nsegndx[0] * n);
9d47a05
       if (unlikely (nsegndx == NULL))
9d47a05
 	{
9d47a05
-	  free (naddr);
9d47a05
+	  if (naddr != dwfl->lookup_addr)
9d47a05
+	    free (naddr);
9d47a05
 	  return true;
9d47a05
 	}
9d47a05
       dwfl->lookup_alloc = n;
9d47a05
       dwfl->lookup_addr = naddr;
9d47a05
       dwfl->lookup_segndx = nsegndx;
9d47a05
+
9d47a05
+      if (dwfl->lookup_module != NULL)
9d47a05
+	{
9d47a05
+	  /* Make sure this array is big enough too.  */
9d47a05
+	  Dwfl_Module **old = dwfl->lookup_module;
9d47a05
+	  dwfl->lookup_module = realloc (dwfl->lookup_module,
9d47a05
+					 sizeof dwfl->lookup_module[0] * n);
9d47a05
+	  if (unlikely (dwfl->lookup_module == NULL))
9d47a05
+	    {
9d47a05
+	      free (old);
9d47a05
+	      return true;
9d47a05
+	    }
9d47a05
+	}
9d47a05
     }
9d47a05
 
9d47a05
   if (unlikely (i < dwfl->lookup_elts))
9d47a05
@@ -175,9 +189,17 @@ reify_segments (Dwfl *dwfl)
b6004ce
 	      return true;
b6004ce
 	    ++idx;
b6004ce
 	  }
b6004ce
+	else if (dwfl->lookup_addr[idx] < start)
b6004ce
+	  {
b6004ce
+	    /* The module starts past the end of this segment.
b6004ce
+	       Add a new one.  */
b6004ce
+	    if (unlikely (insert (dwfl, idx + 1, start, end, -1)))
b6004ce
+	      return true;
b6004ce
+	    ++idx;
b6004ce
+	  }
b6004ce
 
b6004ce
-	if (((size_t) idx + 1 == dwfl->lookup_elts
b6004ce
-	     || end < dwfl->lookup_addr[idx + 1])
b6004ce
+	if ((size_t) idx + 1 < dwfl->lookup_elts
b6004ce
+	    && end < dwfl->lookup_addr[idx + 1]
b6004ce
 	    /* The module ends in the middle of this segment.  Split it.  */
b6004ce
 	    && unlikely (insert (dwfl, idx + 1,
b6004ce
 				 end, dwfl->lookup_addr[idx + 1], -1)))
9d47a05
@@ -261,6 +283,12 @@ dwfl_report_segment (Dwfl *dwfl, int ndx
9d47a05
 			    phdr->p_align < dwfl->segment_align))
9d47a05
     dwfl->segment_align = phdr->p_align;
9d47a05
 
9d47a05
+  if (unlikely (dwfl->lookup_module != NULL))
9d47a05
+    {
9d47a05
+      free (dwfl->lookup_module);
9d47a05
+      dwfl->lookup_module = NULL;
9d47a05
+    }
9d47a05
+
9d47a05
   GElf_Addr start = segment_start (dwfl, bias + phdr->p_vaddr);
9d47a05
   GElf_Addr end = segment_end (dwfl, bias + phdr->p_vaddr + phdr->p_memsz);
9d47a05
 
9d47a05
@@ -289,12 +317,6 @@ dwfl_report_segment (Dwfl *dwfl, int ndx
9d47a05
   dwfl->lookup_tail_offset = end - bias - phdr->p_vaddr + phdr->p_offset;
9d47a05
   dwfl->lookup_tail_ndx = ndx + 1;
9d47a05
 
9d47a05
-  if (unlikely (dwfl->lookup_module != NULL))
9d47a05
-    {
9d47a05
-      free (dwfl->lookup_module);
9d47a05
-      dwfl->lookup_module = NULL;
9d47a05
-    }
9d47a05
-
9d47a05
   return ndx;
9d47a05
 }
9d47a05
 INTDEF (dwfl_report_segment)
b6004ce
--- elfutils-0.137/libelf/ChangeLog
b6004ce
+++ elfutils-0.137/libelf/ChangeLog
b6004ce
@@ -1,3 +1,9 @@
b6004ce
+2008-08-27  Roland McGrath  <roland@redhat.com>
b6004ce
+
b6004ce
+	* elf_begin.c (get_shnum): Avoid misaligned reads for matching endian.
b6004ce
+
b6004ce
+	* libelfP.h [!ALLOW_UNALIGNED] (__libelf_type_align): Fix CLASS index.
b6004ce
+
b6004ce
 2008-08-25  Roland McGrath  <roland@redhat.com>
b6004ce
 
b6004ce
 	* Makefile.am (libelf_so_LDLIBS): New variable.
b6004ce
--- elfutils-0.137/libelf/elf_begin.c
b6004ce
+++ elfutils-0.137/libelf/elf_begin.c
9d47a05
@@ -111,7 +111,11 @@ get_shnum (void *map_address, unsigned c
b6004ce
   bool is32 = e_ident[EI_CLASS] == ELFCLASS32;
b6004ce
 
b6004ce
   /* Make the ELF header available.  */
b6004ce
-  if (e_ident[EI_DATA] == MY_ELFDATA)
b6004ce
+  if (e_ident[EI_DATA] == MY_ELFDATA
b6004ce
+      && (ALLOW_UNALIGNED
b6004ce
+	  || (((size_t) e_ident
b6004ce
+	       & ((is32 ? __alignof__ (Elf32_Ehdr) : __alignof__ (Elf64_Ehdr))
b6004ce
+		  - 1)) == 0)))
b6004ce
     ehdr.p = e_ident;
b6004ce
   else
b6004ce
     {
9d47a05
@@ -130,8 +134,11 @@ get_shnum (void *map_address, unsigned c
b6004ce
 	  else
b6004ce
 	    memcpy (&ehdr_mem, e_ident, sizeof (Elf32_Ehdr));
b6004ce
 
b6004ce
-	  CONVERT (ehdr_mem.e32.e_shnum);
b6004ce
-	  CONVERT (ehdr_mem.e32.e_shoff);
b6004ce
+	  if (e_ident[EI_DATA] != MY_ELFDATA)
b6004ce
+	    {
b6004ce
+	      CONVERT (ehdr_mem.e32.e_shnum);
b6004ce
+	      CONVERT (ehdr_mem.e32.e_shoff);
b6004ce
+	    }
b6004ce
 	}
b6004ce
       else
b6004ce
 	{
9d47a05
@@ -143,8 +150,11 @@ get_shnum (void *map_address, unsigned c
b6004ce
 	  else
b6004ce
 	    memcpy (&ehdr_mem, e_ident, sizeof (Elf64_Ehdr));
b6004ce
 
b6004ce
-	  CONVERT (ehdr_mem.e64.e_shnum);
b6004ce
-	  CONVERT (ehdr_mem.e64.e_shoff);
b6004ce
+	  if (e_ident[EI_DATA] != MY_ELFDATA)
b6004ce
+	    {
b6004ce
+	      CONVERT (ehdr_mem.e64.e_shnum);
b6004ce
+	      CONVERT (ehdr_mem.e64.e_shoff);
b6004ce
+	    }
b6004ce
 	}
b6004ce
     }
b6004ce
 
b6004ce
--- elfutils-0.137/libelf/libelfP.h
b6004ce
+++ elfutils-0.137/libelf/libelfP.h
b6004ce
@@ -460,7 +460,7 @@ extern const uint_fast8_t __libelf_type_
b6004ce
    version, binary class, and type. */
b6004ce
 extern const uint_fast8_t __libelf_type_aligns[EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM] attribute_hidden;
b6004ce
 # define __libelf_type_align(class, type)	\
b6004ce
-    (__libelf_type_aligns[LIBELF_EV_IDX][class][type] ?: 1)
b6004ce
+    (__libelf_type_aligns[LIBELF_EV_IDX][class - 1][type] ?: 1)
b6004ce
 #else
b6004ce
 # define __libelf_type_align(class, type)	1
b6004ce
 #endif