diff options
Diffstat (limited to 'readelf/readelf.c')
-rw-r--r-- | readelf/readelf.c | 161 |
1 files changed, 112 insertions, 49 deletions
diff --git a/readelf/readelf.c b/readelf/readelf.c index 0111f1a..3b4b2d3 100644 --- a/readelf/readelf.c +++ b/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); @@ -332,6 +332,7 @@ static const char *note_type_gnu(unsigned int nt); static const char *note_type_netbsd(unsigned int nt); static const char *note_type_openbsd(unsigned int nt); static const char *note_type_unknown(unsigned int nt); +static const char *note_type_xen(unsigned int nt); static const char *option_kind(uint8_t kind); static const char *phdr_type(unsigned int ptype); static const char *ppc_abi_fp(uint64_t fp); @@ -357,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"}, @@ -1170,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"; @@ -1182,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"; @@ -1295,6 +1311,20 @@ r_type(unsigned int mach, unsigned int type) case 22: return "R_MIPS_GOTLO16"; case 30: return "R_MIPS_CALLHI16"; case 31: return "R_MIPS_CALLLO16"; + case 38: return "R_MIPS_TLS_DTPMOD32"; + case 39: return "R_MIPS_TLS_DTPREL32"; + case 40: return "R_MIPS_TLS_DTPMOD64"; + case 41: return "R_MIPS_TLS_DTPREL64"; + case 42: return "R_MIPS_TLS_GD"; + case 43: return "R_MIPS_TLS_LDM"; + case 44: return "R_MIPS_TLS_DTPREL_HI16"; + case 45: return "R_MIPS_TLS_DTPREL_LO16"; + case 46: return "R_MIPS_TLS_GOTTPREL"; + case 47: return "R_MIPS_TLS_TPREL32"; + case 48: return "R_MIPS_TLS_TPREL64"; + case 49: return "R_MIPS_TLS_TPREL_HI16"; + case 50: return "R_MIPS_TLS_TPREL_LO16"; + default: return ""; } case EM_PPC: @@ -1571,6 +1601,8 @@ note_type(const char *name, unsigned int et, unsigned int nt) return note_type_netbsd(nt); else if (strcmp(name, "OpenBSD") == 0 && et != ET_CORE) return note_type_openbsd(nt); + else if (strcmp(name, "Xen") == 0 && et != ET_CORE) + return note_type_xen(nt); return note_type_unknown(nt); } @@ -1679,6 +1711,32 @@ note_type_unknown(unsigned int nt) return (s_nt); } +static const char * +note_type_xen(unsigned int nt) +{ + switch (nt) { + case 0: return "XEN_ELFNOTE_INFO"; + case 1: return "XEN_ELFNOTE_ENTRY"; + case 2: return "XEN_ELFNOTE_HYPERCALL_PAGE"; + case 3: return "XEN_ELFNOTE_VIRT_BASE"; + case 4: return "XEN_ELFNOTE_PADDR_OFFSET"; + case 5: return "XEN_ELFNOTE_XEN_VERSION"; + case 6: return "XEN_ELFNOTE_GUEST_OS"; + case 7: return "XEN_ELFNOTE_GUEST_VERSION"; + case 8: return "XEN_ELFNOTE_LOADER"; + case 9: return "XEN_ELFNOTE_PAE_MODE"; + case 10: return "XEN_ELFNOTE_FEATURES"; + case 11: return "XEN_ELFNOTE_BSD_SYMTAB"; + case 12: return "XEN_ELFNOTE_HV_START_LOW"; + case 13: return "XEN_ELFNOTE_L1_MFN_VALID"; + case 14: return "XEN_ELFNOTE_SUSPEND_CANCEL"; + case 15: return "XEN_ELFNOTE_INIT_P2M"; + case 16: return "XEN_ELFNOTE_MOD_START_PFN"; + case 17: return "XEN_ELFNOTE_SUPPORTED_FEATURES"; + default: return (note_type_unknown(nt)); + } +} + static struct { const char *name; int value; @@ -2804,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"); } @@ -4199,7 +4257,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; @@ -4216,7 +4274,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); } @@ -4224,11 +4282,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; @@ -4245,7 +4303,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++) { @@ -4254,7 +4312,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)); } @@ -4264,7 +4322,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) @@ -4278,21 +4336,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++; @@ -4316,17 +4374,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; } } @@ -4346,22 +4404,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; } } @@ -4372,7 +4430,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; @@ -4393,6 +4451,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); @@ -4403,18 +4462,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; @@ -4426,14 +4485,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); @@ -4796,9 +4855,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); @@ -4830,7 +4889,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: @@ -4849,9 +4908,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: @@ -4868,7 +4927,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", @@ -4876,19 +4935,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; @@ -4921,7 +4980,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: @@ -7411,7 +7470,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; @@ -7420,6 +7479,8 @@ _decode_sleb128(uint8_t **dp) uint8_t *src = *dp; do { + if (src >= dpe) + break; b = *src++; ret |= ((b & 0x7f) << shift); shift += 7; @@ -7434,7 +7495,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; @@ -7443,6 +7504,8 @@ _decode_uleb128(uint8_t **dp) uint8_t *src = *dp; do { + if (src >= dpe) + break; b = *src++; ret |= ((b & 0x7f) << shift); shift += 7; |