1327e51cbSPeter Avalos /*
2327e51cbSPeter Avalos * Copyright (c) Christos Zoulas 2003.
3327e51cbSPeter Avalos * All Rights Reserved.
4327e51cbSPeter Avalos *
5327e51cbSPeter Avalos * Redistribution and use in source and binary forms, with or without
6327e51cbSPeter Avalos * modification, are permitted provided that the following conditions
7327e51cbSPeter Avalos * are met:
8327e51cbSPeter Avalos * 1. Redistributions of source code must retain the above copyright
9327e51cbSPeter Avalos * notice immediately at the beginning of the file, without modification,
10327e51cbSPeter Avalos * this list of conditions, and the following disclaimer.
11327e51cbSPeter Avalos * 2. Redistributions in binary form must reproduce the above copyright
12327e51cbSPeter Avalos * notice, this list of conditions and the following disclaimer in the
13327e51cbSPeter Avalos * documentation and/or other materials provided with the distribution.
14327e51cbSPeter Avalos *
15327e51cbSPeter Avalos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16327e51cbSPeter Avalos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17327e51cbSPeter Avalos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18327e51cbSPeter Avalos * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
19327e51cbSPeter Avalos * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20327e51cbSPeter Avalos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21327e51cbSPeter Avalos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22327e51cbSPeter Avalos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23327e51cbSPeter Avalos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24327e51cbSPeter Avalos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25327e51cbSPeter Avalos * SUCH DAMAGE.
26327e51cbSPeter Avalos */
27327e51cbSPeter Avalos #include "file.h"
28327e51cbSPeter Avalos
2979343712SPeter Avalos #ifndef lint
30*3b9cdfa3SAntonio Huete Jimenez FILE_RCSID("@(#)$File: readelf.c,v 1.182 2022/07/31 16:01:01 christos Exp $")
3179343712SPeter Avalos #endif
3279343712SPeter Avalos
33327e51cbSPeter Avalos #ifdef BUILTIN_ELF
34327e51cbSPeter Avalos #include <string.h>
35327e51cbSPeter Avalos #include <ctype.h>
36327e51cbSPeter Avalos #include <stdlib.h>
37327e51cbSPeter Avalos #ifdef HAVE_UNISTD_H
38327e51cbSPeter Avalos #include <unistd.h>
39327e51cbSPeter Avalos #endif
40327e51cbSPeter Avalos
41327e51cbSPeter Avalos #include "readelf.h"
4279343712SPeter Avalos #include "magic.h"
43327e51cbSPeter Avalos
44327e51cbSPeter Avalos #ifdef ELFCORE
45327e51cbSPeter Avalos private int dophn_core(struct magic_set *, int, int, int, off_t, int, size_t,
4682c5fa3eSPeter Avalos off_t, int *, uint16_t *);
47327e51cbSPeter Avalos #endif
48327e51cbSPeter Avalos private int dophn_exec(struct magic_set *, int, int, int, off_t, int, size_t,
4982c5fa3eSPeter Avalos off_t, int, int *, uint16_t *);
50a96e001bSPeter Avalos private int doshn(struct magic_set *, int, int, int, off_t, int, size_t,
5182c5fa3eSPeter Avalos off_t, int, int, int *, uint16_t *);
5279343712SPeter Avalos private size_t donote(struct magic_set *, void *, size_t, size_t, int,
53c30bd091SSascha Wildner int, size_t, int *, uint16_t *, int, off_t, int, off_t);
54327e51cbSPeter Avalos
55327e51cbSPeter Avalos #define ELF_ALIGN(a) ((((a) + align - 1) / align) * align)
56327e51cbSPeter Avalos
57327e51cbSPeter Avalos #define isquote(c) (strchr("'\"`", (c)) != NULL)
58327e51cbSPeter Avalos
59327e51cbSPeter Avalos private uint16_t getu16(int, uint16_t);
60327e51cbSPeter Avalos private uint32_t getu32(int, uint32_t);
61327e51cbSPeter Avalos private uint64_t getu64(int, uint64_t);
62327e51cbSPeter Avalos
6382c5fa3eSPeter Avalos #define MAX_PHNUM 128
6482c5fa3eSPeter Avalos #define MAX_SHNUM 32768
65*3b9cdfa3SAntonio Huete Jimenez #define MAX_SHSIZE (64 * 1024 * 1024)
666fca56fbSSascha Wildner #define SIZE_UNKNOWN CAST(off_t, -1)
6782c5fa3eSPeter Avalos
6882c5fa3eSPeter Avalos private int
toomany(struct magic_set * ms,const char * name,uint16_t num)6982c5fa3eSPeter Avalos toomany(struct magic_set *ms, const char *name, uint16_t num)
7082c5fa3eSPeter Avalos {
71c990e5baSDaniel Fojt if (ms->flags & MAGIC_MIME)
72c990e5baSDaniel Fojt return 1;
736fca56fbSSascha Wildner if (file_printf(ms, ", too many %s (%u)", name, num) == -1)
7482c5fa3eSPeter Avalos return -1;
756fca56fbSSascha Wildner return 1;
7682c5fa3eSPeter Avalos }
7782c5fa3eSPeter Avalos
78327e51cbSPeter Avalos private uint16_t
getu16(int swap,uint16_t value)79327e51cbSPeter Avalos getu16(int swap, uint16_t value)
80327e51cbSPeter Avalos {
81327e51cbSPeter Avalos union {
82327e51cbSPeter Avalos uint16_t ui;
83327e51cbSPeter Avalos char c[2];
84327e51cbSPeter Avalos } retval, tmpval;
85327e51cbSPeter Avalos
86327e51cbSPeter Avalos if (swap) {
87327e51cbSPeter Avalos tmpval.ui = value;
88327e51cbSPeter Avalos
89327e51cbSPeter Avalos retval.c[0] = tmpval.c[1];
90327e51cbSPeter Avalos retval.c[1] = tmpval.c[0];
91327e51cbSPeter Avalos
92327e51cbSPeter Avalos return retval.ui;
93327e51cbSPeter Avalos } else
94327e51cbSPeter Avalos return value;
95327e51cbSPeter Avalos }
96327e51cbSPeter Avalos
97327e51cbSPeter Avalos private uint32_t
getu32(int swap,uint32_t value)98327e51cbSPeter Avalos getu32(int swap, uint32_t value)
99327e51cbSPeter Avalos {
100327e51cbSPeter Avalos union {
101327e51cbSPeter Avalos uint32_t ui;
102327e51cbSPeter Avalos char c[4];
103327e51cbSPeter Avalos } retval, tmpval;
104327e51cbSPeter Avalos
105327e51cbSPeter Avalos if (swap) {
106327e51cbSPeter Avalos tmpval.ui = value;
107327e51cbSPeter Avalos
108327e51cbSPeter Avalos retval.c[0] = tmpval.c[3];
109327e51cbSPeter Avalos retval.c[1] = tmpval.c[2];
110327e51cbSPeter Avalos retval.c[2] = tmpval.c[1];
111327e51cbSPeter Avalos retval.c[3] = tmpval.c[0];
112327e51cbSPeter Avalos
113327e51cbSPeter Avalos return retval.ui;
114327e51cbSPeter Avalos } else
115327e51cbSPeter Avalos return value;
116327e51cbSPeter Avalos }
117327e51cbSPeter Avalos
118327e51cbSPeter Avalos private uint64_t
getu64(int swap,uint64_t value)119327e51cbSPeter Avalos getu64(int swap, uint64_t value)
120327e51cbSPeter Avalos {
121327e51cbSPeter Avalos union {
122327e51cbSPeter Avalos uint64_t ui;
123327e51cbSPeter Avalos char c[8];
124327e51cbSPeter Avalos } retval, tmpval;
125327e51cbSPeter Avalos
126327e51cbSPeter Avalos if (swap) {
127327e51cbSPeter Avalos tmpval.ui = value;
128327e51cbSPeter Avalos
129327e51cbSPeter Avalos retval.c[0] = tmpval.c[7];
130327e51cbSPeter Avalos retval.c[1] = tmpval.c[6];
131327e51cbSPeter Avalos retval.c[2] = tmpval.c[5];
132327e51cbSPeter Avalos retval.c[3] = tmpval.c[4];
133327e51cbSPeter Avalos retval.c[4] = tmpval.c[3];
134327e51cbSPeter Avalos retval.c[5] = tmpval.c[2];
135327e51cbSPeter Avalos retval.c[6] = tmpval.c[1];
136327e51cbSPeter Avalos retval.c[7] = tmpval.c[0];
137327e51cbSPeter Avalos
138327e51cbSPeter Avalos return retval.ui;
139327e51cbSPeter Avalos } else
140327e51cbSPeter Avalos return value;
141327e51cbSPeter Avalos }
142327e51cbSPeter Avalos
14379343712SPeter Avalos #define elf_getu16(swap, value) getu16(swap, value)
14479343712SPeter Avalos #define elf_getu32(swap, value) getu32(swap, value)
145327e51cbSPeter Avalos #define elf_getu64(swap, value) getu64(swap, value)
146327e51cbSPeter Avalos
14779343712SPeter Avalos #define xsh_addr (clazz == ELFCLASS32 \
1486fca56fbSSascha Wildner ? CAST(void *, &sh32) \
1496fca56fbSSascha Wildner : CAST(void *, &sh64))
15079343712SPeter Avalos #define xsh_sizeof (clazz == ELFCLASS32 \
151e8af9738SPeter Avalos ? sizeof(sh32) \
152e8af9738SPeter Avalos : sizeof(sh64))
1536fca56fbSSascha Wildner #define xsh_size CAST(size_t, (clazz == ELFCLASS32 \
15479343712SPeter Avalos ? elf_getu32(swap, sh32.sh_size) \
1556fca56fbSSascha Wildner : elf_getu64(swap, sh64.sh_size)))
1566fca56fbSSascha Wildner #define xsh_offset CAST(off_t, (clazz == ELFCLASS32 \
15779343712SPeter Avalos ? elf_getu32(swap, sh32.sh_offset) \
1586fca56fbSSascha Wildner : elf_getu64(swap, sh64.sh_offset)))
15979343712SPeter Avalos #define xsh_type (clazz == ELFCLASS32 \
16079343712SPeter Avalos ? elf_getu32(swap, sh32.sh_type) \
16179343712SPeter Avalos : elf_getu32(swap, sh64.sh_type))
162e8af9738SPeter Avalos #define xsh_name (clazz == ELFCLASS32 \
163e8af9738SPeter Avalos ? elf_getu32(swap, sh32.sh_name) \
164e8af9738SPeter Avalos : elf_getu32(swap, sh64.sh_name))
1656fca56fbSSascha Wildner
16679343712SPeter Avalos #define xph_addr (clazz == ELFCLASS32 \
1676fca56fbSSascha Wildner ? CAST(void *, &ph32) \
1686fca56fbSSascha Wildner : CAST(void *, &ph64))
16979343712SPeter Avalos #define xph_sizeof (clazz == ELFCLASS32 \
170e8af9738SPeter Avalos ? sizeof(ph32) \
171e8af9738SPeter Avalos : sizeof(ph64))
17279343712SPeter Avalos #define xph_type (clazz == ELFCLASS32 \
17379343712SPeter Avalos ? elf_getu32(swap, ph32.p_type) \
17479343712SPeter Avalos : elf_getu32(swap, ph64.p_type))
1756fca56fbSSascha Wildner #define xph_offset CAST(off_t, (clazz == ELFCLASS32 \
17679343712SPeter Avalos ? elf_getu32(swap, ph32.p_offset) \
1776fca56fbSSascha Wildner : elf_getu64(swap, ph64.p_offset)))
1786fca56fbSSascha Wildner #define xph_align CAST(size_t, (clazz == ELFCLASS32 \
1796fca56fbSSascha Wildner ? CAST(off_t, (ph32.p_align ? \
1806fca56fbSSascha Wildner elf_getu32(swap, ph32.p_align) : 4))\
1816fca56fbSSascha Wildner : CAST(off_t, (ph64.p_align ? \
1826fca56fbSSascha Wildner elf_getu64(swap, ph64.p_align) : 4))))
1836fca56fbSSascha Wildner #define xph_vaddr CAST(size_t, (clazz == ELFCLASS32 \
1846fca56fbSSascha Wildner ? CAST(off_t, (ph32.p_vaddr ? \
1856fca56fbSSascha Wildner elf_getu32(swap, ph32.p_vaddr) : 4))\
1866fca56fbSSascha Wildner : CAST(off_t, (ph64.p_vaddr ? \
1876fca56fbSSascha Wildner elf_getu64(swap, ph64.p_vaddr) : 4))))
1886fca56fbSSascha Wildner #define xph_filesz CAST(size_t, (clazz == ELFCLASS32 \
18979343712SPeter Avalos ? elf_getu32(swap, ph32.p_filesz) \
19079343712SPeter Avalos : elf_getu64(swap, ph64.p_filesz)))
1916fca56fbSSascha Wildner #define xph_memsz CAST(size_t, ((clazz == ELFCLASS32 \
19279343712SPeter Avalos ? elf_getu32(swap, ph32.p_memsz) \
1936fca56fbSSascha Wildner : elf_getu64(swap, ph64.p_memsz))))
1946fca56fbSSascha Wildner #define xnh_addr (clazz == ELFCLASS32 \
1956fca56fbSSascha Wildner ? CAST(void *, &nh32) \
1966fca56fbSSascha Wildner : CAST(void *, &nh64))
19779343712SPeter Avalos #define xnh_sizeof (clazz == ELFCLASS32 \
198c30bd091SSascha Wildner ? sizeof(nh32) \
199c30bd091SSascha Wildner : sizeof(nh64))
20079343712SPeter Avalos #define xnh_type (clazz == ELFCLASS32 \
20179343712SPeter Avalos ? elf_getu32(swap, nh32.n_type) \
20279343712SPeter Avalos : elf_getu32(swap, nh64.n_type))
20379343712SPeter Avalos #define xnh_namesz (clazz == ELFCLASS32 \
20479343712SPeter Avalos ? elf_getu32(swap, nh32.n_namesz) \
20579343712SPeter Avalos : elf_getu32(swap, nh64.n_namesz))
20679343712SPeter Avalos #define xnh_descsz (clazz == ELFCLASS32 \
20779343712SPeter Avalos ? elf_getu32(swap, nh32.n_descsz) \
20879343712SPeter Avalos : elf_getu32(swap, nh64.n_descsz))
2096fca56fbSSascha Wildner
2106fca56fbSSascha Wildner #define xdh_addr (clazz == ELFCLASS32 \
2116fca56fbSSascha Wildner ? CAST(void *, &dh32) \
2126fca56fbSSascha Wildner : CAST(void *, &dh64))
2136fca56fbSSascha Wildner #define xdh_sizeof (clazz == ELFCLASS32 \
2146fca56fbSSascha Wildner ? sizeof(dh32) \
2156fca56fbSSascha Wildner : sizeof(dh64))
2166fca56fbSSascha Wildner #define xdh_tag (clazz == ELFCLASS32 \
2176fca56fbSSascha Wildner ? elf_getu32(swap, dh32.d_tag) \
2186fca56fbSSascha Wildner : elf_getu64(swap, dh64.d_tag))
2196fca56fbSSascha Wildner #define xdh_val (clazz == ELFCLASS32 \
2206fca56fbSSascha Wildner ? elf_getu32(swap, dh32.d_un.d_val) \
2216fca56fbSSascha Wildner : elf_getu64(swap, dh64.d_un.d_val))
2226fca56fbSSascha Wildner
22379343712SPeter Avalos #define xcap_addr (clazz == ELFCLASS32 \
2246fca56fbSSascha Wildner ? CAST(void *, &cap32) \
2256fca56fbSSascha Wildner : CAST(void *, &cap64))
22679343712SPeter Avalos #define xcap_sizeof (clazz == ELFCLASS32 \
2276fca56fbSSascha Wildner ? sizeof(cap32) \
2286fca56fbSSascha Wildner : sizeof(cap64))
22979343712SPeter Avalos #define xcap_tag (clazz == ELFCLASS32 \
23079343712SPeter Avalos ? elf_getu32(swap, cap32.c_tag) \
23179343712SPeter Avalos : elf_getu64(swap, cap64.c_tag))
23279343712SPeter Avalos #define xcap_val (clazz == ELFCLASS32 \
23379343712SPeter Avalos ? elf_getu32(swap, cap32.c_un.c_val) \
23479343712SPeter Avalos : elf_getu64(swap, cap64.c_un.c_val))
2356fca56fbSSascha Wildner
236c30bd091SSascha Wildner #define xauxv_addr (clazz == ELFCLASS32 \
2376fca56fbSSascha Wildner ? CAST(void *, &auxv32) \
2386fca56fbSSascha Wildner : CAST(void *, &auxv64))
239c30bd091SSascha Wildner #define xauxv_sizeof (clazz == ELFCLASS32 \
240c30bd091SSascha Wildner ? sizeof(auxv32) \
241c30bd091SSascha Wildner : sizeof(auxv64))
242c30bd091SSascha Wildner #define xauxv_type (clazz == ELFCLASS32 \
243c30bd091SSascha Wildner ? elf_getu32(swap, auxv32.a_type) \
244c30bd091SSascha Wildner : elf_getu64(swap, auxv64.a_type))
245c30bd091SSascha Wildner #define xauxv_val (clazz == ELFCLASS32 \
246c30bd091SSascha Wildner ? elf_getu32(swap, auxv32.a_v) \
247c30bd091SSascha Wildner : elf_getu64(swap, auxv64.a_v))
248327e51cbSPeter Avalos
2496fca56fbSSascha Wildner #define prpsoffsets(i) (clazz == ELFCLASS32 \
2506fca56fbSSascha Wildner ? prpsoffsets32[i] \
2516fca56fbSSascha Wildner : prpsoffsets64[i])
2526fca56fbSSascha Wildner
253327e51cbSPeter Avalos #ifdef ELFCORE
25479343712SPeter Avalos /*
25579343712SPeter Avalos * Try larger offsets first to avoid false matches
25679343712SPeter Avalos * from earlier data that happen to look like strings.
25779343712SPeter Avalos */
25879343712SPeter Avalos static const size_t prpsoffsets32[] = {
25979343712SPeter Avalos #ifdef USE_NT_PSINFO
26079343712SPeter Avalos 104, /* SunOS 5.x (command line) */
26179343712SPeter Avalos 88, /* SunOS 5.x (short name) */
26279343712SPeter Avalos #endif /* USE_NT_PSINFO */
26379343712SPeter Avalos
26479343712SPeter Avalos 100, /* SunOS 5.x (command line) */
26579343712SPeter Avalos 84, /* SunOS 5.x (short name) */
26679343712SPeter Avalos
26779343712SPeter Avalos 44, /* Linux (command line) */
2686fca56fbSSascha Wildner 28, /* Linux (short name) */
2696fca56fbSSascha Wildner
2706fca56fbSSascha Wildner 48, /* Linux PowerPC (command line) */
2716fca56fbSSascha Wildner 32, /* Linux PowerPC (short name) */
27279343712SPeter Avalos
27379343712SPeter Avalos 8, /* FreeBSD */
274327e51cbSPeter Avalos };
275327e51cbSPeter Avalos
27679343712SPeter Avalos static const size_t prpsoffsets64[] = {
27779343712SPeter Avalos #ifdef USE_NT_PSINFO
27879343712SPeter Avalos 152, /* SunOS 5.x (command line) */
27979343712SPeter Avalos 136, /* SunOS 5.x (short name) */
28079343712SPeter Avalos #endif /* USE_NT_PSINFO */
28179343712SPeter Avalos
28279343712SPeter Avalos 136, /* SunOS 5.x, 64-bit (command line) */
28379343712SPeter Avalos 120, /* SunOS 5.x, 64-bit (short name) */
28479343712SPeter Avalos
28579343712SPeter Avalos 56, /* Linux (command line) */
286327e51cbSPeter Avalos 40, /* Linux (tested on core from 2.4.x, short name) */
28779343712SPeter Avalos
28879343712SPeter Avalos 16, /* FreeBSD, 64-bit */
289327e51cbSPeter Avalos };
290327e51cbSPeter Avalos
2916fca56fbSSascha Wildner #define NOFFSETS32 __arraycount(prpsoffsets32)
2926fca56fbSSascha Wildner #define NOFFSETS64 __arraycount(prpsoffsets64)
293327e51cbSPeter Avalos
29479343712SPeter Avalos #define NOFFSETS (clazz == ELFCLASS32 ? NOFFSETS32 : NOFFSETS64)
295327e51cbSPeter Avalos
296327e51cbSPeter Avalos /*
297327e51cbSPeter Avalos * Look through the program headers of an executable image, searching
298327e51cbSPeter Avalos * for a PT_NOTE section of type NT_PRPSINFO, with a name "CORE" or
299327e51cbSPeter Avalos * "FreeBSD"; if one is found, try looking in various places in its
300327e51cbSPeter Avalos * contents for a 16-character string containing only printable
301327e51cbSPeter Avalos * characters - if found, that string should be the name of the program
302327e51cbSPeter Avalos * that dropped core. Note: right after that 16-character string is,
303327e51cbSPeter Avalos * at least in SunOS 5.x (and possibly other SVR4-flavored systems) and
304327e51cbSPeter Avalos * Linux, a longer string (80 characters, in 5.x, probably other
305327e51cbSPeter Avalos * SVR4-flavored systems, and Linux) containing the start of the
306327e51cbSPeter Avalos * command line for that program.
307327e51cbSPeter Avalos *
30879343712SPeter Avalos * SunOS 5.x core files contain two PT_NOTE sections, with the types
30979343712SPeter Avalos * NT_PRPSINFO (old) and NT_PSINFO (new). These structs contain the
31079343712SPeter Avalos * same info about the command name and command line, so it probably
31179343712SPeter Avalos * isn't worthwhile to look for NT_PSINFO, but the offsets are provided
31279343712SPeter Avalos * above (see USE_NT_PSINFO), in case we ever decide to do so. The
31379343712SPeter Avalos * NT_PRPSINFO and NT_PSINFO sections are always in order and adjacent;
31479343712SPeter Avalos * the SunOS 5.x file command relies on this (and prefers the latter).
31579343712SPeter Avalos *
316327e51cbSPeter Avalos * The signal number probably appears in a section of type NT_PRSTATUS,
317327e51cbSPeter Avalos * but that's also rather OS-dependent, in ways that are harder to
318327e51cbSPeter Avalos * dissect with heuristics, so I'm not bothering with the signal number.
319327e51cbSPeter Avalos * (I suppose the signal number could be of interest in situations where
320327e51cbSPeter Avalos * you don't have the binary of the program that dropped core; if you
321327e51cbSPeter Avalos * *do* have that binary, the debugger will probably tell you what
322327e51cbSPeter Avalos * signal it was.)
323327e51cbSPeter Avalos */
324327e51cbSPeter Avalos
325327e51cbSPeter Avalos #define OS_STYLE_SVR4 0
326327e51cbSPeter Avalos #define OS_STYLE_FREEBSD 1
327327e51cbSPeter Avalos #define OS_STYLE_NETBSD 2
328327e51cbSPeter Avalos
32979343712SPeter Avalos private const char os_style_names[][8] = {
330327e51cbSPeter Avalos "SVR4",
331327e51cbSPeter Avalos "FreeBSD",
332327e51cbSPeter Avalos "NetBSD",
333327e51cbSPeter Avalos };
334327e51cbSPeter Avalos
3356fca56fbSSascha Wildner #define FLAGS_CORE_STYLE 0x0003
336c30bd091SSascha Wildner
3376fca56fbSSascha Wildner #define FLAGS_DID_CORE 0x0004
3386fca56fbSSascha Wildner #define FLAGS_DID_OS_NOTE 0x0008
3396fca56fbSSascha Wildner #define FLAGS_DID_BUILD_ID 0x0010
3406fca56fbSSascha Wildner #define FLAGS_DID_CORE_STYLE 0x0020
3416fca56fbSSascha Wildner #define FLAGS_DID_NETBSD_PAX 0x0040
3426fca56fbSSascha Wildner #define FLAGS_DID_NETBSD_MARCH 0x0080
3436fca56fbSSascha Wildner #define FLAGS_DID_NETBSD_CMODEL 0x0100
3446fca56fbSSascha Wildner #define FLAGS_DID_NETBSD_EMULATION 0x0200
3456fca56fbSSascha Wildner #define FLAGS_DID_NETBSD_UNKNOWN 0x0400
3466fca56fbSSascha Wildner #define FLAGS_IS_CORE 0x0800
3476fca56fbSSascha Wildner #define FLAGS_DID_AUXV 0x1000
348327e51cbSPeter Avalos
349327e51cbSPeter Avalos private int
dophn_core(struct magic_set * ms,int clazz,int swap,int fd,off_t off,int num,size_t size,off_t fsize,int * flags,uint16_t * notecount)35079343712SPeter Avalos dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
35182c5fa3eSPeter Avalos int num, size_t size, off_t fsize, int *flags, uint16_t *notecount)
352327e51cbSPeter Avalos {
353327e51cbSPeter Avalos Elf32_Phdr ph32;
354327e51cbSPeter Avalos Elf64_Phdr ph64;
355e8af9738SPeter Avalos size_t offset, len;
356327e51cbSPeter Avalos unsigned char nbuf[BUFSIZ];
357327e51cbSPeter Avalos ssize_t bufsize;
358970935fdSSascha Wildner off_t ph_off = off, offs;
359c30bd091SSascha Wildner int ph_num = num;
360327e51cbSPeter Avalos
361c990e5baSDaniel Fojt if (ms->flags & MAGIC_MIME)
362c990e5baSDaniel Fojt return 0;
363c990e5baSDaniel Fojt
3646fca56fbSSascha Wildner if (num == 0) {
3656fca56fbSSascha Wildner if (file_printf(ms, ", no program header") == -1)
3666fca56fbSSascha Wildner return -1;
3676fca56fbSSascha Wildner return 0;
3686fca56fbSSascha Wildner }
369327e51cbSPeter Avalos if (size != xph_sizeof) {
370327e51cbSPeter Avalos if (file_printf(ms, ", corrupted program header size") == -1)
371327e51cbSPeter Avalos return -1;
372327e51cbSPeter Avalos return 0;
373327e51cbSPeter Avalos }
374327e51cbSPeter Avalos
375327e51cbSPeter Avalos /*
376327e51cbSPeter Avalos * Loop through all the program headers.
377327e51cbSPeter Avalos */
378327e51cbSPeter Avalos for ( ; num; num--) {
3796fca56fbSSascha Wildner if (pread(fd, xph_addr, xph_sizeof, off) <
3806fca56fbSSascha Wildner CAST(ssize_t, xph_sizeof)) {
381970935fdSSascha Wildner if (file_printf(ms,
382970935fdSSascha Wildner ", can't read elf program headers at %jd",
383970935fdSSascha Wildner (intmax_t)off) == -1)
384327e51cbSPeter Avalos return -1;
385970935fdSSascha Wildner return 0;
386327e51cbSPeter Avalos }
387a96e001bSPeter Avalos off += size;
388a96e001bSPeter Avalos
38982c5fa3eSPeter Avalos if (fsize != SIZE_UNKNOWN && xph_offset > fsize) {
390a96e001bSPeter Avalos /* Perhaps warn here */
391327e51cbSPeter Avalos continue;
392327e51cbSPeter Avalos }
393327e51cbSPeter Avalos
394327e51cbSPeter Avalos if (xph_type != PT_NOTE)
395327e51cbSPeter Avalos continue;
396327e51cbSPeter Avalos
397327e51cbSPeter Avalos /*
398327e51cbSPeter Avalos * This is a PT_NOTE section; loop through all the notes
399327e51cbSPeter Avalos * in the section.
400327e51cbSPeter Avalos */
401e8af9738SPeter Avalos len = xph_filesz < sizeof(nbuf) ? xph_filesz : sizeof(nbuf);
402970935fdSSascha Wildner offs = xph_offset;
403970935fdSSascha Wildner if ((bufsize = pread(fd, nbuf, len, offs)) == -1) {
404970935fdSSascha Wildner if (file_printf(ms, " can't read note section at %jd",
405970935fdSSascha Wildner (intmax_t)offs) == -1)
406327e51cbSPeter Avalos return -1;
407970935fdSSascha Wildner return 0;
408327e51cbSPeter Avalos }
409327e51cbSPeter Avalos offset = 0;
410327e51cbSPeter Avalos for (;;) {
4116fca56fbSSascha Wildner if (offset >= CAST(size_t, bufsize))
412327e51cbSPeter Avalos break;
4136fca56fbSSascha Wildner offset = donote(ms, nbuf, offset, CAST(size_t, bufsize),
414c30bd091SSascha Wildner clazz, swap, 4, flags, notecount, fd, ph_off,
415c30bd091SSascha Wildner ph_num, fsize);
416327e51cbSPeter Avalos if (offset == 0)
417327e51cbSPeter Avalos break;
418327e51cbSPeter Avalos
419327e51cbSPeter Avalos }
420327e51cbSPeter Avalos }
421327e51cbSPeter Avalos return 0;
422327e51cbSPeter Avalos }
423327e51cbSPeter Avalos #endif
424327e51cbSPeter Avalos
4256fca56fbSSascha Wildner static int
do_note_netbsd_version(struct magic_set * ms,int swap,void * v)426e8af9738SPeter Avalos do_note_netbsd_version(struct magic_set *ms, int swap, void *v)
427e8af9738SPeter Avalos {
428e8af9738SPeter Avalos uint32_t desc;
4296fca56fbSSascha Wildner memcpy(&desc, v, sizeof(desc));
430e8af9738SPeter Avalos desc = elf_getu32(swap, desc);
431e8af9738SPeter Avalos
432e8af9738SPeter Avalos if (file_printf(ms, ", for NetBSD") == -1)
4336fca56fbSSascha Wildner return -1;
434e8af9738SPeter Avalos /*
435e8af9738SPeter Avalos * The version number used to be stuck as 199905, and was thus
436e8af9738SPeter Avalos * basically content-free. Newer versions of NetBSD have fixed
437e8af9738SPeter Avalos * this and now use the encoding of __NetBSD_Version__:
438e8af9738SPeter Avalos *
439e8af9738SPeter Avalos * MMmmrrpp00
440e8af9738SPeter Avalos *
441e8af9738SPeter Avalos * M = major version
442e8af9738SPeter Avalos * m = minor version
443e8af9738SPeter Avalos * r = release ["",A-Z,Z[A-Z] but numeric]
444e8af9738SPeter Avalos * p = patchlevel
445e8af9738SPeter Avalos */
446e8af9738SPeter Avalos if (desc > 100000000U) {
447e8af9738SPeter Avalos uint32_t ver_patch = (desc / 100) % 100;
448e8af9738SPeter Avalos uint32_t ver_rel = (desc / 10000) % 100;
449e8af9738SPeter Avalos uint32_t ver_min = (desc / 1000000) % 100;
450e8af9738SPeter Avalos uint32_t ver_maj = desc / 100000000;
451e8af9738SPeter Avalos
452e8af9738SPeter Avalos if (file_printf(ms, " %u.%u", ver_maj, ver_min) == -1)
4536fca56fbSSascha Wildner return -1;
454e8af9738SPeter Avalos if (ver_rel == 0 && ver_patch != 0) {
455e8af9738SPeter Avalos if (file_printf(ms, ".%u", ver_patch) == -1)
4566fca56fbSSascha Wildner return -1;
457e8af9738SPeter Avalos } else if (ver_rel != 0) {
458e8af9738SPeter Avalos while (ver_rel > 26) {
459e8af9738SPeter Avalos if (file_printf(ms, "Z") == -1)
4606fca56fbSSascha Wildner return -1;
461e8af9738SPeter Avalos ver_rel -= 26;
462e8af9738SPeter Avalos }
463e8af9738SPeter Avalos if (file_printf(ms, "%c", 'A' + ver_rel - 1)
464e8af9738SPeter Avalos == -1)
4656fca56fbSSascha Wildner return -1;
466e8af9738SPeter Avalos }
467e8af9738SPeter Avalos }
4686fca56fbSSascha Wildner return 0;
469e8af9738SPeter Avalos }
470e8af9738SPeter Avalos
4716fca56fbSSascha Wildner static int
do_note_freebsd_version(struct magic_set * ms,int swap,void * v)472e8af9738SPeter Avalos do_note_freebsd_version(struct magic_set *ms, int swap, void *v)
473e8af9738SPeter Avalos {
474e8af9738SPeter Avalos uint32_t desc;
475e8af9738SPeter Avalos
4766fca56fbSSascha Wildner memcpy(&desc, v, sizeof(desc));
477e8af9738SPeter Avalos desc = elf_getu32(swap, desc);
478e8af9738SPeter Avalos if (file_printf(ms, ", for FreeBSD") == -1)
4796fca56fbSSascha Wildner return -1;
480e8af9738SPeter Avalos
481e8af9738SPeter Avalos /*
482e8af9738SPeter Avalos * Contents is __FreeBSD_version, whose relation to OS
483e8af9738SPeter Avalos * versions is defined by a huge table in the Porter's
484e8af9738SPeter Avalos * Handbook. This is the general scheme:
485e8af9738SPeter Avalos *
486e8af9738SPeter Avalos * Releases:
487e8af9738SPeter Avalos * Mmp000 (before 4.10)
488e8af9738SPeter Avalos * Mmi0p0 (before 5.0)
489e8af9738SPeter Avalos * Mmm0p0
490e8af9738SPeter Avalos *
491e8af9738SPeter Avalos * Development branches:
492e8af9738SPeter Avalos * Mmpxxx (before 4.6)
493e8af9738SPeter Avalos * Mmp1xx (before 4.10)
494e8af9738SPeter Avalos * Mmi1xx (before 5.0)
495e8af9738SPeter Avalos * M000xx (pre-M.0)
496e8af9738SPeter Avalos * Mmm1xx
497e8af9738SPeter Avalos *
498e8af9738SPeter Avalos * M = major version
499e8af9738SPeter Avalos * m = minor version
500e8af9738SPeter Avalos * i = minor version increment (491000 -> 4.10)
501e8af9738SPeter Avalos * p = patchlevel
502e8af9738SPeter Avalos * x = revision
503e8af9738SPeter Avalos *
504e8af9738SPeter Avalos * The first release of FreeBSD to use ELF by default
505e8af9738SPeter Avalos * was version 3.0.
506e8af9738SPeter Avalos */
507e8af9738SPeter Avalos if (desc == 460002) {
508e8af9738SPeter Avalos if (file_printf(ms, " 4.6.2") == -1)
5096fca56fbSSascha Wildner return -1;
510e8af9738SPeter Avalos } else if (desc < 460100) {
511e8af9738SPeter Avalos if (file_printf(ms, " %d.%d", desc / 100000,
512e8af9738SPeter Avalos desc / 10000 % 10) == -1)
5136fca56fbSSascha Wildner return -1;
514e8af9738SPeter Avalos if (desc / 1000 % 10 > 0)
515e8af9738SPeter Avalos if (file_printf(ms, ".%d", desc / 1000 % 10) == -1)
5166fca56fbSSascha Wildner return -1;
517e8af9738SPeter Avalos if ((desc % 1000 > 0) || (desc % 100000 == 0))
518e8af9738SPeter Avalos if (file_printf(ms, " (%d)", desc) == -1)
5196fca56fbSSascha Wildner return -1;
520e8af9738SPeter Avalos } else if (desc < 500000) {
521e8af9738SPeter Avalos if (file_printf(ms, " %d.%d", desc / 100000,
522e8af9738SPeter Avalos desc / 10000 % 10 + desc / 1000 % 10) == -1)
5236fca56fbSSascha Wildner return -1;
524e8af9738SPeter Avalos if (desc / 100 % 10 > 0) {
525e8af9738SPeter Avalos if (file_printf(ms, " (%d)", desc) == -1)
5266fca56fbSSascha Wildner return -1;
527e8af9738SPeter Avalos } else if (desc / 10 % 10 > 0) {
528e8af9738SPeter Avalos if (file_printf(ms, ".%d", desc / 10 % 10) == -1)
5296fca56fbSSascha Wildner return -1;
530e8af9738SPeter Avalos }
531e8af9738SPeter Avalos } else {
532e8af9738SPeter Avalos if (file_printf(ms, " %d.%d", desc / 100000,
533e8af9738SPeter Avalos desc / 1000 % 100) == -1)
5346fca56fbSSascha Wildner return -1;
535e8af9738SPeter Avalos if ((desc / 100 % 10 > 0) ||
536e8af9738SPeter Avalos (desc % 100000 / 100 == 0)) {
537e8af9738SPeter Avalos if (file_printf(ms, " (%d)", desc) == -1)
5386fca56fbSSascha Wildner return -1;
539e8af9738SPeter Avalos } else if (desc / 10 % 10 > 0) {
540e8af9738SPeter Avalos if (file_printf(ms, ".%d", desc / 10 % 10) == -1)
5416fca56fbSSascha Wildner return -1;
542e8af9738SPeter Avalos }
543e8af9738SPeter Avalos }
5446fca56fbSSascha Wildner return 0;
545e8af9738SPeter Avalos }
546e8af9738SPeter Avalos
54782c5fa3eSPeter Avalos private int
548c30bd091SSascha Wildner /*ARGSUSED*/
do_bid_note(struct magic_set * ms,unsigned char * nbuf,uint32_t type,int swap,uint32_t namesz,uint32_t descsz,size_t noff,size_t doff,int * flags)54982c5fa3eSPeter Avalos do_bid_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
55082c5fa3eSPeter Avalos int swap __attribute__((__unused__)), uint32_t namesz, uint32_t descsz,
55182c5fa3eSPeter Avalos size_t noff, size_t doff, int *flags)
552327e51cbSPeter Avalos {
5536fca56fbSSascha Wildner if (namesz == 4 && strcmp(RCAST(char *, &nbuf[noff]), "GNU") == 0 &&
554c30bd091SSascha Wildner type == NT_GNU_BUILD_ID && (descsz >= 4 && descsz <= 20)) {
555e8af9738SPeter Avalos uint8_t desc[20];
556c30bd091SSascha Wildner const char *btype;
557e8af9738SPeter Avalos uint32_t i;
55882c5fa3eSPeter Avalos *flags |= FLAGS_DID_BUILD_ID;
559c30bd091SSascha Wildner switch (descsz) {
560c30bd091SSascha Wildner case 8:
561c30bd091SSascha Wildner btype = "xxHash";
562c30bd091SSascha Wildner break;
563c30bd091SSascha Wildner case 16:
564c30bd091SSascha Wildner btype = "md5/uuid";
565c30bd091SSascha Wildner break;
566c30bd091SSascha Wildner case 20:
567c30bd091SSascha Wildner btype = "sha1";
568c30bd091SSascha Wildner break;
569c30bd091SSascha Wildner default:
570c30bd091SSascha Wildner btype = "unknown";
571c30bd091SSascha Wildner break;
572c30bd091SSascha Wildner }
573c30bd091SSascha Wildner if (file_printf(ms, ", BuildID[%s]=", btype) == -1)
5746fca56fbSSascha Wildner return -1;
5756fca56fbSSascha Wildner memcpy(desc, &nbuf[doff], descsz);
576e8af9738SPeter Avalos for (i = 0; i < descsz; i++)
577e8af9738SPeter Avalos if (file_printf(ms, "%02x", desc[i]) == -1)
5786fca56fbSSascha Wildner return -1;
57982c5fa3eSPeter Avalos return 1;
5806fca56fbSSascha Wildner }
5816fca56fbSSascha Wildner if (namesz == 4 && strcmp(RCAST(char *, &nbuf[noff]), "Go") == 0 &&
5826fca56fbSSascha Wildner type == NT_GO_BUILD_ID && descsz < 128) {
583c990e5baSDaniel Fojt char buf[256];
584c990e5baSDaniel Fojt if (file_printf(ms, ", Go BuildID=%s",
585c990e5baSDaniel Fojt file_copystr(buf, sizeof(buf), descsz,
586c990e5baSDaniel Fojt RCAST(const char *, &nbuf[doff]))) == -1)
5876fca56fbSSascha Wildner return -1;
58882c5fa3eSPeter Avalos return 1;
58982c5fa3eSPeter Avalos }
59082c5fa3eSPeter Avalos return 0;
591a96e001bSPeter Avalos }
592a96e001bSPeter Avalos
59382c5fa3eSPeter Avalos private int
do_os_note(struct magic_set * ms,unsigned char * nbuf,uint32_t type,int swap,uint32_t namesz,uint32_t descsz,size_t noff,size_t doff,int * flags)59482c5fa3eSPeter Avalos do_os_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
59582c5fa3eSPeter Avalos int swap, uint32_t namesz, uint32_t descsz,
59682c5fa3eSPeter Avalos size_t noff, size_t doff, int *flags)
59782c5fa3eSPeter Avalos {
5986fca56fbSSascha Wildner const char *name = RCAST(const char *, &nbuf[noff]);
5996fca56fbSSascha Wildner
6006fca56fbSSascha Wildner if (namesz == 5 && strcmp(name, "SuSE") == 0 &&
60182c5fa3eSPeter Avalos type == NT_GNU_VERSION && descsz == 2) {
60282c5fa3eSPeter Avalos *flags |= FLAGS_DID_OS_NOTE;
6036fca56fbSSascha Wildner if (file_printf(ms, ", for SuSE %d.%d", nbuf[doff],
6046fca56fbSSascha Wildner nbuf[doff + 1]) == -1)
6056fca56fbSSascha Wildner return -1;
60682c5fa3eSPeter Avalos return 1;
60782c5fa3eSPeter Avalos }
60882c5fa3eSPeter Avalos
6096fca56fbSSascha Wildner if (namesz == 4 && strcmp(name, "GNU") == 0 &&
61082c5fa3eSPeter Avalos type == NT_GNU_VERSION && descsz == 16) {
61182c5fa3eSPeter Avalos uint32_t desc[4];
6126fca56fbSSascha Wildner memcpy(desc, &nbuf[doff], sizeof(desc));
61382c5fa3eSPeter Avalos
61482c5fa3eSPeter Avalos *flags |= FLAGS_DID_OS_NOTE;
61582c5fa3eSPeter Avalos if (file_printf(ms, ", for GNU/") == -1)
6166fca56fbSSascha Wildner return -1;
61782c5fa3eSPeter Avalos switch (elf_getu32(swap, desc[0])) {
61882c5fa3eSPeter Avalos case GNU_OS_LINUX:
61982c5fa3eSPeter Avalos if (file_printf(ms, "Linux") == -1)
6206fca56fbSSascha Wildner return -1;
62182c5fa3eSPeter Avalos break;
62282c5fa3eSPeter Avalos case GNU_OS_HURD:
62382c5fa3eSPeter Avalos if (file_printf(ms, "Hurd") == -1)
6246fca56fbSSascha Wildner return -1;
62582c5fa3eSPeter Avalos break;
62682c5fa3eSPeter Avalos case GNU_OS_SOLARIS:
62782c5fa3eSPeter Avalos if (file_printf(ms, "Solaris") == -1)
6286fca56fbSSascha Wildner return -1;
62982c5fa3eSPeter Avalos break;
63082c5fa3eSPeter Avalos case GNU_OS_KFREEBSD:
63182c5fa3eSPeter Avalos if (file_printf(ms, "kFreeBSD") == -1)
6326fca56fbSSascha Wildner return -1;
63382c5fa3eSPeter Avalos break;
63482c5fa3eSPeter Avalos case GNU_OS_KNETBSD:
63582c5fa3eSPeter Avalos if (file_printf(ms, "kNetBSD") == -1)
6366fca56fbSSascha Wildner return -1;
63782c5fa3eSPeter Avalos break;
63882c5fa3eSPeter Avalos default:
63982c5fa3eSPeter Avalos if (file_printf(ms, "<unknown>") == -1)
6406fca56fbSSascha Wildner return -1;
64182c5fa3eSPeter Avalos }
64282c5fa3eSPeter Avalos if (file_printf(ms, " %d.%d.%d", elf_getu32(swap, desc[1]),
64382c5fa3eSPeter Avalos elf_getu32(swap, desc[2]), elf_getu32(swap, desc[3])) == -1)
6446fca56fbSSascha Wildner return -1;
64582c5fa3eSPeter Avalos return 1;
64682c5fa3eSPeter Avalos }
64782c5fa3eSPeter Avalos
6486fca56fbSSascha Wildner if (namesz == 7 && strcmp(name, "NetBSD") == 0) {
64982c5fa3eSPeter Avalos if (type == NT_NETBSD_VERSION && descsz == 4) {
65082c5fa3eSPeter Avalos *flags |= FLAGS_DID_OS_NOTE;
6516fca56fbSSascha Wildner if (do_note_netbsd_version(ms, swap, &nbuf[doff]) == -1)
6526fca56fbSSascha Wildner return -1;
65382c5fa3eSPeter Avalos return 1;
65482c5fa3eSPeter Avalos }
65582c5fa3eSPeter Avalos }
65682c5fa3eSPeter Avalos
6576fca56fbSSascha Wildner if (namesz == 8 && strcmp(name, "FreeBSD") == 0) {
65882c5fa3eSPeter Avalos if (type == NT_FREEBSD_VERSION && descsz == 4) {
65982c5fa3eSPeter Avalos *flags |= FLAGS_DID_OS_NOTE;
6606fca56fbSSascha Wildner if (do_note_freebsd_version(ms, swap, &nbuf[doff])
6616fca56fbSSascha Wildner == -1)
6626fca56fbSSascha Wildner return -1;
66382c5fa3eSPeter Avalos return 1;
66482c5fa3eSPeter Avalos }
66582c5fa3eSPeter Avalos }
66682c5fa3eSPeter Avalos
6676fca56fbSSascha Wildner if (namesz == 8 && strcmp(name, "OpenBSD") == 0 &&
66882c5fa3eSPeter Avalos type == NT_OPENBSD_VERSION && descsz == 4) {
66982c5fa3eSPeter Avalos *flags |= FLAGS_DID_OS_NOTE;
67082c5fa3eSPeter Avalos if (file_printf(ms, ", for OpenBSD") == -1)
6716fca56fbSSascha Wildner return -1;
67282c5fa3eSPeter Avalos /* Content of note is always 0 */
67382c5fa3eSPeter Avalos return 1;
67482c5fa3eSPeter Avalos }
67582c5fa3eSPeter Avalos
6766fca56fbSSascha Wildner if (namesz == 10 && strcmp(name, "DragonFly") == 0 &&
67782c5fa3eSPeter Avalos type == NT_DRAGONFLY_VERSION && descsz == 4) {
67882c5fa3eSPeter Avalos uint32_t desc;
67982c5fa3eSPeter Avalos *flags |= FLAGS_DID_OS_NOTE;
68082c5fa3eSPeter Avalos if (file_printf(ms, ", for DragonFly") == -1)
6816fca56fbSSascha Wildner return -1;
6826fca56fbSSascha Wildner memcpy(&desc, &nbuf[doff], sizeof(desc));
68382c5fa3eSPeter Avalos desc = elf_getu32(swap, desc);
68482c5fa3eSPeter Avalos if (file_printf(ms, " %d.%d.%d", desc / 100000,
68582c5fa3eSPeter Avalos desc / 10000 % 10, desc % 10000) == -1)
6866fca56fbSSascha Wildner return -1;
68782c5fa3eSPeter Avalos return 1;
68882c5fa3eSPeter Avalos }
68982c5fa3eSPeter Avalos return 0;
69082c5fa3eSPeter Avalos }
69182c5fa3eSPeter Avalos
69282c5fa3eSPeter Avalos private int
do_pax_note(struct magic_set * ms,unsigned char * nbuf,uint32_t type,int swap,uint32_t namesz,uint32_t descsz,size_t noff,size_t doff,int * flags)69382c5fa3eSPeter Avalos do_pax_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
69482c5fa3eSPeter Avalos int swap, uint32_t namesz, uint32_t descsz,
69582c5fa3eSPeter Avalos size_t noff, size_t doff, int *flags)
69682c5fa3eSPeter Avalos {
6976fca56fbSSascha Wildner const char *name = RCAST(const char *, &nbuf[noff]);
6986fca56fbSSascha Wildner
6996fca56fbSSascha Wildner if (namesz == 4 && strcmp(name, "PaX") == 0 &&
70082c5fa3eSPeter Avalos type == NT_NETBSD_PAX && descsz == 4) {
701e8af9738SPeter Avalos static const char *pax[] = {
702e8af9738SPeter Avalos "+mprotect",
703e8af9738SPeter Avalos "-mprotect",
704e8af9738SPeter Avalos "+segvguard",
705e8af9738SPeter Avalos "-segvguard",
706e8af9738SPeter Avalos "+ASLR",
707e8af9738SPeter Avalos "-ASLR",
708e8af9738SPeter Avalos };
709327e51cbSPeter Avalos uint32_t desc;
710e8af9738SPeter Avalos size_t i;
711e8af9738SPeter Avalos int did = 0;
712e8af9738SPeter Avalos
71382c5fa3eSPeter Avalos *flags |= FLAGS_DID_NETBSD_PAX;
7146fca56fbSSascha Wildner memcpy(&desc, &nbuf[doff], sizeof(desc));
71579343712SPeter Avalos desc = elf_getu32(swap, desc);
716327e51cbSPeter Avalos
717e8af9738SPeter Avalos if (desc && file_printf(ms, ", PaX: ") == -1)
7186fca56fbSSascha Wildner return -1;
719327e51cbSPeter Avalos
720e8af9738SPeter Avalos for (i = 0; i < __arraycount(pax); i++) {
7216fca56fbSSascha Wildner if (((1 << CAST(int, i)) & desc) == 0)
722e8af9738SPeter Avalos continue;
723e8af9738SPeter Avalos if (file_printf(ms, "%s%s", did++ ? "," : "",
724e8af9738SPeter Avalos pax[i]) == -1)
7256fca56fbSSascha Wildner return -1;
726327e51cbSPeter Avalos }
72782c5fa3eSPeter Avalos return 1;
72882c5fa3eSPeter Avalos }
72982c5fa3eSPeter Avalos return 0;
730327e51cbSPeter Avalos }
731e8af9738SPeter Avalos
73282c5fa3eSPeter Avalos private int
do_core_note(struct magic_set * ms,unsigned char * nbuf,uint32_t type,int swap,uint32_t namesz,uint32_t descsz,size_t noff,size_t doff,int * flags,size_t size,int clazz)73382c5fa3eSPeter Avalos do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
73482c5fa3eSPeter Avalos int swap, uint32_t namesz, uint32_t descsz,
73582c5fa3eSPeter Avalos size_t noff, size_t doff, int *flags, size_t size, int clazz)
73682c5fa3eSPeter Avalos {
73782c5fa3eSPeter Avalos #ifdef ELFCORE
738c990e5baSDaniel Fojt char buf[256];
7396fca56fbSSascha Wildner const char *name = RCAST(const char *, &nbuf[noff]);
7406fca56fbSSascha Wildner
74182c5fa3eSPeter Avalos int os_style = -1;
742327e51cbSPeter Avalos /*
743327e51cbSPeter Avalos * Sigh. The 2.0.36 kernel in Debian 2.1, at
744327e51cbSPeter Avalos * least, doesn't correctly implement name
745327e51cbSPeter Avalos * sections, in core dumps, as specified by
746327e51cbSPeter Avalos * the "Program Linking" section of "UNIX(R) System
747327e51cbSPeter Avalos * V Release 4 Programmer's Guide: ANSI C and
748327e51cbSPeter Avalos * Programming Support Tools", because my copy
749327e51cbSPeter Avalos * clearly says "The first 'namesz' bytes in 'name'
750327e51cbSPeter Avalos * contain a *null-terminated* [emphasis mine]
751327e51cbSPeter Avalos * character representation of the entry's owner
752327e51cbSPeter Avalos * or originator", but the 2.0.36 kernel code
753327e51cbSPeter Avalos * doesn't include the terminating null in the
754327e51cbSPeter Avalos * name....
755327e51cbSPeter Avalos */
7566fca56fbSSascha Wildner if ((namesz == 4 && strncmp(name, "CORE", 4) == 0) ||
7576fca56fbSSascha Wildner (namesz == 5 && strcmp(name, "CORE") == 0)) {
758327e51cbSPeter Avalos os_style = OS_STYLE_SVR4;
759327e51cbSPeter Avalos }
760327e51cbSPeter Avalos
7616fca56fbSSascha Wildner if ((namesz == 8 && strcmp(name, "FreeBSD") == 0)) {
762327e51cbSPeter Avalos os_style = OS_STYLE_FREEBSD;
763327e51cbSPeter Avalos }
764327e51cbSPeter Avalos
7656fca56fbSSascha Wildner if ((namesz >= 11 && strncmp(name, "NetBSD-CORE", 11)
766327e51cbSPeter Avalos == 0)) {
767327e51cbSPeter Avalos os_style = OS_STYLE_NETBSD;
768327e51cbSPeter Avalos }
769327e51cbSPeter Avalos
770327e51cbSPeter Avalos if (os_style != -1 && (*flags & FLAGS_DID_CORE_STYLE) == 0) {
771327e51cbSPeter Avalos if (file_printf(ms, ", %s-style", os_style_names[os_style])
772327e51cbSPeter Avalos == -1)
7736fca56fbSSascha Wildner return -1;
774327e51cbSPeter Avalos *flags |= FLAGS_DID_CORE_STYLE;
775c30bd091SSascha Wildner *flags |= os_style;
776327e51cbSPeter Avalos }
777327e51cbSPeter Avalos
778327e51cbSPeter Avalos switch (os_style) {
779327e51cbSPeter Avalos case OS_STYLE_NETBSD:
78082c5fa3eSPeter Avalos if (type == NT_NETBSD_CORE_PROCINFO) {
78182c5fa3eSPeter Avalos char sbuf[512];
782c30bd091SSascha Wildner struct NetBSD_elfcore_procinfo pi;
783c30bd091SSascha Wildner memset(&pi, 0, sizeof(pi));
7846fca56fbSSascha Wildner memcpy(&pi, nbuf + doff, MIN(descsz, sizeof(pi)));
785c30bd091SSascha Wildner
786c30bd091SSascha Wildner if (file_printf(ms, ", from '%.31s', pid=%u, uid=%u, "
787c30bd091SSascha Wildner "gid=%u, nlwps=%u, lwp=%u (signal %u/code %u)",
788614728caSSascha Wildner file_printable(ms, sbuf, sizeof(sbuf),
7896fca56fbSSascha Wildner RCAST(char *, pi.cpi_name), sizeof(pi.cpi_name)),
7906fca56fbSSascha Wildner elf_getu32(swap, CAST(uint32_t, pi.cpi_pid)),
791c30bd091SSascha Wildner elf_getu32(swap, pi.cpi_euid),
792c30bd091SSascha Wildner elf_getu32(swap, pi.cpi_egid),
793c30bd091SSascha Wildner elf_getu32(swap, pi.cpi_nlwps),
7946fca56fbSSascha Wildner elf_getu32(swap, CAST(uint32_t, pi.cpi_siglwp)),
795c30bd091SSascha Wildner elf_getu32(swap, pi.cpi_signo),
796c30bd091SSascha Wildner elf_getu32(swap, pi.cpi_sigcode)) == -1)
7976fca56fbSSascha Wildner return -1;
798327e51cbSPeter Avalos
799327e51cbSPeter Avalos *flags |= FLAGS_DID_CORE;
80082c5fa3eSPeter Avalos return 1;
801327e51cbSPeter Avalos }
802327e51cbSPeter Avalos break;
803327e51cbSPeter Avalos
8046fca56fbSSascha Wildner case OS_STYLE_FREEBSD:
8056fca56fbSSascha Wildner if (type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) {
8066fca56fbSSascha Wildner size_t argoff, pidoff;
8076fca56fbSSascha Wildner
8086fca56fbSSascha Wildner if (clazz == ELFCLASS32)
8096fca56fbSSascha Wildner argoff = 4 + 4 + 17;
8106fca56fbSSascha Wildner else
8116fca56fbSSascha Wildner argoff = 4 + 4 + 8 + 17;
8126fca56fbSSascha Wildner if (file_printf(ms, ", from '%.80s'", nbuf + doff +
8136fca56fbSSascha Wildner argoff) == -1)
8146fca56fbSSascha Wildner return -1;
8156fca56fbSSascha Wildner pidoff = argoff + 81 + 2;
8166fca56fbSSascha Wildner if (doff + pidoff + 4 <= size) {
8176fca56fbSSascha Wildner if (file_printf(ms, ", pid=%u",
8186fca56fbSSascha Wildner elf_getu32(swap, *RCAST(uint32_t *, (nbuf +
8196fca56fbSSascha Wildner doff + pidoff)))) == -1)
8206fca56fbSSascha Wildner return -1;
8216fca56fbSSascha Wildner }
8226fca56fbSSascha Wildner *flags |= FLAGS_DID_CORE;
8236fca56fbSSascha Wildner }
8246fca56fbSSascha Wildner break;
8256fca56fbSSascha Wildner
826327e51cbSPeter Avalos default:
82782c5fa3eSPeter Avalos if (type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) {
828327e51cbSPeter Avalos size_t i, j;
829327e51cbSPeter Avalos unsigned char c;
830327e51cbSPeter Avalos /*
831327e51cbSPeter Avalos * Extract the program name. We assume
832327e51cbSPeter Avalos * it to be 16 characters (that's what it
833327e51cbSPeter Avalos * is in SunOS 5.x and Linux).
834327e51cbSPeter Avalos *
835327e51cbSPeter Avalos * Unfortunately, it's at a different offset
836327e51cbSPeter Avalos * in various OSes, so try multiple offsets.
837327e51cbSPeter Avalos * If the characters aren't all printable,
838327e51cbSPeter Avalos * reject it.
839327e51cbSPeter Avalos */
840327e51cbSPeter Avalos for (i = 0; i < NOFFSETS; i++) {
841327e51cbSPeter Avalos unsigned char *cname, *cp;
842327e51cbSPeter Avalos size_t reloffset = prpsoffsets(i);
843327e51cbSPeter Avalos size_t noffset = doff + reloffset;
844a96e001bSPeter Avalos size_t k;
845327e51cbSPeter Avalos for (j = 0; j < 16; j++, noffset++,
846327e51cbSPeter Avalos reloffset++) {
847327e51cbSPeter Avalos /*
848327e51cbSPeter Avalos * Make sure we're not past
849327e51cbSPeter Avalos * the end of the buffer; if
850327e51cbSPeter Avalos * we are, just give up.
851327e51cbSPeter Avalos */
852327e51cbSPeter Avalos if (noffset >= size)
853327e51cbSPeter Avalos goto tryanother;
854327e51cbSPeter Avalos
855327e51cbSPeter Avalos /*
856327e51cbSPeter Avalos * Make sure we're not past
857327e51cbSPeter Avalos * the end of the contents;
858327e51cbSPeter Avalos * if we are, this obviously
859327e51cbSPeter Avalos * isn't the right offset.
860327e51cbSPeter Avalos */
861327e51cbSPeter Avalos if (reloffset >= descsz)
862327e51cbSPeter Avalos goto tryanother;
863327e51cbSPeter Avalos
864327e51cbSPeter Avalos c = nbuf[noffset];
865327e51cbSPeter Avalos if (c == '\0') {
866327e51cbSPeter Avalos /*
867327e51cbSPeter Avalos * A '\0' at the
868327e51cbSPeter Avalos * beginning is
869327e51cbSPeter Avalos * obviously wrong.
870327e51cbSPeter Avalos * Any other '\0'
871327e51cbSPeter Avalos * means we're done.
872327e51cbSPeter Avalos */
873327e51cbSPeter Avalos if (j == 0)
874327e51cbSPeter Avalos goto tryanother;
875327e51cbSPeter Avalos else
876327e51cbSPeter Avalos break;
877327e51cbSPeter Avalos } else {
878327e51cbSPeter Avalos /*
879327e51cbSPeter Avalos * A nonprintable
880327e51cbSPeter Avalos * character is also
881327e51cbSPeter Avalos * wrong.
882327e51cbSPeter Avalos */
883327e51cbSPeter Avalos if (!isprint(c) || isquote(c))
884327e51cbSPeter Avalos goto tryanother;
885327e51cbSPeter Avalos }
886327e51cbSPeter Avalos }
887327e51cbSPeter Avalos /*
888327e51cbSPeter Avalos * Well, that worked.
889327e51cbSPeter Avalos */
890e4d4ce0cSPeter Avalos
891e4d4ce0cSPeter Avalos /*
892e4d4ce0cSPeter Avalos * Try next offsets, in case this match is
893e4d4ce0cSPeter Avalos * in the middle of a string.
894e4d4ce0cSPeter Avalos */
895e4d4ce0cSPeter Avalos for (k = i + 1 ; k < NOFFSETS; k++) {
896e4d4ce0cSPeter Avalos size_t no;
897e4d4ce0cSPeter Avalos int adjust = 1;
898a96e001bSPeter Avalos if (prpsoffsets(k) >= prpsoffsets(i))
899a96e001bSPeter Avalos continue;
900*3b9cdfa3SAntonio Huete Jimenez /*
901*3b9cdfa3SAntonio Huete Jimenez * pr_fname == pr_psargs - 16 &&
902*3b9cdfa3SAntonio Huete Jimenez * non-nul-terminated fname (qemu)
903*3b9cdfa3SAntonio Huete Jimenez */
904*3b9cdfa3SAntonio Huete Jimenez if (prpsoffsets(k) ==
905*3b9cdfa3SAntonio Huete Jimenez prpsoffsets(i) - 16 && j == 16)
906*3b9cdfa3SAntonio Huete Jimenez continue;
907e4d4ce0cSPeter Avalos for (no = doff + prpsoffsets(k);
908e4d4ce0cSPeter Avalos no < doff + prpsoffsets(i); no++)
909e4d4ce0cSPeter Avalos adjust = adjust
910e4d4ce0cSPeter Avalos && isprint(nbuf[no]);
911e4d4ce0cSPeter Avalos if (adjust)
912e4d4ce0cSPeter Avalos i = k;
913e4d4ce0cSPeter Avalos }
914e4d4ce0cSPeter Avalos
9156fca56fbSSascha Wildner cname = CAST(unsigned char *,
9166fca56fbSSascha Wildner &nbuf[doff + prpsoffsets(i)]);
9176fca56fbSSascha Wildner for (cp = cname; cp < nbuf + size && *cp
9186fca56fbSSascha Wildner && isprint(*cp); cp++)
919327e51cbSPeter Avalos continue;
92079343712SPeter Avalos /*
92179343712SPeter Avalos * Linux apparently appends a space at the end
92279343712SPeter Avalos * of the command line: remove it.
92379343712SPeter Avalos */
92479343712SPeter Avalos while (cp > cname && isspace(cp[-1]))
925327e51cbSPeter Avalos cp--;
926c990e5baSDaniel Fojt if (file_printf(ms, ", from '%s'",
927c990e5baSDaniel Fojt file_copystr(buf, sizeof(buf),
928c990e5baSDaniel Fojt CAST(size_t, cp - cname),
929614728caSSascha Wildner RCAST(char *, cname))) == -1)
9306fca56fbSSascha Wildner return -1;
931327e51cbSPeter Avalos *flags |= FLAGS_DID_CORE;
93282c5fa3eSPeter Avalos return 1;
933327e51cbSPeter Avalos
934327e51cbSPeter Avalos tryanother:
935327e51cbSPeter Avalos ;
936327e51cbSPeter Avalos }
937327e51cbSPeter Avalos }
938327e51cbSPeter Avalos break;
939327e51cbSPeter Avalos }
940327e51cbSPeter Avalos #endif
94182c5fa3eSPeter Avalos return 0;
94282c5fa3eSPeter Avalos }
94382c5fa3eSPeter Avalos
944c30bd091SSascha Wildner private off_t
get_offset_from_virtaddr(struct magic_set * ms,int swap,int clazz,int fd,off_t off,int num,off_t fsize,uint64_t virtaddr)945c30bd091SSascha Wildner get_offset_from_virtaddr(struct magic_set *ms, int swap, int clazz, int fd,
946c30bd091SSascha Wildner off_t off, int num, off_t fsize, uint64_t virtaddr)
947c30bd091SSascha Wildner {
948c30bd091SSascha Wildner Elf32_Phdr ph32;
949c30bd091SSascha Wildner Elf64_Phdr ph64;
950c30bd091SSascha Wildner
951c30bd091SSascha Wildner /*
952c30bd091SSascha Wildner * Loop through all the program headers and find the header with
953c30bd091SSascha Wildner * virtual address in which the "virtaddr" belongs to.
954c30bd091SSascha Wildner */
955c30bd091SSascha Wildner for ( ; num; num--) {
9566fca56fbSSascha Wildner if (pread(fd, xph_addr, xph_sizeof, off) <
9576fca56fbSSascha Wildner CAST(ssize_t, xph_sizeof)) {
958970935fdSSascha Wildner if (file_printf(ms,
959970935fdSSascha Wildner ", can't read elf program header at %jd",
960970935fdSSascha Wildner (intmax_t)off) == -1)
961c30bd091SSascha Wildner return -1;
962970935fdSSascha Wildner return 0;
963970935fdSSascha Wildner
964c30bd091SSascha Wildner }
965c30bd091SSascha Wildner off += xph_sizeof;
966c30bd091SSascha Wildner
967c30bd091SSascha Wildner if (fsize != SIZE_UNKNOWN && xph_offset > fsize) {
968c30bd091SSascha Wildner /* Perhaps warn here */
969c30bd091SSascha Wildner continue;
970c30bd091SSascha Wildner }
971c30bd091SSascha Wildner
972c30bd091SSascha Wildner if (virtaddr >= xph_vaddr && virtaddr < xph_vaddr + xph_filesz)
973c30bd091SSascha Wildner return xph_offset + (virtaddr - xph_vaddr);
974c30bd091SSascha Wildner }
975c30bd091SSascha Wildner return 0;
976c30bd091SSascha Wildner }
977c30bd091SSascha Wildner
978c30bd091SSascha Wildner private size_t
get_string_on_virtaddr(struct magic_set * ms,int swap,int clazz,int fd,off_t ph_off,int ph_num,off_t fsize,uint64_t virtaddr,char * buf,ssize_t buflen)979c30bd091SSascha Wildner get_string_on_virtaddr(struct magic_set *ms,
980c30bd091SSascha Wildner int swap, int clazz, int fd, off_t ph_off, int ph_num,
981c30bd091SSascha Wildner off_t fsize, uint64_t virtaddr, char *buf, ssize_t buflen)
982c30bd091SSascha Wildner {
983c30bd091SSascha Wildner char *bptr;
984c30bd091SSascha Wildner off_t offset;
985c30bd091SSascha Wildner
986c30bd091SSascha Wildner if (buflen == 0)
987c30bd091SSascha Wildner return 0;
988c30bd091SSascha Wildner
989c30bd091SSascha Wildner offset = get_offset_from_virtaddr(ms, swap, clazz, fd, ph_off, ph_num,
990c30bd091SSascha Wildner fsize, virtaddr);
9916fca56fbSSascha Wildner if (offset < 0 ||
9926fca56fbSSascha Wildner (buflen = pread(fd, buf, CAST(size_t, buflen), offset)) <= 0) {
993614728caSSascha Wildner (void)file_printf(ms, ", can't read elf string at %jd",
994614728caSSascha Wildner (intmax_t)offset);
995c30bd091SSascha Wildner return 0;
996c30bd091SSascha Wildner }
997c30bd091SSascha Wildner
998c30bd091SSascha Wildner buf[buflen - 1] = '\0';
999c30bd091SSascha Wildner
1000c30bd091SSascha Wildner /* We expect only printable characters, so return if buffer contains
1001c30bd091SSascha Wildner * non-printable character before the '\0' or just '\0'. */
10026fca56fbSSascha Wildner for (bptr = buf; *bptr && isprint(CAST(unsigned char, *bptr)); bptr++)
1003c30bd091SSascha Wildner continue;
1004c30bd091SSascha Wildner if (*bptr != '\0')
1005c30bd091SSascha Wildner return 0;
1006c30bd091SSascha Wildner
1007c30bd091SSascha Wildner return bptr - buf;
1008c30bd091SSascha Wildner }
1009c30bd091SSascha Wildner
1010c30bd091SSascha Wildner
10116fca56fbSSascha Wildner /*ARGSUSED*/
1012c30bd091SSascha Wildner private int
do_auxv_note(struct magic_set * ms,unsigned char * nbuf,uint32_t type,int swap,uint32_t namesz,uint32_t descsz,size_t noff,size_t doff,int * flags,size_t size,int clazz,int fd,off_t ph_off,int ph_num,off_t fsize)1013c30bd091SSascha Wildner do_auxv_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
1014c30bd091SSascha Wildner int swap, uint32_t namesz __attribute__((__unused__)),
1015c30bd091SSascha Wildner uint32_t descsz __attribute__((__unused__)),
1016c30bd091SSascha Wildner size_t noff __attribute__((__unused__)), size_t doff,
1017c30bd091SSascha Wildner int *flags, size_t size __attribute__((__unused__)), int clazz,
1018c30bd091SSascha Wildner int fd, off_t ph_off, int ph_num, off_t fsize)
1019c30bd091SSascha Wildner {
1020c30bd091SSascha Wildner #ifdef ELFCORE
1021c30bd091SSascha Wildner Aux32Info auxv32;
1022c30bd091SSascha Wildner Aux64Info auxv64;
1023c30bd091SSascha Wildner size_t elsize = xauxv_sizeof;
1024c30bd091SSascha Wildner const char *tag;
1025c30bd091SSascha Wildner int is_string;
1026*3b9cdfa3SAntonio Huete Jimenez size_t nval, off;
1027c30bd091SSascha Wildner
1028c30bd091SSascha Wildner if ((*flags & (FLAGS_IS_CORE|FLAGS_DID_CORE_STYLE)) !=
1029c30bd091SSascha Wildner (FLAGS_IS_CORE|FLAGS_DID_CORE_STYLE))
1030c30bd091SSascha Wildner return 0;
1031c30bd091SSascha Wildner
1032c30bd091SSascha Wildner switch (*flags & FLAGS_CORE_STYLE) {
1033c30bd091SSascha Wildner case OS_STYLE_SVR4:
1034c30bd091SSascha Wildner if (type != NT_AUXV)
1035c30bd091SSascha Wildner return 0;
1036c30bd091SSascha Wildner break;
1037c30bd091SSascha Wildner #ifdef notyet
1038c30bd091SSascha Wildner case OS_STYLE_NETBSD:
1039c30bd091SSascha Wildner if (type != NT_NETBSD_CORE_AUXV)
1040c30bd091SSascha Wildner return 0;
1041c30bd091SSascha Wildner break;
1042c30bd091SSascha Wildner case OS_STYLE_FREEBSD:
1043c30bd091SSascha Wildner if (type != NT_FREEBSD_PROCSTAT_AUXV)
1044c30bd091SSascha Wildner return 0;
1045c30bd091SSascha Wildner break;
1046c30bd091SSascha Wildner #endif
1047c30bd091SSascha Wildner default:
1048c30bd091SSascha Wildner return 0;
1049c30bd091SSascha Wildner }
1050c30bd091SSascha Wildner
1051c30bd091SSascha Wildner *flags |= FLAGS_DID_AUXV;
1052c30bd091SSascha Wildner
1053c30bd091SSascha Wildner nval = 0;
1054*3b9cdfa3SAntonio Huete Jimenez for (off = 0; off + elsize <= descsz; off += elsize) {
10556fca56fbSSascha Wildner memcpy(xauxv_addr, &nbuf[doff + off], xauxv_sizeof);
1056c30bd091SSascha Wildner /* Limit processing to 50 vector entries to prevent DoS */
1057c30bd091SSascha Wildner if (nval++ >= 50) {
1058c30bd091SSascha Wildner file_error(ms, 0, "Too many ELF Auxv elements");
1059c30bd091SSascha Wildner return 1;
1060c30bd091SSascha Wildner }
1061c30bd091SSascha Wildner
1062c30bd091SSascha Wildner switch(xauxv_type) {
1063c30bd091SSascha Wildner case AT_LINUX_EXECFN:
1064c30bd091SSascha Wildner is_string = 1;
1065c30bd091SSascha Wildner tag = "execfn";
1066c30bd091SSascha Wildner break;
1067c30bd091SSascha Wildner case AT_LINUX_PLATFORM:
1068c30bd091SSascha Wildner is_string = 1;
1069c30bd091SSascha Wildner tag = "platform";
1070c30bd091SSascha Wildner break;
1071c30bd091SSascha Wildner case AT_LINUX_UID:
1072c30bd091SSascha Wildner is_string = 0;
1073c30bd091SSascha Wildner tag = "real uid";
1074c30bd091SSascha Wildner break;
1075c30bd091SSascha Wildner case AT_LINUX_GID:
1076c30bd091SSascha Wildner is_string = 0;
1077c30bd091SSascha Wildner tag = "real gid";
1078c30bd091SSascha Wildner break;
1079c30bd091SSascha Wildner case AT_LINUX_EUID:
1080c30bd091SSascha Wildner is_string = 0;
1081c30bd091SSascha Wildner tag = "effective uid";
1082c30bd091SSascha Wildner break;
1083c30bd091SSascha Wildner case AT_LINUX_EGID:
1084c30bd091SSascha Wildner is_string = 0;
1085c30bd091SSascha Wildner tag = "effective gid";
1086c30bd091SSascha Wildner break;
1087c30bd091SSascha Wildner default:
1088c30bd091SSascha Wildner is_string = 0;
1089c30bd091SSascha Wildner tag = NULL;
1090c30bd091SSascha Wildner break;
1091c30bd091SSascha Wildner }
1092c30bd091SSascha Wildner
1093c30bd091SSascha Wildner if (tag == NULL)
1094c30bd091SSascha Wildner continue;
1095c30bd091SSascha Wildner
1096c30bd091SSascha Wildner if (is_string) {
1097c30bd091SSascha Wildner char buf[256];
1098c30bd091SSascha Wildner ssize_t buflen;
1099c30bd091SSascha Wildner buflen = get_string_on_virtaddr(ms, swap, clazz, fd,
1100c30bd091SSascha Wildner ph_off, ph_num, fsize, xauxv_val, buf, sizeof(buf));
1101c30bd091SSascha Wildner
1102c30bd091SSascha Wildner if (buflen == 0)
1103c30bd091SSascha Wildner continue;
1104c30bd091SSascha Wildner
1105c30bd091SSascha Wildner if (file_printf(ms, ", %s: '%s'", tag, buf) == -1)
11066fca56fbSSascha Wildner return -1;
1107c30bd091SSascha Wildner } else {
11086fca56fbSSascha Wildner if (file_printf(ms, ", %s: %d", tag,
11096fca56fbSSascha Wildner CAST(int, xauxv_val)) == -1)
11106fca56fbSSascha Wildner return -1;
1111c30bd091SSascha Wildner }
1112c30bd091SSascha Wildner }
1113c30bd091SSascha Wildner return 1;
1114c30bd091SSascha Wildner #else
1115c30bd091SSascha Wildner return 0;
1116c30bd091SSascha Wildner #endif
1117c30bd091SSascha Wildner }
1118c30bd091SSascha Wildner
111982c5fa3eSPeter Avalos private size_t
dodynamic(struct magic_set * ms,void * vbuf,size_t offset,size_t size,int clazz,int swap,int * pie,size_t * need)11206fca56fbSSascha Wildner dodynamic(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
1121970935fdSSascha Wildner int clazz, int swap, int *pie, size_t *need)
11226fca56fbSSascha Wildner {
11236fca56fbSSascha Wildner Elf32_Dyn dh32;
11246fca56fbSSascha Wildner Elf64_Dyn dh64;
11256fca56fbSSascha Wildner unsigned char *dbuf = CAST(unsigned char *, vbuf);
11266fca56fbSSascha Wildner
11276fca56fbSSascha Wildner if (xdh_sizeof + offset > size) {
11286fca56fbSSascha Wildner /*
11296fca56fbSSascha Wildner * We're out of note headers.
11306fca56fbSSascha Wildner */
11316fca56fbSSascha Wildner return xdh_sizeof + offset;
11326fca56fbSSascha Wildner }
11336fca56fbSSascha Wildner
11346fca56fbSSascha Wildner memcpy(xdh_addr, &dbuf[offset], xdh_sizeof);
11356fca56fbSSascha Wildner offset += xdh_sizeof;
11366fca56fbSSascha Wildner
11376fca56fbSSascha Wildner switch (xdh_tag) {
11386fca56fbSSascha Wildner case DT_FLAGS_1:
1139970935fdSSascha Wildner *pie = 1;
11406fca56fbSSascha Wildner if (xdh_val & DF_1_PIE)
11416fca56fbSSascha Wildner ms->mode |= 0111;
11426fca56fbSSascha Wildner else
11436fca56fbSSascha Wildner ms->mode &= ~0111;
11446fca56fbSSascha Wildner break;
1145970935fdSSascha Wildner case DT_NEEDED:
1146970935fdSSascha Wildner (*need)++;
1147970935fdSSascha Wildner break;
11486fca56fbSSascha Wildner default:
11496fca56fbSSascha Wildner break;
11506fca56fbSSascha Wildner }
11516fca56fbSSascha Wildner return offset;
11526fca56fbSSascha Wildner }
11536fca56fbSSascha Wildner
11546fca56fbSSascha Wildner
11556fca56fbSSascha Wildner private size_t
donote(struct magic_set * ms,void * vbuf,size_t offset,size_t size,int clazz,int swap,size_t align,int * flags,uint16_t * notecount,int fd,off_t ph_off,int ph_num,off_t fsize)115682c5fa3eSPeter Avalos donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
1157c30bd091SSascha Wildner int clazz, int swap, size_t align, int *flags, uint16_t *notecount,
1158c30bd091SSascha Wildner int fd, off_t ph_off, int ph_num, off_t fsize)
115982c5fa3eSPeter Avalos {
116082c5fa3eSPeter Avalos Elf32_Nhdr nh32;
116182c5fa3eSPeter Avalos Elf64_Nhdr nh64;
116282c5fa3eSPeter Avalos size_t noff, doff;
116382c5fa3eSPeter Avalos uint32_t namesz, descsz;
1164c990e5baSDaniel Fojt char buf[256];
116582c5fa3eSPeter Avalos unsigned char *nbuf = CAST(unsigned char *, vbuf);
116682c5fa3eSPeter Avalos
116782c5fa3eSPeter Avalos if (*notecount == 0)
116882c5fa3eSPeter Avalos return 0;
116982c5fa3eSPeter Avalos --*notecount;
117082c5fa3eSPeter Avalos
117182c5fa3eSPeter Avalos if (xnh_sizeof + offset > size) {
117282c5fa3eSPeter Avalos /*
117382c5fa3eSPeter Avalos * We're out of note headers.
117482c5fa3eSPeter Avalos */
117582c5fa3eSPeter Avalos return xnh_sizeof + offset;
117682c5fa3eSPeter Avalos }
11776fca56fbSSascha Wildner /*XXX: GCC */
11786fca56fbSSascha Wildner memset(&nh32, 0, sizeof(nh32));
11796fca56fbSSascha Wildner memset(&nh64, 0, sizeof(nh64));
118082c5fa3eSPeter Avalos
11816fca56fbSSascha Wildner memcpy(xnh_addr, &nbuf[offset], xnh_sizeof);
118282c5fa3eSPeter Avalos offset += xnh_sizeof;
118382c5fa3eSPeter Avalos
118482c5fa3eSPeter Avalos namesz = xnh_namesz;
118582c5fa3eSPeter Avalos descsz = xnh_descsz;
1186c30bd091SSascha Wildner
118782c5fa3eSPeter Avalos if ((namesz == 0) && (descsz == 0)) {
118882c5fa3eSPeter Avalos /*
118982c5fa3eSPeter Avalos * We're out of note headers.
119082c5fa3eSPeter Avalos */
119182c5fa3eSPeter Avalos return (offset >= size) ? offset : size;
119282c5fa3eSPeter Avalos }
119382c5fa3eSPeter Avalos
119482c5fa3eSPeter Avalos if (namesz & 0x80000000) {
1195614728caSSascha Wildner (void)file_printf(ms, ", bad note name size %#lx",
1196614728caSSascha Wildner CAST(unsigned long, namesz));
119782c5fa3eSPeter Avalos return 0;
119882c5fa3eSPeter Avalos }
119982c5fa3eSPeter Avalos
120082c5fa3eSPeter Avalos if (descsz & 0x80000000) {
1201614728caSSascha Wildner (void)file_printf(ms, ", bad note description size %#lx",
1202614728caSSascha Wildner CAST(unsigned long, descsz));
120382c5fa3eSPeter Avalos return 0;
120482c5fa3eSPeter Avalos }
120582c5fa3eSPeter Avalos
120682c5fa3eSPeter Avalos noff = offset;
120782c5fa3eSPeter Avalos doff = ELF_ALIGN(offset + namesz);
120882c5fa3eSPeter Avalos
120982c5fa3eSPeter Avalos if (offset + namesz > size) {
121082c5fa3eSPeter Avalos /*
121182c5fa3eSPeter Avalos * We're past the end of the buffer.
121282c5fa3eSPeter Avalos */
121382c5fa3eSPeter Avalos return doff;
121482c5fa3eSPeter Avalos }
121582c5fa3eSPeter Avalos
121682c5fa3eSPeter Avalos offset = ELF_ALIGN(doff + descsz);
121782c5fa3eSPeter Avalos if (doff + descsz > size) {
121882c5fa3eSPeter Avalos /*
121982c5fa3eSPeter Avalos * We're past the end of the buffer.
122082c5fa3eSPeter Avalos */
122182c5fa3eSPeter Avalos return (offset >= size) ? offset : size;
122282c5fa3eSPeter Avalos }
122382c5fa3eSPeter Avalos
1224c30bd091SSascha Wildner
122582c5fa3eSPeter Avalos if ((*flags & FLAGS_DID_OS_NOTE) == 0) {
122682c5fa3eSPeter Avalos if (do_os_note(ms, nbuf, xnh_type, swap,
122782c5fa3eSPeter Avalos namesz, descsz, noff, doff, flags))
1228c30bd091SSascha Wildner return offset;
122982c5fa3eSPeter Avalos }
123082c5fa3eSPeter Avalos
123182c5fa3eSPeter Avalos if ((*flags & FLAGS_DID_BUILD_ID) == 0) {
123282c5fa3eSPeter Avalos if (do_bid_note(ms, nbuf, xnh_type, swap,
123382c5fa3eSPeter Avalos namesz, descsz, noff, doff, flags))
1234c30bd091SSascha Wildner return offset;
123582c5fa3eSPeter Avalos }
123682c5fa3eSPeter Avalos
123782c5fa3eSPeter Avalos if ((*flags & FLAGS_DID_NETBSD_PAX) == 0) {
123882c5fa3eSPeter Avalos if (do_pax_note(ms, nbuf, xnh_type, swap,
123982c5fa3eSPeter Avalos namesz, descsz, noff, doff, flags))
1240c30bd091SSascha Wildner return offset;
124182c5fa3eSPeter Avalos }
124282c5fa3eSPeter Avalos
124382c5fa3eSPeter Avalos if ((*flags & FLAGS_DID_CORE) == 0) {
124482c5fa3eSPeter Avalos if (do_core_note(ms, nbuf, xnh_type, swap,
124582c5fa3eSPeter Avalos namesz, descsz, noff, doff, flags, size, clazz))
1246c30bd091SSascha Wildner return offset;
1247c30bd091SSascha Wildner }
1248c30bd091SSascha Wildner
1249c30bd091SSascha Wildner if ((*flags & FLAGS_DID_AUXV) == 0) {
1250c30bd091SSascha Wildner if (do_auxv_note(ms, nbuf, xnh_type, swap,
1251c30bd091SSascha Wildner namesz, descsz, noff, doff, flags, size, clazz,
1252c30bd091SSascha Wildner fd, ph_off, ph_num, fsize))
1253c30bd091SSascha Wildner return offset;
125482c5fa3eSPeter Avalos }
125582c5fa3eSPeter Avalos
12566fca56fbSSascha Wildner if (namesz == 7 && strcmp(RCAST(char *, &nbuf[noff]), "NetBSD") == 0) {
12576fca56fbSSascha Wildner int descw, flag;
12586fca56fbSSascha Wildner const char *str, *tag;
125982c5fa3eSPeter Avalos if (descsz > 100)
126082c5fa3eSPeter Avalos descsz = 100;
126182c5fa3eSPeter Avalos switch (xnh_type) {
126282c5fa3eSPeter Avalos case NT_NETBSD_VERSION:
1263c30bd091SSascha Wildner return offset;
126482c5fa3eSPeter Avalos case NT_NETBSD_MARCH:
12656fca56fbSSascha Wildner flag = FLAGS_DID_NETBSD_MARCH;
12666fca56fbSSascha Wildner tag = "compiled for";
126782c5fa3eSPeter Avalos break;
126882c5fa3eSPeter Avalos case NT_NETBSD_CMODEL:
12696fca56fbSSascha Wildner flag = FLAGS_DID_NETBSD_CMODEL;
12706fca56fbSSascha Wildner tag = "compiler model";
12716fca56fbSSascha Wildner break;
12726fca56fbSSascha Wildner case NT_NETBSD_EMULATION:
12736fca56fbSSascha Wildner flag = FLAGS_DID_NETBSD_EMULATION;
12746fca56fbSSascha Wildner tag = "emulation:";
127582c5fa3eSPeter Avalos break;
127682c5fa3eSPeter Avalos default:
127782c5fa3eSPeter Avalos if (*flags & FLAGS_DID_NETBSD_UNKNOWN)
1278c30bd091SSascha Wildner return offset;
127982c5fa3eSPeter Avalos *flags |= FLAGS_DID_NETBSD_UNKNOWN;
128082c5fa3eSPeter Avalos if (file_printf(ms, ", note=%u", xnh_type) == -1)
1281c30bd091SSascha Wildner return offset;
12826fca56fbSSascha Wildner return offset;
128382c5fa3eSPeter Avalos }
12846fca56fbSSascha Wildner
12856fca56fbSSascha Wildner if (*flags & flag)
12866fca56fbSSascha Wildner return offset;
12876fca56fbSSascha Wildner str = RCAST(const char *, &nbuf[doff]);
12886fca56fbSSascha Wildner descw = CAST(int, descsz);
12896fca56fbSSascha Wildner *flags |= flag;
1290c990e5baSDaniel Fojt file_printf(ms, ", %s: %s", tag,
1291c990e5baSDaniel Fojt file_copystr(buf, sizeof(buf), descw, str));
1292c30bd091SSascha Wildner return offset;
129382c5fa3eSPeter Avalos }
129482c5fa3eSPeter Avalos
1295327e51cbSPeter Avalos return offset;
1296327e51cbSPeter Avalos }
1297327e51cbSPeter Avalos
129879343712SPeter Avalos /* SunOS 5.x hardware capability descriptions */
129979343712SPeter Avalos typedef struct cap_desc {
130079343712SPeter Avalos uint64_t cd_mask;
130179343712SPeter Avalos const char *cd_name;
130279343712SPeter Avalos } cap_desc_t;
130379343712SPeter Avalos
130479343712SPeter Avalos static const cap_desc_t cap_desc_sparc[] = {
130579343712SPeter Avalos { AV_SPARC_MUL32, "MUL32" },
130679343712SPeter Avalos { AV_SPARC_DIV32, "DIV32" },
130779343712SPeter Avalos { AV_SPARC_FSMULD, "FSMULD" },
130879343712SPeter Avalos { AV_SPARC_V8PLUS, "V8PLUS" },
130979343712SPeter Avalos { AV_SPARC_POPC, "POPC" },
131079343712SPeter Avalos { AV_SPARC_VIS, "VIS" },
131179343712SPeter Avalos { AV_SPARC_VIS2, "VIS2" },
131279343712SPeter Avalos { AV_SPARC_ASI_BLK_INIT, "ASI_BLK_INIT" },
131379343712SPeter Avalos { AV_SPARC_FMAF, "FMAF" },
131479343712SPeter Avalos { AV_SPARC_FJFMAU, "FJFMAU" },
131579343712SPeter Avalos { AV_SPARC_IMA, "IMA" },
131679343712SPeter Avalos { 0, NULL }
131779343712SPeter Avalos };
131879343712SPeter Avalos
131979343712SPeter Avalos static const cap_desc_t cap_desc_386[] = {
132079343712SPeter Avalos { AV_386_FPU, "FPU" },
132179343712SPeter Avalos { AV_386_TSC, "TSC" },
132279343712SPeter Avalos { AV_386_CX8, "CX8" },
132379343712SPeter Avalos { AV_386_SEP, "SEP" },
132479343712SPeter Avalos { AV_386_AMD_SYSC, "AMD_SYSC" },
132579343712SPeter Avalos { AV_386_CMOV, "CMOV" },
132679343712SPeter Avalos { AV_386_MMX, "MMX" },
132779343712SPeter Avalos { AV_386_AMD_MMX, "AMD_MMX" },
132879343712SPeter Avalos { AV_386_AMD_3DNow, "AMD_3DNow" },
132979343712SPeter Avalos { AV_386_AMD_3DNowx, "AMD_3DNowx" },
133079343712SPeter Avalos { AV_386_FXSR, "FXSR" },
133179343712SPeter Avalos { AV_386_SSE, "SSE" },
133279343712SPeter Avalos { AV_386_SSE2, "SSE2" },
133379343712SPeter Avalos { AV_386_PAUSE, "PAUSE" },
133479343712SPeter Avalos { AV_386_SSE3, "SSE3" },
133579343712SPeter Avalos { AV_386_MON, "MON" },
133679343712SPeter Avalos { AV_386_CX16, "CX16" },
133779343712SPeter Avalos { AV_386_AHF, "AHF" },
133879343712SPeter Avalos { AV_386_TSCP, "TSCP" },
133979343712SPeter Avalos { AV_386_AMD_SSE4A, "AMD_SSE4A" },
134079343712SPeter Avalos { AV_386_POPCNT, "POPCNT" },
134179343712SPeter Avalos { AV_386_AMD_LZCNT, "AMD_LZCNT" },
134279343712SPeter Avalos { AV_386_SSSE3, "SSSE3" },
134379343712SPeter Avalos { AV_386_SSE4_1, "SSE4.1" },
134479343712SPeter Avalos { AV_386_SSE4_2, "SSE4.2" },
134579343712SPeter Avalos { 0, NULL }
134679343712SPeter Avalos };
134779343712SPeter Avalos
1348327e51cbSPeter Avalos private int
doshn(struct magic_set * ms,int clazz,int swap,int fd,off_t off,int num,size_t size,off_t fsize,int mach,int strtab,int * flags,uint16_t * notecount)134979343712SPeter Avalos doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
135082c5fa3eSPeter Avalos size_t size, off_t fsize, int mach, int strtab, int *flags,
135182c5fa3eSPeter Avalos uint16_t *notecount)
1352327e51cbSPeter Avalos {
1353327e51cbSPeter Avalos Elf32_Shdr sh32;
1354327e51cbSPeter Avalos Elf64_Shdr sh64;
1355c30bd091SSascha Wildner int stripped = 1, has_debug_info = 0;
135682c5fa3eSPeter Avalos size_t nbadcap = 0;
1357327e51cbSPeter Avalos void *nbuf;
1358970935fdSSascha Wildner off_t noff, coff, name_off, offs;
1359c30bd091SSascha Wildner uint64_t cap_hw1 = 0; /* SunOS 5.x hardware capabilities */
1360c30bd091SSascha Wildner uint64_t cap_sf1 = 0; /* SunOS 5.x software capabilities */
1361e8af9738SPeter Avalos char name[50];
136282c5fa3eSPeter Avalos ssize_t namesize;
1363327e51cbSPeter Avalos
1364c990e5baSDaniel Fojt if (ms->flags & MAGIC_MIME)
1365c990e5baSDaniel Fojt return 0;
1366c990e5baSDaniel Fojt
13676fca56fbSSascha Wildner if (num == 0) {
13686fca56fbSSascha Wildner if (file_printf(ms, ", no section header") == -1)
13696fca56fbSSascha Wildner return -1;
13706fca56fbSSascha Wildner return 0;
13716fca56fbSSascha Wildner }
1372327e51cbSPeter Avalos if (size != xsh_sizeof) {
1373327e51cbSPeter Avalos if (file_printf(ms, ", corrupted section header size") == -1)
1374327e51cbSPeter Avalos return -1;
1375327e51cbSPeter Avalos return 0;
1376327e51cbSPeter Avalos }
1377327e51cbSPeter Avalos
1378e8af9738SPeter Avalos /* Read offset of name section to be able to read section names later */
1379970935fdSSascha Wildner offs = CAST(off_t, (off + size * strtab));
1380970935fdSSascha Wildner if (pread(fd, xsh_addr, xsh_sizeof, offs) < CAST(ssize_t, xsh_sizeof)) {
1381970935fdSSascha Wildner if (file_printf(ms, ", missing section headers at %jd",
1382970935fdSSascha Wildner (intmax_t)offs) == -1)
1383327e51cbSPeter Avalos return -1;
1384c30bd091SSascha Wildner return 0;
1385327e51cbSPeter Avalos }
1386e8af9738SPeter Avalos name_off = xsh_offset;
1387e8af9738SPeter Avalos
13886fca56fbSSascha Wildner if (fsize != SIZE_UNKNOWN && fsize < name_off) {
1389c990e5baSDaniel Fojt if (file_printf(ms, ", too large section header offset %jd",
1390c990e5baSDaniel Fojt (intmax_t)name_off) == -1)
13916fca56fbSSascha Wildner return -1;
13926fca56fbSSascha Wildner return 0;
13936fca56fbSSascha Wildner }
13946fca56fbSSascha Wildner
1395e8af9738SPeter Avalos for ( ; num; num--) {
1396e8af9738SPeter Avalos /* Read the name of this section. */
1397970935fdSSascha Wildner offs = name_off + xsh_name;
1398970935fdSSascha Wildner if ((namesize = pread(fd, name, sizeof(name) - 1, offs))
1399970935fdSSascha Wildner == -1) {
1400970935fdSSascha Wildner if (file_printf(ms,
1401970935fdSSascha Wildner ", can't read name of elf section at %jd",
1402970935fdSSascha Wildner (intmax_t)offs) == -1)
1403e8af9738SPeter Avalos return -1;
1404970935fdSSascha Wildner return 0;
1405e8af9738SPeter Avalos }
140682c5fa3eSPeter Avalos name[namesize] = '\0';
1407c30bd091SSascha Wildner if (strcmp(name, ".debug_info") == 0) {
1408c30bd091SSascha Wildner has_debug_info = 1;
1409e8af9738SPeter Avalos stripped = 0;
1410c30bd091SSascha Wildner }
1411e8af9738SPeter Avalos
14126fca56fbSSascha Wildner if (pread(fd, xsh_addr, xsh_sizeof, off) <
14136fca56fbSSascha Wildner CAST(ssize_t, xsh_sizeof)) {
1414970935fdSSascha Wildner if (file_printf(ms, ", can't read elf section at %jd",
1415970935fdSSascha Wildner (intmax_t)off) == -1)
1416327e51cbSPeter Avalos return -1;
1417970935fdSSascha Wildner return 0;
1418327e51cbSPeter Avalos }
1419a96e001bSPeter Avalos off += size;
1420a96e001bSPeter Avalos
1421a96e001bSPeter Avalos /* Things we can determine before we seek */
1422327e51cbSPeter Avalos switch (xsh_type) {
1423327e51cbSPeter Avalos case SHT_SYMTAB:
1424327e51cbSPeter Avalos #if 0
1425327e51cbSPeter Avalos case SHT_DYNSYM:
1426327e51cbSPeter Avalos #endif
1427327e51cbSPeter Avalos stripped = 0;
1428327e51cbSPeter Avalos break;
1429a96e001bSPeter Avalos default:
143082c5fa3eSPeter Avalos if (fsize != SIZE_UNKNOWN && xsh_offset > fsize) {
1431a96e001bSPeter Avalos /* Perhaps warn here */
1432a96e001bSPeter Avalos continue;
1433327e51cbSPeter Avalos }
1434a96e001bSPeter Avalos break;
1435a96e001bSPeter Avalos }
1436a96e001bSPeter Avalos
1437c30bd091SSascha Wildner
1438a96e001bSPeter Avalos /* Things we can determine when we seek */
1439a96e001bSPeter Avalos switch (xsh_type) {
1440a96e001bSPeter Avalos case SHT_NOTE:
14416fca56fbSSascha Wildner if (CAST(uintmax_t, (xsh_size + xsh_offset)) >
14426fca56fbSSascha Wildner CAST(uintmax_t, fsize)) {
1443c30bd091SSascha Wildner if (file_printf(ms,
1444c30bd091SSascha Wildner ", note offset/size %#" INTMAX_T_FORMAT
1445c30bd091SSascha Wildner "x+%#" INTMAX_T_FORMAT "x exceeds"
1446c30bd091SSascha Wildner " file size %#" INTMAX_T_FORMAT "x",
14476fca56fbSSascha Wildner CAST(uintmax_t, xsh_offset),
14486fca56fbSSascha Wildner CAST(uintmax_t, xsh_size),
14496fca56fbSSascha Wildner CAST(uintmax_t, fsize)) == -1)
1450c30bd091SSascha Wildner return -1;
1451c30bd091SSascha Wildner return 0;
1452c30bd091SSascha Wildner }
1453*3b9cdfa3SAntonio Huete Jimenez if (xsh_size > MAX_SHSIZE) {
1454*3b9cdfa3SAntonio Huete Jimenez file_error(ms, errno, "Note section size too "
1455*3b9cdfa3SAntonio Huete Jimenez "big (%ju > %u)", (uintmax_t)xsh_size,
1456*3b9cdfa3SAntonio Huete Jimenez MAX_SHSIZE);
1457*3b9cdfa3SAntonio Huete Jimenez return -1;
1458*3b9cdfa3SAntonio Huete Jimenez }
1459e8af9738SPeter Avalos if ((nbuf = malloc(xsh_size)) == NULL) {
1460327e51cbSPeter Avalos file_error(ms, errno, "Cannot allocate memory"
1461327e51cbSPeter Avalos " for note");
1462327e51cbSPeter Avalos return -1;
1463327e51cbSPeter Avalos }
1464970935fdSSascha Wildner offs = xsh_offset;
1465970935fdSSascha Wildner if (pread(fd, nbuf, xsh_size, offs) <
14666fca56fbSSascha Wildner CAST(ssize_t, xsh_size)) {
1467327e51cbSPeter Avalos free(nbuf);
1468970935fdSSascha Wildner if (file_printf(ms,
1469970935fdSSascha Wildner ", can't read elf note at %jd",
1470970935fdSSascha Wildner (intmax_t)offs) == -1)
1471327e51cbSPeter Avalos return -1;
1472970935fdSSascha Wildner return 0;
1473327e51cbSPeter Avalos }
1474327e51cbSPeter Avalos
1475327e51cbSPeter Avalos noff = 0;
1476327e51cbSPeter Avalos for (;;) {
14776fca56fbSSascha Wildner if (noff >= CAST(off_t, xsh_size))
1478327e51cbSPeter Avalos break;
14796fca56fbSSascha Wildner noff = donote(ms, nbuf, CAST(size_t, noff),
1480c30bd091SSascha Wildner xsh_size, clazz, swap, 4, flags, notecount,
1481c30bd091SSascha Wildner fd, 0, 0, 0);
1482327e51cbSPeter Avalos if (noff == 0)
1483327e51cbSPeter Avalos break;
1484327e51cbSPeter Avalos }
1485327e51cbSPeter Avalos free(nbuf);
1486327e51cbSPeter Avalos break;
148779343712SPeter Avalos case SHT_SUNW_cap:
1488e8af9738SPeter Avalos switch (mach) {
1489e8af9738SPeter Avalos case EM_SPARC:
1490e8af9738SPeter Avalos case EM_SPARCV9:
1491e8af9738SPeter Avalos case EM_IA_64:
1492e8af9738SPeter Avalos case EM_386:
1493e8af9738SPeter Avalos case EM_AMD64:
1494e8af9738SPeter Avalos break;
1495e8af9738SPeter Avalos default:
1496e8af9738SPeter Avalos goto skip;
1497e8af9738SPeter Avalos }
1498e8af9738SPeter Avalos
149982c5fa3eSPeter Avalos if (nbadcap > 5)
150082c5fa3eSPeter Avalos break;
15016fca56fbSSascha Wildner if (lseek(fd, xsh_offset, SEEK_SET)
15026fca56fbSSascha Wildner == CAST(off_t, -1)) {
1503a96e001bSPeter Avalos file_badseek(ms);
150479343712SPeter Avalos return -1;
150579343712SPeter Avalos }
150679343712SPeter Avalos coff = 0;
150779343712SPeter Avalos for (;;) {
150879343712SPeter Avalos Elf32_Cap cap32;
150979343712SPeter Avalos Elf64_Cap cap64;
151079343712SPeter Avalos char cbuf[/*CONSTCOND*/
15116fca56fbSSascha Wildner MAX(sizeof(cap32), sizeof(cap64))];
15126fca56fbSSascha Wildner if ((coff += xcap_sizeof) >
15136fca56fbSSascha Wildner CAST(off_t, xsh_size))
151479343712SPeter Avalos break;
15156fca56fbSSascha Wildner if (read(fd, cbuf, CAST(size_t, xcap_sizeof)) !=
15166fca56fbSSascha Wildner CAST(ssize_t, xcap_sizeof)) {
151779343712SPeter Avalos file_badread(ms);
151879343712SPeter Avalos return -1;
151979343712SPeter Avalos }
152082c5fa3eSPeter Avalos if (cbuf[0] == 'A') {
152182c5fa3eSPeter Avalos #ifdef notyet
152282c5fa3eSPeter Avalos char *p = cbuf + 1;
152382c5fa3eSPeter Avalos uint32_t len, tag;
152482c5fa3eSPeter Avalos memcpy(&len, p, sizeof(len));
152582c5fa3eSPeter Avalos p += 4;
152682c5fa3eSPeter Avalos len = getu32(swap, len);
152782c5fa3eSPeter Avalos if (memcmp("gnu", p, 3) != 0) {
152882c5fa3eSPeter Avalos if (file_printf(ms,
152982c5fa3eSPeter Avalos ", unknown capability %.3s", p)
153082c5fa3eSPeter Avalos == -1)
153182c5fa3eSPeter Avalos return -1;
153282c5fa3eSPeter Avalos break;
153382c5fa3eSPeter Avalos }
153482c5fa3eSPeter Avalos p += strlen(p) + 1;
153582c5fa3eSPeter Avalos tag = *p++;
153682c5fa3eSPeter Avalos memcpy(&len, p, sizeof(len));
153782c5fa3eSPeter Avalos p += 4;
153882c5fa3eSPeter Avalos len = getu32(swap, len);
153982c5fa3eSPeter Avalos if (tag != 1) {
154082c5fa3eSPeter Avalos if (file_printf(ms, ", unknown gnu"
154182c5fa3eSPeter Avalos " capability tag %d", tag)
154282c5fa3eSPeter Avalos == -1)
154382c5fa3eSPeter Avalos return -1;
154482c5fa3eSPeter Avalos break;
154582c5fa3eSPeter Avalos }
154682c5fa3eSPeter Avalos // gnu attributes
154782c5fa3eSPeter Avalos #endif
154882c5fa3eSPeter Avalos break;
154982c5fa3eSPeter Avalos }
15506fca56fbSSascha Wildner memcpy(xcap_addr, cbuf, xcap_sizeof);
155179343712SPeter Avalos switch (xcap_tag) {
155279343712SPeter Avalos case CA_SUNW_NULL:
155379343712SPeter Avalos break;
155479343712SPeter Avalos case CA_SUNW_HW_1:
155579343712SPeter Avalos cap_hw1 |= xcap_val;
155679343712SPeter Avalos break;
155779343712SPeter Avalos case CA_SUNW_SF_1:
155879343712SPeter Avalos cap_sf1 |= xcap_val;
155979343712SPeter Avalos break;
156079343712SPeter Avalos default:
156179343712SPeter Avalos if (file_printf(ms,
156279343712SPeter Avalos ", with unknown capability "
1563c30bd091SSascha Wildner "%#" INT64_T_FORMAT "x = %#"
1564e4d4ce0cSPeter Avalos INT64_T_FORMAT "x",
15656fca56fbSSascha Wildner CAST(unsigned long long, xcap_tag),
15666fca56fbSSascha Wildner CAST(unsigned long long, xcap_val))
15676fca56fbSSascha Wildner == -1)
156879343712SPeter Avalos return -1;
156982c5fa3eSPeter Avalos if (nbadcap++ > 2)
157082c5fa3eSPeter Avalos coff = xsh_size;
157179343712SPeter Avalos break;
157279343712SPeter Avalos }
157379343712SPeter Avalos }
1574e8af9738SPeter Avalos /*FALLTHROUGH*/
1575e8af9738SPeter Avalos skip:
1576a96e001bSPeter Avalos default:
1577a96e001bSPeter Avalos break;
1578327e51cbSPeter Avalos }
1579327e51cbSPeter Avalos }
1580e8af9738SPeter Avalos
1581c30bd091SSascha Wildner if (has_debug_info) {
1582c30bd091SSascha Wildner if (file_printf(ms, ", with debug_info") == -1)
1583c30bd091SSascha Wildner return -1;
1584c30bd091SSascha Wildner }
1585327e51cbSPeter Avalos if (file_printf(ms, ", %sstripped", stripped ? "" : "not ") == -1)
1586327e51cbSPeter Avalos return -1;
158779343712SPeter Avalos if (cap_hw1) {
158879343712SPeter Avalos const cap_desc_t *cdp;
158979343712SPeter Avalos switch (mach) {
159079343712SPeter Avalos case EM_SPARC:
159179343712SPeter Avalos case EM_SPARC32PLUS:
159279343712SPeter Avalos case EM_SPARCV9:
159379343712SPeter Avalos cdp = cap_desc_sparc;
159479343712SPeter Avalos break;
159579343712SPeter Avalos case EM_386:
159679343712SPeter Avalos case EM_IA_64:
159779343712SPeter Avalos case EM_AMD64:
159879343712SPeter Avalos cdp = cap_desc_386;
159979343712SPeter Avalos break;
160079343712SPeter Avalos default:
160179343712SPeter Avalos cdp = NULL;
160279343712SPeter Avalos break;
160379343712SPeter Avalos }
160479343712SPeter Avalos if (file_printf(ms, ", uses") == -1)
160579343712SPeter Avalos return -1;
160679343712SPeter Avalos if (cdp) {
160779343712SPeter Avalos while (cdp->cd_name) {
160879343712SPeter Avalos if (cap_hw1 & cdp->cd_mask) {
160979343712SPeter Avalos if (file_printf(ms,
161079343712SPeter Avalos " %s", cdp->cd_name) == -1)
161179343712SPeter Avalos return -1;
161279343712SPeter Avalos cap_hw1 &= ~cdp->cd_mask;
161379343712SPeter Avalos }
161479343712SPeter Avalos ++cdp;
161579343712SPeter Avalos }
161679343712SPeter Avalos if (cap_hw1)
161779343712SPeter Avalos if (file_printf(ms,
1618c30bd091SSascha Wildner " unknown hardware capability %#"
1619e4d4ce0cSPeter Avalos INT64_T_FORMAT "x",
16206fca56fbSSascha Wildner CAST(unsigned long long, cap_hw1)) == -1)
162179343712SPeter Avalos return -1;
162279343712SPeter Avalos } else {
162379343712SPeter Avalos if (file_printf(ms,
1624c30bd091SSascha Wildner " hardware capability %#" INT64_T_FORMAT "x",
16256fca56fbSSascha Wildner CAST(unsigned long long, cap_hw1)) == -1)
162679343712SPeter Avalos return -1;
162779343712SPeter Avalos }
162879343712SPeter Avalos }
162979343712SPeter Avalos if (cap_sf1) {
163079343712SPeter Avalos if (cap_sf1 & SF1_SUNW_FPUSED) {
163179343712SPeter Avalos if (file_printf(ms,
163279343712SPeter Avalos (cap_sf1 & SF1_SUNW_FPKNWN)
163379343712SPeter Avalos ? ", uses frame pointer"
163479343712SPeter Avalos : ", not known to use frame pointer") == -1)
163579343712SPeter Avalos return -1;
163679343712SPeter Avalos }
163779343712SPeter Avalos cap_sf1 &= ~SF1_SUNW_MASK;
163879343712SPeter Avalos if (cap_sf1)
163979343712SPeter Avalos if (file_printf(ms,
1640c30bd091SSascha Wildner ", with unknown software capability %#"
1641e4d4ce0cSPeter Avalos INT64_T_FORMAT "x",
16426fca56fbSSascha Wildner CAST(unsigned long long, cap_sf1)) == -1)
164379343712SPeter Avalos return -1;
164479343712SPeter Avalos }
1645327e51cbSPeter Avalos return 0;
1646327e51cbSPeter Avalos }
1647327e51cbSPeter Avalos
1648327e51cbSPeter Avalos /*
1649970935fdSSascha Wildner * Look through the program headers of an executable image, to determine
1650970935fdSSascha Wildner * if it is statically or dynamically linked. If it has a dynamic section,
1651970935fdSSascha Wildner * it is pie, and does not have an interpreter or needed libraries, we
1652970935fdSSascha Wildner * call it static pie.
1653327e51cbSPeter Avalos */
1654327e51cbSPeter Avalos private int
dophn_exec(struct magic_set * ms,int clazz,int swap,int fd,off_t off,int num,size_t size,off_t fsize,int sh_num,int * flags,uint16_t * notecount)165579343712SPeter Avalos dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
165682c5fa3eSPeter Avalos int num, size_t size, off_t fsize, int sh_num, int *flags,
165782c5fa3eSPeter Avalos uint16_t *notecount)
1658327e51cbSPeter Avalos {
1659327e51cbSPeter Avalos Elf32_Phdr ph32;
1660327e51cbSPeter Avalos Elf64_Phdr ph64;
1661970935fdSSascha Wildner const char *linking_style;
1662327e51cbSPeter Avalos unsigned char nbuf[BUFSIZ];
166382c5fa3eSPeter Avalos char ibuf[BUFSIZ];
16646fca56fbSSascha Wildner char interp[BUFSIZ];
1665f72f8299SJan Lentfer ssize_t bufsize;
1666*3b9cdfa3SAntonio Huete Jimenez size_t offset, align, need = 0;
1667970935fdSSascha Wildner int pie = 0, dynamic = 0;
1668327e51cbSPeter Avalos
16696fca56fbSSascha Wildner if (num == 0) {
16706fca56fbSSascha Wildner if (file_printf(ms, ", no program header") == -1)
16716fca56fbSSascha Wildner return -1;
16726fca56fbSSascha Wildner return 0;
16736fca56fbSSascha Wildner }
1674327e51cbSPeter Avalos if (size != xph_sizeof) {
1675327e51cbSPeter Avalos if (file_printf(ms, ", corrupted program header size") == -1)
1676327e51cbSPeter Avalos return -1;
1677327e51cbSPeter Avalos return 0;
1678327e51cbSPeter Avalos }
1679327e51cbSPeter Avalos
16806fca56fbSSascha Wildner interp[0] = '\0';
1681a96e001bSPeter Avalos for ( ; num; num--) {
16826fca56fbSSascha Wildner int doread;
16836fca56fbSSascha Wildner if (pread(fd, xph_addr, xph_sizeof, off) <
16846fca56fbSSascha Wildner CAST(ssize_t, xph_sizeof)) {
1685970935fdSSascha Wildner if (file_printf(ms,
1686970935fdSSascha Wildner ", can't read elf program headers at %jd",
1687970935fdSSascha Wildner (intmax_t)off) == -1)
1688327e51cbSPeter Avalos return -1;
1689970935fdSSascha Wildner return 0;
1690327e51cbSPeter Avalos }
1691327e51cbSPeter Avalos
1692a96e001bSPeter Avalos off += size;
169382c5fa3eSPeter Avalos bufsize = 0;
169482c5fa3eSPeter Avalos align = 4;
1695327e51cbSPeter Avalos
1696a96e001bSPeter Avalos /* Things we can determine before we seek */
1697327e51cbSPeter Avalos switch (xph_type) {
1698327e51cbSPeter Avalos case PT_DYNAMIC:
16996fca56fbSSascha Wildner doread = 1;
1700327e51cbSPeter Avalos break;
170182c5fa3eSPeter Avalos case PT_NOTE:
170282c5fa3eSPeter Avalos if (sh_num) /* Did this through section headers */
170382c5fa3eSPeter Avalos continue;
170482c5fa3eSPeter Avalos if (((align = xph_align) & 0x80000000UL) != 0 ||
170582c5fa3eSPeter Avalos align < 4) {
170682c5fa3eSPeter Avalos if (file_printf(ms,
1707c30bd091SSascha Wildner ", invalid note alignment %#lx",
17086fca56fbSSascha Wildner CAST(unsigned long, align)) == -1)
170982c5fa3eSPeter Avalos return -1;
171082c5fa3eSPeter Avalos align = 4;
171182c5fa3eSPeter Avalos }
171282c5fa3eSPeter Avalos /*FALLTHROUGH*/
1713327e51cbSPeter Avalos case PT_INTERP:
17146fca56fbSSascha Wildner doread = 1;
1715327e51cbSPeter Avalos break;
1716a96e001bSPeter Avalos default:
17176fca56fbSSascha Wildner doread = 0;
171882c5fa3eSPeter Avalos if (fsize != SIZE_UNKNOWN && xph_offset > fsize) {
1719a96e001bSPeter Avalos /* Maybe warn here? */
1720a96e001bSPeter Avalos continue;
1721a96e001bSPeter Avalos }
1722a96e001bSPeter Avalos break;
1723a96e001bSPeter Avalos }
1724a96e001bSPeter Avalos
17256fca56fbSSascha Wildner if (doread) {
1726*3b9cdfa3SAntonio Huete Jimenez size_t len = xph_filesz < sizeof(nbuf) ? xph_filesz
17276fca56fbSSascha Wildner : sizeof(nbuf);
1728970935fdSSascha Wildner off_t offs = xph_offset;
1729970935fdSSascha Wildner bufsize = pread(fd, nbuf, len, offs);
17306fca56fbSSascha Wildner if (bufsize == -1) {
1731970935fdSSascha Wildner if (file_printf(ms,
1732970935fdSSascha Wildner ", can't read section at %jd",
1733970935fdSSascha Wildner (intmax_t)offs) == -1)
17346fca56fbSSascha Wildner return -1;
1735970935fdSSascha Wildner return 0;
17366fca56fbSSascha Wildner }
1737*3b9cdfa3SAntonio Huete Jimenez }
17386fca56fbSSascha Wildner
1739a96e001bSPeter Avalos /* Things we can determine when we seek */
1740a96e001bSPeter Avalos switch (xph_type) {
17416fca56fbSSascha Wildner case PT_DYNAMIC:
1742970935fdSSascha Wildner dynamic = 1;
17436fca56fbSSascha Wildner offset = 0;
17446fca56fbSSascha Wildner // Let DF_1 determine if we are PIE or not.
17456fca56fbSSascha Wildner ms->mode &= ~0111;
17466fca56fbSSascha Wildner for (;;) {
17476fca56fbSSascha Wildner if (offset >= CAST(size_t, bufsize))
17486fca56fbSSascha Wildner break;
17496fca56fbSSascha Wildner offset = dodynamic(ms, nbuf, offset,
1750970935fdSSascha Wildner CAST(size_t, bufsize), clazz, swap,
1751970935fdSSascha Wildner &pie, &need);
17526fca56fbSSascha Wildner if (offset == 0)
17536fca56fbSSascha Wildner break;
17546fca56fbSSascha Wildner }
1755c990e5baSDaniel Fojt if (ms->flags & MAGIC_MIME)
1756c990e5baSDaniel Fojt continue;
17576fca56fbSSascha Wildner break;
17586fca56fbSSascha Wildner
175982c5fa3eSPeter Avalos case PT_INTERP:
1760970935fdSSascha Wildner need++;
1761c990e5baSDaniel Fojt if (ms->flags & MAGIC_MIME)
1762c990e5baSDaniel Fojt continue;
176382c5fa3eSPeter Avalos if (bufsize && nbuf[0]) {
176482c5fa3eSPeter Avalos nbuf[bufsize - 1] = '\0';
17656fca56fbSSascha Wildner memcpy(interp, nbuf, CAST(size_t, bufsize));
176682c5fa3eSPeter Avalos } else
17676fca56fbSSascha Wildner strlcpy(interp, "*empty*", sizeof(interp));
176879343712SPeter Avalos break;
176982c5fa3eSPeter Avalos case PT_NOTE:
1770c990e5baSDaniel Fojt if (ms->flags & MAGIC_MIME)
1771c990e5baSDaniel Fojt return 0;
1772327e51cbSPeter Avalos /*
1773327e51cbSPeter Avalos * This is a PT_NOTE section; loop through all the notes
1774327e51cbSPeter Avalos * in the section.
1775327e51cbSPeter Avalos */
1776327e51cbSPeter Avalos offset = 0;
1777327e51cbSPeter Avalos for (;;) {
17786fca56fbSSascha Wildner if (offset >= CAST(size_t, bufsize))
1779327e51cbSPeter Avalos break;
1780327e51cbSPeter Avalos offset = donote(ms, nbuf, offset,
17816fca56fbSSascha Wildner CAST(size_t, bufsize), clazz, swap, align,
1782c30bd091SSascha Wildner flags, notecount, fd, 0, 0, 0);
1783327e51cbSPeter Avalos if (offset == 0)
1784327e51cbSPeter Avalos break;
1785327e51cbSPeter Avalos }
1786327e51cbSPeter Avalos break;
1787327e51cbSPeter Avalos default:
1788c990e5baSDaniel Fojt if (ms->flags & MAGIC_MIME)
1789c990e5baSDaniel Fojt continue;
1790327e51cbSPeter Avalos break;
1791327e51cbSPeter Avalos }
1792327e51cbSPeter Avalos }
1793c990e5baSDaniel Fojt if (ms->flags & MAGIC_MIME)
1794c990e5baSDaniel Fojt return 0;
1795970935fdSSascha Wildner if (dynamic) {
1796970935fdSSascha Wildner if (pie && need == 0)
1797970935fdSSascha Wildner linking_style = "static-pie";
1798970935fdSSascha Wildner else
1799970935fdSSascha Wildner linking_style = "dynamically";
1800970935fdSSascha Wildner } else {
1801970935fdSSascha Wildner linking_style = "statically";
1802970935fdSSascha Wildner }
1803970935fdSSascha Wildner if (file_printf(ms, ", %s linked", linking_style) == -1)
1804327e51cbSPeter Avalos return -1;
180582c5fa3eSPeter Avalos if (interp[0])
1806614728caSSascha Wildner if (file_printf(ms, ", interpreter %s", file_printable(ms,
1807614728caSSascha Wildner ibuf, sizeof(ibuf), interp, sizeof(interp))) == -1)
180882c5fa3eSPeter Avalos return -1;
1809327e51cbSPeter Avalos return 0;
1810327e51cbSPeter Avalos }
1811327e51cbSPeter Avalos
1812327e51cbSPeter Avalos
1813327e51cbSPeter Avalos protected int
file_tryelf(struct magic_set * ms,const struct buffer * b)18146fca56fbSSascha Wildner file_tryelf(struct magic_set *ms, const struct buffer *b)
1815327e51cbSPeter Avalos {
18166fca56fbSSascha Wildner int fd = b->fd;
18176fca56fbSSascha Wildner const unsigned char *buf = CAST(const unsigned char *, b->fbuf);
18186fca56fbSSascha Wildner size_t nbytes = b->flen;
1819327e51cbSPeter Avalos union {
1820327e51cbSPeter Avalos int32_t l;
1821327e51cbSPeter Avalos char c[sizeof(int32_t)];
1822327e51cbSPeter Avalos } u;
182379343712SPeter Avalos int clazz;
1824327e51cbSPeter Avalos int swap;
1825327e51cbSPeter Avalos struct stat st;
18266fca56fbSSascha Wildner const struct stat *stp;
1827327e51cbSPeter Avalos off_t fsize;
1828327e51cbSPeter Avalos int flags = 0;
182979343712SPeter Avalos Elf32_Ehdr elf32hdr;
183079343712SPeter Avalos Elf64_Ehdr elf64hdr;
183182c5fa3eSPeter Avalos uint16_t type, phnum, shnum, notecount;
183279343712SPeter Avalos
1833c990e5baSDaniel Fojt if (ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION))
183479343712SPeter Avalos return 0;
183579343712SPeter Avalos /*
183679343712SPeter Avalos * ELF executables have multiple section headers in arbitrary
183779343712SPeter Avalos * file locations and thus file(1) cannot determine it from easily.
183879343712SPeter Avalos * Instead we traverse thru all section headers until a symbol table
183979343712SPeter Avalos * one is found or else the binary is stripped.
18406fca56fbSSascha Wildner * Return immediately if it's not ELF (so we avoid pipe2file unless
18416fca56fbSSascha Wildner * needed).
184279343712SPeter Avalos */
184379343712SPeter Avalos if (buf[EI_MAG0] != ELFMAG0
184479343712SPeter Avalos || (buf[EI_MAG1] != ELFMAG1 && buf[EI_MAG1] != OLFMAG1)
184579343712SPeter Avalos || buf[EI_MAG2] != ELFMAG2 || buf[EI_MAG3] != ELFMAG3)
184679343712SPeter Avalos return 0;
1847327e51cbSPeter Avalos
1848327e51cbSPeter Avalos /*
1849327e51cbSPeter Avalos * If we cannot seek, it must be a pipe, socket or fifo.
1850327e51cbSPeter Avalos */
18516fca56fbSSascha Wildner if((lseek(fd, CAST(off_t, 0), SEEK_SET) == CAST(off_t, -1))
18526fca56fbSSascha Wildner && (errno == ESPIPE))
1853327e51cbSPeter Avalos fd = file_pipe2file(ms, fd, buf, nbytes);
1854327e51cbSPeter Avalos
18556fca56fbSSascha Wildner if (fd == -1) {
18566fca56fbSSascha Wildner file_badread(ms);
18576fca56fbSSascha Wildner return -1;
18586fca56fbSSascha Wildner }
18596fca56fbSSascha Wildner
18606fca56fbSSascha Wildner stp = &b->st;
18616fca56fbSSascha Wildner /*
18626fca56fbSSascha Wildner * b->st.st_size != 0 if previous fstat() succeeded,
18636fca56fbSSascha Wildner * which is likely, we can avoid extra stat() call.
18646fca56fbSSascha Wildner */
18656fca56fbSSascha Wildner if (b->st.st_size == 0) {
18666fca56fbSSascha Wildner stp = &st;
1867327e51cbSPeter Avalos if (fstat(fd, &st) == -1) {
1868327e51cbSPeter Avalos file_badread(ms);
1869327e51cbSPeter Avalos return -1;
1870327e51cbSPeter Avalos }
18716fca56fbSSascha Wildner }
18726fca56fbSSascha Wildner if (S_ISREG(stp->st_mode) || stp->st_size != 0)
18736fca56fbSSascha Wildner fsize = stp->st_size;
187482c5fa3eSPeter Avalos else
187582c5fa3eSPeter Avalos fsize = SIZE_UNKNOWN;
1876327e51cbSPeter Avalos
187779343712SPeter Avalos clazz = buf[EI_CLASS];
1878327e51cbSPeter Avalos
187979343712SPeter Avalos switch (clazz) {
188079343712SPeter Avalos case ELFCLASS32:
188179343712SPeter Avalos #undef elf_getu
188279343712SPeter Avalos #define elf_getu(a, b) elf_getu32(a, b)
188379343712SPeter Avalos #undef elfhdr
188479343712SPeter Avalos #define elfhdr elf32hdr
188579343712SPeter Avalos #include "elfclass.h"
188679343712SPeter Avalos case ELFCLASS64:
188779343712SPeter Avalos #undef elf_getu
188879343712SPeter Avalos #define elf_getu(a, b) elf_getu64(a, b)
188979343712SPeter Avalos #undef elfhdr
189079343712SPeter Avalos #define elfhdr elf64hdr
189179343712SPeter Avalos #include "elfclass.h"
1892327e51cbSPeter Avalos default:
189379343712SPeter Avalos if (file_printf(ms, ", unknown class %d", clazz) == -1)
189479343712SPeter Avalos return -1;
1895327e51cbSPeter Avalos break;
1896327e51cbSPeter Avalos }
1897327e51cbSPeter Avalos return 0;
1898327e51cbSPeter Avalos }
1899327e51cbSPeter Avalos #endif
1900