From: Christos Zoulas Date: Wed, 15 Jan 1997 17:23:24 +0000 (+0000) Subject: - add support for elf core files: find the program name under SVR4 [Ken Pizzini] X-Git-Tag: FILE3_27~55 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=898cb07d7cdc1db8c9cef07715fcc819bb111c98;p=file - add support for elf core files: find the program name under SVR4 [Ken Pizzini] - print strings only up to the first carriage return [various] - freebsd international ascii support [J Wunsch] - magic fixes and additions [Guy Harris] - 64 bit fixes [Larry Schwimmer] - support for both utime and utimes, but don't restore file access times by default [various] - \xXX only takes 2 hex digits, not 3. - re-implement support for core files [Guy Harris] --- diff --git a/README b/README index 2ee8e677..f88f185f 100644 --- a/README +++ b/README @@ -1,11 +1,9 @@ ** README for file(1) Command ** -@(#) $Id: README,v 1.20 1993/09/23 21:47:01 christos Exp $ +@(#) $Id: README,v 1.21 1997/01/15 17:23:24 christos Exp $ This is Release 3.x of Ian Darwin's (copyright but distributable) -file(1) command. Release 3.x is scheduled for inclusion in the -4.4 BSD (Berkeley Software Distribution) of UNIX-like -software, and is the standard "file" command for Linux, 386bsd, -and other systems. (See "patchlevel.h" for the exact release number). +file(1) command. This version is the standard "file" command for Linux, +*BSD, and other systems. (See "patchlevel.h" for the exact release number). UNIX is a trademark of UNIX System Laboratories. @@ -58,15 +56,29 @@ magic.4 - man page for the magic file, courtesy Guy Harris. file.c - main program file.h - header file fsmagic.c - first set of tests the program runs, based on filesystem info -is_tar.c - knows about tarchives (courtesy John Gilmore). +is_tar.c, tar.h - knows about tarchives (courtesy John Gilmore). magdir - directory of /etc/magic pieces magdir/Makefile - ADJUST THIS FOR YOUR CONFIGURATION names.h - header file for ascmagic.c softmagic.c - 2nd set of tests, based on /etc/magic -strtok.c, getopt.c - in case you them (courtesy of Henry Spencer). -strtol.c, strchr.c - in case you need them - public domain. -tst - simple test suite, built from tst/Makefile +readelf.[ch] - Standalone elf parsing code. +compress.c - on-the-fly decompression. +internat.c - recognize international `text' files. +print.c - print results, errors, warnings. +If your gzip sometimes fails to decompress things complaining about a short +file, apply this patch [which is going to be in the next version of gzip]: +*** - Tue Oct 29 02:06:35 1996 +--- util.c Sun Jul 21 21:51:38 1996 +*** 106,111 **** +--- 108,114 ---- + + if (insize == 0) { + if (eof_ok) return EOF; ++ flush_window(); + read_error(); + } + bytes_in += (ulg)insize; E-mail: christos@deshaw.com, moraes@deshaw.com diff --git a/doc/file.man b/doc/file.man index 32a1c391..9c5cfb0f 100644 --- a/doc/file.man +++ b/doc/file.man @@ -1,5 +1,5 @@ .TH FILE __CSECTION__ "Copyright but distributable" -.\" $Id: file.man,v 1.27 1996/06/22 22:05:07 christos Exp $ +.\" $Id: file.man,v 1.28 1997/01/15 17:23:24 christos Exp $ .SH NAME file \- determine file type @@ -248,7 +248,7 @@ the process running .RE .PP Changes by Ian Darwin and various authors including -Christos Zoulas (christos@ee.cornell.edu), 1990-1992. +Christos Zoulas (christos@deshaw.com), 1990-1992. .SH LEGAL NOTICE Copyright (c) Ian F. Darwin, Toronto, Canada, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993. @@ -360,6 +360,6 @@ This manual page, and particularly this section, is too long. .SH AVAILABILITY You can obtain the original author's latest version by anonymous FTP on -.B tesla.ee.cornell.edu +.B ftp.deshaw.com in the directory -.I /pub/file-X.YY.tar.gz +.I /pub/file/file-X.YY.tar.gz diff --git a/src/Makefile b/src/Makefile index 40007c15..fde51c97 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,6 @@ # Makefile for file(1) cmd. # Copyright (c) Ian F. Darwin 86/09/01 - see LEGAL.NOTICE. -# @(#)$Id: Makefile,v 1.54 1996/12/16 03:33:34 christos Exp $ +# @(#)$Id: Makefile,v 1.55 1997/01/15 17:23:24 christos Exp $ # # This software is not subject to any license of the American Telephone # and Telegraph Company or of the Regents of the University of California. @@ -21,7 +21,7 @@ # ever read sources, credits must appear in the documentation. # # 4. This notice may not be removed or altered. -VERSION = 3.21 +VERSION = 3.22 SHELL = /bin/sh #MAGIC = /etc/magic MAGIC = /usr/local/etc/magic @@ -70,10 +70,10 @@ LOCALOBJS = # localsrc/getopt.o localsrc/strtol.o \ LOCALINC = # localinc/*.h localinc/sys/*.h SRCS = file.c apprentice.c fsmagic.c softmagic.c ascmagic.c \ - compress.c is_tar.c readelf.c international.c \ + compress.c is_tar.c readelf.c internat.c \ print.c $(LOCALSRCS) $(LOCALINC) OBJS = file.o apprentice.o fsmagic.o softmagic.o ascmagic.o \ - compress.o is_tar.o readelf.o international.o \ + compress.o is_tar.o readelf.o internat.o \ print.o $(LOCALOBJS) ALLSRC = LEGAL.NOTICE README MAINT PORTING $(SRCS) *.h \ diff --git a/src/apprentice.c b/src/apprentice.c index 6bdfffef..7d8d9e2e 100644 --- a/src/apprentice.c +++ b/src/apprentice.c @@ -34,7 +34,7 @@ #ifndef lint static char *moduleid = - "@(#)$Id: apprentice.c,v 1.24 1996/06/22 22:04:22 christos Exp $"; + "@(#)$Id: apprentice.c,v 1.25 1997/01/15 17:23:24 christos Exp $"; #endif /* lint */ #define EATAB {while (isascii((unsigned char) *l) && \ @@ -133,10 +133,10 @@ int check; /* non-zero? checking-only run. */ /* * extend the sign bit if the comparison is to be signed */ -unsigned long +uint32 signextend(m, v) struct magic *m; -unsigned long v; +uint32 v; { if (!(m->flag & UNSIGNED)) switch(m->type) { @@ -159,7 +159,7 @@ unsigned long v; case LONG: case BELONG: case LELONG: - v = (long) v; + v = (int32) v; break; case STRING: break; @@ -495,21 +495,16 @@ int plen, *slen; *p++ = (char)val; break; - /* \x and up to 3 hex digits */ + /* \x and up to 2 hex digits */ case 'x': val = 'x'; /* Default if no digits */ c = hextoint(*s++); /* Get next char */ if (c >= 0) { val = c; c = hextoint(*s++); - if (c >= 0) { + if (c >= 0) val = (val << 4) + c; - c = hextoint(*s++); - if (c >= 0) { - val = (val << 4) + c; - } else - --s; - } else + else --s; } else --s; diff --git a/src/ascmagic.c b/src/ascmagic.c index 600d468b..7ba9ae1c 100644 --- a/src/ascmagic.c +++ b/src/ascmagic.c @@ -36,7 +36,7 @@ #ifndef lint static char *moduleid = - "@(#)$Id: ascmagic.c,v 1.20 1995/05/20 22:09:21 christos Exp $"; + "@(#)$Id: ascmagic.c,v 1.21 1997/01/15 17:23:24 christos Exp $"; #endif /* lint */ /* an optimisation over plain strcmp() */ @@ -88,6 +88,13 @@ int nbytes; /* size actually read */ return 1; } + + /* Make sure we are dealing with ascii text before looking for tokens */ + for (i = 0; i < nbytes; i++) { + if (!isascii(buf[i])) + return 0; /* not all ASCII */ + } + /* look for tokens from names.h - this is expensive! */ /* make a copy of the buffer here because strtok() will destroy it */ s = (unsigned char*) memcpy(nbuf, buf, nbytes); @@ -106,12 +113,6 @@ int nbytes; /* size actually read */ } } - - for (i = 0; i < nbytes; i++) { - if (!isascii(buf[i])) - return 0; /* not all ASCII */ - } - /* all else fails, but it is ASCII... */ ckfputs("ASCII text", stdout); if (has_escapes) { diff --git a/src/file.c b/src/file.c index 3b6b1ca9..22a3c442 100644 --- a/src/file.c +++ b/src/file.c @@ -26,7 +26,7 @@ */ #ifndef lint static char *moduleid = - "@(#)$Id: file.c,v 1.36 1996/10/05 18:13:57 christos Exp $"; + "@(#)$Id: file.c,v 1.37 1997/01/15 17:23:24 christos Exp $"; #endif /* lint */ #include @@ -37,9 +37,13 @@ static char *moduleid = #include #include /* for open() */ #if (__COHERENT__ >= 0x420) -#include +# include #else -#include +# ifdef USE_UTIMES +# include +# else +# include +# endif #endif #include /* for read() */ @@ -281,7 +285,6 @@ int wid; int fd = 0; static const char stdname[] = "standard input"; unsigned char buf[HOWMANY+1]; /* one extra for terminating '\0' */ - struct utimbuf utbuf; struct stat sb; int nbytes = 0; /* number of bytes read from a datafile */ char match = '\0'; @@ -340,12 +343,24 @@ int wid; #endif if (inname != stdname) { +#ifdef RESTORE_TIME /* * Try to restore access, modification times if read it. */ +# ifdef USE_UTIMES + struct timeval utsbuf[2]; + utsbuf[0].tv_sec = sb.st_atime; + utsbuf[1].tv_sec = sb.st_mtime; + + (void) utimes(inname, utsbuf); /* don't care if loses */ +# else + struct utimbuf utbuf; + utbuf.actime = sb.st_atime; utbuf.modtime = sb.st_mtime; (void) utime(inname, &utbuf); /* don't care if loses */ +# endif +#endif (void) close(fd); } (void) putchar('\n'); @@ -369,6 +384,10 @@ int nb, zflag; if (ascmagic(buf, nb)) return 'a'; + /* see if it's international language text */ + if (internatmagic(buf, nb)) + return 'i'; + /* abandon hope, all ye who remain here */ ckfputs("data", stdout); return '\0'; diff --git a/src/file.h b/src/file.h index 3c4363cc..513ffd66 100644 --- a/src/file.h +++ b/src/file.h @@ -1,6 +1,6 @@ /* * file.h - definitions for file(1) program - * @(#)$Id: file.h,v 1.23 1996/06/22 22:04:22 christos Exp $ + * @(#)$Id: file.h,v 1.24 1997/01/15 17:23:24 christos Exp $ * * Copyright (c) Ian F. Darwin, 1987. * Written by Ian F. Darwin. @@ -26,6 +26,12 @@ * 4. This notice may not be removed or altered. */ +#ifndef __file_h__ +#define __file_h__ + +typedef int int32; +typedef unsigned int uint32; + #ifndef HOWMANY # define HOWMANY 8192 /* how much of the file to look at */ #endif @@ -41,9 +47,9 @@ struct magic { short cont_level; /* level of ">" */ struct { char type; /* byte short long */ - long offset; /* offset from indirection */ + int32 offset; /* offset from indirection */ } in; - long offset; /* offset to magic number */ + int32 offset; /* offset to magic number */ unsigned char reln; /* relation (0=eq, '>'=gt, etc) */ char type; /* int, short, long or string. */ char vallen; /* length of string value, if any */ @@ -61,12 +67,12 @@ struct magic { union VALUETYPE { unsigned char b; unsigned short h; - unsigned long l; + uint32 l; char s[MAXstring]; unsigned char hs[2]; /* 2 bytes of a fixed-endian "short" */ unsigned char hl[4]; /* 2 bytes of a fixed-endian "long" */ } value; /* either number or string */ - unsigned long mask; /* mask before comparison with value */ + uint32 mask; /* mask before comparison with value */ char nospflag; /* supress space character */ char desc[MAXDESC]; /* description */ }; @@ -98,7 +104,7 @@ extern int softmagic __P((unsigned char *, int)); extern int tryit __P((unsigned char *, int, int)); extern int zmagic __P((unsigned char *, int)); extern void ckfprintf __P((FILE *, const char *, ...)); -extern unsigned long signextend __P((struct magic *, unsigned long)); +extern uint32 signextend __P((struct magic *, unsigned int32)); @@ -119,7 +125,16 @@ extern int lflag; /* follow symbolic links? */ extern int optind; /* From getopt(3) */ extern char *optarg; -#if !defined(__STDC__) || defined(sun) || defined(__sun__) || defined(__convex__) +#if defined(sun) || defined(__sun__) || defined (__sun) +# if defined(__svr4) || defined (__SVR4) || defined(__svr4__) +# define SOLARIS +# else +# define SUNOS +# endif +#endif + + +#if !defined(__STDC__) || defined(SUNOS) || defined(__convex__) extern int sys_nerr; extern char *sys_errlist[]; #define strerror(e) \ @@ -130,3 +145,5 @@ extern char *sys_errlist[]; #ifndef MAXPATHLEN #define MAXPATHLEN 512 #endif + +#endif /* __file_h__ */ diff --git a/src/is_tar.c b/src/is_tar.c index 5b036be1..86541041 100644 --- a/src/is_tar.c +++ b/src/is_tar.c @@ -5,7 +5,7 @@ * Pubic Domain version written 26 Aug 1985 John Gilmore (ihnp4!hoptoad!gnu). * * @(#)list.c 1.18 9/23/86 Public Domain - gnu - * $Id: is_tar.c,v 1.8 1993/09/16 21:09:35 christos Exp $ + * $Id: is_tar.c,v 1.9 1997/01/15 17:23:24 christos Exp $ * * Comments changed and some code/comments reformatted * for file command by Ian Darwin. @@ -19,9 +19,9 @@ #define isodigit(c) ( ((c) >= '0') && ((c) <= '7') ) #if defined(__STDC__) || defined(__cplusplus) -static long from_oct(int, char*); /* Decode octal number */ +static int from_oct(int, char*); /* Decode octal number */ #else -static long from_oct(); +static int from_oct(); #endif /* @@ -37,7 +37,7 @@ int nbytes; { register union record *header = (union record *)buf; register int i; - register long sum, recsum; + register int sum, recsum; register char *p; if (nbytes < sizeof(union record)) @@ -75,12 +75,12 @@ int nbytes; * * Result is -1 if the field is invalid (all blank, or nonoctal). */ -static long +static int from_oct(digs, where) register int digs; register char *where; { - register long value; + register int value; while (isspace(*where)) { /* Skip spaces */ where++; diff --git a/src/names.h b/src/names.h index 86633dd0..54d1cbb1 100644 --- a/src/names.h +++ b/src/names.h @@ -10,22 +10,24 @@ * * See LEGAL.NOTICE * - * $Id: names.h,v 1.12 1995/04/28 17:29:13 christos Exp $ + * $Id: names.h,v 1.13 1997/01/15 17:23:24 christos Exp $ */ /* these types are used to index the table 'types': keep em in sync! */ #define L_C 0 /* first and foremost on UNIX */ -#define L_FORT 1 /* the oldest one */ -#define L_MAKE 2 /* Makefiles */ -#define L_PLI 3 /* PL/1 */ -#define L_MACH 4 /* some kinda assembler */ -#define L_ENG 5 /* English */ -#define L_PAS 6 /* Pascal */ -#define L_MAIL 7 /* Electronic mail */ -#define L_NEWS 8 /* Usenet Netnews */ +#define L_CC 1 /* Bjarne's postincrement */ +#define L_FORT 2 /* the oldest one */ +#define L_MAKE 3 /* Makefiles */ +#define L_PLI 4 /* PL/1 */ +#define L_MACH 5 /* some kinda assembler */ +#define L_ENG 6 /* English */ +#define L_PAS 7 /* Pascal */ +#define L_MAIL 8 /* Electronic mail */ +#define L_NEWS 9 /* Usenet Netnews */ static char *types[] = { "C program text", + "C++ program text", "FORTRAN program text", "make commands text" , "PL/1 program text", @@ -43,6 +45,12 @@ static struct names { } names[] = { /* These must be sorted by eye for optimal hit rate */ /* Add to this list only after substantial meditation */ + {"//", L_CC}, + {"template", L_CC}, + {"virtual", L_CC}, + {"class", L_CC}, + {"public:", L_CC}, + {"private:", L_CC}, {"/*", L_C}, /* must precede "The", "the", etc. */ {"#include", L_C}, {"char", L_C}, diff --git a/src/patchlevel.h b/src/patchlevel.h index 10708c5c..387ac2ca 100644 --- a/src/patchlevel.h +++ b/src/patchlevel.h @@ -1,11 +1,22 @@ #define FILE_VERSION_MAJOR 3 -#define patchlevel 21 +#define patchlevel 22 /* * Patchlevel file for Ian Darwin's MAGIC command. - * $Id: patchlevel.h,v 1.21 1996/10/05 18:15:29 christos Exp $ + * $Id: patchlevel.h,v 1.22 1997/01/15 17:23:24 christos Exp $ * * $Log: patchlevel.h,v $ + * Revision 1.22 1997/01/15 17:23:24 christos + * - add support for elf core files: find the program name under SVR4 [Ken Pizzini] + * - print strings only up to the first carriage return [various] + * - freebsd international ascii support [J Wunsch] + * - magic fixes and additions [Guy Harris] + * - 64 bit fixes [Larry Schwimmer] + * - support for both utime and utimes, but don't restore file access times + * by default [various] + * - \xXX only takes 2 hex digits, not 3. + * - re-implement support for core files [Guy Harris] + * * Revision 1.21 1996/10/05 18:15:29 christos * Segregate elf stuff and conditionally enable it with -DBUILTIN_ELF * More magic fixes diff --git a/src/readelf.c b/src/readelf.c index dc4a3ac0..6f6f3b40 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -1,13 +1,11 @@ #ifdef BUILTIN_ELF +#include #include #include #include #include #include -#ifdef __SVR4 -#include -#endif #include "readelf.h" #include "file.h" @@ -20,7 +18,14 @@ doshn(fd, off, num, size, buf) size_t size; char *buf; { - /* This works for both 32 and 64 bit elf formats */ + /* + * This works for both 32-bit and 64-bit ELF formats, + * because it looks only at the "sh_type" field, which is + * always 32 bits, and is preceded only by the "sh_name" + * field which is also always 32 bits, and because it uses + * the shdr size from the ELF header rather than using + * the size of an "Elf32_Shdr". + */ Elf32_Shdr *sh = (Elf32_Shdr *) buf; if (lseek(fd, off, SEEK_SET) == -1) @@ -29,17 +34,21 @@ doshn(fd, off, num, size, buf) for ( ; num; num--) { if (read(fd, buf, size) == -1) error("read failed (%s).\n", strerror(errno)); - if (sh->sh_type == SHT_SYMTAB) + if (sh->sh_type == SHT_SYMTAB) { + (void) printf (", not stripped"); return; + } } (void) printf (", stripped"); } /* - * From: Ken Pizzini + * 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(fd, off, num, size, buf) +dophn_exec(fd, off, num, size, buf) int fd; off_t off; int num; @@ -47,48 +56,168 @@ dophn(fd, off, num, size, buf) char *buf; { /* I am not sure if this works for 64 bit elf formats */ - Elf32_Phdr ph; - Elf32_Nhdr nh; - off_t off_sv; - off_t fname_off; + Elf32_Phdr *ph = (Elf32_Phdr *) buf; if (lseek(fd, off, SEEK_SET) == -1) error("lseek failed (%s).\n", strerror(errno)); + for ( ; num; num--) { + if (read(fd, buf, size) == -1) + error("read failed (%s).\n", strerror(errno)); + if (ph->p_type == PT_INTERP) { + /* + * Has an interpreter - must be a dynamically-linked + * executable. + */ + printf(", dynamically linked"); + return; + } + } + printf(", statically linked"); +} + +size_t prpsoffsets[] = { + 100, /* SunOS 5.x */ + 32, /* Linux */ +}; + +#define NOFFSETS (sizeof prpsoffsets / sizeof prpsoffsets[0]) + +/* + * 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(fd, off, num, size, buf) + int fd; + off_t off; + int num; + size_t size; + char *buf; +{ + /* + * This doesn't work for 64-bit ELF, as the "p_offset" field is + * 64 bits in 64-bit ELF. + */ + /* + * This doesn't work for 64-bit ELF, as the "p_offset" field is + * 64 bits in 64-bit ELF. + */ + Elf32_Phdr *ph = (Elf32_Phdr *) buf; + Elf32_Nhdr *nh; + size_t offset, noffset, reloffset; + unsigned char c; + int i, j; + char nbuf[BUFSIZ]; + int bufsize; + for ( ; num; num--) { - if (read(fd, &ph, sizeof ph) != sizeof ph) + if (lseek(fd, off, SEEK_SET) == -1) + error("lseek failed (%s).\n", strerror(errno)); + if (read(fd, buf, size) == -1) error("read failed (%s).\n", strerror(errno)); - if (ph.p_type != PT_NOTE) + off += size; + if (ph->p_type != PT_NOTE) continue; - off_sv = lseek(fd, ph.p_offset, SEEK_SET); - if (off_sv == -1) + if (lseek(fd, ph->p_offset, SEEK_SET) == -1) error("lseek failed (%s).\n", strerror(errno)); - if (read(fd, &nh, sizeof nh) != sizeof nh) + bufsize = read(fd, nbuf, BUFSIZ); + if (bufsize == -1) error("read failed (%s).\n", strerror(errno)); - if (nh.n_type != NT_PRPSINFO) { - if (lseek(fd, off_sv, SEEK_SET) == -1) - error("lseek failed (%s).\n", strerror(errno)); - continue; - } + offset = 0; + for (;;) { + if (offset >= bufsize) + break; + nh = (Elf32_Nhdr *)&nbuf[offset]; + offset += sizeof *nh; -#ifdef __SVR4 + /* + * If this note isn't an NT_PRPSINFO note, it's + * not what we're looking for. + */ + if (nh->n_type != NT_PRPSINFO) { + offset += nh->n_namesz; + offset = ((offset + 3)/4)*4; + offset += nh->n_descsz; + offset = ((offset + 3)/4)*4; + continue; + } -#define ALIGN(n) (((n)+3) & ~3) /* round up to nearest multiple of 4 */ -#define offsetof(a, b) (int) &((a *) 0)->b + /* + * Make sure this note has the name "CORE". + */ + if (offset + nh->n_namesz >= bufsize) { + /* + * We're past the end of the buffer. + */ + break; + } + if (nh->n_namesz != 5 + || strcmp(&nbuf[offset], "CORE") != 0) + continue; + offset += nh->n_namesz; + offset = ((offset + 3)/4)*4; - fname_off = offsetof(struct prpsinfo, pr_fname) + - ALIGN(nh.n_namesz); - if (lseek(fd, fname_off, SEEK_CUR) == -1) - error("lseek failed (%s).\n", strerror(errno)); - if (read(fd, buf, size) == -1) - error("read failed (%s).\n", strerror(errno)); - (void) printf ("; from `%s'", buf); -#endif - return; + /* + * 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->n_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->n_descsz; + offset = ((offset + 3)/4)*4; + } } } - void tryelf(fd, buf, nbytes) int fd; @@ -96,8 +225,8 @@ tryelf(fd, buf, nbytes) int nbytes; { union { - long l; - char c[sizeof (long)]; + int32 l; + char c[sizeof (int32)]; } u; /* @@ -119,21 +248,27 @@ tryelf(fd, buf, nbytes) u.l = 1; (void) memcpy(&elfhdr, buf, sizeof elfhdr); - - if (elfhdr.e_type == ET_CORE) - dophn(fd, elfhdr.e_phoff, elfhdr.e_phnum, - elfhdr.e_phentsize, buf); - else - { - /* - * If the system byteorder does not equal the - * object byteorder then don't test. - */ - if ((u.c[sizeof(long) - 1] + 1) == elfhdr.e_ident[5]) + /* + * If the system byteorder does not equal the + * object byteorder then don't test. + * XXX - we could conceivably fix up the "dophn_XXX()" and + * "doshn()" routines to extract stuff in the right + * byte order.... + */ + if ((u.c[sizeof(long) - 1] + 1) == elfhdr.e_ident[5]) { + if (elfhdr.e_type == ET_CORE) + dophn_core(fd, elfhdr.e_phoff, elfhdr.e_phnum, + elfhdr.e_phentsize, buf); + else { + if (elfhdr.e_type == ET_EXEC) { + dophn_exec(fd, elfhdr.e_phoff, + elfhdr.e_phnum, + elfhdr.e_phentsize, buf); + } doshn(fd, elfhdr.e_shoff, elfhdr.e_shnum, elfhdr.e_shentsize, buf); + } } - return; } @@ -146,20 +281,32 @@ tryelf(fd, buf, nbytes) u.l = 1; (void) memcpy(&elfhdr, buf, sizeof elfhdr); - if (elfhdr.e_type == ET_CORE) - dophn(fd, elfhdr.e_phoff, elfhdr.e_phnum, - elfhdr.e_phentsize, buf); - else - { - /* - * If the system byteorder does not equal the - * object byteorder then don't test. - */ - if ((u.c[sizeof(long) - 1] + 1) == elfhdr.e_ident[5]) + /* + * If the system byteorder does not equal the + * object byteorder then don't test. + * XXX - we could conceivably fix up the "dophn_XXX()" and + * "doshn()" routines to extract stuff in the right + * byte order.... + */ + if ((u.c[sizeof(long) - 1] + 1) == elfhdr.e_ident[5]) { +#ifdef notyet + if (elfhdr.e_type == ET_CORE) + dophn_core(fd, elfhdr.e_phoff, elfhdr.e_phnum, + elfhdr.e_phentsize, buf); + else +#endif + { +#ifdef notyet + if (elfhdr.e_type == ET_EXEC) { + dophn_exec(fd, elfhdr.e_phoff, + elfhdr.e_phnum, + elfhdr.e_phentsize, buf); + } +#endif doshn(fd, elfhdr.e_shoff, elfhdr.e_shnum, elfhdr.e_shentsize, buf); + } } - return; } } diff --git a/src/readelf.h b/src/readelf.h index 15fb8573..c4b42d7e 100644 --- a/src/readelf.h +++ b/src/readelf.h @@ -1,6 +1,6 @@ /* * readelf.h - * @(#)$Id: readelf.h,v 1.3 1996/10/25 18:11:51 christos Exp $ + * @(#)$Id: readelf.h,v 1.4 1997/01/15 17:23:24 christos Exp $ * * Provide elf data structures for non-elf machines, allowing file * non-elf hosts to determine if an elf binary is stripped. @@ -59,6 +59,7 @@ typedef struct { } Elf64_Ehdr; /* e_type */ +#define ET_EXEC 2 #define ET_CORE 4 /* sh_type */ @@ -137,11 +138,17 @@ typedef struct { Elf64_Off sh_entsize; } Elf64_Shdr; - -typedef struct { - Elf32_Word n_namesz; - Elf32_Word n_descsz; - Elf32_Word n_type; +/* Notes used in ET_CORE */ +#define NT_PRSTATUS 1 +#define NT_PRFPREG 2 +#define NT_PRPSINFO 3 +#define NT_TASKSTRUCT 4 + +/* Note header in a PT_NOTE section */ +typedef struct elf_note { + Elf32_Word n_namesz; /* Name size */ + Elf32_Word n_descsz; /* Content size */ + Elf32_Word n_type; /* Content type */ } Elf32_Nhdr; typedef struct { diff --git a/src/softmagic.c b/src/softmagic.c index d3eac07b..e79a1730 100644 --- a/src/softmagic.c +++ b/src/softmagic.c @@ -35,15 +35,15 @@ #ifndef lint static char *moduleid = - "@(#)$Id: softmagic.c,v 1.32 1996/10/25 19:50:35 christos Exp $"; + "@(#)$Id: softmagic.c,v 1.33 1997/01/15 17:23:24 christos Exp $"; #endif /* lint */ static int match __P((unsigned char *, int)); static int mget __P((union VALUETYPE *, unsigned char *, struct magic *, int)); static int mcheck __P((union VALUETYPE *, struct magic *)); -static long mprint __P((union VALUETYPE *, struct magic *)); -static void mdebug __P((long, char *, int)); +static int32 mprint __P((union VALUETYPE *, struct magic *)); +static void mdebug __P((int32, char *, int)); static int mconvert __P((union VALUETYPE *, struct magic *)); /* @@ -99,12 +99,12 @@ int nbytes; int cont_level = 0; int need_separator = 0; union VALUETYPE p; - static long *tmpoff = NULL; + static int32 *tmpoff = NULL; static size_t tmplen = 0; - long oldoff = 0; + int32 oldoff = 0; if (tmpoff == NULL) - if ((tmpoff = (long *) malloc(tmplen = 20)) == NULL) + if ((tmpoff = (int32 *) malloc(tmplen = 20)) == NULL) error("out of memory\n"); for (magindex = 0; magindex < nmagic; magindex++) { @@ -130,7 +130,7 @@ int nbytes; need_separator = 1; /* and any continuations that match */ if (++cont_level >= tmplen) - if ((tmpoff = (long *) realloc(tmpoff, + if ((tmpoff = (int32 *) realloc(tmpoff, tmplen += 20)) == NULL) error("out of memory\n"); while (magic[magindex+1].cont_level != 0 && @@ -175,7 +175,7 @@ int nbytes; */ if (++cont_level >= tmplen) if ((tmpoff = - (long *) realloc(tmpoff, + (int32 *) realloc(tmpoff, tmplen += 20)) == NULL) error("out of memory\n"); } @@ -189,14 +189,14 @@ int nbytes; return 0; /* no match at all */ } -static long +static int32 mprint(p, m) union VALUETYPE *p; struct magic *m; { char *pp, *rt; - unsigned long v; - long t=0 ; + uint32 v; + int32 t=0 ; switch (m->type) { @@ -221,8 +221,8 @@ struct magic *m; case LELONG: v = p->l; v = signextend(m, v) & m->mask; - (void) printf(m->desc, (unsigned long) v); - t = m->offset + sizeof(long); + (void) printf(m->desc, (uint32) v); + t = m->offset + sizeof(int32); break; case STRING: @@ -231,6 +231,11 @@ struct magic *m; t = m->offset + strlen(m->value.s); } else { + if (*m->value.s == '\0') { + char *cp = strchr(p->s,'\n'); + if (cp) + *cp = '\0'; + } (void) printf(m->desc, p->s); t = m->offset + strlen(p->s); } @@ -282,7 +287,7 @@ struct magic *m; return 1; case BELONG: case BEDATE: - p->l = (long) + p->l = (int32) ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3])); return 1; case LESHORT: @@ -290,7 +295,7 @@ struct magic *m; return 1; case LELONG: case LEDATE: - p->l = (long) + p->l = (int32) ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0])); return 1; default: @@ -302,7 +307,7 @@ struct magic *m; static void mdebug(offset, str, len) -long offset; +int32 offset; char *str; int len; { @@ -319,7 +324,7 @@ unsigned char *s; struct magic *m; int nbytes; { - long offset = m->offset; + int32 offset = m->offset; if (offset + sizeof(union VALUETYPE) <= nbytes) memcpy(p, s + offset, sizeof(union VALUETYPE)); @@ -328,7 +333,7 @@ int nbytes; * the usefulness of padding with zeroes eludes me, it * might even cause problems */ - long have = nbytes - offset; + int32 have = nbytes - offset; memset(p, 0, sizeof(union VALUETYPE)); if (have > 0) memcpy(p, s + offset, have); @@ -378,8 +383,8 @@ mcheck(p, m) union VALUETYPE* p; struct magic *m; { - register unsigned long l = m->value.l; - register unsigned long v; + register uint32 l = m->value.l; + register uint32 v; int matched; if ( (m->value.s[0] == 'x') && (m->value.s[1] == '\0') ) { @@ -462,7 +467,7 @@ struct magic *m; v, l, matched); } else { - matched = (long) v > (long) l; + matched = (int32) v > (int32) l; if (debug) (void) fprintf(stderr, "%ld > %ld = %d\n", v, l, matched); @@ -477,7 +482,7 @@ struct magic *m; v, l, matched); } else { - matched = (long) v < (long) l; + matched = (int32) v < (int32) l; if (debug) (void) fprintf(stderr, "%ld < %ld = %d\n", v, l, matched);