Blob Blame History Raw
--- a/libdw/ChangeLog	2012-08-27 20:29:31.000000000 +0200
+++ b/libdw/ChangeLog	2013-01-10 10:59:28.039026230 +0100
@@ -1,3 +1,9 @@
+2013-01-07  Roland McGrath  <roland@hack.frob.com>
+
+	* memory-access.h
+	[ALLOW_UNALIGNED] (read_8ubyte_unaligned_noncvt): New macro.
+	[!ALLOW_UNALIGNED] (read_8ubyte_unaligned_noncvt): New inline function.
+
 2012-08-24  Mark Wielaard  <mjw@redhat.com>
 
 	* dwarf_begin_elf.c (check_section): Only probe for dwz multi files
--- a/libdw/memory-access.h	2012-08-27 20:27:31.000000000 +0200
+++ b/libdw/memory-access.h	2013-01-10 10:56:07.171152555 +0100
@@ -1,5 +1,5 @@
 /* Unaligned memory access functionality.
-   Copyright (C) 2000-2010 Red Hat, Inc.
+   Copyright (C) 2000-2013 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2001.
 
@@ -147,6 +147,8 @@
    ? (int32_t) bswap_32 (*((const int32_t *) (Addr)))			      \
    : *((const int32_t *) (Addr)))
 
+# define read_8ubyte_unaligned_noncvt(Addr) \
+   *((const uint64_t *) (Addr))
 # define read_8ubyte_unaligned(Dbg, Addr) \
   (unlikely ((Dbg)->other_byte_order)					      \
    ? bswap_64 (*((const uint64_t *) (Addr)))				      \
@@ -223,6 +225,12 @@
 }
 
 static inline uint64_t
+read_8ubyte_unaligned_noncvt (const void *p)
+{
+  const union unaligned *up = p;
+  return up->u8;
+}
+static inline uint64_t
 read_8ubyte_unaligned_1 (bool other_byte_order, const void *p)
 {
   const union unaligned *up = p;
--- a/libdwfl/ChangeLog	2013-01-10 10:59:53.882008409 +0100
+++ b/libdwfl/ChangeLog	2013-01-10 10:57:48.451130775 +0100
@@ -1,3 +1,9 @@
+2013-01-07  Roland McGrath  <roland@hack.frob.com>
+
+	* link_map.c (auxv_format_probe): Handle unaligned 64-bit data, but
+	still assume the data is at least 32-bit aligned anyway.
+	(dwfl_link_map_report): Handle unaligned auxv data.
+
 2012-08-01  Petr Machata  <pmachata@redhat.com>
 
 	* offline.c (process_archive_member): Ignore entry "/SYM64/".
--- a/libdwfl/link_map.c	2012-08-27 20:27:31.000000000 +0200
+++ b/libdwfl/link_map.c	2013-01-10 10:56:07.207002831 +0100
@@ -1,5 +1,5 @@
 /* Report modules by examining dynamic linker data structures.
-   Copyright (C) 2008-2010 Red Hat, Inc.
+   Copyright (C) 2008-2013 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -28,6 +28,7 @@
 
 #include <config.h>
 #include "libdwflP.h"
+#include "../libdw/memory-access.h"
 
 #include <byteswap.h>
 #include <endian.h>
@@ -66,15 +67,22 @@
 
   inline bool check64 (size_t i)
   {
-    if (u->a64[i].a_type == BE64 (PROBE_TYPE)
-	&& u->a64[i].a_un.a_val == BE64 (PROBE_VAL64))
+    /* The AUXV pointer might not even be naturally aligned for 64-bit
+       data, because note payloads in a core file are not aligned.
+       But we assume the data is 32-bit aligned.  */
+
+    uint64_t type = read_8ubyte_unaligned_noncvt (&u->a64[i].a_type);
+    uint64_t val = read_8ubyte_unaligned_noncvt (&u->a64[i].a_un.a_val);
+
+    if (type == BE64 (PROBE_TYPE)
+	&& val == BE64 (PROBE_VAL64))
       {
 	*elfdata = ELFDATA2MSB;
 	return true;
       }
 
