]> granicus.if.org Git - file/commitdiff
Solaris enchancements from Bob Byrnes.
authorChristos Zoulas <christos@zoulas.com>
Wed, 28 May 2008 21:02:28 +0000 (21:02 +0000)
committerChristos Zoulas <christos@zoulas.com>
Wed, 28 May 2008 21:02:28 +0000 (21:02 +0000)
ChangeLog
magic/Magdir/elf
src/elfclass.h
src/file.h
src/readelf.c
src/readelf.h
src/vasprintf.c

index a6f203eb12935641d4532a87fbd311937a386816..b1c78210008849387f5d1d909f71573ea7856ef8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2008-05-28 15:12  Robert Byrnes  <byrnes@wildpumpkin.net>
+
+       * magic/Magdir/elf:
+         Note invalid byte order for little-endian SPARC32PLUS.
+         Add SPARC V9 vendor extensions and memory model.
+
+       * src/elfclass.h:
+         Pass target machine to doshn (for Solaris hardware capabilities).
+
+       * src/readelf.c (doshn):
+         Add support for Solaris hardware/software capabilities.
+
+       * src/readelf.h:
+         Ditto.
+
+       * src/vasprintf.c (dispatch):
+         Add support for ll modifier.
+
 2008-05-16 10:25  Christos Zoulas  <christos@astron.com>
 
        * Fix compiler warnings.
index 74070502db2fb5dde4726afb6b4cda063ca8f59a..b578929ddd8c85db0900cb610b938318bfe76180 100644 (file)
@@ -82,7 +82,7 @@
 >>>48  leshort         &0x0008         (LP64),
 >>18   leshort         16              nCUBE,
 >>18   leshort         17              Fujitsu VPP500,
->>18   leshort         18              SPARC32PLUS,
+>>18   leshort         18              SPARC32PLUS - invalid byte order,
 >>18   leshort         20              PowerPC,
 >>18   leshort         22              IBM S/390,
 >>18   leshort         36              NEC V800,
 >>18   beshort         41              Alpha,
 >>18   beshort         42              Renesas SH,
 >>18   beshort         43              SPARC V9,
+>>>48  belong&0xffff00 &0x000200       Sun UltraSPARC1 Extensions Required,
+>>>48  belong&0xffff00 &0x000400       HaL R1 Extensions Required,
+>>>48  belong&0xffff00 &0x000800       Sun UltraSPARC3 Extensions Required,
+>>>48  belong&0x3      0               total store ordering,
+>>>48  belong&0x3      1               partial store ordering,
+>>>48  belong&0x3      2               relaxed memory ordering,
 >>18   beshort         44              Siemens Tricore Embedded Processor,
 >>18   beshort         45              Argonaut RISC Core, Argonaut Technologies Inc.,
 >>18   beshort         46              Renesas H8/300,
index 7f6d8adce6d53cefe2c49c1b25a569dc69e2ea6d..8b7f6f903b4880e1542bec9cff9aa59278c8624b 100644 (file)
@@ -57,7 +57,8 @@
                    (off_t)elf_getu(swap, elfhdr.e_shoff),
                    elf_getu16(swap, elfhdr.e_shnum),
                    (size_t)elf_getu16(swap, elfhdr.e_shentsize),
-                   &flags) == -1)
+                   &flags,
+                   elf_getu16(swap, elfhdr.e_machine)) == -1)
                        return -1;
                break;
 
index b8b211b82159e8ea91ab7b7d4ea127cbea64f690..ea8e59c783e3638d499678f42fd9358661631e1d 100644 (file)
@@ -27,7 +27,7 @@
  */
 /*
  * file.h - definitions for file(1) program
- * @(#)$File: file.h,v 1.103 2008/03/01 22:21:49 rrt Exp $
+ * @(#)$File: file.h,v 1.104 2008/05/09 14:20:28 christos Exp $
  */
 
 #ifndef __file_h__
