Coverage Report

Created: 2025-12-11 07:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/file/src/readelf.c
Line
Count
Source
1
/*
2
 * Copyright (c) Christos Zoulas 2003.
3
 * All Rights Reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice immediately at the beginning of the file, without modification,
10
 *    this list of conditions, and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
19
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * SUCH DAMAGE.
26
 */
27
#include "file.h"
28
29
#ifndef lint
30
FILE_RCSID("@(#)$File: readelf.c,v 1.204 2025/06/27 16:57:44 christos Exp $")
31
#endif
32
33
#ifdef BUILTIN_ELF
34
#include <string.h>
35
#include <ctype.h>
36
#include <stdlib.h>
37
#include <stdarg.h>
38
#ifdef HAVE_UNISTD_H
39
#include <unistd.h>
40
#endif
41
42
#include "readelf.h"
43
#include "magic.h"
44
45
#ifdef  ELFCORE
46
file_private int dophn_core(struct magic_set *, int, int, int, off_t, int,
47
    size_t, off_t, int *, uint16_t *);
48
#endif
49
file_private int dophn_exec(struct magic_set *, int, int, int, off_t, int,
50
    size_t, off_t, int, int *, uint16_t *);
51
file_private int doshn(struct magic_set *, int, int, int, off_t, int, size_t,
52
    off_t, int, int, int *, uint16_t *);
53
file_private size_t donote(struct magic_set *, void *, size_t, size_t, int,
54
    int, size_t, int *, uint16_t *, int, off_t, int, off_t);
55
56
49.7k
#define ELF_ALIGN(a)  ((((a) + align - 1) / align) * align)
57
58
2.16k
#define isquote(c) (strchr("'\"`", (c)) != NULL)
59
60
file_private uint16_t getu16(int, uint16_t);
61
file_private uint32_t getu32(int, uint32_t);
62
file_private uint64_t getu64(int, uint64_t);
63
64
#define NBUFSIZE 2024
65
117k
#define SIZE_UNKNOWN  CAST(off_t, -1)
66
#define NAMEEQUALS(n, v) \
67
502k
    (namesz == sizeof(v) && memcmp(n, v, namesz) == 0)
68
69
__attribute__((__format__(__printf__, 2, 3)))
70
file_private int
71
elf_printf(struct magic_set *ms, const char *fmt, ...)
72
16.3k
{
73
16.3k
  va_list ap;
74
16.3k
  int rv;
75
76
16.3k
  if (ms->flags & MAGIC_MIME)
77
0
    return 1;
78
79
16.3k
  va_start(ap, fmt);
80
16.3k
  rv = file_vprintf(ms, fmt, ap);
81
16.3k
  va_end(ap);
82
16.3k
  return rv;
83
16.3k
}
84
file_private int
85
toomany(struct magic_set *ms, const char *name, uint16_t num)
86
109
{
87
109
  if (elf_printf(ms, ", too many %s (%u)", name, num) == -1)
88
0
    return -1;
89
109
  return 1;
90
109
}
91
92
file_private uint16_t
93
getu16(int swap, uint16_t value)
94
22.4k
{
95
22.4k
  union {
96
22.4k
    uint16_t ui;
97
22.4k
    char c[2];
98
22.4k
  } retval, tmpval;
99
100
22.4k
  if (swap) {
101
6.23k
    tmpval.ui = value;
102
103
6.23k
    retval.c[0] = tmpval.c[1];
104
6.23k
    retval.c[1] = tmpval.c[0];
105
106
6.23k
    return retval.ui;
107
6.23k
  } else
108
16.2k
    return value;
109
22.4k
}
110
111
file_private uint32_t
112
getu32(int swap, uint32_t value)
113
603k
{
114
603k
  union {
115
603k
    uint32_t ui;
116
603k
    char c[4];
117
603k
  } retval, tmpval;
118
119
603k
  if (swap) {
120
159k
    tmpval.ui = value;
121
122
159k
    retval.c[0] = tmpval.c[3];
123
159k
    retval.c[1] = tmpval.c[2];
124
159k
    retval.c[2] = tmpval.c[1];
125
159k
    retval.c[3] = tmpval.c[0];
126
127
159k
    return retval.ui;
128
159k
  } else
129
443k
    return value;
130
603k
}
131
132
file_private uint64_t
133
getu64(int swap, uint64_t value)
134
66.8k
{
135
66.8k
  union {
136
66.8k
    uint64_t ui;
137
66.8k
    char c[8];
138
66.8k
  } retval, tmpval;
139
140
66.8k
  if (swap) {
141
28.1k
    tmpval.ui = value;
142
143
28.1k
    retval.c[0] = tmpval.c[7];
144
28.1k
    retval.c[1] = tmpval.c[6];
145
28.1k
    retval.c[2] = tmpval.c[5];
146
28.1k
    retval.c[3] = tmpval.c[4];
147
28.1k
    retval.c[4] = tmpval.c[3];
148
28.1k
    retval.c[5] = tmpval.c[2];
149
28.1k
    retval.c[6] = tmpval.c[1];
150
28.1k
    retval.c[7] = tmpval.c[0];
151
152
28.1k
    return retval.ui;
153
28.1k
  } else
154
38.7k
    return value;
155
66.8k
}
156
157
14.4k
#define elf_getu16(swap, value) getu16(swap, value)
158
452k
#define elf_getu32(swap, value) getu32(swap, value)
159
11.1k
#define elf_getu64(swap, value) getu64(swap, value)
160
161
64.9k
#define xsh_addr  (clazz == ELFCLASS32      \
162
64.9k
       ? CAST(void *, &sh32)     \
163
64.9k
       : CAST(void *, &sh64))
164
66.3k
#define xsh_sizeof  (clazz == ELFCLASS32      \
165
66.3k
       ? sizeof(sh32)        \
166
66.3k
       : sizeof(sh64))
167
9.10k
#define xsh_size  CAST(size_t, (clazz == ELFCLASS32 \
168
9.10k
       ? elf_getu32(swap, sh32.sh_size) \
169
9.10k
       : elf_getu64(swap, sh64.sh_size)))
170
66.5k
#define xsh_offset  CAST(off_t, (clazz == ELFCLASS32  \
171
66.5k
       ? elf_getu32(swap, sh32.sh_offset) \
172
66.5k
       : elf_getu64(swap, sh64.sh_offset)))
173
100k
#define xsh_type  (clazz == ELFCLASS32      \
174
100k
       ? elf_getu32(swap, sh32.sh_type)  \
175
100k
       : elf_getu32(swap, sh64.sh_type))
176
63.9k
#define xsh_name      (clazz == ELFCLASS32      \
177
63.9k
       ? elf_getu32(swap, sh32.sh_name)  \
178
63.9k
       : elf_getu32(swap, sh64.sh_name))
179
180
65.9k
#define xph_addr  (clazz == ELFCLASS32      \
181
65.9k
       ? CAST(void *, &ph32)     \
182
65.9k
       : CAST(void *, &ph64))
183
87.6k
#define xph_sizeof  (clazz == ELFCLASS32      \
184
87.6k
       ? sizeof(ph32)        \
185
87.6k
       : sizeof(ph64))
186
52.9k
#define xph_type  (clazz == ELFCLASS32      \
187
52.9k
       ? elf_getu32(swap, ph32.p_type) \
188
52.9k
       : elf_getu32(swap, ph64.p_type))
189
68.5k
#define xph_offset  CAST(off_t, (clazz == ELFCLASS32  \
190
68.5k
       ? elf_getu32(swap, ph32.p_offset)  \
191
68.5k
       : elf_getu64(swap, ph64.p_offset)))
192
4.25k
#define xph_align CAST(size_t, (clazz == ELFCLASS32 \
193
4.25k
       ? CAST(off_t, (ph32.p_align ?    \
194
4.25k
          elf_getu32(swap, ph32.p_align) : 4))\
195
4.25k
       : CAST(off_t, (ph64.p_align ?    \
196
4.25k
          elf_getu64(swap, ph64.p_align) : 4))))
197
13.1k
#define xph_vaddr CAST(size_t, (clazz == ELFCLASS32 \
198
13.1k
       ? CAST(off_t, (ph32.p_vaddr ?    \
199
13.1k
          elf_getu32(swap, ph32.p_vaddr) : 4))\
200
13.1k
       : CAST(off_t, (ph64.p_vaddr ?    \
201
13.1k
          elf_getu64(swap, ph64.p_vaddr) : 4))))
202
21.4k
#define xph_filesz  CAST(size_t, (clazz == ELFCLASS32 \
203
24.9k
       ? elf_getu32(swap, ph32.p_filesz)  \
204
24.9k
       : elf_getu64(swap, ph64.p_filesz)))
205
#define xph_memsz CAST(size_t, ((clazz == ELFCLASS32  \
206
       ? elf_getu32(swap, ph32.p_memsz) \
207
       : elf_getu64(swap, ph64.p_memsz))))
208
28.1k
#define xnh_addr  (clazz == ELFCLASS32      \
209
28.1k
       ? CAST(void *, &nh32)     \
210
28.1k
       : CAST(void *, &nh64))
211
89.3k
#define xnh_sizeof  (clazz == ELFCLASS32      \
212
89.3k
       ? sizeof(nh32)        \
213
89.3k
       : sizeof(nh64))
214
131k
#define xnh_type  (clazz == ELFCLASS32      \
215
131k
       ? elf_getu32(swap, nh32.n_type) \
216
131k
       : elf_getu32(swap, nh64.n_type))
217
28.1k
#define xnh_namesz  (clazz == ELFCLASS32      \
218
28.1k
       ? elf_getu32(swap, nh32.n_namesz) \
219
28.1k
       : elf_getu32(swap, nh64.n_namesz))
220
28.1k
#define xnh_descsz  (clazz == ELFCLASS32      \
221
28.1k
       ? elf_getu32(swap, nh32.n_descsz) \
222
28.1k
       : elf_getu32(swap, nh64.n_descsz))
223
224
41.5k
#define xdh_addr  (clazz == ELFCLASS32      \
225
41.5k
       ? CAST(void *, &dh32)     \
226
41.5k
       : CAST(void *, &dh64))
227
126k
#define xdh_sizeof  (clazz == ELFCLASS32      \
228
126k
       ? sizeof(dh32)        \
229
126k
       : sizeof(dh64))
230
41.5k
#define xdh_tag   (clazz == ELFCLASS32      \
231
41.5k
       ? elf_getu32(swap, dh32.d_tag)    \
232
41.5k
       : elf_getu64(swap, dh64.d_tag))
233
2.00k
#define xdh_val   (clazz == ELFCLASS32      \
234
2.00k
       ? elf_getu32(swap, dh32.d_un.d_val) \
235
2.00k
       : elf_getu64(swap, dh64.d_un.d_val))
