Skip to content

Add OpenBSD program headers to elfdump #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion common/elfdefinitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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, \
Expand All @@ -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
Expand Down
25 changes: 14 additions & 11 deletions elfdump/elfdump.c
Original file line number Diff line number Diff line change
Expand Up @@ -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), "<unknown: %#x>", type);
return (s_type);
Expand Down
8 changes: 7 additions & 1 deletion libdwarf/libdwarf_reloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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);
Expand Down
122 changes: 119 additions & 3 deletions readelf/readelf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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");
}
Expand Down Expand Up @@ -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)
{
Expand All @@ -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
Expand All @@ -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);
}
}

Expand Down