diff options
author | Ed Maste <emaste@FreeBSD.org> | 2015-10-09 16:43:36 +0000 |
---|---|---|
committer | Ed Maste <emaste@FreeBSD.org> | 2015-10-09 16:43:36 +0000 |
commit | 91b92b626c28ca4664d62bd9c7bc84681d6202e3 (patch) | |
tree | 3204d66ea62cf44f2804254b0f09d779e55564e8 | |
parent | d8a0b3e7b110453a0d5558b4c1128a071b846d3f (diff) |
Notes
-rw-r--r-- | addr2line/addr2line.c | 92 | ||||
-rw-r--r-- | ar/ar.1 | 25 | ||||
-rw-r--r-- | ar/ar.c | 18 | ||||
-rw-r--r-- | brandelf/brandelf.1 | 12 | ||||
-rw-r--r-- | brandelf/brandelf.c | 4 | ||||
-rw-r--r-- | common/_elftc.h | 6 | ||||
-rw-r--r-- | common/elfdefinitions.h | 57 | ||||
-rw-r--r-- | elfcopy/sections.c | 10 | ||||
-rw-r--r-- | elfdump/elfdump.1 | 4 | ||||
-rw-r--r-- | elfdump/elfdump.c | 81 | ||||
-rw-r--r-- | libdwarf/dwarf_sections.c | 6 | ||||
-rw-r--r-- | mk/elftoolchain.inc.mk | 6 | ||||
-rw-r--r-- | mk/os.Darwin.mk | 8 | ||||
-rw-r--r-- | readelf/readelf.c | 178 | ||||
-rw-r--r-- | size/size.c | 3 |
15 files changed, 389 insertions, 121 deletions
diff --git a/addr2line/addr2line.c b/addr2line/addr2line.c index cfdcc745f9fb0..9863fcdc634aa 100644 --- a/addr2line/addr2line.c +++ b/addr2line/addr2line.c @@ -39,7 +39,7 @@ #include "_elftc.h" -ELFTC_VCSID("$Id: addr2line.c 3197 2015-05-12 21:01:31Z emaste $"); +ELFTC_VCSID("$Id: addr2line.c 3249 2015-10-04 08:11:30Z kaiwang27 $"); static struct option longopts[] = { {"target" , required_argument, NULL, 'b'}, @@ -61,7 +61,7 @@ Usage: %s [options] hexaddress...\n\ Map program addresses to source file names and line numbers.\n\n\ Options:\n\ -b TGT | --target=TGT (Accepted but ignored).\n\ - -e EXE | --exec=EXE Use program \"EXE\" to translate addresses.\n\ + -e EXE | --exe=EXE Use program \"EXE\" to translate addresses.\n\ -f | --functions Display function names.\n\ -j NAME | --section=NAME Values are offsets into section \"NAME\".\n\ -s | --basename Only show the base name for each file name.\n\ @@ -123,8 +123,7 @@ handle_high_pc(Dwarf_Die die, Dwarf_Unsigned lopc, Dwarf_Unsigned *hipc) } static void -search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr, - const char **rlt_func) +search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr, char **rlt_func) { Dwarf_Die ret_die, spec_die; Dwarf_Error de; @@ -133,10 +132,11 @@ search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr, Dwarf_Off ref; Dwarf_Attribute sub_at, spec_at; char *func0; + const char *func1; int ret; if (*rlt_func != NULL) - return; + goto done; if (dwarf_tag(die, &tag, &de)) { warnx("dwarf_tag: %s", dwarf_errmsg(de)); @@ -153,16 +153,19 @@ search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr, /* Found it! */ - *rlt_func = unknown; + if ((*rlt_func = strdup(unknown)) == NULL) + err(EXIT_FAILURE, "strdup"); ret = dwarf_attr(die, DW_AT_name, &sub_at, &de); if (ret == DW_DLV_ERROR) - return; + goto done; if (ret == DW_DLV_OK) { - if (dwarf_formstring(sub_at, &func0, &de)) - *rlt_func = unknown; - else - *rlt_func = func0; - return; + if (dwarf_formstring(sub_at, &func0, &de) == + DW_DLV_OK) { + free(*rlt_func); + if ((*rlt_func = strdup(func0)) == NULL) + err(EXIT_FAILURE, "strdup"); + } + goto done; } /* @@ -171,15 +174,19 @@ search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr, * referenced by DW_AT_specification. */ if (dwarf_attr(die, DW_AT_specification, &spec_at, &de)) - return; + goto done; if (dwarf_global_formref(spec_at, &ref, &de)) - return; + goto done; if (dwarf_offdie(dbg, ref, &spec_die, &de)) - return; - if (dwarf_attrval_string(spec_die, DW_AT_name, rlt_func, &de)) - *rlt_func = unknown; + goto done; + if (dwarf_attrval_string(spec_die, DW_AT_name, &func1, &de) == + DW_DLV_OK) { + free(*rlt_func); + if ((*rlt_func = strdup(func1)) == NULL) + err(EXIT_FAILURE, "strdup"); + } - return; + goto done; } cont_search: @@ -197,19 +204,22 @@ cont_search: errx(EXIT_FAILURE, "dwarf_siblingof: %s", dwarf_errmsg(de)); else if (ret == DW_DLV_OK) search_func(dbg, ret_die, addr, rlt_func); + +done: + dwarf_dealloc(dbg, die, DW_DLA_DIE); } static void translate(Dwarf_Debug dbg, const char* addrstr) { - Dwarf_Die die; + Dwarf_Die die, ret_die; Dwarf_Line *lbuf; Dwarf_Error de; Dwarf_Half tag; Dwarf_Unsigned lopc, hipc, addr, lineno, plineno; Dwarf_Signed lcount; Dwarf_Addr lineaddr, plineaddr; - const char *funcname; + char *funcname; char *file, *file0, *pfile; char demangled[1024]; int i, ret; @@ -218,23 +228,29 @@ translate(Dwarf_Debug dbg, const char* addrstr) addr += section_base; lineno = 0; file = unknown; + lbuf = NULL; + lcount = 0; while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, &de)) == DW_DLV_OK) { die = NULL; - while (dwarf_siblingof(dbg, die, &die, &de) == DW_DLV_OK) { + while (dwarf_siblingof(dbg, die, &ret_die, &de) == DW_DLV_OK) { + if (die != NULL) + dwarf_dealloc(dbg, die, DW_DLA_DIE); + die = ret_die; if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { warnx("dwarf_tag failed: %s", dwarf_errmsg(de)); - goto out; + goto next_cu; } + /* XXX: What about DW_TAG_partial_unit? */ if (tag == DW_TAG_compile_unit) break; } - if (die == NULL) { + if (ret_die == NULL) { warnx("could not find DW_TAG_compile_unit die"); - goto out; + goto next_cu; } if (!dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) && !dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de)) { @@ -243,12 +259,18 @@ translate(Dwarf_Debug dbg, const char* addrstr) * this CU. */ if (handle_high_pc(die, lopc, &hipc) != DW_DLV_OK) - continue; + goto next_cu; if (addr < lopc || addr >= hipc) - continue; + goto next_cu; } - if (dwarf_srclines(die, &lbuf, &lcount, &de) != DW_DLV_OK) { + switch (dwarf_srclines(die, &lbuf, &lcount, &de)) { + case DW_DLV_OK: + break; + case DW_DLV_NO_ENTRY: + /* If a CU lacks debug info, just skip it. */ + goto next_cu; + default: warnx("dwarf_srclines: %s", dwarf_errmsg(de)); goto out; } @@ -283,25 +305,37 @@ translate(Dwarf_Debug dbg, const char* addrstr) plineno = lineno; pfile = file; } + next_cu: + if (die != NULL) { + dwarf_dealloc(dbg, die, DW_DLA_DIE); + die = NULL; + } } out: funcname = NULL; - if (ret == DW_DLV_OK && func) + if (ret == DW_DLV_OK && func) { search_func(dbg, die, addr, &funcname); + die = NULL; + } if (func) { if (funcname == NULL) - funcname = unknown; + if ((funcname = strdup(unknown)) == NULL) + err(EXIT_FAILURE, "strdup"); if (demangle && !elftc_demangle(funcname, demangled, sizeof(demangled), 0)) printf("%s\n", demangled); else printf("%s\n", funcname); + free(funcname); } (void) printf("%s:%ju\n", base ? basename(file) : file, lineno); + if (die != NULL) + dwarf_dealloc(dbg, die, DW_DLA_DIE); + /* * Reset internal CU pointer, so we will start from the first CU * next round. @@ -21,9 +21,9 @@ .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: ar.1 3195 2015-05-12 17:22:19Z emaste $ +.\" $Id: ar.1 3230 2015-07-27 17:11:38Z emaste $ .\" -.Dd December 10, 2012 +.Dd July 27, 2015 .Os .Dt AR 1 .Sh NAME @@ -66,6 +66,7 @@ .Op Fl f .Op Fl F Ar flavor | Fl -flavor Ar flavor .Op Fl s | Fl S +.Op Fl U .Op Fl v .Op Fl z .Ar archive @@ -83,6 +84,7 @@ .Op Fl j .Op Fl s | Fl S .Op Fl u +.Op Fl U .Op Fl v .Op Fl z .Ar archive @@ -91,6 +93,7 @@ .Fl s .Op Fl D .Op Fl j +.Op Fl U .Op Fl z .Ar archive .Nm @@ -203,6 +206,11 @@ and 0644 instead of file mode from the members named by arguments .Ar . This ensures that checksums on the resulting archives are reproducible when member contents are identical. +If multiple +.Fl D +and +.Fl U +options are specified on the command line, the final one takes precedence. .It Fl f Synonymous with option .Fl T . @@ -335,6 +343,19 @@ option, the members specified by arguments .Ar will be extracted only if they are newer than the corresponding files in the file system. +.It Fl U +When used in combination with the +.Fl r +or +.Fl q +option, insert the real mtime, uid and gid, and file mode values +from the members named by arguments +.Ar . +If multiple +.Fl D +and +.Fl U +options are specified on the command line, the final one takes precedence. .It Fl v Provide verbose output. When used with the @@ -72,7 +72,7 @@ #include "ar.h" -ELFTC_VCSID("$Id: ar.c 3183 2015-04-10 16:18:42Z emaste $"); +ELFTC_VCSID("$Id: ar.c 3243 2015-08-31 19:28:45Z emaste $"); enum options { @@ -123,7 +123,7 @@ main(int argc, char **argv) len = strlen(bsdar->progname); if (len >= strlen("ranlib") && strcmp(bsdar->progname + len - strlen("ranlib"), "ranlib") == 0) { - while ((opt = getopt_long(argc, argv, "tDV", longopts, + while ((opt = getopt_long(argc, argv, "tDUV", longopts, NULL)) != -1) { switch(opt) { case 't': @@ -132,6 +132,9 @@ main(int argc, char **argv) case 'D': bsdar->options |= AR_D; break; + case 'U': + bsdar->options &= ~AR_D; + break; case 'V': bsdar_version(); break; @@ -148,7 +151,7 @@ main(int argc, char **argv) ranlib_usage(); bsdar->options |= AR_S; - for (;(bsdar->filename = *argv++) != NULL;) + while ((bsdar->filename = *argv++) != NULL) ar_write_archive(bsdar, 's'); exit(EXIT_SUCCESS); @@ -169,7 +172,7 @@ main(int argc, char **argv) } } - while ((opt = getopt_long(argc, argv, "abCcdDfF:ijlMmopqrSsTtuVvxz", + while ((opt = getopt_long(argc, argv, "abCcdDfF:ijlMmopqrSsTtUuVvxz", longopts, NULL)) != -1) { switch(opt) { case 'a': @@ -237,6 +240,9 @@ main(int argc, char **argv) case 't': set_mode(bsdar, opt); break; + case 'U': + bsdar->options &= ~AR_D; + break; case 'u': bsdar->options |= AR_U; break; @@ -400,7 +406,8 @@ Usage: %s <command> [options] archive file...\n\ -D Use fixed metadata, for consistent archive checksums.\n\ -F FORMAT | --flavor=FORMAT\n\ Create archives with the specified format.\n\ - -S Do not generate an archive symbol table.\n" + -S Do not generate an archive symbol table.\n\ + -U Use original metadata, for unique archive checksums.\n" static void bsdar_usage(void) @@ -415,6 +422,7 @@ Usage: %s [options] archive...\n\ Options:\n\ -t (This option is accepted, but ignored).\n\ -D Use fixed metadata, for consistent archive checksums.\n\ + -U Use original metadata, for unique archive checksums.\n\ -V Print a version identifier and exit.\n" static void diff --git a/brandelf/brandelf.1 b/brandelf/brandelf.1 index 1c2e485e44e18..8df5fa8cc86c5 100644 --- a/brandelf/brandelf.1 +++ b/brandelf/brandelf.1 @@ -1,5 +1,4 @@ -.\" Copyright (c) 1997 -.\" John-Mark Gurney. All rights reserved. +.\" Copyright 1997 John-Mark Gurney. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -9,11 +8,8 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the author nor the names of any co-contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. .\" -.\" THIS SOFTWARE IS PROVIDED BY John-Mark Gurney AND CONTRIBUTORS ``AS IS'' +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' .\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE @@ -26,7 +22,7 @@ .\" SUCH DAMAGE. .\" .\" $FreeBSD: src/usr.bin/brandelf/brandelf.1,v 1.17 2007/03/09 14:36:18 ru Exp $ -.\" $Id: brandelf.1 3195 2015-05-12 17:22:19Z emaste $ +.\" $Id: brandelf.1 3235 2015-07-31 16:44:47Z emaste $ .\" .Dd October 27, 2014 .Dt BRANDELF 1 @@ -148,4 +144,4 @@ manual page first appeared in .Fx 2.2 . .Sh AUTHORS This manual page was written by -.An John-Mark Gurney Aq Mt gurney_j@efn.org . +.An John-Mark Gurney Aq Mt jmg@FreeBSD.org . diff --git a/brandelf/brandelf.c b/brandelf/brandelf.c index 5f5e6317b7b68..cbe5d6cabbb21 100644 --- a/brandelf/brandelf.c +++ b/brandelf/brandelf.c @@ -1,7 +1,7 @@ /*- * Copyright (c) 2008 Hyogeol Lee * Copyright (c) 2000, 2001 David O'Brien - * Copyright (c) 1996 Søren Schmidt + * Copyright (c) 1996 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,7 +44,7 @@ #include "_elftc.h" -ELFTC_VCSID("$Id: brandelf.c 3174 2015-03-27 17:13:41Z emaste $"); +ELFTC_VCSID("$Id: brandelf.c 3234 2015-07-31 12:35:09Z emaste $"); static int elftype(const char *); static const char *iselftype(int); diff --git a/common/_elftc.h b/common/_elftc.h index 6769519a16d63..94272ef6aba0b 100644 --- a/common/_elftc.h +++ b/common/_elftc.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: _elftc.h 3209 2015-05-17 13:40:46Z kaiwang27 $ + * $Id: _elftc.h 3244 2015-08-31 19:53:08Z emaste $ */ /** @@ -372,7 +372,8 @@ extern const char *__progname; #if defined(__APPLE__) -#include <machine/endian.h> +#include <libkern/OSByteOrder.h> +#define htobe32(x) OSSwapHostToBigInt32(x) #define roundup2 roundup #define ELFTC_BYTE_ORDER _BYTE_ORDER @@ -382,6 +383,7 @@ extern const char *__progname; #define ELFTC_HAVE_MMAP 1 #define ELFTC_HAVE_STRMODE 1 +#define ELFTC_NEED_BYTEORDER_EXTENSIONS 1 #endif /* __APPLE__ */ diff --git a/common/elfdefinitions.h b/common/elfdefinitions.h index 58554fef2ebf3..ab7001fb82e76 100644 --- a/common/elfdefinitions.h +++ b/common/elfdefinitions.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: elfdefinitions.h 3198 2015-05-14 18:36:19Z emaste $ + * $Id: elfdefinitions.h 3247 2015-09-22 16:57:51Z emaste $ */ /* @@ -813,7 +813,8 @@ _ELF_DEFINE_EM(EM_KM32, 210, "KM211 KM32 32-bit processor") \ _ELF_DEFINE_EM(EM_KMX32, 211, "KM211 KMX32 32-bit processor") \ _ELF_DEFINE_EM(EM_KMX16, 212, "KM211 KMX16 16-bit processor") \ _ELF_DEFINE_EM(EM_KMX8, 213, "KM211 KMX8 8-bit processor") \ -_ELF_DEFINE_EM(EM_KVARC, 214, "KM211 KMX32 KVARC processor") +_ELF_DEFINE_EM(EM_KVARC, 214, "KM211 KMX32 KVARC processor") \ +_ELF_DEFINE_EM(EM_RISCV, 243, "RISC-V") #undef _ELF_DEFINE_EM #define _ELF_DEFINE_EM(N, V, DESCR) N = V , @@ -859,6 +860,12 @@ enum { #define GRP_MASKPROC 0xf0000000 /* processor-specific flags */ /* + * Flags / mask for .gnu.versym sections. + */ +#define VERSYM_VERSION 0x7fff +#define VERSYM_HIDDEN 0x8000 + +/* * Flags used by program header table entries. */ @@ -1182,6 +1189,8 @@ _ELF_DEFINE_SHT(SHT_MIPS_XLATE_OLD, 0x70000028UL, \ "obsolete") \ _ELF_DEFINE_SHT(SHT_MIPS_PDR_EXCEPTION, 0x70000029UL, \ "runtime procedure descriptor table exception information") \ +_ELF_DEFINE_SHT(SHT_MIPS_ABIFLAGS, 0x7000002AUL, \ + "ABI flags") \ _ELF_DEFINE_SHT(SHT_SPARC_GOTDATA, 0x70000000UL, \ "SPARC-specific data") \ _ELF_DEFINE_SHT(SHT_AMD64_UNWIND, 0x70000001UL, \ @@ -1864,6 +1873,50 @@ _ELF_DEFINE_RELOC(R_PPC64_DTPREL16_HIGHESTA, 106) \ _ELF_DEFINE_RELOC(R_PPC64_TLSGD, 107) \ _ELF_DEFINE_RELOC(R_PPC64_TLSLD, 108) +#define _ELF_DEFINE_RISCV_RELOCATIONS() \ +_ELF_DEFINE_RELOC(R_RISCV_NONE, 0) \ +_ELF_DEFINE_RELOC(R_RISCV_32, 1) \ +_ELF_DEFINE_RELOC(R_RISCV_64, 2) \ +_ELF_DEFINE_RELOC(R_RISCV_RELATIVE, 3) \ +_ELF_DEFINE_RELOC(R_RISCV_COPY, 4) \ +_ELF_DEFINE_RELOC(R_RISCV_JUMP_SLOT, 5) \ +_ELF_DEFINE_RELOC(R_RISCV_TLS_DTPMOD32, 6) \ +_ELF_DEFINE_RELOC(R_RISCV_TLS_DTPMOD64, 7) \ +_ELF_DEFINE_RELOC(R_RISCV_TLS_DTPREL32, 8) \ +_ELF_DEFINE_RELOC(R_RISCV_TLS_DTPREL64, 9) \ +_ELF_DEFINE_RELOC(R_RISCV_TLS_TPREL32, 10) \ +_ELF_DEFINE_RELOC(R_RISCV_TLS_TPREL64, 11) \ +_ELF_DEFINE_RELOC(R_RISCV_BRANCH, 16) \ +_ELF_DEFINE_RELOC(R_RISCV_JAL, 17) \ +_ELF_DEFINE_RELOC(R_RISCV_CALL, 18) \ +_ELF_DEFINE_RELOC(R_RISCV_CALL_PLT, 19) \ +_ELF_DEFINE_RELOC(R_RISCV_GOT_HI20, 20) \ +_ELF_DEFINE_RELOC(R_RISCV_TLS_GOT_HI20, 21) \ +_ELF_DEFINE_RELOC(R_RISCV_TLS_GD_HI20, 22) \ +_ELF_DEFINE_RELOC(R_RISCV_PCREL_HI20, 23) \ +_ELF_DEFINE_RELOC(R_RISCV_PCREL_LO12_I, 24) \ +_ELF_DEFINE_RELOC(R_RISCV_PCREL_LO12_S, 25) \ +_ELF_DEFINE_RELOC(R_RISCV_HI20, 26) \ +_ELF_DEFINE_RELOC(R_RISCV_LO12_I, 27) \ +_ELF_DEFINE_RELOC(R_RISCV_LO12_S, 28) \ +_ELF_DEFINE_RELOC(R_RISCV_TPREL_HI20, 29) \ +_ELF_DEFINE_RELOC(R_RISCV_TPREL_LO12_I, 30) \ +_ELF_DEFINE_RELOC(R_RISCV_TPREL_LO12_S, 31) \ +_ELF_DEFINE_RELOC(R_RISCV_TPREL_ADD, 32) \ +_ELF_DEFINE_RELOC(R_RISCV_ADD8, 33) \ +_ELF_DEFINE_RELOC(R_RISCV_ADD16, 34) \ +_ELF_DEFINE_RELOC(R_RISCV_ADD32, 35) \ +_ELF_DEFINE_RELOC(R_RISCV_ADD64, 36) \ +_ELF_DEFINE_RELOC(R_RISCV_SUB8, 37) \ +_ELF_DEFINE_RELOC(R_RISCV_SUB16, 38) \ +_ELF_DEFINE_RELOC(R_RISCV_SUB32, 39) \ +_ELF_DEFINE_RELOC(R_RISCV_SUB64, 40) \ +_ELF_DEFINE_RELOC(R_RISCV_GNU_VTINHERIT, 41) \ +_ELF_DEFINE_RELOC(R_RISCV_GNU_VTENTRY, 42) \ +_ELF_DEFINE_RELOC(R_RISCV_ALIGN 43) \ +_ELF_DEFINE_RELOC(R_RISCV_RVC_BRANCH, 44) \ +_ELF_DEFINE_RELOC(R_RISCV_RVC_JUMP, 45) + #define _ELF_DEFINE_SPARC_RELOCATIONS() \ _ELF_DEFINE_RELOC(R_SPARC_NONE, 0) \ _ELF_DEFINE_RELOC(R_SPARC_8, 1) \ diff --git a/elfcopy/sections.c b/elfcopy/sections.c index b417646ae557a..f1ec6c0f80233 100644 --- a/elfcopy/sections.c +++ b/elfcopy/sections.c @@ -34,7 +34,7 @@ #include "elfcopy.h" -ELFTC_VCSID("$Id: sections.c 3220 2015-05-24 23:42:39Z kaiwang27 $"); +ELFTC_VCSID("$Id: sections.c 3225 2015-06-06 02:35:23Z kaiwang27 $"); static void add_gnu_debuglink(struct elfcopy *ecp); static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc); @@ -1346,6 +1346,14 @@ set_shstrtab(struct elfcopy *ecp) s = ecp->shstrtab; + if (s->os == NULL) { + /* Input object does not contain .shstrtab section */ + if ((s->os = elf_newscn(ecp->eout)) == NULL) + errx(EXIT_FAILURE, "elf_newscn failed: %s", + elf_errmsg(-1)); + insert_to_sec_list(ecp, s, 1); + } + if (gelf_getshdr(s->os, &sh) == NULL) errx(EXIT_FAILURE, "692 gelf_getshdr() failed: %s", elf_errmsg(-1)); diff --git a/elfdump/elfdump.1 b/elfdump/elfdump.1 index eae7262900a84..e586ab23c56de 100644 --- a/elfdump/elfdump.1 +++ b/elfdump/elfdump.1 @@ -23,7 +23,7 @@ .\" SUCH DAMAGE. .\" .\" $FreeBSD: src/usr.bin/elfdump/elfdump.1,v 1.6 2005/01/18 13:43:48 ru Exp $ -.\" $Id: elfdump.1 3195 2015-05-12 17:22:19Z emaste $ +.\" $Id: elfdump.1 3231 2015-07-30 13:47:56Z emaste $ .\" .Dd August 25, 2011 .Dt ELFDUMP 1 @@ -54,7 +54,7 @@ The options are as follows: .It Fl a Dump all information. .It Fl c -Dump shared headers. +Dump section headers. .It Fl d Dump dynamic symbols. .It Fl e diff --git a/elfdump/elfdump.c b/elfdump/elfdump.c index e4e565bdd5c58..baf99eee1e908 100644 --- a/elfdump/elfdump.c +++ b/elfdump/elfdump.c @@ -50,7 +50,7 @@ #include "_elftc.h" -ELFTC_VCSID("$Id: elfdump.c 3198 2015-05-14 18:36:19Z emaste $"); +ELFTC_VCSID("$Id: elfdump.c 3250 2015-10-06 13:56:15Z emaste $"); #if defined(ELFTC_NEED_ELF_NOTE_DEFINITION) #include "native-elf-format.h" @@ -205,11 +205,11 @@ d_tags(uint64_t tag) case 0x6ffffef5: return "DT_GNU_HASH"; case 0x6ffffef8: return "DT_GNU_CONFLICT"; case 0x6ffffef9: return "DT_GNU_LIBLIST"; - case 0x6ffffefa: return "DT_SUNW_CONFIG"; - case 0x6ffffefb: return "DT_SUNW_DEPAUDIT"; - case 0x6ffffefc: return "DT_SUNW_AUDIT"; - case 0x6ffffefd: return "DT_SUNW_PLTPAD"; - case 0x6ffffefe: return "DT_SUNW_MOVETAB"; + case 0x6ffffefa: return "DT_CONFIG"; + case 0x6ffffefb: return "DT_DEPAUDIT"; + case 0x6ffffefc: return "DT_AUDIT"; + case 0x6ffffefd: return "DT_PLTPAD"; + case 0x6ffffefe: return "DT_MOVETAB"; case 0x6ffffeff: return "DT_SYMINFO (DT_ADDRRNGHI)"; case 0x6ffffff9: return "DT_RELACOUNT"; case 0x6ffffffa: return "DT_RELCOUNT"; @@ -244,11 +244,14 @@ e_machines(unsigned int mach) case EM_860: return "EM_860"; case EM_MIPS: return "EM_MIPS"; case EM_PPC: return "EM_PPC"; + case EM_PPC64: return "EM_PPC64"; case EM_ARM: return "EM_ARM"; case EM_ALPHA: return "EM_ALPHA (legacy)"; case EM_SPARCV9:return "EM_SPARCV9"; case EM_IA_64: return "EM_IA_64"; case EM_X86_64: return "EM_X86_64"; + case EM_AARCH64:return "EM_AARCH64"; + case EM_RISCV: return "EM_RISCV"; } snprintf(machdesc, sizeof(machdesc), "(unknown machine) -- type 0x%x", mach); @@ -271,11 +274,12 @@ static const char *ei_data[] = { "ELFDATANONE", "ELFDATA2LSB", "ELFDATA2MSB" }; -static const char *ei_abis[] = { - "ELFOSABI_SYSV", "ELFOSABI_HPUX", "ELFOSABI_NETBSD", "ELFOSABI_LINUX", - "ELFOSABI_HURD", "ELFOSABI_86OPEN", "ELFOSABI_SOLARIS", - "ELFOSABI_MONTEREY", "ELFOSABI_IRIX", "ELFOSABI_FREEBSD", - "ELFOSABI_TRU64", "ELFOSABI_MODESTO", "ELFOSABI_OPENBSD" +static const char *ei_abis[256] = { + "ELFOSABI_NONE", "ELFOSABI_HPUX", "ELFOSABI_NETBSD", "ELFOSABI_LINUX", + "ELFOSABI_HURD", "ELFOSABI_86OPEN", "ELFOSABI_SOLARIS", "ELFOSABI_AIX", + "ELFOSABI_IRIX", "ELFOSABI_FREEBSD", "ELFOSABI_TRU64", + "ELFOSABI_MODESTO", "ELFOSABI_OPENBSD", + [255] = "ELFOSABI_STANDALONE" }; static const char *p_types[] = { @@ -330,6 +334,7 @@ sh_types(u_int64_t sht) { case 18: return "SHT_SYMTAB_SHNDX"; /* 0x60000000 - 0x6fffffff operating system-specific semantics */ case 0x6ffffff0: return "XXX:VERSYM"; + case 0x6ffffff4: return "SHT_SUNW_dof"; case 0x6ffffff6: return "SHT_GNU_HASH"; case 0x6ffffff7: return "SHT_GNU_LIBLIST"; case 0x6ffffffc: return "XXX:VERDEF"; @@ -818,6 +823,7 @@ static void elf_print_checksum(struct elfdump *ed); static void find_gotrel(struct elfdump *ed, struct section *gs, struct rel_entry *got); static struct spec_name *find_name(struct elfdump *ed, const char *name); +static int get_ent_count(const struct section *s, int *ent_count); static const char *get_symbol_name(struct elfdump *ed, int symtab, int i); static const char *get_string(struct elfdump *ed, int strtab, size_t off); static void get_versym(struct elfdump *ed, int i, uint16_t **vs, int *nvs); @@ -1626,6 +1632,24 @@ elf_print_shdr(struct elfdump *ed) } /* + * Return number of entries in the given section. We'd prefer ent_count be a + * size_t, but libelf APIs already use int for section indices. + */ +static int +get_ent_count(const struct section *s, int *ent_count) +{ + if (s->entsize == 0) { + warnx("section %s has entry size 0", s->name); + return (0); + } else if (s->sz / s->entsize > INT_MAX) { + warnx("section %s has invalid section count", s->name); + return (0); + } + *ent_count = (int)(s->sz / s->entsize); + return (1); +} + +/* * Retrieve the content of the corresponding SHT_SUNW_versym section for * a symbol table section. */ @@ -1656,7 +1680,9 @@ get_versym(struct elfdump *ed, int i, uint16_t **vs, int *nvs) } *vs = data->d_buf; - *nvs = data->d_size / s->entsize; + assert(data->d_size == s->sz); + if (!get_ent_count(s, nvs)) + *nvs = 0; } /* @@ -1687,7 +1713,9 @@ elf_print_symtab(struct elfdump *ed, int i) } vs = NULL; nvs = 0; - len = data->d_size / s->entsize; + assert(data->d_size == s->sz); + if (!get_ent_count(s, &len)) + return; if (ed->flags & SOLARIS_FMT) { if (ed->ec == ELFCLASS32) PRT(" index value "); @@ -1786,7 +1814,9 @@ elf_print_dynamic(struct elfdump *ed) warnx("elf_getdata failed: %s", elf_errmsg(elferr)); return; } - len = data->d_size / s->entsize; + assert(data->d_size == s->sz); + if (!get_ent_count(s, &len)) + return; for (i = 0; i < len; i++) { if (gelf_getdyn(data, i, &dyn) != &dyn) { warnx("gelf_getdyn failed: %s", elf_errmsg(-1)); @@ -1912,7 +1942,9 @@ elf_print_rela(struct elfdump *ed, struct section *s, Elf_Data *data) } else PRT("\nrelocation with addend (%s):\n", s->name); r.type = SHT_RELA; - len = data->d_size / s->entsize; + assert(data->d_size == s->sz); + if (!get_ent_count(s, &len)) + return; for (j = 0; j < len; j++) { if (gelf_getrela(data, j, &r.u_r.rela) != &r.u_r.rela) { warnx("gelf_getrela failed: %s", @@ -1941,7 +1973,9 @@ elf_print_rel(struct elfdump *ed, struct section *s, Elf_Data *data) } else PRT("\nrelocation (%s):\n", s->name); r.type = SHT_REL; - len = data->d_size / s->entsize; + assert(data->d_size == s->sz); + if (!get_ent_count(s, &len)) + return; for (j = 0; j < len; j++) { if (gelf_getrel(data, j, &r.u_r.rel) != &r.u_r.rel) { warnx("gelf_getrel failed: %s", elf_errmsg(-1)); @@ -2042,7 +2076,9 @@ find_gotrel(struct elfdump *ed, struct section *gs, struct rel_entry *got) } memset(&r, 0, sizeof(struct rel_entry)); r.type = s->type; - len = data->d_size / s->entsize; + assert(data->d_size == s->sz); + if (!get_ent_count(s, &len)) + return; for (j = 0; j < len; j++) { if (s->type == SHT_REL) { if (gelf_getrel(data, j, &r.u_r.rel) != @@ -2086,9 +2122,11 @@ elf_print_got_section(struct elfdump *ed, struct section *s) return; } + if (!get_ent_count(s, &len)) + return; if (ed->flags & SOLARIS_FMT) - PRT("\nGlobal Offset Table Section: %s (%jd entries)\n", - s->name, s->sz / s->entsize); + PRT("\nGlobal Offset Table Section: %s (%d entries)\n", + s->name, len); else PRT("\nglobal offset table: %s\n", s->name); (void) elf_errno(); @@ -2115,7 +2153,7 @@ elf_print_got_section(struct elfdump *ed, struct section *s) warnx("gelf_xlatetom failed: %s", elf_errmsg(-1)); return; } - len = dst.d_size / s->entsize; + assert(dst.d_size == s->sz); if (ed->flags & SOLARIS_FMT) { /* * In verbose/Solaris mode, we search the relocation sections @@ -2503,7 +2541,8 @@ elf_print_gnu_hash(struct elfdump *ed, struct section *s) shift2 = buf[3]; buf += 4; ds = &ed->sl[s->link]; - dynsymcount = ds->sz / ds->entsize; + if (!get_ent_count(ds, &dynsymcount)) + return; nchain = dynsymcount - symndx; if (data->d_size != 4 * sizeof(uint32_t) + maskwords * (ed->ec == ELFCLASS32 ? sizeof(uint32_t) : sizeof(uint64_t)) + diff --git a/libdwarf/dwarf_sections.c b/libdwarf/dwarf_sections.c index d3c1379378feb..dc676a383b863 100644 --- a/libdwarf/dwarf_sections.c +++ b/libdwarf/dwarf_sections.c @@ -26,7 +26,7 @@ #include "_libdwarf.h" -ELFTC_VCSID("$Id: dwarf_sections.c 3036 2014-05-05 19:19:31Z kaiwang27 $"); +ELFTC_VCSID("$Id: dwarf_sections.c 3226 2015-06-23 13:00:16Z emaste $"); #define SET(N, V) \ do { \ @@ -104,8 +104,8 @@ dwarf_get_section_max_offsets(Dwarf_Debug dbg, Dwarf_Unsigned *debug_info, Dwarf_Unsigned *debug_ranges, Dwarf_Unsigned *debug_pubtypes) { - return (dwarf_get_section_max_offsets(dbg, debug_info, debug_abbrev, + return (dwarf_get_section_max_offsets_b(dbg, debug_info, debug_abbrev, debug_line, debug_loc, debug_aranges, debug_macinfo, debug_pubnames, debug_str, debug_frame, debug_ranges, - debug_pubtypes)); + debug_pubtypes, NULL)); } diff --git a/mk/elftoolchain.inc.mk b/mk/elftoolchain.inc.mk index 2d93c69e54cf2..86f51bcd42def 100644 --- a/mk/elftoolchain.inc.mk +++ b/mk/elftoolchain.inc.mk @@ -1,7 +1,7 @@ # # Rules for handling include files. # -# $Id: elftoolchain.inc.mk 2608 2012-10-03 09:16:11Z jkoshy $ +# $Id: elftoolchain.inc.mk 3245 2015-08-31 19:54:13Z emaste $ .if !defined(TOP) .error Make variable \"TOP\" has not been defined. @@ -11,8 +11,8 @@ .include <bsd.own.mk> -.if ${OS_HOST} == "DragonFly" || ${OS_HOST} == "FreeBSD" || \ - ${OS_HOST} == "OpenBSD" +.if ${OS_HOST} == "Darwin" || ${OS_HOST} == "DragonFly" || \ + ${OS_HOST} == "FreeBSD" || ${OS_HOST} == "OpenBSD" # Simulate <bsd.inc.mk>. NOBINMODE?= 444 # Missing in OpenBSD's rule set. diff --git a/mk/os.Darwin.mk b/mk/os.Darwin.mk new file mode 100644 index 0000000000000..450c671abda32 --- /dev/null +++ b/mk/os.Darwin.mk @@ -0,0 +1,8 @@ +# $Id$ +# +# Build definitions for Darwin + +# Apple ships libarchive, but for some reason does not provide the headers. +# Build against a homebrew-provided libarchive library and headers. +LDFLAGS+= -L/usr/local/opt/libarchive/lib +CFLAGS+= -I/usr/local/opt/libarchive/include diff --git a/readelf/readelf.c b/readelf/readelf.c index 31d7e1316f385..0111f1a593763 100644 --- a/readelf/readelf.c +++ b/readelf/readelf.c @@ -27,6 +27,7 @@ #include <sys/param.h> #include <sys/queue.h> #include <ar.h> +#include <assert.h> #include <ctype.h> #include <dwarf.h> #include <err.h> @@ -46,7 +47,7 @@ #include "_elftc.h" -ELFTC_VCSID("$Id: readelf.c 3223 2015-05-25 20:37:57Z emaste $"); +ELFTC_VCSID("$Id: readelf.c 3250 2015-10-06 13:56:15Z emaste $"); /* * readelf(1) options. @@ -314,6 +315,7 @@ static const char *dwarf_reg(unsigned int mach, unsigned int reg); static const char *dwarf_regname(struct readelf *re, unsigned int num); static struct dumpop *find_dumpop(struct readelf *re, size_t si, const char *sn, int op, int t); +static int get_ent_count(struct section *s, int *ent_count); static char *get_regoff_str(struct readelf *re, Dwarf_Half reg, Dwarf_Addr off); static const char *get_string(struct readelf *re, int strtab, size_t off); @@ -412,8 +414,8 @@ elf_osabi(unsigned int abi) static char s_abi[32]; switch(abi) { - case ELFOSABI_SYSV: return "SYSV"; - case ELFOSABI_HPUX: return "HPUS"; + case ELFOSABI_NONE: return "NONE"; + case ELFOSABI_HPUX: return "HPUX"; case ELFOSABI_NETBSD: return "NetBSD"; case ELFOSABI_GNU: return "GNU"; case ELFOSABI_HURD: return "HURD"; @@ -532,6 +534,7 @@ elf_machine(unsigned int mach) case EM_ARCA: return "Arca RISC Microprocessor"; case EM_UNICORE: return "Microprocessor series from PKU-Unity Ltd"; case EM_AARCH64: return "AArch64"; + case EM_RISCV: return "RISC-V"; default: snprintf(s_mach, sizeof(s_mach), "<unknown: %#x>", mach); return (s_mach); @@ -1375,6 +1378,51 @@ r_type(unsigned int mach, unsigned int type) case 116: return "R_PPC_EMB_RELSDA"; default: return ""; } + case EM_RISCV: + switch(type) { + case 0: return "R_RISCV_NONE"; + case 1: return "R_RISCV_32"; + case 2: return "R_RISCV_64"; + case 3: return "R_RISCV_RELATIVE"; + case 4: return "R_RISCV_COPY"; + case 5: return "R_RISCV_JUMP_SLOT"; + case 6: return "R_RISCV_TLS_DTPMOD32"; + case 7: return "R_RISCV_TLS_DTPMOD64"; + case 8: return "R_RISCV_TLS_DTPREL32"; + case 9: return "R_RISCV_TLS_DTPREL64"; + case 10: return "R_RISCV_TLS_TPREL32"; + case 11: return "R_RISCV_TLS_TPREL64"; + case 16: return "R_RISCV_BRANCH"; + case 17: return "R_RISCV_JAL"; + case 18: return "R_RISCV_CALL"; + case 19: return "R_RISCV_CALL_PLT"; + case 20: return "R_RISCV_GOT_HI20"; + case 21: return "R_RISCV_TLS_GOT_HI20"; + case 22: return "R_RISCV_TLS_GD_HI20"; + case 23: return "R_RISCV_PCREL_HI20"; + case 24: return "R_RISCV_PCREL_LO12_I"; + case 25: return "R_RISCV_PCREL_LO12_S"; + case 26: return "R_RISCV_HI20"; + case 27: return "R_RISCV_LO12_I"; + case 28: return "R_RISCV_LO12_S"; + case 29: return "R_RISCV_TPREL_HI20"; + case 30: return "R_RISCV_TPREL_LO12_I"; + case 31: return "R_RISCV_TPREL_LO12_S"; + case 32: return "R_RISCV_TPREL_ADD"; + case 33: return "R_RISCV_ADD8"; + case 34: return "R_RISCV_ADD16"; + case 35: return "R_RISCV_ADD32"; + case 36: return "R_RISCV_ADD64"; + case 37: return "R_RISCV_SUB8"; + case 38: return "R_RISCV_SUB16"; + case 39: return "R_RISCV_SUB32"; + case 40: return "R_RISCV_SUB64"; + case 41: return "R_RISCV_GNU_VTINHERIT"; + case 42: return "R_RISCV_GNU_VTENTRY"; + case 43: return "R_RISCV_ALIGN"; + case 44: return "R_RISCV_RVC_BRANCH"; + case 45: return "R_RISCV_RVC_JUMP"; + } case EM_SPARC: case EM_SPARCV9: switch(type) { @@ -2900,6 +2948,24 @@ dump_shdr(struct readelf *re) #undef ST_CTL } +/* + * Return number of entries in the given section. We'd prefer ent_count be a + * size_t *, but libelf APIs already use int for section indices. + */ +static int +get_ent_count(struct section *s, int *ent_count) +{ + if (s->entsize == 0) { + warnx("section %s has entry size 0", s->name); + return (0); + } else if (s->sz / s->entsize > INT_MAX) { + warnx("section %s has invalid section count", s->name); + return (0); + } + *ent_count = (int)(s->sz / s->entsize); + return (1); +} + static void dump_dynamic(struct readelf *re) { @@ -2928,8 +2994,8 @@ dump_dynamic(struct readelf *re) /* Determine the actual number of table entries. */ nentries = 0; - jmax = (int) (s->sz / s->entsize); - + if (!get_ent_count(s, &jmax)) + continue; for (j = 0; j < jmax; j++) { if (gelf_getdyn(d, j, &dyn) != &dyn) { warnx("gelf_getdyn failed: %s", @@ -3158,6 +3224,9 @@ dump_rel(struct readelf *re, struct section *s, Elf_Data *d) uint64_t symval; int i, len; + if (s->link >= re->shnum) + return; + #define REL_HDR "r_offset", "r_info", "r_type", "st_value", "st_name" #define REL_CT32 (uintmax_t)r.r_offset, (uintmax_t)r.r_info, \ r_type(re->ehdr.e_machine, ELF32_R_TYPE(r.r_info)), \ @@ -3175,16 +3244,14 @@ dump_rel(struct readelf *re, struct section *s, Elf_Data *d) else printf("%-12s %-12s %-19s %-16s %s\n", REL_HDR); } - len = d->d_size / s->entsize; + assert(d->d_size == s->sz); + if (!get_ent_count(s, &len)) + return; for (i = 0; i < len; i++) { if (gelf_getrel(d, i, &r) != &r) { warnx("gelf_getrel failed: %s", elf_errmsg(-1)); continue; } - if (s->link >= re->shnum) { - warnx("invalid section link index %u", s->link); - continue; - } symname = get_symbol_name(re, s->link, GELF_R_SYM(r.r_info)); symval = get_symbol_value(re, s->link, GELF_R_SYM(r.r_info)); if (re->ec == ELFCLASS32) { @@ -3213,6 +3280,9 @@ dump_rela(struct readelf *re, struct section *s, Elf_Data *d) uint64_t symval; int i, len; + if (s->link >= re->shnum) + return; + #define RELA_HDR "r_offset", "r_info", "r_type", "st_value", \ "st_name + r_addend" #define RELA_CT32 (uintmax_t)r.r_offset, (uintmax_t)r.r_info, \ @@ -3231,16 +3301,14 @@ dump_rela(struct readelf *re, struct section *s, Elf_Data *d) else printf("%-12s %-12s %-19s %-16s %s\n", RELA_HDR); } - len = d->d_size / s->entsize; + assert(d->d_size == s->sz); + if (!get_ent_count(s, &len)) + return; for (i = 0; i < len; i++) { if (gelf_getrela(d, i, &r) != &r) { warnx("gelf_getrel failed: %s", elf_errmsg(-1)); continue; } - if (s->link >= re->shnum) { - warnx("invalid section link index %u", s->link); - continue; - } symname = get_symbol_name(re, s->link, GELF_R_SYM(r.r_info)); symval = get_symbol_value(re, s->link, GELF_R_SYM(r.r_info)); if (re->ec == ELFCLASS32) { @@ -3296,9 +3364,13 @@ dump_symtab(struct readelf *re, int i) Elf_Data *d; GElf_Sym sym; const char *name; - int elferr, stab, j; + uint32_t stab; + int elferr, j, len; + uint16_t vs; s = &re->sl[i]; + if (s->link >= re->shnum) + return; stab = s->link; (void) elf_errno(); if ((d = elf_getdata(s->scn, NULL)) == NULL) { @@ -3309,12 +3381,14 @@ dump_symtab(struct readelf *re, int i) } if (d->d_size <= 0) return; + if (!get_ent_count(s, &len)) + return; printf("Symbol table (%s)", s->name); - printf(" contains %ju entries:\n", s->sz / s->entsize); + printf(" contains %d entries:\n", len); printf("%7s%9s%14s%5s%8s%6s%9s%5s\n", "Num:", "Value", "Size", "Type", "Bind", "Vis", "Ndx", "Name"); - for (j = 0; (uint64_t)j < s->sz / s->entsize; j++) { + for (j = 0; j < len; j++) { if (gelf_getsym(d, j, &sym) != &sym) { warnx("gelf_getsym failed: %s", elf_errmsg(-1)); continue; @@ -3331,14 +3405,15 @@ dump_symtab(struct readelf *re, int i) /* Append symbol version string for SHT_DYNSYM symbol table. */ if (s->type == SHT_DYNSYM && re->ver != NULL && re->vs != NULL && re->vs[j] > 1) { - if (re->vs[j] & 0x8000 || - re->ver[re->vs[j] & 0x7fff].type == 0) - printf("@%s (%d)", - re->ver[re->vs[j] & 0x7fff].name, - re->vs[j] & 0x7fff); + vs = re->vs[j] & VERSYM_VERSION; + if (vs >= re->ver_sz || re->ver[vs].name == NULL) { + warnx("invalid versym version index %u", vs); + break; + } + if (re->vs[j] & VERSYM_HIDDEN || re->ver[vs].type == 0) + printf("@%s (%d)", re->ver[vs].name, vs); else - printf("@@%s (%d)", re->ver[re->vs[j]].name, - re->vs[j]); + printf("@@%s (%d)", re->ver[vs].name, vs); } putchar('\n'); } @@ -3352,7 +3427,7 @@ dump_symtabs(struct readelf *re) Elf_Data *d; struct section *s; uint64_t dyn_off; - int elferr, i; + int elferr, i, len; /* * If -D is specified, only dump the symbol table specified by @@ -3377,8 +3452,10 @@ dump_symtabs(struct readelf *re) } if (d->d_size <= 0) return; + if (!get_ent_count(s, &len)) + return; - for (i = 0; (uint64_t)i < s->sz / s->entsize; i++) { + for (i = 0; i < len; i++) { if (gelf_getdyn(d, i, &dyn) != &dyn) { warnx("gelf_getdyn failed: %s", elf_errmsg(-1)); continue; @@ -3565,8 +3642,11 @@ dump_gnu_hash(struct readelf *re, struct section *s) symndx = buf[1]; maskwords = buf[2]; buf += 4; + if (s->link >= re->shnum) + return; ds = &re->sl[s->link]; - dynsymcount = ds->sz / ds->entsize; + if (!get_ent_count(ds, &dynsymcount)) + return; nchain = dynsymcount - symndx; if (d->d_size != 4 * sizeof(uint32_t) + maskwords * (re->ec == ELFCLASS32 ? sizeof(uint32_t) : sizeof(uint64_t)) + @@ -3770,6 +3850,8 @@ dump_verdef(struct readelf *re, int dump) if ((s = re->vd_s) == NULL) return; + if (s->link >= re->shnum) + return; if (re->ver == NULL) { re->ver_sz = 16; @@ -3843,6 +3925,8 @@ dump_verneed(struct readelf *re, int dump) if ((s = re->vn_s) == NULL) return; + if (s->link >= re->shnum) + return; if (re->ver == NULL) { re->ver_sz = 16; @@ -3907,6 +3991,7 @@ static void dump_versym(struct readelf *re) { int i; + uint16_t vs; if (re->vs_s == NULL || re->ver == NULL || re->vs == NULL) return; @@ -3917,12 +4002,16 @@ dump_versym(struct readelf *re) putchar('\n'); printf(" %03x:", i); } - if (re->vs[i] & 0x8000) - printf(" %3xh %-12s ", re->vs[i] & 0x7fff, - re->ver[re->vs[i] & 0x7fff].name); + vs = re->vs[i] & VERSYM_VERSION; + if (vs >= re->ver_sz || re->ver[vs].name == NULL) { + warnx("invalid versym version index %u", re->vs[i]); + break; + } + if (re->vs[i] & VERSYM_HIDDEN) + printf(" %3xh %-12s ", vs, + re->ver[re->vs[i] & VERSYM_VERSION].name); else - printf(" %3x %-12s ", re->vs[i], - re->ver[re->vs[i]].name); + printf(" %3x %-12s ", vs, re->ver[re->vs[i]].name); } putchar('\n'); } @@ -3995,12 +4084,14 @@ dump_liblist(struct readelf *re) char tbuf[20]; Elf_Data *d; Elf_Lib *lib; - int i, j, k, elferr, first; + int i, j, k, elferr, first, len; for (i = 0; (size_t) i < re->shnum; i++) { s = &re->sl[i]; if (s->type != SHT_GNU_LIBLIST) continue; + if (s->link >= re->shnum) + continue; (void) elf_errno(); if ((d = elf_getdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); @@ -4012,8 +4103,10 @@ dump_liblist(struct readelf *re) if (d->d_size <= 0) continue; lib = d->d_buf; + if (!get_ent_count(s, &len)) + continue; printf("\nLibrary list section '%s' ", s->name); - printf("contains %ju entries:\n", s->sz / s->entsize); + printf("contains %d entries:\n", len); printf("%12s%24s%18s%10s%6s\n", "Library", "Time Stamp", "Checksum", "Version", "Flags"); for (j = 0; (uint64_t) j < s->sz / s->entsize; j++) { @@ -4065,6 +4158,8 @@ dump_section_groups(struct readelf *re) s = &re->sl[i]; if (s->type != SHT_GROUP) continue; + if (s->link >= re->shnum) + continue; (void) elf_errno(); if ((d = elf_getdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); @@ -4395,7 +4490,7 @@ static void dump_mips_reginfo(struct readelf *re, struct section *s) { Elf_Data *d; - int elferr; + int elferr, len; (void) elf_errno(); if ((d = elf_rawdata(s->scn, NULL)) == NULL) { @@ -4407,9 +4502,10 @@ dump_mips_reginfo(struct readelf *re, struct section *s) } if (d->d_size <= 0) return; + if (!get_ent_count(s, &len)) + return; - printf("\nSection '%s' contains %ju entries:\n", s->name, - s->sz / s->entsize); + printf("\nSection '%s' contains %d entries:\n", s->name, len); dump_mips_odk_reginfo(re, d->d_buf, d->d_size); } @@ -6633,7 +6729,8 @@ get_symbol_name(struct readelf *re, int symtab, int i) if (GELF_ST_TYPE(sym.st_info) == STT_SECTION && re->sl[sym.st_shndx].name != NULL) return (re->sl[sym.st_shndx].name); - if ((name = elf_strptr(re->elf, s->link, sym.st_name)) == NULL) + if (s->link >= re->shnum || + (name = elf_strptr(re->elf, s->link, sym.st_name)) == NULL) return (""); return (name); @@ -6824,6 +6921,9 @@ load_sections(struct readelf *re) warnx("section index of '%s' out of range", name); continue; } + if (sh.sh_link >= re->shnum) + warnx("section link %llu of '%s' out of range", + (unsigned long long)sh.sh_link, name); s = &re->sl[ndx]; s->name = name; s->scn = scn; diff --git a/size/size.c b/size/size.c index 1d91d500146b0..be7fbf4de34b7 100644 --- a/size/size.c +++ b/size/size.c @@ -38,7 +38,7 @@ #include "_elftc.h" -ELFTC_VCSID("$Id: size.c 3183 2015-04-10 16:18:42Z emaste $"); +ELFTC_VCSID("$Id: size.c 3242 2015-08-07 12:47:11Z emaste $"); #define BUF_SIZE 1024 #define ELF_ALIGN(val,x) (((val)+(x)-1) & ~((x)-1)) @@ -440,7 +440,6 @@ handle_phdr(Elf *elf, GElf_Ehdr *elfhdr, GElf_Phdr *phdr, if (elf == NULL || elfhdr == NULL || phdr == NULL) return; - size = addr = 0; split = (phdr->p_memsz > 0) && (phdr->p_filesz > 0) && (phdr->p_memsz > phdr->p_filesz); |