| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462 | 
							- #include "file.h"
 
- #ifdef BUILTIN_ELF
 
- #ifdef HAVE_CONFIG_H
 
- #include <config.h>
 
- #endif
 
- #include <sys/types.h>
 
- #include <string.h>
 
- #include <stdio.h>
 
- #include <ctype.h>
 
- #include <stdlib.h>
 
- #ifdef HAVE_UNISTD_H
 
- #include <unistd.h>
 
- #endif
 
- #include <errno.h>
 
- #include "readelf.h"
 
- #ifndef lint
 
- FILE_RCSID("@(#)$Id: readelf.c,v 1.11 1999/10/31 22:23:04 christos Exp $")
 
- #endif
 
- #ifdef	ELFCORE
 
- static void dophn_core __P((int, int, int, off_t, int, size_t));
 
- #endif
 
- static void dophn_exec __P((int, int, int, off_t, int, size_t));
 
- static void doshn __P((int, int, int, off_t, int, size_t));
 
- static uint16_t getu16 __P((int, int));
 
- static uint32_t getu32 __P((int, uint32_t));
 
- static uint64_t getu64 __P((int, uint64_t));
 
- static uint16_t
 
- getu16(swap, value)
 
- 	int swap;
 
- 	uint16_t value;
 
- {
 
- 	union {
 
- 		uint16_t ui;
 
- 		char c[2];
 
- 	} retval, tmpval;
 
- 	if (swap) {
 
- 		tmpval.ui = value;
 
- 		retval.c[0] = tmpval.c[1];
 
- 		retval.c[1] = tmpval.c[0];
 
- 		
 
- 		return retval.ui;
 
- 	} else
 
- 		return value;
 
- }
 
- static uint32_t
 
- getu32(swap, value)
 
- 	int swap;
 
- 	uint32_t value;
 
- {
 
- 	union {
 
- 		uint32_t ui;
 
- 		char c[4];
 
- 	} retval, tmpval;
 
- 	if (swap) {
 
- 		tmpval.ui = value;
 
- 		retval.c[0] = tmpval.c[3];
 
- 		retval.c[1] = tmpval.c[2];
 
- 		retval.c[2] = tmpval.c[1];
 
- 		retval.c[3] = tmpval.c[0];
 
- 		
 
- 		return retval.ui;
 
- 	} else
 
- 		return value;
 
- }
 
- static uint64_t
 
- getu64(swap, value)
 
- 	int swap;
 
- 	uint64_t value;
 
- {
 
- 	union {
 
- 		uint64_t ui;
 
- 		char c[8];
 
- 	} retval, tmpval;
 
- 	if (swap) {
 
- 		tmpval.ui = value;
 
- 		retval.c[0] = tmpval.c[7];
 
- 		retval.c[1] = tmpval.c[6];
 
- 		retval.c[2] = tmpval.c[5];
 
- 		retval.c[3] = tmpval.c[4];
 
- 		retval.c[4] = tmpval.c[3];
 
- 		retval.c[5] = tmpval.c[2];
 
- 		retval.c[6] = tmpval.c[1];
 
- 		retval.c[7] = tmpval.c[0];
 
- 		
 
- 		return retval.ui;
 
- 	} else
 
- 		return value;
 
- }
 
- #define sh_addr		(class == ELFCLASS32		\
 
- 			 ? (void *) &sh32		\
 
- 			 : (void *) &sh64)
 
- #define shs_type	(class == ELFCLASS32		\
 
- 			 ? getu32(swap, sh32.sh_type)	\
 
- 			 : getu32(swap, sh64.sh_type))
 
- #define ph_addr		(class == ELFCLASS32		\
 
- 			 ? (void *) &ph32		\
 
- 			 : (void *) &ph64)
 
- #define ph_type		(class == ELFCLASS32		\
 
- 			 ? getu32(swap, ph32.p_type)	\
 
- 			 : getu32(swap, ph64.p_type))
 
- #define ph_offset	(class == ELFCLASS32		\
 
- 			 ? getu32(swap, ph32.p_offset)	\
 
- 			 : getu64(swap, ph64.p_offset))
 
- #define nh_size		(class == ELFCLASS32		\
 
- 			 ? sizeof *nh32			\
 
- 			 : sizeof *nh64)
 
- #define nh_type		(class == ELFCLASS32		\
 
- 			 ? getu32(swap, nh32->n_type)	\
 
- 			 : getu32(swap, nh64->n_type))
 
