From: Christos Zoulas Date: Wed, 28 May 2008 21:02:28 +0000 (+0000) Subject: Solaris enchancements from Bob Byrnes. X-Git-Tag: FILE4_25~20 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5c0645db483680f01bc5d9cd2a12f63e7afd0c44;p=file Solaris enchancements from Bob Byrnes. --- diff --git a/ChangeLog b/ChangeLog index a6f203eb..b1c78210 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2008-05-28 15:12 Robert Byrnes + + * 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 * Fix compiler warnings. diff --git a/magic/Magdir/elf b/magic/Magdir/elf index 74070502..b578929d 100644 --- a/magic/Magdir/elf +++ b/magic/Magdir/elf @@ -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, @@ -231,6 +231,12 @@ >>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, diff --git a/src/elfclass.h b/src/elfclass.h index 7f6d8adc..8b7f6f90 100644 --- a/src/elfclass.h +++ b/src/elfclass.h @@ -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; diff --git a/src/file.h b/src/file.h index b8b211b8..ea8e59c7 100644 --- a/src/file.h +++ b/src/file.h @@ -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, ...); diff --git a/src/readelf.c b/src/readelf.c index f780c266..4b86d56f 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -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; } diff --git a/src/readelf.h b/src/readelf.h index 2848f6de..ab4b5d1d 100644 --- a/src/readelf.h +++ b/src/readelf.h @@ -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 diff --git a/src/vasprintf.c b/src/vasprintf.c index 2ee73121..5022f163 100644 --- a/src/vasprintf.c +++ b/src/vasprintf.c @@ -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':