-    if (u->a64[i].a_type == LE64 (PROBE_TYPE)
-	&& u->a64[i].a_un.a_val == LE64 (PROBE_VAL64))
+    if (type == LE64 (PROBE_TYPE)
+	&& val == LE64 (PROBE_VAL64))
       {
 	*elfdata = ELFDATA2LSB;
 	return true;
@@ -618,29 +626,32 @@
       GElf_Xword phent = 0;
       GElf_Xword phnum = 0;
 
-#define AUXV_SCAN(NN, BL) do					\
-	{							\
-	  const Elf##NN##_auxv_t *av = auxv;			\
-	  for (size_t i = 0; i < auxv_size / sizeof av[0]; ++i)	\
-	    {							\
-	      Elf##NN##_Addr val = BL##NN (av[i].a_un.a_val);	\
-	      if (av[i].a_type == BL##NN (AT_ENTRY))		\
-		entry = val;					\
-	      else if (av[i].a_type == BL##NN (AT_PHDR))	\
-		phdr = val;					\
-	      else if (av[i].a_type == BL##NN (AT_PHNUM))	\
-		phnum = val;					\
-	      else if (av[i].a_type == BL##NN (AT_PHENT))	\
-		phent = val;					\
-	      else if (av[i].a_type == BL##NN (AT_PAGESZ))	\
-		{						\
-		  if (val > 1					\
-		      && (dwfl->segment_align == 0		\
-			  || val < dwfl->segment_align))	\
-		    dwfl->segment_align = val;			\
-		}						\
-	    }							\
-	}							\
+#define READ_AUXV32(ptr)	read_4ubyte_unaligned_noncvt (ptr)
+#define READ_AUXV64(ptr)	read_8ubyte_unaligned_noncvt (ptr)
+#define AUXV_SCAN(NN, BL) do                                            \
+	{                                                               \
+	  const Elf##NN##_auxv_t *av = auxv;                            \
+	  for (size_t i = 0; i < auxv_size / sizeof av[0]; ++i)         \
+	    {                                                           \
+              uint##NN##_t type = READ_AUXV##NN (&av[i].a_type);        \
+              uint##NN##_t val = BL##NN (READ_AUXV##NN (&av[i].a_un.a_val)); \
+	      if (type == BL##NN (AT_ENTRY))                            \
+		entry = val;                                            \
+	      else if (type == BL##NN (AT_PHDR))                        \
+		phdr = val;                                             \
+	      else if (type == BL##NN (AT_PHNUM))                       \
+		phnum = val;                                            \
+	      else if (type == BL##NN (AT_PHENT))                       \
+		phent = val;                                            \
+	      else if (type == BL##NN (AT_PAGESZ))                      \
+		{                                                       \
+		  if (val > 1                                           \
+		      && (dwfl->segment_align == 0                      \
+			  || val < dwfl->segment_align))                \
+		    dwfl->segment_align = val;                          \
+		}                                                       \
+	    }                                                           \
+	}                                                               \
       while (0)
 
       if (elfclass == ELFCLASS32)
--- a/libelf/ChangeLog	2013-01-10 10:59:53.884010033 +0100
+++ b/libelf/ChangeLog	2013-01-10 10:58:57.505003982 +0100
@@ -1,3 +1,13 @@
+2013-01-07  Roland McGrath  <roland@hack.frob.com>
+
+	* elf_getarsym.c (elf_getarsym): Copy FILE_DATA into stack space if it
+	would be unaligned and !ALLOW_UNALIGNED.
+
+2013-01-07  Roland McGrath  <roland@hack.frob.com>
+
+	* elf_getarsym.c (read_number_entries): Use memcpy instead of pointer
+	dereference so as not to assume the field is naturally aligned.
+
 2012-08-16  Roland McGrath  <roland@hack.frob.com>
 
 	* elf.h: Update from glibc.
--- a/libelf/elf_getarsym.c	2013-01-10 10:59:53.888006636 +0100
+++ b/libelf/elf_getarsym.c	2013-01-10 10:56:07.210254028 +0100
@@ -57,7 +57,9 @@
 
   size_t w = index64_p ? 8 : 4;
   if (elf->map_address != NULL)
-    u = *(union u *) (elf->map_address + *offp);
+    /* Use memcpy instead of pointer dereference so as not to assume the
+       field is naturally aligned within the file.  */
+    memcpy (&u, elf->map_address + *offp, sizeof u);
   else if ((size_t) pread_retry (elf->fildes, &u, w, *offp) != w)
     return -1;
 
@@ -241,6 +243,9 @@
 	  else
 	    {
 	      file_data = (void *) (elf->map_address + off);
+	      if (!ALLOW_UNALIGNED
+		  && ((uintptr_t) file_data & -(uintptr_t) n) != 0)
+		file_data = memcpy (alloca (sz), elf->map_address + off, sz);
 	      str_data = (char *) (elf->map_address + off + sz);
 	    }