@@ -324,6 +324,7 @@ protected int file_buffer(struct magic_set *, int, const char *, const void *,
     size_t);
 protected int file_fsmagic(struct magic_set *, const char *, struct stat *);
 protected int file_pipe2file(struct magic_set *, int, const void *, size_t);
+protected int file_vprintf(struct magic_set *, const char *, va_list);
 protected int file_printf(struct magic_set *, const char *, ...)
     __attribute__((__format__(__printf__, 2, 3)));
 protected int file_reset(struct magic_set *);
@@ -372,7 +373,7 @@ extern char *sys_errlist[];
 #endif
 
 #ifndef HAVE_VASPRINTF
-int vasprintf(char **ptr, const char *format_string, va_list vargs);
+int vasprintf(char **, const char *, va_list);
 #endif
 #ifndef HAVE_ASPRINTF
 int asprintf(char **ptr, const char *format_string, ...);
index f780c2662a973fa4963c031e50770d403ff8d073..4b86d56fb5897bb2ef5ce344705c4b34173b9e63 100644 (file)
@@ -38,7 +38,7 @@
 #include "magic.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: readelf.c,v 1.72 2008/02/19 15:53:09 christos Exp $")
+FILE_RCSID("@(#)$File: readelf.c,v 1.73 2008/03/27 22:00:28 christos Exp $")
 #endif
 
 #ifdef ELFCORE
