Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 20 Mar 2007 15:51:23 +0100
From:      Kai Wang <kaiwang27@gmail.com>
To:        current@freebsd.org
Subject:   A rewriting of the elfdump utility
Message-ID:  <20070320145123.GA2518@plan0.kaiwan.csbnet.se>

next in thread | raw e-mail | index | archive | help

--YiEDa0DAkWCtVeE4
Content-Type: text/plain; charset=gb2312
Content-Disposition: inline

Hi there,

This patch is a rewriting of elfdump utility using the libelf library.
Major improvements include:

* Support for extended numbering.
* Support for symbol hash table dump.

It also fixes several bugs of the old elfdump when handling 64bit ELF
binary.

Test I've done:

1. make universe
2. apply both the old elfdump and the new one to the
   huge amount of ".o" and executables produced by the
   "make universe" and compare the results.

The patch has been reviewed by jkoshy@ and I think it may be
time for a public review.

(patch against /usr/src/usr.bin/elfdump in -CURRENT)

Thank you!

Best Regards,
Kai Wang


--YiEDa0DAkWCtVeE4
Content-Type: text/x-diff; charset=gb2312
Content-Disposition: attachment; filename="elfdump.diff"

diff -urN elfdump/Makefile elfdump.new/Makefile
--- elfdump/Makefile	Tue Mar 20 13:44:59 2007
+++ elfdump.new/Makefile	Mon Mar 19 13:40:10 2007
@@ -3,4 +3,6 @@
 PROG=	elfdump
 WARNS?=	5
 
+LDADD=	-lelf
+
 .include <bsd.prog.mk>
diff -urN elfdump/elfdump.1 elfdump.new/elfdump.1
--- elfdump/elfdump.1	Tue Mar 20 13:44:59 2007
+++ elfdump.new/elfdump.1	Mon Mar 19 13:49:59 2007
@@ -103,6 +103,8 @@
 utility
 was written by
 .An Jake Burkholder Aq jake@FreeBSD.org .
+Later it was rewritten based on the
+libelf library.
 This
 manual page was written by
 .An David O'Brien Aq obrien@FreeBSD.org .
diff -urN elfdump/elfdump.c elfdump.new/elfdump.c
--- elfdump/elfdump.c	Tue Mar 20 13:44:59 2007
+++ elfdump.new/elfdump.c	Tue Mar 20 13:07:06 2007
@@ -28,18 +28,15 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD: src/usr.bin/elfdump/elfdump.c,v 1.14 2006/01/28 17:58:22 marcel Exp $");
 
-#include <sys/types.h>
-#include <sys/elf32.h>
-#include <sys/elf64.h>
-#include <sys/endian.h>
-#include <sys/mman.h>
+#include <sys/param.h>
 #include <sys/stat.h>
 #include <err.h>
 #include <fcntl.h>
+#include <gelf.h>
 #include <inttypes.h>
-#include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <sysexits.h>
 #include <string.h>
 #include <unistd.h>
 
@@ -55,116 +52,6 @@
 #define	ED_SYMTAB	(1<<9)
 #define	ED_ALL		((1<<10)-1)
 
-#define	elf_get_addr	elf_get_quad
-#define	elf_get_off	elf_get_quad
-#define	elf_get_size	elf_get_quad
-
-enum elf_member {
-	D_TAG = 1, D_PTR, D_VAL,
-
-	E_CLASS, E_DATA, E_OSABI, E_TYPE, E_MACHINE, E_VERSION, E_ENTRY,
-	E_PHOFF, E_SHOFF, E_FLAGS, E_EHSIZE, E_PHENTSIZE, E_PHNUM, E_SHENTSIZE,
-	E_SHNUM, E_SHSTRNDX,
-
-	N_NAMESZ, N_DESCSZ, N_TYPE,
-
-	P_TYPE, P_OFFSET, P_VADDR, P_PADDR, P_FILESZ, P_MEMSZ, P_FLAGS,
-	P_ALIGN,
-
-	SH_NAME, SH_TYPE, SH_FLAGS, SH_ADDR, SH_OFFSET, SH_SIZE, SH_LINK,
-	SH_INFO, SH_ADDRALIGN, SH_ENTSIZE,
-
-	ST_NAME, ST_VALUE, ST_SIZE, ST_INFO, ST_SHNDX,
-
-	R_OFFSET, R_INFO,
-
-	RA_OFFSET, RA_INFO, RA_ADDEND
-};
-
-typedef enum elf_member elf_member_t;
-
-int elf32_offsets[] = {
-	0,
-
-	offsetof(Elf32_Dyn, d_tag), offsetof(Elf32_Dyn, d_un.d_ptr),
-	offsetof(Elf32_Dyn, d_un.d_val),
-
-	offsetof(Elf32_Ehdr, e_ident[EI_CLASS]),
-	offsetof(Elf32_Ehdr, e_ident[EI_DATA]),
-	offsetof(Elf32_Ehdr, e_ident[EI_OSABI]),
-	offsetof(Elf32_Ehdr, e_type), offsetof(Elf32_Ehdr, e_machine),
-	offsetof(Elf32_Ehdr, e_version), offsetof(Elf32_Ehdr, e_entry),
-	offsetof(Elf32_Ehdr, e_phoff), offsetof(Elf32_Ehdr, e_shoff),
-	offsetof(Elf32_Ehdr, e_flags), offsetof(Elf32_Ehdr, e_ehsize),
-	offsetof(Elf32_Ehdr, e_phentsize), offsetof(Elf32_Ehdr, e_phnum),
-	offsetof(Elf32_Ehdr, e_shentsize), offsetof(Elf32_Ehdr, e_shnum),
-	offsetof(Elf32_Ehdr, e_shstrndx),
-
-	offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz),
-	offsetof(Elf_Note, n_type),
-
-	offsetof(Elf32_Phdr, p_type), offsetof(Elf32_Phdr, p_offset),
-	offsetof(Elf32_Phdr, p_vaddr), offsetof(Elf32_Phdr, p_paddr),
-	offsetof(Elf32_Phdr, p_filesz), offsetof(Elf32_Phdr, p_memsz),
-	offsetof(Elf32_Phdr, p_flags), offsetof(Elf32_Phdr, p_align),
-
-	offsetof(Elf32_Shdr, sh_name), offsetof(Elf32_Shdr, sh_type),
-	offsetof(Elf32_Shdr, sh_flags), offsetof(Elf32_Shdr, sh_addr),
-	offsetof(Elf32_Shdr, sh_offset), offsetof(Elf32_Shdr, sh_size),
-	offsetof(Elf32_Shdr, sh_link), offsetof(Elf32_Shdr, sh_info),
-	offsetof(Elf32_Shdr, sh_addralign), offsetof(Elf32_Shdr, sh_entsize),
-
-	offsetof(Elf32_Sym, st_name), offsetof(Elf32_Sym, st_value),
-	offsetof(Elf32_Sym, st_size), offsetof(Elf32_Sym, st_info),
-	offsetof(Elf32_Sym, st_shndx),
-
-	offsetof(Elf32_Rel, r_offset), offsetof(Elf32_Rel, r_info),
-
-	offsetof(Elf32_Rela, r_offset), offsetof(Elf32_Rela, r_info),
-	offsetof(Elf32_Rela, r_addend)
-};
-
-int elf64_offsets[] = {
-	0,
-
-	offsetof(Elf64_Dyn, d_tag), offsetof(Elf64_Dyn, d_un.d_ptr),
-	offsetof(Elf64_Dyn, d_un.d_val),
-
-	offsetof(Elf32_Ehdr, e_ident[EI_CLASS]),
-	offsetof(Elf32_Ehdr, e_ident[EI_DATA]),
-	offsetof(Elf32_Ehdr, e_ident[EI_OSABI]),
-	offsetof(Elf64_Ehdr, e_type), offsetof(Elf64_Ehdr, e_machine),
-	offsetof(Elf64_Ehdr, e_version), offsetof(Elf64_Ehdr, e_entry),
-	offsetof(Elf64_Ehdr, e_phoff), offsetof(Elf64_Ehdr, e_shoff),
-	offsetof(Elf64_Ehdr, e_flags), offsetof(Elf64_Ehdr, e_ehsize),
-	offsetof(Elf64_Ehdr, e_phentsize), offsetof(Elf64_Ehdr, e_phnum),
-	offsetof(Elf64_Ehdr, e_shentsize), offsetof(Elf64_Ehdr, e_shnum),
-	offsetof(Elf64_Ehdr, e_shstrndx),
-
-	offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz),
-	offsetof(Elf_Note, n_type),
-
-	offsetof(Elf64_Phdr, p_type), offsetof(Elf64_Phdr, p_offset),
-	offsetof(Elf64_Phdr, p_vaddr), offsetof(Elf64_Phdr, p_paddr),
-	offsetof(Elf64_Phdr, p_filesz), offsetof(Elf64_Phdr, p_memsz),
-	offsetof(Elf64_Phdr, p_flags), offsetof(Elf64_Phdr, p_align),
-
-	offsetof(Elf64_Shdr, sh_name), offsetof(Elf64_Shdr, sh_type),
-	offsetof(Elf64_Shdr, sh_flags), offsetof(Elf64_Shdr, sh_addr),
-	offsetof(Elf64_Shdr, sh_offset), offsetof(Elf64_Shdr, sh_size),
-	offsetof(Elf64_Shdr, sh_link), offsetof(Elf64_Shdr, sh_info),
-	offsetof(Elf64_Shdr, sh_addralign), offsetof(Elf64_Shdr, sh_entsize),
-
-	offsetof(Elf64_Sym, st_name), offsetof(Elf64_Sym, st_value),
-	offsetof(Elf64_Sym, st_size), offsetof(Elf64_Sym, st_info),
-	offsetof(Elf64_Sym, st_shndx),
-
-	offsetof(Elf64_Rel, r_offset), offsetof(Elf64_Rel, r_info),
-
-	offsetof(Elf64_Rela, r_offset), offsetof(Elf64_Rela, r_info),
-	offsetof(Elf64_Rela, r_addend)
-};
-
 /* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#tag_encodings */
 static const char *
 d_tags(u_int64_t tag) {
@@ -351,53 +238,40 @@
 	"STB_LOCAL", "STB_GLOBAL", "STB_WEAK"
 };
 
