1 diff -ur rpm.org/file/src/readelf.c rpm/file/src/readelf.c
2 --- rpm.org/file/src/readelf.c 2004-06-14 16:30:54.607870936 +0200
3 +++ rpm/file/src/readelf.c 2004-03-22 21:28:40.000000000 +0100
7 + * Copyright (c) Christos Zoulas 2003.
8 + * All Rights Reserved.
10 + * Redistribution and use in source and binary forms, with or without
11 + * modification, are permitted provided that the following conditions
13 + * 1. Redistributions of source code must retain the above copyright
14 + * notice immediately at the beginning of the file, without modification,
15 + * this list of conditions, and the following disclaimer.
16 + * 2. Redistributions in binary form must reproduce the above copyright
17 + * notice, this list of conditions and the following disclaimer in the
18 + * documentation and/or other materials provided with the distribution.
19 + * 3. The name of the author may not be used to endorse or promote products
20 + * derived from this software without specific prior written permission.
22 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
26 + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 -FILE_RCSID("@(#)Id: readelf.c,v 1.22 2002/07/03 18:26:38 christos Exp ")
50 +FILE_RCSID("@(#)$Id$")
55 +private int dophn_core(struct magic_set *, int, int, int, off_t, int, size_t);
57 +private int dophn_exec(struct magic_set *, int, int, int, off_t, int, size_t);
58 +private int doshn(struct magic_set *, int, int, int, off_t, int, size_t);
59 +private size_t donote(struct magic_set *, unsigned char *, size_t, size_t, int,
62 +#define ELF_ALIGN(a) ((((a) + align - 1) / align) * align)
64 +private uint16_t getu16(int, uint16_t);
65 +private uint32_t getu32(int, uint32_t);
66 +private uint64_t getu64(int, uint64_t);
70 -getu16(const fmagic fm, uint16_t value)
73 +getu16(int swap, uint16_t value)
84 retval.c[0] = tmpval.c[1];
90 -getu32(const fmagic fm, uint32_t value)
93 +getu32(int swap, uint32_t value)
104 retval.c[0] = tmpval.c[3];
110 -getu64(const fmagic fm, uint64_t value)
113 +getu64(int swap, uint64_t value)
124 retval.c[0] = tmpval.c[7];
125 @@ -77,294 +120,65 @@
131 -#define sh_addr (fm->cls == ELFCLASS32 \
132 +#define sh_addr (class == ELFCLASS32 \
135 -#define sh_size (fm->cls == ELFCLASS32 \
136 +#define sh_size (class == ELFCLASS32 \
139 -#define shs_type (fm->cls == ELFCLASS32 \
140 - ? getu32(fm, sh32.sh_type) \
141 - : getu32(fm, sh64.sh_type))
143 -#define ph_addr (fm->cls == ELFCLASS32 \
144 +#define shs_type (class == ELFCLASS32 \
145 + ? getu32(swap, sh32.sh_type) \
146 + : getu32(swap, sh64.sh_type))
147 +#define ph_addr (class == ELFCLASS32 \
150 -#define ph_size (fm->cls == ELFCLASS32 \
151 +#define ph_size (class == ELFCLASS32 \
154 -#define ph_type (fm->cls == ELFCLASS32 \
155 - ? getu32(fm, ph32.p_type) \
156 - : getu32(fm, ph64.p_type))
157 -#define ph_offset (fm->cls == ELFCLASS32 \
158 - ? getu32(fm, ph32.p_offset) \
159 - : getu64(fm, ph64.p_offset))
160 -#define ph_align (fm->cls == ELFCLASS32 \
161 - ? (ph32.p_align ? getu32(fm, ph32.p_align) : 4) \
162 - : (ph64.p_align ? getu64(fm, ph64.p_align) : 4))
163 -#define ph_filesz (fm->cls == ELFCLASS32 \
164 - ? getu32(fm, ph32.p_filesz) \
165 - : getu64(fm, ph64.p_filesz))
167 -#define nh_type (fm->cls == ELFCLASS32 \
168 - ? getu32(fm, nh32->n_type) \
169 - : getu32(fm, nh64->n_type))
170 -#define nh_namesz (fm->cls == ELFCLASS32 \
171 - ? getu32(fm, nh32->n_namesz) \
172 - : getu32(fm, nh64->n_namesz))
173 -#define nh_descsz (fm->cls == ELFCLASS32 \
174 - ? getu32(fm, nh32->n_descsz) \
175 - : getu32(fm, nh64->n_descsz))
176 -#define prpsoffsets(i) (fm->cls == ELFCLASS32 \
177 +#define ph_type (class == ELFCLASS32 \
178 + ? getu32(swap, ph32.p_type) \
179 + : getu32(swap, ph64.p_type))
180 +#define ph_offset (class == ELFCLASS32 \
181 + ? getu32(swap, ph32.p_offset) \
182 + : getu64(swap, ph64.p_offset))
183 +#define ph_align (size_t)((class == ELFCLASS32 \
184 + ? (off_t) (ph32.p_align ? \
185 + getu32(swap, ph32.p_align) : 4) \
186 + : (off_t) (ph64.p_align ? \
187 + getu64(swap, ph64.p_align) : 4)))
188 +#define nh_size (class == ELFCLASS32 \
191 +#define nh_type (class == ELFCLASS32 \
192 + ? getu32(swap, nh32.n_type) \
193 + : getu32(swap, nh64.n_type))
194 +#define nh_namesz (class == ELFCLASS32 \
195 + ? getu32(swap, nh32.n_namesz) \
196 + : getu32(swap, nh64.n_namesz))
197 +#define nh_descsz (class == ELFCLASS32 \
198 + ? getu32(swap, nh32.n_descsz) \
199 + : getu32(swap, nh64.n_descsz))
200 +#define prpsoffsets(i) (class == ELFCLASS32 \
206 -doshn(fmagic fm, off_t off, int num, size_t size)
207 - /*@globals fileSystem @*/
208 - /*@modifies fm, fileSystem @*/
213 - if (size != sh_size) {
214 - error(EXIT_FAILURE, 0, "corrupted program header size.\n");
218 - if (lseek(fm->fd, off, SEEK_SET) == -1) {
219 - error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
223 - for ( ; num; num--) {
224 - if (read(fm->fd, sh_addr, size) == -1) {
225 - error(EXIT_FAILURE, 0, "read failed (%s).\n", strerror(errno));
228 - if (shs_type == SHT_SYMTAB /* || shs_type == SHT_DYNSYM */) {
229 - file_printf(fm, ", not stripped");
233 - file_printf(fm, ", stripped");
238 - * Look through the program headers of an executable image, searching
239 - * for a PT_INTERP section; if one is found, it's dynamically linked,
240 - * otherwise it's statically linked.
244 -dophn_exec(fmagic fm, off_t off, int num, size_t size)
245 - /*@globals fileSystem @*/
246 - /*@modifies fm, fileSystem @*/
249 - Elf32_Nhdr *nh32 = NULL;
251 - Elf64_Nhdr *nh64 = NULL;
252 - char *linking_style = "statically";
253 - char *shared_libraries = "";
256 - size_t nbufsize, offset, end, noff, doff;
257 - size_t align = (fm->cls == ELFCLASS32 ? 4 : 8);
258 -#define ALIGNED_LEN(len) (((len) + align - 1) & ~(align - 1))
261 - if (size != ph_size) {
262 - error(EXIT_FAILURE, 0, "corrupted program header size.\n");
266 - if (lseek(fm->fd, off, SEEK_SET) == -1) {
267 - error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
271 - for ( ; num; num--) {
272 - /* Read the program header data. */
273 - nb = read(fm->fd, ph_addr, size);
275 - error(EXIT_FAILURE, 0, "read failed (%s).\n", strerror(errno));
279 - /* XXX Elf64 notes cannot be read, so don't attempt for now. */
280 -#if !defined(__i386__)
281 - if (ph_type == PT_NOTE)
287 - linking_style = "dynamically";
288 - /*@switchbreak@*/ break;
290 - shared_libraries = " (uses shared libs)";
291 - /*@switchbreak@*/ break;
294 - * This is a PT_NOTE section; loop through all the notes
297 - if (lseek(fm->fd, (off_t) ph_offset, SEEK_SET) == -1) {
298 - error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
302 - /* XXX Read only the notes section. */
303 - nbufsize = (ph_filesz < sizeof(nbuf)
304 - ? ph_filesz : sizeof(nbuf));
305 - nb = read(fm->fd, nbuf, nbufsize);
307 - error(EXIT_FAILURE, 0, ": " "read failed (%s).\n",
316 - /*@innerbreak@*/ break;
318 - if (fm->cls == ELFCLASS32)
319 - nh32 = (Elf32_Nhdr *)&nbuf[offset];
321 - nh64 = (Elf64_Nhdr *)&nbuf[offset];
323 - offset = end; /* skip note header. */
325 - /* XXX Avoid notes that are not 1-16 bytes */
326 - if (nh_namesz <= 0 || nh_descsz <= 0)
328 - if (nh_namesz > 16 || nh_descsz > 16)
331 - end = offset + ALIGNED_LEN (nh_namesz)
332 - + ALIGNED_LEN (nh_descsz);
334 - /*@innerbreak@*/ break;
337 - doff = ALIGNED_LEN(offset + nh_namesz);
343 - if (nh_namesz == 4 &&
344 - strcmp(&nbuf[noff], "GNU") == 0 &&
345 - nh_type == NT_GNU_VERSION &&
348 - (uint32_t *)&nbuf[doff];
351 - file_printf(fm, ", for GNU/");
352 - switch (getu32(fm, desc[0])) {
354 - file_printf(fm, "Linux");
355 - /*@switchbreak@*/ break;
357 - file_printf(fm, "Hurd");
358 - /*@switchbreak@*/ break;
359 - case GNU_OS_SOLARIS:
360 - file_printf(fm, "Solaris");
361 - /*@switchbreak@*/ break;
363 - file_printf(fm, "<unknown>");
364 - /*@switchbreak@*/ break;
366 - file_printf(fm, " %d.%d.%d",
367 - getu32(fm, desc[1]),
368 - getu32(fm, desc[2]),
369 - getu32(fm, desc[3]));
373 - if (nh_namesz == 7 &&
374 - strcmp(&nbuf[noff], "NetBSD") == 0 &&
375 - nh_type == NT_NETBSD_VERSION &&
377 - file_printf(fm, ", for NetBSD");
379 - * Version number is stuck at 199905,
380 - * and hence is basically content-free.
385 - if (nh_namesz == 8 &&
386 - strcmp(&nbuf[noff], "FreeBSD") == 0 &&
387 - nh_type == NT_FREEBSD_VERSION &&
389 - uint32_t desc = getu32(fm,
390 - *(uint32_t *)&nbuf[doff]);
391 - file_printf(fm, ", for FreeBSD");
393 - * Contents is __FreeBSD_version,
394 - * whose relation to OS versions is
395 - * defined by a huge table in the
396 - * Porters' Handbook. Happily, the
397 - * first three digits are the version
398 - * number, at least in versions of
399 - * FreeBSD that use this note.
402 - file_printf(fm, " %d.%d", desc / 100000,
403 - desc / 10000 % 10);
404 - if (desc / 1000 % 10 > 0)
405 - file_printf(fm, ".%d",
410 - if (nh_namesz == 8 &&
411 - strcmp(&nbuf[noff], "OpenBSD") == 0 &&
412 - nh_type == NT_OPENBSD_VERSION &&
414 - file_printf(fm, ", for OpenBSD");
415 - /* Content of note is always 0 */
419 - if ((lseek(fm->fd, ph_offset + offset, SEEK_SET)) == -1) {
420 - error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
423 - /*@switchbreak@*/ break;
426 - file_printf(fm, ", %s linked%s", linking_style, shared_libraries);
431 -/*@unchecked@*/ /*@observer@*/
432 -static size_t prpsoffsets32[] = {
433 +size_t prpsoffsets32[] = {
435 28, /* Linux 2.0.36 */
436 32, /* Linux (I forget which kernel version) */
438 + 84, /* SunOS 5.x */
441 -/*@unchecked@*/ /*@observer@*/
442 -static size_t prpsoffsets64[] = {
443 - 120 /* SunOS 5.x, 64-bit */
444 +size_t prpsoffsets64[] = {
445 + 120, /* SunOS 5.x, 64-bit */
448 #define NOFFSETS32 (sizeof prpsoffsets32 / sizeof prpsoffsets32[0])
449 #define NOFFSETS64 (sizeof prpsoffsets64 / sizeof prpsoffsets64[0])
451 -#define NOFFSETS (fm->cls == ELFCLASS32 ? NOFFSETS32 : NOFFSETS64)
452 +#define NOFFSETS (class == ELFCLASS32 ? NOFFSETS32 : NOFFSETS64)
455 * Look through the program headers of an executable image, searching
456 @@ -391,46 +205,38 @@
457 #define OS_STYLE_FREEBSD 1
458 #define OS_STYLE_NETBSD 2
460 -/*@unchecked@*/ /*@observer@*/
461 -static const char *os_style_names[] = {
462 +private const char *os_style_names[] = {
470 -dophn_core(fmagic fm, off_t off, int num, size_t size)
471 - /*@globals fileSystem @*/
472 - /*@modifies fm, fileSystem @*/
474 +dophn_core(struct magic_set *ms, int class, int swap, int fd, off_t off,
475 + int num, size_t size)
478 - Elf32_Nhdr *nh32 = NULL;
480 - Elf64_Nhdr *nh64 = NULL;
481 - size_t offset, nameoffset, noffset, reloffset;
488 + unsigned char nbuf[BUFSIZ];
491 if (size != ph_size) {
492 - error(EXIT_FAILURE, 0, "corrupted program header size.\n");
494 + if (file_printf(ms, ", corrupted program header size") == -1)
500 * Loop through all the program headers.
502 for ( ; num; num--) {
503 - if (lseek(fm->fd, off, SEEK_SET) == -1) {
504 - error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
507 - if (read(fm->fd, ph_addr, size) == -1) {
508 - error(EXIT_FAILURE, 0, "read failed (%s).\n", strerror(errno));
510 + if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
514 + if (read(fd, ph_addr, ph_size) == -1) {
519 if (ph_type != PT_NOTE)
520 @@ -440,192 +246,475 @@
521 * This is a PT_NOTE section; loop through all the notes
524 - if (lseek(fm->fd, (off_t) ph_offset, SEEK_SET) == -1) {
525 - error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
528 - nb = read(fm->fd, nbuf, BUFSIZ);
530 - error(EXIT_FAILURE, 0, ": " "read failed (%s).\n", strerror(errno));
532 + if (lseek(fd, (off_t) ph_offset, SEEK_SET) == (off_t)-1) {
536 + bufsize = read(fd, nbuf, BUFSIZ);
537 + if (bufsize == -1) {
544 - /*@innerbreak@*/ break;
545 - if (fm->cls == ELFCLASS32)
546 - nh32 = (Elf32_Nhdr *)&nbuf[offset];
548 - nh64 = (Elf64_Nhdr *)&nbuf[offset];
550 + if (offset >= (size_t)bufsize)
552 + offset = donote(ms, nbuf, offset, (size_t)bufsize,
558 - * Check whether this note has the name "CORE" or
559 - * "FreeBSD", or "NetBSD-CORE".
561 - if (offset + nh_namesz >= nb) {
563 - * We're past the end of the buffer.
565 - /*@innerbreak@*/ break;
573 +donote(struct magic_set *ms, unsigned char *nbuf, size_t offset, size_t size,
574 + int class, int swap, size_t align)
582 + uint32_t namesz, descsz;
584 + if (class == ELFCLASS32)
585 + memcpy(&nh32, &nbuf[offset], sizeof(nh32));
587 + memcpy(&nh64, &nbuf[offset], sizeof(nh64));
590 + namesz = nh_namesz;
591 + descsz = nh_descsz;
592 + if ((namesz == 0) && (descsz == 0)) {
594 + * We're out of note headers.
599 + if (namesz & 0x80000000) {
600 + (void)file_printf(ms, ", bad note name size 0x%lx",
601 + (unsigned long)namesz);
605 + if (descsz & 0x80000000) {
606 + (void)file_printf(ms, ", bad note description size 0x%lx",
607 + (unsigned long)descsz);
613 + doff = ELF_ALIGN(offset + namesz);
615 + if (offset + namesz >= size) {
617 + * We're past the end of the buffer.
622 + offset = ELF_ALIGN(doff + descsz);
623 + if (offset + descsz >= size) {
627 + if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 &&
628 + nh_type == NT_GNU_VERSION && descsz == 16) {
630 + (void)memcpy(desc, &nbuf[doff], sizeof(desc));
632 + if (file_printf(ms, ", for GNU/") == -1)
634 + switch (getu32(swap, desc[0])) {
636 + if (file_printf(ms, "Linux") == -1)
640 + if (file_printf(ms, "Hurd") == -1)
643 + case GNU_OS_SOLARIS:
644 + if (file_printf(ms, "Solaris") == -1)
648 + if (file_printf(ms, "<unknown>") == -1)
651 + if (file_printf(ms, " %d.%d.%d", getu32(swap, desc[1]),
652 + getu32(swap, desc[2]), getu32(swap, desc[3])) == -1)
657 + if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0 &&
658 + nh_type == NT_NETBSD_VERSION && descsz == 4) {
660 + (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
661 + desc = getu32(swap, desc);
663 + if (file_printf(ms, ", for NetBSD") == -1)
666 + * The version number used to be stuck as 199905, and was thus
667 + * basically content-free. Newer versions of NetBSD have fixed
668 + * this and now use the encoding of __NetBSD_Version__:
672 + * M = major version
673 + * m = minor version
674 + * r = release ["",A-Z,Z[A-Z] but numeric]
677 + if (desc > 100000000U) {
678 + u_int ver_patch = (desc / 100) % 100;
679 + u_int ver_rel = (desc / 10000) % 100;
680 + u_int ver_min = (desc / 1000000) % 100;
681 + u_int ver_maj = desc / 100000000;
683 + if (file_printf(ms, " %u.%u", ver_maj, ver_min) == -1)
685 + if (ver_rel == 0 && ver_patch != 0) {
686 + if (file_printf(ms, ".%u", ver_patch) == -1)
688 + } else if (ver_rel != 0) {
689 + while (ver_rel > 26) {
690 + file_printf(ms, "Z");
693 + file_printf(ms, "%c", 'A' + ver_rel - 1);
699 - nameoffset = offset;
700 - offset += nh_namesz;
701 - offset = ((offset + 3)/4)*4;
702 + if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0 &&
703 + nh_type == NT_FREEBSD_VERSION && descsz == 4) {
705 + (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
706 + desc = getu32(swap, desc);
707 + if (file_printf(ms, ", for FreeBSD") == -1)
711 - * Sigh. The 2.0.36 kernel in Debian 2.1, at
712 - * least, doesn't correctly implement name
713 - * sections, in core dumps, as specified by
714 - * the "Program Linking" section of "UNIX(R) System
715 - * V Release 4 Programmer's Guide: ANSI C and
716 - * Programming Support Tools", because my copy
717 - * clearly says "The first 'namesz' bytes in 'name'
718 - * contain a *null-terminated* [emphasis mine]
719 - * character representation of the entry's owner
720 - * or originator", but the 2.0.36 kernel code
721 - * doesn't include the terminating null in the
724 - if (os_style == -1) {
725 - if ((nh_namesz == 4 &&
726 - strncmp(&nbuf[nameoffset],
727 - "CORE", 4) == 0) ||
729 - strcmp(&nbuf[nameoffset],
731 - os_style = OS_STYLE_SVR4;
733 - if ((nh_namesz == 8 &&
734 - strcmp(&nbuf[nameoffset],
735 - "FreeBSD") == 0)) {
736 - os_style = OS_STYLE_FREEBSD;
738 - if ((nh_namesz >= 11 &&
739 - strncmp(&nbuf[nameoffset],
740 - "NetBSD-CORE", 11) == 0)) {
741 - os_style = OS_STYLE_NETBSD;
743 - /*@innercontinue@*/ continue;
744 - file_printf(fm, ", %s-style", os_style_names[os_style]);
746 + * Contents is __FreeBSD_version, whose relation to OS
747 + * versions is defined by a huge table in the Porters'
748 + * Handbook. For up to 5.x, the first three digits are
749 + * the version number. For 5.x and higher, the scheme
750 + * is: <major><two digit minor> <0 if release branch,
753 + if (desc / 100000 < 5) {
754 + if (file_printf(ms, " %d.%d", desc / 100000,
755 + desc / 10000 % 10) == -1)
757 + if (desc / 1000 % 10 > 0)
758 + if (file_printf(ms, ".%d", desc / 1000 % 10)
762 + if (file_printf(ms, " %d.%d", desc / 100000,
763 + desc / 1000 % 100) == -1)
767 + if (file_printf(ms, "-CURRENT (rev %d)",
770 + } else if (desc != 0) {
771 + if (file_printf(ms, ".%d", desc / 10) == -1)
778 - if (os_style == OS_STYLE_NETBSD &&
779 - nh_type == NT_NETBSD_CORE_PROCINFO) {
781 + if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 &&
782 + nh_type == NT_OPENBSD_VERSION && descsz == 4) {
783 + if (file_printf(ms, ", for OpenBSD") == -1)
785 + /* Content of note is always 0 */
790 + * Sigh. The 2.0.36 kernel in Debian 2.1, at
791 + * least, doesn't correctly implement name
792 + * sections, in core dumps, as specified by
793 + * the "Program Linking" section of "UNIX(R) System
794 + * V Release 4 Programmer's Guide: ANSI C and
795 + * Programming Support Tools", because my copy
796 + * clearly says "The first 'namesz' bytes in 'name'
797 + * contain a *null-terminated* [emphasis mine]
798 + * character representation of the entry's owner
799 + * or originator", but the 2.0.36 kernel code
800 + * doesn't include the terminating null in the
803 + if ((namesz == 4 && strncmp((char *)&nbuf[noff], "CORE", 4) == 0) ||
804 + (namesz == 5 && strcmp((char *)&nbuf[noff], "CORE") == 0)) {
805 + os_style = OS_STYLE_SVR4;
808 + if ((namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0)) {
809 + os_style = OS_STYLE_FREEBSD;
812 + if ((namesz >= 11 && strncmp((char *)&nbuf[noff], "NetBSD-CORE", 11)
814 + os_style = OS_STYLE_NETBSD;
818 + if (os_style != -1)
819 + if (file_printf(ms, ", %s-style", os_style_names[os_style]) == -1)
822 + if (os_style == OS_STYLE_NETBSD && nh_type == NT_NETBSD_CORE_PROCINFO) {
825 + * Extract the program name. It is at
826 + * offset 0x7c, and is up to 32-bytes,
827 + * including the terminating NUL.
829 + if (file_printf(ms, ", from '%.31s'", &nbuf[doff + 0x7c]) == -1)
833 + * Extract the signal number. It is at
836 + memcpy(&signo, &nbuf[doff + 0x08],
838 + if (file_printf(ms, " (signal %u)", getu32(swap, signo)) == -1)
841 + } else if (os_style != OS_STYLE_NETBSD && nh_type == NT_PRPSINFO) {
845 + * Extract the program name. We assume
846 + * it to be 16 characters (that's what it
847 + * is in SunOS 5.x and Linux).
849 + * Unfortunately, it's at a different offset
850 + * in varous OSes, so try multiple offsets.
851 + * If the characters aren't all printable,
854 + for (i = 0; i < NOFFSETS; i++) {
855 + size_t reloffset = prpsoffsets(i);
856 + size_t noffset = doff + reloffset;
857 + for (j = 0; j < 16; j++, noffset++, reloffset++) {
859 - * Extract the program name. It is at
860 - * offset 0x7c, and is up to 32-bytes,
861 - * including the terminating NUL.
863 - file_printf(fm, ", from '%.31s'", &nbuf[offset + 0x7c]);
866 - * Extract the signal number. It is at
868 + * Make sure we're not past
869 + * the end of the buffer; if
870 + * we are, just give up.
872 - memcpy(&signo, &nbuf[offset + 0x08],
874 - file_printf(fm, " (signal %u)", getu32(fm, signo));
876 - if (os_style != OS_STYLE_NETBSD &&
877 - nh_type == NT_PRPSINFO) {
878 + if (noffset >= size)
882 - * Extract the program name. We assume
883 - * it to be 16 characters (that's what it
884 - * is in SunOS 5.x and Linux).
886 - * Unfortunately, it's at a different offset
887 - * in varous OSes, so try multiple offsets.
888 - * If the characters aren't all printable,
890 + * Make sure we're not past
891 + * the end of the contents;
892 + * if we are, this obviously
893 + * isn't the right offset.
895 - for (i = 0; i < NOFFSETS; i++) {
896 - reloffset = prpsoffsets(i);
897 - noffset = offset + reloffset;
898 - for (j = 0; j < 16;
899 - j++, noffset++, reloffset++) {
901 - * Make sure we're not past
902 - * the end of the buffer; if
903 - * we are, just give up.
909 - * Make sure we're not past
910 - * the end of the contents;
911 - * if we are, this obviously
912 - * isn't the right offset.
914 - if (reloffset >= nh_descsz)
924 - * means we're done.
929 - /*@innerbreak@*/ break;
933 - * character is also
936 -#define isquote(c) (strchr("'\"`", (c)) != NULL)
942 + if (reloffset >= descsz)
948 - * Well, that worked.
953 + * means we're done.
955 - file_printf(fm, ", from '%.16s'",
956 - &nbuf[offset + prpsoffsets(i)]);
957 - /*@innerbreak@*/ break;
968 + * character is also
971 +#define isquote(c) (strchr("'\"`", (c)) != NULL)
972 + if (!isprint(c) || isquote(c))
975 - /*@innerbreak@*/ break;
977 - offset += nh_descsz;
978 - offset = ((offset + 3)/4)*4;
981 + * Well, that worked.
983 + if (file_printf(ms, ", from '%.16s'",
984 + &nbuf[doff + prpsoffsets(i)]) == -1)
1003 +doshn(struct magic_set *ms, int class, int swap, int fd, off_t off, int num,
1009 + if (size != sh_size) {
1010 + if (file_printf(ms, ", corrupted section header size") == -1)
1015 + if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
1020 + for ( ; num; num--) {
1021 + if (read(fd, sh_addr, sh_size) == -1) {
1025 + if (shs_type == SHT_SYMTAB /* || shs_type == SHT_DYNSYM */) {
1026 + if (file_printf(ms, ", not stripped") == -1)
1031 + if (file_printf(ms, ", stripped") == -1)
1037 + * Look through the program headers of an executable image, searching
1038 + * for a PT_INTERP section; if one is found, it's dynamically linked,
1039 + * otherwise it's statically linked.
1042 +dophn_exec(struct magic_set *ms, int class, int swap, int fd, off_t off,
1043 + int num, size_t size)
1047 + const char *linking_style = "statically";
1048 + const char *shared_libraries = "";
1049 + unsigned char nbuf[BUFSIZ];
1051 + size_t offset, align;
1052 + off_t savedoffset;
1054 + if (size != ph_size) {
1055 + if (file_printf(ms, ", corrupted program header size") == -1)
1059 + if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
1064 + for ( ; num; num--) {
1065 + if (read(fd, ph_addr, ph_size) == -1) {
1069 + if ((savedoffset = lseek(fd, (off_t)0, SEEK_CUR)) == (off_t)-1) {
1074 + switch (ph_type) {
1076 + linking_style = "dynamically";
1079 + shared_libraries = " (uses shared libs)";
1082 + if ((align = ph_align) & 0x80000000) {
1083 + if (file_printf(ms,
1084 + ", invalid note alignment 0x%lx",
1085 + (unsigned long)align) == -1)
1090 + * This is a PT_NOTE section; loop through all the notes
1093 + if (lseek(fd, (off_t) ph_offset, SEEK_SET)
1098 + bufsize = read(fd, nbuf, sizeof(nbuf));
1099 + if (bufsize == -1) {
1105 + if (offset >= (size_t)bufsize)
1107 + offset = donote(ms, nbuf, offset,
1108 + (size_t)bufsize, class, swap, align);
1112 + if (lseek(fd, savedoffset + offset, SEEK_SET)
1120 + if (file_printf(ms, ", %s linked%s", linking_style, shared_libraries)
1128 +file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf,
1134 char c[sizeof (int32_t)];
1141 - * If we can't seek, it must be a pipe, socket or fifo.
1142 + * If we cannot seek, it must be a pipe, socket or fifo.
1144 - if((lseek(fm->fd, (off_t)0, SEEK_SET) == (off_t)-1) && (errno == ESPIPE))
1145 - fm->fd = file_pipe2file(fm->fd, fm->buf, fm->nb);
1146 + if((lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) && (errno == ESPIPE))
1147 + fd = file_pipe2file(ms, fd, buf, nbytes);
1150 * ELF executables have multiple section headers in arbitrary
1151 @@ -633,96 +722,101 @@
1152 * Instead we traverse thru all section headers until a symbol table
1153 * one is found or else the binary is stripped.
1155 - if (fm->buf[EI_MAG0] != ELFMAG0
1156 - || (fm->buf[EI_MAG1] != ELFMAG1 && fm->buf[EI_MAG1] != OLFMAG1)
1157 - || fm->buf[EI_MAG2] != ELFMAG2 || fm->buf[EI_MAG3] != ELFMAG3)
1159 + if (buf[EI_MAG0] != ELFMAG0
1160 + || (buf[EI_MAG1] != ELFMAG1 && buf[EI_MAG1] != OLFMAG1)
1161 + || buf[EI_MAG2] != ELFMAG2 || buf[EI_MAG3] != ELFMAG3)
1164 - fm->cls = fm->buf[EI_CLASS];
1166 - if (fm->cls == ELFCLASS32) {
1169 + if (class == ELFCLASS32) {
1171 - if (fm->nb <= sizeof (elfhdr))
1173 + if (nbytes <= sizeof (Elf32_Ehdr))
1178 - (void) memcpy(&elfhdr, fm->buf, sizeof elfhdr);
1180 - fm->swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[EI_DATA];
1182 + (void) memcpy(&elfhdr, buf, sizeof elfhdr);
1183 + swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[5];
1185 - if (getu16(fm, elfhdr.e_type) == ET_CORE)
1186 + if (getu16(swap, elfhdr.e_type) == ET_CORE) {
1189 - getu32(fm, elfhdr.e_phoff),
1190 - getu16(fm, elfhdr.e_phnum),
1191 - getu16(fm, elfhdr.e_phentsize));
1192 + if (dophn_core(ms, class, swap, fd,
1193 + (off_t)getu32(swap, elfhdr.e_phoff),
1194 + getu16(swap, elfhdr.e_phnum),
1195 + (size_t)getu16(swap, elfhdr.e_phentsize)) == -1)
1201 - if (getu16(fm, elfhdr.e_type) == ET_EXEC) {
1203 - getu32(fm, elfhdr.e_phoff),
1204 - getu16(fm, elfhdr.e_phnum),
1205 - getu16(fm, elfhdr.e_phentsize));
1207 + if (getu16(swap, elfhdr.e_type) == ET_EXEC) {
1208 + if (dophn_exec(ms, class, swap,
1209 + fd, (off_t)getu32(swap, elfhdr.e_phoff),
1210 + getu16(swap, elfhdr.e_phnum),
1211 + (size_t)getu16(swap, elfhdr.e_phentsize))
1216 - getu32(fm, elfhdr.e_shoff),
1217 - getu16(fm, elfhdr.e_shnum),
1218 - getu16(fm, elfhdr.e_shentsize));
1219 + if (doshn(ms, class, swap, fd,
1220 + (off_t)getu32(swap, elfhdr.e_shoff),
1221 + getu16(swap, elfhdr.e_shnum),
1222 + (size_t)getu16(swap, elfhdr.e_shentsize)) == -1)
1229 - if (fm->cls == ELFCLASS64) {
1230 + if (class == ELFCLASS64) {
1232 - if (fm->nb <= sizeof (elfhdr))
1234 + if (nbytes <= sizeof (Elf64_Ehdr))
1239 - (void) memcpy(&elfhdr, fm->buf, sizeof elfhdr);
1241 - fm->swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[EI_DATA];
1243 + (void) memcpy(&elfhdr, buf, sizeof elfhdr);
1244 + swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[5];
1246 - if (getu16(fm, elfhdr.e_type) == ET_CORE)
1247 + if (getu16(swap, elfhdr.e_type) == ET_CORE) {
1250 + if (dophn_core(ms, class, swap, fd,
1251 #ifdef USE_ARRAY_FOR_64BIT_TYPES
1252 - getu32(fm, elfhdr.e_phoff[1]),
1253 + (off_t)getu32(swap, elfhdr.e_phoff[1]),
1255 - getu64(fm, elfhdr.e_phoff),
1256 + (off_t)getu64(swap, elfhdr.e_phoff),
1258 - getu16(fm, elfhdr.e_phnum),
1259 - getu16(fm, elfhdr.e_phentsize));
1260 + getu16(swap, elfhdr.e_phnum),
1261 + (size_t)getu16(swap, elfhdr.e_phentsize)) == -1)
1268 - if (getu16(fm, elfhdr.e_type) == ET_EXEC) {
1271 + if (getu16(swap, elfhdr.e_type) == ET_EXEC) {
1272 + if (dophn_exec(ms, class, swap, fd,
1273 #ifdef USE_ARRAY_FOR_64BIT_TYPES
1274 - getu32(fm, elfhdr.e_phoff[1]),
1275 + (off_t)getu32(swap, elfhdr.e_phoff[1]),
1277 - getu64(fm, elfhdr.e_phoff),
1278 + (off_t)getu64(swap, elfhdr.e_phoff),
1280 - getu16(fm, elfhdr.e_phnum),
1281 - getu16(fm, elfhdr.e_phentsize));
1282 + getu16(swap, elfhdr.e_phnum),
1283 + (size_t)getu16(swap, elfhdr.e_phentsize))
1288 + if (doshn(ms, class, swap, fd,
1289 #ifdef USE_ARRAY_FOR_64BIT_TYPES
1290 - getu32(fm, elfhdr.e_shoff[1]),
1291 + (off_t)getu32(swap, elfhdr.e_shoff[1]),
1293 - getu64(fm, elfhdr.e_shoff),
1294 + (off_t)getu64(swap, elfhdr.e_shoff),
1296 - getu16(fm, elfhdr.e_shnum),
1297 - getu16(fm, elfhdr.e_shentsize));
1298 + getu16(swap, elfhdr.e_shnum),
1299 + (size_t)getu16(swap, elfhdr.e_shentsize)) == -1)
1308 -#endif /* BUILTIN_ELF */