@@ -47,7 +47,8 @@ private int dophn_core(struct magic_set *, int, int, int, off_t, int, size_t,
 #endif
 private int dophn_exec(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 int doshn(struct magic_set *, int, int, int, off_t, int, size_t, int *,
+    int);
 private size_t donote(struct magic_set *, unsigned char *, size_t, size_t, int,
     int, size_t, int *);
 
@@ -190,6 +191,18 @@ getu64(int swap, uint64_t value)
 #define prpsoffsets(i) (class == ELFCLASS32                    \
                         ? prpsoffsets32[i]                     \
                         : prpsoffsets64[i])
+#define xcap_addr      (class == ELFCLASS32                    \
+                        ? (void *) &cap32                      \
+                        : (void *) &cap64)
+#define xcap_sizeof    (class == ELFCLASS32                    \
+                        ? sizeof cap32                         \
+                        : sizeof cap64)
+#define xcap_tag       (class == ELFCLASS32                    \
+                        ? elf_getu32(swap, cap32.c_tag)        \
+                        : elf_getu64(swap, cap64.c_tag))
+#define xcap_val       (class == ELFCLASS32                    \
+                        ? elf_getu32(swap, cap32.c_un.c_val)   \
+                        : elf_getu64(swap, cap64.c_un.c_val))
 
 #ifdef ELFCORE
 /*
@@ -750,15 +763,67 @@ core:
        return offset;
 }
 
+/* SunOS 5.x hardware capability descriptions */
+typedef struct cap_desc {
+       uint64_t cd_mask;
+       const char *cd_name;
+} cap_desc_t;
+
+static const cap_desc_t cap_desc_sparc[] = {
+       { AV_SPARC_MUL32,               "MUL32" },
+       { AV_SPARC_DIV32,               "DIV32" },
+       { AV_SPARC_FSMULD,              "FSMULD" },
+       { AV_SPARC_V8PLUS,              "V8PLUS" },
+       { AV_SPARC_POPC,                "POPC" },
+       { AV_SPARC_VIS,                 "VIS" },
+       { AV_SPARC_VIS2,                "VIS2" },
+       { AV_SPARC_ASI_BLK_INIT,        "ASI_BLK_INIT" },
+       { AV_SPARC_FMAF,                "FMAF" },
+       { AV_SPARC_FJFMAU,              "FJFMAU" },
+       { AV_SPARC_IMA,                 "IMA" },
+       { 0, NULL }
+};
+
+static const cap_desc_t cap_desc_386[] = {
+       { AV_386_FPU,                   "FPU" },
+       { AV_386_TSC,                   "TSC" },
+       { AV_386_CX8,                   "CX8" },
+       { AV_386_SEP,                   "SEP" },
+       { AV_386_AMD_SYSC,              "AMD_SYSC" },
+       { AV_386_CMOV,                  "CMOV" },
+       { AV_386_MMX,                   "MMX" },
+       { AV_386_AMD_MMX,               "AMD_MMX" },
+       { AV_386_AMD_3DNow,             "AMD_3DNow" },
+       { AV_386_AMD_3DNowx,            "AMD_3DNowx" },
+       { AV_386_FXSR,                  "FXSR" },
+       { AV_386_SSE,                   "SSE" },
+       { AV_386_SSE2,                  "SSE2" },
+       { AV_386_PAUSE,                 "PAUSE" },
+       { AV_386_SSE3,                  "SSE3" },
+       { AV_386_MON,                   "MON" },
+       { AV_386_CX16,                  "CX16" },
+       { AV_386_AHF,                   "AHF" },
+       { AV_386_TSCP,                  "TSCP" },
+       { AV_386_AMD_SSE4A,             "AMD_SSE4A" },
+       { AV_386_POPCNT,                "POPCNT" },
+       { AV_386_AMD_LZCNT,             "AMD_LZCNT" },
+       { AV_386_SSSE3,                 "SSSE3" },
+       { AV_386_SSE4_1,                "SSE4.1" },
+       { AV_386_SSE4_2,                "SSE4.2" },
+       { 0, NULL }
+};
+
 private int
 doshn(struct magic_set *ms, int class, int swap, int fd, off_t off, int num,
-    size_t size, int *flags)
+    size_t size, int *flags, int mach)
 {
        Elf32_Shdr sh32;
        Elf64_Shdr sh64;
        int stripped = 1;
        void *nbuf;
        off_t noff;
+       uint64_t cap_hw1 = 0;   /* SunOS 5.x hardware capabilites */
+       uint64_t cap_sf1 = 0;   /* SunOS 5.x software capabilites */
 
        if (size != xsh_sizeof) {
                if (file_printf(ms, ", corrupted section header size") == -1)
@@ -824,10 +889,115 @@ doshn(struct magic_set *ms, int class, int swap, int fd, off_t off, int num,
                        }
                        free(nbuf);
                        break;
+               case SHT_SUNW_cap:
+                   {
+                       off_t coff;
+                       if ((off = lseek(fd, (off_t)0, SEEK_CUR)) ==
+                           (off_t)-1) {
+                               file_badread(ms);
+                               return -1;
+                       }
+                       if (lseek(fd, (off_t)xsh_offset, SEEK_SET) ==
+                           (off_t)-1) {
+                               file_badread(ms);
+                               return -1;
+                       }
+                       coff = 0;
+                       for (;;) {
+                               Elf32_Cap cap32;
+                               Elf64_Cap cap64;
+                               char cbuf[MAX(sizeof cap32, sizeof cap64)];
+                               if ((coff += xcap_sizeof) >= (size_t)xsh_size)
+                                       break;
+                               if (read(fd, cbuf, (size_t)xcap_sizeof) !=
+                                   (ssize_t)xcap_sizeof) {
+                                       file_badread(ms);
+                                       return -1;
+                               }
+                               (void)memcpy(xcap_addr, cbuf, xcap_sizeof);
+                               switch (xcap_tag) {
+                               case CA_SUNW_NULL:
+                                       break;
+                               case CA_SUNW_HW_1:
+                                       cap_hw1 |= xcap_val;
+                                       break;
+                               case CA_SUNW_SF_1:
+                                       cap_sf1 |= xcap_val;
+                                       break;
+                               default:
+                                       if (file_printf(ms,
+                                           ", with unknown capability "
+                                           "0x%llx = 0x%llx",
+                                           xcap_tag, xcap_val) == -1)
+                                               return -1;
+                                       break;
+                               }
+                       }
+                       if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
+                               file_badread(ms);
+                               return -1;
+                       }
+                       break;
+                   }
                }
        }
        if (file_printf(ms, ", %sstripped", stripped ? "" : "not ") == -1)
                return -1;
