1/* Copyright (C) 1998, 1999, 2000, 2002 Red Hat, Inc.
2   This file is part of Red Hat elfutils.
3   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
4
5   Red Hat elfutils is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by the
7   Free Software Foundation; version 2 of the License.
8
9   Red Hat elfutils is distributed in the hope that it will be useful, but
10   WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   General Public License for more details.
13
14   You should have received a copy of the GNU General Public License along
15   with Red Hat elfutils; if not, write to the Free Software Foundation,
16   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
17
18   Red Hat elfutils is an included package of the Open Invention Network.
19   An included package of the Open Invention Network is a package for which
20   Open Invention Network licensees cross-license their patents.  No patent
21   license is granted, either expressly or impliedly, by designation as an
22   included package.  Should you wish to participate in the Open Invention
23   Network licensing program, please visit www.openinventionnetwork.com
24   <http://www.openinventionnetwork.com>.  */
25
26#include <config.h>
27
28#include <error.h>
29#include <fcntl.h>
30#include <gelf.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <time.h>
35#include <unistd.h>
36
37
38static const char *machines[] =
39{
40#define MACHINE(name) [name] = #name
41  MACHINE (EM_NONE),
42  MACHINE (EM_M32),
43  MACHINE (EM_SPARC),
44  MACHINE (EM_386),
45  MACHINE (EM_68K),
46  MACHINE (EM_88K),
47  MACHINE (EM_860),
48  MACHINE (EM_MIPS),
49  MACHINE (EM_MIPS_RS3_LE),
50  MACHINE (EM_PARISC),
51  MACHINE (EM_VPP500),
52  MACHINE (EM_SPARC32PLUS),
53  MACHINE (EM_960),
54  MACHINE (EM_PPC),
55  MACHINE (EM_PPC64),
56  MACHINE (EM_V800),
57  MACHINE (EM_FR20),
58  MACHINE (EM_RH32),
59  MACHINE (EM_RCE),
60  MACHINE (EM_ARM),
61  MACHINE (EM_FAKE_ALPHA),
62  MACHINE (EM_SH),
63  MACHINE (EM_SPARCV9),
64  MACHINE (EM_TRICORE),
65  MACHINE (EM_ARC),
66  MACHINE (EM_H8_300),
67  MACHINE (EM_H8_300H),
68  MACHINE (EM_H8S),
69  MACHINE (EM_H8_500),
70  MACHINE (EM_IA_64),
71  MACHINE (EM_MIPS_X),
72  MACHINE (EM_COLDFIRE),
73  MACHINE (EM_68HC12),
74  MACHINE (EM_MMA),
75  MACHINE (EM_PCP),
76  MACHINE (EM_NCPU),
77  MACHINE (EM_NDR1),
78  MACHINE (EM_STARCORE),
79  MACHINE (EM_ME16),
80  MACHINE (EM_ST100),
81  MACHINE (EM_TINYJ),
82  MACHINE (EM_FX66),
83  MACHINE (EM_ST9PLUS),
84  MACHINE (EM_ST7),
85  MACHINE (EM_68HC16),
86  MACHINE (EM_68HC11),
87  MACHINE (EM_68HC08),
88  MACHINE (EM_68HC05),
89  MACHINE (EM_SVX),
90  MACHINE (EM_ST19),
91  MACHINE (EM_VAX)
92};
93
94
95int
96main (int argc, char *argv[])
97{
98  int fd;
99  Elf *elf;
100  Elf_Cmd cmd;
101  size_t n;
102  int arg = 1;
103  int verbose = 0;
104
105  /* Recognize optional verbosity flag.  */
106  if (arg < argc && strcmp (argv[arg], "-v") == 0)
107    {
108      verbose = 1;
109      ++arg;
110    }
111
112  /* Any more arguments available.  */
113  if (arg >= argc)
114    error (EXIT_FAILURE, 0, "No input file given");
115
116  /* Open the input file.  */
117  fd = open (argv[arg], O_RDONLY);
118  if (fd == -1)
119    {
120      perror ("cannot open input file");
121      exit (1);
122    }
123
124  /* Set the ELF version we are using here.  */
125  if (elf_version (EV_CURRENT) == EV_NONE)
126    {
127      puts ("ELF library too old");
128      exit (1);
129    }
130
131  /* Start reading the file.  */
132  cmd = ELF_C_READ;
133  elf = elf_begin (fd, cmd, NULL);
134  if (elf == NULL)
135    {
136      printf ("elf_begin: %s\n", elf_errmsg (-1));
137      exit (1);
138    }
139
140  /* If it is no archive punt.  */
141  if (elf_kind (elf) != ELF_K_AR)
142    {
143      printf ("%s is not an archive\n", argv[1]);
144      exit (1);
145    }
146
147  if (verbose)
148    {
149      /* The verbose variant.  We print a lot of information.  */
150      Elf *subelf;
151      char buf[100];
152      time_t t;
153
154      /* Get the elements of the archive one after the other.  */
155      while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
156	{
157	  /* The the header for this element.  */
158	  Elf_Arhdr *arhdr = elf_getarhdr (subelf);
159
160	  if (arhdr == NULL)
161	    {
162	      printf ("cannot get arhdr: %s\n", elf_errmsg (-1));
163	      break;
164	    }
165
166	  switch (elf_kind (subelf))
167	    {
168	    case ELF_K_ELF:
169	      fputs ("ELF file:\n", stdout);
170	      break;
171
172	    case ELF_K_AR:
173	      fputs ("archive:\n", stdout);
174	      break;
175
176	    default:
177	      fputs ("unknown file:\n", stdout);
178	      break;
179	    }
180
181	  /* Print general information.  */
182	  t = arhdr->ar_date;
183	  strftime (buf, sizeof buf, "%Y-%m-%dT%H:%M:%S%z", gmtime (&t));
184	  printf ("  name         : \"%s\"\n"
185		  "  time         : %s\n"
186		  "  uid          : %ld\n"
187		  "  gid          : %ld\n"
188		  "  mode         : %o\n"
189		  "  size         : %ld\n"
190		  "  rawname      : \"%s\"\n",
191		  arhdr->ar_name,
192		  buf,
193		  (long int) arhdr->ar_uid,
194		  (long int) arhdr->ar_gid,
195		  arhdr->ar_mode,
196		  (long int) arhdr->ar_size,
197		  arhdr->ar_rawname);
198
199	  /* For ELF files we can provide some more information.  */
200	  if (elf_kind (subelf) == ELF_K_ELF)
201	    {
202	      GElf_Ehdr ehdr;
203
204	      /* Get the ELF header.  */
205	      if (gelf_getehdr (subelf, &ehdr) == NULL)
206		printf ("  *** cannot get ELF header: %s\n", elf_errmsg (-1));
207	      else
208		{
209		  printf ("  binary class : %s\n",
210			  ehdr.e_ident[EI_CLASS] == ELFCLASS32
211			  ? "ELFCLASS32" : "ELFCLASS64");
212		  printf ("  data encoding: %s\n",
213			  ehdr.e_ident[EI_DATA] == ELFDATA2LSB
214			  ? "ELFDATA2LSB" : "ELFDATA2MSB");
215		  printf ("  binary type  : %s\n",
216			  ehdr.e_type == ET_REL
217			  ? "relocatable"
218			  : (ehdr.e_type == ET_EXEC
219			     ? "executable"
220			     : (ehdr.e_type == ET_DYN
221				? "dynamic"
222				: "core file")));
223		  printf ("  machine      : %s\n",
224			  (ehdr.e_machine >= (sizeof (machines)
225					      / sizeof (machines[0]))
226			   || machines[ehdr.e_machine] == NULL)
227			  ? "???"
228			  : machines[ehdr.e_machine]);
229		}
230	    }
231
232	  /* Get next archive element.  */
233	  cmd = elf_next (subelf);
234	  if (elf_end (subelf) != 0)
235	    printf ("error while freeing sub-ELF descriptor: %s\n",
236		    elf_errmsg (-1));
237	}
238    }
239  else
240    {
241      /* The simple version.  Only print a bit of information.  */
242      Elf_Arsym *arsym = elf_getarsym (elf, &n);
243
244      if (n == 0)
245	printf ("no symbol table in archive: %s\n", elf_errmsg (-1));
246      else
247	{
248	  --n;
249
250	  while (n-- > 0)
251	    printf ("name = \"%s\", offset = %ld, hash = %lx\n",
252		    arsym[n].as_name, (long int) arsym[n].as_off,
253		    arsym[n].as_hash);
254	}
255    }
256
257  /* Free the ELF handle.  */
258  if (elf_end (elf) != 0)
259    printf ("error while freeing ELF descriptor: %s\n", elf_errmsg (-1));
260
261  /* Close the underlying file.  */
262  close (fd);
263
264  return 0;
265}
266