236
237
5.76k
#define xcap_addr (clazz == ELFCLASS32      \
238
5.76k
       ? CAST(void *, &cap32)      \
239
5.76k
       : CAST(void *, &cap64))
240
13.0k
#define xcap_sizeof (clazz == ELFCLASS32      \
241
13.0k
       ? sizeof(cap32)      \
242
13.0k
       : sizeof(cap64))
243
5.76k
#define xcap_tag  (clazz == ELFCLASS32      \
244
5.76k
       ? elf_getu32(swap, cap32.c_tag) \
245
5.76k
       : elf_getu64(swap, cap64.c_tag))
246
1.86k
#define xcap_val  (clazz == ELFCLASS32      \
247
1.86k
       ? elf_getu32(swap, cap32.c_un.c_val)  \
248
1.86k
       : elf_getu64(swap, cap64.c_un.c_val))
249
250
4.90k
#define xauxv_addr  (clazz == ELFCLASS32      \
251
4.90k
       ? CAST(void *, &auxv32)   \
252
4.90k
       : CAST(void *, &auxv64))
253
26.2k
#define xauxv_sizeof  (clazz == ELFCLASS32      \
254
26.2k
       ? sizeof(auxv32)      \
255
26.2k
       : sizeof(auxv64))
256
4.88k
#define xauxv_type  (clazz == ELFCLASS32      \
257
4.88k
       ? elf_getu32(swap, auxv32.a_type) \
258
4.88k
       : elf_getu64(swap, auxv64.a_type))
259
1.76k
#define xauxv_val (clazz == ELFCLASS32      \
260
1.76k
       ? elf_getu32(swap, auxv32.a_v)    \
261
1.76k
       : elf_getu64(swap, auxv64.a_v))
262
263
20.2k
#define prpsoffsets(i)  (clazz == ELFCLASS32      \
264
20.2k
       ? prpsoffsets32[i]      \
265
20.2k
       : prpsoffsets64[i])
266
267
#ifdef ELFCORE
268
/*
269
 * Try larger offsets first to avoid false matches
270
 * from earlier data that happen to look like strings.
271
 */
272
static const size_t prpsoffsets32[] = {
273
#ifdef USE_NT_PSINFO
274
  104,    /* SunOS 5.x (command line) */
275
  88,   /* SunOS 5.x (short name) */
276
#endif /* USE_NT_PSINFO */
277
278
  100,    /* SunOS 5.x (command line) */
279
  84,   /* SunOS 5.x (short name) */
280
281
  44,   /* Linux (command line) */
282
  28,   /* Linux (short name) */
283
284
  48,   /* Linux PowerPC (command line) */
285
  32,   /* Linux PowerPC (short name) */
286
287
  8,    /* FreeBSD */
288
};
289
290
static const size_t prpsoffsets64[] = {
291
#ifdef USE_NT_PSINFO
292
  152,    /* SunOS 5.x (command line) */
293
  136,    /* SunOS 5.x (short name) */
294
#endif /* USE_NT_PSINFO */
295
296
  136,    /* SunOS 5.x, 64-bit (command line) */
297
  120,    /* SunOS 5.x, 64-bit (short name) */
298
299
  56,   /* Linux (command line) */
300
  40,             /* Linux (tested on core from 2.4.x, short name) */
301
302
  16,   /* FreeBSD, 64-bit */
303
};
304
305
17.1k
#define NOFFSETS32  __arraycount(prpsoffsets32)
306
1.20k
#define NOFFSETS64  __arraycount(prpsoffsets64)
307
308
18.3k
#define NOFFSETS  (clazz == ELFCLASS32 ? NOFFSETS32 : NOFFSETS64)
309
310
/*
311
 * Look through the program headers of an executable image, searching
312
 * for a PT_NOTE section of type NT_PRPSINFO, with a name "CORE" or
313
 * "FreeBSD"; if one is found, try looking in various places in its
314
 * contents for a 16-character string containing only printable
315
 * characters - if found, that string should be the name of the program
316
 * that dropped core.  Note: right after that 16-character string is,
317
 * at least in SunOS 5.x (and possibly other SVR4-flavored systems) and
318
 * Linux, a longer string (80 characters, in 5.x, probably other
319
 * SVR4-flavored systems, and Linux) containing the start of the
320
 * command line for that program.
321
 *
322
 * SunOS 5.x core files contain two PT_NOTE sections, with the types
323
 * NT_PRPSINFO (old) and NT_PSINFO (new).  These structs contain the
324
 * same info about the command name and command line, so it probably
325
 * isn't worthwhile to look for NT_PSINFO, but the offsets are provided
326
 * above (see USE_NT_PSINFO), in case we ever decide to do so.  The
327
 * NT_PRPSINFO and NT_PSINFO sections are always in order and adjacent;
328
 * the SunOS 5.x file command relies on this (and prefers the latter).
329
 *
330
 * The signal number probably appears in a section of type NT_PRSTATUS,
331
 * but that's also rather OS-dependent, in ways that are harder to
332
 * dissect with heuristics, so I'm not bothering with the signal number.
333
 * (I suppose the signal number could be of interest in situations where
334
 * you don't have the binary of the program that dropped core; if you
335
 * *do* have that binary, the debugger will probably tell you what
336
 * signal it was.)
337
 */
338
339
4.05k
#define OS_STYLE_SVR4   0
340
808
#define OS_STYLE_FREEBSD  1
341
582
#define OS_STYLE_NETBSD   2
342
343
file_private const char os_style_names[][8] = {
344
  "SVR4",
345
  "FreeBSD",
346
  "NetBSD",
347
};
348
349
3.67k
#define FLAGS_CORE_STYLE    0x0003
350
351
21.8k
#define FLAGS_DID_CORE      0x0004
352
23.1k
#define FLAGS_DID_OS_NOTE   0x0008
353
22.8k
#define FLAGS_DID_BUILD_ID    0x0010
354
45.8k
#define FLAGS_DID_CORE_STYLE    0x0020
355
21.9k
#define FLAGS_DID_NETBSD_PAX    0x0040
356
201
#define FLAGS_DID_NETBSD_MARCH    0x0080
357
84
#define FLAGS_DID_NETBSD_CMODEL   0x0100
358
208
#define FLAGS_DID_NETBSD_EMULATION  0x0200
359
1.06k
#define FLAGS_DID_NETBSD_UNKNOWN  0x0400
360
21.8k
#define FLAGS_DID_ANDROID_MEMTAG  0x0800
361
47.6k
#define FLAGS_IS_CORE     0x1000
362
22.3k
#define FLAGS_DID_AUXV      0x2000
363
364
file_private int
365
dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
366
    int num, size_t size, off_t fsize, int *flags, uint16_t *notecount)
367
2.37k
{
368
2.37k
  Elf32_Phdr ph32;
369
2.37k
  Elf64_Phdr ph64;
370
2.37k
  size_t offset, len;
371
2.37k
  unsigned char nbuf[NBUFSIZE];
372
2.37k
  ssize_t bufsize;
373
2.37k
  off_t ph_off = off, offs;
374
2.37k
  int ph_num = num;
375
376
2.37k
  if (ms->flags & MAGIC_MIME)
377
0
    return 0;
378
379
2.37k
  if (num == 0) {
380
3
    if (elf_printf(ms, ", no program header") == -1)
381
0
      return -1;
382
3
    return 0;
383
3
  }
384
2.36k
  if (size != xph_sizeof) {
385
26
    if (elf_printf(ms, ", corrupted program header size") == -1)
386
0
      return -1;
387
26
    return 0;
388
26
  }
389
390
  /*
391
   * Loop through all the program headers.
392
   */
393
19.4k
  for ( ; num; num--) {
394
19.3k
    if (pread(fd, xph_addr, xph_sizeof, off) <
395
19.3k
        CAST(ssize_t, xph_sizeof)) {
396
2.22k
      if (elf_printf(ms, 
397
2.22k
          ", can't read elf program headers at %jd",
398
2.22k
          (intmax_t)off) == -1)
399
0
        return -1;
400
2.22k
      return 0;
401
2.22k
    }
402
17.1k
    off += size;
403
404
17.1k
    if (fsize != SIZE_UNKNOWN && xph_offset > fsize) {
405
      /* Perhaps warn here */
406
5.79k
      continue;
407
5.79k
    }
408
409
11.3k
    if (xph_type != PT_NOTE)
410
5.31k
      continue;
411
412
    /*
413
     * This is a PT_NOTE section; loop through all the notes
414
     * in the section.
415
     */
416
6.03k
    len = xph_filesz < sizeof(nbuf) ? xph_filesz : sizeof(nbuf);
417
6.03k
    offs = xph_offset;
418
6.03k
    if ((bufsize = pread(fd, nbuf, len, offs)) == -1) {
419
39
      if (elf_printf(ms, " can't read note section at %jd",
420
39
          (intmax_t)offs) == -1)
421
0
        return -1;
422
39
      return 0;
423
39
    }
424
5.99k
    offset = 0;
425
28.8k
    for (;;) {
426
28.8k
      if (offset >= CAST(size_t, bufsize))
427
4.97k
        break;
428
23.8k
      offset = donote(ms, nbuf, offset, CAST(size_t, bufsize),
429
23.8k
          clazz, swap, 4, flags, notecount, fd, ph_off,
430
23.8k
          ph_num, fsize);
431
23.8k
      if (offset == 0)
432
1.02k
        break;
433
434
23.8k
    }
435
5.99k
  }
436
79
  return 0;
437
2.34k
}
438
#endif
439
440
static int
441
do_note_netbsd_version(struct magic_set *ms, int swap, void *v)
442
76
{
443
76
  uint32_t desc;
444
76
  memcpy(&desc, v, sizeof(desc));
445
76
  desc = elf_getu32(swap, desc);
446
447
76
  if (elf_printf(ms, ", for NetBSD") == -1)
448
0
    return -1;
449
  /*
450
   * The version number used to be stuck as 199905, and was thus
451
   * basically content-free.  Newer versions of NetBSD have fixed
452
   * this and now use the encoding of __NetBSD_Version__:
453
   *
454
   *  MMmmrrpp00
455
   *
456
   * M = major version
457
   * m = minor version
458
   * r = release ["",A-Z,Z[A-Z] but numeric]
459
   * p = patchlevel
460
   */
461
76
  if (desc > 100000000U) {
462
50
    uint32_t ver_patch = (desc / 100) % 100;
463
50
    uint32_t ver_rel = (desc / 10000) % 100;
464
50
    uint32_t ver_min = (desc / 1000000) % 100;
465
50
    uint32_t ver_maj = desc / 100000000;
466
467
50
    if (elf_printf(ms, " %u.%u", ver_maj, ver_min) == -1)
468
0
      return -1;
469
50
    if (ver_maj >= 9) {
470
23
      ver_patch += 100 * ver_rel;
471
23
      ver_rel = 0;
472
23
    }
473
50
    if (ver_rel == 0 && ver_patch != 0) {
474
22
      if (elf_printf(ms, ".%u", ver_patch) == -1)
475
0
        return -1;
476
28
    } else if (ver_rel != 0) {
477
78
      while (ver_rel > 26) {
478
51
        if (elf_printf(ms, "Z") == -1)
479
0
          return -1;
480
51
        ver_rel -= 26;
481
51
      }
482
27
      if (elf_printf(ms, "%c", 'A' + ver_rel - 1) == -1)
483
0
        return -1;
484
27
    }
485
50
  }
486
76
  return 0;
487
76
}
488
489
static int
490
do_note_freebsd_version(struct magic_set *ms, int swap, void *v)
491
60
{
492
60
  uint32_t desc;
493
494
60
  memcpy(&desc, v, sizeof(desc));
495
60
  desc = elf_getu32(swap, desc);
496
60
  if (elf_printf(ms, ", for FreeBSD") == -1)
497
0
    return -1;
498
499
  /*
500
   * Contents is __FreeBSD_version, whose relation to OS
501
   * versions is defined by a huge table in the Porter's
502
   * Handbook.  This is the general scheme:
503
   *
504
   * Releases:
505
   *  Mmp000 (before 4.10)
506
   *  Mmi0p0 (before 5.0)
507
   *  Mmm0p0
508
   *
509
   * Development branches:
510
   *  Mmpxxx (before 4.6)
511
   *  Mmp1xx (before 4.10)
512
   *  Mmi1xx (before 5.0)
513
   *  M000xx (pre-M.0)
514
   *  Mmm1xx
515
   *
516
   * M = major version
517
   * m = minor version
518
   * i = minor version increment (491000 -> 4.10)
519
   * p = patchlevel
520
   * x = revision
521
   *
522
   * The first release of FreeBSD to use ELF by default
523
   * was version 3.0.
524
   */
525
60
  if (desc == 460002) {
526
1
    if (elf_printf(ms, " 4.6.2") == -1)
527
0
      return -1;
528
59
  } else if (desc < 460100) {
529
25
    if (elf_printf(ms, " %d.%d", desc / 100000,
530
25
        desc / 10000 % 10) == -1)
531
0
      return -1;
532
25
    if (desc / 1000 % 10 > 0)
533
18
      if (elf_printf(ms, ".%d", desc / 1000 % 10) == -1)
534
0
        return -1;
535
25
    if ((desc % 1000 > 0) || (desc % 100000 == 0))
536
24
      if (elf_printf(ms, " (%d)", desc) == -1)
537
0
        return -1;
538
34
  } else if (desc < 500000) {
539
5
    if (elf_printf(ms, " %d.%d", desc / 100000,
540
5
        desc / 10000 % 10 + desc / 1000 % 10) == -1)
541
0
      return -1;
542
5
    if (desc / 100 % 10 > 0) {
543
3
      if (elf_printf(ms, " (%d)", desc) == -1)
544
0
        return -1;
545
3
    } else if (desc / 10 % 10 > 0) {
546
1
      if (elf_printf(ms, ".%d", desc / 10 % 10) == -1)
547
0
        return -1;
548
1
    }
549
29
  } else {
550
29
    if (elf_printf(ms, " %d.%d", desc / 100000,
551
29
        desc / 1000 % 100) == -1)
552
0
      return -1;
553
29
    if ((desc / 100 % 10 > 0) ||
554
26
        (desc % 100000 / 100 == 0)) {
555
26
      if (elf_printf(ms, " (%d)", desc) == -1)
556
0
        return -1;
557
26
    } else if (desc / 10 % 10 > 0) {
558
1
      if (elf_printf(ms, ".%d", desc / 10 % 10) == -1)
559
0
        return -1;
560
1
    }
561
29
  }
562
60
  return 0;
563
60
}
564
565
file_private int
566
/*ARGSUSED*/
567
do_bid_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
568
    int swap __attribute__((__unused__)), uint32_t namesz, uint32_t descsz,
