diff --git a/common/elfdefinitions.h b/common/elfdefinitions.h index 0c207226..dabc9b52 100644 --- a/common/elfdefinitions.h +++ b/common/elfdefinitions.h @@ -72,7 +72,23 @@ _ELF_DEFINE_DF(DF_TEXTREL, 0x4, \ _ELF_DEFINE_DF(DF_BIND_NOW, 0x8, \ "process relocation entries at load time") \ _ELF_DEFINE_DF(DF_STATIC_TLS, 0x10, \ - "uses static thread-local storage") + "uses static thread-local storage") \ +_ELF_DEFINE_DF(DF_1_BIND_NOW, 0x1, \ + "process relocation entries at load time") \ +_ELF_DEFINE_DF(DF_1_GLOBAL, 0x2, \ + "") \ +_ELF_DEFINE_DF(DF_1_NODELETE, 0x8, \ + "") \ +_ELF_DEFINE_DF(DF_1_LOADFLTR, 0x10, \ + "") \ +_ELF_DEFINE_DF(DF_1_NOOPEN, 0x40, \ + "") \ +_ELF_DEFINE_DF(DF_1_ORIGIN, 0x80, \ + "") \ +_ELF_DEFINE_DF(DF_1_INTERPOSE, 0x400, \ + "") \ +_ELF_DEFINE_DF(DF_1_NODEFLIB, 0x800, \ + "") #undef _ELF_DEFINE_DF #define _ELF_DEFINE_DF(N, V, DESCR) N = V , enum { @@ -2434,6 +2450,9 @@ enum { #define _ELF_DEFINE_NOTE_ENTRY_TYPES() \ _ELF_DEFINE_NT(NT_ABI_TAG, 1, "Tag indicating the ABI") \ +_ELF_DEFINE_NT(NT_FREEBSD_NOINIT_TAG, 2, "") \ +_ELF_DEFINE_NT(NT_FREEBSD_ARCH_TAG, 3, "") \ +_ELF_DEFINE_NT(NT_FREEBSD_FEATURE_CTL, 4, "") \ _ELF_DEFINE_NT(NT_GNU_HWCAP, 2, "Hardware capabilities") \ _ELF_DEFINE_NT(NT_GNU_BUILD_ID, 3, "Build id, set by ld(1)") \ _ELF_DEFINE_NT(NT_GNU_GOLD_VERSION, 4, \ @@ -2457,6 +2476,8 @@ enum { NT__LAST__ }; +#define NT_FREEBSD_FCTL_ASLR_DISABLE 1 + /* Aliases for the ABI tag. */ #define NT_FREEBSD_ABI_TAG NT_ABI_TAG #define NT_GNU_ABI_TAG NT_ABI_TAG diff --git a/elfdump/elfdump.c b/elfdump/elfdump.c index fd85ed7b..1911fbad 100644 --- a/elfdump/elfdump.c +++ b/elfdump/elfdump.c @@ -343,17 +343,20 @@ elf_phdr_type_str(unsigned int type) static char s_type[32]; switch (type) { - case PT_NULL: return "PT_NULL"; - case PT_LOAD: return "PT_LOAD"; - case PT_DYNAMIC: return "PT_DYNAMIC"; - case PT_INTERP: return "PT_INTERP"; - case PT_NOTE: return "PT_NOTE"; - case PT_SHLIB: return "PT_SHLIB"; - case PT_PHDR: return "PT_PHDR"; - case PT_TLS: return "PT_TLS"; - case PT_GNU_EH_FRAME: return "PT_GNU_EH_FRAME"; - case PT_GNU_STACK: return "PT_GNU_STACK"; - case PT_GNU_RELRO: return "PT_GNU_RELRO"; + case PT_NULL: return "PT_NULL"; + case PT_LOAD: return "PT_LOAD"; + case PT_DYNAMIC: return "PT_DYNAMIC"; + case PT_INTERP: return "PT_INTERP"; + case PT_NOTE: return "PT_NOTE"; + case PT_SHLIB: return "PT_SHLIB"; + case PT_PHDR: return "PT_PHDR"; + case PT_TLS: return "PT_TLS"; + case PT_GNU_EH_FRAME: return "PT_GNU_EH_FRAME"; + case PT_GNU_STACK: return "PT_GNU_STACK"; + case PT_GNU_RELRO: return "PT_GNU_RELRO"; + case PT_OPENBSD_RANDOMIZE: return "PT_OPENBSD_RANDOMIZE"; + case PT_OPENBSD_WXNEEDED: return "PT_OPENBSD_WXNEEDED"; + case PT_OPENBSD_BOOTDATA: return "PT_OPENBSD_BOOTDATA"; } snprintf(s_type, sizeof(s_type), "", type); return (s_type); diff --git a/libdwarf/libdwarf_reloc.c b/libdwarf/libdwarf_reloc.c index 996c2706..690b5b95 100644 --- a/libdwarf/libdwarf_reloc.c +++ b/libdwarf/libdwarf_reloc.c @@ -44,7 +44,7 @@ _dwarf_get_reloc_type(Dwarf_P_Debug dbg, int is64) case DW_ISA_SPARC: return (is64 ? R_SPARC_UA64 : R_SPARC_UA32); case DW_ISA_PPC: - return (R_PPC_ADDR32); + return (is64 ? R_PPC64_ADDR64 : R_PPC_ADDR32); case DW_ISA_ARM: return (R_ARM_ABS32); case DW_ISA_MIPS: @@ -97,6 +97,12 @@ _dwarf_get_reloc_size(Dwarf_Debug dbg, Dwarf_Unsigned rel_type) if (rel_type == R_PPC_ADDR32) return (4); break; + case EM_PPC64: + if (rel_type == R_PPC_ADDR32) + return (4); + else if (rel_type == R_PPC64_ADDR64) + return (8); + break; case EM_MIPS: if (rel_type == R_MIPS_32) return (4); diff --git a/readelf/readelf.c b/readelf/readelf.c index 4cbf3465..f82f1fec 100644 --- a/readelf/readelf.c +++ b/readelf/readelf.c @@ -211,6 +211,11 @@ struct mips_option { const char *desc; }; +struct flag_desc { + uint64_t flag; + const char *desc; +}; + static void add_dumpop(struct readelf *re, size_t si, const char *sn, int op, int t); static const char *aeabi_adv_simd_arch(uint64_t simd); @@ -284,6 +289,7 @@ static void dump_dwarf_ranges_foreach(struct readelf *re, Dwarf_Die die, static void dump_dwarf_str(struct readelf *re); static void dump_eflags(struct readelf *re, uint64_t e_flags); static void dump_elf(struct readelf *re); +static void dump_flags(struct flag_desc *fd, uint64_t flags); static void dump_dyn_val(struct readelf *re, GElf_Dyn *dyn, uint32_t stab); static void dump_dynamic(struct readelf *re); static void dump_liblist(struct readelf *re); @@ -298,6 +304,8 @@ static void dump_mips_specific_info(struct readelf *re); static void dump_notes(struct readelf *re); static void dump_notes_content(struct readelf *re, const char *buf, size_t sz, off_t off); +static void dump_notes_data(const char *name, uint32_t type, const char *buf, + size_t sz); static void dump_svr4_hash(struct section *s); static void dump_svr4_hash64(struct readelf *re, struct section *s); static void dump_gnu_hash(struct readelf *re, struct section *s); @@ -2713,6 +2721,59 @@ dump_arch_dyn_val(struct readelf *re, GElf_Dyn *dyn) } } +static void +dump_flags(struct flag_desc *desc, uint64_t val) +{ + struct flag_desc *fd; + + for (fd = desc; fd->flag != 0; fd++) { + if (val & fd->flag) { + val &= ~fd->flag; + printf(" %s", fd->desc); + } + } + if (val != 0) + printf(" unknown (0x%jx)", (uintmax_t)val); + printf("\n"); +} + +static struct flag_desc dt_flags[] = { + { DF_ORIGIN, "ORIGIN" }, + { DF_SYMBOLIC, "SYMBOLIC" }, + { DF_TEXTREL, "TEXTREL" }, + { DF_BIND_NOW, "BIND_NOW" }, + { DF_STATIC_TLS, "STATIC_TLS" }, + { 0, NULL } +}; + +static struct flag_desc dt_flags_1[] = { + { DF_1_BIND_NOW, "NOW" }, + { DF_1_GLOBAL, "GLOBAL" }, + { 0x4, "GROUP" }, + { DF_1_NODELETE, "NODELETE" }, + { DF_1_LOADFLTR, "LOADFLTR" }, + { 0x20, "INITFIRST" }, + { DF_1_NOOPEN, "NOOPEN" }, + { DF_1_ORIGIN, "ORIGIN" }, + { 0x100, "DIRECT" }, + { DF_1_INTERPOSE, "INTERPOSE" }, + { DF_1_NODEFLIB, "NODEFLIB" }, + { 0x1000, "NODUMP" }, + { 0x2000, "CONFALT" }, + { 0x4000, "ENDFILTEE" }, + { 0x8000, "DISPRELDNE" }, + { 0x10000, "DISPRELPND" }, + { 0x20000, "NODIRECT" }, + { 0x40000, "IGNMULDEF" }, + { 0x80000, "NOKSYMS" }, + { 0x100000, "NOHDR" }, + { 0x200000, "EDITED" }, + { 0x400000, "NORELOC" }, + { 0x800000, "SYMINTPOSE" }, + { 0x1000000, "GLOBAUDIT" }, + { 0, NULL } +}; + static void dump_dyn_val(struct readelf *re, GElf_Dyn *dyn, uint32_t stab) { @@ -2796,6 +2857,12 @@ dump_dyn_val(struct readelf *re, GElf_Dyn *dyn, uint32_t stab) case DT_GNU_PRELINKED: printf(" %s\n", timestamp(dyn->d_un.d_val)); break; + case DT_FLAGS: + dump_flags(dt_flags, dyn->d_un.d_val); + break; + case DT_FLAGS_1: + dump_flags(dt_flags_1, dyn->d_un.d_val); + break; default: printf("\n"); } @@ -3414,6 +3481,53 @@ dump_notes(struct readelf *re) } } +static struct flag_desc note_feature_ctl_flags[] = { + { NT_FREEBSD_FCTL_ASLR_DISABLE, "ASLR_DISABLE" }, + { 0, NULL } +}; + +static void +dump_notes_data(const char *name, uint32_t type, const char *buf, size_t sz) +{ + size_t i; + const uint32_t *ubuf; + + /* Note data is at least 4-byte aligned. */ + if (((uintptr_t)buf & 3) != 0) { + warnx("bad note data alignment"); + goto unknown; + } + ubuf = (const uint32_t *)(const void *)buf; + + if (strcmp(name, "FreeBSD") == 0) { + switch (type) { + case NT_FREEBSD_ABI_TAG: + if (sz != 4) + goto unknown; + printf(" ABI tag: %u\n", ubuf[0]); + return; + /* NT_FREEBSD_NOINIT_TAG carries no data, treat as unknown. */ + case NT_FREEBSD_ARCH_TAG: + if (sz != 4) + goto unknown; + printf(" Arch tag: %x\n", ubuf[0]); + return; + case NT_FREEBSD_FEATURE_CTL: + if (sz != 4) + goto unknown; + printf(" Features:"); + dump_flags(note_feature_ctl_flags, ubuf[0]); + printf("\n"); + return; + } + } +unknown: + printf(" description data:"); + for (i = 0; i < sz; i++) + printf(" %02x", (unsigned char)buf[i]); + printf("\n"); +} + static void dump_notes_content(struct readelf *re, const char *buf, size_t sz, off_t off) { @@ -3430,7 +3544,9 @@ dump_notes_content(struct readelf *re, const char *buf, size_t sz, off_t off) return; } note = (Elf_Note *)(uintptr_t) buf; - name = (char *)(uintptr_t)(note + 1); + buf += sizeof(Elf_Note); + name = buf; + buf += roundup2(note->n_namesz, 4); /* * The name field is required to be nul-terminated, and * n_namesz includes the terminating nul in observed @@ -3448,8 +3564,8 @@ dump_notes_content(struct readelf *re, const char *buf, size_t sz, off_t off) printf(" %-13s %#010jx", name, (uintmax_t) note->n_descsz); printf(" %s\n", note_type(name, re->ehdr.e_type, note->n_type)); - buf += sizeof(Elf_Note) + roundup2(note->n_namesz, 4) + - roundup2(note->n_descsz, 4); + dump_notes_data(name, note->n_type, buf, note->n_descsz); + buf += roundup2(note->n_descsz, 4); } }