diff options
author | emaste <emaste@FreeBSD.org> | 2015-12-11 20:28:27 +0000 |
---|---|---|
committer | emaste <emaste@FreeBSD.org> | 2015-12-11 20:28:27 +0000 |
commit | 8d8726ea868dc8e8e2dbaf693c2933d8aecd6e40 (patch) | |
tree | 0a74d93c155b930ca554757f4e220766fdcea7bc /contrib/elftoolchain/readelf/readelf.c | |
parent | 98fd4878e04a40df20d37039ee02a0fbd5e6e474 (diff) | |
download | FreeBSD-src-8d8726ea868dc8e8e2dbaf693c2933d8aecd6e40.zip FreeBSD-src-8d8726ea868dc8e8e2dbaf693c2933d8aecd6e40.tar.gz |
Update to ELF Tool Chain r3272
Highlights (not already in the FreeBSD tree):
- addr2line: Speed up and support searching inlined functions
- addr2line: Support -i, -a, -p options
- readelf: Add some ARM relocation types
- readelf, libelf: Avoid reading beyond end of buffer/file
Relnotes: Yes
Sponsored by: The FreeBSD Foundation
Diffstat (limited to 'contrib/elftoolchain/readelf/readelf.c')
-rw-r--r-- | contrib/elftoolchain/readelf/readelf.c | 118 |
1 files changed, 69 insertions, 49 deletions
diff --git a/contrib/elftoolchain/readelf/readelf.c b/contrib/elftoolchain/readelf/readelf.c index f197403..d768f6c 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 3250 2015-10-06 13:56:15Z emaste $"); +ELFTC_VCSID("$Id: readelf.c 3271 2015-12-11 18:53:08Z kaiwang27 $"); /* * readelf(1) options. @@ -256,7 +256,7 @@ static const char *dt_type(unsigned int mach, unsigned int dtype); static void dump_ar(struct readelf *re, int); static void dump_arm_attributes(struct readelf *re, uint8_t *p, uint8_t *pe); static void dump_attributes(struct readelf *re); -static uint8_t *dump_compatibility_tag(uint8_t *p); +static uint8_t *dump_compatibility_tag(uint8_t *p, uint8_t *pe); static void dump_dwarf(struct readelf *re); static void dump_dwarf_abbrev(struct readelf *re); static void dump_dwarf_aranges(struct readelf *re); @@ -306,7 +306,7 @@ static void dump_ppc_attributes(uint8_t *p, uint8_t *pe); static void dump_section_groups(struct readelf *re); static void dump_symtab(struct readelf *re, int i); static void dump_symtabs(struct readelf *re); -static uint8_t *dump_unknown_tag(uint64_t tag, uint8_t *p); +static uint8_t *dump_unknown_tag(uint64_t tag, uint8_t *p, uint8_t *pe); static void dump_ver(struct readelf *re); static void dump_verdef(struct readelf *re, int dump); static void dump_verneed(struct readelf *re, int dump); @@ -358,8 +358,8 @@ static uint64_t _read_msb(Elf_Data *d, uint64_t *offsetp, int bytes_to_read); static uint64_t _decode_lsb(uint8_t **data, int bytes_to_read); static uint64_t _decode_msb(uint8_t **data, int bytes_to_read); -static int64_t _decode_sleb128(uint8_t **dp); -static uint64_t _decode_uleb128(uint8_t **dp); +static int64_t _decode_sleb128(uint8_t **dp, uint8_t *dpe); +static uint64_t _decode_uleb128(uint8_t **dp, uint8_t *dpe); static struct eflags_desc arm_eflags_desc[] = { {EF_ARM_RELEXEC, "relocatable executable"}, @@ -1171,10 +1171,14 @@ r_type(unsigned int mach, unsigned int type) case 10: return "R_ARM_THM_PC22"; case 11: return "R_ARM_THM_PC8"; case 12: return "R_ARM_AMP_VCALL9"; - case 13: return "R_ARM_SWI24"; + case 13: return "R_ARM_TLS_DESC"; + /* Obsolete R_ARM_SWI24 is also 13 */ case 14: return "R_ARM_THM_SWI8"; case 15: return "R_ARM_XPC25"; case 16: return "R_ARM_THM_XPC22"; + case 17: return "R_ARM_TLS_DTPMOD32"; + case 18: return "R_ARM_TLS_DTPOFF32"; + case 19: return "R_ARM_TLS_TPOFF32"; case 20: return "R_ARM_COPY"; case 21: return "R_ARM_GLOB_DAT"; case 22: return "R_ARM_JUMP_SLOT"; @@ -1183,6 +1187,17 @@ r_type(unsigned int mach, unsigned int type) case 25: return "R_ARM_GOTPC"; case 26: return "R_ARM_GOT32"; case 27: return "R_ARM_PLT32"; + case 28: return "R_ARM_CALL"; + case 29: return "R_ARM_JUMP24"; + case 30: return "R_ARM_THM_JUMP24"; + case 31: return "R_ARM_BASE_ABS"; + case 38: return "R_ARM_TARGET1"; + case 40: return "R_ARM_V4BX"; + case 42: return "R_ARM_PREL31"; + case 43: return "R_ARM_MOVW_ABS_NC"; + case 44: return "R_ARM_MOVT_ABS"; + case 45: return "R_ARM_MOVW_PREL_NC"; + case 46: return "R_ARM_MOVT_PREL"; case 100: return "R_ARM_GNU_VTENTRY"; case 101: return "R_ARM_GNU_VTINHERIT"; case 250: return "R_ARM_RSBREL32"; @@ -2847,9 +2862,9 @@ dump_phdr(struct readelf *re) printf(" %2.2d ", i); /* skip NULL section. */ for (j = 1; (size_t)j < re->shnum; j++) - if (re->sl[j].off >= phdr.p_offset && - re->sl[j].off + re->sl[j].sz <= - phdr.p_offset + phdr.p_memsz) + if (re->sl[j].addr >= phdr.p_vaddr && + re->sl[j].addr + re->sl[j].sz <= + phdr.p_vaddr + phdr.p_memsz) printf("%s ", re->sl[j].name); printf("\n"); } @@ -4245,7 +4260,7 @@ dump_section_groups(struct readelf *re) } static uint8_t * -dump_unknown_tag(uint64_t tag, uint8_t *p) +dump_unknown_tag(uint64_t tag, uint8_t *p, uint8_t *pe) { uint64_t val; @@ -4262,7 +4277,7 @@ dump_unknown_tag(uint64_t tag, uint8_t *p) printf("%s\n", (char *) p); p += strlen((char *) p) + 1; } else { - val = _decode_uleb128(&p); + val = _decode_uleb128(&p, pe); printf("%ju\n", (uintmax_t) val); } @@ -4270,11 +4285,11 @@ dump_unknown_tag(uint64_t tag, uint8_t *p) } static uint8_t * -dump_compatibility_tag(uint8_t *p) +dump_compatibility_tag(uint8_t *p, uint8_t *pe) { uint64_t val; - val = _decode_uleb128(&p); + val = _decode_uleb128(&p, pe); printf("flag = %ju, vendor = %s\n", val, p); p += strlen((char *) p) + 1; @@ -4291,7 +4306,7 @@ dump_arm_attributes(struct readelf *re, uint8_t *p, uint8_t *pe) (void) re; while (p < pe) { - tag = _decode_uleb128(&p); + tag = _decode_uleb128(&p, pe); found = desc = 0; for (i = 0; i < sizeof(aeabi_tags) / sizeof(aeabi_tags[0]); i++) { @@ -4300,7 +4315,7 @@ dump_arm_attributes(struct readelf *re, uint8_t *p, uint8_t *pe) printf(" %s: ", aeabi_tags[i].s_tag); if (aeabi_tags[i].get_desc) { desc = 1; - val = _decode_uleb128(&p); + val = _decode_uleb128(&p, pe); printf("%s\n", aeabi_tags[i].get_desc(val)); } @@ -4310,7 +4325,7 @@ dump_arm_attributes(struct readelf *re, uint8_t *p, uint8_t *pe) break; } if (!found) { - p = dump_unknown_tag(tag, p); + p = dump_unknown_tag(tag, p, pe); continue; } if (desc) @@ -4324,21 +4339,21 @@ dump_arm_attributes(struct readelf *re, uint8_t *p, uint8_t *pe) p += strlen((char *) p) + 1; break; case 32: /* Tag_compatibility */ - p = dump_compatibility_tag(p); + p = dump_compatibility_tag(p, pe); break; case 64: /* Tag_nodefaults */ /* ignored, written as 0. */ - (void) _decode_uleb128(&p); + (void) _decode_uleb128(&p, pe); printf("True\n"); break; case 65: /* Tag_also_compatible_with */ - val = _decode_uleb128(&p); + val = _decode_uleb128(&p, pe); /* Must be Tag_CPU_arch */ if (val != 6) { printf("unknown\n"); break; } - val = _decode_uleb128(&p); + val = _decode_uleb128(&p, pe); printf("%s\n", aeabi_cpu_arch(val)); /* Skip NUL terminator. */ p++; @@ -4362,17 +4377,17 @@ dump_mips_attributes(struct readelf *re, uint8_t *p, uint8_t *pe) (void) re; while (p < pe) { - tag = _decode_uleb128(&p); + tag = _decode_uleb128(&p, pe); switch (tag) { case Tag_GNU_MIPS_ABI_FP: - val = _decode_uleb128(&p); + val = _decode_uleb128(&p, pe); printf(" Tag_GNU_MIPS_ABI_FP: %s\n", mips_abi_fp(val)); break; case 32: /* Tag_compatibility */ - p = dump_compatibility_tag(p); + p = dump_compatibility_tag(p, pe); break; default: - p = dump_unknown_tag(tag, p); + p = dump_unknown_tag(tag, p, pe); break; } } @@ -4392,22 +4407,22 @@ dump_ppc_attributes(uint8_t *p, uint8_t *pe) uint64_t tag, val; while (p < pe) { - tag = _decode_uleb128(&p); + tag = _decode_uleb128(&p, pe); switch (tag) { case Tag_GNU_Power_ABI_FP: - val = _decode_uleb128(&p); + val = _decode_uleb128(&p, pe); printf(" Tag_GNU_Power_ABI_FP: %s\n", ppc_abi_fp(val)); break; case Tag_GNU_Power_ABI_Vector: - val = _decode_uleb128(&p); + val = _decode_uleb128(&p, pe); printf(" Tag_GNU_Power_ABI_Vector: %s\n", ppc_abi_vector(val)); break; case 32: /* Tag_compatibility */ - p = dump_compatibility_tag(p); + p = dump_compatibility_tag(p, pe); break; default: - p = dump_unknown_tag(tag, p); + p = dump_unknown_tag(tag, p, pe); break; } } @@ -4418,7 +4433,7 @@ dump_attributes(struct readelf *re) { struct section *s; Elf_Data *d; - uint8_t *p, *sp; + uint8_t *p, *pe, *sp; size_t len, seclen, nlen, sublen; uint64_t val; int tag, i, elferr; @@ -4439,6 +4454,7 @@ dump_attributes(struct readelf *re) if (d->d_size <= 0) continue; p = d->d_buf; + pe = p + d->d_size; if (*p != 'A') { printf("Unknown Attribute Section Format: %c\n", (char) *p); @@ -4449,18 +4465,18 @@ dump_attributes(struct readelf *re) while (len > 0) { if (len < 4) { warnx("truncated attribute section length"); - break; + return; } seclen = re->dw_decode(&p, 4); if (seclen > len) { warnx("invalid attribute section length"); - break; + return; } len -= seclen; nlen = strlen((char *) p) + 1; if (nlen + 4 > seclen) { warnx("invalid attribute section name"); - break; + return; } printf("Attribute Section: %s\n", (char *) p); p += nlen; @@ -4472,14 +4488,14 @@ dump_attributes(struct readelf *re) if (sublen > seclen) { warnx("invalid attribute sub-section" " length"); - break; + return; } seclen -= sublen; printf("%s", top_tag(tag)); if (tag == 2 || tag == 3) { putchar(':'); for (;;) { - val = _decode_uleb128(&p); + val = _decode_uleb128(&p, pe); if (val == 0) break; printf(" %ju", (uintmax_t) val); @@ -4842,9 +4858,9 @@ dump_dwarf_line(struct readelf *re) i++; pn = (char *) p; p += strlen(pn) + 1; - dirndx = _decode_uleb128(&p); - mtime = _decode_uleb128(&p); - fsize = _decode_uleb128(&p); + dirndx = _decode_uleb128(&p, pe); + mtime = _decode_uleb128(&p, pe); + fsize = _decode_uleb128(&p, pe); printf(" %d\t%ju\t%ju\t%ju\t%s\n", i, (uintmax_t) dirndx, (uintmax_t) mtime, (uintmax_t) fsize, pn); @@ -4876,7 +4892,7 @@ dump_dwarf_line(struct readelf *re) * Extended Opcodes. */ p++; - opsize = _decode_uleb128(&p); + opsize = _decode_uleb128(&p, pe); printf(" Extended opcode %u: ", *p); switch (*p) { case DW_LNE_end_sequence: @@ -4895,9 +4911,9 @@ dump_dwarf_line(struct readelf *re) p++; pn = (char *) p; p += strlen(pn) + 1; - dirndx = _decode_uleb128(&p); - mtime = _decode_uleb128(&p); - fsize = _decode_uleb128(&p); + dirndx = _decode_uleb128(&p, pe); + mtime = _decode_uleb128(&p, pe); + fsize = _decode_uleb128(&p, pe); printf("define new file: %s\n", pn); break; default: @@ -4914,7 +4930,7 @@ dump_dwarf_line(struct readelf *re) printf(" Copy\n"); break; case DW_LNS_advance_pc: - udelta = _decode_uleb128(&p) * + udelta = _decode_uleb128(&p, pe) * minlen; address += udelta; printf(" Advance PC by %ju to %#jx\n", @@ -4922,19 +4938,19 @@ dump_dwarf_line(struct readelf *re) (uintmax_t) address); break; case DW_LNS_advance_line: - sdelta = _decode_sleb128(&p); + sdelta = _decode_sleb128(&p, pe); line += sdelta; printf(" Advance Line by %jd to %ju\n", (intmax_t) sdelta, (uintmax_t) line); break; case DW_LNS_set_file: - file = _decode_uleb128(&p); + file = _decode_uleb128(&p, pe); printf(" Set File to %ju\n", (uintmax_t) file); break; case DW_LNS_set_column: - column = _decode_uleb128(&p); + column = _decode_uleb128(&p, pe); printf(" Set Column to %ju\n", (uintmax_t) column); break; @@ -4967,7 +4983,7 @@ dump_dwarf_line(struct readelf *re) printf(" Set epilogue begin flag\n"); break; case DW_LNS_set_isa: - isa = _decode_uleb128(&p); + isa = _decode_uleb128(&p, pe); printf(" Set isa to %ju\n", isa); break; default: @@ -7457,7 +7473,7 @@ _decode_msb(uint8_t **data, int bytes_to_read) } static int64_t -_decode_sleb128(uint8_t **dp) +_decode_sleb128(uint8_t **dp, uint8_t *dpe) { int64_t ret = 0; uint8_t b; @@ -7466,6 +7482,8 @@ _decode_sleb128(uint8_t **dp) uint8_t *src = *dp; do { + if (src >= dpe) + break; b = *src++; ret |= ((b & 0x7f) << shift); shift += 7; @@ -7480,7 +7498,7 @@ _decode_sleb128(uint8_t **dp) } static uint64_t -_decode_uleb128(uint8_t **dp) +_decode_uleb128(uint8_t **dp, uint8_t *dpe) { uint64_t ret = 0; uint8_t b; @@ -7489,6 +7507,8 @@ _decode_uleb128(uint8_t **dp) uint8_t *src = *dp; do { + if (src >= dpe) + break; b = *src++; ret |= ((b & 0x7f) << shift); shift += 7; |