569
    size_t noff, size_t doff, int *flags)
570
22.5k
{
571
22.5k
  if (NAMEEQUALS(RCAST(char *, &nbuf[noff]), "GNU") &&
572
945
      type == NT_GNU_BUILD_ID && (descsz >= 4 && descsz <= 20)) {
573
15
    uint8_t desc[20];
574
15
    const char *btype;
575
15
    uint32_t i;
576
15
    *flags |= FLAGS_DID_BUILD_ID;
577
15
    switch (descsz) {
578
1
    case 8:
579
1
        btype = "xxHash";
580
1
        break;
581
9
    case 16:
582
9
        btype = "md5/uuid";
583
9
        break;
584
1
    case 20:
585
1
        btype = "sha1";
586
1
        break;
587
4
    default:
588
4
        btype = "unknown";
589
4
        break;
590
15
    }
591
15
    if (elf_printf(ms, ", BuildID[%s]=", btype) == -1)
592
0
      return -1;
593
15
    memcpy(desc, &nbuf[doff], descsz);
594
230
    for (i = 0; i < descsz; i++)
595
215
        if (elf_printf(ms, "%02x", desc[i]) == -1)
596
0
      return -1;
597
15
    return 1;
598
15
  }
599
22.5k
  if (namesz == 4 && memcmp(RCAST(char *, &nbuf[noff]), "Go", 3) == 0 &&
600
1.82k
      type == NT_GO_BUILD_ID && descsz < 128) {
601
929
    char buf[256];
602
929
    if (elf_printf(ms, ", Go BuildID=%s",
603
929
        file_copystr(buf, sizeof(buf), descsz,
604
929
        RCAST(const char *, &nbuf[doff]))) == -1)
605
0
      return -1;
606
929
    return 1;
607
929
  }
608
21.6k
  return 0;
609
22.5k
}
610
611
file_private int
612
do_os_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
613
    int swap, uint32_t namesz, uint32_t descsz,
614
    size_t noff, size_t doff, int *flags)
615
22.2k
{
616
22.2k
  const char *name = RCAST(const char *, &nbuf[noff]);
617
618
22.2k
  if (NAMEEQUALS(name, "SuSE") && type == NT_GNU_VERSION && descsz == 2) {
619
1
    *flags |= FLAGS_DID_OS_NOTE;
620
1
    if (elf_printf(ms, ", for SuSE %d.%d", nbuf[doff],
621
1
        nbuf[doff + 1]) == -1)
622
0
        return -1;
623
1
      return 1;
624
1
  }
625
626
22.2k
  if (NAMEEQUALS(name, "GNU") && type == NT_GNU_VERSION && descsz == 16) {
627
13
    uint32_t desc[4];
628
13
    memcpy(desc, &nbuf[doff], sizeof(desc));
629
630
13
    *flags |= FLAGS_DID_OS_NOTE;
631
13
    if (elf_printf(ms, ", for GNU/") == -1)
632
0
      return -1;
633
13
    switch (elf_getu32(swap, desc[0])) {
634
1
    case GNU_OS_LINUX:
635
1
      if (elf_printf(ms, "Linux") == -1)
636
0
        return -1;
637
1
      break;
638
1
    case GNU_OS_HURD:
639
1
      if (elf_printf(ms, "Hurd") == -1)
640
0
        return -1;
641
1
      break;
642
1
    case GNU_OS_SOLARIS:
643
1
      if (elf_printf(ms, "Solaris") == -1)
644
0
        return -1;
645
1
      break;
646
1
    case GNU_OS_KFREEBSD:
647
1
      if (elf_printf(ms, "kFreeBSD") == -1)
648
0
        return -1;
649
1
      break;
650
1
    case GNU_OS_KNETBSD:
651
1
      if (elf_printf(ms, "kNetBSD") == -1)
652
0
        return -1;
653
1
      break;
654
8
    default:
655
8
      if (elf_printf(ms, "<unknown>") == -1)
656
0
        return -1;
657
13
    }
658
13
    if (elf_printf(ms, " %d.%d.%d", elf_getu32(swap, desc[1]),
659
13
        elf_getu32(swap, desc[2]), elf_getu32(swap, desc[3])) == -1)
660
0
      return -1;
661
13
    return 1;
662
13
  }
663
664
22.2k
  if (NAMEEQUALS(name, "NetBSD") &&
665
1.92k
      type == NT_NETBSD_VERSION && descsz == 4) {
666
76
    *flags |= FLAGS_DID_OS_NOTE;
667
76
    if (do_note_netbsd_version(ms, swap, &nbuf[doff]) == -1)
668
0
      return -1;
669
76
    return 1;
670
76
  }
671
672
22.1k
  if (NAMEEQUALS(name, "FreeBSD") &&
673
464
      type == NT_FREEBSD_VERSION && descsz == 4) {
674
60
    *flags |= FLAGS_DID_OS_NOTE;
675
60
    if (do_note_freebsd_version(ms, swap, &nbuf[doff])
676
60
        == -1)
677
0
      return -1;
678
60
    return 1;
679
60
  }
680
681
22.0k
  if (NAMEEQUALS(name, "OpenBSD") &&
682
299
      type == NT_OPENBSD_VERSION && descsz == 4) {
683
1
    *flags |= FLAGS_DID_OS_NOTE;
684
1
    if (elf_printf(ms, ", for OpenBSD") == -1)
685
0
      return -1;
686
    /* Content of note is always 0 */
687
1
    return 1;
688
1
  }
689
690
22.0k
  if (NAMEEQUALS(name, "DragonFly") &&
691
183
      type == NT_DRAGONFLY_VERSION && descsz == 4) {
692
2
    uint32_t desc;
693
2
    *flags |= FLAGS_DID_OS_NOTE;
694
2
    if (elf_printf(ms, ", for DragonFly") == -1)
695
0
      return -1;
696
2
    memcpy(&desc, &nbuf[doff], sizeof(desc));
697
2
    desc = elf_getu32(swap, desc);
698
2
    if (elf_printf(ms, " %d.%d.%d", desc / 100000,
699
2
        desc / 10000 % 10, desc % 10000) == -1)
700
0
      return -1;
701
2
    return 1;
702
2
  }
703
704
22.0k
  if (NAMEEQUALS(name, "Android") &&
705
346
      type == NT_ANDROID_VERSION && descsz >= 4) {
706
15
    uint32_t api_level;
707
15
    *flags |= FLAGS_DID_OS_NOTE;
708
15
    memcpy(&api_level, &nbuf[doff], sizeof(api_level));
709
15
    api_level = elf_getu32(swap, api_level);
710
15
    if (elf_printf(ms, ", for Android %d", api_level) == -1)
711
0
      return -1;
712
    /*
713
     * NDK r14 and later also include details of the NDK that
714
     * built the binary. OS binaries (or binaries built by older
715
     * NDKs) don't have this. The NDK release and build number
716
     * are both 64-byte strings.
717
     */
718
15
    if (descsz >= 4 + 64 + 64) {
719
1
      if (elf_printf(ms, ", built by NDK %.64s (%.64s)",
720
1
          &nbuf[doff + 4], &nbuf[doff + 4 + 64]) == -1)
721
0
        return -1;
722
1
    }
723
15
  }
724
725
22.0k
  return 0;
726
22.0k
}
727
728
file_private int
729
do_pax_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
730
    int swap, uint32_t namesz, uint32_t descsz,
