--- 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 + + * 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 * 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 , 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 + + * 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 * 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 #include "libdwflP.h" +#include "../libdw/memory-access.h" #include #include @@ -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 + + * elf_getarsym.c (elf_getarsym): Copy FILE_DATA into stack space if it + would be unaligned and !ALLOW_UNALIGNED. + +2013-01-07 Roland McGrath + + * 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 * 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); }