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