731
    size_t noff, size_t doff, int *flags)
732
21.4k
{
733
21.4k
  const char *name = RCAST(const char *, &nbuf[noff]);
734
735
21.4k
  if (NAMEEQUALS(name, "PaX") && type == NT_NETBSD_PAX && descsz == 4) {
736
54
    static const char *pax[] = {
737
54
        "+mprotect",
738
54
        "-mprotect",
739
54
        "+segvguard",
740
54
        "-segvguard",
741
54
        "+ASLR",
742
54
        "-ASLR",
743
54
    };
744
54
    uint32_t desc;
745
54
    size_t i;
746
54
    int did = 0;
747
748
54
    *flags |= FLAGS_DID_NETBSD_PAX;
749
54
    memcpy(&desc, &nbuf[doff], sizeof(desc));
750
54
    desc = elf_getu32(swap, desc);
751
752
54
    if (desc && elf_printf(ms, ", PaX: ") == -1)
753
0
      return -1;
754
755
378
    for (i = 0; i < __arraycount(pax); i++) {
756
324
      if (((1 << CAST(int, i)) & desc) == 0)
757
195
        continue;
758
129
      if (elf_printf(ms, "%s%s", did++ ? "," : "",
759
129
          pax[i]) == -1)
760
0
        return -1;
761
129
    }
762
54
    return 1;
763
54
  }
764
21.3k
  return 0;
765
21.4k
}
766
767
file_private int
768
do_memtag_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
769
    int swap, uint32_t namesz, uint32_t descsz,
770
    size_t noff, size_t doff, int *flags)
771
21.6k
{
772
21.6k
  const char *name = RCAST(const char *, &nbuf[noff]);
773
774
21.6k
  if (NAMEEQUALS(name, "Android") &&
775
337
      type == NT_ANDROID_MEMTAG && descsz == 4) {
776
54
    static const char *memtag[] = {
777
54
        "none",
778
54
        "async",
779
54
        "sync",
780
54
        "heap",
781
54
        "stack",
782
54
    };
783
54
    uint32_t desc;
784
54
    size_t i;
785
54
    int did = 0;
786
787
54
    *flags |= FLAGS_DID_ANDROID_MEMTAG;
788
54
    memcpy(&desc, &nbuf[doff], sizeof(desc));
789
54
    desc = elf_getu32(swap, desc);
790
791
54
    if (desc && elf_printf(ms, ", Android Memtag: ") == -1)
792
0
      return -1;
793
794
324
    for (i = 0; i < __arraycount(memtag); i++) {
795
270
      if (((1 << CAST(int, i)) & desc) == 0)
796
149
        continue;
797
121
      if (elf_printf(ms, "%s%s", did++ ? "," : "",
798
121
          memtag[i]) == -1)
799
0
        return -1;
800
121
    }
801
54
    return 1;
802
54
  }
803
21.5k
  return 0;
804
21.6k
}
805
806
file_private int
807
do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
808
    int swap, uint32_t namesz, uint32_t descsz,
809
    size_t noff, size_t doff, int *flags, size_t size, int clazz)
810
20.6k
{
811
20.6k
#ifdef ELFCORE
812
20.6k
  char buf[256];
813
20.6k
  const char *name = RCAST(const char *, &nbuf[noff]);
814
815
20.6k
  int os_style = -1;
816
  /*
817
   * Sigh.  The 2.0.36 kernel in Debian 2.1, at
818
   * least, doesn't correctly implement name
819
   * sections, in core dumps, as specified by
820
   * the "Program Linking" section of "UNIX(R) System
821
   * V Release 4 Programmer's Guide: ANSI C and
822
   * Programming Support Tools", because my copy
823
   * clearly says "The first 'namesz' bytes in 'name'
824
   * contain a *null-terminated* [emphasis mine]
825
   * character representation of the entry's owner
826
   * or originator", but the 2.0.36 kernel code
827
   * doesn't include the terminating null in the
828
   * name....
829
   */
830
20.6k
  if ((namesz == 4 && memcmp(name, "CORE", 4) == 0) ||
831
18.9k
      NAMEEQUALS(name, "CORE")) {
832
1.73k
    os_style = OS_STYLE_SVR4;
833
1.73k
  }
834
835
20.6k
  if (NAMEEQUALS(name, "FreeBSD")) {
836
404
    os_style = OS_STYLE_FREEBSD;
837
404
  }
838
839
20.6k
  if ((namesz >= 11 && memcmp(name, "NetBSD-CORE", 11) == 0)) {
840
291
    os_style = OS_STYLE_NETBSD;
841
291
  }
842
843
20.6k
  if (os_style != -1 && (*flags & FLAGS_DID_CORE_STYLE) == 0) {
844
836
    if (elf_printf(ms, ", %s-style", os_style_names[os_style])
845
836
        == -1)
846
0
      return -1;
847
836
    *flags |= FLAGS_DID_CORE_STYLE;
848
836
    *flags |= os_style;
849
836
  }
850
851
20.6k
  switch (os_style) {
852
291
  case OS_STYLE_NETBSD:
853
291
    if (type == NT_NETBSD_CORE_PROCINFO) {
854
6
      char sbuf[512];
855
6
      struct NetBSD_elfcore_procinfo pi;
856
6
      memset(&pi, 0, sizeof(pi));
857
6
      memcpy(&pi, nbuf + doff, MIN(descsz, sizeof(pi)));
858
859
6
      if (elf_printf(ms, ", from '%.31s', pid=%u, uid=%u, "
860
6
          "gid=%u, nlwps=%u, lwp=%u (signal %u/code %u)",
861
6
          file_printable(ms, sbuf, sizeof(sbuf),
862
6
          RCAST(char *, pi.cpi_name), sizeof(pi.cpi_name)),
863
6
          elf_getu32(swap, CAST(uint32_t, pi.cpi_pid)),
864
6
          elf_getu32(swap, pi.cpi_euid),
865
6
          elf_getu32(swap, pi.cpi_egid),
866
6
          elf_getu32(swap, pi.cpi_nlwps),
867
6
          elf_getu32(swap, CAST(uint32_t, pi.cpi_siglwp)),
868
6
          elf_getu32(swap, pi.cpi_signo),
869
6
          elf_getu32(swap, pi.cpi_sigcode)) == -1)
870
0
        return -1;
871
872
6
      *flags |= FLAGS_DID_CORE;
873
6
      return 1;
874
6
    }
875
285
    break;
876
877
404
  case OS_STYLE_FREEBSD:
878
404
    if (type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) {
879
9
      size_t argoff, pidoff;
880
881
9
      if (clazz == ELFCLASS32)
882
7
        argoff = 4 + 4 + 17;
883
2
      else
884
2
        argoff = 4 + 4 + 8 + 17;
885
9
      if (elf_printf(ms, ", from '%.80s'", nbuf + doff +
886
9
          argoff) == -1)
887
0
        return -1;
888
9
      pidoff = argoff + 81 + 2;
889
9
      if (doff + pidoff + 4 <= size) {
890
2
        if (elf_printf(ms, ", pid=%u",
891
2
            elf_getu32(swap, *RCAST(uint32_t *, (nbuf +
892
2
            doff + pidoff)))) == -1)
893
0
          return -1;
894
2
      }
895
9
      *flags |= FLAGS_DID_CORE;
896
9
    }          
897
404
    break;
898
899
19.9k
  default:
900
19.9k
    if (type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) {
901
2.34k
      size_t i, j;
902
2.34k
      unsigned char c;
903
      /*
904
       * Extract the program name.  We assume
905
       * it to be 16 characters (that's what it
906
       * is in SunOS 5.x and Linux).
907
       *
908
       * Unfortunately, it's at a different offset
909
       * in various OSes, so try multiple offsets.
910
       * If the characters aren't all printable,
911
       * reject it.
912
       */
913
18.1k
      for (i = 0; i < NOFFSETS; i++) {
914
15.8k
        unsigned char *cname, *cp;
915
15.8k
        size_t reloffset = prpsoffsets(i);
916
15.8k
        size_t noffset = doff + reloffset;
917
15.8k
        size_t k;
918
17.5k
        for (j = 0; j < 16; j++, noffset++,
919
17.5k
            reloffset++) {
920
          /*
921
           * Make sure we're not past
922
           * the end of the buffer; if
923
           * we are, just give up.
924
           */
925
17.5k
          if (noffset >= size)
926
3.09k
            goto tryanother;
927
928
          /*
929
           * Make sure we're not past
930
           * the end of the contents;
931
           * if we are, this obviously
932
           * isn't the right offset.
933
           */
934
14.4k
          if (reloffset >= descsz)
935
9.95k
            goto tryanother;
936
937
4.52k
          c = nbuf[noffset];
938
4.52k
          if (c == '\0') {
939
            /*
940
             * A '\0' at the
941
             * beginning is
942
             * obviously wrong.
943
             * Any other '\0'
944
             * means we're done.
945
             */
946
1.15k
            if (j == 0)
947
1.09k
              goto tryanother;
948
58
            else
949
58
              break;
950
3.36k
          } else {
951
            /*
952
             * A nonprintable
953
             * character is also
954
             * wrong.
955
             */
956
3.36k
            if (!isprint(c) || isquote(c))
957
1.65k
              goto tryanother;
958
3.36k
          }
959
4.52k
        }
960
        /*
961
         * Well, that worked.
962
         */
963
964
        /*
965
         * Try next offsets, in case this match is
966
         * in the middle of a string.
967
         */
968
254
        for (k = i + 1 ; k < NOFFSETS; k++) {
969
178
          size_t no;
970
178
          int adjust = 1;
971
178
          if (prpsoffsets(k) >= prpsoffsets(i))
972
47
            continue;
973
          /*
974
           * pr_fname == pr_psargs - 16 &&
975
           * non-nul-terminated fname (qemu)
976
           */
977
131
          if (prpsoffsets(k) ==
978
131
              prpsoffsets(i) - 16 && j == 16)
979
19
            continue;
980
112
          for (no = doff + prpsoffsets(k);
981
3.65k
               no < doff + prpsoffsets(i); no++)
982
3.54k
            adjust = adjust
983
3.54k
                     && isprint(nbuf[no]);
984
112
          if (adjust)
985
35
            i = k;
986
112
        }
987
988
76
        cname = CAST(unsigned char *,
989
76
            &nbuf[doff + prpsoffsets(i)]);
990
3.43k
        for (cp = cname; cp < nbuf + size && *cp
991
3.43k
            && isprint(*cp); cp++)
992
3.36k
          continue;
993
        /*
994
         * Linux apparently appends a space at the end
995
         * of the command line: remove it.
996
         */
997
355
        while (cp > cname && isspace(cp[-1]))
998
279
          cp--;
999
76
        if (elf_printf(ms, ", from '%s'",
1000
76
            file_copystr(buf, sizeof(buf),
1001
76
            CAST(size_t, cp - cname),
1002
76
            RCAST(char *, cname))) == -1)
1003
0
          return -1;
1004
76
        *flags |= FLAGS_DID_CORE;
1005
76
        return 1;
1006
1007
15.7k
      tryanother:
1008
15.7k
        ;
1009
15.7k
      }
1010
2.34k
    }
1011
19.8k
    break;
1012
20.6k
  }
1013
20.5k
#endif
1014
20.5k
  return 0;
1015
20.6k
}
1016
1017
file_private off_t
1018
get_offset_from_virtaddr(struct magic_set *ms, int swap, int clazz, int fd,
1019
    off_t off, int num, off_t fsize, uint64_t virtaddr)
