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