83d9a8
diff --git a/src/readelf.c b/src/readelf.c
83d9a8
index 9651239..807affc 100644
83d9a8
--- a/src/readelf.c
83d9a8
+++ b/src/readelf.c
83d9a8
@@ -41,6 +41,8 @@ FILE_RCSID("@(#)$File: readelf.c,v 1.90 2011/08/23 08:01:12 christos Exp $")
83d9a8
 #include "readelf.h"
83d9a8
 #include "magic.h"
83d9a8
 
83d9a8
+#define __arraycount(a) (sizeof(a) / sizeof(a[0]))
83d9a8
+
83d9a8
 #ifdef	ELFCORE
83d9a8
 private int dophn_core(struct magic_set *, int, int, int, off_t, int, size_t,
83d9a8
     off_t, int *);
83d9a8
@@ -50,7 +52,7 @@ private int dophn_exec(struct magic_set *, int, int, int, off_t, int, size_t,
83d9a8
 private int doshn(struct magic_set *, int, int, int, off_t, int, size_t,
83d9a8
     off_t, int *, int, int);
83d9a8
 private size_t donote(struct magic_set *, void *, size_t, size_t, int,
83d9a8
-    int, size_t, int *);
83d9a8
+    int, size_t, int *, int, off_t, int, off_t);
83d9a8
 
83d9a8
 #define	ELF_ALIGN(a)	((((a) + align - 1) / align) * align)
83d9a8
 
83d9a8
@@ -184,6 +186,11 @@ getu64(int swap, uint64_t value)
83d9a8
 			    elf_getu32(swap, ph32.p_align) : 4) \
83d9a8
 			 : (off_t) (ph64.p_align ?		\
83d9a8
 			    elf_getu64(swap, ph64.p_align) : 4)))
83d9a8
+#define xph_vaddr	(size_t)((clazz == ELFCLASS32		\
83d9a8
+			 ? (off_t) (ph32.p_vaddr ? 		\
83d9a8
+			    elf_getu32(swap, ph32.p_vaddr) : 4) \
83d9a8
+			 : (off_t) (ph64.p_vaddr ?		\
83d9a8
+			    elf_getu64(swap, ph64.p_vaddr) : 4)))
83d9a8
 #define xph_filesz	(size_t)((clazz == ELFCLASS32		\
83d9a8
 			 ? elf_getu32(swap, ph32.p_filesz)	\
83d9a8
 			 : elf_getu64(swap, ph64.p_filesz)))
83d9a8
@@ -194,8 +201,8 @@ getu64(int swap, uint64_t value)
83d9a8
 			 ? elf_getu32(swap, ph32.p_memsz)	\
83d9a8
 			 : elf_getu64(swap, ph64.p_memsz)))
83d9a8
 #define xnh_sizeof	(clazz == ELFCLASS32			\
83d9a8
-			 ? sizeof nh32				\
83d9a8
-			 : sizeof nh64)
83d9a8
+			 ? sizeof(nh32)				\
83d9a8
+			 : sizeof(nh64))
83d9a8
 #define xnh_type	(clazz == ELFCLASS32			\
83d9a8
 			 ? elf_getu32(swap, nh32.n_type)	\
83d9a8
 			 : elf_getu32(swap, nh64.n_type))
83d9a8
@@ -220,6 +227,18 @@ getu64(int swap, uint64_t value)
83d9a8
 #define xcap_val	(clazz == ELFCLASS32			\
83d9a8
 			 ? elf_getu32(swap, cap32.c_un.c_val)	\
83d9a8
 			 : elf_getu64(swap, cap64.c_un.c_val))
83d9a8
+#define xauxv_addr	(clazz == ELFCLASS32			\
83d9a8
+			 ? (void *)&auxv32			\
83d9a8
+			 : (void *)&auxv64)
83d9a8
+#define xauxv_sizeof	(clazz == ELFCLASS32			\
83d9a8
+			 ? sizeof(auxv32)			\
83d9a8
+			 : sizeof(auxv64))
83d9a8
+#define xauxv_type	(clazz == ELFCLASS32			\
83d9a8
+			 ? elf_getu32(swap, auxv32.a_type)	\
83d9a8
+			 : elf_getu64(swap, auxv64.a_type))
83d9a8
+#define xauxv_val	(clazz == ELFCLASS32			\
83d9a8
+			 ? elf_getu32(swap, auxv32.a_v)		\
83d9a8
+			 : elf_getu64(swap, auxv64.a_v))
83d9a8
 