+       if (cap_hw1) {
+               const cap_desc_t *cdp;
+               switch (mach) {
+               case EM_SPARC:
+               case EM_SPARC32PLUS:
+               case EM_SPARCV9:
+                       cdp = cap_desc_sparc;
+                       break;
+               case EM_386:
+               case EM_IA_64:
+               case EM_AMD64:
+                       cdp = cap_desc_386;
+                       break;
+               default:
+                       cdp = NULL;
+                       break;
+               }
+               if (file_printf(ms, ", uses") == -1)
+                       return -1;
+               if (cdp) {
+                       while (cdp->cd_name) {
+                               if (cap_hw1 & cdp->cd_mask) {
+                                       if (file_printf(ms,
+                                           " %s", cdp->cd_name) == -1)
+                                               return -1;
+                                       cap_hw1 &= ~cdp->cd_mask;
+                               }
+                               ++cdp;
+                       }
+                       if (cap_hw1)
+                               if (file_printf(ms,
+                                   " unknown hardware capability 0x%llx",
+                                   cap_hw1) == -1)
+                                       return -1;
+               } else {
+                       if (file_printf(ms,
+                           " hardware capability 0x%llx", cap_hw1) == -1)
+                               return -1;
+               }
+       }
+       if (cap_sf1) {
+               if (cap_sf1 & SF1_SUNW_FPUSED) {
+                       if (file_printf(ms,
+                           (cap_sf1 & SF1_SUNW_FPKNWN)
+                           ? ", uses frame pointer"
+                           : ", not known to use frame pointer") == -1)
+                               return -1;
+               }
+               cap_sf1 &= ~SF1_SUNW_MASK;
+               if (cap_sf1)
+                       if (file_printf(ms,
+                           ", with unknown software capability 0x%llx",
+                           cap_sf1) == -1)
+                               return -1;
+       }
        return 0;
 }
 