1020
1.76k
{
1021
1.76k
  Elf32_Phdr ph32;
1022
1.76k
  Elf64_Phdr ph64;
1023
1024
  /*
1025
   * Loop through all the program headers and find the header with
1026
   * virtual address in which the "virtaddr" belongs to.
1027
   */
1028
18.8k
  for ( ; num; num--) {
1029
18.7k
    if (pread(fd, xph_addr, xph_sizeof, off) <
1030
18.7k
        CAST(ssize_t, xph_sizeof)) {
1031
665
      if (elf_printf(ms,
1032
665
          ", can't read elf program header at %jd",
1033
665
          (intmax_t)off) == -1)
1034
0
        return -1;
1035
665
      return 0;
1036
1037
665
    }
1038
18.1k
    off += xph_sizeof;
1039
1040
18.1k
    if (fsize != SIZE_UNKNOWN && xph_offset > fsize) {
1041
      /* Perhaps warn here */
1042
10.9k
      continue;
1043
10.9k
    }
1044
1045
7.16k
    if (virtaddr >= xph_vaddr && virtaddr < xph_vaddr + xph_filesz)
1046
999
      return xph_offset + (virtaddr - xph_vaddr);
1047
7.16k
  }
1048
104
  return 0;
1049
1.76k
}
1050
1051
file_private size_t
1052
get_string_on_virtaddr(struct magic_set *ms,
1053
    int swap, int clazz, int fd, off_t ph_off, int ph_num,
1054
    off_t fsize, uint64_t virtaddr, char *buf, ssize_t buflen)
1055
1.76k
{
1056
1.76k
  char *bptr;
1057
1.76k
  off_t offset;
1058
1059
1.76k
  if (buflen == 0)
1060
0
    return 0;
1061
1062
1.76k
  offset = get_offset_from_virtaddr(ms, swap, clazz, fd, ph_off, ph_num,
1063
1.76k
      fsize, virtaddr);
1064
1.76k
  if (offset < 0 ||
1065
1.62k
      (buflen = pread(fd, buf, CAST(size_t, buflen), offset)) <= 0) {
1066
785
    (void)elf_printf(ms, ", can't read elf string at %jd",
1067
785
        (intmax_t)offset);
1068
785
    return 0;
1069
785
  }
1070
1071
983
  buf[buflen - 1] = '\0';
1072
1073
  /* We expect only printable characters, so return if buffer contains
1074
   * non-printable character before the '\0' or just '\0'. */
1075
6.96k
  for (bptr = buf; *bptr && isprint(CAST(unsigned char, *bptr)); bptr++)
1076
5.97k
    continue;
1077
983
  if (*bptr != '\0')
1078
794
    return 0;
1079
1080
189
  return bptr - buf;
1081
983
}
1082
1083
1084
/*ARGSUSED*/
1085
file_private int
1086
do_auxv_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
1087
    int swap, uint32_t namesz __attribute__((__unused__)),
1088
    uint32_t descsz __attribute__((__unused__)),
1089
    size_t noff __attribute__((__unused__)), size_t doff,
1090
    int *flags, size_t size __attribute__((__unused__)), int clazz,
1091
    int fd, off_t ph_off, int ph_num, off_t fsize)
1092
21.3k
{
1093
21.3k
#ifdef ELFCORE
1094
21.3k
  Aux32Info auxv32;
1095
21.3k
  Aux64Info auxv64;
1096
21.3k
  size_t elsize = xauxv_sizeof;
1097
21.3k
  const char *tag;
1098
21.3k
  int is_string;
1099
21.3k
  size_t nval, off;
1100
1101
21.3k
  if ((*flags & (FLAGS_IS_CORE|FLAGS_DID_CORE_STYLE)) !=
1102
21.3k
      (FLAGS_IS_CORE|FLAGS_DID_CORE_STYLE))
1103
17.6k
    return 0;
1104
1105
3.67k
  switch (*flags & FLAGS_CORE_STYLE) {
1106
2.31k
  case OS_STYLE_SVR4:
1107
2.31k
    if (type != NT_AUXV)
1108
1.68k
      return 0;
1109
633
    break;
1110
#ifdef notyet
1111
  case OS_STYLE_NETBSD:
1112
    if (type != NT_NETBSD_CORE_AUXV)
1113
      return 0;
1114
    break;
1115
  case OS_STYLE_FREEBSD:
1116
    if (type != NT_FREEBSD_PROCSTAT_AUXV)
1117
      return 0;
1118
    break;
1119
#endif
1120
1.35k
  default:
1121
1.35k
    return 0;
1122
3.67k
  }
1123
1124
633
  *flags |= FLAGS_DID_AUXV;
1125
1126
633
  nval = 0;
1127
5.52k
  for (off = 0; off + elsize <= descsz; off += elsize) {
1128
4.90k
    memcpy(xauxv_addr, &nbuf[doff + off], xauxv_sizeof);
1129
    /* Limit processing to 50 vector entries to prevent DoS */
1130
4.90k
    if (nval++ >= 50) {
1131
20
      file_error(ms, 0, "Too many ELF Auxv elements");
1132
20
      return 1;
1133
20
    }
1134
1135
4.88k
    switch(xauxv_type) {
1136
745
    case AT_LINUX_EXECFN:
1137
745
      is_string = 1;
1138
745
      tag = "execfn";
1139
745
      break;
1140
1.02k
    case AT_LINUX_PLATFORM:
1141
1.02k
      is_string = 1;
1142
1.02k
      tag = "platform";
1143
1.02k
      break;
1144
51
    case AT_LINUX_UID:
1145
51
      is_string = 0;
1146
51
      tag = "real uid";
1147
51
      break;
1148
32
    case AT_LINUX_GID:
1149
32
      is_string = 0;
1150
32
      tag = "real gid";
1151
32
      break;
1152
42
    case AT_LINUX_EUID:
1153
42
      is_string = 0;
1154
42
      tag = "effective uid";
1155
42
      break;
1156
65
    case AT_LINUX_EGID:
1157
65
      is_string = 0;
1158
65
      tag = "effective gid";
1159
65
      break;
1160
2.92k
    default:
1161
2.92k
      is_string = 0;
1162
2.92k
      tag = NULL;
1163
2.92k
      break;
1164
4.88k
    }
1165
1166
4.88k
    if (tag == NULL)
1167
2.92k
      continue;
1168
1169
1.95k
    if (is_string) {
1170
1.76k
      char buf[256];
1171
1.76k
      ssize_t buflen;
1172
1.76k
      buflen = get_string_on_virtaddr(ms, swap, clazz, fd,
1173
1.76k
          ph_off, ph_num, fsize, xauxv_val, buf, sizeof(buf));
1174
1175
1.76k
      if (buflen == 0)
1176
1.65k
        continue;
1177
1178
110
      if (elf_printf(ms, ", %s: '%s'", tag, buf) == -1)
1179
0
        return -1;
1180
190
    } else {
1181
190
      if (elf_printf(ms, ", %s: %d", tag,
1182
190
          CAST(int, xauxv_val)) == -1)
1183
0
        return -1;
1184
190
    }
1185
1.95k
  }
1186
613
  return 1;
1187
#else
1188
  return 0;
1189
#endif
1190
633
}
1191
1192
file_private size_t
1193
dodynamic(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
1194
    int clazz, int swap, int *pie, size_t *need)
1195
42.6k
{
1196
42.6k
  Elf32_Dyn dh32;
1197
42.6k
  Elf64_Dyn dh64;
1198
42.6k
  unsigned char *dbuf = CAST(unsigned char *, vbuf);
1199
1200
42.6k
  if (xdh_sizeof + offset > size) {
1201
    /*
1202
     * We're out of note headers.
1203
     */
1204
1.04k
    return xdh_sizeof + offset;
1205
1.04k
  }
1206
1207
41.5k
  memcpy(xdh_addr, &dbuf[offset], xdh_sizeof);
1208
41.5k
  offset += xdh_sizeof;
1209
1210
41.5k
  switch (xdh_tag) {
1211
2.00k
  case DT_FLAGS_1:
1212
2.00k
    if (xdh_val & DF_1_PIE) {
1213
1.16k
      *pie = 1;
1214
1.16k
      ms->mode |= 0111;
1215
1.16k
    } else
1216
842
      ms->mode &= ~0111;
1217
2.00k
    break;
1218
1.26k
  case DT_NEEDED:
1219
1.26k
    (*need)++;
1220
1.26k
    break;
1221
38.3k
  default:
1222
38.3k
    break;
1223
41.5k
  }
1224
41.5k
  return offset;
1225
41.5k
}
1226
1227
1228
file_private size_t
1229
donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
1230
    int clazz, int swap, size_t align, int *flags, uint16_t *notecount,
1231
    int fd, off_t ph_off, int ph_num, off_t fsize)
