diff options
author | emaste <emaste@FreeBSD.org> | 2015-10-09 17:46:05 +0000 |
---|---|---|
committer | emaste <emaste@FreeBSD.org> | 2015-10-09 17:46:05 +0000 |
commit | ac41e8b0a6a86647d95d96654473088399a00a56 (patch) | |
tree | 3bd6905dc0a31e28ae318cfa49b4c6a5691f0ff5 /contrib/elftoolchain/readelf/readelf.c | |
parent | a74309d279605965878b1d80d3466c661c64e2a8 (diff) | |
download | FreeBSD-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/readelf.c')
-rw-r--r-- | contrib/elftoolchain/readelf/readelf.c | 113 |
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; |