summaryrefslogtreecommitdiffstats
path: root/contrib/elftoolchain/readelf
diff options
context:
space:
mode:
authoremaste <emaste@FreeBSD.org>2015-10-09 17:46:05 +0000
committeremaste <emaste@FreeBSD.org>2015-10-09 17:46:05 +0000
commitac41e8b0a6a86647d95d96654473088399a00a56 (patch)
tree3bd6905dc0a31e28ae318cfa49b4c6a5691f0ff5 /contrib/elftoolchain/readelf
parenta74309d279605965878b1d80d3466c661c64e2a8 (diff)
downloadFreeBSD-src-ac41e8b0a6a86647d95d96654473088399a00a56.zip
FreeBSD-src-ac41e8b0a6a86647d95d96654473088399a00a56.tar.gz
Update to ELF Tool Chain r3250
Highlights (not already in the FreeBSD tree): - addr2line: Fixed multiple memory leaks related to DIE allocation - readelf: improve sh_link validation - various man page improvements Sponsored by: The FreeBSD Foundation
Diffstat (limited to 'contrib/elftoolchain/readelf')
-rw-r--r--contrib/elftoolchain/readelf/readelf.c113
1 files changed, 90 insertions, 23 deletions
diff --git a/contrib/elftoolchain/readelf/readelf.c b/contrib/elftoolchain/readelf/readelf.c
index e4ebe26..8e4688a 100644
--- a/contrib/elftoolchain/readelf/readelf.c
+++ b/contrib/elftoolchain/readelf/readelf.c
@@ -47,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.
@@ -1378,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) {
@@ -3179,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)), \
@@ -3204,10 +3252,6 @@ dump_rel(struct readelf *re, struct section *s, Elf_Data *d)
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) {
@@ -3236,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, \
@@ -3262,10 +3309,6 @@ dump_rela(struct readelf *re, struct section *s, Elf_Data *d)
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) {
@@ -3321,9 +3364,13 @@ dump_symtab(struct readelf *re, int i)
Elf_Data *d;
GElf_Sym sym;
const char *name;
- int elferr, stab, j, len;
+ 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) {
@@ -3358,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');
}
@@ -3594,6 +3642,8 @@ 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];
if (!get_ent_count(ds, &dynsymcount))
return;
@@ -3800,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;
@@ -3873,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;
@@ -3937,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;
@@ -3947,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');
}
@@ -4031,6 +4090,8 @@ dump_liblist(struct readelf *re)
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();
@@ -4097,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();
@@ -6669,7 +6732,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);
@@ -6860,6 +6924,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;
OpenPOWER on IntegriCloud