1232
30.9k
{
1233
30.9k
  Elf32_Nhdr nh32;
1234
30.9k
  Elf64_Nhdr nh64;
1235
30.9k
  size_t noff, doff;
1236
30.9k
  uint32_t namesz, descsz;
1237
30.9k
  char buf[256];
1238
30.9k
  unsigned char *nbuf = CAST(unsigned char *, vbuf);
1239
1240
30.9k
  if (*notecount == 0)
1241
322
    return 0;
1242
30.6k
  --*notecount;
1243
1244
30.6k
  if (xnh_sizeof + offset > size) {
1245
    /*
1246
     * We're out of note headers.
1247
     */
1248
2.46k
    return xnh_sizeof + offset;
1249
2.46k
  }
1250
  /*XXX: GCC */
1251
28.1k
  memset(&nh32, 0, sizeof(nh32));
1252
28.1k
  memset(&nh64, 0, sizeof(nh64));
1253
1254
28.1k
  memcpy(xnh_addr, &nbuf[offset], xnh_sizeof);
1255
28.1k
  offset += xnh_sizeof;
1256
1257
28.1k
  namesz = xnh_namesz;
1258
28.1k
  descsz = xnh_descsz;
1259
1260
28.1k
  if ((namesz == 0) && (descsz == 0)) {
1261
    /*
1262
     * We're out of note headers.
1263
     */
1264
348
    return (offset >= size) ? offset : size;
1265
348
  }
1266
1267
27.7k
  if (namesz & 0x80000000) {
1268
919
      (void)elf_printf(ms, ", bad note name size %#lx",
1269
919
    CAST(unsigned long, namesz));
1270
919
      return 0;
1271
919
  }
1272
1273
26.8k
  if (descsz & 0x80000000) {
1274
1.02k
    (void)elf_printf(ms, ", bad note description size %#lx",
1275
1.02k
        CAST(unsigned long, descsz));
1276
1.02k
    return 0;
1277
1.02k
  }
1278
1279
25.8k
  noff = offset;
1280
25.8k
  doff = ELF_ALIGN(offset + namesz);
1281
1282
25.8k
  if (offset + namesz > size) {
1283
    /*
1284
     * We're past the end of the buffer.
1285
     */
1286
1.97k
    return doff;
1287
1.97k
  }
1288
1289
23.8k
  offset = ELF_ALIGN(doff + descsz);
1290
23.8k
  if (doff + descsz > size) {
1291
    /*
1292
     * We're past the end of the buffer.
1293
     */
1294
902
    return (offset >= size) ? offset : size;
1295
902
  }
1296
1297
1298
22.9k
  if ((*flags & FLAGS_DID_OS_NOTE) == 0) {
1299
22.2k
    if (do_os_note(ms, nbuf, xnh_type, swap,
1300
22.2k
        namesz, descsz, noff, doff, flags))
1301
153
      return offset;
1302
22.2k
  }
1303
1304
22.8k
  if ((*flags & FLAGS_DID_BUILD_ID) == 0) {
1305
22.5k
    if (do_bid_note(ms, nbuf, xnh_type, swap,
1306
22.5k
        namesz, descsz, noff, doff, flags))
1307
944
      return offset;
1308
22.5k
  }
1309
1310
21.8k
  if ((*flags & FLAGS_DID_NETBSD_PAX) == 0) {
1311
21.4k
    if (do_pax_note(ms, nbuf, xnh_type, swap,
1312
21.4k
        namesz, descsz, noff, doff, flags))
1313
54
      return offset;
1314
21.4k
  }
1315
21.8k
  if ((*flags & FLAGS_DID_ANDROID_MEMTAG) == 0) {
1316
21.6k
    if (do_memtag_note(ms, nbuf, xnh_type, swap,
1317
21.6k
        namesz, descsz, noff, doff, flags))
1318
54
      return offset;
1319
21.6k
  }
1320
1321
21.7k
  if ((*flags & FLAGS_DID_CORE) == 0) {
1322
20.6k
    if (do_core_note(ms, nbuf, xnh_type, swap,
1323
20.6k
        namesz, descsz, noff, doff, flags, size, clazz))
1324
82
      return offset;
1325
20.6k
  }
1326
1327
21.6k
  if ((*flags & FLAGS_DID_AUXV) == 0) {
1328
21.3k
    if (do_auxv_note(ms, nbuf, xnh_type, swap,
1329
21.3k
      namesz, descsz, noff, doff, flags, size, clazz,
1330
21.3k
      fd, ph_off, ph_num, fsize))
1331
633
      return offset;
1332
21.3k
  }
1333
1334
21.0k
  if (NAMEEQUALS(RCAST(char *, &nbuf[noff]), "NetBSD")) {
1335
1.85k
    int descw, flag;
1336
1.85k
    const char *str, *tag;
1337
1.85k
    if (descsz > 100)
1338
335
      descsz = 100;
1339
1.85k
    switch (xnh_type) {
1340
378
        case NT_NETBSD_VERSION:
1341
378
      return offset;
1342
201
    case NT_NETBSD_MARCH:
1343
201
      flag = FLAGS_DID_NETBSD_MARCH;
1344
201
      tag = "compiled for";
1345
201
      break;
1346
84
    case NT_NETBSD_CMODEL:
1347
84
      flag = FLAGS_DID_NETBSD_CMODEL;
1348
84
      tag = "compiler model";
1349
84
      break;
1350
208
    case NT_NETBSD_EMULATION:
1351
208
      flag = FLAGS_DID_NETBSD_EMULATION;
1352
208
      tag = "emulation:";
1353
208
      break;
1354
980
    default:
1355
980
      if (*flags & FLAGS_DID_NETBSD_UNKNOWN)
1356
893
        return offset;
1357
87
      *flags |= FLAGS_DID_NETBSD_UNKNOWN;
1358
87
      if (elf_printf(ms, ", note=%u", xnh_type) == -1)
1359
0
        return offset;
1360
87
      return offset;
1361
1.85k
    }
1362
1363
493
    if (*flags & flag)
1364
461
      return offset;
1365
32
    str = RCAST(const char *, &nbuf[doff]);
1366
32
    descw = CAST(int, descsz);
1367
32
    *flags |= flag;
1368
32
    elf_printf(ms, ", %s: %s", tag,
1369
32
        file_copystr(buf, sizeof(buf), descw, str));
1370
32
    return offset;
1371
493
  }
1372
1373
19.2k
  return offset;
1374
21.0k
}
1375
1376
/* SunOS 5.x hardware capability descriptions */
1377
typedef struct cap_desc {
1378
  uint64_t cd_mask;
1379
  const char *cd_name;
1380
} cap_desc_t;
1381
1382
static const cap_desc_t cap_desc_sparc[] = {
1383
  { AV_SPARC_MUL32,   "MUL32" },
1384
  { AV_SPARC_DIV32,   "DIV32" },
1385
  { AV_SPARC_FSMULD,    "FSMULD" },
1386
  { AV_SPARC_V8PLUS,    "V8PLUS" },
1387
  { AV_SPARC_POPC,    "POPC" },
1388
  { AV_SPARC_VIS,     "VIS" },
1389
  { AV_SPARC_VIS2,    "VIS2" },
1390
  { AV_SPARC_ASI_BLK_INIT,  "ASI_BLK_INIT" },
1391
  { AV_SPARC_FMAF,    "FMAF" },
1392
  { AV_SPARC_FJFMAU,    "FJFMAU" },
1393
  { AV_SPARC_IMA,     "IMA" },
1394
  { 0, NULL }
1395
};
1396
1397
static const cap_desc_t cap_desc_386[] = {
1398
  { AV_386_FPU,     "FPU" },
1399
  { AV_386_TSC,     "TSC" },
1400
  { AV_386_CX8,     "CX8" },
1401
  { AV_386_SEP,     "SEP" },
1402
  { AV_386_AMD_SYSC,    "AMD_SYSC" },
1403
  { AV_386_CMOV,      "CMOV" },
1404
  { AV_386_MMX,     "MMX" },
1405
  { AV_386_AMD_MMX,   "AMD_MMX" },
1406
  { AV_386_AMD_3DNow,   "AMD_3DNow" },
1407
  { AV_386_AMD_3DNowx,    "AMD_3DNowx" },
1408
  { AV_386_FXSR,      "FXSR" },
1409
  { AV_386_SSE,     "SSE" },
1410
  { AV_386_SSE2,      "SSE2" },
1411
  { AV_386_PAUSE,     "PAUSE" },
1412
  { AV_386_SSE3,      "SSE3" },
1413
  { AV_386_MON,     "MON" },
1414
  { AV_386_CX16,      "CX16" },
1415
  { AV_386_AHF,     "AHF" },
1416
  { AV_386_TSCP,      "TSCP" },
1417
  { AV_386_AMD_SSE4A,   "AMD_SSE4A" },
1418
  { AV_386_POPCNT,    "POPCNT" },
1419
  { AV_386_AMD_LZCNT,   "AMD_LZCNT" },
1420
  { AV_386_SSSE3,     "SSSE3" },
1421
  { AV_386_SSE4_1,    "SSE4.1" },
1422
  { AV_386_SSE4_2,    "SSE4.2" },
1423
  { 0, NULL }
1424
};
1425
1426
file_private int
1427
doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
1428
    size_t size, off_t fsize, int mach, int strtab, int *flags,
1429
    uint16_t *notecount)
