From a49ad4fb5eb87a7f0cce99654755fb62a9b67c8a Mon Sep 17 00:00:00 2001 From: Chih-Hung Hsieh Date: Tue, 8 Sep 2015 11:53:16 -0700 Subject: [PATCH] Do without union of variable length arrays. Prepare to compile without gnu99 extension. A union like { T32 a32[n]; T64 a64[n]; } u; is expanded to void *data = malloc (...); T32 *a32 = data; T64 *a64 = data; Signed-off-by: Chih-Hung Hsieh --- libdwfl/ChangeLog | 10 +++++ libdwfl/dwfl_module_getdwarf.c | 50 +++++++++++----------- libdwfl/dwfl_segment_report_module.c | 66 ++++++++++++++--------------- libdwfl/elf-from-memory.c | 47 +++++++++++---------- libdwfl/link_map.c | 81 +++++++++++++----------------------- libelf/ChangeLog | 5 +++ libelf/elf_getarsym.c | 12 ++---- src/ChangeLog | 9 ++++ src/readelf.c | 30 +++++++------ src/unstrip.c | 25 ++++++----- 10 files changed, 170 insertions(+), 165 deletions(-) diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 3e36aa7..0b3af9f 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,13 @@ +2015-09-08 Chih-Hung Hsieh + + * dwfl_module_getdwarf.c (find_prelink_address_sync): Do not use + union of variable length arrays. + * dwfl_segment_report_module.c (dwfl_segment_report_module): Likewise + * elf-from-memory.c (elf_from_remote_memory): Likewise + * link_map.c (auxv_format_probe): Likewise + * link_map.c (report_r_debug): Likewise + * link_map.c (dwfl_link_map_report): Likewise + 2015-08-14 Dodji Seketeli * find-debuginfo.c (find_debuginfo_in_path): Try to locate the diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c index dba9d66..93afb76 100644 --- a/libdwfl/dwfl_module_getdwarf.c +++ b/libdwfl/dwfl_module_getdwarf.c @@ -34,6 +34,10 @@ #include "../libdw/libdwP.h" /* DWARF_E_* values are here. */ #include "../libelf/libelfP.h" +#ifndef MAX +# define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + static inline Dwfl_Error open_elf_file (Elf **elf, int *fd, char **name) { @@ -368,16 +372,15 @@ find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file) GElf_Addr undo_interp = 0; { - typedef union - { - Elf32_Phdr p32[phnum]; - Elf64_Phdr p64[phnum]; - } phdr; - phdr *phdrs = malloc (sizeof (phdr)); + const int phdrs_bytes = + phnum * MAX (sizeof (Elf32_Phdr), sizeof (Elf64_Phdr)); + void *phdrs = malloc (phdrs_bytes); + Elf32_Phdr *p32 = phdrs; + Elf64_Phdr *p64 = phdrs; if (unlikely (phdrs == NULL)) return DWFL_E_NOMEM; dst.d_buf = phdrs; - dst.d_size = sizeof (phdr); + dst.d_size = phdrs_bytes; if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src, ehdr.e32.e_ident[EI_DATA]) == NULL)) { @@ -387,18 +390,18 @@ find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file) if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32) { for (uint_fast16_t i = 0; i < phnum; ++i) - if (phdrs->p32[i].p_type == PT_INTERP) + if (p32[i].p_type == PT_INTERP) { - undo_interp = phdrs->p32[i].p_vaddr; + undo_interp = p32[i].p_vaddr; break; } } else { for (uint_fast16_t i = 0; i < phnum; ++i) - if (phdrs->p64[i].p_type == PT_INTERP) + if (p64[i].p_type == PT_INTERP) { - undo_interp = phdrs->p64[i].p_vaddr; + undo_interp = p64[i].p_vaddr; break; } } @@ -412,16 +415,15 @@ find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file) src.d_type = ELF_T_SHDR; src.d_size = gelf_fsize (mod->main.elf, ELF_T_SHDR, shnum - 1, EV_CURRENT); - typedef union - { - Elf32_Shdr s32[shnum - 1]; - Elf64_Shdr s64[shnum - 1]; - } shdr; - shdr *shdrs = malloc (sizeof (shdr)); + const int shdrs_bytes = + (shnum - 1) * MAX (sizeof (Elf32_Shdr), sizeof (Elf64_Shdr)); + void *shdrs = malloc (shdrs_bytes); + Elf32_Shdr *s32 = shdrs; + Elf64_Shdr *s64 = shdrs; if (unlikely (shdrs == NULL)) return DWFL_E_NOMEM; dst.d_buf = shdrs; - dst.d_size = sizeof (shdr); + dst.d_size = shdrs_bytes; if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src, ehdr.e32.e_ident[EI_DATA]) == NULL)) { @@ -484,14 +486,14 @@ find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file) highest = 0; if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32) for (size_t i = 0; i < shnum - 1; ++i) - consider_shdr (undo_interp, shdrs->s32[i].sh_type, - shdrs->s32[i].sh_flags, shdrs->s32[i].sh_addr, - shdrs->s32[i].sh_size); + consider_shdr (undo_interp, s32[i].sh_type, + s32[i].sh_flags, s32[i].sh_addr, + s32[i].sh_size); else for (size_t i = 0; i < shnum - 1; ++i) - consider_shdr (undo_interp, shdrs->s64[i].sh_type, - shdrs->s64[i].sh_flags, shdrs->s64[i].sh_addr, - shdrs->s64[i].sh_size); + consider_shdr (undo_interp, s64[i].sh_type, + s64[i].sh_flags, s64[i].sh_addr, + s64[i].sh_size); if (highest > file->vaddr) file->address_sync = highest; diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c index a0f07ad..43742ef 100644 --- a/libdwfl/dwfl_segment_report_module.c +++ b/libdwfl/dwfl_segment_report_module.c @@ -53,6 +53,10 @@ # define MY_ELFDATA ELFDATA2MSB #endif +#ifndef MAX +# define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + /* Return user segment index closest to ADDR but not above it. If NEXT, return the closest to ADDR but not below it. */ @@ -404,19 +408,16 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, xlatefrom.d_buf = ph_buffer; - typedef union - { - Elf32_Phdr p32[phnum]; - Elf64_Phdr p64[phnum]; - } phdrsn; - - phdrsp = malloc (sizeof (phdrsn)); + const int phdrsp_bytes = + phnum * MAX (sizeof (Elf32_Phdr), sizeof (Elf64_Phdr)); + phdrsp = malloc (phdrsp_bytes); + Elf32_Phdr *p32 = phdrsp; + Elf64_Phdr *p64 = phdrsp; if (unlikely (phdrsp == NULL)) return finish (); - phdrsn *phdrs = (phdrsn *) phdrsp; - xlateto.d_buf = phdrs; - xlateto.d_size = sizeof (phdrsn); + xlateto.d_buf = phdrsp; + xlateto.d_size = phdrsp_bytes; /* Track the bounds of the file visible in memory. */ GElf_Off file_trimmed_end = 0; /* Proper p_vaddr + p_filesz end. */ @@ -579,10 +580,10 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, found_bias = false; /* Trigger error check. */ else for (uint_fast16_t i = 0; i < phnum; ++i) - consider_phdr (phdrs->p32[i].p_type, - phdrs->p32[i].p_vaddr, phdrs->p32[i].p_memsz, - phdrs->p32[i].p_offset, phdrs->p32[i].p_filesz, - phdrs->p32[i].p_align); + consider_phdr (p32[i].p_type, + p32[i].p_vaddr, p32[i].p_memsz, + p32[i].p_offset, p32[i].p_filesz, + p32[i].p_align); } else { @@ -590,10 +591,10 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, found_bias = false; /* Trigger error check. */ else for (uint_fast16_t i = 0; i < phnum; ++i) - consider_phdr (phdrs->p64[i].p_type, - phdrs->p64[i].p_vaddr, phdrs->p64[i].p_memsz, - phdrs->p64[i].p_offset, phdrs->p64[i].p_filesz, - phdrs->p64[i].p_align); + consider_phdr (p64[i].p_type, + p64[i].p_vaddr, p64[i].p_memsz, + p64[i].p_offset, p64[i].p_filesz, + p64[i].p_align); } finish_portion (&ph_buffer, &ph_buffer_size); @@ -749,44 +750,39 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, const size_t dyn_entsize = (ei_class == ELFCLASS32 ? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn)); - void *dyns = NULL; void *dyn_data = NULL; size_t dyn_data_size = 0; if (dyn_filesz != 0 && dyn_filesz % dyn_entsize == 0 && ! read_portion (&dyn_data, &dyn_data_size, dyn_vaddr, dyn_filesz)) { - typedef union - { - Elf32_Dyn d32[dyn_filesz / sizeof (Elf32_Dyn)]; - Elf64_Dyn d64[dyn_filesz / sizeof (Elf64_Dyn)]; - } dynn; - dyns = malloc (sizeof (dynn)); + void *dyns = malloc (dyn_filesz); + Elf32_Dyn *d32 = dyns; + Elf64_Dyn *d64 = dyns; if (unlikely (dyns == NULL)) return finish (); - dynn *dyn = (dynn *) dyns; xlatefrom.d_type = xlateto.d_type = ELF_T_DYN; xlatefrom.d_buf = (void *) dyn_data; xlatefrom.d_size = dyn_filesz; - xlateto.d_buf = dyn; - xlateto.d_size = sizeof (dynn); + xlateto.d_buf = dyns; + xlateto.d_size = dyn_filesz; if (ei_class == ELFCLASS32) { if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL) for (size_t i = 0; i < dyn_filesz / sizeof (Elf32_Dyn); ++i) - if (consider_dyn (dyn->d32[i].d_tag, dyn->d32[i].d_un.d_val)) + if (consider_dyn (d32[i].d_tag, d32[i].d_un.d_val)) break; } else { if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL) for (size_t i = 0; i < dyn_filesz / sizeof (Elf64_Dyn); ++i) - if (consider_dyn (dyn->d64[i].d_tag, dyn->d64[i].d_un.d_val)) + if (consider_dyn (d64[i].d_tag, d64[i].d_un.d_val)) break; } + free (dyns); } - free (dyns); finish_portion (&dyn_data, &dyn_data_size); /* We'll use the name passed in or a stupid default if not DT_SONAME. */ @@ -901,12 +897,12 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, if (ei_class == ELFCLASS32) for (uint_fast16_t i = 0; i < phnum; ++i) - read_phdr (phdrs->p32[i].p_type, phdrs->p32[i].p_vaddr, - phdrs->p32[i].p_offset, phdrs->p32[i].p_filesz); + read_phdr (p32[i].p_type, p32[i].p_vaddr, + p32[i].p_offset, p32[i].p_filesz); else for (uint_fast16_t i = 0; i < phnum; ++i) - read_phdr (phdrs->p64[i].p_type, phdrs->p64[i].p_vaddr, - phdrs->p64[i].p_offset, phdrs->p64[i].p_filesz); + read_phdr (p64[i].p_type, p64[i].p_vaddr, + p64[i].p_offset, p64[i].p_filesz); } else { diff --git a/libdwfl/elf-from-memory.c b/libdwfl/elf-from-memory.c index ed8f6e9..47e743d 100644 --- a/libdwfl/elf-from-memory.c +++ b/libdwfl/elf-from-memory.c @@ -38,6 +38,10 @@ #include #include +#ifndef MAX +# define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + /* Reconstruct an ELF file by reading the segments out of remote memory based on the ELF file header at EHDR_VMA and the ELF program headers it points to. If not null, *LOADBASEP is filled in with the difference @@ -191,22 +195,19 @@ elf_from_remote_memory (GElf_Addr ehdr_vma, xlatefrom.d_buf = buffer; } - typedef union - { - Elf32_Phdr p32[phnum]; - Elf64_Phdr p64[phnum]; - } phdrsn; - - phdrsp = malloc (sizeof (phdrsn)); + const int phdrsp_bytes = + phnum * MAX (sizeof (Elf32_Phdr), sizeof (Elf64_Phdr)); + phdrsp = malloc (phdrsp_bytes); + Elf32_Phdr *p32 = phdrsp; + Elf64_Phdr *p64 = phdrsp; if (unlikely (phdrsp == NULL)) { free (buffer); goto no_memory; } - phdrsn *phdrs = (phdrsn *) phdrsp; - xlateto.d_buf = phdrs; - xlateto.d_size = sizeof (phdrsn); + xlateto.d_buf = phdrsp; + xlateto.d_size = phdrsp_bytes; /* Scan for PT_LOAD segments to find the total size of the file image. */ size_t contents_size = 0; @@ -249,9 +250,9 @@ elf_from_remote_memory (GElf_Addr ehdr_vma, ehdr.e32.e_ident[EI_DATA]) == NULL) goto libelf_error; for (uint_fast16_t i = 0; i < phnum; ++i) - if (phdrs->p32[i].p_type == PT_LOAD) - if (handle_segment (phdrs->p32[i].p_vaddr, phdrs->p32[i].p_offset, - phdrs->p32[i].p_filesz, phdrs->p32[i].p_memsz)) + if (p32[i].p_type == PT_LOAD) + if (handle_segment (p32[i].p_vaddr, p32[i].p_offset, + p32[i].p_filesz, p32[i].p_memsz)) goto bad_elf; break; @@ -260,9 +261,9 @@ elf_from_remote_memory (GElf_Addr ehdr_vma, ehdr.e64.e_ident[EI_DATA]) == NULL) goto libelf_error; for (uint_fast16_t i = 0; i < phnum; ++i) - if (phdrs->p64[i].p_type == PT_LOAD) - if (handle_segment (phdrs->p64[i].p_vaddr, phdrs->p64[i].p_offset, - phdrs->p64[i].p_filesz, phdrs->p64[i].p_memsz)) + if (p64[i].p_type == PT_LOAD) + if (handle_segment (p64[i].p_vaddr, p64[i].p_offset, + p64[i].p_filesz, p64[i].p_memsz)) goto bad_elf; break; @@ -315,9 +316,9 @@ elf_from_remote_memory (GElf_Addr ehdr_vma, case ELFCLASS32: for (uint_fast16_t i = 0; i < phnum; ++i) - if (phdrs->p32[i].p_type == PT_LOAD) - if (handle_segment (phdrs->p32[i].p_vaddr, phdrs->p32[i].p_offset, - phdrs->p32[i].p_filesz)) + if (p32[i].p_type == PT_LOAD) + if (handle_segment (p32[i].p_vaddr, p32[i].p_offset, + p32[i].p_filesz)) goto read_error; /* If the segments visible in memory didn't include the section @@ -342,9 +343,9 @@ elf_from_remote_memory (GElf_Addr ehdr_vma, case ELFCLASS64: for (uint_fast16_t i = 0; i < phnum; ++i) - if (phdrs->p64[i].p_type == PT_LOAD) - if (handle_segment (phdrs->p64[i].p_vaddr, phdrs->p64[i].p_offset, - phdrs->p64[i].p_filesz)) + if (p64[i].p_type == PT_LOAD) + if (handle_segment (p64[i].p_vaddr, p64[i].p_offset, + p64[i].p_filesz)) goto read_error; /* If the segments visible in memory didn't include the section @@ -373,7 +374,7 @@ elf_from_remote_memory (GElf_Addr ehdr_vma, } free (phdrsp); - phdrs = phdrsp = NULL; + phdrsp = NULL; /* Now we have the image. Open libelf on it. */ diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c index 030c600..a756e43 100644 --- a/libdwfl/link_map.c +++ b/libdwfl/link_map.c @@ -48,20 +48,16 @@ static bool auxv_format_probe (const void *auxv, size_t size, uint_fast8_t *elfclass, uint_fast8_t *elfdata) { - const union - { - char buf[size]; - Elf32_auxv_t a32[size / sizeof (Elf32_auxv_t)]; - Elf64_auxv_t a64[size / sizeof (Elf64_auxv_t)]; - } *u = auxv; + const Elf32_auxv_t *a32 = auxv; + const Elf64_auxv_t *a64 = auxv; inline bool check64 (size_t i) { /* The AUXV pointer might not even be naturally aligned for 64-bit data, because note payloads in a core file are not 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); + uint64_t type = read_8ubyte_unaligned_noncvt (&a64[i].a_type); + uint64_t val = read_8ubyte_unaligned_noncvt (&a64[i].a_un.a_val); if (type == BE64 (PROBE_TYPE) && val == BE64 (PROBE_VAL64)) @@ -85,8 +81,8 @@ auxv_format_probe (const void *auxv, size_t size, /* The AUXV pointer might not even be naturally aligned for 32-bit data, because note payloads in a core file are not aligned. */ - uint32_t type = read_4ubyte_unaligned_noncvt (&u->a32[i].a_type); - uint32_t val = read_4ubyte_unaligned_noncvt (&u->a32[i].a_un.a_val); + uint32_t type = read_4ubyte_unaligned_noncvt (&a32[i].a_type); + uint32_t val = read_4ubyte_unaligned_noncvt (&a32[i].a_un.a_val); if (type == BE32 (PROBE_TYPE) && val == BE32 (PROBE_VAL32)) @@ -280,29 +276,26 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata, return true; } - const union - { - Elf32_Addr a32[n]; - Elf64_Addr a64[n]; - } *in = vaddr - read_vaddr + buffer; + Elf32_Addr *a32 = vaddr - read_vaddr + buffer; + Elf64_Addr *a64 = (void *) a32; if (elfclass == ELFCLASS32) { if (elfdata == ELFDATA2MSB) for (size_t i = 0; i < n; ++i) - addrs[i] = BE32 (read_4ubyte_unaligned_noncvt (&in->a32[i])); + addrs[i] = BE32 (read_4ubyte_unaligned_noncvt (&a32[i])); else for (size_t i = 0; i < n; ++i) - addrs[i] = LE32 (read_4ubyte_unaligned_noncvt (&in->a32[i])); + addrs[i] = LE32 (read_4ubyte_unaligned_noncvt (&a32[i])); } else { if (elfdata == ELFDATA2MSB) for (size_t i = 0; i < n; ++i) - addrs[i] = BE64 (read_8ubyte_unaligned_noncvt (&in->a64[i])); + addrs[i] = BE64 (read_8ubyte_unaligned_noncvt (&a64[i])); else for (size_t i = 0; i < n; ++i) - addrs[i] = LE64 (read_8ubyte_unaligned_noncvt (&in->a64[i])); + addrs[i] = LE64 (read_8ubyte_unaligned_noncvt (&a64[i])); } return false; @@ -861,13 +854,9 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size, } if (in_ok) { - typedef union - { - Elf32_Phdr p32; - Elf64_Phdr p64; - char data[phnum * phent]; - } data_buf; - data_buf *buf = malloc (sizeof (data_buf)); + void *buf = malloc (phnum * phent); + Elf32_Phdr *p32 = buf; + Elf64_Phdr *p64 = buf; if (unlikely (buf == NULL)) { __libdwfl_seterrno (DWFL_E_NOMEM); @@ -886,25 +875,20 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size, (&out, &in, elfdata) != NULL)) { /* We are looking for PT_DYNAMIC. */ - const union - { - Elf32_Phdr p32[phnum]; - Elf64_Phdr p64[phnum]; - } *u = (void *) buf; if (elfclass == ELFCLASS32) { for (size_t i = 0; i < phnum; ++i) - if (consider_phdr (u->p32[i].p_type, - u->p32[i].p_vaddr, - u->p32[i].p_filesz)) + if (consider_phdr (p32[i].p_type, + p32[i].p_vaddr, + p32[i].p_filesz)) break; } else { for (size_t i = 0; i < phnum; ++i) - if (consider_phdr (u->p64[i].p_type, - u->p64[i].p_vaddr, - u->p64[i].p_filesz)) + if (consider_phdr (p64[i].p_type, + p64[i].p_vaddr, + p64[i].p_filesz)) break; } } @@ -955,13 +939,9 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size, if ((*memory_callback) (dwfl, dyn_segndx, &in.d_buf, &in.d_size, dyn_vaddr, dyn_filesz, memory_callback_arg)) { - typedef union - { - Elf32_Dyn d32; - Elf64_Dyn d64; - char data[dyn_filesz]; - } data_buf; - data_buf *buf = malloc (sizeof (data_buf)); + void *buf = malloc (dyn_filesz); + Elf32_Dyn *d32 = buf; + Elf64_Dyn *d64 = buf; if (unlikely (buf == NULL)) { __libdwfl_seterrno (DWFL_E_NOMEM); @@ -980,18 +960,13 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size, (&out, &in, elfdata) != NULL)) { /* We are looking for DT_DEBUG. */ - const union - { - Elf32_Dyn d32[dyn_filesz / sizeof (Elf32_Dyn)]; - Elf64_Dyn d64[dyn_filesz / sizeof (Elf64_Dyn)]; - } *u = (void *) buf; if (elfclass == ELFCLASS32) { size_t n = dyn_filesz / sizeof (Elf32_Dyn); for (size_t i = 0; i < n; ++i) - if (u->d32[i].d_tag == DT_DEBUG) + if (d32[i].d_tag == DT_DEBUG) { - r_debug_vaddr = u->d32[i].d_un.d_val; + r_debug_vaddr = d32[i].d_un.d_val; break; } } @@ -999,9 +974,9 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size, { size_t n = dyn_filesz / sizeof (Elf64_Dyn); for (size_t i = 0; i < n; ++i) - if (u->d64[i].d_tag == DT_DEBUG) + if (d64[i].d_tag == DT_DEBUG) { - r_debug_vaddr = u->d64[i].d_un.d_val; + r_debug_vaddr = d64[i].d_un.d_val; break; } } diff --git a/libelf/ChangeLog b/libelf/ChangeLog index bb56e5b..a9685ba 100644 --- a/libelf/ChangeLog +++ b/libelf/ChangeLog @@ -1,3 +1,8 @@ +2015-09-08 Chih-Hung Hsieh + + * elf_getarsym.c (elf_getarsym): Do not use + union of variable length arrays. + 2015-06-18 Mark Wielaard * elf32_updatefile.c (updatefile): Always free shdr_data and scns diff --git a/libelf/elf_getarsym.c b/libelf/elf_getarsym.c index 8324244..6f7bfab 100644 --- a/libelf/elf_getarsym.c +++ b/libelf/elf_getarsym.c @@ -203,11 +203,7 @@ elf_getarsym (elf, ptr) elf->state.ar.ar_sym = (Elf_Arsym *) malloc (ar_sym_len); if (elf->state.ar.ar_sym != NULL) { - union - { - uint32_t u32[n]; - uint64_t u64[n]; - } *file_data; + void *file_data; /* unit32_t[n] or uint64_t[n] */ char *str_data; size_t sz = n * w; @@ -274,7 +270,7 @@ elf_getarsym (elf, ptr) arsym[cnt].as_name = str_data; if (index64_p) { - uint64_t tmp = file_data->u64[cnt]; + uint64_t tmp = ((uint64_t *) file_data)[cnt]; if (__BYTE_ORDER == __LITTLE_ENDIAN) tmp = bswap_64 (tmp); @@ -296,9 +292,9 @@ elf_getarsym (elf, ptr) } } else if (__BYTE_ORDER == __LITTLE_ENDIAN) - arsym[cnt].as_off = bswap_32 (file_data->u32[cnt]); + arsym[cnt].as_off = bswap_32 (((uint32_t *) file_data)[cnt]); else - arsym[cnt].as_off = file_data->u32[cnt]; + arsym[cnt].as_off = ((uint32_t *) file_data)[cnt]; arsym[cnt].as_hash = _dl_elf_hash (str_data); str_data = rawmemchr (str_data, '\0') + 1; diff --git a/src/ChangeLog b/src/ChangeLog index fb92807..1eb3b93 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,12 @@ +2015-09-08 Chih-Hung Hsieh + + * readelf.c (print_cfa_program): Do not use + variable length arrays on stack or in union. + * readelf.c (handle_core_item): Likewise + * readelf.c (handle_core_registers): Likewise + * unstrip.c (find_alloc_sections_prelink): Likewise + * unstrip.c (copy_elided_sections): Likewise + 2015-09-04 Chih-Hung Hsieh * elflint.c (check_group): Replace %Z length modifier with %z. diff --git a/src/readelf.c b/src/readelf.c index 8e64400..6011ad7 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -4943,7 +4943,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp, unsigned int version, unsigned int ptr_size, Dwfl_Module *dwflmod, Ebl *ebl, Dwarf *dbg) { - char regnamebuf[REGNAMESZ]; + char *regnamebuf = alloca (REGNAMESZ); const char *regname (unsigned int regno) { register_info (ebl, regno, NULL, regnamebuf, NULL, NULL); @@ -8378,11 +8378,16 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64); \ DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64) -#define DO_TYPE(NAME, Name, hex, dec) GElf_##Name Name[count] - union { TYPES; } value; +#define DO_TYPE(NAME, Name, hex, dec) GElf_##Name Name + typedef union { TYPES; } value_t; + void *data = alloca (count * sizeof (value_t)); +#undef DO_TYPE + +#define DO_TYPE(NAME, Name, hex, dec) \ + GElf_##Name *value_##Name __attribute__((unused)) = data + TYPES; #undef DO_TYPE - void *data = &value; size_t size = gelf_fsize (core, item->type, count, EV_CURRENT); size_t convsize = size; if (repeated_size != NULL) @@ -8413,7 +8418,7 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, #define DO_TYPE(NAME, Name, hex, dec) \ case ELF_T_##NAME: \ colno = print_core_item (colno, ',', WRAP_COLUMN, \ - 0, item->name, dec, value.Name[0]); \ + 0, item->name, dec, value_##Name[0]); \ break TYPES; #undef DO_TYPE @@ -8429,7 +8434,7 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, #define DO_TYPE(NAME, Name, hex, dec) \ case ELF_T_##NAME: \ colno = print_core_item (colno, ',', WRAP_COLUMN, \ - 0, item->name, hex, value.Name[0]); \ + 0, item->name, hex, value_##Name[0]); \ break TYPES; #undef DO_TYPE @@ -8519,8 +8524,8 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, { #define DO_TYPE(NAME, Name, hex, dec) \ case ELF_T_##NAME: \ - sec = value.Name[0]; \ - usec = value.Name[1]; \ + sec = value_##Name[0]; \ + usec = value_##Name[1]; \ break TYPES; #undef DO_TYPE @@ -8550,12 +8555,12 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, case 'c': assert (count == 1); colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name, - "%c", value.Byte[0]); + "%c", value_Byte[0]); break; case 's': colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name, - "%.*s", (int) count, value.Byte); + "%.*s", (int) count, value_Byte); break; case '\n': @@ -8899,8 +8904,9 @@ handle_core_registers (Ebl *ebl, Elf *core, const void *desc, assert (maxnreg > 0); } - struct register_info regs[maxnreg]; - memset (regs, 0, sizeof regs); + const int sizeof_regs = sizeof (struct register_info) * maxnreg; + struct register_info *regs = alloca (sizeof_regs); + memset (regs, 0, sizeof_regs); /* Sort to collect the sets together. */ int maxreg = 0; diff --git a/src/unstrip.c b/src/unstrip.c index 82bcdd8..a42aad6 100644 --- a/src/unstrip.c +++ b/src/unstrip.c @@ -54,6 +54,10 @@ # define _(str) gettext (str) #endif +#ifndef MAX +# define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + /* Name and version of program. */ static void print_version (FILE *stream, struct argp_state *state); ARGP_PROGRAM_VERSION_HOOK_DEF = print_version; @@ -1013,13 +1017,13 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab, error (EXIT_FAILURE, 0, _("invalid contents in '%s' section"), ".gnu.prelink_undo"); - union - { - Elf32_Shdr s32[shnum - 1]; - Elf64_Shdr s64[shnum - 1]; - } shdr; - dst.d_buf = &shdr; - dst.d_size = sizeof shdr; + const int shdr_bytes = + (shnum - 1) * MAX (sizeof (Elf32_Shdr), sizeof (Elf64_Shdr)); + void *shdr = alloca (shdr_bytes); + Elf32_Shdr *s32 = shdr; + Elf64_Shdr *s64 = shdr; + dst.d_buf = shdr; + dst.d_size = shdr_bytes; ELF_CHECK (gelf_xlatetom (main, &dst, &src, main_ehdr->e_ident[EI_DATA]) != NULL, _("cannot read '.gnu.prelink_undo' section: %s")); @@ -1030,7 +1034,7 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab, struct section *sec = &undo_sections[undo_nalloc]; if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32) { -#define COPY(field) sec->shdr.field = shdr.s32[i].field +#define COPY(field) sec->shdr.field = s32[i].field COPY (sh_name); COPY (sh_type); COPY (sh_flags); @@ -1044,7 +1048,7 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab, #undef COPY } else - sec->shdr = shdr.s64[i]; + sec->shdr = s64[i]; if (sec->shdr.sh_flags & SHF_ALLOC) { sec->shdr.sh_addr += bias; @@ -1260,7 +1264,8 @@ copy_elided_sections (Elf *unstripped, Elf *stripped, more sections in stripped file than debug file -- arguments reversed?")); /* Cache the stripped file's section details. */ - struct section sections[stripped_shnum - 1]; + struct section *sections = + alloca (sizeof (struct section) * (stripped_shnum - 1)); Elf_Scn *scn = NULL; while ((scn = elf_nextscn (stripped, scn)) != NULL) { -- 2.6.0.rc0.131.gf624c3d