83d9a8
 #ifdef ELFCORE
83d9a8
 /*
83d9a8
@@ -306,6 +325,7 @@ private const char os_style_names[][8] = {
83d9a8
 #define FLAGS_DID_BUILD_ID	0x04
83d9a8
 #define FLAGS_DID_CORE_STYLE	0x08
83d9a8
 #define FLAGS_IS_CORE		0x10
83d9a8
+#define FLAGS_DID_AUXV			0x200
83d9a8
 
83d9a8
 private int
83d9a8
 dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
83d9a8
@@ -316,6 +336,8 @@ dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
83d9a8
 	size_t offset, len;
83d9a8
 	unsigned char nbuf[BUFSIZ];
83d9a8
 	ssize_t bufsize;
83d9a8
+	off_t ph_off = off;
83d9a8
+	int ph_num = num;
83d9a8
 
83d9a8
 	if (size != xph_sizeof) {
83d9a8
 		if (file_printf(ms, ", corrupted program header size") == -1)
83d9a8
@@ -355,7 +377,8 @@ dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
83d9a8
 			if (offset >= (size_t)bufsize)
83d9a8
 				break;
83d9a8
 			offset = donote(ms, nbuf, offset, (size_t)bufsize,
83d9a8
-			    clazz, swap, 4, flags);
83d9a8
+			    clazz, swap, 4, flags, fd, ph_off,
83d9a8
+			    ph_num, fsize);
83d9a8
 			if (offset == 0)
83d9a8
 				break;
83d9a8
 
83d9a8
@@ -365,9 +388,160 @@ dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
83d9a8
 }
83d9a8
 #endif
83d9a8
 
83d9a8
+private off_t
83d9a8
+get_offset_from_virtaddr(struct magic_set *ms, int swap, int clazz, int fd,
83d9a8
+    off_t off, int num, off_t fsize, uint64_t virtaddr)
83d9a8
+{
83d9a8
+	Elf32_Phdr ph32;
83d9a8
+	Elf64_Phdr ph64;
83d9a8
+
83d9a8
+	/*
83d9a8
+	 * Loop through all the program headers and find the header with
83d9a8
+	 * virtual address in which the "virtaddr" belongs to.
83d9a8
+	 */
83d9a8
+	for ( ; num; num--) {
83d9a8
+		if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) {
83d9a8
+			file_badread(ms);
83d9a8
+			return -1;
83d9a8
+		}
83d9a8
+		off += xph_sizeof;
83d9a8
+
83d9a8
+		if (xph_offset > fsize) {
83d9a8
+			/* Perhaps warn here */
83d9a8
+			continue;
83d9a8
+		}
83d9a8
+
83d9a8
+		if (virtaddr >= xph_vaddr && virtaddr < xph_vaddr + xph_filesz)
83d9a8
+			return xph_offset + (virtaddr - xph_vaddr);
83d9a8
+	}
83d9a8
+	return 0;
83d9a8
+}
83d9a8
+
83d9a8
+private size_t
83d9a8
+get_string_on_virtaddr(struct magic_set *ms,
83d9a8
+    int swap, int clazz, int fd, off_t ph_off, int ph_num,
83d9a8
+    off_t fsize, uint64_t virtaddr, char *buf, ssize_t buflen)
83d9a8
+{
83d9a8
+	char *bptr;
83d9a8
+	off_t offset;
83d9a8
+
83d9a8
+	if (buflen == 0)
83d9a8
+		return 0;
83d9a8
+
83d9a8
+	offset = get_offset_from_virtaddr(ms, swap, clazz, fd, ph_off, ph_num,
83d9a8
+	    fsize, virtaddr);
83d9a8
+	if (offset < 0 || (buflen = pread(fd, buf, buflen, offset)) <= 0) {
83d9a8
+		file_badread(ms);
83d9a8
+		return 0;
83d9a8
+	}
83d9a8
+
83d9a8
+	buf[buflen - 1] = '\0';
83d9a8
+
83d9a8
+	/* We expect only printable characters, so return if buffer contains
83d9a8
+	 * non-printable character before the '\0' or just '\0'. */
83d9a8
+	for (bptr = buf; *bptr && isprint((unsigned char)*bptr); bptr++)
83d9a8
+		continue;
83d9a8
+	if (*bptr != '\0')
83d9a8
+		return 0;
83d9a8
+
83d9a8
+	return bptr - buf;
83d9a8
+}
83d9a8
+
83d9a8
+
83d9a8
+private int
83d9a8
+do_auxv_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
83d9a8
+    int swap, uint32_t namesz __attribute__((__unused__)),
83d9a8
+    uint32_t descsz __attribute__((__unused__)),
83d9a8
+    size_t noff __attribute__((__unused__)), size_t doff,
83d9a8
+    int *flags, size_t size __attribute__((__unused__)), int clazz,
83d9a8
+    int fd, off_t ph_off, int ph_num, off_t fsize)
83d9a8
+{
83d9a8
+#ifdef ELFCORE
83d9a8
+	Aux32Info auxv32;
83d9a8
+	Aux64Info auxv64;
83d9a8
+	size_t elsize = xauxv_sizeof;
83d9a8
+	const char *tag;
83d9a8
+	int is_string;
83d9a8
+	size_t nval;
83d9a8
+	size_t off;
83d9a8
+
83d9a8
+
83d9a8
+	if (type != NT_AUXV || (*flags & FLAGS_IS_CORE) == 0)
83d9a8
+		return 0;
83d9a8
+
83d9a8
+	*flags |= FLAGS_DID_AUXV;
83d9a8
+
83d9a8
+	nval = 0;
83d9a8
+	for (off = 0; off + elsize <= descsz; off += elsize) {
83d9a8
+		(void)memcpy(xauxv_addr, &nbuf[doff + off], xauxv_sizeof);
83d9a8
+		/* Limit processing to 50 vector entries to prevent DoS */
83d9a8
+		if (nval++ >= 50) {
83d9a8
+			file_error(ms, 0, "Too many ELF Auxv elements");
83d9a8
+			return 1;
83d9a8
+		}
83d9a8
+
83d9a8
+		switch(xauxv_type) {
83d9a8
+		case AT_LINUX_EXECFN:
83d9a8
+			is_string = 1;
83d9a8
+			tag = "execfn";
83d9a8
+			break;
83d9a8
+		case AT_LINUX_PLATFORM:
83d9a8
+			is_string = 1;
83d9a8
+			tag = "platform";
83d9a8
+			break;
83d9a8
+		case AT_LINUX_UID:
83d9a8
+			is_string = 0;
83d9a8
+			tag = "real uid";
83d9a8
+			break;
83d9a8
+		case AT_LINUX_GID:
83d9a8
+			is_string = 0;
83d9a8
+			tag = "real gid";
83d9a8
+			break;
83d9a8
+		case AT_LINUX_EUID:
83d9a8
+			is_string = 0;
83d9a8
+			tag = "effective uid";
83d9a8
+			break;
83d9a8
+		case AT_LINUX_EGID:
83d9a8
+			is_string = 0;
83d9a8
+			tag = "effective gid";
83d9a8
+			break;
83d9a8
+		default:
83d9a8
+			is_string = 0;
83d9a8
+			tag = NULL;
83d9a8
+			break;
83d9a8
+		}
83d9a8
+
83d9a8
+		if (tag == NULL)
83d9a8
+			continue;
83d9a8
+
83d9a8
+		if (is_string) {
83d9a8
+			char buf[256];
83d9a8
+			ssize_t buflen;
83d9a8
+			buflen = get_string_on_virtaddr(ms, swap, clazz, fd,
83d9a8
+			    ph_off, ph_num, fsize, xauxv_val, buf, sizeof(buf));
83d9a8
+
83d9a8
+			if (buflen == 0)
83d9a8
+				continue;
83d9a8
+			
83d9a8
+			if (file_printf(ms, ", %s: '%s'", tag, buf) == -1)
83d9a8
+				return 0;
83d9a8
+		} else {
83d9a8
+			if (file_printf(ms, ", %s: %d", tag, (int) xauxv_val)
83d9a8
+			    == -1)
83d9a8
+				return 0;
83d9a8
+		}
83d9a8
+	}
83d9a8
+	return 1;
83d9a8
+#else
83d9a8
+	return 0;
83d9a8
+#endif
83d9a8
+}
83d9a8
+
83d9a8
+
83d9a8
 private size_t
