summaryrefslogtreecommitdiffstats
path: root/readelf/readelf.c
diff options
context:
space:
mode:
Diffstat (limited to 'readelf/readelf.c')
-rw-r--r--readelf/readelf.c161
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;
OpenPOWER on IntegriCloud