-char *dynstr;
-char *shstrtab;
-char *strtab;
-FILE *out;
-
-u_int64_t elf_get_byte(Elf32_Ehdr *e, void *base, elf_member_t member);
-u_int64_t elf_get_quarter(Elf32_Ehdr *e, void *base, elf_member_t member);
-u_int64_t elf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member);
-u_int64_t elf_get_word(Elf32_Ehdr *e, void *base, elf_member_t member);
-u_int64_t elf_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member);
-
-void elf_print_ehdr(Elf32_Ehdr *e);
-void elf_print_phdr(Elf32_Ehdr *e, void *p);
-void elf_print_shdr(Elf32_Ehdr *e, void *sh);
-void elf_print_symtab(Elf32_Ehdr *e, void *sh, char *str);
-void elf_print_dynamic(Elf32_Ehdr *e, void *sh);
-void elf_print_rel(Elf32_Ehdr *e, void *r);
-void elf_print_rela(Elf32_Ehdr *e, void *ra);
-void elf_print_interp(Elf32_Ehdr *e, void *p);
-void elf_print_got(Elf32_Ehdr *e, void *sh);
-void elf_print_hash(Elf32_Ehdr *e, void *sh);
-void elf_print_note(Elf32_Ehdr *e, void *sh);
+size_t		 shstrndx;
+size_t		 strtab;
+size_t		 dynstr;
+FILE		*out;
+
+void		elf_print_ehdr(Elf * e);
+void		elf_print_phdr(Elf * e);
+void		elf_print_shdr(Elf * e);
+void		elf_print_symtab(Elf * e, Elf_Scn * scn, size_t strndx);
+void		elf_print_interp(Elf * e, Elf64_Off p_offset);
+void		elf_print_dynamic(Elf * e, Elf_Scn * scn);
+void		elf_print_rela(Elf * e, Elf_Scn * scn);
+void		elf_print_rel(Elf * e, Elf_Scn * scn);
+void		elf_print_got(Elf * e, Elf_Scn * scn);
+void		elf_print_note(Elf * e, Elf_Scn * scn);
+void		elf_print_hash(Elf * e, Elf_Scn * scn);
 
-void usage(void);
+void		usage	  (void);
 
 int
 main(int ac, char **av)
 {
-	u_int64_t phoff;
-	u_int64_t shoff;
-	u_int64_t phentsize;
-	u_int64_t phnum;
-	u_int64_t shentsize;
-	u_int64_t shnum;
-	u_int64_t shstrndx;
-	u_int64_t offset;
-	u_int64_t name;
-	u_int64_t type;
-	struct stat sb;
-	u_int flags;
-	Elf32_Ehdr *e;
-	void *p;
-	void *sh;
-	void *v;
-	int fd;
-	int ch;
-	int i;
+	u_int		 flags;
+	Elf		*e;
+	Elf_Scn		*scn;
+	GElf_Phdr	 phdr;
+	GElf_Shdr	 shdr;
+	struct stat	 sb;
+	int		 ch;
+	int		 elferr;
+	int		 fd;
+	int		 i;
+	size_t		 phnum;
+	char		*name;
 
 	out = stdout;
 	flags = 0;
@@ -438,56 +312,73 @@
 			break;
 		case 'w':
 			if ((out = fopen(optarg, "w")) == NULL)
-				err(1, "%s", optarg);
+				err(EX_NOINPUT, "%s", optarg);
 			break;
 		case '?':
 		default:
 			usage();
 		}
+
 	ac -= optind;
 	av += optind;
+
 	if (ac == 0 || flags == 0)
 		usage();
+
+	if (elf_version(EV_CURRENT) == EV_NONE)
+		errx(EX_SOFTWARE, "ELF library initialization failed: %s",
+		     elf_errmsg(-1));
+
 	if ((fd = open(*av, O_RDONLY)) < 0 ||
 	    fstat(fd, &sb) < 0)
