[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.8 and 1.9

version 1.8, 2004/05/19 02:32:35 version 1.9, 2008/05/08 01:40:56
Line 12 
Line 12 
  * 2. Redistributions in binary form must reproduce the above copyright   * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the   *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.   *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products  
  *    derived from this software without specific prior written permission.  
  *   *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Line 44 
Line 42 
 #endif  #endif
   
 #ifdef  ELFCORE  #ifdef  ELFCORE
 private int dophn_core(struct magic_set *, int, int, int, off_t, int, size_t);  private int dophn_core(struct magic_set *, int, int, int, off_t, int, size_t,
       off_t, int *);
 #endif  #endif
 private int dophn_exec(struct magic_set *, int, int, int, off_t, int, size_t);  private int dophn_exec(struct magic_set *, int, int, int, off_t, int, size_t,
 private int doshn(struct magic_set *, int, int, int, off_t, int, size_t);      off_t, int *);
   private int doshn(struct magic_set *, int, int, int, off_t, int, size_t, int *);
 private size_t donote(struct magic_set *, unsigned char *, size_t, size_t, int,  private size_t donote(struct magic_set *, unsigned char *, size_t, size_t, int,
     int, size_t);      int, size_t, int *);
   
 #define ELF_ALIGN(a)    ((((a) + align - 1) / align) * align)  #define ELF_ALIGN(a)    ((((a) + align - 1) / align) * align)
   
   #define isquote(c) (strchr("'\"`", (c)) != NULL)
   
 private uint16_t getu16(int, uint16_t);  private uint16_t getu16(int, uint16_t);
 private uint32_t getu32(int, uint32_t);  private uint32_t getu32(int, uint32_t);
 private uint64_t getu64(int, uint64_t);  private uint64_t getu64(int, uint64_t);
Line 122 
Line 124 
                 return value;                  return value;
 }  }
   
 #define sh_addr         (class == ELFCLASS32            \  #ifdef USE_ARRAY_FOR_64BIT_TYPES
   # define elf_getu64(swap, array) \
           ((swap ? ((uint64_t)getu32(swap, array[0])) << 32 : getu32(swap, array[0])) + \
            (swap ? getu32(swap, array[1]) : ((uint64_t)getu32(swap, array[1]) << 32)))
   #else
   # define elf_getu64(swap, value) getu64(swap, value)
   #endif
   
   #define xsh_addr        (class == ELFCLASS32            \
                          ? (void *) &sh32               \                           ? (void *) &sh32               \
                          : (void *) &sh64)                           : (void *) &sh64)
 #define sh_size         (class == ELFCLASS32            \  #define xsh_sizeof      (class == ELFCLASS32            \
                          ? sizeof sh32                  \                           ? sizeof sh32                  \
                          : sizeof sh64)                           : sizeof sh64)
 #define shs_type        (class == ELFCLASS32            \  #define xsh_size        (class == ELFCLASS32            \
                            ? getu32(swap, sh32.sh_size)   \
                            : getu64(swap, sh64.sh_size))
   #define xsh_offset      (class == ELFCLASS32            \
                            ? getu32(swap, sh32.sh_offset) \
                            : getu64(swap, sh64.sh_offset))
   #define xsh_type        (class == ELFCLASS32            \
                          ? getu32(swap, sh32.sh_type)   \                           ? getu32(swap, sh32.sh_type)   \
                          : getu32(swap, sh64.sh_type))                           : getu32(swap, sh64.sh_type))
 #define ph_addr         (class == ELFCLASS32            \  #define xph_addr        (class == ELFCLASS32            \
                          ? (void *) &ph32               \                           ? (void *) &ph32               \
                          : (void *) &ph64)                           : (void *) &ph64)
 #define ph_size         (class == ELFCLASS32            \  #define xph_sizeof      (class == ELFCLASS32            \
                          ? sizeof ph32                  \                           ? sizeof ph32                  \
                          : sizeof ph64)                           : sizeof ph64)
 #define ph_type         (class == ELFCLASS32            \  #define xph_type        (class == ELFCLASS32            \
                          ? getu32(swap, ph32.p_type)    \                           ? getu32(swap, ph32.p_type)    \
                          : getu32(swap, ph64.p_type))                           : getu32(swap, ph64.p_type))
 #define ph_offset       (class == ELFCLASS32            \  #define xph_offset      (off_t)(class == ELFCLASS32     \
                          ? getu32(swap, ph32.p_offset)  \                           ? getu32(swap, ph32.p_offset)  \
                          : getu64(swap, ph64.p_offset))                           : getu64(swap, ph64.p_offset))
 #define ph_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) \                              getu32(swap, ph32.p_align) : 4) \
                          : (off_t) (ph64.p_align ?      \                           : (off_t) (ph64.p_align ?      \
                             getu64(swap, ph64.p_align) : 4)))                              getu64(swap, ph64.p_align) : 4)))
 #define nh_size         (class == ELFCLASS32            \  #define xph_filesz      (size_t)((class == ELFCLASS32   \
                            ? getu32(swap, ph32.p_filesz)  \
                            : getu64(swap, ph64.p_filesz)))
   #define xnh_addr        (class == ELFCLASS32            \
                            ? (void *) &nh32               \
                            : (void *) &nh64)
   #define xph_memsz       (size_t)((class == ELFCLASS32   \
                            ? getu32(swap, ph32.p_memsz)   \
                            : getu64(swap, ph64.p_memsz)))
   #define xnh_sizeof      (class == ELFCLASS32            \
                          ? sizeof nh32                  \                           ? sizeof nh32                  \
                          : sizeof nh64)                           : sizeof nh64)
 #define nh_type         (class == ELFCLASS32            \  #define xnh_type        (class == ELFCLASS32            \
                          ? getu32(swap, nh32.n_type)    \                           ? getu32(swap, nh32.n_type)    \
                          : getu32(swap, nh64.n_type))                           : getu32(swap, nh64.n_type))
 #define nh_namesz       (class == ELFCLASS32            \  #define xnh_namesz      (class == ELFCLASS32            \
                          ? getu32(swap, nh32.n_namesz)  \                           ? getu32(swap, nh32.n_namesz)  \
                          : getu32(swap, nh64.n_namesz))                           : getu32(swap, nh64.n_namesz))
 #define nh_descsz       (class == ELFCLASS32            \  #define xnh_descsz      (class == ELFCLASS32            \
                          ? getu32(swap, nh32.n_descsz)  \                           ? getu32(swap, nh32.n_descsz)  \
                          : getu32(swap, nh64.n_descsz))                           : getu32(swap, nh64.n_descsz))
 #define prpsoffsets(i)  (class == ELFCLASS32            \  #define prpsoffsets(i)  (class == ELFCLASS32            \
