#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
#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 *);
#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
/*
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)
}
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;
}
#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] */
#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