From: Christos Zoulas Date: Thu, 16 May 2002 15:01:41 +0000 (+0000) Subject: misc cleanups from NetBSD and addition of PT_NOTE field handling. X-Git-Tag: FILE3_38~12 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6d3dc5e31f688ca786f43bccf468f85254663a3c;p=file misc cleanups from NetBSD and addition of PT_NOTE field handling. --- diff --git a/magic/Magdir/elf b/magic/Magdir/elf index 53a6bc96..70135e7f 100644 --- a/magic/Magdir/elf +++ b/magic/Magdir/elf @@ -44,14 +44,18 @@ # Core handling from Peter Tobias # corrections by Christian 'Dr. Disk' Hechelmann >>16 leshort 4 core file ->>>(0x38+0xcc) string >\0 of '%s' ->>>(0x38+0x10) lelong >0 (signal %d), +# Core file detection is not reliable. +#>>>(0x38+0xcc) string >\0 of '%s' +#>>>(0x38+0x10) lelong >0 (signal %d), >>16 leshort &0xff00 processor-specific, >>18 leshort 0 no machine, >>18 leshort 1 AT&T WE32100 - invalid byte order, >>18 leshort 2 SPARC - invalid byte order, >>18 leshort 3 Intel 80386, ->>18 leshort 4 Motorola 68000 - invalid byte order, +>>18 leshort 4 Motorola +>>>36 lelong &0x01000000 68000 - invalid byte order, +>>>36 lelong &0x00810000 CPU32 - invalid byte order, +>>>36 lelong 0 68020 - invalid byte order, >>18 leshort 5 Motorola 88000 - invalid byte order, >>18 leshort 6 Intel 80486, >>18 leshort 7 Intel 80860, @@ -122,7 +126,10 @@ >>18 beshort 1 AT&T WE32100, >>18 beshort 2 SPARC, >>18 beshort 3 Intel 80386 - invalid byte order, ->>18 beshort 4 Motorola 68000, +>>18 beshort 4 Motorola +>>>36 belong &0x01000000 68000, +>>>36 belong &0x00810000 CPU32, +>>>36 belong 0 68020, >>18 beshort 5 Motorola 88000, >>18 beshort 6 Intel 80486 - invalid byte order, >>18 beshort 7 Intel 80860, diff --git a/src/names.h b/src/names.h index 856632a9..ea4e85cc 100644 --- a/src/names.h +++ b/src/names.h @@ -1,7 +1,7 @@ /* * Names.h - names and types used by ascmagic in file(1). * These tokens are here because they can appear anywhere in - * the first HOWMANY bytes, while tokens in /etc/magic must + * the first HOWMANY bytes, while tokens in MAGIC must * appear at fixed offsets into the file. Don't make HOWMANY * too high unless you have a very fast CPU. * @@ -10,7 +10,7 @@ * * See LEGAL.NOTICE * - * $Id: names.h,v 1.18 2000/08/05 17:36:49 christos Exp $ + * $Id: names.h,v 1.19 2002/05/16 15:01:41 christos Exp $ */ /* diff --git a/src/readelf.c b/src/readelf.c index ccce5992..357c2eaa 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -14,7 +14,7 @@ #include "readelf.h" #ifndef lint -FILE_RCSID("@(#)$Id: readelf.c,v 1.18 2001/10/20 17:44:53 christos Exp $") +FILE_RCSID("@(#)$Id: readelf.c,v 1.19 2002/05/16 15:01:41 christos Exp $") #endif #ifdef ELFCORE @@ -170,9 +170,14 @@ dophn_exec(class, swap, fd, off, num, size) size_t size; { Elf32_Phdr ph32; + Elf32_Nhdr *nh32; Elf64_Phdr ph64; + Elf64_Nhdr *nh64; char *linking_style = "statically"; char *shared_libraries = ""; + char nbuf[BUFSIZ]; + int bufsize; + size_t offset, nameoffset; if (lseek(fd, off, SEEK_SET) == -1) error("lseek failed (%s).\n", strerror(errno)); @@ -188,6 +193,112 @@ dophn_exec(class, swap, fd, off, num, size) case PT_INTERP: shared_libraries = " (uses shared libs)"; break; + case PT_NOTE: + /* + * This is a PT_NOTE section; loop through all the notes + * in the section. + */ + 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 (offset + nh_namesz >= bufsize) { + /* + * We're past the end of the buffer. + */ + break; + } + + nameoffset = offset; + offset += nh_namesz; + offset = ((offset + 3)/4)*4; + + if (offset + nh_descsz >= bufsize) + break; + + if (nh_namesz == 4 && + strcmp(&nbuf[nameoffset], "GNU") == 0 && + nh_type == NT_GNU_VERSION && + nh_descsz == 16) { + uint32_t *desc = + (uint32_t *)&nbuf[offset]; + + printf(", for GNU/"); + switch (getu32(swap, desc[0])) { + case GNU_OS_LINUX: + printf("Linux"); + break; + case GNU_OS_HURD: + printf("Hurd"); + break; + case GNU_OS_SOLARIS: + printf("Solaris"); + break; + default: + printf(""); + } + printf(" %d.%d.%d", + getu32(swap, desc[1]), + getu32(swap, desc[2]), + getu32(swap, desc[3])); + } + + if (nh_namesz == 7 && + strcmp(&nbuf[nameoffset], "NetBSD") == 0 && + nh_type == NT_NETBSD_VERSION && + nh_descsz == 4) { + printf(", for NetBSD"); + /* + * Version number is stuck at 199905, + * and hence is basically content-free. + */ + } + + if (nh_namesz == 8 && + strcmp(&nbuf[nameoffset], "FreeBSD") == 0 && + nh_type == NT_FREEBSD_VERSION && + nh_descsz == 4) { + uint32_t desc = getu32(swap, + *(uint32_t *)&nbuf[offset]); + printf(", for FreeBSD"); + /* + * Contents is __FreeBSD_version, + * whose relation to OS versions is + * defined by a huge table in the + * Porters' Handbook. Happily, the + * first three digits are the version + * number, at least in versions of + * FreeBSD that use this note. + */ + + printf(" %d.%d", desc / 100000, + desc / 10000 % 10); + if (desc / 1000 % 10 > 0) + printf(".%d", + desc / 1000 % 10); + } + + if (nh_namesz == 8 && + strcmp(&nbuf[nameoffset], "OpenBSD") == 0 && + nh_type == NT_OPENBSD_VERSION && + nh_descsz == 4) { + printf(", for OpenBSD"); + /* Content of note is always 0 */ + } + } + break; } } printf(", %s linked%s", linking_style, shared_libraries); @@ -230,6 +341,17 @@ size_t prpsoffsets64[] = { * *do* have that binary, the debugger will probably tell you what * signal it was.) */ + +#define OS_STYLE_SVR4 0 +#define OS_STYLE_FREEBSD 1 +#define OS_STYLE_NETBSD 2 + +static const char *os_style_names[] = { + "SVR4", + "FreeBSD", + "NetBSD", +}; + static void dophn_core(class, swap, fd, off, num, size) int class; @@ -248,7 +370,7 @@ dophn_core(class, swap, fd, off, num, size) int i, j; char nbuf[BUFSIZ]; int bufsize; - int is_freebsd; + int os_style = -1; /* * Loop through all the program headers. @@ -283,7 +405,7 @@ dophn_core(class, swap, fd, off, num, size) /* * Check whether this note has the name "CORE" or - * "FreeBSD". + * "FreeBSD", or "NetBSD-CORE". */ if (offset + nh_namesz >= bufsize) { /* @@ -310,17 +432,50 @@ dophn_core(class, swap, fd, off, num, size) * doesn't include the terminating null in the * name.... */ - if ((nh_namesz == 4 && - strncmp(&nbuf[nameoffset], "CORE", 4) == 0) || - (nh_namesz == 5 && - strcmp(&nbuf[nameoffset], "CORE") == 0)) - is_freebsd = 0; - else if ((nh_namesz == 8 && - strcmp(&nbuf[nameoffset], "FreeBSD") == 0)) - is_freebsd = 1; - else - continue; - if (nh_type == NT_PRPSINFO) { + if (os_style == -1) { + if ((nh_namesz == 4 && + strncmp(&nbuf[nameoffset], + "CORE", 4) == 0) || + (nh_namesz == 5 && + strcmp(&nbuf[nameoffset], + "CORE") == 0)) { + os_style = OS_STYLE_SVR4; + } else + if ((nh_namesz == 8 && + strcmp(&nbuf[nameoffset], + "FreeBSD") == 0)) { + os_style = OS_STYLE_FREEBSD; + } else + if ((nh_namesz >= 11 && + strncmp(&nbuf[nameoffset], + "NetBSD-CORE", 11) == 0)) { + os_style = OS_STYLE_NETBSD; + } else + continue; + printf(", %s-style", os_style_names[os_style]); + } + + if (os_style == OS_STYLE_NETBSD && + nh_type == NT_NETBSD_CORE_PROCINFO) { + uint32_t signo; + + /* + * Extract the program name. It is at + * offset 0x7c, and is up to 32-bytes, + * including the terminating NUL. + */ + printf(", from '%.31s'", &nbuf[offset + 0x7c]); + + /* + * Extract the signal number. It is at + * offset 0x08. + */ + memcpy(&signo, &nbuf[offset + 0x08], + sizeof(signo)); + printf(" (signal %u)", getu32(swap, signo)); + } else + if (os_style != OS_STYLE_NETBSD && + nh_type == NT_PRPSINFO) { /* * Extract the program name. We assume * it to be 16 characters (that's what it diff --git a/src/readelf.h b/src/readelf.h index d0ae3337..21d64362 100644 --- a/src/readelf.h +++ b/src/readelf.h @@ -1,6 +1,6 @@ /* * readelf.h - * @(#)$Id: readelf.h,v 1.7 1999/02/14 17:16:11 christos Exp $ + * @(#)$Id: readelf.h,v 1.8 2002/05/16 15:01:41 christos Exp $ * * Provide elf data structures for non-elf machines, allowing file * non-elf hosts to determine if an elf binary is stripped. @@ -166,6 +166,8 @@ typedef struct { #define NT_PRPSINFO 3 #define NT_TASKSTRUCT 4 +#define NT_NETBSD_CORE_PROCINFO 1 + /* Note header in a PT_NOTE section */ typedef struct elf_note { Elf32_Word n_namesz; /* Name size */ @@ -186,4 +188,18 @@ typedef struct { #define NT_PLATFORM 5 #define NT_AUXV 6 +/* Note types used in executables */ +/* NetBSD executables (name = "NetBSD") */ +#define NT_NETBSD_VERSION 1 +#define NT_NETBSD_EMULATION 2 +#define NT_FREEBSD_VERSION 1 +#define NT_OPENBSD_VERSION 1 +/* GNU executables (name = "GNU") */ +#define NT_GNU_VERSION 1 + +/* GNU OS tags */ +#define GNU_OS_LINUX 0 +#define GNU_OS_HURD 1 +#define GNU_OS_SOLARIS 2 + #endif diff --git a/src/softmagic.c b/src/softmagic.c index fc916154..904360e2 100644 --- a/src/softmagic.c +++ b/src/softmagic.c @@ -35,7 +35,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$Id: softmagic.c,v 1.46 2001/07/23 00:02:32 christos Exp $") +FILE_RCSID("@(#)$Id: softmagic.c,v 1.47 2002/05/16 15:01:41 christos Exp $") #endif /* lint */ static int match __P((struct magic *, uint32, unsigned char *, int)); @@ -50,7 +50,7 @@ extern int kflag; /* * softmagic - lookup one file in database - * (already read from /etc/magic by apprentice.c). + * (already read from MAGIC by apprentice.c). * Passed the name and FILE * of one file to be typed. */ /*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */