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-06-14 17:14:56.000000000 +0200
6 + * Copyright (c) Christos Zoulas 2003.
7 + * All Rights Reserved.
9 + * Redistribution and use in source and binary forms, with or without
10 + * modification, are permitted provided that the following conditions
12 + * 1. Redistributions of source code must retain the above copyright
13 + * notice immediately at the beginning of the file, without modification,
14 + * this list of conditions, and the following disclaimer.
15 + * 2. Redistributions in binary form must reproduce the above copyright
16 + * notice, this list of conditions and the following disclaimer in the
17 + * documentation and/or other materials provided with the distribution.
18 + * 3. The name of the author may not be used to endorse or promote products
19 + * derived from this software without specific prior written permission.
21 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
25 + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 FILE_RCSID("@(#)Id: readelf.c,v 1.22 2002/07/03 18:26:38 christos Exp ")
40 +static size_t donote(const fmagic fm, unsigned char *, size_t, size_t, int);
42 +#define ELF_ALIGN(a) ((((a) + align - 1) / align) * align)
47 #define shs_type (fm->cls == ELFCLASS32 \
48 ? getu32(fm, sh32.sh_type) \
49 : getu32(fm, sh64.sh_type))
51 #define ph_addr (fm->cls == ELFCLASS32 \
54 @@ -101,252 +131,27 @@
55 #define ph_offset (fm->cls == ELFCLASS32 \
56 ? getu32(fm, ph32.p_offset) \
57 : getu64(fm, ph64.p_offset))
58 -#define ph_align (fm->cls == ELFCLASS32 \
59 - ? (ph32.p_align ? getu32(fm, ph32.p_align) : 4) \
60 - : (ph64.p_align ? getu64(fm, ph64.p_align) : 4))
61 -#define ph_filesz (fm->cls == ELFCLASS32 \
62 - ? getu32(fm, ph32.p_filesz) \
63 - : getu64(fm, ph64.p_filesz))
65 +#define ph_align (int)((fm->cls == ELFCLASS32 \
66 + ? (off_t) (ph32.p_align ? \
67 + getu32(fm, ph32.p_align) : 4) \
68 + : (off_t) (ph64.p_align ? \
69 + getu64(fm, ph64.p_align) : 4)))
70 +#define nh_size (fm->cls == ELFCLASS32 \
73 #define nh_type (fm->cls == ELFCLASS32 \
74 - ? getu32(fm, nh32->n_type) \
75 - : getu32(fm, nh64->n_type))
76 + ? getu32(fm, nh32.n_type) \
77 + : getu32(fm, nh64.n_type))
78 #define nh_namesz (fm->cls == ELFCLASS32 \
79 - ? getu32(fm, nh32->n_namesz) \
80 - : getu32(fm, nh64->n_namesz))
81 + ? getu32(fm, nh32.n_namesz) \
82 + : getu32(fm, nh64.n_namesz))
83 #define nh_descsz (fm->cls == ELFCLASS32 \
84 - ? getu32(fm, nh32->n_descsz) \
85 - : getu32(fm, nh64->n_descsz))
86 + ? getu32(fm, nh32.n_descsz) \
87 + : getu32(fm, nh64.n_descsz))
88 #define prpsoffsets(i) (fm->cls == ELFCLASS32 \
94 -doshn(fmagic fm, off_t off, int num, size_t size)
95 - /*@globals fileSystem @*/
96 - /*@modifies fm, fileSystem @*/
101 - if (size != sh_size) {
102 - error(EXIT_FAILURE, 0, "corrupted program header size.\n");
106 - if (lseek(fm->fd, off, SEEK_SET) == -1) {
107 - error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
111 - for ( ; num; num--) {
112 - if (read(fm->fd, sh_addr, size) == -1) {
113 - error(EXIT_FAILURE, 0, "read failed (%s).\n", strerror(errno));
116 - if (shs_type == SHT_SYMTAB /* || shs_type == SHT_DYNSYM */) {
117 - file_printf(fm, ", not stripped");
121 - file_printf(fm, ", stripped");
126 - * Look through the program headers of an executable image, searching
127 - * for a PT_INTERP section; if one is found, it's dynamically linked,
128 - * otherwise it's statically linked.
132 -dophn_exec(fmagic fm, off_t off, int num, size_t size)
133 - /*@globals fileSystem @*/
134 - /*@modifies fm, fileSystem @*/
137 - Elf32_Nhdr *nh32 = NULL;
139 - Elf64_Nhdr *nh64 = NULL;
140 - char *linking_style = "statically";
141 - char *shared_libraries = "";
144 - size_t nbufsize, offset, end, noff, doff;
145 - size_t align = (fm->cls == ELFCLASS32 ? 4 : 8);
146 -#define ALIGNED_LEN(len) (((len) + align - 1) & ~(align - 1))
149 - if (size != ph_size) {
150 - error(EXIT_FAILURE, 0, "corrupted program header size.\n");
154 - if (lseek(fm->fd, off, SEEK_SET) == -1) {
155 - error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
159 - for ( ; num; num--) {
160 - /* Read the program header data. */
161 - nb = read(fm->fd, ph_addr, size);
163 - error(EXIT_FAILURE, 0, "read failed (%s).\n", strerror(errno));
167 - /* XXX Elf64 notes cannot be read, so don't attempt for now. */
168 -#if !defined(__i386__)
169 - if (ph_type == PT_NOTE)
175 - linking_style = "dynamically";
176 - /*@switchbreak@*/ break;
178 - shared_libraries = " (uses shared libs)";
179 - /*@switchbreak@*/ break;
182 - * This is a PT_NOTE section; loop through all the notes
185 - if (lseek(fm->fd, (off_t) ph_offset, SEEK_SET) == -1) {
186 - error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
190 - /* XXX Read only the notes section. */
191 - nbufsize = (ph_filesz < sizeof(nbuf)
192 - ? ph_filesz : sizeof(nbuf));
193 - nb = read(fm->fd, nbuf, nbufsize);
195 - error(EXIT_FAILURE, 0, ": " "read failed (%s).\n",
204 - /*@innerbreak@*/ break;
206 - if (fm->cls == ELFCLASS32)
207 - nh32 = (Elf32_Nhdr *)&nbuf[offset];
209 - nh64 = (Elf64_Nhdr *)&nbuf[offset];
211 - offset = end; /* skip note header. */
213 - /* XXX Avoid notes that are not 1-16 bytes */
214 - if (nh_namesz <= 0 || nh_descsz <= 0)
216 - if (nh_namesz > 16 || nh_descsz > 16)
219 - end = offset + ALIGNED_LEN (nh_namesz)
220 - + ALIGNED_LEN (nh_descsz);
222 - /*@innerbreak@*/ break;
225 - doff = ALIGNED_LEN(offset + nh_namesz);
231 - if (nh_namesz == 4 &&
232 - strcmp(&nbuf[noff], "GNU") == 0 &&
233 - nh_type == NT_GNU_VERSION &&
236 - (uint32_t *)&nbuf[doff];
239 - file_printf(fm, ", for GNU/");
240 - switch (getu32(fm, desc[0])) {
242 - file_printf(fm, "Linux");
243 - /*@switchbreak@*/ break;
245 - file_printf(fm, "Hurd");
246 - /*@switchbreak@*/ break;
247 - case GNU_OS_SOLARIS:
248 - file_printf(fm, "Solaris");
249 - /*@switchbreak@*/ break;
251 - file_printf(fm, "<unknown>");
252 - /*@switchbreak@*/ break;
254 - file_printf(fm, " %d.%d.%d",
255 - getu32(fm, desc[1]),
256 - getu32(fm, desc[2]),
257 - getu32(fm, desc[3]));
261 - if (nh_namesz == 7 &&
262 - strcmp(&nbuf[noff], "NetBSD") == 0 &&
263 - nh_type == NT_NETBSD_VERSION &&
265 - file_printf(fm, ", for NetBSD");
267 - * Version number is stuck at 199905,
268 - * and hence is basically content-free.
273 - if (nh_namesz == 8 &&
274 - strcmp(&nbuf[noff], "FreeBSD") == 0 &&
275 - nh_type == NT_FREEBSD_VERSION &&
277 - uint32_t desc = getu32(fm,
278 - *(uint32_t *)&nbuf[doff]);
279 - file_printf(fm, ", for FreeBSD");
281 - * Contents is __FreeBSD_version,
282 - * whose relation to OS versions is
283 - * defined by a huge table in the
284 - * Porters' Handbook. Happily, the
285 - * first three digits are the version
286 - * number, at least in versions of
287 - * FreeBSD that use this note.
290 - file_printf(fm, " %d.%d", desc / 100000,
291 - desc / 10000 % 10);
292 - if (desc / 1000 % 10 > 0)
293 - file_printf(fm, ".%d",
298 - if (nh_namesz == 8 &&
299 - strcmp(&nbuf[noff], "OpenBSD") == 0 &&
300 - nh_type == NT_OPENBSD_VERSION &&
302 - file_printf(fm, ", for OpenBSD");
303 - /* Content of note is always 0 */
307 - if ((lseek(fm->fd, ph_offset + offset, SEEK_SET)) == -1) {
308 - error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
311 - /*@switchbreak@*/ break;
314 - file_printf(fm, ", %s linked%s", linking_style, shared_libraries);
319 /*@unchecked@*/ /*@observer@*/
320 static size_t prpsoffsets32[] = {
321 @@ -405,15 +210,10 @@
322 /*@modifies fm, fileSystem @*/
325 - Elf32_Nhdr *nh32 = NULL;
327 - Elf64_Nhdr *nh64 = NULL;
328 - size_t offset, nameoffset, noffset, reloffset;
335 + unsigned char nbuf[BUFSIZ];
338 if (size != ph_size) {
339 error(EXIT_FAILURE, 0, "corrupted program header size.\n");
340 @@ -424,11 +224,11 @@
341 * Loop through all the program headers.
343 for ( ; num; num--) {
344 - if (lseek(fm->fd, off, SEEK_SET) == -1) {
345 + if (lseek(fm->fd, off, SEEK_SET) == (off_t)-1) {
346 error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
349 - if (read(fm->fd, ph_addr, size) == -1) {
350 + if (read(fm->fd, ph_addr, ph_size) == -1) {
351 error(EXIT_FAILURE, 0, "read failed (%s).\n", strerror(errno));
354 @@ -440,175 +240,390 @@
355 * This is a PT_NOTE section; loop through all the notes
358 - if (lseek(fm->fd, (off_t) ph_offset, SEEK_SET) == -1) {
359 + if (lseek(fm->fd, (off_t) ph_offset, SEEK_SET) == (off_t)-1) {
360 error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
363 - nb = read(fm->fd, nbuf, BUFSIZ);
365 + bufsize = read(fm->fd, nbuf, BUFSIZ);
366 + if (bufsize == -1) {
367 error(EXIT_FAILURE, 0, ": " "read failed (%s).\n", strerror(errno));
373 + if (offset >= (size_t)bufsize)
374 /*@innerbreak@*/ break;
375 - if (fm->cls == ELFCLASS32)
376 - nh32 = (Elf32_Nhdr *)&nbuf[offset];
378 - nh64 = (Elf64_Nhdr *)&nbuf[offset];
380 + offset = donote(fm, nbuf, offset, (size_t)bufsize,
384 - * Check whether this note has the name "CORE" or
385 - * "FreeBSD", or "NetBSD-CORE".
387 - if (offset + nh_namesz >= nb) {
389 - * We're past the end of the buffer.
391 - /*@innerbreak@*/ break;
399 - nameoffset = offset;
400 - offset += nh_namesz;
401 - offset = ((offset + 3)/4)*4;
404 +donote(const fmagic fm, unsigned char *nbuf, size_t offset, size_t size,
415 - * Sigh. The 2.0.36 kernel in Debian 2.1, at
416 - * least, doesn't correctly implement name
417 - * sections, in core dumps, as specified by
418 - * the "Program Linking" section of "UNIX(R) System
419 - * V Release 4 Programmer's Guide: ANSI C and
420 - * Programming Support Tools", because my copy
421 - * clearly says "The first 'namesz' bytes in 'name'
422 - * contain a *null-terminated* [emphasis mine]
423 - * character representation of the entry's owner
424 - * or originator", but the 2.0.36 kernel code
425 - * doesn't include the terminating null in the
428 - if (os_style == -1) {
429 - if ((nh_namesz == 4 &&
430 - strncmp(&nbuf[nameoffset],
431 - "CORE", 4) == 0) ||
433 - strcmp(&nbuf[nameoffset],
435 - os_style = OS_STYLE_SVR4;
437 - if ((nh_namesz == 8 &&
438 - strcmp(&nbuf[nameoffset],
439 - "FreeBSD") == 0)) {
440 - os_style = OS_STYLE_FREEBSD;
442 - if ((nh_namesz >= 11 &&
443 - strncmp(&nbuf[nameoffset],
444 - "NetBSD-CORE", 11) == 0)) {
445 - os_style = OS_STYLE_NETBSD;
447 - /*@innercontinue@*/ continue;
448 - file_printf(fm, ", %s-style", os_style_names[os_style]);
449 + if (fm->cls == ELFCLASS32)
450 + memcpy(&nh32, &nbuf[offset], sizeof(nh32));
452 + memcpy(&nh64, &nbuf[offset], sizeof(nh64));
455 + if ((nh_namesz == 0) && (nh_descsz == 0)) {
457 + * We're out of note headers.
463 + doff = ELF_ALIGN(offset + nh_namesz);
465 + if (offset + nh_namesz >= size) {
467 + * We're past the end of the buffer.
472 + offset = ELF_ALIGN(doff + nh_descsz);
473 + if (offset + nh_descsz >= size)
476 + if (nh_namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 &&
477 + nh_type == NT_GNU_VERSION && nh_descsz == 16) {
479 + (void)memcpy(desc, &nbuf[doff], sizeof(desc));
481 + file_printf(fm, ", for GNU/");
482 + switch (getu32(fm, desc[0])) {
484 + file_printf(fm, "Linux");
487 + file_printf(fm, "Hurd");
489 + case GNU_OS_SOLARIS:
490 + file_printf(fm, "Solaris");
493 + file_printf(fm, "<unknown>");
495 + file_printf(fm, " %d.%d.%d", getu32(fm, desc[1]),
496 + getu32(fm, desc[2]), getu32(fm, desc[3]));
500 + if (nh_namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0 &&
501 + nh_type == NT_NETBSD_VERSION && nh_descsz == 4) {
503 + (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
504 + desc = getu32(fm, desc);
506 + file_printf(fm, ", for NetBSD");
508 + * The version number used to be stuck as 199905, and was thus
509 + * basically content-free. Newer versions of NetBSD have fixed
510 + * this and now use the encoding of __NetBSD_Version__:
514 + * M = major version
515 + * m = minor version
516 + * r = release ["",A-Z,Z[A-Z] but numeric]
519 + if (desc > 100000000U) {
520 + u_int ver_patch = (desc / 100) % 100;
521 + u_int ver_rel = (desc / 10000) % 100;
522 + u_int ver_min = (desc / 1000000) % 100;
523 + u_int ver_maj = desc / 100000000;
525 + file_printf(fm, " %u.%u", ver_maj, ver_min);
526 + if (ver_rel == 0 && ver_patch != 0) {
527 + file_printf(fm, ".%u", ver_patch);
528 + } else if (ver_rel != 0) {
529 + while (ver_rel > 26) {
530 + file_printf(fm, "Z");
533 + file_printf(fm, "%c", 'A' + ver_rel - 1);
539 - if (os_style == OS_STYLE_NETBSD &&
540 - nh_type == NT_NETBSD_CORE_PROCINFO) {
542 + if (nh_namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0 &&
543 + nh_type == NT_FREEBSD_VERSION && nh_descsz == 4) {
545 + (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
546 + desc = getu32(fm, desc);
547 + file_printf(fm, ", for FreeBSD");
549 + * Contents is __FreeBSD_version, whose relation to OS versions
550 + * is defined by a huge table in the Porters' Handbook. Happily,
551 + * the first three digits are the version number, at least in
552 + * versions of FreeBSD that use this note.
554 + file_printf(fm, " %d.%d", desc / 100000, desc / 10000 % 10);
555 + if (desc / 1000 % 10 > 0)
556 + file_printf(fm, ".%d", desc / 1000 % 10);
560 + if (nh_namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 &&
561 + nh_type == NT_OPENBSD_VERSION && nh_descsz == 4) {
562 + file_printf(fm, ", for OpenBSD");
563 + /* Content of note is always 0 */
568 + * Sigh. The 2.0.36 kernel in Debian 2.1, at
569 + * least, doesn't correctly implement name
570 + * sections, in core dumps, as specified by
571 + * the "Program Linking" section of "UNIX(R) System
572 + * V Release 4 Programmer's Guide: ANSI C and
573 + * Programming Support Tools", because my copy
574 + * clearly says "The first 'namesz' bytes in 'name'
575 + * contain a *null-terminated* [emphasis mine]
576 + * character representation of the entry's owner
577 + * or originator", but the 2.0.36 kernel code
578 + * doesn't include the terminating null in the
581 + if ((nh_namesz == 4 && strncmp((char *)&nbuf[noff], "CORE", 4) == 0) ||
582 + (nh_namesz == 5 && strcmp((char *)&nbuf[noff], "CORE") == 0)) {
583 + os_style = OS_STYLE_SVR4;
586 + if ((nh_namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0)) {
587 + os_style = OS_STYLE_FREEBSD;
590 + if ((nh_namesz >= 11 && strncmp((char *)&nbuf[noff], "NetBSD-CORE", 11)
592 + os_style = OS_STYLE_NETBSD;
596 + if (os_style != -1)
597 + file_printf(fm, ", %s-style", os_style_names[os_style]);
599 + if (os_style == OS_STYLE_NETBSD && nh_type == NT_NETBSD_CORE_PROCINFO) {
602 + * Extract the program name. It is at
603 + * offset 0x7c, and is up to 32-bytes,
604 + * including the terminating NUL.
606 + file_printf(fm, ", from '%.31s'", &nbuf[doff + 0x7c]);
609 + * Extract the signal number. It is at
612 + memcpy(&signo, &nbuf[doff + 0x08],
614 + file_printf(fm, " (signal %u)", getu32(fm, signo));
616 + } else if (os_style != OS_STYLE_NETBSD && nh_type == NT_PRPSINFO) {
620 + * Extract the program name. We assume
621 + * it to be 16 characters (that's what it
622 + * is in SunOS 5.x and Linux).
624 + * Unfortunately, it's at a different offset
625 + * in varous OSes, so try multiple offsets.
626 + * If the characters aren't all printable,
629 + for (i = 0; i < NOFFSETS; i++) {
630 + size_t reloffset = prpsoffsets(i);
631 + size_t noffset = doff + reloffset;
632 + for (j = 0; j < 16; j++, noffset++, reloffset++) {
634 - * Extract the program name. It is at
635 - * offset 0x7c, and is up to 32-bytes,
636 - * including the terminating NUL.
638 - file_printf(fm, ", from '%.31s'", &nbuf[offset + 0x7c]);
641 - * Extract the signal number. It is at
643 + * Make sure we're not past
644 + * the end of the buffer; if
645 + * we are, just give up.
647 - memcpy(&signo, &nbuf[offset + 0x08],
649 - file_printf(fm, " (signal %u)", getu32(fm, signo));
651 - if (os_style != OS_STYLE_NETBSD &&
652 - nh_type == NT_PRPSINFO) {
653 + if (noffset >= size)
657 - * Extract the program name. We assume
658 - * it to be 16 characters (that's what it
659 - * is in SunOS 5.x and Linux).
661 - * Unfortunately, it's at a different offset
662 - * in varous OSes, so try multiple offsets.
663 - * If the characters aren't all printable,
665 + * Make sure we're not past
666 + * the end of the contents;
667 + * if we are, this obviously
668 + * isn't the right offset.
670 - for (i = 0; i < NOFFSETS; i++) {
671 - reloffset = prpsoffsets(i);
672 - noffset = offset + reloffset;
673 - for (j = 0; j < 16;
674 - j++, noffset++, reloffset++) {
676 - * Make sure we're not past
677 - * the end of the buffer; if
678 - * we are, just give up.
684 - * Make sure we're not past
685 - * the end of the contents;
686 - * if we are, this obviously
687 - * isn't the right offset.
689 - if (reloffset >= nh_descsz)
699 - * means we're done.
704 - /*@innerbreak@*/ break;
708 - * character is also
711 -#define isquote(c) (strchr("'\"`", (c)) != NULL)
717 + if (reloffset >= nh_descsz)
723 - * Well, that worked.
728 + * means we're done.
730 - file_printf(fm, ", from '%.16s'",
731 - &nbuf[offset + prpsoffsets(i)]);
732 - /*@innerbreak@*/ break;
743 + * character is also
746 +#define isquote(c) (strchr("'\"`", (c)) != NULL)
747 + if (!isprint(c) || isquote(c))
750 - /*@innerbreak@*/ break;
752 - offset += nh_descsz;
753 - offset = ((offset + 3)/4)*4;
756 + * Well, that worked.
758 + file_printf(fm, ", from '%.16s'",
759 + &nbuf[doff + prpsoffsets(i)]);
772 +doshn(fmagic fm, off_t off, int num, size_t size)
773 + /*@globals fileSystem @*/
774 + /*@modifies fm, fileSystem @*/
779 + if (size != sh_size) {
780 + error(EXIT_FAILURE, 0, "corrupted program header size.\n");
784 + if (lseek(fm->fd, off, SEEK_SET) == (off_t)-1) {
785 + error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
789 + for ( ; num; num--) {
790 + if (read(fm->fd, sh_addr, sh_size) == -1) {
791 + error(EXIT_FAILURE, 0, "read failed (%s).\n", strerror(errno));
794 + if (shs_type == SHT_SYMTAB /* || shs_type == SHT_DYNSYM */) {
795 + file_printf(fm, ", not stripped");
799 + file_printf(fm, ", stripped");
804 + * Look through the program headers of an executable image, searching
805 + * for a PT_INTERP section; if one is found, it's dynamically linked,
806 + * otherwise it's statically linked.
810 +dophn_exec(fmagic fm, off_t off, int num, size_t size)
811 + /*@globals fileSystem @*/
812 + /*@modifies fm, fileSystem @*/
816 + const char *linking_style = "statically";
817 + const char *shared_libraries = "";
818 + unsigned char nbuf[BUFSIZ];
823 + if (size != ph_size) {
824 + error(EXIT_FAILURE, 0, "corrupted program header size.\n");
828 + if (lseek(fm->fd, off, SEEK_SET) == (off_t)-1) {
829 + error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
833 + for ( ; num; num--) {
834 + if (read(fm->fd, ph_addr, ph_size) == -1) {
835 + error(EXIT_FAILURE, 0, "read failed (%s).\n", strerror(errno));
838 + if ((savedoffset = lseek(fm->fd, (off_t)0, SEEK_CUR)) == (off_t)-1) {
839 + error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
845 + linking_style = "dynamically";
846 + /*@switchbreak@*/ break;
848 + shared_libraries = " (uses shared libs)";
849 + /*@switchbreak@*/ break;
852 + * This is a PT_NOTE section; loop through all the notes
855 + if (lseek(fm->fd, (off_t) ph_offset, SEEK_SET) == -1) {
856 + error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
859 + bufsize = read(fm->fd, nbuf, sizeof(nbuf));
860 + if (bufsize == -1) {
861 + error(EXIT_FAILURE, 0, ": " "read failed (%s).\n",
867 + if (offset >= (size_t)bufsize)
868 + /*@innerbreak@*/ break;
869 + offset = donote(fm, nbuf, offset,
870 + (size_t)bufsize, ph_align);
872 + if ((lseek(fm->fd, savedoffset + offset, SEEK_SET)) == (off_t)-1) {
873 + error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
876 + /*@switchbreak@*/ break;
879 + file_printf(fm, ", %s linked%s", linking_style, shared_libraries);
887 || fm->buf[EI_MAG2] != ELFMAG2 || fm->buf[EI_MAG3] != ELFMAG3)
891 fm->cls = fm->buf[EI_CLASS];
893 if (fm->cls == ELFCLASS32) {