83d9a8
 donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
83d9a8
-    int clazz, int swap, size_t align, int *flags)
83d9a8
+    int clazz, int swap, size_t align, int *flags,
83d9a8
+	int fd, off_t ph_off, int ph_num, off_t fsize)
83d9a8
 {
83d9a8
 	Elf32_Nhdr nh32;
83d9a8
 	Elf64_Nhdr nh64;
83d9a8
@@ -390,6 +564,7 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
83d9a8
 
83d9a8
 	namesz = xnh_namesz;
83d9a8
 	descsz = xnh_descsz;
83d9a8
+
83d9a8
 	if ((namesz == 0) && (descsz == 0)) {
83d9a8
 		/*
83d9a8
 		 * We're out of note headers.
83d9a8
@@ -438,37 +613,37 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
83d9a8
 		(void)memcpy(desc, &nbuf[doff], sizeof(desc));
83d9a8
 
83d9a8
 		if (file_printf(ms, ", for GNU/") == -1)
83d9a8
-			return size;
83d9a8
+			return offset;
83d9a8
 		switch (elf_getu32(swap, desc[0])) {
83d9a8
 		case GNU_OS_LINUX:
83d9a8
 			if (file_printf(ms, "Linux") == -1)
83d9a8
-				return size;
83d9a8
+				return offset;
83d9a8
 			break;
83d9a8
 		case GNU_OS_HURD:
83d9a8
 			if (file_printf(ms, "Hurd") == -1)
83d9a8
-				return size;
83d9a8
+				return offset;
83d9a8
 			break;
83d9a8
 		case GNU_OS_SOLARIS:
83d9a8
 			if (file_printf(ms, "Solaris") == -1)
83d9a8
-				return size;
83d9a8
+				return offset;
83d9a8
 			break;
83d9a8
 		case GNU_OS_KFREEBSD:
83d9a8
 			if (file_printf(ms, "kFreeBSD") == -1)
83d9a8
-				return size;
83d9a8
+				return offset;
83d9a8
 			break;
83d9a8
 		case GNU_OS_KNETBSD:
83d9a8
 			if (file_printf(ms, "kNetBSD") == -1)
83d9a8
-				return size;
83d9a8
+				return offset;
83d9a8
 			break;
83d9a8
 		default:
83d9a8
 			if (file_printf(ms, "<unknown>") == -1)
83d9a8
-				return size; 
83d9a8
+				return offset; 
83d9a8
 		}
83d9a8
 		if (file_printf(ms, " %d.%d.%d", elf_getu32(swap, desc[1]),
83d9a8
 		    elf_getu32(swap, desc[2]), elf_getu32(swap, desc[3])) == -1)
83d9a8
-			return size;
83d9a8
+			return offset;
83d9a8
 		*flags |= FLAGS_DID_NOTE;
83d9a8
-		return size;
83d9a8
+		return offset;
83d9a8
 	}
83d9a8
 
83d9a8
 	if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 &&
83d9a8
@@ -492,7 +667,7 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
83d9a8
 		desc = elf_getu32(swap, desc);
83d9a8
 
83d9a8
 		if (file_printf(ms, ", for NetBSD") == -1)
83d9a8
-			return size;
83d9a8
+			return offset;
83d9a8
 		/*
83d9a8
 		 * The version number used to be stuck as 199905, and was thus
83d9a8
 		 * basically content-free.  Newer versions of NetBSD have fixed
83d9a8
@@ -512,23 +687,23 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
83d9a8
 			uint32_t ver_maj = desc / 100000000;
83d9a8
 
83d9a8
 			if (file_printf(ms, " %u.%u", ver_maj, ver_min) == -1)
83d9a8
-				return size;
83d9a8
+				return offset;
83d9a8
 			if (ver_rel == 0 && ver_patch != 0) {
83d9a8
 				if (file_printf(ms, ".%u", ver_patch) == -1)
83d9a8
-					return size;
83d9a8
+					return offset;
83d9a8
 			} else if (ver_rel != 0) {
83d9a8
 				while (ver_rel > 26) {
83d9a8
 					if (file_printf(ms, "Z") == -1)
83d9a8
-						return size;
83d9a8
+						return offset;
83d9a8
 					ver_rel -= 26;
83d9a8
 				}
83d9a8
 				if (file_printf(ms, "%c", 'A' + ver_rel - 1)
83d9a8
 				    == -1)
83d9a8
-					return size;
83d9a8
+					return offset;
83d9a8
 			}
83d9a8
 		}
83d9a8
 		*flags |= FLAGS_DID_NOTE;
83d9a8
-		return size;
83d9a8
+		return offset;
83d9a8
 	}
83d9a8
 
83d9a8
 	if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0 &&
83d9a8
@@ -537,7 +712,7 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
83d9a8
 		(void)memcpy(&desc, &nbuf[doff], sizeof(desc));
83d9a8
 		desc = elf_getu32(swap, desc);
83d9a8
 		if (file_printf(ms, ", for FreeBSD") == -1)
83d9a8
-			return size;
83d9a8
+			return offset;
83d9a8
 
83d9a8
 		/*
83d9a8
 		 * Contents is __FreeBSD_version, whose relation to OS
83d9a8
@@ -567,69 +742,69 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
83d9a8
 		 */
83d9a8
 		if (desc == 460002) {
83d9a8
 			if (file_printf(ms, " 4.6.2") == -1)
83d9a8
-				return size;
83d9a8
+				return offset;
83d9a8
 		} else if (desc < 460100) {
83d9a8
 			if (file_printf(ms, " %d.%d", desc / 100000,
83d9a8
 			    desc / 10000 % 10) == -1)
83d9a8
-				return size;
83d9a8
+				return offset;
83d9a8
 			if (desc / 1000 % 10 > 0)
83d9a8
 				if (file_printf(ms, ".%d", desc / 1000 % 10)
83d9a8
 				    == -1)
83d9a8
-					return size;
83d9a8
+					return offset;
83d9a8
 			if ((desc % 1000 > 0) || (desc % 100000 == 0))
83d9a8
 				if (file_printf(ms, " (%d)", desc) == -1)
83d9a8
-					return size;
83d9a8
+					return offset;
83d9a8
 		} else if (desc < 500000) {
83d9a8
 			if (file_printf(ms, " %d.%d", desc / 100000,
83d9a8
 			    desc / 10000 % 10 + desc / 1000 % 10) == -1)
83d9a8
-				return size;
83d9a8
+				return offset;
83d9a8
 			if (desc / 100 % 10 > 0) {
83d9a8
 				if (file_printf(ms, " (%d)", desc) == -1)
83d9a8
-					return size;
83d9a8
+					return offset;
83d9a8
 			} else if (desc / 10 % 10 > 0) {
83d9a8
 				if (file_printf(ms, ".%d", desc / 10 % 10)
83d9a8
 				    == -1)
83d9a8
-					return size;
83d9a8
+					return offset;
83d9a8
 			}
83d9a8
 		} else {
83d9a8
 			if (file_printf(ms, " %d.%d", desc / 100000,
83d9a8
 			    desc / 1000 % 100) == -1)
83d9a8
-				return size;
83d9a8
+				return offset;
83d9a8
 			if ((desc / 100 % 10 > 0) ||
83d9a8
 			    (desc % 100000 / 100 == 0)) {
83d9a8
 				if (file_printf(ms, " (%d)", desc) == -1)
83d9a8
-					return size;
83d9a8
+					return offset;
83d9a8
 			} else if (desc / 10 % 10 > 0) {
83d9a8
 				if (file_printf(ms, ".%d", desc / 10 % 10)
83d9a8
 				    == -1)
83d9a8
-					return size;
83d9a8
+					return offset;
83d9a8
 			}
83d9a8
 		}
83d9a8
 		*flags |= FLAGS_DID_NOTE;
83d9a8
-		return size;
83d9a8
+		return offset;
83d9a8
 	}
83d9a8
 
83d9a8
 	if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 &&
83d9a8
 	    xnh_type == NT_OPENBSD_VERSION && descsz == 4) {
83d9a8
 		if (file_printf(ms, ", for OpenBSD") == -1)
83d9a8
-			return size;
83d9a8
+			return offset;
83d9a8
 		/* Content of note is always 0 */
83d9a8
 		*flags |= FLAGS_DID_NOTE;
83d9a8
-		return size;
83d9a8
+		return offset;
83d9a8
 	}
