]> git.pld-linux.org Git - packages/rpm.git/blob - rpm-file-readelf.patch
- %addusertogroup macro for RPM
[packages/rpm.git] / rpm-file-readelf.patch
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
4 @@ -1,3 +1,31 @@
5 +/*
6 + * Copyright (c) Christos Zoulas 2003.
7 + * All Rights Reserved.
8 + * 
9 + * Redistribution and use in source and binary forms, with or without
10 + * modification, are permitted provided that the following conditions
11 + * are met:
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.
20 + *  
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
31 + * SUCH DAMAGE.
32 + */
33  #include "system.h"
34  
35  #ifdef BUILTIN_ELF
36 @@ -8,6 +36,9 @@
37  FILE_RCSID("@(#)Id: readelf.c,v 1.22 2002/07/03 18:26:38 christos Exp ")
38  
39  /*@access fmagic @*/
40 +static size_t donote(const fmagic fm, unsigned char *, size_t, size_t, int);
41 +
42 +#define        ELF_ALIGN(a)    ((((a) + align - 1) / align) * align)
43  
44  /*@-bounds@*/
45  static uint16_t
46 @@ -88,7 +119,6 @@
47  #define shs_type       (fm->cls == ELFCLASS32          \
48                          ? getu32(fm, sh32.sh_type)     \
49                          : getu32(fm, sh64.sh_type))
50 -
51  #define ph_addr                (fm->cls == ELFCLASS32          \
52                          ? (void *) &ph32               \
53                          : (void *) &ph64)
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))
64 -
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          \
71 +                        ? sizeof nh32                  \
72 +                        : sizeof nh64)
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          \
89                          ? prpsoffsets32[i]             \
90                          : prpsoffsets64[i])
91  
92 -/*@-bounds@*/
93 -static void
94 -doshn(fmagic fm, off_t off, int num, size_t size)
95 -       /*@globals fileSystem @*/
96 -       /*@modifies fm, fileSystem @*/
97 -{
98 -       Elf32_Shdr sh32;
99 -       Elf64_Shdr sh64;
100 -
101 -       if (size != sh_size) {
102 -               error(EXIT_FAILURE, 0, "corrupted program header size.\n");
103 -               /*@notreached@*/
104 -       }
105 -
106 -       if (lseek(fm->fd, off, SEEK_SET) == -1) {
107 -               error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
108 -               /*@notreached@*/
109 -       }
110 -
111 -       for ( ; num; num--) {
112 -               if (read(fm->fd, sh_addr, size) == -1) {
113 -                       error(EXIT_FAILURE, 0, "read failed (%s).\n", strerror(errno));
114 -                       /*@notreached@*/
115 -               }
116 -               if (shs_type == SHT_SYMTAB /* || shs_type == SHT_DYNSYM */) {
117 -                       file_printf(fm, ", not stripped");
118 -                       return;
119 -               }
120 -       }
121 -       file_printf(fm, ", stripped");
122 -}
123 -/*@=bounds@*/
124 -
125 -/*
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.
129 - */
130 -/*@-bounds@*/
131 -static void
132 -dophn_exec(fmagic fm, off_t off, int num, size_t size)
133 -       /*@globals fileSystem @*/
134 -       /*@modifies fm, fileSystem @*/
135 -{
136 -       Elf32_Phdr ph32;
137 -       Elf32_Nhdr *nh32 = NULL;
138 -       Elf64_Phdr ph64;
139 -       Elf64_Nhdr *nh64 = NULL;
140 -       char *linking_style = "statically";
141 -       char *shared_libraries = "";
142 -       char nbuf[BUFSIZ];
143 -       int nb;
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))
147 -       int printed;
148 -
149 -       if (size != ph_size) {
150 -               error(EXIT_FAILURE, 0, "corrupted program header size.\n");
151 -               /*@notreached@*/
152 -       }
153 -
154 -       if (lseek(fm->fd, off, SEEK_SET) == -1) {
155 -               error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
156 -               /*@notreached@*/
157 -       }
158 -
159 -       for ( ; num; num--) {
160 -               /* Read the program header data. */
161 -               nb = read(fm->fd, ph_addr, size);
162 -               if (nb == -1) {
163 -                       error(EXIT_FAILURE, 0, "read failed (%s).\n", strerror(errno));
164 -                       /*@notreached@*/
165 -               }
166 -
167 -               /* XXX Elf64 notes cannot be read, so don't attempt for now. */
168 -#if !defined(__i386__)
169 -               if (ph_type == PT_NOTE) 
170 -                       break;          
171 -#endif
172 -
173 -               switch (ph_type) {
174 -               case PT_DYNAMIC:
175 -                       linking_style = "dynamically";
176 -                       /*@switchbreak@*/ break;
177 -               case PT_INTERP:
178 -                       shared_libraries = " (uses shared libs)";
179 -                       /*@switchbreak@*/ break;
180 -               case PT_NOTE:
181 -                       /*
182 -                        * This is a PT_NOTE section; loop through all the notes
183 -                        * in the section.
184 -                        */
185 -                       if (lseek(fm->fd, (off_t) ph_offset, SEEK_SET) == -1) {
186 -                               error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
187 -                               /*@notreached@*/
188 -                       }
189 -
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);
194 -                       if (nb == -1) {
195 -                               error(EXIT_FAILURE, 0, ": " "read failed (%s).\n",
196 -                                   strerror(errno));
197 -                               /*@notreached@*/
198 -                       }
199 -                       offset = 0;
200 -                       printed = 0;
201 -                       for (;;) {
202 -                               end = offset + 12;
203 -                               if (end >= nb)
204 -                                       /*@innerbreak@*/ break;
205 -
206 -                               if (fm->cls == ELFCLASS32)
207 -                                       nh32 = (Elf32_Nhdr *)&nbuf[offset];
208 -                               else
209 -                                       nh64 = (Elf64_Nhdr *)&nbuf[offset];
210 -
211 -                               offset = end;   /* skip note header. */
212 -
213 -                               /* XXX Avoid notes that are not 1-16 bytes */
214 -                               if (nh_namesz <= 0 || nh_descsz <= 0)
215 -                                       break;
216 -                               if (nh_namesz  > 16 || nh_descsz > 16)
217 -                                       break;
218 -
219 -                               end = offset    + ALIGNED_LEN (nh_namesz)
220 -                                               + ALIGNED_LEN (nh_descsz);
221 -                               if (end > nb)
222 -                                       /*@innerbreak@*/ break;
223 -
224 -                               noff = offset;
225 -                               doff = ALIGNED_LEN(offset + nh_namesz);
226 -                               offset = end;
227 -
228 -                               if (printed)
229 -                                       continue;
230 -
231 -                               if (nh_namesz == 4 &&
232 -                                   strcmp(&nbuf[noff], "GNU") == 0 &&
233 -                                   nh_type == NT_GNU_VERSION &&
234 -                                   nh_descsz == 16) {
235 -                                       uint32_t *desc =
236 -                                           (uint32_t *)&nbuf[doff];
237 -
238 -                                       if (!printed)
239 -                                       file_printf(fm, ", for GNU/");
240 -                                       switch (getu32(fm, desc[0])) {
241 -                                       case GNU_OS_LINUX:
242 -                                               file_printf(fm, "Linux");
243 -                                               /*@switchbreak@*/ break;
244 -                                       case GNU_OS_HURD:
245 -                                               file_printf(fm, "Hurd");
246 -                                               /*@switchbreak@*/ break;
247 -                                       case GNU_OS_SOLARIS:
248 -                                               file_printf(fm, "Solaris");
249 -                                               /*@switchbreak@*/ break;
250 -                                       default:
251 -                                               file_printf(fm, "<unknown>");
252 -                                               /*@switchbreak@*/ break;
253 -                                       }
254 -                                       file_printf(fm, " %d.%d.%d",
255 -                                           getu32(fm, desc[1]),
256 -                                           getu32(fm, desc[2]),
257 -                                           getu32(fm, desc[3]));
258 -                                       printed = 1;
259 -                               }
260 -
261 -                               if (nh_namesz == 7 &&
262 -                                   strcmp(&nbuf[noff], "NetBSD") == 0 &&
263 -                                   nh_type == NT_NETBSD_VERSION &&
264 -                                   nh_descsz == 4) {
265 -                                       file_printf(fm, ", for NetBSD");
266 -                                       /*
267 -                                        * Version number is stuck at 199905,
268 -                                        * and hence is basically content-free.
269 -                                        */
270 -                                       printed = 1;
271 -                               }
272 -
273 -                               if (nh_namesz == 8 &&
274 -                                   strcmp(&nbuf[noff], "FreeBSD") == 0 &&
275 -                                   nh_type == NT_FREEBSD_VERSION &&
276 -                                   nh_descsz == 4) {
277 -                                       uint32_t desc = getu32(fm,
278 -                                           *(uint32_t *)&nbuf[doff]);
279 -                                       file_printf(fm, ", for FreeBSD");
280 -                                       /*
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.
288 -                                        */
289 -
290 -                                       file_printf(fm, " %d.%d", desc / 100000,
291 -                                           desc / 10000 % 10);
292 -                                       if (desc / 1000 % 10 > 0)
293 -                                               file_printf(fm, ".%d",
294 -                                                   desc / 1000 % 10);
295 -                                       printed = 1;
296 -                               }
297 -
298 -                               if (nh_namesz == 8 &&
299 -                                   strcmp(&nbuf[noff], "OpenBSD") == 0 &&
300 -                                   nh_type == NT_OPENBSD_VERSION &&
301 -                                   nh_descsz == 4) {
302 -                                       file_printf(fm, ", for OpenBSD");
303 -                                       /* Content of note is always 0 */
304 -                                       printed = 1;
305 -                               }
306 -                       }
307 -                       if ((lseek(fm->fd, ph_offset + offset, SEEK_SET)) == -1) {
308 -                           error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
309 -                           /*@notreached@*/
310 -                       }
311 -                       /*@switchbreak@*/ break;
312 -               }
313 -       }
314 -       file_printf(fm, ", %s linked%s", linking_style, shared_libraries);
315 -}
316 -/*@=bounds@*/
317 -
318  #ifdef ELFCORE
319  /*@unchecked@*/ /*@observer@*/
320  static size_t  prpsoffsets32[] = {
321 @@ -405,15 +210,10 @@
322         /*@modifies fm, fileSystem @*/
323  {
324         Elf32_Phdr ph32;
325 -       Elf32_Nhdr *nh32 = NULL;
326         Elf64_Phdr ph64;
327 -       Elf64_Nhdr *nh64 = NULL;
328 -       size_t offset, nameoffset, noffset, reloffset;
329 -       unsigned char c;
330 -       int i, j;
331 -       char nbuf[BUFSIZ];
332 -       int nb;
333 -       int os_style = -1;
334 +       size_t offset;
335 +       unsigned char nbuf[BUFSIZ];
336 +       ssize_t bufsize;
337  
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.
342          */
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));
347                         /*@notreached@*/
348                 }
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));
352                         /*@notreached@*/
353                 }
354 @@ -440,175 +240,390 @@
355                  * This is a PT_NOTE section; loop through all the notes
356                  * in the section.
357                  */
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));
361                         /*@notreached@*/
362                 }
363 -               nb = read(fm->fd, nbuf, BUFSIZ);
364 -               if (nb == -1) {
365 +               bufsize = read(fm->fd, nbuf, BUFSIZ);
366 +               if (bufsize == -1) {
367                         error(EXIT_FAILURE, 0, ": " "read failed (%s).\n", strerror(errno));
368                         /*@notreached@*/
369                 }
370                 offset = 0;
371                 for (;;) {
372 -                       if (offset >= nb)
373 +                       if (offset >= (size_t)bufsize)
374                                 /*@innerbreak@*/ break;
375 -                       if (fm->cls == ELFCLASS32)
376 -                               nh32 = (Elf32_Nhdr *)&nbuf[offset];
377 -                       else
378 -                               nh64 = (Elf64_Nhdr *)&nbuf[offset];
379 -                       offset += 12;
380 +                       offset = donote(fm, nbuf, offset, (size_t)bufsize,
381 +                           4);
382  
383 -                       /*
384 -                        * Check whether this note has the name "CORE" or
385 -                        * "FreeBSD", or "NetBSD-CORE".
386 -                        */
387 -                       if (offset + nh_namesz >= nb) {
388 -                               /*
389 -                                * We're past the end of the buffer.
390 -                                */
391 -                               /*@innerbreak@*/ break;
392 -                       }
393 +               }
394 +       }
395 +}
396 +/*@=bounds@*/
397 +#endif
398  
399 -                       nameoffset = offset;
400 -                       offset += nh_namesz;
401 -                       offset = ((offset + 3)/4)*4;
402 +/*@-bounds@*/
403 +static size_t
404 +donote(const fmagic fm, unsigned char *nbuf, size_t offset, size_t size,
405 +    int align)
406 +{
407 +       Elf32_Nhdr nh32;
408 +       Elf64_Nhdr nh64;
409 +       size_t noff, doff;
410 +#ifdef ELFCORE
411 +       int os_style = -1;
412 +#endif
413  
414 -                       /*
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
426 -                        * name....
427 -                        */
428 -                       if (os_style == -1) {
429 -                               if ((nh_namesz == 4 &&
430 -                                    strncmp(&nbuf[nameoffset],
431 -                                           "CORE", 4) == 0) ||
432 -                                   (nh_namesz == 5 &&
433 -                                    strcmp(&nbuf[nameoffset],
434 -                                           "CORE") == 0)) {
435 -                                       os_style = OS_STYLE_SVR4;
436 -                               } else
437 -                               if ((nh_namesz == 8 &&
438 -                                    strcmp(&nbuf[nameoffset],
439 -                                           "FreeBSD") == 0)) {
440 -                                       os_style = OS_STYLE_FREEBSD;
441 -                               } else
442 -                               if ((nh_namesz >= 11 &&
443 -                                    strncmp(&nbuf[nameoffset],
444 -                                            "NetBSD-CORE", 11) == 0)) {
445 -                                       os_style = OS_STYLE_NETBSD;
446 -                               } else
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));
451 +       else
452 +               memcpy(&nh64, &nbuf[offset], sizeof(nh64));
453 +       offset += nh_size;
454 +
455 +       if ((nh_namesz == 0) && (nh_descsz == 0)) {
456 +               /*
457 +                * We're out of note headers.
458 +                */
459 +               return offset;
460 +       }
461 +
462 +       noff = offset;
463 +       doff = ELF_ALIGN(offset + nh_namesz);
464 +
465 +       if (offset + nh_namesz >= size) {
466 +               /*
467 +                * We're past the end of the buffer.
468 +                */
469 +               return doff;
470 +       }
471 +
472 +       offset = ELF_ALIGN(doff + nh_descsz);
473 +       if (offset + nh_descsz >= size)
474 +               return offset;
475 +
476 +       if (nh_namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 &&
477 +           nh_type == NT_GNU_VERSION && nh_descsz == 16) {
478 +               uint32_t desc[4];
479 +               (void)memcpy(desc, &nbuf[doff], sizeof(desc));
480 +
481 +               file_printf(fm, ", for GNU/");
482 +               switch (getu32(fm, desc[0])) {
483 +               case GNU_OS_LINUX:
484 +                       file_printf(fm, "Linux");
485 +                       break;
486 +               case GNU_OS_HURD:
487 +                       file_printf(fm, "Hurd");
488 +                       break;
489 +               case GNU_OS_SOLARIS:
490 +                       file_printf(fm, "Solaris");
491 +                       break;
492 +               default:
493 +                       file_printf(fm, "<unknown>");
494 +               }
495 +               file_printf(fm, " %d.%d.%d", getu32(fm, desc[1]),
496 +                   getu32(fm, desc[2]), getu32(fm, desc[3]));
497 +               return size;
498 +       }
499 +
500 +       if (nh_namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0 &&
501 +           nh_type == NT_NETBSD_VERSION && nh_descsz == 4) {
502 +               uint32_t desc;
503 +               (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
504 +               desc = getu32(fm, desc);
505 +
506 +               file_printf(fm, ", for NetBSD");
507 +               /*
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__:
511 +                *
512 +                *      MMmmrrpp00
513 +                *
514 +                * M = major version
515 +                * m = minor version
516 +                * r = release ["",A-Z,Z[A-Z] but numeric]
517 +                * p = patchlevel
518 +                */
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;
524 +
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");
531 +                                       ver_rel -= 26;
532 +                               }
533 +                               file_printf(fm, "%c", 'A' + ver_rel - 1);
534                         }
535 +               }
536 +               return size;
537 +       }
538  
539 -                       if (os_style == OS_STYLE_NETBSD &&
540 -                           nh_type == NT_NETBSD_CORE_PROCINFO) {
541 -                               uint32_t signo;
542 +       if (nh_namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0 &&
543 +           nh_type == NT_FREEBSD_VERSION && nh_descsz == 4) {
544 +               uint32_t desc;
545 +               (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
546 +               desc = getu32(fm, desc);
547 +               file_printf(fm, ", for FreeBSD");
548 +               /*
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.
553 +                */
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);
557 +               return size;
558 +       }
559  
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 */
564 +               return size;
565 +       }
566 +
567 +       /*
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
579 +        * name....
580 +        */
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;
584 +       } 
585 +
586 +       if ((nh_namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0)) {
587 +               os_style = OS_STYLE_FREEBSD;
588 +       }
589 +
590 +       if ((nh_namesz >= 11 && strncmp((char *)&nbuf[noff], "NetBSD-CORE", 11)
591 +           == 0)) {
592 +               os_style = OS_STYLE_NETBSD;
593 +       }
594 +
595 +#ifdef ELFCORE
596 +       if (os_style != -1)
597 +               file_printf(fm, ", %s-style", os_style_names[os_style]);
598 +
599 +       if (os_style == OS_STYLE_NETBSD && nh_type == NT_NETBSD_CORE_PROCINFO) {
600 +               uint32_t signo;
601 +               /*
602 +                * Extract the program name.  It is at
603 +                * offset 0x7c, and is up to 32-bytes,
604 +                * including the terminating NUL.
605 +                */
606 +               file_printf(fm, ", from '%.31s'", &nbuf[doff + 0x7c]);
607 +               
608 +               /*
609 +                * Extract the signal number.  It is at
610 +                * offset 0x08.
611 +                */
612 +               memcpy(&signo, &nbuf[doff + 0x08],
613 +                   sizeof(signo));
614 +               file_printf(fm, " (signal %u)", getu32(fm, signo));
615 +               return size;
616 +       } else if (os_style != OS_STYLE_NETBSD && nh_type == NT_PRPSINFO) {
617 +               size_t i, j;
618 +               unsigned char c;
619 +               /*
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).
623 +                *
624 +                * Unfortunately, it's at a different offset
625 +                * in varous OSes, so try multiple offsets.
626 +                * If the characters aren't all printable,
627 +                * reject it.
628 +                */
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++) {
633                                 /*
634 -                                * Extract the program name.  It is at
635 -                                * offset 0x7c, and is up to 32-bytes,
636 -                                * including the terminating NUL.
637 -                                */
638 -                               file_printf(fm, ", from '%.31s'", &nbuf[offset + 0x7c]);
639 -                               
640 -                               /*
641 -                                * Extract the signal number.  It is at
642 -                                * offset 0x08.
643 +                                * Make sure we're not past
644 +                                * the end of the buffer; if
645 +                                * we are, just give up.
646                                  */
647 -                               memcpy(&signo, &nbuf[offset + 0x08],
648 -                                   sizeof(signo));
649 -                               file_printf(fm, " (signal %u)", getu32(fm, signo));
650 -                       } else
651 -                       if (os_style != OS_STYLE_NETBSD &&
652 -                           nh_type == NT_PRPSINFO) {
653 +                               if (noffset >= size)
654 +                                       goto tryanother;
655 +
656                                 /*
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).
660 -                                *
661 -                                * Unfortunately, it's at a different offset
662 -                                * in varous OSes, so try multiple offsets.
663 -                                * If the characters aren't all printable,
664 -                                * reject it.
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.
669                                  */
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++) {
675 -                                               /*
676 -                                                * Make sure we're not past
677 -                                                * the end of the buffer; if
678 -                                                * we are, just give up.
679 -                                                */
680 -                                               if (noffset >= nb)
681 -                                                       goto tryanother;
682 -
683 -                                               /*
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.
688 -                                                */
689 -                                               if (reloffset >= nh_descsz)
690 -                                                       goto tryanother;
691 -
692 -                                               c = nbuf[noffset];
693 -                                               if (c == '\0') {
694 -                                                       /*
695 -                                                        * A '\0' at the
696 -                                                        * beginning is
697 -                                                        * obviously wrong.
698 -                                                        * Any other '\0'
699 -                                                        * means we're done.
700 -                                                        */
701 -                                                       if (j == 0)
702 -                                                               goto tryanother;
703 -                                                       else
704 -                                                               /*@innerbreak@*/ break;
705 -                                               } else {
706 -                                                       /*
707 -                                                        * A nonprintable
708 -                                                        * character is also
709 -                                                        * wrong.
710 -                                                        */
711 -#define isquote(c) (strchr("'\"`", (c)) != NULL)
712 -                                                       if (!isprint(c) ||
713 -                                                            isquote(c))
714 -                                                               goto tryanother;
715 -                                               }
716 -                                       }
717 +                               if (reloffset >= nh_descsz)
718 +                                       goto tryanother;
719  
720 +                               c = nbuf[noffset];
721 +                               if (c == '\0') {
722                                         /*
723 -                                        * Well, that worked.
724 +                                        * A '\0' at the
725 +                                        * beginning is
726 +                                        * obviously wrong.
727 +                                        * Any other '\0'
728 +                                        * means we're done.
729                                          */
730 -                                       file_printf(fm, ", from '%.16s'",
731 -                                           &nbuf[offset + prpsoffsets(i)]);
732 -                                       /*@innerbreak@*/ break;
733 -
734 -                               tryanother:
735 -                                       ;
736 +                                       if (j == 0)
737 +                                               goto tryanother;
738 +                                       else
739 +                                               break;
740 +                               } else {
741 +                                       /*
742 +                                        * A nonprintable
743 +                                        * character is also
744 +                                        * wrong.
745 +                                        */
746 +#define isquote(c) (strchr("'\"`", (c)) != NULL)
747 +                                       if (!isprint(c) || isquote(c))
748 +                                               goto tryanother;
749                                 }
750 -                               /*@innerbreak@*/ break;
751                         }
752 -                       offset += nh_descsz;
753 -                       offset = ((offset + 3)/4)*4;
754 +
755 +                       /*
756 +                        * Well, that worked.
757 +                        */
758 +                       file_printf(fm, ", from '%.16s'",
759 +                           &nbuf[doff + prpsoffsets(i)]);
760 +                       return size;
761 +
762 +               tryanother:
763 +                       ;
764                 }
765 +               return offset;
766         }
767 +#endif
768 +       return offset;
769 +}
770 +
771 +static void
772 +doshn(fmagic fm, off_t off, int num, size_t size)
773 +       /*@globals fileSystem @*/
774 +       /*@modifies fm, fileSystem @*/
775 +{
776 +       Elf32_Shdr sh32;
777 +       Elf64_Shdr sh64;
778 +
779 +       if (size != sh_size) {
780 +               error(EXIT_FAILURE, 0, "corrupted program header size.\n");
781 +               /*@notreached@*/
782 +       }
783 +
784 +       if (lseek(fm->fd, off, SEEK_SET) == (off_t)-1) {
785 +               error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
786 +               /*@notreached@*/
787 +       }
788 +
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));
792 +                       /*@notreached@*/
793 +               }
794 +               if (shs_type == SHT_SYMTAB /* || shs_type == SHT_DYNSYM */) {
795 +                       file_printf(fm, ", not stripped");
796 +                       return;
797 +               }
798 +       }
799 +       file_printf(fm, ", stripped");
800 +}
801 +/*@=bounds@*/
802 +
803 +/*
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.
807 + */
808 +/*@-bounds@*/
809 +static void
810 +dophn_exec(fmagic fm, off_t off, int num, size_t size)
811 +       /*@globals fileSystem @*/
812 +       /*@modifies fm, fileSystem @*/
813 +{
814 +       Elf32_Phdr ph32;
815 +       Elf64_Phdr ph64;
816 +       const char *linking_style = "statically";
817 +       const char *shared_libraries = "";
818 +       unsigned char nbuf[BUFSIZ];
819 +       int bufsize;
820 +       size_t offset;
821 +       off_t savedoffset;
822 +
823 +       if (size != ph_size) {
824 +               error(EXIT_FAILURE, 0, "corrupted program header size.\n");
825 +               /*@notreached@*/
826 +       }
827 +
828 +       if (lseek(fm->fd, off, SEEK_SET) == (off_t)-1) {
829 +               error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
830 +               /*@notreached@*/
831 +       }
832 +
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));
836 +                       /*@notreached@*/
837 +               }
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));
840 +                       /*@notreached@*/
841 +               }
842 +
843 +               switch (ph_type) {
844 +               case PT_DYNAMIC:
845 +                       linking_style = "dynamically";
846 +                       /*@switchbreak@*/ break;
847 +               case PT_INTERP:
848 +                       shared_libraries = " (uses shared libs)";
849 +                       /*@switchbreak@*/ break;
850 +               case PT_NOTE:
851 +                       /*
852 +                        * This is a PT_NOTE section; loop through all the notes
853 +                        * in the section.
854 +                        */
855 +                       if (lseek(fm->fd, (off_t) ph_offset, SEEK_SET) == -1) {
856 +                               error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
857 +                               /*@notreached@*/
858 +                       }
859 +                       bufsize = read(fm->fd, nbuf, sizeof(nbuf));
860 +                       if (bufsize == -1) {
861 +                               error(EXIT_FAILURE, 0, ": " "read failed (%s).\n",
862 +                                   strerror(errno));
863 +                               /*@notreached@*/
864 +                       }
865 +                       offset = 0;
866 +                       for (;;) {
867 +                               if (offset >= (size_t)bufsize)
868 +                                       /*@innerbreak@*/ break;
869 +                               offset = donote(fm, nbuf, offset,
870 +                                   (size_t)bufsize, ph_align);
871 +                       }
872 +                       if ((lseek(fm->fd, savedoffset + offset, SEEK_SET)) == (off_t)-1) {
873 +                           error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
874 +                           /*@notreached@*/
875 +                       }
876 +                       /*@switchbreak@*/ break;
877 +               }
878 +       }
879 +       file_printf(fm, ", %s linked%s", linking_style, shared_libraries);
880  }
881  /*@=bounds@*/
882 -#endif
883  
884  /*@-bounds@*/
885  void
886 @@ -638,6 +653,7 @@
887             || fm->buf[EI_MAG2] != ELFMAG2 || fm->buf[EI_MAG3] != ELFMAG3)
888             return;
889  
890 +
891         fm->cls = fm->buf[EI_CLASS];
892  
893         if (fm->cls == ELFCLASS32) {
This page took 0.283626 seconds and 3 git commands to generate.