- #define nh_namesz	(class == ELFCLASS32		\
 
- 			 ? getu32(swap, nh32->n_namesz)	\
 
- 			 : getu32(swap, nh64->n_namesz))
 
- #define nh_descsz	(class == ELFCLASS32		\
 
- 			 ? getu32(swap, nh32->n_descsz)	\
 
- 			 : getu32(swap, nh64->n_descsz))
 
- #define prpsoffsets(i)	(class == ELFCLASS32		\
 
- 			 ? prpsoffsets32[i]		\
 
- 			 : prpsoffsets64[i])
 
- static void
 
- doshn(class, swap, fd, off, num, size)
 
- 	int class;
 
- 	int swap;
 
- 	int fd;
 
- 	off_t off;
 
- 	int num;
 
- 	size_t size;
 
- {
 
- 	Elf32_Shdr sh32;
 
- 	Elf64_Shdr sh64;
 
- 	if (lseek(fd, off, SEEK_SET) == -1)
 
- 		error("lseek failed (%s).\n", strerror(errno));
 
- 	for ( ; num; num--) {
 
- 		if (read(fd, sh_addr, size) == -1)
 
- 			error("read failed (%s).\n", strerror(errno));
 
- 		if (shs_type == SHT_SYMTAB /* || shs_type == SHT_DYNSYM */) {
 
- 			(void) printf (", not stripped");
 
- 			return;
 
- 		}
 
- 	}
 
- 	(void) printf (", stripped");
 
- }
 
- /*
 
-  * Look through the program headers of an executable image, searching
 
-  * for a PT_INTERP section; if one is found, it's dynamically linked,
 
-  * otherwise it's statically linked.
 
-  */
 
- static void
 
- dophn_exec(class, swap, fd, off, num, size)
 
- 	int class;
 
- 	int swap;
 
- 	int fd;
 
- 	off_t off;
 
- 	int num;
 
- 	size_t size;
 
- {
 
- 	Elf32_Phdr ph32;
 
- 	Elf64_Phdr ph64;
 
- 	char *linking_style = "statically";
 
- 	char *shared_libraries = "";
 
- 	if (lseek(fd, off, SEEK_SET) == -1)
 
- 		error("lseek failed (%s).\n", strerror(errno));
 
-   	for ( ; num; num--) {
 
-   		if (read(fd, ph_addr, size) == -1)
 
-   			error("read failed (%s).\n", strerror(errno));
 
- 		switch (ph_type) {
 
- 		case PT_DYNAMIC:
 
- 			linking_style = "dynamically";
 
- 			break;
 
- 		case PT_INTERP:
 
- 			shared_libraries = " (uses shared libs)";
 
- 			break;
 
- 		}
 
- 	}
 
- 	printf(", %s linked%s", linking_style, shared_libraries);
 
- }
 
- #ifdef ELFCORE
 
- size_t	prpsoffsets32[] = {
 
- 	84,		/* SunOS 5.x */
 
- 	32,		/* Linux */
 
- };
 
- size_t	prpsoffsets64[] = {
 
-        120,		/* SunOS 5.x, 64-bit */
 
- };
 
- #define	NOFFSETS32	(sizeof prpsoffsets32 / sizeof prpsoffsets32[0])
 
- #define NOFFSETS64	(sizeof prpsoffsets64 / sizeof prpsoffsets64[0])
 
- #define NOFFSETS	(class == ELFCLASS32 ? NOFFSETS32 : NOFFSETS64)
 
- /*
 
-  * Look through the program headers of an executable image, searching
 
-  * for a PT_NOTE section of type NT_PRPSINFO, with a name "CORE"; if one
 
-  * is found, try looking in various places in its contents for a 16-character
 
-  * string containing only printable characters - if found, that string
 
-  * should be the name of the program that dropped core.
 
-  * Note: right after that 16-character string is, at least in SunOS 5.x
 
-  * (and possibly other SVR4-flavored systems) and Linux, a longer string
 
-  * (80 characters, in 5.x, probably other SVR4-flavored systems, and Linux)
 
-  * containing the start of the command line for that program.
 
-  */
 
- static void
 
- dophn_core(class, swap, fd, off, num, size)
 
- 	int class;
 
- 	int swap;
 
- 	int fd;
 
- 	off_t off;
 
- 	int num;
 
- 	size_t size;
 