83d9a8
 
83d9a8
 	if (namesz == 10 && strcmp((char *)&nbuf[noff], "DragonFly") == 0 &&
83d9a8
 	    xnh_type == NT_DRAGONFLY_VERSION && descsz == 4) {
83d9a8
 		uint32_t desc;
83d9a8
 		if (file_printf(ms, ", for DragonFly") == -1)
83d9a8
-			return size;
83d9a8
+			return offset;
83d9a8
 		(void)memcpy(&desc, &nbuf[doff], sizeof(desc));
83d9a8
 		desc = elf_getu32(swap, desc);
83d9a8
 		if (file_printf(ms, " %d.%d.%d", desc / 100000,
83d9a8
 		    desc / 10000 % 10, desc % 10000) == -1)
83d9a8
-			return size;
83d9a8
+			return offset;
83d9a8
 		*flags |= FLAGS_DID_NOTE;
83d9a8
-		return size;
83d9a8
+		return offset;
83d9a8
 	}
83d9a8
 
83d9a8
 core:
83d9a8
@@ -661,14 +836,22 @@ core:
83d9a8
 		os_style = OS_STYLE_NETBSD;
83d9a8
 	}
83d9a8
 
83d9a8
+	if ((*flags & FLAGS_DID_AUXV) == 0) {
83d9a8
+		if (do_auxv_note(ms, nbuf, xnh_type, swap,
83d9a8
+			namesz, descsz, noff, doff, flags, size, clazz,
83d9a8
+			fd, ph_off, ph_num, fsize))
83d9a8
+			return offset;
83d9a8
+	}
83d9a8
+
83d9a8
+
83d9a8
 #ifdef ELFCORE