Line 167 
Line 192 
 #ifdef ELFCORE  #ifdef ELFCORE
 size_t  prpsoffsets32[] = {  size_t  prpsoffsets32[] = {
         8,              /* FreeBSD */          8,              /* FreeBSD */
         28,             /* Linux 2.0.36 */          28,             /* Linux 2.0.36 (short name) */
         32,             /* Linux (I forget which kernel version) */          44,             /* Linux (path name) */
         84,             /* SunOS 5.x */          84,             /* SunOS 5.x */
 };  };
   
 size_t  prpsoffsets64[] = {  size_t  prpsoffsets64[] = {
        120,             /* SunOS 5.x, 64-bit */          16,             /* FreeBSD, 64-bit */
           40,             /* Linux (tested on core from 2.4.x, short name) */
           56,             /* Linux (path name) */
           120,            /* SunOS 5.x, 64-bit */
 };  };
   
 #define NOFFSETS32      (sizeof prpsoffsets32 / sizeof prpsoffsets32[0])  #define NOFFSETS32      (sizeof prpsoffsets32 / sizeof prpsoffsets32[0])
Line 212 
Line 240 
         "NetBSD",          "NetBSD",
 };  };
   
   #define FLAGS_DID_CORE          1
   #define FLAGS_DID_NOTE          2
   
 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,
     int num, size_t size)      int num, size_t size, off_t fsize, int *flags)
 {  {
         Elf32_Phdr ph32;          Elf32_Phdr ph32;
         Elf64_Phdr ph64;          Elf64_Phdr ph64;
         size_t offset;          size_t offset;
         unsigned char nbuf[BUFSIZ];          unsigned char nbuf[BUFSIZ];
         ssize_t bufsize;          ssize_t bufsize;
           off_t savedoffset;
           struct stat st;
   
         if (size != ph_size) {          if (fstat(fd, &st) < 0) {
                   file_badread(ms);
                   return -1;
           }
   
           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;
         }          }
   
         /*          /*
          * Loop through all the program headers.           * Loop through all the program headers.
          */           */
         for ( ; num; num--) {          for ( ; num; num--) {
                 if (lseek(fd, off, SEEK_SET) == (off_t)-1) {                  if ((savedoffset = lseek(fd, off, SEEK_SET)) == (off_t)-1) {
                         file_badseek(ms);                          file_badseek(ms);
                         return -1;                          return -1;
                 }                  }
                 if (read(fd, ph_addr, ph_size) == -1) {                  if (read(fd, xph_addr, xph_sizeof) == -1) {
                         file_badread(ms);                          file_badread(ms);
                         return -1;                          return -1;
                 }                  }
                   if (xph_offset > fsize) {
                           if (lseek(fd, savedoffset, SEEK_SET) == (off_t)-1) {
                                   file_badseek(ms);
                                   return -1;
                           }
                           continue;
                   }
   
                 off += size;                  off += size;
                 if (ph_type != PT_NOTE)                  if (xph_type != PT_NOTE)
                         continue;                          continue;
   
                 /*                  /*
                  * This is a PT_NOTE section; loop through all the notes                   * This is a PT_NOTE section; loop through all the notes
                  * in the section.                   * in the section.
                  */                   */
                 if (lseek(fd, (off_t) ph_offset, SEEK_SET) == (off_t)-1) {                  if (lseek(fd, xph_offset, SEEK_SET) == (off_t)-1) {
                         file_badseek(ms);                          file_badseek(ms);
                         return -1;                          return -1;
                 }                  }
                 bufsize = read(fd, nbuf, BUFSIZ);                  bufsize = read(fd, nbuf,
                       ((xph_filesz < sizeof(nbuf)) ? xph_filesz : sizeof(nbuf)));
                 if (bufsize == -1) {                  if (bufsize == -1) {
                         file_badread(ms);                          file_badread(ms);
                         return -1;                          return -1;
Line 261 
Line 309 
                         if (offset >= (size_t)bufsize)                          if (offset >= (size_t)bufsize)
                                 break;                                  break;
                         offset = donote(ms, nbuf, offset, (size_t)bufsize,                          offset = donote(ms, nbuf, offset, (size_t)bufsize,
                             class, swap, 4);                              class, swap, 4, flags);
                         if (offset == 0)                          if (offset == 0)
                                 break;                                  break;
   
Line 273 
Line 321 
   
 private size_t  private size_t
 donote(struct magic_set *ms, unsigned char *nbuf, size_t offset, size_t size,  donote(struct magic_set *ms, unsigned char *nbuf, size_t offset, size_t size,
     int class, int swap, size_t align)      int class, int swap, size_t align, int *flags)
 {  {
         Elf32_Nhdr nh32;          Elf32_Nhdr nh32;
         Elf64_Nhdr nh64;          Elf64_Nhdr nh64;
Line 283 
Line 331 
 #endif  #endif
         uint32_t namesz, descsz;          uint32_t namesz, descsz;
   
         if (class == ELFCLASS32)          (void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof);
                 memcpy(&nh32, &nbuf[offset], sizeof(nh32));          offset += xnh_sizeof;
         else  
                 memcpy(&nh64, &nbuf[offset], sizeof(nh64));  
         offset += nh_size;  
   
         namesz = nh_namesz;          namesz = xnh_namesz;
         descsz = nh_descsz;          descsz = xnh_descsz;
         if ((namesz == 0) && (descsz == 0)) {          if ((namesz == 0) && (descsz == 0)) {
                 /*                  /*
                  * We're out of note headers.                   * We're out of note headers.
                  */                   */
                 return offset;                  return (offset >= size) ? offset : size;
         }          }
   
         if (namesz & 0x80000000) {          if (namesz & 0x80000000) {
Line 314 
Line 359 
         noff = offset;          noff = offset;
         doff = ELF_ALIGN(offset + namesz);          doff = ELF_ALIGN(offset + namesz);
   
         if (offset + namesz >= size) {          if (offset + namesz > size) {
                 /*                  /*
                  * We're past the end of the buffer.                   * We're past the end of the buffer.
                  */                   */
Line 322 
Line 367 
         }          }
   
         offset = ELF_ALIGN(doff + descsz);          offset = ELF_ALIGN(doff + descsz);
         if (offset + descsz >= size) {          if (doff + descsz > size) {
                 return offset;                  /*
                    * We're past the end of the buffer.
                    */
                   return (offset >= size) ? offset : size;
         }          }
   
           if (*flags & FLAGS_DID_NOTE)
                   goto core;
   
         if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 &&          if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 &&
             nh_type == NT_GNU_VERSION && descsz == 16) {              xnh_type == NT_GNU_VERSION && descsz == 16) {
                 uint32_t desc[4];                  uint32_t desc[4];
                 (void)memcpy(desc, &nbuf[doff], sizeof(desc));                  (void)memcpy(desc, &nbuf[doff], sizeof(desc));
   
Line 353 
Line 404 
                 if (file_printf(ms, " %d.%d.%d", getu32(swap, desc[1]),                  if (file_printf(ms, " %d.%d.%d", getu32(swap, desc[1]),
                     getu32(swap, desc[2]), getu32(swap, desc[3])) == -1)                      getu32(swap, desc[2]), getu32(swap, desc[3])) == -1)
                         return size;                          return size;
                   *flags |= FLAGS_DID_NOTE;
                 return size;                  return size;
         }          }
   
         if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0 &&          if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0 &&
             nh_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 = getu32(swap, desc);
Line 377 
Line 429 
                  * p = patchlevel                   * p = patchlevel
                  */                   */
                 if (desc > 100000000U) {                  if (desc > 100000000U) {
                         u_int ver_patch = (desc / 100) % 100;                          uint32_t ver_patch = (desc / 100) % 100;
                         u_int ver_rel = (desc / 10000) % 100;                          uint32_t ver_rel = (desc / 10000) % 100;
                         u_int ver_min = (desc / 1000000) % 100;                          uint32_t ver_min = (desc / 1000000) % 100;
                         u_int ver_maj = desc / 100000000;                          uint32_t ver_maj = desc / 100000000;
   
                         if (file_printf(ms, " %u.%u", ver_maj, ver_min) == -1)                          if (file_printf(ms, " %u.%u", ver_maj, ver_min) == -1)
                                 return size;                                  return size;
Line 389 
Line 441 
                                         return size;                                          return size;
                         } else if (ver_rel != 0) {                          } else if (ver_rel != 0) {
                                 while (ver_rel > 26) {                                  while (ver_rel > 26) {
                                         file_printf(ms, "Z");                                          if (file_printf(ms, "Z") == -1)
                                                   return size;
                                         ver_rel -= 26;                                          ver_rel -= 26;
                                 }                                  }
                                 file_printf(ms, "%c", 'A' + ver_rel - 1);                                  if (file_printf(ms, "%c", 'A' + ver_rel - 1)
                                       == -1)
                                           return size;
                         }                          }
                 }                  }
                   *flags |= FLAGS_DID_NOTE;
                 return size;                  return size;
         }          }
   
         if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0 &&          if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0 &&
             nh_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 = getu32(swap, desc);
Line 408 
Line 464 
   
                 /*                  /*
                  * Contents is __FreeBSD_version, whose relation to OS                   * Contents is __FreeBSD_version, whose relation to OS
                  * versions is defined by a huge table in the Porters'                   * versions is defined by a huge table in the Porter's
                  * Handbook. For up to 5.x, the first three digits are                   * Handbook.  This is the general scheme:
                  * the version number.  For 5.x and higher, the scheme                   *
                  * is: <major><two digit minor> <0 if release branch,                   * Releases:
                  * otherwise 1>xx                   *      Mmp000 (before 4.10)
                    *      Mmi0p0 (before 5.0)
                    *      Mmm0p0
                    *
                    * Development branches:
                    *      Mmpxxx (before 4.6)
                    *      Mmp1xx (before 4.10)
                    *      Mmi1xx (before 5.0)
                    *      M000xx (pre-M.0)
                    *      Mmm1xx
                    *
                    * M = major version
                    * m = minor version
                    * i = minor version increment (491000 -> 4.10)
                    * p = patchlevel
                    * x = revision
                    *
                    * The first release of FreeBSD to use ELF by default
                    * was version 3.0.
                  */                   */
                 if (desc / 100000 < 5) {                  if (desc == 460002) {
                           if (file_printf(ms, " 4.6.2") == -1)
                                   return size;
                   } else if (desc < 460100) {
                         if (file_printf(ms, " %d.%d", desc / 100000,                          if (file_printf(ms, " %d.%d", desc / 100000,
                             desc / 10000 % 10) == -1)                              desc / 10000 % 10) == -1)
                                 return size;                                  return size;
Line 422 
Line 499 
                                 if (file_printf(ms, ".%d", desc / 1000 % 10)                                  if (file_printf(ms, ".%d", desc / 1000 % 10)
                                     == -1)                                      == -1)
                                         return size;                                          return size;
                           if ((desc % 1000 > 0) || (desc % 100000 == 0))
                                   if (file_printf(ms, " (%d)", desc) == -1)
                                           return size;
                   } else if (desc < 500000) {
                           if (file_printf(ms, " %d.%d", desc / 100000,
                               desc / 10000 % 10 + desc / 1000 % 10) == -1)
                                   return size;
                           if (desc / 100 % 10 > 0) {
                                   if (file_printf(ms, " (%d)", desc) == -1)
                                           return size;
                           } else if (desc / 10 % 10 > 0) {
                                   if (file_printf(ms, ".%d", desc / 10 % 10)
                                       == -1)
                                           return size;
                           }
                 } else {                  } else {
                         if (file_printf(ms, " %d.%d", desc / 100000,                          if (file_printf(ms, " %d.%d", desc / 100000,
                             desc / 1000 % 100) == -1)                              desc / 1000 % 100) == -1)
                                 return size;                                  return size;
                         desc %= 1000;                          if ((desc / 100 % 10 > 0) ||
                         if (desc > 100) {                              (desc % 100000 / 100 == 0)) {
                                 if (file_printf(ms, "-CURRENT (rev %d)",                                  if (file_printf(ms, " (%d)", desc) == -1)
                                     desc % 100) == -1)  
                                         return size;                                          return size;
                         } else if (desc != 0) {                          } else if (desc / 10 % 10 > 0) {
                                 if (file_printf(ms, ".%d", desc / 10) == -1)                                  if (file_printf(ms, ".%d", desc / 10 % 10)
                                       == -1)
                                         return size;                                          return size;
                         }                          }
                 }                  }
                   *flags |= FLAGS_DID_NOTE;
                 return size;                  return size;
         }          }
   
         if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 &&          if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 &&
             nh_type == NT_OPENBSD_VERSION && descsz == 4) {              xnh_type == NT_OPENBSD_VERSION && descsz == 4) {
                 if (file_printf(ms, ", for OpenBSD") == -1)                  if (file_printf(ms, ", for OpenBSD") == -1)
                         return size;                          return size;
                 /* Content of note is always 0 */                  /* Content of note is always 0 */
                   *flags |= FLAGS_DID_NOTE;
                 return size;                  return size;
         }          }
   
           if (namesz == 10 && strcmp((char *)&nbuf[noff], "DragonFly") == 0 &&
               xnh_type == NT_DRAGONFLY_VERSION && descsz == 4) {
                   uint32_t desc;
                   if (file_printf(ms, ", for DragonFly") == -1)
                           return size;
                   (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
                   desc = getu32(swap, desc);
                   if (file_printf(ms, " %d.%d.%d", desc / 100000,
                       desc / 10000 % 10, desc % 10000) == -1)
                           return size;
                   *flags |= FLAGS_DID_NOTE;
                   return size;
           }
   
   core:
         /*          /*
          * Sigh.  The 2.0.36 kernel in Debian 2.1, at           * Sigh.  The 2.0.36 kernel in Debian 2.1, at
          * least, doesn't correctly implement name           * least, doesn't correctly implement name
Line 476 
Line 585 
         }          }
   
 #ifdef ELFCORE  #ifdef ELFCORE
         if (os_style != -1)          if ((*flags & FLAGS_DID_CORE) != 0)
                 if (file_printf(ms, ", %s-style", os_style_names[os_style]) == -1)                  return size;
   
           if (os_style != -1) {
                   if (file_printf(ms, ", %s-style", os_style_names[os_style])
                       == -1)
                         return size;                          return size;
           }
   
         if (os_style == OS_STYLE_NETBSD && nh_type == NT_NETBSD_CORE_PROCINFO) {          switch (os_style) {
                 uint32_t signo;          case OS_STYLE_NETBSD:
                 /*                  if (xnh_type == NT_NETBSD_CORE_PROCINFO) {
                  * Extract the program name.  It is at                          uint32_t signo;
                  * offset 0x7c, and is up to 32-bytes,                          /*
                  * including the terminating NUL.                           * Extract the program name.  It is at
                  */                           * offset 0x7c, and is up to 32-bytes,
                 if (file_printf(ms, ", from '%.31s'", &nbuf[doff + 0x7c]) == -1)                           * including the terminating NUL.
                            */
                           if (file_printf(ms, ", from '%.31s'",
                               &nbuf[doff + 0x7c]) == -1)
                                   return size;
   
                           /*
                            * Extract the signal number.  It is at
                            * offset 0x08.
                            */
                           (void)memcpy(&signo, &nbuf[doff + 0x08],
                               sizeof(signo));
                           if (file_printf(ms, " (signal %u)",
                               getu32(swap, signo)) == -1)
                                   return size;
                         return size;                          return size;
                   }
                 /*                  break;
                  * Extract the signal number.  It is at  
                  * offset 0x08.  
                  */  
                 memcpy(&signo, &nbuf[doff + 0x08],  
                     sizeof(signo));  
                 if (file_printf(ms, " (signal %u)", getu32(swap, signo)) == -1)  
                         return size;  
                 return size;  
         } else if (os_style != OS_STYLE_NETBSD && nh_type == NT_PRPSINFO) {  
                 size_t i, j;  
                 unsigned char c;  
                 /*  
                  * 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 varous OSes, so try multiple offsets.  
                  * If the characters aren't all printable,  
                  * reject it.  
                  */  
                 for (i = 0; i < NOFFSETS; i++) {  
                         size_t reloffset = prpsoffsets(i);  
                         size_t noffset = doff + 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 >= size)  
                                         goto tryanother;  
   
                                 /*          default:
                                  * Make sure we're not past                  if (xnh_type == NT_PRPSINFO) {
                                  * the end of the contents;                          size_t i, j;
                                  * if we are, this obviously                          unsigned char c;
                                  * isn't the right offset.                          /*
                                  */                           * Extract the program name.  We assume
                                 if (reloffset >= descsz)                           * it to be 16 characters (that's what it
                                         goto tryanother;                           * is in SunOS 5.x and Linux).
                            *
                                 c = nbuf[noffset];                           * Unfortunately, it's at a different offset
                                 if (c == '\0') {                           * in various OSes, so try multiple offsets.
                            * If the characters aren't all printable,
                            * reject it.
                            */
                           for (i = 0; i < NOFFSETS; i++) {
                                   size_t reloffset = prpsoffsets(i);
                                   size_t noffset = doff + reloffset;
                                   for (j = 0; j < 16; j++, noffset++,
                                       reloffset++) {
                                         /*                                          /*
                                          * A '\0' at the                                           * Make sure we're not past
                                          * beginning is                                           * the end of the buffer; if
                                          * obviously wrong.                                           * we are, just give up.
                                          * Any other '\0'  
                                          * means we're done.  
                                          */                                           */
                                         if (j == 0)                                          if (noffset >= size)
                                                 goto tryanother;                                                  goto tryanother;
                                         else  
                                                 break;  
                                 } else {  
                                         /*                                          /*
                                          * A nonprintable                                           * Make sure we're not past
                                          * character is also                                           * the end of the contents;
                                          * wrong.                                           * if we are, this obviously
                                            * isn't the right offset.
                                          */                                           */
 #define isquote(c) (strchr("'\"`", (c)) != NULL)                                          if (reloffset >= descsz)
                                         if (!isprint(c) || isquote(c))  
                                                 goto tryanother;                                                  goto tryanother;
                                 }  
                         }  
   
                         /*                                          c = nbuf[noffset];
                          * Well, that worked.                                          if (c == '\0') {
                          */                                                  /*
                         if (file_printf(ms, ", from '%.16s'",                                                   * A '\0' at the
                             &nbuf[doff + prpsoffsets(i)]) == -1)                                                   * beginning is
                                                    * obviously wrong.
                                                    * Any other '\0'
                                                    * means we're done.
                                                    */
                                                   if (j == 0)
                                                           goto tryanother;
                                                   else
                                                           break;
                                           } else {
                                                   /*
                                                    * A nonprintable
                                                    * character is also
                                                    * wrong.
                                                    */
                                                   if (!isprint(c) || isquote(c))
                                                           goto tryanother;
                                           }
                                   }
                                   /*
                                    * Well, that worked.
                                    */
                                   if (file_printf(ms, ", from '%.16s'",
                                       &nbuf[doff + prpsoffsets(i)]) == -1)
                                           return size;
                                 return size;                                  return size;
                         return size;  
   
                 tryanother:                          tryanother:
                         ;                                  ;
                           }
                 }                  }
                 return offset;                  break;
         }          }
 #endif  #endif
           *flags |= FLAGS_DID_CORE;
         return offset;          return offset;
 }  }
   
 private int  private int
 doshn(struct magic_set *ms, int class, int swap, int fd, off_t off, int num,  doshn(struct magic_set *ms, int class, int swap, int fd, off_t off, int num,
     size_t size)      size_t size, int *flags)
 {  {
         Elf32_Shdr sh32;          Elf32_Shdr sh32;
         Elf64_Shdr sh64;          Elf64_Shdr sh64;
           int stripped = 1;
           void *nbuf;
           off_t noff;
   
         if (size != sh_size) {          if (size != xsh_sizeof) {
                 if (file_printf(ms, ", corrupted section header size") == -1)                  if (file_printf(ms, ", corrupted section header size") == -1)
                         return -1;                          return -1;
                 return 0;                  return 0;
Line 594 
Line 720 
         }          }
   
         for ( ; num; num--) {          for ( ; num; num--) {
                 if (read(fd, sh_addr, sh_size) == -1) {                  if (read(fd, xsh_addr, xsh_sizeof) == -1) {
                         file_badread(ms);                          file_badread(ms);
                         return -1;                          return -1;
                 }                  }
                 if (shs_type == SHT_SYMTAB /* || shs_type == SHT_DYNSYM */) {                  switch (xsh_type) {
                         if (file_printf(ms, ", not stripped") == -1)                  case SHT_SYMTAB:
   #if 0
                   case SHT_DYNSYM:
   #endif
                           stripped = 0;
                           break;
                   case SHT_NOTE:
                           if ((off = lseek(fd, (off_t)0, SEEK_CUR)) ==
                               (off_t)-1) {
                                   file_badread(ms);
                                 return -1;                                  return -1;
                         return 0;                          }
                           if ((nbuf = malloc((size_t)xsh_size)) == NULL) {
                                   file_error(ms, errno, "Cannot allocate memory"
                                       " for note");
                                   return -1;
                           }
                           if ((noff = lseek(fd, (off_t)xsh_offset, SEEK_SET)) ==
                               (off_t)-1) {
                                   file_badread(ms);
                                   free(nbuf);
                                   return -1;
                           }
                           if (read(fd, nbuf, (size_t)xsh_size) !=
                               (ssize_t)xsh_size) {
                                   free(nbuf);
                                   file_badread(ms);
                                   return -1;
                           }
   
                           noff = 0;
                           for (;;) {
                                   if (noff >= (size_t)xsh_size)
                                           break;
                                   noff = donote(ms, nbuf, (size_t)noff,
                                       (size_t)xsh_size, class, swap, 4,
                                       flags);
                                   if (noff == 0)
                                           break;
                           }
                           if ((lseek(fd, off, SEEK_SET)) == (off_t)-1) {
                                   free(nbuf);
                                   file_badread(ms);
                                   return -1;
                           }
                           free(nbuf);
                           break;
                 }                  }
         }          }
         if (file_printf(ms, ", stripped") == -1)          if (file_printf(ms, ", %sstripped", stripped ? "" : "not ") == -1)
                 return -1;                  return -1;
         return 0;          return 0;
 }  }
