]>
git.saurik.com Git - apple/file_cmds.git/blob - file/readelf.c
6c6437d989a193dbf68bfba055ff414e5881d0d3
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
24 /* $OpenBSD: readelf.c,v 1.1 1997/02/09 23:58:33 millert Exp $ */
27 #include <sys/types.h>
39 doshn(fd
, off
, num
, size
, buf
)
47 * This works for both 32-bit and 64-bit ELF formats,
48 * because it looks only at the "sh_type" field, which is
49 * always 32 bits, and is preceded only by the "sh_name"
50 * field which is also always 32 bits, and because it uses
51 * the shdr size from the ELF header rather than using
52 * the size of an "Elf32_Shdr".
54 Elf32_Shdr
*sh
= (Elf32_Shdr
*) buf
;
56 if (lseek(fd
, off
, SEEK_SET
) == -1)
57 error("lseek failed (%s).\n", strerror(errno
));
60 if (read(fd
, buf
, size
) == -1)
61 error("read failed (%s).\n", strerror(errno
));
62 if (sh
->sh_type
== SHT_SYMTAB
) {
63 (void) printf (", not stripped");
67 (void) printf (", stripped");
71 * Look through the program headers of an executable image, searching
72 * for a PT_INTERP section; if one is found, it's dynamically linked,
73 * otherwise it's statically linked.
76 dophn_exec(fd
, off
, num
, size
, buf
)
83 /* I am not sure if this works for 64 bit elf formats */
84 Elf32_Phdr
*ph
= (Elf32_Phdr
*) buf
;
86 if (lseek(fd
, off
, SEEK_SET
) == -1)
87 error("lseek failed (%s).\n", strerror(errno
));
90 if (read(fd
, buf
, size
) == -1)
91 error("read failed (%s).\n", strerror(errno
));
92 if (ph
->p_type
== PT_INTERP
) {
94 * Has an interpreter - must be a dynamically-linked
97 printf(", dynamically linked");
101 printf(", statically linked");
104 size_t prpsoffsets
[] = {
109 #define NOFFSETS (sizeof prpsoffsets / sizeof prpsoffsets[0])
112 * Look through the program headers of an executable image, searching
113 * for a PT_NOTE section of type NT_PRPSINFO, with a name "CORE"; if one
114 * is found, try looking in various places in its contents for a 16-character
115 * string containing only printable characters - if found, that string
116 * should be the name of the program that dropped core.
117 * Note: right after that 16-character string is, at least in SunOS 5.x
118 * (and possibly other SVR4-flavored systems) and Linux, a longer string
119 * (80 characters, in 5.x, probably other SVR4-flavored systems, and Linux)
120 * containing the start of the command line for that program.
123 dophn_core(fd
, off
, num
, size
, buf
)
131 * This doesn't work for 64-bit ELF, as the "p_offset" field is
132 * 64 bits in 64-bit ELF.
135 * This doesn't work for 64-bit ELF, as the "p_offset" field is
136 * 64 bits in 64-bit ELF.
138 Elf32_Phdr
*ph
= (Elf32_Phdr
*) buf
;
140 size_t offset
, noffset
, reloffset
;
146 for ( ; num
; num
--) {
147 if (lseek(fd
, off
, SEEK_SET
) == -1)
148 error("lseek failed (%s).\n", strerror(errno
));
149 if (read(fd
, buf
, size
) == -1)
150 error("read failed (%s).\n", strerror(errno
));
152 if (ph
->p_type
!= PT_NOTE
)
154 if (lseek(fd
, ph
->p_offset
, SEEK_SET
) == -1)
155 error("lseek failed (%s).\n", strerror(errno
));
156 bufsize
= read(fd
, nbuf
, BUFSIZ
);
158 error("read failed (%s).\n", strerror(errno
));
161 if (offset
>= bufsize
)
163 nh
= (Elf32_Nhdr
*)&nbuf
[offset
];
164 offset
+= sizeof *nh
;
167 * If this note isn't an NT_PRPSINFO note, it's
168 * not what we're looking for.
170 if (nh
->n_type
!= NT_PRPSINFO
) {
171 offset
+= nh
->n_namesz
;
172 offset
= ((offset
+ 3)/4)*4;
173 offset
+= nh
->n_descsz
;
174 offset
= ((offset
+ 3)/4)*4;
179 * Make sure this note has the name "CORE".
181 if (offset
+ nh
->n_namesz
>= bufsize
) {
183 * We're past the end of the buffer.
187 if (nh
->n_namesz
!= 5
188 || strcmp(&nbuf
[offset
], "CORE") != 0)
190 offset
+= nh
->n_namesz
;
191 offset
= ((offset
+ 3)/4)*4;
194 * Extract the program name. We assume it to be
195 * 16 characters (that's what it is in SunOS 5.x
198 * Unfortunately, it's at a different offset in
199 * SunOS 5.x and Linux, so try multiple offsets.
200 * If the characters aren't all printable, reject
203 for (i
= 0; i
< NOFFSETS
; i
++) {
204 reloffset
= prpsoffsets
[i
];
205 noffset
= offset
+ reloffset
;
207 j
++, noffset
++, reloffset
++) {
209 * Make sure we're not past the end
210 * of the buffer; if we are, just
213 if (noffset
>= bufsize
)
217 * Make sure we're not past the
218 * end of the contents; if we
219 * are, this obviously isn't
222 if (reloffset
>= nh
->n_descsz
)
226 if (c
!= '\0' && !isprint(c
))
233 printf(", from '%.16s'",
234 &nbuf
[offset
+ prpsoffsets
[i
]]);
240 offset
+= nh
->n_descsz
;
241 offset
= ((offset
+ 3)/4)*4;
247 tryelf(fd
, buf
, nbytes
)
254 char c
[sizeof (int32
)];
258 * ELF executables have multiple section headers in arbitrary
259 * file locations and thus file(1) cannot determine it from easily.
260 * Instead we traverse thru all section headers until a symbol table
261 * one is found or else the binary is stripped.
263 if (buf
[EI_MAG0
] != ELFMAG0
|| buf
[EI_MAG1
] != ELFMAG1
264 || buf
[EI_MAG2
] != ELFMAG2
|| buf
[EI_MAG3
] != ELFMAG3
)
268 if (buf
[4] == ELFCLASS32
) {
270 if (nbytes
<= sizeof (Elf32_Ehdr
))
275 (void) memcpy(&elfhdr
, buf
, sizeof elfhdr
);
277 * If the system byteorder does not equal the
278 * object byteorder then don't test.
279 * XXX - we could conceivably fix up the "dophn_XXX()" and
280 * "doshn()" routines to extract stuff in the right
283 if ((u
.c
[sizeof(long) - 1] + 1) == elfhdr
.e_ident
[5]) {
284 if (elfhdr
.e_type
== ET_CORE
)
285 dophn_core(fd
, elfhdr
.e_phoff
, elfhdr
.e_phnum
,
286 elfhdr
.e_phentsize
, buf
);
288 if (elfhdr
.e_type
== ET_EXEC
) {
289 dophn_exec(fd
, elfhdr
.e_phoff
,
291 elfhdr
.e_phentsize
, buf
);
293 doshn(fd
, elfhdr
.e_shoff
, elfhdr
.e_shnum
,
294 elfhdr
.e_shentsize
, buf
);
300 if (buf
[4] == ELFCLASS64
) {
302 if (nbytes
<= sizeof (Elf64_Ehdr
))
307 (void) memcpy(&elfhdr
, buf
, sizeof elfhdr
);
310 * If the system byteorder does not equal the
311 * object byteorder then don't test.
312 * XXX - we could conceivably fix up the "dophn_XXX()" and
313 * "doshn()" routines to extract stuff in the right
316 if ((u
.c
[sizeof(long) - 1] + 1) == elfhdr
.e_ident
[5]) {
318 if (elfhdr
.e_type
== ET_CORE
)
319 dophn_core(fd
, elfhdr
.e_phoff
, elfhdr
.e_phnum
,
320 elfhdr
.e_phentsize
, buf
);
325 if (elfhdr
.e_type
== ET_EXEC
) {
326 dophn_exec(fd
, elfhdr
.e_phoff
,
328 elfhdr
.e_phentsize
, buf
);
331 doshn(fd
, elfhdr
.e_shoff
, elfhdr
.e_shnum
,
332 elfhdr
.e_shentsize
, buf
);