-		err(1, "%s", *av);
-	e = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
-	if (e == MAP_FAILED)
-		err(1, NULL);
-	if (!IS_ELF(*(Elf32_Ehdr *)e))
-		errx(1, "not an elf file");
-	phoff = elf_get_off(e, e, E_PHOFF);
-	shoff = elf_get_off(e, e, E_SHOFF);
-	phentsize = elf_get_quarter(e, e, E_PHENTSIZE);
-	phnum = elf_get_quarter(e, e, E_PHNUM);
-	shentsize = elf_get_quarter(e, e, E_SHENTSIZE);
-	shnum = elf_get_quarter(e, e, E_SHNUM);
-	shstrndx = elf_get_quarter(e, e, E_SHSTRNDX);
-	p = (char *)e + phoff;
-	sh = (char *)e + shoff;
-	offset = elf_get_off(e, (char *)sh + shstrndx * shentsize, SH_OFFSET);
-	shstrtab = (char *)e + offset;
-	for (i = 0; (u_int64_t)i < shnum; i++) {
-		name = elf_get_word(e, (char *)sh + i * shentsize, SH_NAME);
-		offset = elf_get_off(e, (char *)sh + i * shentsize, SH_OFFSET);
-		if (strcmp(shstrtab + name, ".strtab") == 0)
-			strtab = (char *)e + offset;
-		if (strcmp(shstrtab + name, ".dynstr") == 0)
-			dynstr = (char *)e + offset;
-	}
+		err(EX_NOINPUT, "%s", *av);
+
+	if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
+		errx(EX_SOFTWARE, "elf_begin() failed: %s",
+		     elf_errmsg(-1));
+
+	if (elf_kind(e) != ELF_K_ELF)
+		errx(EX_DATAERR, "not an elf file");
+
+	if (elf_getshstrndx(e, &shstrndx) == 0)
+		errx(EX_SOFTWARE, "elf_getshstrndx failed: %s",
+		     elf_errmsg(-1));
+
+	scn = NULL;
+	while ((scn = elf_nextscn(e, scn)) != NULL) {
+		if (gelf_getshdr(scn, &shdr) != &shdr)
+			errx(EX_SOFTWARE, "elf_getshdr failed: %s",
+			     elf_errmsg(-1));
+		if ((name = elf_strptr(e, shstrndx, shdr.sh_name)) == NULL)
+			errx(EX_SOFTWARE, "elf_strptr failed: %s",
+			     elf_errmsg(-1));
+		if (strcmp(name, ".strtab") == 0)
+			strtab = elf_ndxscn(scn);
+		if (strcmp(name, ".dynstr") == 0)
+			dynstr = elf_ndxscn(scn);
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		errx(EX_SOFTWARE, "elf_nextscn failed: %s",
+		     elf_errmsg(elferr));
+
 	if (flags & ED_EHDR)
 		elf_print_ehdr(e);
 	if (flags & ED_PHDR)
-		elf_print_phdr(e, p);
+		elf_print_phdr(e);
 	if (flags & ED_SHDR)
-		elf_print_shdr(e, sh);
+		elf_print_shdr(e);
+	if (elf_getphnum(e, &phnum) == 0)
+		errx(EX_DATAERR, "elf_getphnum failed: %s",
+		     elf_errmsg(-1));
 	for (i = 0; (u_int64_t)i < phnum; i++) {
-		v = (char *)p + i * phentsize;
-		type = elf_get_word(e, v, P_TYPE);
-		switch (type) {
+		if (gelf_getphdr(e, i, &phdr) != &phdr)
+			errx(EX_SOFTWARE, "elf_getphdr failed: %s",
+			     elf_errmsg(-1));
+		switch (phdr.p_type) {
 		case PT_INTERP:
 			if (flags & ED_INTERP)
-				elf_print_interp(e, v);
+				elf_print_interp(e, phdr.p_offset);
 			break;
 		case PT_NULL:
 		case PT_LOAD:
@@ -498,45 +389,52 @@
 			break;
 		}
 	}
-	for (i = 0; (u_int64_t)i < shnum; i++) {
-		v = (char *)sh + i * shentsize;
-		type = elf_get_word(e, v, SH_TYPE);
-		switch (type) {
+
+	scn = NULL;
+	while ((scn = elf_nextscn(e, scn)) != NULL) {
+		if (gelf_getshdr(scn, &shdr) != &shdr)
+			errx(EX_SOFTWARE, "elf_getshdr failed: %s",
+			     elf_errmsg(-1));
+		switch (shdr.sh_type) {
 		case SHT_SYMTAB:
 			if (flags & ED_SYMTAB)
-				elf_print_symtab(e, v, strtab);
+				elf_print_symtab(e, scn, strtab);
 			break;
 		case SHT_DYNAMIC:
 			if (flags & ED_DYN)
-				elf_print_dynamic(e, v);
+				elf_print_dynamic(e, scn);
 			break;
 		case SHT_RELA:
 			if (flags & ED_REL)
-				elf_print_rela(e, v);
+				elf_print_rela(e, scn);
 			break;
 		case SHT_REL:
 			if (flags & ED_REL)
-				elf_print_rel(e, v);
+				elf_print_rel(e, scn);
 			break;
 		case SHT_NOTE:
-			name = elf_get_word(e, v, SH_NAME);
+			if ((name = elf_strptr(e, shstrndx, shdr.sh_name)) == NULL)
+				errx(EX_SOFTWARE, "elf_strptr failed: %s",
+				     elf_errmsg(-1));
 			if (flags & ED_NOTE &&
-			    strcmp(shstrtab + name, ".note.ABI-tag") == 0)
-				elf_print_note(e, v);
+			    strcmp(name, ".note.ABI-tag") == 0)
+				elf_print_note(e, scn);
 			break;
 		case SHT_DYNSYM:
 			if (flags & ED_SYMTAB)
-				elf_print_symtab(e, v, dynstr);
+				elf_print_symtab(e, scn, dynstr);
 			break;
 		case SHT_PROGBITS:
-			name = elf_get_word(e, v, SH_NAME);
+			if ((name = elf_strptr(e, shstrndx, shdr.sh_name)) == NULL)
+				errx(EX_SOFTWARE, "elf_strptr failed: %s",
+				     elf_errmsg(-1));
 			if (flags & ED_GOT &&
-			    strcmp(shstrtab + name, ".got") == 0)
-				elf_print_got(e, v);
+			    strcmp(name, ".got") == 0)
+				elf_print_got(e, scn);
 			break;
 		case SHT_HASH:
 			if (flags & ED_HASH)
-				elf_print_hash(e, v);
+				elf_print_hash(e, scn);
 			break;
 		case SHT_NULL:
 		case SHT_STRTAB:
@@ -545,561 +443,494 @@
 			break;
 		}
 	}
-
-	return 0;
+	elferr = elf_errno();
+	if (elferr != 0)
+		errx(EX_SOFTWARE, "elf_nextscn failed: %s",
+		     elf_errmsg(elferr));
+	return (0);
 }
 
 void
-elf_print_ehdr(Elf32_Ehdr *e)
+elf_print_ehdr(Elf * e)
 {
-	u_int64_t class;
-	u_int64_t data;
-	u_int64_t osabi;
-	u_int64_t type;
-	u_int64_t machine;
-	u_int64_t version;
-	u_int64_t entry;
-	u_int64_t phoff;
-	u_int64_t shoff;
-	u_int64_t flags;
-	u_int64_t ehsize;
-	u_int64_t phentsize;
-	u_int64_t phnum;
-	u_int64_t shentsize;
-	u_int64_t shnum;
-	u_int64_t shstrndx;
-
-	class = elf_get_byte(e, e, E_CLASS);
-	data = elf_get_byte(e, e, E_DATA);
-	osabi = elf_get_byte(e, e, E_OSABI);
-	type = elf_get_quarter(e, e, E_TYPE);
-	machine = elf_get_quarter(e, e, E_MACHINE);
-	version = elf_get_word(e, e, E_VERSION);
-	entry = elf_get_addr(e, e, E_ENTRY);
-	phoff = elf_get_off(e, e, E_PHOFF);
-	shoff = elf_get_off(e, e, E_SHOFF);
-	flags = elf_get_word(e, e, E_FLAGS);
-	ehsize = elf_get_quarter(e, e, E_EHSIZE);
-	phentsize = elf_get_quarter(e, e, E_PHENTSIZE);
-	phnum = elf_get_quarter(e, e, E_PHNUM);
-	shentsize = elf_get_quarter(e, e, E_SHENTSIZE);
-	shnum = elf_get_quarter(e, e, E_SHNUM);
-	shstrndx = elf_get_quarter(e, e, E_SHSTRNDX);
+	GElf_Ehdr	 ehdr;
+
+	if (gelf_getehdr(e, &ehdr) == NULL)
+		errx(EX_SOFTWARE, "gelf_getehdr failed: %s",
+		     elf_errmsg(-1));
 	fprintf(out, "\nelf header:\n");
 	fprintf(out, "\n");
-	fprintf(out, "\te_ident: %s %s %s\n", ei_classes[class], ei_data[data],
-	    ei_abis[osabi]);
-	fprintf(out, "\te_type: %s\n", e_types[type]);
-	fprintf(out, "\te_machine: %s\n", e_machines(machine));
-	fprintf(out, "\te_version: %s\n", ei_versions[version]);
-	fprintf(out, "\te_entry: %#jx\n", (intmax_t)entry);
-	fprintf(out, "\te_phoff: %jd\n", (intmax_t)phoff);
-	fprintf(out, "\te_shoff: %jd\n", (intmax_t)shoff);
-	fprintf(out, "\te_flags: %jd\n", (intmax_t)flags);
-	fprintf(out, "\te_ehsize: %jd\n", (intmax_t)ehsize);
-	fprintf(out, "\te_phentsize: %jd\n", (intmax_t)phentsize);
-	fprintf(out, "\te_phnum: %jd\n", (intmax_t)phnum);
-	fprintf(out, "\te_shentsize: %jd\n", (intmax_t)shentsize);
-	fprintf(out, "\te_shnum: %jd\n", (intmax_t)shnum);
-	fprintf(out, "\te_shstrndx: %jd\n", (intmax_t)shstrndx);
+	fprintf(out, "\te_ident: %s %s %s\n",
+		ei_classes[ehdr.e_ident[EI_CLASS]],
+		ei_data[ehdr.e_ident[EI_DATA]],
+		ei_abis[ehdr.e_ident[EI_OSABI]]);
+	fprintf(out, "\te_type: %s\n", e_types[ehdr.e_type]);
+	fprintf(out, "\te_machine: %s\n", e_machines(ehdr.e_machine));
+	fprintf(out, "\te_version: %s\n", ei_versions[ehdr.e_version]);
+	fprintf(out, "\te_entry: %#jx\n", (uintmax_t)ehdr.e_entry);
+	fprintf(out, "\te_phoff: %ju\n", (uintmax_t)ehdr.e_phoff);
+	fprintf(out, "\te_shoff: %ju\n", (uintmax_t)ehdr.e_shoff);
+	fprintf(out, "\te_flags: %ju\n", (uintmax_t)ehdr.e_flags);
+	fprintf(out, "\te_ehsize: %ju\n", (uintmax_t)ehdr.e_ehsize);
+	fprintf(out, "\te_phentsize: %ju\n", (uintmax_t)ehdr.e_phentsize);
+	fprintf(out, "\te_phnum: %ju\n", (uintmax_t)ehdr.e_phnum);
+	fprintf(out, "\te_shentsize: %ju\n", (uintmax_t)ehdr.e_shentsize);
+	fprintf(out, "\te_shnum: %ju\n", (uintmax_t)ehdr.e_shnum);
+	fprintf(out, "\te_shstrndx: %ju\n", (uintmax_t)ehdr.e_shstrndx);
 }
 
 void
-elf_print_phdr(Elf32_Ehdr *e, void *p)
-{
-	u_int64_t phentsize;
-	u_int64_t phnum;
-	u_int64_t type;
-	u_int64_t offset;
-	u_int64_t vaddr;
-	u_int64_t paddr;
-	u_int64_t filesz;
-	u_int64_t memsz;
-	u_int64_t flags;
-	u_int64_t align;
-	void *v;
-	int i;
-
-	phentsize = elf_get_quarter(e, e, E_PHENTSIZE);
-	phnum = elf_get_quarter(e, e, E_PHNUM);
+elf_print_phdr(Elf * e)
+{
+	GElf_Phdr	 phdr;
+	size_t		 phnum;
+	int		 i;
+
+	if (elf_getphnum(e, &phnum) == 0)
+		errx(EX_DATAERR, "elf_getphnum failed: %s",
+		     elf_errmsg(-1));
 	fprintf(out, "\nprogram header:\n");
-	for (i = 0; (u_int64_t)i < phnum; i++) {
-		v = (char *)p + i * phentsize;
-		type = elf_get_word(e, v, P_TYPE);
-		offset = elf_get_off(e, v, P_OFFSET);
-		vaddr = elf_get_addr(e, v, P_VADDR);
-		paddr = elf_get_addr(e, v, P_PADDR);
-		filesz = elf_get_size(e, v, P_FILESZ);
-		memsz = elf_get_size(e, v, P_MEMSZ);
-		flags = elf_get_word(e, v, P_FLAGS);
-		align = elf_get_size(e, v, P_ALIGN);
+	for (i = 0; (u_int64_t) i < phnum; i++) {
+		if (gelf_getphdr(e, i, &phdr) != &phdr)
+			errx(EX_SOFTWARE, "elf_getphdr failed: %s",
+			     elf_errmsg(-1));
 		fprintf(out, "\n");
 		fprintf(out, "entry: %d\n", i);
-		fprintf(out, "\tp_type: %s\n", p_types[type & 0x7]);
-		fprintf(out, "\tp_offset: %jd\n", (intmax_t)offset);
-		fprintf(out, "\tp_vaddr: %#jx\n", (intmax_t)vaddr);
-		fprintf(out, "\tp_paddr: %#jx\n", (intmax_t)paddr);
-		fprintf(out, "\tp_filesz: %jd\n", (intmax_t)filesz);
-		fprintf(out, "\tp_memsz: %jd\n", (intmax_t)memsz);
-		fprintf(out, "\tp_flags: %s\n", p_flags[flags]);
-		fprintf(out, "\tp_align: %jd\n", (intmax_t)align);
+		fprintf(out, "\tp_type: %s\n", p_types[phdr.p_type & 0x7]);
+		fprintf(out, "\tp_offset: %ju\n", (uintmax_t)phdr.p_offset);
+		fprintf(out, "\tp_vaddr: %#jx\n", (uintmax_t)phdr.p_vaddr);
+		fprintf(out, "\tp_paddr: %#jx\n", (uintmax_t)phdr.p_paddr);
+		fprintf(out, "\tp_filesz: %ju\n", (uintmax_t)phdr.p_filesz);
+		fprintf(out, "\tp_memsz: %ju\n", (uintmax_t)phdr.p_memsz);
+		fprintf(out, "\tp_flags: %s\n", p_flags[phdr.p_flags]);
+		fprintf(out, "\tp_align: %ju\n", (uintmax_t)phdr.p_align);
 	}
 }
 
 void
-elf_print_shdr(Elf32_Ehdr *e, void *sh)
+elf_print_shdr(Elf * e)
 {
-	u_int64_t shentsize;
-	u_int64_t shnum;
-	u_int64_t name;
-	u_int64_t type;
-	u_int64_t flags;
-	u_int64_t addr;
-	u_int64_t offset;
-	u_int64_t size;
-	u_int64_t shlink;
-	u_int64_t info;
-	u_int64_t addralign;
-	u_int64_t entsize;
-	void *v;
-	int i;
+	GElf_Shdr	 shdr;
+	Elf_Scn		*scn;
+	char		*name;
+	int		 elferr;
 
-	shentsize = elf_get_quarter(e, e, E_SHENTSIZE);
-	shnum = elf_get_quarter(e, e, E_SHNUM);
 	fprintf(out, "\nsection header:\n");
-	for (i = 0; (u_int64_t)i < shnum; i++) {
-		v = (char *)sh + i * shentsize;
-		name = elf_get_word(e, v, SH_NAME);
-		type = elf_get_word(e, v, SH_TYPE);
-		flags = elf_get_word(e, v, SH_FLAGS);
-		addr = elf_get_addr(e, v, SH_ADDR);
-		offset = elf_get_off(e, v, SH_OFFSET);
-		size = elf_get_size(e, v, SH_SIZE);
-		shlink = elf_get_word(e, v, SH_LINK);
-		info = elf_get_word(e, v, SH_INFO);
-		addralign = elf_get_size(e, v, SH_ADDRALIGN);
-		entsize = elf_get_size(e, v, SH_ENTSIZE);
+	scn = elf_getscn(e, SHN_UNDEF);
+	do {
+		if (gelf_getshdr(scn, &shdr) != &shdr)
+			errx(EX_SOFTWARE, "elf_getshdr failed: %s",
+			     elf_errmsg(-1));
+		if ((name = elf_strptr(e, shstrndx, shdr.sh_name)) == NULL)
+			errx(EX_SOFTWARE, "elf_strptr failed: %s",
+			     elf_errmsg(-1));
 		fprintf(out, "\n");
-		fprintf(out, "entry: %d\n", i);
-		fprintf(out, "\tsh_name: %s\n", shstrtab + name);
-		fprintf(out, "\tsh_type: %s\n", sh_types(type));
-		fprintf(out, "\tsh_flags: %s\n", sh_flags[flags & 0x7]);
-		fprintf(out, "\tsh_addr: %#jx\n", addr);
-		fprintf(out, "\tsh_offset: %jd\n", (intmax_t)offset);
-		fprintf(out, "\tsh_size: %jd\n", (intmax_t)size);
-		fprintf(out, "\tsh_link: %jd\n", (intmax_t)shlink);
-		fprintf(out, "\tsh_info: %jd\n", (intmax_t)info);
-		fprintf(out, "\tsh_addralign: %jd\n", (intmax_t)addralign);
-		fprintf(out, "\tsh_entsize: %jd\n", (intmax_t)entsize);
-	}
-}
-
-void
-elf_print_symtab(Elf32_Ehdr *e, void *sh, char *str)
-{
-	u_int64_t offset;
-	u_int64_t entsize;
-	u_int64_t size;
-	u_int64_t name;
-	u_int64_t value;
-	u_int64_t info;
-	u_int64_t shndx;
-	void *st;
-	int len;
-	int i;
-
-	offset = elf_get_off(e, sh, SH_OFFSET);
-	entsize = elf_get_size(e, sh, SH_ENTSIZE);
-	size = elf_get_size(e, sh, SH_SIZE);
-	name = elf_get_word(e, sh, SH_NAME);
-	len = size / entsize;
-	fprintf(out, "\nsymbol table (%s):\n", shstrtab + name);
-	for (i = 0; i < len; i++) {
-		st = (char *)e + offset + i * entsize;
-		name = elf_get_word(e, st, ST_NAME);
-		value = elf_get_addr(e, st, ST_VALUE);
-		size = elf_get_size(e, st, ST_SIZE);
-		info = elf_get_byte(e, st, ST_INFO);
-		shndx = elf_get_quarter(e, st, ST_SHNDX);
-		fprintf(out, "\n");
-		fprintf(out, "entry: %d\n", i);
-		fprintf(out, "\tst_name: %s\n", str + name);
-		fprintf(out, "\tst_value: %#jx\n", value);
-		fprintf(out, "\tst_size: %jd\n", (intmax_t)size);
-		fprintf(out, "\tst_info: %s %s\n",
-		    st_types[ELF32_ST_TYPE(info)],
-		    st_bindings[ELF32_ST_BIND(info)]);
-		fprintf(out, "\tst_shndx: %jd\n", (intmax_t)shndx);
-	}
-}
-
-void
-elf_print_dynamic(Elf32_Ehdr *e, void *sh)
-{
-	u_int64_t offset;
-	u_int64_t entsize;
-	u_int64_t size;
-	int64_t tag;
-	u_int64_t ptr;
-	u_int64_t val;
-	void *d;
-	int i;
-
-	offset = elf_get_off(e, sh, SH_OFFSET);
-	entsize = elf_get_size(e, sh, SH_ENTSIZE);
-	size = elf_get_size(e, sh, SH_SIZE);
+		fprintf(out, "entry: %ju\n", (uintmax_t)elf_ndxscn(scn));
+		fprintf(out, "\tsh_name: %s\n", name);
+		fprintf(out, "\tsh_type: %s\n", sh_types(shdr.sh_type));
+		fprintf(out, "\tsh_flags: %s\n", sh_flags[shdr.sh_flags & 0x7]);
+		fprintf(out, "\tsh_addr: %#jx\n", shdr.sh_addr);
+		fprintf(out, "\tsh_offset: %ju\n", (uintmax_t)shdr.sh_offset);
+		fprintf(out, "\tsh_size: %ju\n", (uintmax_t)shdr.sh_size);
+		fprintf(out, "\tsh_link: %ju\n", (uintmax_t)shdr.sh_link);
+		fprintf(out, "\tsh_info: %ju\n", (uintmax_t)shdr.sh_info);
+		fprintf(out, "\tsh_addralign: %ju\n", (uintmax_t)shdr.sh_addralign);
+		fprintf(out, "\tsh_entsize: %ju\n", (uintmax_t)shdr.sh_entsize);
+	} while ((scn = elf_nextscn(e, scn)) != NULL);
+	elferr = elf_errno();
+	if (elferr != 0)
+		errx(EX_SOFTWARE, "elf_nextscn failed: %s",
+		     elf_errmsg(elferr));
+}
+
+void
+elf_print_symtab(Elf * e, Elf_Scn * scn, size_t strndx)
+{
+	size_t		 n;
+	char		*name;
+	Elf_Data	*data;
+	GElf_Sym	 sym;
+	GElf_Shdr	 shdr;
+	int		 elferr;
+	int		 i;
+	int		 len;
+
+	if (gelf_getshdr(scn, &shdr) != &shdr)
+		errx(EX_SOFTWARE, "elf_getshdr failed: %s",
+		     elf_errmsg(-1));
+	if ((name = elf_strptr(e, shstrndx, shdr.sh_name)) == NULL)
+		errx(EX_SOFTWARE, "elf_strptr failed: %s",
+		     elf_errmsg(-1));
+	fprintf(out, "\nsymbol table (%s):\n", name);
+	data = NULL;
+	n = 0;
+	while (n < shdr.sh_size && (data = elf_getdata(scn, data)) != NULL) {
+		len = data->d_size / shdr.sh_entsize;
+		for (i = 0; i < len; i++) {
+			if (gelf_getsym(data, i, &sym) != &sym)
+				errx(EX_SOFTWARE, "gelf_getsym failed: %s",
+				     elf_errmsg(-1));
+			if ((name = elf_strptr(e, strndx, sym.st_name)) ==
+			    NULL)
+				errx(EX_SOFTWARE, "elf_strptr failed: %s",
+				     elf_errmsg(-1));
+			fprintf(out, "\n");
+			fprintf(out, "entry: %d\n", i);
+			fprintf(out, "\tst_name: %s\n", name);
+			fprintf(out, "\tst_value: %#jx\n", sym.st_value);
+			fprintf(out, "\tst_size: %ju\n", 
+				(uintmax_t)sym.st_size);
+			fprintf(out, "\tst_info: %s %s\n",
+				st_types[GELF_ST_TYPE(sym.st_info)],
+				st_bindings[GELF_ST_BIND(sym.st_info)]);
+			fprintf(out, "\tst_shndx: %ju\n", 
+				(uintmax_t)sym.st_shndx);
+		}
+		n += data->d_size;
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		errx(EX_SOFTWARE, "elf_getdata failed: %s",
+		     elf_errmsg(elferr));
+}
+
+void
+elf_print_dynamic(Elf * e, Elf_Scn * scn)
+{
+	size_t		 n;
+	char		*name;
+	Elf_Data	*data;
+	GElf_Dyn	 dyn;
+	GElf_Shdr	 shdr;
+	int		 elferr;
+	int		 i;
+	int		 len;
+
+	if (gelf_getshdr(scn, &shdr) != &shdr)
+		errx(EX_SOFTWARE, "elf_getshdr failed: %s",
+		     elf_errmsg(-1));
 	fprintf(out, "\ndynamic:\n");
-	for (i = 0; (u_int64_t)i < size / entsize; i++) {
-		d = (char *)e + offset + i * entsize;
-		tag = elf_get_size(e, d, D_TAG);
-		ptr = elf_get_size(e, d, D_PTR);
-		val = elf_get_addr(e, d, D_VAL);
-		fprintf(out, "\n");
-		fprintf(out, "entry: %d\n", i);
-		fprintf(out, "\td_tag: %s\n", d_tags(tag));
-		switch (tag) {
-		case DT_NEEDED:
-		case DT_SONAME:
-		case DT_RPATH:
-			fprintf(out, "\td_val: %s\n", dynstr + val);
-			break;
-		case DT_PLTRELSZ:
-		case DT_RELA:
-		case DT_RELASZ:
-		case DT_RELAENT:
-		case DT_STRSZ:
-		case DT_SYMENT:
-		case DT_RELSZ:
-		case DT_RELENT:
-		case DT_PLTREL:
-			fprintf(out, "\td_val: %jd\n", (intmax_t)val);
-			break;
-		case DT_PLTGOT:
-		case DT_HASH:
-		case DT_STRTAB:
-		case DT_SYMTAB:
-		case DT_INIT:
-		case DT_FINI:
-		case DT_REL:
-		case DT_JMPREL:
-			fprintf(out, "\td_ptr: %#jx\n", ptr);
-			break;
-		case DT_NULL:
-		case DT_SYMBOLIC:
-		case DT_DEBUG:
-		case DT_TEXTREL:
-			break;
-		}
-	}
-}
-
-void
-elf_print_rela(Elf32_Ehdr *e, void *sh)
-{
-	u_int64_t offset;
-	u_int64_t entsize;
-	u_int64_t size;
-	u_int64_t name;
-	u_int64_t info;
-	int64_t addend;
-	void *ra;
-	void *v;
-	int i;
-
-	offset = elf_get_off(e, sh, SH_OFFSET);
-	entsize = elf_get_size(e, sh, SH_ENTSIZE);
-	size = elf_get_size(e, sh, SH_SIZE);
-	name = elf_get_word(e, sh, SH_NAME);
-	v = (char *)e + offset;
-	fprintf(out, "\nrelocation with addend (%s):\n", shstrtab + name);
-	for (i = 0; (u_int64_t)i < size / entsize; i++) {
-		ra = (char *)v + i * entsize;
-		offset = elf_get_addr(e, ra, RA_OFFSET);
-		info = elf_get_word(e, ra, RA_INFO);
-		addend = elf_get_off(e, ra, RA_ADDEND);
-		fprintf(out, "\n");
-		fprintf(out, "entry: %d\n", i);
-		fprintf(out, "\tr_offset: %#jx\n", offset);
-		fprintf(out, "\tr_info: %jd\n", (intmax_t)info);
-		fprintf(out, "\tr_addend: %jd\n", (intmax_t)addend);
-	}
-}
-
-void
-elf_print_rel(Elf32_Ehdr *e, void *sh)
-{
-	u_int64_t offset;
-	u_int64_t entsize;
-	u_int64_t size;
-	u_int64_t name;
-	u_int64_t info;
-	void *r;
-	void *v;
-	int i;
-
-	offset = elf_get_off(e, sh, SH_OFFSET);
-	entsize = elf_get_size(e, sh, SH_ENTSIZE);
-	size = elf_get_size(e, sh, SH_SIZE);
-	name = elf_get_word(e, sh, SH_NAME);
-	v = (char *)e + offset;
-	fprintf(out, "\nrelocation (%s):\n", shstrtab + name);
-	for (i = 0; (u_int64_t)i < size / entsize; i++) {
-		r = (char *)v + i * entsize;
-		offset = elf_get_addr(e, r, R_OFFSET);
-		info = elf_get_word(e, r, R_INFO);
-		fprintf(out, "\n");
-		fprintf(out, "entry: %d\n", i);
-		fprintf(out, "\tr_offset: %#jx\n", offset);
-		fprintf(out, "\tr_info: %jd\n", (intmax_t)info);
-	}
-}
-
-void
-elf_print_interp(Elf32_Ehdr *e, void *p)
-{
-	u_int64_t offset;
-	char *s;
-
-	offset = elf_get_off(e, p, P_OFFSET);
-	s = (char *)e + offset;
+	data = NULL;
+	n = 0;
+	while (n < shdr.sh_size && (data = elf_getdata(scn, data)) != NULL) {
+		len = data->d_size / shdr.sh_entsize;
+		for (i = 0; i < len; i++) {
+			if (gelf_getdyn(data, i, &dyn) != &dyn)
+				errx(EX_SOFTWARE, "gelf_getdyn failed: %s",
+				     elf_errmsg(-1));
+			fprintf(out, "\n");
+			fprintf(out, "entry: %d\n", i);
+			fprintf(out, "\td_tag: %s\n", d_tags(dyn.d_tag));
+			switch(dyn.d_tag) {
+			case DT_NEEDED:
+			case DT_SONAME:
+			case DT_RPATH:
+				if ((name = 
+				     elf_strptr(e, dynstr, dyn.d_un.d_val)) ==
+				    NULL)
+					errx(EX_SOFTWARE, 
+					     "elf_strptr failed: %s",
+					     elf_errmsg(-1));
+				fprintf(out, "\td_val: %s\n", name);
+				break;
+			case DT_PLTRELSZ:
+			case DT_RELA:
+			case DT_RELASZ:
+			case DT_RELAENT:
+			case DT_STRSZ:
+			case DT_SYMENT:
+			case DT_RELSZ:
+			case DT_RELENT:
+			case DT_PLTREL:
+				fprintf(out, "\td_val: %ju\n", 
+					(uintmax_t)dyn.d_un.d_val);
+				break;
+			case DT_PLTGOT:
+			case DT_HASH:
+			case DT_STRTAB:
+			case DT_SYMTAB:
+			case DT_INIT:
+			case DT_FINI:
+			case DT_REL:
+			case DT_JMPREL:
+				fprintf(out, "\td_ptr: %#jx\n", 
+					dyn.d_un.d_ptr);
+				break;
+			case DT_NULL:
+			case DT_SYMBOLIC:
+			case DT_DEBUG:
+			case DT_TEXTREL:
+				break;
+			}
+		}
+		n += data->d_size;
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		errx(EX_SOFTWARE, "elf_getdata failed: %s",
+		     elf_errmsg(elferr));
+}
+
+void
+elf_print_rela(Elf * e, Elf_Scn * scn)
+{
+	size_t		 n;
+	char		*name;
+	Elf_Data	*data;
+	GElf_Rela	 rela;
+	GElf_Shdr	 shdr;
+	int		 elferr;
+	int		 i;
+	int		 len;
+
+	if (gelf_getshdr(scn, &shdr) != &shdr)
+		errx(EX_SOFTWARE, "elf_getshdr failed: %s",
+		     elf_errmsg(-1));
+	if ((name = elf_strptr(e, shstrndx, shdr.sh_name)) == NULL)
+		errx(EX_SOFTWARE, "elf_strptr failed: %s",
+		     elf_errmsg(-1));
+	fprintf(out, "\nrelocation with addend (%s):\n", name);
+	data = NULL;
+	n = 0;
+	while (n < shdr.sh_size && (data = elf_getdata(scn, data)) != NULL) {
+		len = data->d_size / shdr.sh_entsize;
+		for (i = 0; i < len; i++) {
+			if (gelf_getrela(data, i, &rela) != &rela)
+				errx(EX_SOFTWARE, "gelf_getrela failed: %s",
+				     elf_errmsg(-1));
+			fprintf(out, "\n");
+			fprintf(out, "entry: %d\n", i);
+			fprintf(out, "\tr_offset: %#jx\n",
+				rela.r_offset);
+			fprintf(out, "\tr_info: %ju\n", 
+				(uintmax_t)rela.r_info);
+			fprintf(out, "\tr_addend: %jd\n", 
+				(intmax_t)rela.r_addend);
+		}
+		n += data->d_size;
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		errx(EX_SOFTWARE, "elf_getdata failed: %s",
+		     elf_errmsg(elferr));
+}
+
+void
+elf_print_rel(Elf * e, Elf_Scn * scn)
+{
+	size_t		 n;
+	char		*name;
+	Elf_Data	*data;
+	GElf_Rel	 rel;
+	GElf_Shdr	 shdr;
+	int		 elferr;
+	int		 i;
+	int		 len;
+
+	if (gelf_getshdr(scn, &shdr) != &shdr)
+		errx(EX_SOFTWARE, "elf_getshdr failed: %s",
+		     elf_errmsg(-1));
+	if ((name = elf_strptr(e, shstrndx, shdr.sh_name)) == NULL)
+		errx(EX_SOFTWARE, "elf_strptr failed: %s",
+		     elf_errmsg(-1));
+	fprintf(out, "\nrelocation (%s):\n", name);
+	data = NULL;
+	n = 0;
+	while (n < shdr.sh_size && (data = elf_getdata(scn, data)) != NULL) {
+		len = data->d_size / shdr.sh_entsize;
+		for (i = 0; i < len; i++) {
+			if (gelf_getrel(data, i, &rel) != &rel)
+				errx(EX_SOFTWARE, "gelf_getrel failed: %s",
+				     elf_errmsg(-1));
+			fprintf(out, "\n");
+			fprintf(out, "entry: %d\n", i);
+			fprintf(out, "\tr_offset: %#jx\n",
+				rel.r_offset);
+			fprintf(out, "\tr_info: %ju\n", 
+				(uintmax_t)rel.r_info);
+		}
+		n += data->d_size;
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		errx(EX_SOFTWARE, "elf_getdata failed: %s",
+		     elf_errmsg(elferr));
+}
+	
+void
+elf_print_interp(Elf * e, Elf64_Off p_offset)
+{
+	char	       *s;
+
+	if ((s = elf_rawfile(e, NULL)) == NULL)
+		errx(EX_SOFTWARE, "elf_rawfile failed: %s",
+		     elf_errmsg(-1));
 	fprintf(out, "\ninterp:\n");
-	fprintf(out, "\t%s\n", s);
+	fprintf(out, "\t%s\n", s + (size_t)p_offset);
 }
 
 void
-elf_print_got(Elf32_Ehdr *e, void *sh)
+elf_print_got(Elf * e, Elf_Scn * scn)
 {
-	u_int64_t offset;
-	u_int64_t addralign;
-	u_int64_t size;
-	u_int64_t addr;
-	void *v;
-	int i;
-
-	offset = elf_get_off(e, sh, SH_OFFSET);
-	addralign = elf_get_size(e, sh, SH_ADDRALIGN);
-	size = elf_get_size(e, sh, SH_SIZE);
-	v = (char *)e + offset;
+	GElf_Ehdr	 ehdr;
+	GElf_Shdr	 shdr;
+	Elf_Data	*data;
+	Elf_Data	*dst;
+	size_t		 n;
+	int		 ec;
+	int		 elferr;
+	int		 i;
+
+	if (gelf_getehdr(e, &ehdr) == NULL)
+		errx(EX_SOFTWARE, "gelf_getehdr failed: %s",
+		     elf_errmsg(-1));
+	if (gelf_getshdr(scn, &shdr) != &shdr)
+		errx(EX_SOFTWARE, "elf_getshdr failed: %s",
+		     elf_errmsg(-1));
+	if ((ec = gelf_getclass(e)) == ELFCLASSNONE)
+		errx(EX_DATAERR, "gelf_getclass failed: %s",
+		     elf_errmsg(-1));
 	fprintf(out, "\nglobal offset table:\n");
-	for (i = 0; (u_int64_t)i < size / addralign; i++) {
-		addr = elf_get_addr(e, (char *)v + i * addralign, 0);
-		fprintf(out, "\n");
-		fprintf(out, "entry: %d\n", i);
-		fprintf(out, "\t%#jx\n", addr);
-	}
-}
-
-void
-elf_print_hash(Elf32_Ehdr *e __unused, void *sh __unused)
-{
-}
-
-void
-elf_print_note(Elf32_Ehdr *e, void *sh)
-{
-	u_int64_t offset;
-	u_int64_t size;
-	u_int64_t name;
-	u_int32_t namesz;
-	u_int32_t descsz;
-	u_int32_t type;
-	u_int32_t desc;
-	char *n, *s;
-
-	offset = elf_get_off(e, sh, SH_OFFSET);
-	size = elf_get_size(e, sh, SH_SIZE);
-	name = elf_get_word(e, sh, SH_NAME);
-	n = (char *)e + offset;
-	fprintf(out, "\nnote (%s):\n", shstrtab + name);
- 	while (n < ((char *)e + offset + size)) {
-		namesz = elf_get_word(e, n, N_NAMESZ);
-		descsz = elf_get_word(e, n, N_DESCSZ);
-		type = elf_get_word(e, n, N_TYPE);
- 		s = n + sizeof(Elf_Note);
- 		desc = elf_get_word(e, n + sizeof(Elf_Note) + namesz, 0);
-		fprintf(out, "\t%s %d\n", s, desc);
-		n += sizeof(Elf_Note) + namesz + descsz;
-	}
-}
-
-u_int64_t
-elf_get_byte(Elf32_Ehdr *e, void *base, elf_member_t member)
-{
-	u_int64_t val;
-
-	val = 0;
-	switch (e->e_ident[EI_CLASS]) {
-	case ELFCLASS32:
-		val = ((char *)base)[elf32_offsets[member]];
-		break;
-	case ELFCLASS64:
-		val = ((char *)base)[elf64_offsets[member]];
-		break;
-	case ELFCLASSNONE:
-		errx(1, "invalid class");
-	}
-
-	return val;
-}
-
-u_int64_t
-elf_get_quarter(Elf32_Ehdr *e, void *base, elf_member_t member)
-{
-	u_int64_t val;
-
-	val = 0;
-	switch (e->e_ident[EI_CLASS]) {
-	case ELFCLASS32:
-		base = (char *)base + elf32_offsets[member];
-		switch (e->e_ident[EI_DATA]) {
-		case ELFDATA2MSB:
-			val = be16dec(base);
-			break;
-		case ELFDATA2LSB:
-			val = le16dec(base);
-			break;
-		case ELFDATANONE:
-			errx(1, "invalid data format");
-		}
-		break;
-	case ELFCLASS64:
-		base = (char *)base + elf64_offsets[member];
-		switch (e->e_ident[EI_DATA]) {
-		case ELFDATA2MSB:
-			val = be16dec(base);
-			break;
-		case ELFDATA2LSB:
-			val = le16dec(base);
-			break;
-		case ELFDATANONE:
-			errx(1, "invalid data format");
-		}
-		break;
-	case ELFCLASSNONE:
-		errx(1, "invalid class");
-	}
-
-	return val;
-}
-
-u_int64_t
-elf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member)
-{
-	u_int64_t val;
-
-	val = 0;
-	switch (e->e_ident[EI_CLASS]) {
-	case ELFCLASS32:
-		base = (char *)base + elf32_offsets[member];
-		switch (e->e_ident[EI_DATA]) {
-		case ELFDATA2MSB:
-			val = be16dec(base);
-			break;
-		case ELFDATA2LSB:
-			val = le16dec(base);
-			break;
-		case ELFDATANONE:
-			errx(1, "invalid data format");
-		}
-		break;
-	case ELFCLASS64:
-		base = (char *)base + elf64_offsets[member];
-		switch (e->e_ident[EI_DATA]) {
-		case ELFDATA2MSB:
-			val = be32dec(base);
-			break;
-		case ELFDATA2LSB:
-			val = le32dec(base);
-			break;
-		case ELFDATANONE:
-			errx(1, "invalid data format");
-		}
-		break;
-	case ELFCLASSNONE:
-		errx(1, "invalid class");
-	}
-
-	return val;
-}
-
-u_int64_t
-elf_get_word(Elf32_Ehdr *e, void *base, elf_member_t member)
-{
-	u_int64_t val;
-
-	val = 0;
-	switch (e->e_ident[EI_CLASS]) {
-	case ELFCLASS32:
-		base = (char *)base + elf32_offsets[member];
-		switch (e->e_ident[EI_DATA]) {
-		case ELFDATA2MSB:
-			val = be32dec(base);
-			break;
-		case ELFDATA2LSB:
-			val = le32dec(base);
-			break;
-		case ELFDATANONE:
-			errx(1, "invalid data format");
-		}
-		break;
-	case ELFCLASS64:
-		base = (char *)base + elf64_offsets[member];
-		switch (e->e_ident[EI_DATA]) {
-		case ELFDATA2MSB:
-			val = be32dec(base);
-			break;
-		case ELFDATA2LSB:
-			val = le32dec(base);
-			break;
-		case ELFDATANONE:
-			errx(1, "invalid data format");
-		}
-		break;
-	case ELFCLASSNONE:
-		errx(1, "invalid class");
-	}
-
-	return val;
-}
-
-u_int64_t
-elf_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member)
-{
-	u_int64_t val;
-
-	val = 0;
-	switch (e->e_ident[EI_CLASS]) {
-	case ELFCLASS32:
-		base = (char *)base + elf32_offsets[member];
-		switch (e->e_ident[EI_DATA]) {
-		case ELFDATA2MSB:
-			val = be32dec(base);
-			break;
-		case ELFDATA2LSB:
-			val = le32dec(base);
-			break;
-		case ELFDATANONE:
-			errx(1, "invalid data format");
-		}
-		break;
-	case ELFCLASS64:
-		base = (char *)base + elf64_offsets[member];
-		switch (e->e_ident[EI_DATA]) {
-		case ELFDATA2MSB:
-			val = be64dec(base);
-			break;
-		case ELFDATA2LSB:
-			val = le64dec(base);
-			break;
-		case ELFDATANONE:
-			errx(1, "invalid data format");
-		}
-		break;
-	case ELFCLASSNONE:
-		errx(1, "invalid class");
-	}
-
-	return val;
+	data = NULL;
+	n = 0;
+	while (n < shdr.sh_size && (data = elf_getdata(scn, data)) != NULL) {
+		if (ec == ELFCLASS32)
+			data->d_type = ELF_T_WORD;
+		else
+			data->d_type = ELF_T_XWORD;
+		if ((dst = malloc(sizeof(Elf_Data))) == NULL)
+			err(1, "malloc failed: ");
+		memcpy(dst, data, sizeof(Elf_Data));
+		if (gelf_xlatetom(e, dst, data, ehdr.e_ident[EI_DATA]) != dst)
+			errx(EX_SOFTWARE, "gelf_xlatetom failed: %s",
+			     elf_errmsg(-1));
+		for(i = 0; i * dst->d_align <  dst->d_size; i++) {
+			fprintf(out, "\nentry: %d\n", i);
+			if (ec == ELFCLASS32)
+				fprintf(out, "\t%#x\n", *((u_int32_t *)dst->d_buf + i));
+			else
+				fprintf(out, "\t%#jx\n", *((u_int64_t *)dst->d_buf + i));
+		}
+		n += data->d_size;
+		free(dst);
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		errx(EX_SOFTWARE, "elf_getdata failed: %s",
+		     elf_errmsg(elferr));
+}
+
+void
+elf_print_note(Elf * e, Elf_Scn * scn)
+{
+	GElf_Shdr	 shdr;
+	Elf_Data        *data;
+	u_int32_t	 namesz;
+	u_int32_t	 descsz;
+	u_int32_t	*s;
+	size_t		 n;
+	char		*name;
+	int		 elferr;
+	
+	if (gelf_getshdr(scn, &shdr) != &shdr)
+		errx(EX_SOFTWARE, "elf_getshdr failed: %s",
+		     elf_errmsg(-1));
+	if ((name = elf_strptr(e, shstrndx, shdr.sh_name)) == NULL)
+		errx(EX_SOFTWARE, "elf_strptr failed: %s",
+		     elf_errmsg(-1));
+	fprintf(out, "\nnote (%s):\n", name);
+	data = NULL;
+	n = 0;
+	while (n < shdr.sh_size && (data = elf_getdata(scn, data)) != NULL) {
+		s = data->d_buf;
+		while ((char *)s < (char *)data->d_buf + data->d_size) {
+			namesz = ((Elf_Note *)s)->n_namesz;
+			descsz = ((Elf_Note *)s)->n_descsz;
+			fprintf(out, "\t%s %d\n", (char *)s + sizeof(Elf_Note),
+				*(s + sizeof(Elf_Note)/sizeof(u_int32_t) +
+				  roundup2(namesz, sizeof(u_int32_t)) /
+				  sizeof(u_int32_t)));
+			s = s + sizeof(Elf_Note)/sizeof(u_int32_t) + 
+				roundup2(namesz,sizeof(u_int32_t)) /
+				sizeof(u_int32_t) + 
+				roundup2(descsz,sizeof(u_int32_t)) /
+				sizeof(u_int32_t);
+		}
+		n += data->d_size;
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		errx(EX_SOFTWARE, "elf_getdata failed: %s",
+		     elf_errmsg(elferr));
+}
+
+void
+elf_print_hash(Elf * e, Elf_Scn * scn)
+{
+	GElf_Ehdr	 ehdr;
+	GElf_Shdr	 shdr;
+	Elf_Data	*data;
+	Elf_Data	*dst;
+	u_int32_t	*s;
+	u_int64_t	 i;
+	u_int64_t	 nbucket;
+	u_int64_t	 nchain;
+	u_int64_t	*s64;
+	char		*name;
+	int		 elferr;
+
+	if (gelf_getehdr(e, &ehdr) == NULL)
+		errx(EX_SOFTWARE, "gelf_getehdr failed: %s",
+		     elf_errmsg(-1));
+	if (gelf_getshdr(scn, &shdr) != &shdr)
+		errx(EX_SOFTWARE, "elf_getshdr failed: %s",
+		     elf_errmsg(-1));
+	if ((name = elf_strptr(e, shstrndx, shdr.sh_name)) == NULL)
+		errx(EX_SOFTWARE, "elf_strptr failed: %s",
+		     elf_errmsg(-1));
+	fprintf(out, "\nhash table (%s):\n", name);
+	data = NULL;
+	if (ehdr.e_machine == EM_ALPHA) {
+		/* Alpha uses 64-bit hash entries */
+		if ((data = elf_rawdata(scn, data)) != NULL) {
+			data->d_type = ELF_T_XWORD;
+			if ((dst = malloc(sizeof(Elf_Data))) == NULL)
+				err(1, "malloc failed: ");
+			memcpy(dst, data, sizeof(Elf_Data));
+			if (gelf_xlatetom(e, dst,
+					  data, ehdr.e_ident[EI_DATA]) != dst)
+				errx(EX_SOFTWARE, "gelf_xlatetom failed: %s",
+				     elf_errmsg(-1));
+			s64 = dst->d_buf;
+			nbucket = *s64++;
+			nchain = *s64++;
+			fprintf(out, "\nnbucket:\n\t%ju\n", nbucket);
+			fprintf(out, "\nnchain:\n\t%ju\n\n", nchain);
+			for(i = 0; i < nbucket; i++, s64++)
+				fprintf(out, "bucket[%jd]:\n\t%ju\n\n",
+					i, *s64);
+			for(i = 0; i < nchain; i++, s64++)
+				fprintf(out, "chain[%jd]:\n\t%ju\n\n",
+					i, *s64);
+			free(dst);
+		}
+	} else {
+		if ((data = elf_getdata(scn, data)) != NULL) {
+			s = data->d_buf;
+			nbucket = *s++;
+			nchain = *s++;
+			fprintf(out, "\nnbucket:\n\t%ju\n", nbucket);
+			fprintf(out, "\nnchain:\n\t%ju\n\n", nchain);
+			for(i = 0; i < nbucket; i++, s++)
+				fprintf(out, "bucket[%jd]:\n\t%u\n\n", i, *s);
+			for(i = 0; i < nchain; i++, s++)
+				fprintf(out, "chain[%jd]:\n\t%u\n\n", i, *s);
+		}
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		errx(EX_SOFTWARE, "elf_getdata failed: %s",
+		     elf_errmsg(elferr));
 }
 
 void

--YiEDa0DAkWCtVeE4--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20070320145123.GA2518>