Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

file/src/readelf.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) Christos Zoulas 2003.
00003  * All Rights Reserved.
00004  * 
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice immediately at the beginning of the file, without modification,
00010  *    this list of conditions, and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. The name of the author may not be used to endorse or promote products
00015  *    derived from this software without specific prior written permission.
00016  *  
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
00021  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  */
00029 #include "system.h"
00030 
00031 #ifdef BUILTIN_ELF
00032 #include "file.h"
00033 #include "readelf.h"
00034 #include "debug.h"
00035 
00036 FILE_RCSID("@(#)Id: readelf.c,v 1.22 2002/07/03 18:26:38 christos Exp ")
00037 
00038 /*@access fmagic @*/
00039 static size_t donote(const fmagic fm, unsigned char *, size_t, size_t, int);
00040 
00041 #define ELF_ALIGN(a)    ((((a) + align - 1) / align) * align)
00042 
00043 /*@-bounds@*/
00044 static uint16_t
00045 getu16(const fmagic fm, uint16_t value)
00046         /*@*/
00047 {
00048         union {
00049                 uint16_t ui;
00050                 char c[2];
00051         } retval, tmpval;
00052 
00053         if (fm->swap) {
00054                 tmpval.ui = value;
00055 
00056                 retval.c[0] = tmpval.c[1];
00057                 retval.c[1] = tmpval.c[0];
00058                 
00059                 return retval.ui;
00060         } else
00061                 return value;
00062 }
00063 
00064 static uint32_t
00065 getu32(const fmagic fm, uint32_t value)
00066         /*@*/
00067 {
00068         union {
00069                 uint32_t ui;
00070                 char c[4];
00071         } retval, tmpval;
00072 
00073         if (fm->swap) {
00074                 tmpval.ui = value;
00075 
00076                 retval.c[0] = tmpval.c[3];
00077                 retval.c[1] = tmpval.c[2];
00078                 retval.c[2] = tmpval.c[1];
00079                 retval.c[3] = tmpval.c[0];
00080                 
00081                 return retval.ui;
00082         } else
00083                 return value;
00084 }
00085 
00086 static uint64_t
00087 getu64(const fmagic fm, uint64_t value)
00088         /*@*/
00089 {
00090         union {
00091                 uint64_t ui;
00092                 char c[8];
00093         } retval, tmpval;
00094 
00095         if (fm->swap) {
00096                 tmpval.ui = value;
00097 
00098                 retval.c[0] = tmpval.c[7];
00099                 retval.c[1] = tmpval.c[6];
00100                 retval.c[2] = tmpval.c[5];
00101                 retval.c[3] = tmpval.c[4];
00102                 retval.c[4] = tmpval.c[3];
00103                 retval.c[5] = tmpval.c[2];
00104                 retval.c[6] = tmpval.c[1];
00105                 retval.c[7] = tmpval.c[0];
00106                 
00107                 return retval.ui;
00108         } else
00109                 return value;
00110 }
00111 /*@=bounds@*/
00112 
00113 #define sh_addr         (fm->cls == ELFCLASS32          \
00114                          ? (void *) &sh32               \
00115                          : (void *) &sh64)
00116 #define sh_size         (fm->cls == ELFCLASS32          \
00117                          ? sizeof sh32                  \
00118                          : sizeof sh64)
00119 #define shs_type        (fm->cls == ELFCLASS32          \
00120                          ? getu32(fm, sh32.sh_type)     \
00121                          : getu32(fm, sh64.sh_type))
00122 #define ph_addr         (fm->cls == ELFCLASS32          \
00123                          ? (void *) &ph32               \
00124                          : (void *) &ph64)
00125 #define ph_size         (fm->cls == ELFCLASS32          \
00126                          ? sizeof ph32                  \
00127                          : sizeof ph64)
00128 #define ph_type         (fm->cls == ELFCLASS32          \
00129                          ? getu32(fm, ph32.p_type)      \
00130                          : getu32(fm, ph64.p_type))
00131 #define ph_offset       (fm->cls == ELFCLASS32          \
00132                          ? getu32(fm, ph32.p_offset)    \
00133                          : getu64(fm, ph64.p_offset))
00134 #define ph_align        (int)((fm->cls == ELFCLASS32    \
00135                          ? (off_t) (ph32.p_align ?      \
00136                             getu32(fm, ph32.p_align) : 4) \
00137                          : (off_t) (ph64.p_align ?      \
00138                             getu64(fm, ph64.p_align) : 4)))
00139 #define ph_filesz       (fm->cls == ELFCLASS32            \
00140                         ? getu32(fm, ph32.p_filesz)  \
00141                         : getu64(fm, ph64.p_filesz))
00142 #define nh_size         (fm->cls == ELFCLASS32          \
00143                          ? sizeof nh32                  \
00144                          : sizeof nh64)
00145 #define nh_type         (fm->cls == ELFCLASS32          \
00146                          ? getu32(fm, nh32.n_type)      \
00147                          : getu32(fm, nh64.n_type))
00148 #define nh_namesz       (fm->cls == ELFCLASS32          \
00149                          ? getu32(fm, nh32.n_namesz)    \
00150                          : getu32(fm, nh64.n_namesz))
00151 #define nh_descsz       (fm->cls == ELFCLASS32          \
00152                          ? getu32(fm, nh32.n_descsz)    \
00153                          : getu32(fm, nh64.n_descsz))
00154 #define prpsoffsets(i)  (fm->cls == ELFCLASS32          \
00155                          ? prpsoffsets32[i]             \
00156                          : prpsoffsets64[i])
00157 
00158 #ifdef ELFCORE
00159 /*@unchecked@*/ /*@observer@*/
00160 static size_t   prpsoffsets32[] = {
00161         8,              /* FreeBSD */
00162         28,             /* Linux 2.0.36 */
00163         32,             /* Linux (I forget which kernel version) */
00164         84              /* SunOS 5.x */
00165 };
00166 
00167 /*@unchecked@*/ /*@observer@*/
00168 static size_t   prpsoffsets64[] = {
00169        120              /* SunOS 5.x, 64-bit */
00170 };
00171 
00172 #define NOFFSETS32      (sizeof prpsoffsets32 / sizeof prpsoffsets32[0])
00173 #define NOFFSETS64      (sizeof prpsoffsets64 / sizeof prpsoffsets64[0])
00174 
00175 #define NOFFSETS        (fm->cls == ELFCLASS32 ? NOFFSETS32 : NOFFSETS64)
00176 
00177 /*
00178  * Look through the program headers of an executable image, searching
00179  * for a PT_NOTE section of type NT_PRPSINFO, with a name "CORE" or
00180  * "FreeBSD"; if one is found, try looking in various places in its
00181  * contents for a 16-character string containing only printable
00182  * characters - if found, that string should be the name of the program
00183  * that dropped core.  Note: right after that 16-character string is,
00184  * at least in SunOS 5.x (and possibly other SVR4-flavored systems) and
00185  * Linux, a longer string (80 characters, in 5.x, probably other
00186  * SVR4-flavored systems, and Linux) containing the start of the
00187  * command line for that program.
00188  *
00189  * The signal number probably appears in a section of type NT_PRSTATUS,
00190  * but that's also rather OS-dependent, in ways that are harder to
00191  * dissect with heuristics, so I'm not bothering with the signal number.
00192  * (I suppose the signal number could be of interest in situations where
00193  * you don't have the binary of the program that dropped core; if you
00194  * *do* have that binary, the debugger will probably tell you what
00195  * signal it was.)
00196  */
00197 
00198 #define OS_STYLE_SVR4           0
00199 #define OS_STYLE_FREEBSD        1
00200 #define OS_STYLE_NETBSD         2
00201 
00202 /*@unchecked@*/ /*@observer@*/
00203 static const char *os_style_names[] = {
00204         "SVR4",
00205         "FreeBSD",
00206         "NetBSD",
00207 };
00208 
00209 /*@-bounds@*/
00210 static void
00211 dophn_core(fmagic fm, off_t off, int num, size_t size)
00212         /*@globals fileSystem @*/
00213         /*@modifies fm, fileSystem @*/
00214 {
00215         Elf32_Phdr ph32;
00216         Elf64_Phdr ph64;
00217         size_t offset;
00218         unsigned char nbuf[BUFSIZ];
00219         ssize_t bufsize;
00220 
00221         if (size != ph_size) {
00222                 error(EXIT_FAILURE, 0, "corrupted program header size.\n");
00223                 /*@notreached@*/
00224         }
00225 
00226         /*
00227          * Loop through all the program headers.
00228          */
00229         for ( ; num; num--) {
00230                 if (lseek(fm->fd, off, SEEK_SET) == (off_t)-1) {
00231                         error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
00232                         /*@notreached@*/
00233                 }
00234                 if (read(fm->fd, ph_addr, ph_size) == -1) {
00235                         error(EXIT_FAILURE, 0, "read failed (%s).\n", strerror(errno));
00236                         /*@notreached@*/
00237                 }
00238                 off += size;
00239                 if (ph_type != PT_NOTE)
00240                         continue;
00241 
00242                 /*
00243                  * This is a PT_NOTE section; loop through all the notes
00244                  * in the section.
00245                  */
00246                 if (lseek(fm->fd, (off_t) ph_offset, SEEK_SET) == (off_t)-1) {
00247                         error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
00248                         /*@notreached@*/
00249                 }
00250                 bufsize = read(fm->fd, nbuf, ((ph_filesz < BUFSIZ) ? ph_filesz : BUFSIZ));
00251                 if (bufsize == -1) {
00252                         error(EXIT_FAILURE, 0, ": " "read failed (%s).\n", strerror(errno));
00253                         /*@notreached@*/
00254                 }
00255                 offset = 0;
00256                 for (;;) {
00257                         if (offset >= (size_t)bufsize)
00258                                 /*@innerbreak@*/ break;
00259                         offset = donote(fm, nbuf, offset, (size_t)bufsize,
00260                             4);
00261 
00262                 }
00263         }
00264 }
00265 /*@=bounds@*/
00266 #endif
00267 
00268 /*@-bounds@*/
00269 static size_t
00270 donote(const fmagic fm, unsigned char *nbuf, size_t offset, size_t size,
00271     int align)
00272 {
00273         Elf32_Nhdr nh32;
00274         Elf64_Nhdr nh64;
00275         size_t noff, doff;
00276 #ifdef ELFCORE
00277         int os_style = -1;
00278 #endif
00279 
00280         if (fm->cls == ELFCLASS32)
00281                 memcpy(&nh32, &nbuf[offset], sizeof(nh32));
00282         else
00283                 memcpy(&nh64, &nbuf[offset], sizeof(nh64));
00284         offset += nh_size;
00285 
00286         if ((nh_namesz == 0) && (nh_descsz == 0)) {
00287                 /*
00288                  * We're out of note headers.
00289                  */
00290                 return offset;
00291         }
00292 
00293         noff = offset;
00294         doff = ELF_ALIGN(offset + nh_namesz);
00295 
00296         if (offset + nh_namesz > size) {
00297                 /*
00298                  * We're past the end of the buffer.
00299                  */
00300                 return doff;
00301         }
00302 
00303         offset = ELF_ALIGN(doff + nh_descsz);
00304         if (doff + nh_descsz > size)
00305                 return offset;
00306 
00307         if (nh_namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 &&
00308             nh_type == NT_GNU_VERSION && nh_descsz == 16) {
00309                 uint32_t desc[4];
00310                 (void)memcpy(desc, &nbuf[doff], sizeof(desc));
00311 
00312                 file_printf(fm, ", for GNU/");
00313                 switch (getu32(fm, desc[0])) {
00314                 case GNU_OS_LINUX:
00315                         file_printf(fm, "Linux");
00316                         break;
00317                 case GNU_OS_HURD:
00318                         file_printf(fm, "Hurd");
00319                         break;
00320                 case GNU_OS_SOLARIS:
00321                         file_printf(fm, "Solaris");
00322                         break;
00323                 default:
00324                         file_printf(fm, "<unknown>");
00325                 }
00326                 file_printf(fm, " %d.%d.%d", getu32(fm, desc[1]),
00327                     getu32(fm, desc[2]), getu32(fm, desc[3]));
00328                 return size;
00329         }
00330 
00331         if (nh_namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0 &&
00332             nh_type == NT_NETBSD_VERSION && nh_descsz == 4) {
00333                 uint32_t desc;
00334                 (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
00335                 desc = getu32(fm, desc);
00336 
00337                 file_printf(fm, ", for NetBSD");
00338                 /*
00339                  * The version number used to be stuck as 199905, and was thus
00340                  * basically content-free.  Newer versions of NetBSD have fixed
00341                  * this and now use the encoding of __NetBSD_Version__:
00342                  *
00343                  *      MMmmrrpp00
00344                  *
00345                  * M = major version
00346                  * m = minor version
00347                  * r = release ["",A-Z,Z[A-Z] but numeric]
00348                  * p = patchlevel
00349                  */
00350                 if (desc > 100000000U) {
00351                         u_int ver_patch = (desc / 100) % 100;
00352                         u_int ver_rel = (desc / 10000) % 100;
00353                         u_int ver_min = (desc / 1000000) % 100;
00354                         u_int ver_maj = desc / 100000000;
00355 
00356                         file_printf(fm, " %u.%u", ver_maj, ver_min);
00357                         if (ver_rel == 0 && ver_patch != 0) {
00358                                 file_printf(fm, ".%u", ver_patch);
00359                         } else if (ver_rel != 0) {
00360                                 while (ver_rel > 26) {
00361                                         file_printf(fm, "Z");
00362                                         ver_rel -= 26;
00363                                 }
00364                                 file_printf(fm, "%c", 'A' + ver_rel - 1);
00365                         }
00366                 }
00367                 return size;
00368         }
00369 
00370         if (nh_namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0 &&
00371             nh_type == NT_FREEBSD_VERSION && nh_descsz == 4) {
00372                 uint32_t desc;
00373                 (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
00374                 desc = getu32(fm, desc);
00375                 file_printf(fm, ", for FreeBSD");
00376                 /*
00377                  * Contents is __FreeBSD_version, whose relation to OS versions
00378                  * is defined by a huge table in the Porters' Handbook. Happily,
00379                  * the first three digits are the version number, at least in
00380                  * versions of FreeBSD that use this note.
00381                  */
00382                 file_printf(fm, " %d.%d", desc / 100000, desc / 10000 % 10);
00383                 if (desc / 1000 % 10 > 0)
00384                         file_printf(fm, ".%d", desc / 1000 % 10);
00385                 return size;
00386         }
00387 
00388         if (nh_namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 &&
00389             nh_type == NT_OPENBSD_VERSION && nh_descsz == 4) {
00390                 file_printf(fm, ", for OpenBSD");
00391                 /* Content of note is always 0 */
00392                 return size;
00393         }
00394 
00395         /*
00396          * Sigh.  The 2.0.36 kernel in Debian 2.1, at
00397          * least, doesn't correctly implement name
00398          * sections, in core dumps, as specified by
00399          * the "Program Linking" section of "UNIX(R) System
00400          * V Release 4 Programmer's Guide: ANSI C and
00401          * Programming Support Tools", because my copy
00402          * clearly says "The first 'namesz' bytes in 'name'
00403          * contain a *null-terminated* [emphasis mine]
00404          * character representation of the entry's owner
00405          * or originator", but the 2.0.36 kernel code
00406          * doesn't include the terminating null in the
00407          * name....
00408          */
00409         if ((nh_namesz == 4 && strncmp((char *)&nbuf[noff], "CORE", 4) == 0) ||
00410             (nh_namesz == 5 && strcmp((char *)&nbuf[noff], "CORE") == 0)) {
00411                 os_style = OS_STYLE_SVR4;
00412         } 
00413 
00414         if ((nh_namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0)) {
00415                 os_style = OS_STYLE_FREEBSD;
00416         }
00417 
00418         if ((nh_namesz >= 11 && strncmp((char *)&nbuf[noff], "NetBSD-CORE", 11)
00419             == 0)) {
00420                 os_style = OS_STYLE_NETBSD;
00421         }
00422 
00423 #ifdef ELFCORE
00424         if (os_style != -1)
00425                 file_printf(fm, ", %s-style", os_style_names[os_style]);
00426 
00427         if (os_style == OS_STYLE_NETBSD && nh_type == NT_NETBSD_CORE_PROCINFO) {
00428                 uint32_t signo;
00429                 /*
00430                  * Extract the program name.  It is at
00431                  * offset 0x7c, and is up to 32-bytes,
00432                  * including the terminating NUL.
00433                  */
00434                 file_printf(fm, ", from '%.31s'", &nbuf[doff + 0x7c]);
00435                 
00436                 /*
00437                  * Extract the signal number.  It is at
00438                  * offset 0x08.
00439                  */
00440                 memcpy(&signo, &nbuf[doff + 0x08],
00441                     sizeof(signo));
00442                 file_printf(fm, " (signal %u)", getu32(fm, signo));
00443                 return size;
00444         } else if (os_style != OS_STYLE_NETBSD && nh_type == NT_PRPSINFO) {
00445                 size_t i, j;
00446                 unsigned char c;
00447                 /*
00448                  * Extract the program name.  We assume
00449                  * it to be 16 characters (that's what it
00450                  * is in SunOS 5.x and Linux).
00451                  *
00452                  * Unfortunately, it's at a different offset
00453                  * in varous OSes, so try multiple offsets.
00454                  * If the characters aren't all printable,
00455                  * reject it.
00456                  */
00457                 for (i = 0; i < NOFFSETS; i++) {
00458                         size_t reloffset = prpsoffsets(i);
00459                         size_t noffset = doff + reloffset;
00460                         for (j = 0; j < 16; j++, noffset++, reloffset++) {
00461                                 /*
00462                                  * Make sure we're not past
00463                                  * the end of the buffer; if
00464                                  * we are, just give up.
00465                                  */
00466                                 if (noffset >= size)
00467                                         goto tryanother;
00468 
00469                                 /*
00470                                  * Make sure we're not past
00471                                  * the end of the contents;
00472                                  * if we are, this obviously
00473                                  * isn't the right offset.
00474                                  */
00475                                 if (reloffset >= nh_descsz)
00476                                         goto tryanother;
00477 
00478                                 c = nbuf[noffset];
00479                                 if (c == '\0') {
00480                                         /*
00481                                          * A '\0' at the
00482                                          * beginning is
00483                                          * obviously wrong.
00484                                          * Any other '\0'
00485                                          * means we're done.
00486                                          */
00487                                         if (j == 0)
00488                                                 goto tryanother;
00489                                         else
00490                                                 break;
00491                                 } else {
00492                                         /*
00493                                          * A nonprintable
00494                                          * character is also
00495                                          * wrong.
00496                                          */
00497 #define isquote(c) (strchr("'\"`", (c)) != NULL)
00498                                         if (!isprint(c) || isquote(c))
00499                                                 goto tryanother;
00500                                 }
00501                         }
00502 
00503                         /*
00504                          * Well, that worked.
00505                          */
00506                         file_printf(fm, ", from '%.16s'",
00507                             &nbuf[doff + prpsoffsets(i)]);
00508                         return size;
00509 
00510                 tryanother:
00511                         ;
00512                 }
00513                 return offset;
00514         }
00515 #endif
00516         return offset;
00517 }
00518 
00519 static void
00520 doshn(fmagic fm, off_t off, int num, size_t size)
00521         /*@globals fileSystem @*/
00522         /*@modifies fm, fileSystem @*/
00523 {
00524         Elf32_Shdr sh32;
00525         Elf64_Shdr sh64;
00526 
00527         if (size != sh_size) {
00528                 error(EXIT_FAILURE, 0, "corrupted program header size.\n");
00529                 /*@notreached@*/
00530         }
00531 
00532         if (lseek(fm->fd, off, SEEK_SET) == (off_t)-1) {
00533                 error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
00534                 /*@notreached@*/
00535         }
00536 
00537         for ( ; num; num--) {
00538                 if (read(fm->fd, sh_addr, sh_size) == -1) {
00539                         error(EXIT_FAILURE, 0, "read failed (%s).\n", strerror(errno));
00540                         /*@notreached@*/
00541                 }
00542                 if (shs_type == SHT_SYMTAB /* || shs_type == SHT_DYNSYM */) {
00543                         file_printf(fm, ", not stripped");
00544                         return;
00545                 }
00546         }
00547         file_printf(fm, ", stripped");
00548 }
00549 /*@=bounds@*/
00550 
00551 /*
00552  * Look through the program headers of an executable image, searching
00553  * for a PT_INTERP section; if one is found, it's dynamically linked,
00554  * otherwise it's statically linked.
00555  */
00556 /*@-bounds@*/
00557 static void
00558 dophn_exec(fmagic fm, off_t off, int num, size_t size)
00559         /*@globals fileSystem @*/
00560         /*@modifies fm, fileSystem @*/
00561 {
00562         Elf32_Phdr ph32;
00563         Elf64_Phdr ph64;
00564         const char *linking_style = "statically";
00565         const char *shared_libraries = "";
00566         unsigned char nbuf[BUFSIZ];
00567         int bufsize;
00568         size_t offset;
00569         off_t savedoffset;
00570 
00571         if (size != ph_size) {
00572                 error(EXIT_FAILURE, 0, "corrupted program header size.\n");
00573                 /*@notreached@*/
00574         }
00575 
00576         if (lseek(fm->fd, off, SEEK_SET) == (off_t)-1) {
00577                 error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
00578                 /*@notreached@*/
00579         }
00580 
00581         for ( ; num; num--) {
00582                 if (read(fm->fd, ph_addr, ph_size) == -1) {
00583                         error(EXIT_FAILURE, 0, "read failed (%s).\n", strerror(errno));
00584                         /*@notreached@*/
00585                 }
00586                 if ((savedoffset = lseek(fm->fd, (off_t)0, SEEK_CUR)) == (off_t)-1) {
00587                         error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
00588                         /*@notreached@*/
00589                 }
00590 
00591                 switch (ph_type) {
00592                 case PT_DYNAMIC:
00593                         linking_style = "dynamically";
00594                         /*@switchbreak@*/ break;
00595                 case PT_INTERP:
00596                         shared_libraries = " (uses shared libs)";
00597                         /*@switchbreak@*/ break;
00598                 case PT_NOTE:
00599                         /*
00600                          * This is a PT_NOTE section; loop through all the notes
00601                          * in the section.
00602                          */
00603                         if (lseek(fm->fd, (off_t) ph_offset, SEEK_SET) == -1) {
00604                                 error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
00605                                 /*@notreached@*/
00606                         }
00607                         bufsize = read(fm->fd, nbuf, ((ph_filesz < sizeof(nbuf)) ? ph_filesz : sizeof(nbuf)));
00608                         if (bufsize == -1) {
00609                                 error(EXIT_FAILURE, 0, ": " "read failed (%s).\n",
00610                                     strerror(errno));
00611                                 /*@notreached@*/
00612                         }
00613                         offset = 0;
00614                         for (;;) {
00615                                 if (offset >= (size_t)bufsize)
00616                                         /*@innerbreak@*/ break;
00617                                 offset = donote(fm, nbuf, offset,
00618                                     (size_t)bufsize, ph_align);
00619                         }
00620                         if ((lseek(fm->fd, savedoffset, SEEK_SET)) == (off_t)-1) {
00621                             error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
00622                             /*@notreached@*/
00623                         }
00624                         /*@switchbreak@*/ break;
00625                 }
00626         }
00627         file_printf(fm, ", %s linked%s", linking_style, shared_libraries);
00628 }
00629 /*@=bounds@*/
00630 
00631 /*@-bounds@*/
00632 void
00633 fmagicE(fmagic fm)
00634 {
00635 /*@-sizeoftype@*/
00636         union {
00637                 int32_t l;
00638                 char c[sizeof (int32_t)];
00639         } u;
00640 /*@=sizeoftype@*/
00641 
00642         /*
00643          * If we can't seek, it must be a pipe, socket or fifo.
00644          */
00645         if((lseek(fm->fd, (off_t)0, SEEK_SET) == (off_t)-1) && (errno == ESPIPE))
00646                 fm->fd = file_pipe2file(fm->fd, fm->buf, fm->nb);
00647 
00648         /*
00649          * ELF executables have multiple section headers in arbitrary
00650          * file locations and thus file(1) cannot determine it from easily.
00651          * Instead we traverse thru all section headers until a symbol table
00652          * one is found or else the binary is stripped.
00653          */
00654         if (fm->buf[EI_MAG0] != ELFMAG0
00655             || (fm->buf[EI_MAG1] != ELFMAG1 && fm->buf[EI_MAG1] != OLFMAG1)
00656             || fm->buf[EI_MAG2] != ELFMAG2 || fm->buf[EI_MAG3] != ELFMAG3)
00657             return;
00658 
00659         fm->cls = fm->buf[EI_CLASS];
00660 
00661         if (fm->cls == ELFCLASS32) {
00662                 Elf32_Ehdr elfhdr;
00663                 if (fm->nb <= sizeof (elfhdr))
00664                         return;
00665 
00666 
00667                 u.l = 1;
00668                 (void) memcpy(&elfhdr, fm->buf, sizeof elfhdr);
00669 /*@-sizeoftype@*/
00670                 fm->swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[EI_DATA];
00671 /*@=sizeoftype@*/
00672 
00673                 if (getu16(fm, elfhdr.e_type) == ET_CORE) 
00674 #ifdef ELFCORE
00675                         dophn_core(fm,
00676                                    getu32(fm, elfhdr.e_phoff),
00677                                    getu16(fm, elfhdr.e_phnum), 
00678                                    getu16(fm, elfhdr.e_phentsize));
00679 #else
00680                         ;
00681 #endif
00682                 else {
00683                         if (getu16(fm, elfhdr.e_type) == ET_EXEC) {
00684                                 dophn_exec(fm,
00685                                            getu32(fm, elfhdr.e_phoff),
00686                                            getu16(fm, elfhdr.e_phnum), 
00687                                            getu16(fm, elfhdr.e_phentsize));
00688                         }
00689                         doshn(fm,
00690                               getu32(fm, elfhdr.e_shoff),
00691                               getu16(fm, elfhdr.e_shnum),
00692                               getu16(fm, elfhdr.e_shentsize));
00693                 }
00694                 return;
00695         }
00696 
00697         if (fm->cls == ELFCLASS64) {
00698                 Elf64_Ehdr elfhdr;
00699                 if (fm->nb <= sizeof (elfhdr))
00700                         return;
00701 
00702                 u.l = 1;
00703                 (void) memcpy(&elfhdr, fm->buf, sizeof elfhdr);
00704 /*@-sizeoftype@*/
00705                 fm->swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[EI_DATA];
00706 /*@=sizeoftype@*/
00707 
00708                 if (getu16(fm, elfhdr.e_type) == ET_CORE) 
00709 #ifdef ELFCORE
00710                         dophn_core(fm,
00711 #ifdef USE_ARRAY_FOR_64BIT_TYPES
00712                                    getu32(fm, elfhdr.e_phoff[1]),
00713 #else
00714                                    getu64(fm, elfhdr.e_phoff),
00715 #endif
00716                                    getu16(fm, elfhdr.e_phnum), 
00717                                    getu16(fm, elfhdr.e_phentsize));
00718 #else
00719                         ;
00720 #endif
00721                 else
00722                 {
00723                         if (getu16(fm, elfhdr.e_type) == ET_EXEC) {
00724                                 dophn_exec(fm,
00725 #ifdef USE_ARRAY_FOR_64BIT_TYPES
00726                                            getu32(fm, elfhdr.e_phoff[1]),
00727 #else
00728                                            getu64(fm, elfhdr.e_phoff),
00729 #endif
00730                                            getu16(fm, elfhdr.e_phnum), 
00731                                            getu16(fm, elfhdr.e_phentsize));
00732                         }
00733                         doshn(fm,
00734 #ifdef USE_ARRAY_FOR_64BIT_TYPES
00735                               getu32(fm, elfhdr.e_shoff[1]),
00736 #else
00737                               getu64(fm, elfhdr.e_shoff),
00738 #endif
00739                               getu16(fm, elfhdr.e_shnum),
00740                               getu16(fm, elfhdr.e_shentsize));
00741                 }
00742                 return;
00743         }
00744 }
00745 /*@=bounds@*/
00746 #endif  /* BUILTIN_ELF */

Generated on Sat Jun 17 22:55:30 2006 for rpm by doxygen 1.3.5