[BACK]Return to readelf.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / file

Diff for /src/usr.bin/file/Attic/readelf.c between version 1.9 and 1.10

version 1.9, 2008/05/08 01:40:56 version 1.10, 2009/04/24 18:54:34
Line 36 
Line 36 
 #endif  #endif
   
 #include "readelf.h"  #include "readelf.h"
   #include "magic.h"
   
 #ifndef lint  #ifndef lint
 FILE_RCSID("@(#)$Id$")  FILE_RCSID("@(#)$Id$")
Line 124 
Line 125 
                 return value;                  return value;
 }  }
   
   #define elf_getu16(swap, value) getu16(swap, value)
   #define elf_getu32(swap, value) getu32(swap, value)
 #ifdef USE_ARRAY_FOR_64BIT_TYPES  #ifdef USE_ARRAY_FOR_64BIT_TYPES
 # define elf_getu64(swap, array) \  # define elf_getu64(swap, array) \
         ((swap ? ((uint64_t)getu32(swap, array[0])) << 32 : getu32(swap, array[0])) + \          ((swap ? ((uint64_t)elf_getu32(swap, array[0])) << 32 : elf_getu32(swap, array[0])) + \
          (swap ? getu32(swap, array[1]) : ((uint64_t)getu32(swap, array[1]) << 32)))           (swap ? elf_getu32(swap, array[1]) : ((uint64_t)elf_getu32(swap, array[1]) << 32)))
 #else  #else
 # define elf_getu64(swap, value) getu64(swap, value)  # define elf_getu64(swap, value) getu64(swap, value)
 #endif  #endif
   
 #define xsh_addr        (class == ELFCLASS32            \  #define xsh_addr        (class == ELFCLASS32                    \
                          ? (void *) &sh32               \                           ? (void *) &sh32                       \
                          : (void *) &sh64)                           : (void *) &sh64)
 #define xsh_sizeof      (class == ELFCLASS32            \  #define xsh_sizeof      (class == ELFCLASS32                    \
                          ? sizeof sh32                  \                           ? sizeof sh32                          \
                          : sizeof sh64)                           : sizeof sh64)
 #define xsh_size        (class == ELFCLASS32            \  #define xsh_size        (class == ELFCLASS32                    \
                          ? getu32(swap, sh32.sh_size)   \                           ? elf_getu32(swap, sh32.sh_size)       \
                          : getu64(swap, sh64.sh_size))                           : elf_getu64(swap, sh64.sh_size))
 #define xsh_offset      (class == ELFCLASS32            \  #define xsh_offset      (class == ELFCLASS32                    \
                          ? getu32(swap, sh32.sh_offset) \                           ? elf_getu32(swap, sh32.sh_offset)     \
                          : getu64(swap, sh64.sh_offset))                           : elf_getu64(swap, sh64.sh_offset))
 #define xsh_type        (class == ELFCLASS32            \  #define xsh_type        (class == ELFCLASS32                    \
                          ? getu32(swap, sh32.sh_type)   \                           ? elf_getu32(swap, sh32.sh_type)       \
                          : getu32(swap, sh64.sh_type))                           : elf_getu32(swap, sh64.sh_type))
 #define xph_addr        (class == ELFCLASS32            \  #define xph_addr        (class == ELFCLASS32                    \
                          ? (void *) &ph32               \                           ? (void *) &ph32                       \
                          : (void *) &ph64)                           : (void *) &ph64)
 #define xph_sizeof      (class == ELFCLASS32            \  #define xph_sizeof      (class == ELFCLASS32                    \
                          ? sizeof ph32                  \                           ? sizeof ph32                          \
                          : sizeof ph64)                           : sizeof ph64)
 #define xph_type        (class == ELFCLASS32            \  #define xph_type        (class == ELFCLASS32                    \
                          ? getu32(swap, ph32.p_type)    \                           ? elf_getu32(swap, ph32.p_type)        \
                          : getu32(swap, ph64.p_type))                           : elf_getu32(swap, ph64.p_type))
 #define xph_offset      (off_t)(class == ELFCLASS32     \  #define xph_offset      (off_t)(class == ELFCLASS32             \
                          ? getu32(swap, ph32.p_offset)  \                           ? elf_getu32(swap, ph32.p_offset)      \
                          : getu64(swap, ph64.p_offset))                           : elf_getu64(swap, ph64.p_offset))
 #define xph_align       (size_t)((class == ELFCLASS32   \  #define xph_align       (size_t)((class == ELFCLASS32           \
                          ? (off_t) (ph32.p_align ?      \                           ? (off_t) (ph32.p_align ?              \
                             getu32(swap, ph32.p_align) : 4) \                              elf_getu32(swap, ph32.p_align) : 4) \
                          : (off_t) (ph64.p_align ?      \                           : (off_t) (ph64.p_align ?              \
                             getu64(swap, ph64.p_align) : 4)))                              elf_getu64(swap, ph64.p_align) : 4)))
 #define xph_filesz      (size_t)((class == ELFCLASS32   \  #define xph_filesz      (size_t)((class == ELFCLASS32           \
                          ? getu32(swap, ph32.p_filesz)  \                           ? elf_getu32(swap, ph32.p_filesz)      \
                          : getu64(swap, ph64.p_filesz)))                           : elf_getu64(swap, ph64.p_filesz)))
 #define xnh_addr        (class == ELFCLASS32            \  #define xnh_addr        (class == ELFCLASS32                    \
                          ? (void *) &nh32               \                           ? (void *) &nh32                       \
                          : (void *) &nh64)                           : (void *) &nh64)
 #define xph_memsz       (size_t)((class == ELFCLASS32   \  #define xph_memsz       (size_t)((class == ELFCLASS32           \
                          ? getu32(swap, ph32.p_memsz)   \                           ? elf_getu32(swap, ph32.p_memsz)       \
                          : getu64(swap, ph64.p_memsz)))                           : elf_getu64(swap, ph64.p_memsz)))
 #define xnh_sizeof      (class == ELFCLASS32            \  #define xnh_sizeof      (class == ELFCLASS32                    \
                          ? sizeof nh32                  \                           ? sizeof nh32                          \
                          : sizeof nh64)                           : sizeof nh64)
 #define xnh_type        (class == ELFCLASS32            \  #define xnh_type        (class == ELFCLASS32                    \
                          ? getu32(swap, nh32.n_type)    \                           ? elf_getu32(swap, nh32.n_type)        \
                          : getu32(swap, nh64.n_type))                           : elf_getu32(swap, nh64.n_type))
 #define xnh_namesz      (class == ELFCLASS32            \  #define xnh_namesz      (class == ELFCLASS32                    \
                          ? getu32(swap, nh32.n_namesz)  \                           ? elf_getu32(swap, nh32.n_namesz)      \
                          : getu32(swap, nh64.n_namesz))                           : elf_getu32(swap, nh64.n_namesz))
 #define xnh_descsz      (class == ELFCLASS32            \  #define xnh_descsz      (class == ELFCLASS32                    \
                          ? getu32(swap, nh32.n_descsz)  \                           ? elf_getu32(swap, nh32.n_descsz)      \
                          : getu32(swap, nh64.n_descsz))                           : elf_getu32(swap, nh64.n_descsz))
 #define prpsoffsets(i)  (class == ELFCLASS32            \  #define prpsoffsets(i)  (class == ELFCLASS32                    \
                          ? prpsoffsets32[i]             \                           ? prpsoffsets32[i]                     \
                          : prpsoffsets64[i])                           : prpsoffsets64[i])
   
 #ifdef ELFCORE  #ifdef ELFCORE
 size_t  prpsoffsets32[] = {  /*
         8,              /* FreeBSD */   * Try larger offsets first to avoid false matches
    * from earlier data that happen to look like strings.
    */
   static const size_t     prpsoffsets32[] = {
   #ifdef USE_NT_PSINFO
           104,            /* SunOS 5.x (command line) */
           88,             /* SunOS 5.x (short name) */
   #endif /* USE_NT_PSINFO */
   
           100,            /* SunOS 5.x (command line) */
           84,             /* SunOS 5.x (short name) */
   
           44,             /* Linux (command line) */
         28,             /* Linux 2.0.36 (short name) */          28,             /* Linux 2.0.36 (short name) */
         44,             /* Linux (path name) */  
         84,             /* SunOS 5.x */          8,              /* FreeBSD */
 };  };
   
 size_t  prpsoffsets64[] = {  static const size_t     prpsoffsets64[] = {
         16,             /* FreeBSD, 64-bit */  #ifdef USE_NT_PSINFO
           152,            /* SunOS 5.x (command line) */
           136,            /* SunOS 5.x (short name) */
   #endif /* USE_NT_PSINFO */
   
           136,            /* SunOS 5.x, 64-bit (command line) */
           120,            /* SunOS 5.x, 64-bit (short name) */
   
           56,             /* Linux (command line) */
         40,             /* Linux (tested on core from 2.4.x, short name) */          40,             /* Linux (tested on core from 2.4.x, short name) */
         56,             /* Linux (path name) */  
         120,            /* SunOS 5.x, 64-bit */          16,             /* FreeBSD, 64-bit */
 };  };
   
 #define NOFFSETS32      (sizeof prpsoffsets32 / sizeof prpsoffsets32[0])  #define NOFFSETS32      (sizeof prpsoffsets32 / sizeof prpsoffsets32[0])