1430
1.92k
{
1431
1.92k
  Elf32_Shdr sh32;
1432
1.92k
  Elf64_Shdr sh64;
1433
1.92k
  int stripped = 1, has_debug_info = 0;
1434
1.92k
  size_t nbadcap = 0;
1435
1.92k
  void *nbuf;
1436
1.92k
  off_t noff, coff, name_off, offs;
1437
1.92k
  uint64_t cap_hw1 = 0; /* SunOS 5.x hardware capabilities */
1438
1.92k
  uint64_t cap_sf1 = 0; /* SunOS 5.x software capabilities */
1439
1.92k
  char name[50];
1440
1.92k
  ssize_t namesize;
1441
1442
1.92k
  if (ms->flags & MAGIC_MIME)
1443
0
    return 0;
1444
1445
1.92k
  if (num == 0) {
1446
539
    if (elf_printf(ms, ", no section header") == -1)
1447
0
      return -1;
1448
539
    return 0;
1449
539
  }
1450
1.38k
  if (size != xsh_sizeof) {
1451
323
    if (elf_printf(ms, ", corrupted section header size") == -1)
1452
0
      return -1;
1453
323
    return 0;
1454
323
  }
1455
1456
  /* Read offset of name section to be able to read section names later */
1457
1.05k
  offs = CAST(off_t, (off + size * strtab));
1458
1.05k
  if (pread(fd, xsh_addr, xsh_sizeof, offs) < CAST(ssize_t, xsh_sizeof)) {
1459
9
    if (elf_printf(ms, ", missing section headers at %jd",
1460
9
        (intmax_t)offs) == -1)
1461
0
      return -1;
1462
9
    return 0;
1463
9
  }
1464
1.05k
  name_off = xsh_offset;
1465
1466
1.05k
  if (fsize != SIZE_UNKNOWN && fsize < name_off) {
1467
2
    if (elf_printf(ms, ", too large section header offset %jd",
1468
2
        (intmax_t)name_off) == -1)
1469
0
      return -1;
1470
2
    return 0;
1471
2
  }
1472
1473
64.1k
  for ( ; num; num--) {
1474
    /* Read the name of this section. */
1475
63.9k
    offs = name_off + xsh_name;
1476
63.9k
    if ((namesize = pread(fd, name, sizeof(name) - 1, offs))
1477
63.9k
        == -1) {
1478
14
      if (elf_printf(ms, 
1479
14
          ", can't read name of elf section at %jd",
1480
14
          (intmax_t)offs) == -1)
1481
0
        return -1;
1482
14
      return 0;
1483
14
    }
1484
63.9k
    name[namesize] = '\0';
1485
63.9k
    if (strcmp(name, ".debug_info") == 0) {
1486
196
      has_debug_info = 1;
1487
196
      stripped = 0;
1488
196
    }
1489
1490
63.9k
    if (pread(fd, xsh_addr, xsh_sizeof, off) <
1491
63.9k
        CAST(ssize_t, xsh_sizeof)) {
1492
539
      if (elf_printf(ms, ", can't read elf section at %jd",
1493
539
          (intmax_t)off) == -1)
1494
0
        return -1;
1495
539
      return 0;
1496
539
    }
1497
63.3k
    off += size;
1498
1499
    /* Things we can determine before we seek */
1500
63.3k
    switch (xsh_type) {
1501
1.56k
    case SHT_SYMTAB:
1502
#if 0
1503
    case SHT_DYNSYM:
1504
#endif
1505
1.56k
      stripped = 0;
1506
1.56k
      break;
1507
61.8k
    default:
1508
61.8k
      if (fsize != SIZE_UNKNOWN && xsh_offset > fsize) {
1509
        /* Perhaps warn here */
1510
26.5k
        continue;
1511
26.5k
      }
1512
35.2k
      break;
1513
63.3k
    }
1514
1515
1516
    /* Things we can determine when we seek */
1517
36.8k
    switch (xsh_type) {
1518
2.08k
    case SHT_NOTE:
1519
2.08k
      if (CAST(uintmax_t, (xsh_size + xsh_offset)) >
1520
2.08k
          CAST(uintmax_t, fsize)) {
1521
115
        if (elf_printf(ms,
1522
115
            ", note offset/size %#" INTMAX_T_FORMAT
1523
115
            "x+%#" INTMAX_T_FORMAT "x exceeds"
1524
115
            " file size %#" INTMAX_T_FORMAT "x",
1525
115
            CAST(uintmax_t, xsh_offset),
1526
115
            CAST(uintmax_t, xsh_size),
1527
115
            CAST(uintmax_t, fsize)) == -1)
1528
0
          return -1;
1529
115
        return 0;
1530
115
      }
1531
1.97k
      if (xsh_size > ms->elf_shsize_max) {
1532
49
        file_error(ms, errno, "Note section size too "
1533
49
            "big (%ju > %zu)", (uintmax_t)xsh_size,
1534
49
            ms->elf_shsize_max);
1535
49
        return -1;
1536
49
      }
1537
1.92k
      if ((nbuf = malloc(xsh_size)) == NULL) {
1538
0
        file_error(ms, errno, "Cannot allocate memory"
1539
0
            " for note");
1540
0
        return -1;
1541
0
      }
1542
1.92k
      offs = xsh_offset;
1543
1.92k
      if (pread(fd, nbuf, xsh_size, offs) <
1544
1.92k
          CAST(ssize_t, xsh_size)) {
1545
24
        free(nbuf);
1546
24
        if (elf_printf(ms,
1547
24
            ", can't read elf note at %jd",
1548
24
            (intmax_t)offs) == -1)
1549
0
          return -1;
1550
24
        return 0;
1551
24
      }
1552
1553
1.89k
      noff = 0;
1554
4.91k
      for (;;) {
1555
4.91k
        if (noff >= CAST(off_t, xsh_size))
1556
1.67k
          break;
1557
3.24k
        noff = donote(ms, nbuf, CAST(size_t, noff),
1558
3.24k
            xsh_size, clazz, swap, 4, flags, notecount,
1559
3.24k
            fd, 0, 0, 0);
1560
3.24k
        if (noff == 0)
1561
219
          break;
1562
3.24k
      }
1563
1.89k
      free(nbuf);
1564
1.89k
      break;
1565
2.77k
    case SHT_SUNW_cap:
1566
2.77k
      switch (mach) {
1567
206
      case EM_SPARC:
1568
768
      case EM_SPARCV9:
1569
1.03k
      case EM_IA_64:
1570
1.95k
      case EM_386:
1571
2.54k
      case EM_AMD64:
1572
2.54k
        break;
1573
229
      default:
1574
229
        goto skip;
1575
2.77k
      }
1576
1577
2.54k
      if (nbadcap > 5)
1578
736
        break;
1579
1.80k
      if (lseek(fd, xsh_offset, SEEK_SET)
1580
1.80k
          == CAST(off_t, -1)) {
1581
5
        file_badseek(ms);
1582
5
        return -1;
1583
5
      }
1584
1.80k
      coff = 0;
1585
7.31k
      for (;;) {
1586
7.31k
        Elf32_Cap cap32;
1587
7.31k
        Elf64_Cap cap64;
1588
7.31k
        cap32.c_un.c_val = 0;
1589
7.31k
        cap64.c_un.c_val = 0;
1590
7.31k
        char cbuf[/*CONSTCOND*/
1591
7.31k
            MAX(sizeof(cap32), sizeof(cap64))];
1592
7.31k
        if ((coff += xcap_sizeof) >
1593
7.31k
            CAST(off_t, xsh_size))
1594
1.02k
          break;
1595
6.29k
        if (read(fd, cbuf, CAST(size_t, xcap_sizeof)) !=
1596
6.29k
            CAST(ssize_t, xcap_sizeof)) {
1597
90
          file_badread(ms);
1598
90
          return -1;
1599
90
        }
1600
6.20k
        if (cbuf[0] == 'A') {
1601
#ifdef notyet
1602
          char *p = cbuf + 1;
1603
          uint32_t len, tag;
1604
          memcpy(&len, p, sizeof(len));
1605
          p += 4;
1606
          len = getu32(swap, len);
1607
          if (memcmp("gnu", p, 3) != 0) {
1608
              if (elf_printf(ms,
1609
            ", unknown capability %.3s", p)
1610
            == -1)
1611
            return -1;
1612
              break;
1613
          }
1614
          p += strlen(p) + 1;
1615
          tag = *p++;
1616
          memcpy(&len, p, sizeof(len));
1617
          p += 4;
1618
          len = getu32(swap, len);
1619
          if (tag != 1) {
1620
              if (elf_printf(ms, ", unknown gnu"
1621
            " capability tag %d", tag)
1622
            == -1)
1623
            return -1;
1624
              break;
1625
          }
1626
          // gnu attributes
1627
#endif
1628
441
          break;
1629
441
        }
1630
5.76k
        memcpy(xcap_addr, cbuf, xcap_sizeof);
1631
5.76k
        switch (xcap_tag) {
1632
2.77k
        case CA_SUNW_NULL:
1633
2.77k
          break;
1634
826
        case CA_SUNW_HW_1:
1635
826
          cap_hw1 |= xcap_val;
1636
826
          break;
1637
1.04k
        case CA_SUNW_SF_1:
1638
1.04k
          cap_sf1 |= xcap_val;
1639
1.04k
          break;
1640
1.12k
        default:
1641
1.12k
          if (elf_printf(ms,
1642
1.12k
              ", with unknown capability "
1643
1.12k
              "%#" INT64_T_FORMAT "x = %#"
1644
1.12k
              INT64_T_FORMAT "x",
1645
1.12k
              CAST(unsigned long long, xcap_tag),
1646
1.12k
              CAST(unsigned long long, xcap_val))
1647
1.12k
              == -1)
1648
0
            return -1;
1649
1.12k
          if (nbadcap++ > 2)
1650
248
            goto skip;
1651
874
          break;
1652
5.76k
        }
1653
5.76k
      }
1654
      /*FALLTHROUGH*/
1655
1.93k
    skip:
1656
33.9k
    default:
1657
33.9k
      break;
1658
36.8k
    }
1659
36.8k
  }
1660
1661
212
  if (has_debug_info) {
1662
1
    if (elf_printf(ms, ", with debug_info") == -1)
1663
0
      return -1;
1664
1
  }
1665
212
  if (elf_printf(ms, ", %sstripped", stripped ? "" : "not ") == -1)
1666
0
    return -1;
1667
212
  if (cap_hw1) {
1668
116
    const cap_desc_t *cdp;
1669
116
    switch (mach) {
1670
1
    case EM_SPARC:
1671
1
    case EM_SPARC32PLUS:
1672
104
    case EM_SPARCV9:
1673
104
      cdp = cap_desc_sparc;
1674
104
      break;
1675
2
    case EM_386:
1676
11
    case EM_IA_64:
1677
12
    case EM_AMD64:
1678
12
      cdp = cap_desc_386;
1679
12
      break;
1680
0
    default:
1681
0
      cdp = NULL;
1682
0
      break;
1683
116
    }
1684
116
    if (elf_printf(ms, ", uses") == -1)
1685
0
      return -1;
1686
116
    if (cdp) {
1687
1.56k
      while (cdp->cd_name) {
1688
1.44k
        if (cap_hw1 & cdp->cd_mask) {
1689
712
          if (elf_printf(ms,
1690
712
              " %s", cdp->cd_name) == -1)
1691
0
            return -1;
1692
712
          cap_hw1 &= ~cdp->cd_mask;
1693
712
        }
1694
1.44k
        ++cdp;
1695
1.44k
      }
1696
116
      if (cap_hw1)
1697
110
        if (elf_printf(ms,
1698
110
            " unknown hardware capability %#"
1699
110
            INT64_T_FORMAT "x",
1700
110
            CAST(unsigned long long, cap_hw1)) == -1)
1701
0
          return -1;
1702
116
    } else {
1703
0
      if (elf_printf(ms,
1704
0
          " hardware capability %#" INT64_T_FORMAT "x",
1705
0
          CAST(unsigned long long, cap_hw1)) == -1)
1706
0
        return -1;
1707
0
    }
1708
116
  }
1709
212
  if (cap_sf1) {
1710
67
    if (cap_sf1 & SF1_SUNW_FPUSED) {
1711
30
      if (elf_printf(ms,
1712
30
          (cap_sf1 & SF1_SUNW_FPKNWN)
1713
30
          ? ", uses frame pointer"
1714
30
          : ", not known to use frame pointer") == -1)
1715
0
        return -1;
1716
30
    }
1717
67
    cap_sf1 &= ~SF1_SUNW_MASK;
1718
67
    if (cap_sf1)
1719
66
      if (elf_printf(ms,
1720
66
          ", with unknown software capability %#"
1721
66
          INT64_T_FORMAT "x",
1722
66
          CAST(unsigned long long, cap_sf1)) == -1)
1723
0
        return -1;
1724
67
  }
1725
212
  return 0;
1726
212
}
1727
1728
/*
1729
 * Look through the program headers of an executable image, to determine
1730
 * if it is statically or dynamically linked. If it has a dynamic section,
1731
 * it is pie, and does not have an interpreter or needed libraries, we
1732
 * call it static pie.
1733
 */