83d9a8
 	if ((*flags & FLAGS_DID_CORE) != 0)
83d9a8
-		return size;
83d9a8
+		return offset;
83d9a8
 
83d9a8
 	if (os_style != -1 && (*flags & FLAGS_DID_CORE_STYLE) == 0) {
83d9a8
 		if (file_printf(ms, ", %s-style", os_style_names[os_style])
83d9a8
 		    == -1)
83d9a8
-			return size;
83d9a8
+			return offset;
83d9a8
 		*flags |= FLAGS_DID_CORE_STYLE;
83d9a8
 	}
83d9a8
 
83d9a8
@@ -683,7 +866,7 @@ core:
83d9a8
 			 */
83d9a8
 			if (file_printf(ms, ", from '%.31s'",
83d9a8
 			    &nbuf[doff + 0x7c]) == -1)
83d9a8
-				return size;
83d9a8
+				return offset;
83d9a8
 			
83d9a8
 			/*
83d9a8
 			 * Extract the signal number.  It is at
83d9a8
@@ -693,9 +876,9 @@ core:
83d9a8
 			    sizeof(signo));
83d9a8
 			if (file_printf(ms, " (signal %u)",
83d9a8
 			    elf_getu32(swap, signo)) == -1)
83d9a8
-				return size;
83d9a8
+				return offset;
83d9a8
 			*flags |= FLAGS_DID_CORE;
83d9a8
-			return size;
83d9a8
+			return offset;
83d9a8
 		}
83d9a8
 		break;
83d9a8
 
83d9a8
@@ -793,9 +976,9 @@ core:
83d9a8
 					cp--;
83d9a8
 				if (file_printf(ms, ", from '%.*s'",
83d9a8
 				    (int)(cp - cname), cname) == -1)
83d9a8
-					return size;
83d9a8
+					return offset;
83d9a8
 				*flags |= FLAGS_DID_CORE;
83d9a8
-				return size;
83d9a8
+				return offset;
83d9a8
 
83d9a8
 			tryanother:
83d9a8
 				;
83d9a8
@@ -936,7 +1119,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
83d9a8
 				if (noff >= (off_t)xsh_size)
83d9a8
 					break;
83d9a8
 				noff = donote(ms, nbuf, (size_t)noff,
83d9a8
-				    xsh_size, clazz, swap, 4, flags);
83d9a8
+				    xsh_size, clazz, swap, 4, flags, 0, 0, 0, 0);
83d9a8
 				if (noff == 0)
83d9a8
 					break;
83d9a8
 			}
83d9a8
@@ -1130,7 +1313,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
83d9a8
 					break;
83d9a8
 				offset = donote(ms, nbuf, offset,
83d9a8
 				    (size_t)bufsize, clazz, swap, align,
83d9a8
-				    flags);
83d9a8
+				    flags, 0, 0, 0, 0);
83d9a8
 				if (offset == 0)
83d9a8
 					break;
83d9a8
 			}
83d9a8
diff --git a/src/readelf.h b/src/readelf.h
83d9a8
index ab4b5d1..fb34585 100644
83d9a8
--- a/src/readelf.h
83d9a8
+++ b/src/readelf.h
83d9a8
@@ -62,6 +62,42 @@ typedef uint8_t		Elf64_Char;
83d9a8
 #define	EI_NIDENT	16
83d9a8
 
83d9a8
 typedef struct {
83d9a8
+	Elf32_Word	a_type;		/* 32-bit id */
83d9a8
+	Elf32_Word	a_v;		/* 32-bit id */
83d9a8
+} Aux32Info;
83d9a8
+
83d9a8
+typedef struct {
83d9a8
+	Elf64_Xword	a_type;		/* 64-bit id */
83d9a8
+	Elf64_Xword	a_v;		/* 64-bit id */
83d9a8
+} Aux64Info;
83d9a8
+
83d9a8
+#define AT_NULL   0     /* end of vector */
83d9a8
+#define AT_IGNORE 1     /* entry should be ignored */
83d9a8
+#define AT_EXECFD 2     /* file descriptor of program */
83d9a8
+#define AT_PHDR   3     /* program headers for program */
83d9a8
+#define AT_PHENT  4     /* size of program header entry */
83d9a8
+#define AT_PHNUM  5     /* number of program headers */
83d9a8
+#define AT_PAGESZ 6     /* system page size */
83d9a8
+#define AT_BASE   7     /* base address of interpreter */
83d9a8
+#define AT_FLAGS  8     /* flags */
83d9a8
+#define AT_ENTRY  9     /* entry point of program */
83d9a8
+#define AT_LINUX_NOTELF 10    /* program is not ELF */
83d9a8
+#define AT_LINUX_UID    11    /* real uid */
83d9a8
+#define AT_LINUX_EUID   12    /* effective uid */
83d9a8
+#define AT_LINUX_GID    13    /* real gid */
83d9a8
+#define AT_LINUX_EGID   14    /* effective gid */
83d9a8
+#define AT_LINUX_PLATFORM 15  /* string identifying CPU for optimizations */
83d9a8
+#define AT_LINUX_HWCAP  16    /* arch dependent hints at CPU capabilities */
83d9a8
+#define AT_LINUX_CLKTCK 17    /* frequency at which times() increments */
83d9a8
+/* AT_* values 18 through 22 are reserved */
83d9a8
+#define AT_LINUX_SECURE 23   /* secure mode boolean */
83d9a8
+#define AT_LINUX_BASE_PLATFORM 24     /* string identifying real platform, may
83d9a8
+                                 * differ from AT_PLATFORM. */
83d9a8
+#define AT_LINUX_RANDOM 25    /* address of 16 random bytes */
83d9a8
+#define AT_LINUX_HWCAP2 26    /* extension of AT_HWCAP */
83d9a8
+#define AT_LINUX_EXECFN 31   /* filename of program */
83d9a8
+
83d9a8
+typedef struct {
83d9a8
     Elf32_Char	e_ident[EI_NIDENT];
83d9a8
     Elf32_Half	e_type;
83d9a8
     Elf32_Half	e_machine;