Line 616 
Line 786 
  */   */
 private int  private int
 dophn_exec(struct magic_set *ms, int class, int swap, int fd, off_t off,  dophn_exec(struct magic_set *ms, int class, int swap, int fd, off_t off,
     int num, size_t size)      int num, size_t size, off_t fsize, int *flags)
 {  {
         Elf32_Phdr ph32;          Elf32_Phdr ph32;
         Elf64_Phdr ph64;          Elf64_Phdr ph64;
Line 625 
Line 795 
         unsigned char nbuf[BUFSIZ];          unsigned char nbuf[BUFSIZ];
         int bufsize;          int bufsize;
         size_t offset, align;          size_t offset, align;
         off_t savedoffset;          off_t savedoffset = (off_t)-1;
           struct stat st;
   
         if (size != ph_size) {          if (fstat(fd, &st) < 0) {
                   file_badread(ms);
                   return -1;
           }
   
           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;
         }          }
   
         if (lseek(fd, off, SEEK_SET) == (off_t)-1) {          if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
                 file_badseek(ms);                  file_badseek(ms);
                 return -1;                  return -1;
         }          }
   
         for ( ; num; num--) {          for ( ; num; num--) {
                 if (read(fd, ph_addr, ph_size) == -1) {                  if (read(fd, xph_addr, xph_sizeof) == -1) {
                         file_badread(ms);                          file_badread(ms);
                         return -1;                          return -1;
                 }                  }
                   if (xph_offset > st.st_size && savedoffset != (off_t)-1) {
                           if (lseek(fd, savedoffset, SEEK_SET) == (off_t)-1) {
                                   file_badseek(ms);
                                   return -1;
                           }
                           continue;
                   }
   
                 if ((savedoffset = lseek(fd, (off_t)0, SEEK_CUR)) == (off_t)-1) {                  if ((savedoffset = lseek(fd, (off_t)0, SEEK_CUR)) == (off_t)-1) {
                         file_badseek(ms);                          file_badseek(ms);
                         return -1;                          return -1;
                 }                  }
   
                 switch (ph_type) {                  if (xph_offset > fsize) {
                           if (lseek(fd, savedoffset, SEEK_SET) == (off_t)-1) {
                                   file_badseek(ms);
                                   return -1;
                           }
                           continue;
                   }
   
                   switch (xph_type) {
                 case PT_DYNAMIC:                  case PT_DYNAMIC:
                         linking_style = "dynamically";                          linking_style = "dynamically";
                         break;                          break;
Line 655 
Line 848 
                         shared_libraries = " (uses shared libs)";                          shared_libraries = " (uses shared libs)";
                         break;                          break;
                 case PT_NOTE:                  case PT_NOTE:
                         if ((align = ph_align) & 0x80000000) {                          if ((align = xph_align) & 0x80000000) {
                                 if (file_printf(ms,                                  if (file_printf(ms,
                                     ", invalid note alignment 0x%lx",                                      ", invalid note alignment 0x%lx",
                                     (unsigned long)align) == -1)                                      (unsigned long)align) == -1)
Line 666 
Line 859 
                          * This is a PT_NOTE section; loop through all the notes                           * This is a PT_NOTE section; loop through all the notes
                          * in the section.                           * in the section.
                          */                           */
                         if (lseek(fd, (off_t) ph_offset, SEEK_SET)                          if (lseek(fd, xph_offset, SEEK_SET)
                             == (off_t)-1) {                              == (off_t)-1) {
                                 file_badseek(ms);                                  file_badseek(ms);
                                 return -1;                                  return -1;
                         }                          }
                         bufsize = read(fd, nbuf, sizeof(nbuf));                          bufsize = read(fd, nbuf, ((xph_filesz < sizeof(nbuf)) ?
                               xph_filesz : sizeof(nbuf)));
                         if (bufsize == -1) {                          if (bufsize == -1) {
                                 file_badread(ms);                                  file_badread(ms);
                                 return -1;                                  return -1;
Line 681 
Line 875 
                                 if (offset >= (size_t)bufsize)                                  if (offset >= (size_t)bufsize)
                                         break;                                          break;
                                 offset = donote(ms, nbuf, offset,                                  offset = donote(ms, nbuf, offset,
                                     (size_t)bufsize, class, swap, align);                                      (size_t)bufsize, class, swap, align,
                                       flags);
                                 if (offset == 0)                                  if (offset == 0)
                                         break;                                          break;
                         }                          }
                         if (lseek(fd, savedoffset + offset, SEEK_SET)                          if (lseek(fd, savedoffset, SEEK_SET) == (off_t)-1) {
                             == (off_t)-1) {  
                                 file_badseek(ms);                                  file_badseek(ms);
                                 return -1;                                  return -1;
                         }                          }
Line 710 
Line 904 
         } u;          } u;
         int class;          int class;
         int swap;          int swap;
           struct stat st;
           off_t fsize;
           int flags = 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.
Line 717 
Line 914 
         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))
                 fd = file_pipe2file(ms, fd, buf, nbytes);                  fd = file_pipe2file(ms, fd, buf, nbytes);
   
           if (fstat(fd, &st) == -1) {
                   file_badread(ms);
                   return -1;
           }
           fsize = st.st_size;
   
         /*          /*
          * ELF executables have multiple section headers in arbitrary           * ELF executables have multiple section headers in arbitrary
          * file locations and thus file(1) cannot determine it from easily.           * file locations and thus file(1) cannot determine it from easily.
Line 729 
Line 932 
             return 0;              return 0;
   
   
         class = buf[4];          class = buf[EI_CLASS];
   
         if (class == ELFCLASS32) {          if (class == ELFCLASS32) {
                 Elf32_Ehdr elfhdr;                  Elf32_Ehdr elfhdr;
Line 739 
Line 942 
   
                 u.l = 1;                  u.l = 1;
                 (void) memcpy(&elfhdr, buf, sizeof elfhdr);                  (void) memcpy(&elfhdr, buf, sizeof elfhdr);
                 swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[5];                  swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[EI_DATA];
   
                 if (getu16(swap, elfhdr.e_type) == ET_CORE) {                  if (getu16(swap, elfhdr.e_type) == ET_CORE) {
 #ifdef ELFCORE  #ifdef ELFCORE
                         if (dophn_core(ms, class, swap, fd,                          if (dophn_core(ms, class, swap, fd,
                             (off_t)getu32(swap, elfhdr.e_phoff),                              (off_t)getu32(swap, elfhdr.e_phoff),
                             getu16(swap, elfhdr.e_phnum),                              getu16(swap, elfhdr.e_phnum),
                             (size_t)getu16(swap, elfhdr.e_phentsize)) == -1)                              (size_t)getu16(swap, elfhdr.e_phentsize),
                               fsize, &flags) == -1)
                                 return -1;                                  return -1;
 #else  #else
                         ;                          ;
Line 756 
Line 960 
                                 if (dophn_exec(ms, class, swap,                                  if (dophn_exec(ms, class, swap,
                                     fd, (off_t)getu32(swap, elfhdr.e_phoff),                                      fd, (off_t)getu32(swap, elfhdr.e_phoff),
                                     getu16(swap, elfhdr.e_phnum),                                      getu16(swap, elfhdr.e_phnum),
                                     (size_t)getu16(swap, elfhdr.e_phentsize))                                      (size_t)getu16(swap, elfhdr.e_phentsize),
                                       fsize, &flags)
                                     == -1)                                      == -1)
                                         return -1;                                          return -1;
                         }                          }
                         if (doshn(ms, class, swap, fd,                          if (doshn(ms, class, swap, fd,
                             (off_t)getu32(swap, elfhdr.e_shoff),                              (off_t)getu32(swap, elfhdr.e_shoff),
                             getu16(swap, elfhdr.e_shnum),                              getu16(swap, elfhdr.e_shnum),
                             (size_t)getu16(swap, elfhdr.e_shentsize)) == -1)                              (size_t)getu16(swap, elfhdr.e_shentsize),
                               &flags) == -1)
                                 return -1;                                  return -1;
                 }                  }
                 return 1;                  return 1;
Line 777 
Line 983 
   
                 u.l = 1;                  u.l = 1;
                 (void) memcpy(&elfhdr, buf, sizeof elfhdr);                  (void) memcpy(&elfhdr, buf, sizeof elfhdr);
                 swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[5];                  swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[EI_DATA];
   
                 if (getu16(swap, elfhdr.e_type) == ET_CORE) {                  if (getu16(swap, elfhdr.e_type) == ET_CORE) {
 #ifdef ELFCORE  #ifdef ELFCORE
                         if (dophn_core(ms, class, swap, fd,                          if (dophn_core(ms, class, swap, fd,
 #ifdef USE_ARRAY_FOR_64BIT_TYPES                              (off_t)elf_getu64(swap, elfhdr.e_phoff),
                             (off_t)getu32(swap, elfhdr.e_phoff[1]),  
 #else  
                             (off_t)getu64(swap, elfhdr.e_phoff),  
 #endif  
                             getu16(swap, elfhdr.e_phnum),                              getu16(swap, elfhdr.e_phnum),
                             (size_t)getu16(swap, elfhdr.e_phentsize)) == -1)                              (size_t)getu16(swap, elfhdr.e_phentsize),
                               fsize, &flags) == -1)
                                 return -1;                                  return -1;
 #else  #else
                         ;                          ;
Line 796 
Line 999 
                 } else {                  } else {
                         if (getu16(swap, elfhdr.e_type) == ET_EXEC) {                          if (getu16(swap, elfhdr.e_type) == ET_EXEC) {
                                 if (dophn_exec(ms, class, swap, fd,                                  if (dophn_exec(ms, class, swap, fd,
 #ifdef USE_ARRAY_FOR_64BIT_TYPES                                      (off_t)elf_getu64(swap, elfhdr.e_phoff),
                                     (off_t)getu32(swap, elfhdr.e_phoff[1]),  
 #else  
                                     (off_t)getu64(swap, elfhdr.e_phoff),  
 #endif  
                                     getu16(swap, elfhdr.e_phnum),                                      getu16(swap, elfhdr.e_phnum),
                                     (size_t)getu16(swap, elfhdr.e_phentsize))                                      (size_t)getu16(swap, elfhdr.e_phentsize),
                                     == -1)                                      fsize, &flags) == -1)
                                         return -1;                                          return -1;
                         }                          }
                         if (doshn(ms, class, swap, fd,                          if (doshn(ms, class, swap, fd,
 #ifdef USE_ARRAY_FOR_64BIT_TYPES                              (off_t)elf_getu64(swap, elfhdr.e_shoff),
                             (off_t)getu32(swap, elfhdr.e_shoff[1]),  
 #else  
                             (off_t)getu64(swap, elfhdr.e_shoff),  
 #endif  
                             getu16(swap, elfhdr.e_shnum),                              getu16(swap, elfhdr.e_shnum),
                             (size_t)getu16(swap, elfhdr.e_shentsize)) == -1)                              (size_t)getu16(swap, elfhdr.e_shentsize), &flags)
                               == -1)
                                 return -1;                                  return -1;
                 }                  }
                 return 1;                  return 1;

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