- {
 
- 	Elf32_Phdr ph32;
 
- 	Elf32_Nhdr *nh32;
 
- 	Elf64_Phdr ph64;
 
- 	Elf64_Nhdr *nh64;
 
- 	size_t offset, noffset, reloffset;
 
- 	unsigned char c;
 
- 	int i, j;
 
- 	char nbuf[BUFSIZ];
 
- 	int bufsize;
 
- 	for ( ; num; num--) {
 
- 		if (lseek(fd, off, SEEK_SET) == -1)
 
- 			error("lseek failed (%s).\n", strerror(errno));
 
- 		if (read(fd, ph_addr, size) == -1)
 
- 			error("read failed (%s).\n", strerror(errno));
 
- 		off += size;
 
- 		if (ph_type != PT_NOTE)
 
- 			continue;
 
- 		if (lseek(fd, (off_t) ph_offset, SEEK_SET) == -1)
 
- 			error("lseek failed (%s).\n", strerror(errno));
 
- 		bufsize = read(fd, nbuf, BUFSIZ);
 
- 		if (bufsize == -1)
 
- 			error("read failed (%s).\n", strerror(errno));
 
- 		offset = 0;
 
- 		for (;;) {
 
- 			if (offset >= bufsize)
 
- 				break;
 
- 			if (class == ELFCLASS32)
 
- 				nh32 = (Elf32_Nhdr *)&nbuf[offset];
 
- 			else
 
- 				nh64 = (Elf64_Nhdr *)&nbuf[offset];
 
- 			offset += nh_size;
 
- 			/*
 
- 			 * If this note isn't an NT_PRPSINFO note, it's
 
- 			 * not what we're looking for.
 
- 			 */
 
- 			if (nh_type != NT_PRPSINFO) {
 
- 				offset += nh_namesz;
 
- 				offset = ((offset + 3)/4)*4;
 
- 				offset += nh_descsz;
 
- 				offset = ((offset + 3)/4)*4;
 
- 				continue;
 
- 			}
 
- 			/*
 
- 			 * Make sure this note has the name "CORE".
 
- 			 */
 
- 			if (offset + nh_namesz >= bufsize) {
 
- 				/*
 
- 				 * We're past the end of the buffer.
 
- 				 */
 
- 				break;
 
- 			}
 
- 			if (nh_namesz != 5
 
- 			    || strcmp(&nbuf[offset], "CORE") != 0)
 
- 				continue;
 
- 			offset += nh_namesz;
 
- 			offset = ((offset + 3)/4)*4;
 
- 			/*
 
- 			 * Extract the program name.  We assume it to be
 
- 			 * 16 characters (that's what it is in SunOS 5.x
 
- 			 * and Linux).
 
- 			 *
 
- 			 * Unfortunately, it's at a different offset in
 
- 			 * SunOS 5.x and Linux, so try multiple offsets.
 
- 			 * If the characters aren't all printable, reject
 
- 			 * it.
 
- 			 */
 
- 			for (i = 0; i < NOFFSETS; i++) {
 
- 				reloffset = prpsoffsets(i);
 
- 				noffset = offset + reloffset;
 
- 				for (j = 0; j < 16;
 
- 				    j++, noffset++, reloffset++) {
 
- 					/*
 
- 					 * Make sure we're not past the end
 
- 					 * of the buffer; if we are, just
 
- 					 * give up.
 
- 					 */
 
- 					if (noffset >= bufsize)
 
- 						return;
 
- 					/*
 
- 					 * Make sure we're not past the
 
- 					 * end of the contents; if we
 
- 					 * are, this obviously isn't
 
- 					 * the right offset.
 
- 					 */
 
- 					if (reloffset >= nh_descsz)
 
- 						goto tryanother;
 
- 					c = nbuf[noffset];
 
- 					if (c != '\0' && !isprint(c))
 
- 						goto tryanother;
 
- 				}
 
- 				/*
 
- 				 * Well, that worked.
 
- 				 */
 
- 				printf(", from '%.16s'",
 
- 				    &nbuf[offset + prpsoffsets(i)]);
 
- 				return;
 
- 			tryanother:
 
- 				;
 
- 			}
 
- 			offset += nh_descsz;
 
- 			offset = ((offset + 3)/4)*4;
 
- 		}
 
- 	}
 
- }
 
- #endif
 
- void
 
- tryelf(fd, buf, nbytes)
 
- 	int fd;
 
- 	unsigned char *buf;
 
- 	int nbytes;
 