Line 221 
Line 244 
  * SVR4-flavored systems, and Linux) containing the start of the   * SVR4-flavored systems, and Linux) containing the start of the
  * command line for that program.   * command line for that program.
  *   *
    * SunOS 5.x core files contain two PT_NOTE sections, with the types
    * NT_PRPSINFO (old) and NT_PSINFO (new).  These structs contain the
    * same info about the command name and command line, so it probably
    * isn't worthwhile to look for NT_PSINFO, but the offsets are provided
    * above (see USE_NT_PSINFO), in case we ever decide to do so.  The
    * NT_PRPSINFO and NT_PSINFO sections are always in order and adjacent;
    * the SunOS 5.x file command relies on this (and prefers the latter).
    *
  * The signal number probably appears in a section of type NT_PRSTATUS,   * The signal number probably appears in a section of type NT_PRSTATUS,
  * but that's also rather OS-dependent, in ways that are harder to   * but that's also rather OS-dependent, in ways that are harder to
  * dissect with heuristics, so I'm not bothering with the signal number.   * dissect with heuristics, so I'm not bothering with the signal number.
Line 234 
Line 265 
 #define OS_STYLE_FREEBSD        1  #define OS_STYLE_FREEBSD        1
 #define OS_STYLE_NETBSD         2  #define OS_STYLE_NETBSD         2
   
 private const char *os_style_names[] = {  private const char os_style_names[][8] = {
         "SVR4",          "SVR4",
         "FreeBSD",          "FreeBSD",
         "NetBSD",          "NetBSD",
Line 242 
Line 273 
   
 #define FLAGS_DID_CORE          1  #define FLAGS_DID_CORE          1
 #define FLAGS_DID_NOTE          2  #define FLAGS_DID_NOTE          2
   #define FLAGS_DID_CORE_STYLE    4
   
 private int  private int
 dophn_core(struct magic_set *ms, int class, int swap, int fd, off_t off,  dophn_core(struct magic_set *ms, int class, int swap, int fd, off_t off,
Line 384 
Line 416 
   
                 if (file_printf(ms, ", for GNU/") == -1)                  if (file_printf(ms, ", for GNU/") == -1)
                         return size;                          return size;
                 switch (getu32(swap, desc[0])) {                  switch (elf_getu32(swap, desc[0])) {
                 case GNU_OS_LINUX:                  case GNU_OS_LINUX:
                         if (file_printf(ms, "Linux") == -1)                          if (file_printf(ms, "Linux") == -1)
                                 return size;                                  return size;
Line 397 
Line 429 
                         if (file_printf(ms, "Solaris") == -1)                          if (file_printf(ms, "Solaris") == -1)
                                 return size;                                  return size;
                         break;                          break;
                   case GNU_OS_KFREEBSD:
                           if (file_printf(ms, "kFreeBSD") == -1)
                                   return size;
                           break;
                   case GNU_OS_KNETBSD:
                           if (file_printf(ms, "kNetBSD") == -1)
                                   return size;
                           break;
                 default:                  default:
                         if (file_printf(ms, "<unknown>") == -1)                          if (file_printf(ms, "<unknown>") == -1)
                                 return size;                                  return size;
                 }                  }
                 if (file_printf(ms, " %d.%d.%d", getu32(swap, desc[1]),                  if (file_printf(ms, " %d.%d.%d", elf_getu32(swap, desc[1]),
                     getu32(swap, desc[2]), getu32(swap, desc[3])) == -1)                      elf_getu32(swap, desc[2]), elf_getu32(swap, desc[3])) == -1)
                         return size;                          return size;
                 *flags |= FLAGS_DID_NOTE;                  *flags |= FLAGS_DID_NOTE;
                 return size;                  return size;
Line 412 
Line 452 
             xnh_type == NT_NETBSD_VERSION && descsz == 4) {              xnh_type == NT_NETBSD_VERSION && descsz == 4) {
                 uint32_t desc;                  uint32_t desc;
                 (void)memcpy(&desc, &nbuf[doff], sizeof(desc));                  (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
                 desc = getu32(swap, desc);                  desc = elf_getu32(swap, desc);
   
                 if (file_printf(ms, ", for NetBSD") == -1)                  if (file_printf(ms, ", for NetBSD") == -1)
                         return size;                          return size;
Line 458 
Line 498 
             xnh_type == NT_FREEBSD_VERSION && descsz == 4) {              xnh_type == NT_FREEBSD_VERSION && descsz == 4) {
                 uint32_t desc;                  uint32_t desc;
                 (void)memcpy(&desc, &nbuf[doff], sizeof(desc));                  (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
                 desc = getu32(swap, desc);                  desc = elf_getu32(swap, desc);
                 if (file_printf(ms, ", for FreeBSD") == -1)                  if (file_printf(ms, ", for FreeBSD") == -1)
                         return size;                          return size;
   
Line 547 
Line 587 
                 if (file_printf(ms, ", for DragonFly") == -1)                  if (file_printf(ms, ", for DragonFly") == -1)
                         return size;                          return size;
                 (void)memcpy(&desc, &nbuf[doff], sizeof(desc));                  (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
                 desc = getu32(swap, desc);                  desc = elf_getu32(swap, desc);
                 if (file_printf(ms, " %d.%d.%d", desc / 100000,                  if (file_printf(ms, " %d.%d.%d", desc / 100000,
                     desc / 10000 % 10, desc % 10000) == -1)                      desc / 10000 % 10, desc % 10000) == -1)
                         return size;                          return size;
Line 588 
Line 628 
         if ((*flags & FLAGS_DID_CORE) != 0)          if ((*flags & FLAGS_DID_CORE) != 0)
                 return size;                  return size;
   
         if (os_style != -1) {          if (os_style != -1 && (*flags & FLAGS_DID_CORE_STYLE) == 0) {
                 if (file_printf(ms, ", %s-style", os_style_names[os_style])                  if (file_printf(ms, ", %s-style", os_style_names[os_style])
                     == -1)                      == -1)
                         return size;                          return size;
                   *flags |= FLAGS_DID_CORE_STYLE;
         }          }
   
         switch (os_style) {          switch (os_style) {
Line 614 
Line 655 
                         (void)memcpy(&signo, &nbuf[doff + 0x08],                          (void)memcpy(&signo, &nbuf[doff + 0x08],
                             sizeof(signo));                              sizeof(signo));
                         if (file_printf(ms, " (signal %u)",                          if (file_printf(ms, " (signal %u)",
                             getu32(swap, signo)) == -1)                              elf_getu32(swap, signo)) == -1)
                                 return size;                                  return size;
                           *flags |= FLAGS_DID_CORE;
                         return size;                          return size;
                 }                  }
                 break;                  break;
Line 635 
Line 677 
                          * reject it.                           * reject it.
                          */                           */
                         for (i = 0; i < NOFFSETS; i++) {                          for (i = 0; i < NOFFSETS; i++) {
                                   unsigned char *cname, *cp;
                                 size_t reloffset = prpsoffsets(i);                                  size_t reloffset = prpsoffsets(i);
                                 size_t noffset = doff + reloffset;                                  size_t noffset = doff + reloffset;
                                 for (j = 0; j < 16; j++, noffset++,                                  for (j = 0; j < 16; j++, noffset++,
Line 682 
Line 725 
                                 /*                                  /*
                                  * Well, that worked.                                   * Well, that worked.
                                  */                                   */
                                 if (file_printf(ms, ", from '%.16s'",                                  cname = (unsigned char *)
                                     &nbuf[doff + prpsoffsets(i)]) == -1)                                      &nbuf[doff + prpsoffsets(i)];
                                   for (cp = cname; *cp && isprint(*cp); cp++)
                                           continue;
                                   /*
                                    * Linux apparently appends a space at the end
                                    * of the command line: remove it.
                                    */
                                   while (cp > cname && isspace(cp[-1]))
                                           cp--;
                                   if (file_printf(ms, ", from '%.*s'",
                                       (int)(cp - cname), cname) == -1)
                                         return size;                                          return size;
                                   *flags |= FLAGS_DID_CORE;
                                 return size;                                  return size;
   
                         tryanother:                          tryanother:
Line 694 
Line 748 
                 break;                  break;
         }          }
 #endif  #endif
         *flags |= FLAGS_DID_CORE;  
         return offset;          return offset;
 }  }
   
Line 805 
Line 858 
   
         if (size != xph_sizeof) {          if (size != xph_sizeof) {
                 if (file_printf(ms, ", corrupted program header size") == -1)                  if (file_printf(ms, ", corrupted program header size") == -1)
                     return -1;                          return -1;
                 return 0;                  return 0;
         }          }
   
Line 885 
Line 938 
                                 return -1;                                  return -1;
                         }                          }
                         break;                          break;
                   default:
                           break;
                 }                  }
         }          }
         if (file_printf(ms, ", %s linked%s", linking_style, shared_libraries)          if (file_printf(ms, ", %s linked%s", linking_style, shared_libraries)
Line 907 
Line 962 
         struct stat st;          struct stat st;
         off_t fsize;          off_t fsize;
         int flags = 0;          int flags = 0;
           Elf32_Ehdr elf32hdr;
           Elf64_Ehdr elf64hdr;
           uint16_t type;
   
           if (ms->flags & MAGIC_MIME)
                   return 0;
         /*          /*
            * 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.
            * Return immediately if it's not ELF (so we avoid pipe2file unless needed).
            */
           if (buf[EI_MAG0] != ELFMAG0
               || (buf[EI_MAG1] != ELFMAG1 && buf[EI_MAG1] != OLFMAG1)
               || buf[EI_MAG2] != ELFMAG2 || buf[EI_MAG3] != ELFMAG3)
                   return 0;
   
           /*
          * If we cannot seek, it must be a pipe, socket or fifo.           * If we cannot seek, it must be a pipe, socket or fifo.
          */           */
         if((lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) && (errno == ESPIPE))          if((lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) && (errno == ESPIPE))
Line 920 
Line 992 
         }          }
         fsize = st.st_size;          fsize = st.st_size;
   
         /*  
          * 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 0;  
   
   
         class = buf[EI_CLASS];          class = buf[EI_CLASS];
   
         if (class == ELFCLASS32) {          switch (class) {
                 Elf32_Ehdr elfhdr;          case ELFCLASS32:
                 if (nbytes <= sizeof (Elf32_Ehdr))  #undef elf_getu
                         return 0;  #define elf_getu(a, b)  elf_getu32(a, b)
   #undef elfhdr
   #define elfhdr elf32hdr
                 u.l = 1;  #include "elfclass.h"
                 (void) memcpy(&elfhdr, buf, sizeof elfhdr);          case ELFCLASS64:
                 swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[EI_DATA];  #undef elf_getu
   #define elf_getu(a, b)  elf_getu64(a, b)
                 if (getu16(swap, elfhdr.e_type) == ET_CORE) {  #undef elfhdr
 #ifdef ELFCORE  #define elfhdr elf64hdr
                         if (dophn_core(ms, class, swap, fd,  #include "elfclass.h"
                             (off_t)getu32(swap, elfhdr.e_phoff),          default:
                             getu16(swap, elfhdr.e_phnum),              if (file_printf(ms, ", unknown class %d", class) == -1)
                             (size_t)getu16(swap, elfhdr.e_phentsize),                      return -1;
                             fsize, &flags) == -1)              break;
                                 return -1;  
 #else  
                         ;  
 #endif  
                 } else {  
                         if (getu16(swap, elfhdr.e_type) == ET_EXEC) {  
                                 if (dophn_exec(ms, class, swap,  
                                     fd, (off_t)getu32(swap, elfhdr.e_phoff),  
                                     getu16(swap, elfhdr.e_phnum),  
                                     (size_t)getu16(swap, elfhdr.e_phentsize),  
                                     fsize, &flags)  
                                     == -1)  
                                         return -1;  
                         }  
                         if (doshn(ms, class, swap, fd,  
                             (off_t)getu32(swap, elfhdr.e_shoff),  
                             getu16(swap, elfhdr.e_shnum),  
                             (size_t)getu16(swap, elfhdr.e_shentsize),  
                             &flags) == -1)  
                                 return -1;  
                 }  
                 return 1;  
         }  
   
         if (class == ELFCLASS64) {  
                 Elf64_Ehdr elfhdr;  
                 if (nbytes <= sizeof (Elf64_Ehdr))  
                         return 0;  
   
   
                 u.l = 1;  
                 (void) memcpy(&elfhdr, buf, sizeof elfhdr);  
                 swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[EI_DATA];  
   
                 if (getu16(swap, elfhdr.e_type) == ET_CORE) {  
 #ifdef ELFCORE  
                         if (dophn_core(ms, class, swap, fd,  
                             (off_t)elf_getu64(swap, elfhdr.e_phoff),  
                             getu16(swap, elfhdr.e_phnum),  
                             (size_t)getu16(swap, elfhdr.e_phentsize),  
                             fsize, &flags) == -1)  
                                 return -1;  
 #else  
                         ;  
 #endif  
                 } else {  
                         if (getu16(swap, elfhdr.e_type) == ET_EXEC) {  
                                 if (dophn_exec(ms, class, swap, fd,  
                                     (off_t)elf_getu64(swap, elfhdr.e_phoff),  
                                     getu16(swap, elfhdr.e_phnum),  
                                     (size_t)getu16(swap, elfhdr.e_phentsize),  
                                     fsize, &flags) == -1)  
                                         return -1;  
                         }  
                         if (doshn(ms, class, swap, fd,  
                             (off_t)elf_getu64(swap, elfhdr.e_shoff),  
                             getu16(swap, elfhdr.e_shnum),  
                             (size_t)getu16(swap, elfhdr.e_shentsize), &flags)  
                             == -1)  
                                 return -1;  
                 }  
                 return 1;  
         }          }
         return 0;          return 0;
 }  }

Legend:
Removed from v.1.9  
changed lines
  Added in v.1.10