index 2848f6dedef294f2e3e5f76d1c052204307eaf00..ab4b5d1d60c5b60ef225675efac688cb4623e575 100644 (file)
@@ -101,10 +101,19 @@ typedef struct {
 #define ET_DYN         3
 #define ET_CORE                4
 
+/* e_machine (used only for SunOS 5.x hardware capabilities) */
+#define        EM_SPARC        2
+#define        EM_386          3
+#define        EM_SPARC32PLUS  18
+#define        EM_SPARCV9      43
+#define        EM_IA_64        50
+#define        EM_AMD64        62
+
 /* sh_type */
 #define SHT_SYMTAB     2
 #define SHT_NOTE       7
 #define SHT_DYNSYM     11
+#define SHT_SUNW_cap   0x6ffffff5      /* SunOS 5.x hw/sw capabilites */
 
 /* elf type */
 #define ELFDATANONE    0               /* e_ident[EI_DATA] */
@@ -233,4 +242,71 @@ typedef struct {
 #define GNU_OS_KFREEBSD        3
 #define GNU_OS_KNETBSD 4
 
+/* SunOS 5.x hardware/software capabilities */
+typedef struct {
+       Elf32_Word      c_tag;
+       union {
+               Elf32_Word      c_val;
+               Elf32_Addr      c_ptr;
+       } c_un;
+} Elf32_Cap;
+
+typedef struct {
+       Elf64_Xword     c_tag;
+       union {
+               Elf64_Xword     c_val;
+               Elf64_Addr      c_ptr;
+       } c_un;
+} Elf64_Cap;
+
+/* SunOS 5.x hardware/software capability tags */
+#define        CA_SUNW_NULL    0
+#define        CA_SUNW_HW_1    1
+#define        CA_SUNW_SF_1    2
+
+/* SunOS 5.x software capabilities */
+#define        SF1_SUNW_FPKNWN 0x01
+#define        SF1_SUNW_FPUSED 0x02
+#define        SF1_SUNW_MASK   0x03
+
+/* SunOS 5.x hardware capabilities: sparc */
+#define        AV_SPARC_MUL32          0x0001
+#define        AV_SPARC_DIV32          0x0002
+#define        AV_SPARC_FSMULD         0x0004
+#define        AV_SPARC_V8PLUS         0x0008
+#define        AV_SPARC_POPC           0x0010
+#define        AV_SPARC_VIS            0x0020
+#define        AV_SPARC_VIS2           0x0040
+#define        AV_SPARC_ASI_BLK_INIT   0x0080
+#define        AV_SPARC_FMAF           0x0100
+#define        AV_SPARC_FJFMAU         0x4000
+#define        AV_SPARC_IMA            0x8000
+
+/* SunOS 5.x hardware capabilities: 386 */
+#define        AV_386_FPU              0x00000001
+#define        AV_386_TSC              0x00000002
+#define        AV_386_CX8              0x00000004
+#define        AV_386_SEP              0x00000008
+#define        AV_386_AMD_SYSC         0x00000010
+#define        AV_386_CMOV             0x00000020
+#define        AV_386_MMX              0x00000040
+#define        AV_386_AMD_MMX          0x00000080
+#define        AV_386_AMD_3DNow        0x00000100
+#define        AV_386_AMD_3DNowx       0x00000200
+#define        AV_386_FXSR             0x00000400
+#define        AV_386_SSE              0x00000800
+#define        AV_386_SSE2             0x00001000
+#define        AV_386_PAUSE            0x00002000
+#define        AV_386_SSE3             0x00004000
+#define        AV_386_MON              0x00008000
+#define        AV_386_CX16             0x00010000
+#define        AV_386_AHF              0x00020000
+#define        AV_386_TSCP             0x00040000
+#define        AV_386_AMD_SSE4A        0x00080000
+#define        AV_386_POPCNT           0x00100000
+#define        AV_386_AMD_LZCNT        0x00200000
+#define        AV_386_SSSE3            0x00400000
+#define        AV_386_SSE4_1           0x00800000
+#define        AV_386_SSE4_2           0x01000000
+
 #endif
index 2ee73121730866af37711f7e45722a69b2c68e63..5022f1634ee25755e58db940e28188130231da41 100644 (file)
@@ -83,7 +83,7 @@ trying to do any interpretation
 flag:   none   +     -     #     (blank)
 width:  n    0n    *
 prec:   none   .0    .n     .*
-modifier:    F N L h l    ('F' and 'N' are ms-dos/16-bit specific)
+modifier:    F N L h l ll    ('F' and 'N' are ms-dos/16-bit specific)
 type:  d i o u x X f e g E G c s p n
 
 
@@ -436,8 +436,15 @@ static int dispatch(xprintf_struct *s)
   }
 
   if (modifier != -1) {
-    *format_ptr = modifier;
-    format_ptr++;
+    if (modifier == 'L' && strchr("diouxX",type) != NULL) {
+      *format_ptr = 'l';
+      format_ptr++;
+      *format_ptr = 'l';
+      format_ptr++;
+    } else {
+      *format_ptr = modifier;
+      format_ptr++;
+    }
   }
 
   *format_ptr = type;
@@ -460,6 +467,8 @@ static int dispatch(xprintf_struct *s)
     switch (modifier) {
     case -1 :
       return print_it(s, (size_t)approx_width, format_string, va_arg(s->vargs, int));
+    case 'L':
+      return print_it(s, (size_t)approx_width, format_string, va_arg(s->vargs, long long int));
     case 'l':
       return print_it(s, (size_t)approx_width, format_string, va_arg(s->vargs, long int));
     case 'h':