- {
 
- 	union {
 
- 		int32 l;
 
- 		char c[sizeof (int32)];
 
- 	} u;
 
- 	int class;
 
- 	int swap;
 
- 	/*
 
- 	 * ELF executables have multiple section headers in arbitrary
 
- 	 * file locations and thus file(1) cannot determine it from easily.
 
- 	 * Instead we traverse thru all section headers until a symbol table
 
- 	 * one is found or else the binary is stripped.
 
- 	 */
 
- 	if (buf[EI_MAG0] != ELFMAG0
 
- 	    || (buf[EI_MAG1] != ELFMAG1 && buf[EI_MAG1] != OLFMAG1)
 
- 	    || buf[EI_MAG2] != ELFMAG2 || buf[EI_MAG3] != ELFMAG3)
 
- 	    return;
 
- 	class = buf[4];
 
- 	if (class == ELFCLASS32) {
 
- 		Elf32_Ehdr elfhdr;
 
- 		if (nbytes <= sizeof (Elf32_Ehdr))
 
- 			return;
 
- 		u.l = 1;
 
- 		(void) memcpy(&elfhdr, buf, sizeof elfhdr);
 
- 		swap = (u.c[sizeof(long) - 1] + 1) != elfhdr.e_ident[5];
 
- 		if (getu16(swap, elfhdr.e_type) == ET_CORE) 
 
- #ifdef ELFCORE
 
- 			dophn_core(class, swap,
 
- 				   fd,
 
- 				   getu32(swap, elfhdr.e_phoff),
 
- 				   getu16(swap, elfhdr.e_phnum), 
 
- 				   getu16(swap, elfhdr.e_phentsize));
 
- #else
 
- 			;
 
- #endif
 
- 		else {
 
- 			if (getu16(swap, elfhdr.e_type) == ET_EXEC) {
 
- 				dophn_exec(class, swap,
 
- 					   fd,
 
- 					   getu32(swap, elfhdr.e_phoff),
 
- 					   getu16(swap, elfhdr.e_phnum), 
 
- 					   getu16(swap, elfhdr.e_phentsize));
 
- 			}
 
- 			doshn(class, swap,
 
- 			      fd,
 
- 			      getu32(swap, elfhdr.e_shoff),
 
- 			      getu16(swap, elfhdr.e_shnum),
 
- 			      getu16(swap, elfhdr.e_shentsize));
 
- 		}
 
- 		return;
 
- 	}
 
-         if (class == ELFCLASS64) {
 
- 		Elf64_Ehdr elfhdr;
 
- 		if (nbytes <= sizeof (Elf64_Ehdr))
 
- 			return;
 
- 		u.l = 1;
 
- 		(void) memcpy(&elfhdr, buf, sizeof elfhdr);
 
- 		swap = (u.c[sizeof(long) - 1] + 1) != elfhdr.e_ident[5];
 
- 		if (getu16(swap, elfhdr.e_type) == ET_CORE) 
 
- #ifdef ELFCORE
 
- 			dophn_core(class, swap,
 
- 				   fd,
 
- #ifdef USE_ARRAY_FOR_64BIT_TYPES
 
- 				   getu32(swap, elfhdr.e_phoff[1]),
 
- #else
 
- 				   getu64(swap, elfhdr.e_phoff),
 
- #endif
 
- 				   getu16(swap, elfhdr.e_phnum), 
 
- 				   getu16(swap, elfhdr.e_phentsize));
 
- #else
 
- 			;
 
- #endif
 
- 		else
 
- 		{
 
- 			if (getu16(swap, elfhdr.e_type) == ET_EXEC) {
 
- 				dophn_exec(class, swap,
 
- 					   fd,
 
- #ifdef USE_ARRAY_FOR_64BIT_TYPES
 
- 					   getu32(swap, elfhdr.e_phoff[1]),
 
- #else
 
- 					   getu64(swap, elfhdr.e_phoff),
 
- #endif
 
- 					   getu16(swap, elfhdr.e_phnum), 
 
- 					   getu16(swap, elfhdr.e_phentsize));
 
- 			}
 
- 			doshn(class, swap,
 
- 			      fd,
 
- #ifdef USE_ARRAY_FOR_64BIT_TYPES
 
- 			      getu32(swap, elfhdr.e_shoff[1]),
 
- #else
 
- 			      getu64(swap, elfhdr.e_shoff),
 
- #endif
 
- 			      getu16(swap, elfhdr.e_shnum),
 
- 			      getu16(swap, elfhdr.e_shentsize));
 
- 		}
 
- 		return;
 
- 	}
 
- }
 
- #endif
 
 
  |