1734
file_private int
1735
dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
1736
    int num, size_t size, off_t fsize, int sh_num, int *flags,
1737
    uint16_t *notecount)
1738
1.85k
{
1739
1.85k
  Elf32_Phdr ph32;
1740
1.85k
  Elf64_Phdr ph64;
1741
1.85k
  const char *str;
1742
1.85k
  unsigned char nbuf[NBUFSIZE];
1743
1.85k
  char interp[NBUFSIZE];
1744
1.85k
  ssize_t bufsize;
1745
1.85k
  size_t offset, align, need = 0;
1746
1.85k
  int pie = 0, dynamic = 0;
1747
1748
1.85k
  if (num == 0) {
1749
574
    if (elf_printf(ms, ", no program header") == -1)
1750
0
      return -1;
1751
574
    return 0;
1752
574
  }
1753
1.27k
  if (size != xph_sizeof) {
1754
363
    if (elf_printf(ms, ", corrupted program header size") == -1)
1755
0
      return -1;
1756
363
    return 0;
1757
363
  }
1758
1759
913
  interp[0] = '\0';
1760
27.9k
    for ( ; num; num--) {
1761
27.7k
    int doread;
1762
27.7k
    if (pread(fd, xph_addr, xph_sizeof, off) <
1763
27.7k
        CAST(ssize_t, xph_sizeof)) {
1764
751
      if (elf_printf(ms,
1765
751
          ", can't read elf program headers at %jd",
1766
751
          (intmax_t)off) == -1)
1767
0
        return -1;
1768
751
      return 0;
1769
751
    }
1770
1771
27.0k
    off += size;
1772
27.0k
    bufsize = 0;
1773
27.0k
    align = 4;
1774
1775
    /* Things we can determine before we seek */
1776
27.0k
    switch (xph_type) {
1777
1.52k
    case PT_DYNAMIC:
1778
1.52k
      doread = 1;
1779
1.52k
      break;
1780
4.99k
    case PT_NOTE:
1781
4.99k
      if (sh_num)  /* Did this through section headers */
1782
744
        continue;
1783
4.25k
      if (((align = xph_align) & 0x80000000UL) != 0 ||
1784
3.77k
          align < 4) {
1785
1.37k
        if (elf_printf(ms,
1786
1.37k
            ", invalid note alignment %#lx",
1787
1.37k
            CAST(unsigned long, align)) == -1)
1788
0
          return -1;
1789
1.37k
        align = 4;
1790
1.37k
      }
1791
      /*FALLTHROUGH*/
1792
4.94k
    case PT_INTERP:
1793
4.94k
      doread = 1;
1794
4.94k
      break;
1795
19.8k
    default:
1796
19.8k
      doread = 0;
1797
19.8k
      if (fsize != SIZE_UNKNOWN && xph_offset > fsize) {
1798
        /* Maybe warn here? */
1799
11.7k
        continue;
1800
11.7k
      }
1801
8.08k
      break;
1802
27.0k
    }
1803
1804
14.5k
    if (doread) {
1805
6.46k
      size_t len = xph_filesz < sizeof(nbuf) ? xph_filesz
1806
6.46k
          : sizeof(nbuf);
1807
6.46k
      off_t offs = xph_offset;
1808
6.46k
      bufsize = pread(fd, nbuf, len, offs);
1809
6.46k
      if (bufsize == -1) {
1810
18
        if (elf_printf(ms,
1811
18
            ", can't read section at %jd",
1812
18
            (intmax_t)offs) == -1)
1813
0
          return -1;
1814
18
        return 0;
1815
18
      }
1816
6.46k
    }
1817
1818
    /* Things we can determine when we seek */
1819
14.5k
    switch (xph_type) {
1820
1.51k
    case PT_DYNAMIC:
1821
1.51k
      dynamic = 1;
1822
1.51k
      offset = 0;
1823
      // Let DF_1 determine if we are PIE or not.
1824
1.51k
      ms->mode &= ~0111;
1825
44.1k
      for (;;) {
1826
44.1k
        if (offset >= CAST(size_t, bufsize))
1827
1.51k
          break;
1828
42.6k
        offset = dodynamic(ms, nbuf, offset,
1829
42.6k
            CAST(size_t, bufsize), clazz, swap,
1830
42.6k
            &pie, &need);
1831
42.6k
        if (offset == 0)
1832
0
          break;
1833
42.6k
      }
1834
1.51k
      break;
1835
1836
42.6k
    case PT_INTERP:
1837
692
      need++;
1838
692
      if (ms->flags & MAGIC_MIME)
1839
0
        continue;
1840
692
      if (bufsize && nbuf[0]) {
1841
259
        nbuf[bufsize - 1] = '\0';
1842
259
        str = CAST(const char *, nbuf);
1843
259
      } else
1844
433
        str = "*empty*";
1845
692
      strlcpy(interp, str, sizeof(interp));
1846
692
      break;
1847
4.23k
    case PT_NOTE:
1848
4.23k
      if (ms->flags & MAGIC_MIME)
1849
0
        return 0;
1850
      /*
1851
       * This is a PT_NOTE section; loop through all the notes
1852
       * in the section.
1853
       */
1854
4.23k
      offset = 0;
1855
7.03k
      for (;;) {
1856
7.03k
        if (offset >= CAST(size_t, bufsize))
1857
3.21k
          break;
1858
3.82k
        offset = donote(ms, nbuf, offset,
1859
3.82k
            CAST(size_t, bufsize), clazz, swap, align,
1860
3.82k
            flags, notecount, fd, 0, 0, 0);
1861
3.82k
        if (offset == 0)
1862
1.02k
          break;
1863
3.82k
      }
1864
4.23k
      break;
1865
8.08k
    default:
1866
8.08k
      if (ms->flags & MAGIC_MIME)
1867
0
        continue;
1868
8.08k
      break;
1869
14.5k
    }
1870
14.5k
  }
1871
144
  if (ms->flags & MAGIC_MIME)
1872
0
    return 0;
1873
144
  if (dynamic) {
1874
27
    if (pie && need == 0)
1875
2
      str = "static-pie";
1876
25
    else
1877
25
      str = "dynamically";
1878
117
  } else {
1879
117
    str = "statically";
1880
117
  }
1881
144
  if (elf_printf(ms, ", %s linked", str) == -1)
1882
0
    return -1;
1883
144
  if (interp[0])
1884
6
    if (elf_printf(ms, ", interpreter %s", file_printable(ms,
1885
6
        RCAST(char *, nbuf), sizeof(nbuf),
1886
6
        interp, sizeof(interp))) == -1)
1887
2
      return -1;
1888
142
  return 0;
1889
144
}
1890
1891
1892
file_protected int
1893
file_tryelf(struct magic_set *ms, const struct buffer *b)
1894
8.29k
{
1895
8.29k
  int fd = b->fd;
1896
8.29k
  const unsigned char *buf = CAST(const unsigned char *, b->fbuf);
1897
8.29k
  size_t nbytes = b->flen;
1898
8.29k
  union {
1899
8.29k
    int32_t l;
1900
8.29k
    char c[sizeof(int32_t)];
1901
8.29k
  } u;
1902
8.29k
  int clazz;
1903
8.29k
  int swap;
1904
8.29k
  struct stat st;
1905
8.29k
  const struct stat *stp;
1906
8.29k
  off_t fsize;
1907
8.29k
  int flags = 0;
1908
8.29k
  Elf32_Ehdr elf32hdr;
1909
8.29k
  Elf64_Ehdr elf64hdr;
1910
8.29k
  uint16_t type, phnum, shnum, notecount;
1911
1912
8.29k
  if (ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION))
1913
0
    return 0;
1914
  /*
1915
   * ELF executables have multiple section headers in arbitrary
1916
   * file locations and thus file(1) cannot determine it from easily.
1917
   * Instead we traverse thru all section headers until a symbol table
1918
   * one is found or else the binary is stripped.
1919
   * Return immediately if it's not ELF (so we avoid pipe2file unless
1920
   * needed).
1921
   */
1922
8.29k
  if (buf[EI_MAG0] != ELFMAG0
1923
4.45k
      || (buf[EI_MAG1] != ELFMAG1 && buf[EI_MAG1] != OLFMAG1)
1924
4.43k
      || buf[EI_MAG2] != ELFMAG2 || buf[EI_MAG3] != ELFMAG3)
1925
3.86k
    return 0;
1926
1927
  /*
1928
   * If we cannot seek, it must be a pipe, socket or fifo.
1929
   */
1930
4.42k
  if((lseek(fd, CAST(off_t, 0), SEEK_SET) == CAST(off_t, -1))
1931
0
      && (errno == ESPIPE))
1932
0
    fd = file_pipe2file(ms, fd, buf, nbytes);
1933
1934
4.42k
  if (fd == -1) {
1935
0
    file_badread(ms);
1936
0
    return -1;
1937
0
  }
1938
1939
4.42k
  stp = &b->st;
1940
  /*
1941
   * b->st.st_size != 0 if previous fstat() succeeded,
1942
   * which is likely, we can avoid extra stat() call.
1943
   */
1944
4.42k
  if (b->st.st_size == 0) {
1945
0
    stp = &st;
1946
0
    if (fstat(fd, &st) == -1) {
1947
0
      file_badread(ms);
1948
0
      return -1;
1949
0
    }
1950
0
  }
1951
4.42k
  if (S_ISREG(stp->st_mode) || stp->st_size != 0)
1952
4.42k
    fsize = stp->st_size;
1953
0
  else
1954
0
    fsize = SIZE_UNKNOWN;
1955
1956
4.42k
  clazz = buf[EI_CLASS];
1957
1958
4.42k
  switch (clazz) {
1959
2.84k
  case ELFCLASS32:
1960
2.84k
#undef elf_getu
1961
2.84k
#define elf_getu(a, b)  elf_getu32(a, b)
1962
2.84k
#undef elfhdr
1963
11.3k
#define elfhdr elf32hdr
1964
2.84k
#include "elfclass.h"
1965
1.58k
  case ELFCLASS64:
1966
1.58k
#undef elf_getu
1967
1.58k
#define elf_getu(a, b)  elf_getu64(a, b)
1968
1.58k
#undef elfhdr
1969
6.27k
#define elfhdr elf64hdr
1970
1.58k
#include "elfclass.h"
1971
6
  default:
1972
6
      if (elf_printf(ms, ", unknown class %d", clazz) == -1)
1973
0
        return -1;
1974
6
      break;
1975
4.42k
  }
1976
6
  return 0;
1977
4.42k
}
1978
#endif