3 static const char rcsid[] =
17 static void doshn __P((int, off_t, int, size_t, char *));
18 static void dophn_exec __P((int, off_t, int, size_t, char *));
19 static void dophn_core __P((int, off_t, int, size_t, char *));
22 doshn(fd, off, num, size, buf)
30 * This works for both 32-bit and 64-bit ELF formats,
31 * because it looks only at the "sh_type" field, which is
32 * always 32 bits, and is preceded only by the "sh_name"
33 * field which is also always 32 bits, and because it uses
34 * the shdr size from the ELF header rather than using
35 * the size of an "Elf32_Shdr".
37 Elf32_Shdr *sh = (Elf32_Shdr *) buf;
39 if (lseek(fd, off, SEEK_SET) == -1)
40 err(1, "lseek failed");
43 if (read(fd, buf, size) == -1)
44 err(1, "read failed");
45 if (sh->sh_type == SHT_SYMTAB) {
46 (void) printf (", not stripped");
50 (void) printf (", stripped");
54 * Look through the program headers of an executable image, searching
55 * for a PT_INTERP section; if one is found, it's dynamically linked,
56 * otherwise it's statically linked.
59 dophn_exec(fd, off, num, size, buf)
66 /* I am not sure if this works for 64 bit elf formats */
67 Elf32_Phdr *ph = (Elf32_Phdr *) buf;
69 if (lseek(fd, off, SEEK_SET) == -1)
70 err(1, "lseek failed");
73 if (read(fd, buf, size) == -1)
74 err(1, "read failed");
75 if (ph->p_type == PT_INTERP) {
77 * Has an interpreter - must be a dynamically-linked
80 printf(", dynamically linked");
84 printf(", statically linked");
87 size_t prpsoffsets[] = {
93 #define NOFFSETS (sizeof prpsoffsets / sizeof prpsoffsets[0])
96 * Look through the program headers of an executable image, searching
97 * for a PT_NOTE section of type NT_PRPSINFO, with a name "CORE" or
98 * "FreeBSD"; if one is found, try looking in various places in its
99 * contents for a 16-character string containing only printable
100 * characters - if found, that string should be the name of the program
101 * that dropped core. Note: right after that 16-character string is,
102 * at least in SunOS 5.x (and possibly other SVR4-flavored systems) and
103 * Linux, a longer string (80 characters, in 5.x, probably other
104 * SVR4-flavored systems, and Linux) containing the start of the
105 * command line for that program.
108 dophn_core(fd, off, num, size, buf)
116 * This doesn't work for 64-bit ELF, as the "p_offset" field is
117 * 64 bits in 64-bit ELF.
120 * This doesn't work for 64-bit ELF, as the "p_offset" field is
121 * 64 bits in 64-bit ELF.
123 Elf32_Phdr *ph = (Elf32_Phdr *) buf;
125 size_t offset, noffset, reloffset;
131 for ( ; num; num--) {
132 if (lseek(fd, off, SEEK_SET) == -1)
133 err(1, "lseek failed");
134 if (read(fd, buf, size) == -1)
135 err(1, "read failed");
137 if (ph->p_type != PT_NOTE)
139 if (lseek(fd, ph->p_offset, SEEK_SET) == -1)
140 err(1, "lseek failed");
141 bufsize = read(fd, nbuf, BUFSIZ);
143 err(1, "read failed");
146 if (offset >= bufsize)
148 nh = (Elf32_Nhdr *)&nbuf[offset];
149 offset += sizeof *nh;
152 * If this note isn't an NT_PRPSINFO note, it's
153 * not what we're looking for.
155 if (nh->n_type != NT_PRPSINFO) {
156 offset += nh->n_namesz;
157 offset = ((offset + 3)/4)*4;
158 offset += nh->n_descsz;
159 offset = ((offset + 3)/4)*4;
164 * Make sure this note has the name "CORE" or
167 if (offset + nh->n_namesz >= bufsize) {
169 * We're past the end of the buffer.
173 if (nbuf[offset + nh->n_namesz - 1] != '\0' ||
174 (strcmp(&nbuf[offset], "CORE") != 0 &&
175 strcmp(&nbuf[offset], "FreeBSD") != 0))
177 offset += nh->n_namesz;
178 offset = ((offset + 3)/4)*4;
181 * Extract the program name. We assume it to be
182 * 16 characters (that's what it is in SunOS 5.x
185 * Unfortunately, it's at a different offset in
186 * SunOS 5.x and Linux, so try multiple offsets.
187 * If the characters aren't all printable, reject
190 for (i = 0; i < NOFFSETS; i++) {
191 reloffset = prpsoffsets[i];
192 noffset = offset + reloffset;
194 j++, noffset++, reloffset++) {
196 * Make sure we're not past the end
197 * of the buffer; if we are, just
200 if (noffset >= bufsize)
204 * Make sure we're not past the
205 * end of the contents; if we
206 * are, this obviously isn't
209 if (reloffset >= nh->n_descsz)
213 if (c != '\0' && !isprint(c))
220 printf(", from '%.16s'",
221 &nbuf[offset + prpsoffsets[i]]);
227 offset += nh->n_descsz;
228 offset = ((offset + 3)/4)*4;
234 tryelf(fd, buf, nbytes)
241 char c[sizeof (int32)];
245 * ELF executables have multiple section headers in arbitrary
246 * file locations and thus file(1) cannot determine it from easily.
247 * Instead we traverse thru all section headers until a symbol table
248 * one is found or else the binary is stripped.
250 if (buf[EI_MAG0] != ELFMAG0 || buf[EI_MAG1] != ELFMAG1
251 || buf[EI_MAG2] != ELFMAG2 || buf[EI_MAG3] != ELFMAG3)
255 if (buf[4] == ELFCLASS32) {
257 if (nbytes <= sizeof (Elf32_Ehdr))
262 (void) memcpy(&elfhdr, buf, sizeof elfhdr);
264 * If the system byteorder does not equal the
265 * object byteorder then don't test.
266 * XXX - we could conceivably fix up the "dophn_XXX()" and
267 * "doshn()" routines to extract stuff in the right
270 if ((u.c[sizeof(long) - 1] + 1) == elfhdr.e_ident[5]) {
271 if (elfhdr.e_type == ET_CORE)
272 dophn_core(fd, elfhdr.e_phoff, elfhdr.e_phnum,
273 elfhdr.e_phentsize, buf);
275 if (elfhdr.e_type == ET_EXEC) {
276 dophn_exec(fd, elfhdr.e_phoff,
278 elfhdr.e_phentsize, buf);
280 doshn(fd, elfhdr.e_shoff, elfhdr.e_shnum,
281 elfhdr.e_shentsize, buf);
287 if (buf[4] == ELFCLASS64) {
289 if (nbytes <= sizeof (Elf64_Ehdr))
294 (void) memcpy(&elfhdr, buf, sizeof elfhdr);
297 * If the system byteorder does not equal the
298 * object byteorder then don't test.
299 * XXX - we could conceivably fix up the "dophn_XXX()" and
300 * "doshn()" routines to extract stuff in the right
303 if ((u.c[sizeof(long) - 1] + 1) == elfhdr.e_ident[5]) {
305 if (elfhdr.e_type == ET_CORE)
306 dophn_core(fd, elfhdr.e_phoff, elfhdr.e_phnum,
307 elfhdr.e_phentsize, buf);
312 if (elfhdr.e_type == ET_EXEC) {
313 dophn_exec(fd, elfhdr.e_phoff,
315 elfhdr.e_phentsize, buf);
318 doshn(fd, elfhdr.e_shoff, elfhdr.e_shnum,
319 elfhdr.e_shentsize, buf);