/* Copyright (C) 1998, 1999, 2000, 2002 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 1998. This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <config.h> #include <error.h> #include <fcntl.h> #include <gelf.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <unistd.h> static const char *machines[] = { #define MACHINE(name) [name] = #name MACHINE (EM_NONE), MACHINE (EM_M32), MACHINE (EM_SPARC), MACHINE (EM_386), MACHINE (EM_68K), MACHINE (EM_88K), MACHINE (EM_860), MACHINE (EM_MIPS), MACHINE (EM_MIPS_RS3_LE), MACHINE (EM_PARISC), MACHINE (EM_VPP500), MACHINE (EM_SPARC32PLUS), MACHINE (EM_960), MACHINE (EM_PPC), MACHINE (EM_PPC64), MACHINE (EM_V800), MACHINE (EM_FR20), MACHINE (EM_RH32), MACHINE (EM_RCE), MACHINE (EM_ARM), MACHINE (EM_FAKE_ALPHA), MACHINE (EM_SH), MACHINE (EM_SPARCV9), MACHINE (EM_TRICORE), MACHINE (EM_ARC), MACHINE (EM_H8_300), MACHINE (EM_H8_300H), MACHINE (EM_H8S), MACHINE (EM_H8_500), MACHINE (EM_IA_64), MACHINE (EM_MIPS_X), MACHINE (EM_COLDFIRE), MACHINE (EM_68HC12), MACHINE (EM_MMA), MACHINE (EM_PCP), MACHINE (EM_NCPU), MACHINE (EM_NDR1), MACHINE (EM_STARCORE), MACHINE (EM_ME16), MACHINE (EM_ST100), MACHINE (EM_TINYJ), MACHINE (EM_FX66), MACHINE (EM_ST9PLUS), MACHINE (EM_ST7), MACHINE (EM_68HC16), MACHINE (EM_68HC11), MACHINE (EM_68HC08), MACHINE (EM_68HC05), MACHINE (EM_SVX), MACHINE (EM_ST19), MACHINE (EM_VAX) }; int main (int argc, char *argv[]) { int fd; Elf *elf; Elf_Cmd cmd; size_t n; int arg = 1; int verbose = 0; /* Recognize optional verbosity flag. */ if (arg < argc && strcmp (argv[arg], "-v") == 0) { verbose = 1; ++arg; } /* Any more arguments available. */ if (arg >= argc) error (EXIT_FAILURE, 0, "No input file given"); /* Open the input file. */ fd = open (argv[arg], O_RDONLY); if (fd == -1) { perror ("cannot open input file"); exit (1); } /* Set the ELF version we are using here. */ if (elf_version (EV_CURRENT) == EV_NONE) { puts ("ELF library too old"); exit (1); } /* Start reading the file. */ cmd = ELF_C_READ; elf = elf_begin (fd, cmd, NULL); if (elf == NULL) { printf ("elf_begin: %s\n", elf_errmsg (-1)); exit (1); } /* If it is no archive punt. */ if (elf_kind (elf) != ELF_K_AR) { printf ("%s is not an archive\n", argv[1]); exit (1); } if (verbose) { /* The verbose variant. We print a lot of information. */ Elf *subelf; char buf[100]; time_t t; /* Get the elements of the archive one after the other. */ while ((subelf = elf_begin (fd, cmd, elf)) != NULL) { /* The the header for this element. */ Elf_Arhdr *arhdr = elf_getarhdr (subelf); if (arhdr == NULL) { printf ("cannot get arhdr: %s\n", elf_errmsg (-1)); break; } switch (elf_kind (subelf)) { case ELF_K_ELF: fputs ("ELF file:\n", stdout); break; case ELF_K_AR: fputs ("archive:\n", stdout); break; default: fputs ("unknown file:\n", stdout); break; } /* Print general information. */ t = arhdr->ar_date; strftime (buf, sizeof buf, "%Y-%m-%dT%H:%M:%S%z", gmtime (&t)); printf (" name : \"%s\"\n" " time : %s\n" " uid : %ld\n" " gid : %ld\n" " mode : %o\n" " size : %ld\n" " rawname : \"%s\"\n", arhdr->ar_name, buf, (long int) arhdr->ar_uid, (long int) arhdr->ar_gid, arhdr->ar_mode, (long int) arhdr->ar_size, arhdr->ar_rawname); /* For ELF files we can provide some more information. */ if (elf_kind (subelf) == ELF_K_ELF) { GElf_Ehdr ehdr; /* Get the ELF header. */ if (gelf_getehdr (subelf, &ehdr) == NULL) printf (" *** cannot get ELF header: %s\n", elf_errmsg (-1)); else { printf (" binary class : %s\n", ehdr.e_ident[EI_CLASS] == ELFCLASS32 ? "ELFCLASS32" : "ELFCLASS64"); printf (" data encoding: %s\n", ehdr.e_ident[EI_DATA] == ELFDATA2LSB ? "ELFDATA2LSB" : "ELFDATA2MSB"); printf (" binary type : %s\n", ehdr.e_type == ET_REL ? "relocatable" : (ehdr.e_type == ET_EXEC ? "executable" : (ehdr.e_type == ET_DYN ? "dynamic" : "core file"))); printf (" machine : %s\n", (ehdr.e_machine >= (sizeof (machines) / sizeof (machines[0])) || machines[ehdr.e_machine] == NULL) ? "???" : machines[ehdr.e_machine]); } } /* Get next archive element. */ cmd = elf_next (subelf); if (elf_end (subelf) != 0) printf ("error while freeing sub-ELF descriptor: %s\n", elf_errmsg (-1)); } } else { /* The simple version. Only print a bit of information. */ Elf_Arsym *arsym = elf_getarsym (elf, &n); if (n == 0) printf ("no symbol table in archive: %s\n", elf_errmsg (-1)); else { --n; while (n-- > 0) printf ("name = \"%s\", offset = %ld, hash = %lx\n", arsym[n].as_name, (long int) arsym[n].as_off, arsym[n].as_hash); } } /* Free the ELF handle. */ if (elf_end (elf) != 0) printf ("error while freeing ELF descriptor: %s\n", elf_errmsg (-1)); /* Close the underlying file. */ close (fd); return 0; }