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