OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [utils/] [readelf.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/* vi: set sw=4 ts=4: */
2
/*
3
 * A small little readelf implementation for uClibc
4
 *
5
 * Copyright (C) 2000 by Lineo, inc and Erik Andersen
6
 * Copyright (C) 2000-2002 Erik Andersen <andersee@debian.org>
7
 *
8
 * Several functions in this file (specifically, elf_find_section_type(),
9
 * elf_find_phdr_type(), and elf_find_dynamic(), were stolen from elflib.c from
10
 * elfvector (http://www.BitWagon.com/elfvector.html) by John F. Reiser
11
 * <jreiser@BitWagon.com>, which is copyright 2000 BitWagon Software LLC
12
 * (GPL2).
13
 *
14
 * This program is free software; you can redistribute it and/or modify
15
 * it under the terms of the GNU General Public License as published by
16
 * the Free Software Foundation; either version 2 of the License, or
17
 * (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22
 * General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program; if not, write to the Free Software
26
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27
 *
28
 */
29
 
30
 
31
#include <fcntl.h>
32
#include <stdio.h>
33
#include <stdlib.h>
34
#include <string.h>
35
#include <unistd.h>
36
#include <sys/mman.h>
37
#include <sys/stat.h>
38
#include <sys/types.h>
39
 
40
#include "bswap.h"
41
#include "elf.h"
42
 
43
 
44
int byteswap;
45
inline uint32_t byteswap32_to_host(uint32_t value)
46
{
47
        if (byteswap==1) {
48
                return(bswap_32(value));
49
        } else {
50
                return(value);
51
        }
52
}
53
 
54
Elf32_Shdr * elf_find_section_type( int key, Elf32_Ehdr *ehdr)
55
{
56
        int j;
57
        Elf32_Shdr *shdr = (Elf32_Shdr *)(ehdr->e_shoff + (char *)ehdr);
58
        for (j = ehdr->e_shnum; --j>=0; ++shdr) {
59
                if (key==(int)byteswap32_to_host(shdr->sh_type)) {
60
                        return shdr;
61
                }
62
        }
63
        return NULL;
64
}
65
 
66
Elf32_Phdr * elf_find_phdr_type( int type, Elf32_Ehdr *ehdr)
67
{
68
        int j;
69
        Elf32_Phdr *phdr = (Elf32_Phdr *)(ehdr->e_phoff + (char *)ehdr);
70
        for (j = ehdr->e_phnum; --j>=0; ++phdr) {
71
                if (type==(int)byteswap32_to_host(phdr->p_type)) {
72
                        return phdr;
73
                }
74
        }
75
        return NULL;
76
}
77
 
78
/* Returns value if return_val==1, ptr otherwise */
79
void * elf_find_dynamic(int const key, Elf32_Dyn *dynp,
80
        Elf32_Ehdr *ehdr, int return_val)
81
{
82
        Elf32_Phdr *pt_text = elf_find_phdr_type(PT_LOAD, ehdr);
83
        unsigned tx_reloc = byteswap32_to_host(pt_text->p_vaddr) - byteswap32_to_host(pt_text->p_offset);
84
        for (; DT_NULL!=byteswap32_to_host(dynp->d_tag); ++dynp) {
85
                if (key == (int)byteswap32_to_host(dynp->d_tag)) {
86
                        if (return_val == 1)
87
                                return (void *)(intptr_t)byteswap32_to_host(dynp->d_un.d_val);
88
                        else
89
                                return (void *)(byteswap32_to_host(dynp->d_un.d_val) - tx_reloc + (char *)ehdr );
90
                }
91
        }
92
        return NULL;
93
}
94
 
95
int check_elf_header(Elf32_Ehdr *const ehdr)
96
{
97
        if (! ehdr || strncmp((void *)ehdr, ELFMAG, SELFMAG) != 0 ||
98
                        ehdr->e_ident[EI_CLASS] != ELFCLASS32 ||
99
                        ehdr->e_ident[EI_VERSION] != EV_CURRENT)
100
        {
101
                return 1;
102
        }
103
 
104
        /* Check if the target endianness matches the host's endianness */
105
        byteswap = 0;
106
#if __BYTE_ORDER == __LITTLE_ENDIAN
107
        if (ehdr->e_ident[5] == ELFDATA2MSB) {
108
                /* Ick -- we will have to byte-swap everything */
109
                byteswap = 1;
110
        }
111
#elif __BYTE_ORDER == __BIG_ENDIAN
112
        if (ehdr->e_ident[5] == ELFDATA2LSB) {
113
                byteswap = 1;
114
        }
115
#else
116
#error Unknown host byte order!
117
#endif
118
        /* Be vary lazy, and only byteswap the stuff we use */
119
        if (byteswap==1) {
120
                ehdr->e_type=bswap_16(ehdr->e_type);
121
                ehdr->e_machine=bswap_16(ehdr->e_machine);
122
                ehdr->e_phoff=bswap_32(ehdr->e_phoff);
123
                ehdr->e_shoff=bswap_32(ehdr->e_shoff);
124
                ehdr->e_phnum=bswap_16(ehdr->e_phnum);
125
                ehdr->e_shnum=bswap_16(ehdr->e_shnum);
126
        }
127
        return 0;
128
}
129
 
130
 
131
#define ELFOSABI_NONE   0       /* UNIX System V ABI */
132
#define ELFOSABI_HPUX   1       /* HP-UX operating system */
133
#define ELFOSABI_NETBSD 2       /* NetBSD */
134
#define ELFOSABI_LINUX  3       /* GNU/Linux */
135
#define ELFOSABI_HURD   4       /* GNU/Hurd */
136
#define ELFOSABI_SOLARIS 6      /* Solaris */
137
#define ELFOSABI_AIX    7       /* AIX */
138
#define ELFOSABI_IRIX   8       /* IRIX */
139
#define ELFOSABI_FREEBSD 9      /* FreeBSD */
140
#define ELFOSABI_TRU64  10      /* TRU64 UNIX */
141
#define ELFOSABI_MODESTO 11     /* Novell Modesto */
142
#define ELFOSABI_OPENBSD 12     /* OpenBSD */
143
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
144
#define ELFOSABI_ARM   97       /* ARM */
145
static void describe_elf_hdr(Elf32_Ehdr* ehdr)
146
{
147
        char *tmp, *tmp1;
148
 
149
        switch (ehdr->e_type) {
150
                case ET_NONE:   tmp = "None"; tmp1 = "NONE"; break;
151
                case ET_REL:    tmp = "Relocatable File"; tmp1 = "REL"; break;
152
                case ET_EXEC:   tmp = "Executable file"; tmp1 = "EXEC"; break;
153
                case ET_DYN:    tmp = "Shared object file"; tmp1 = "DYN"; break;
154
                case ET_CORE:   tmp = "Core file"; tmp1 = "CORE"; break;
155
                default:
156
                                                tmp = tmp1 = "Unknown";
157
        }
158
        printf( "Type:\t\t%s (%s)\n", tmp1, tmp);
159
 
160
        switch (ehdr->e_machine) {
161
                case EM_NONE:           tmp="No machine"; break;
162
                case EM_M32:            tmp="AT&T WE 32100"; break;
163
                case EM_SPARC:          tmp="SUN SPARC"; break;
164
                case EM_386:            tmp="Intel 80386"; break;
165
                case EM_68K:            tmp="Motorola m68k family"; break;
166
                case EM_88K:            tmp="Motorola m88k family"; break;
167
                case EM_860:            tmp="Intel 80860"; break;
168
                case EM_MIPS:           tmp="MIPS R3000 big-endian"; break;
169
                case EM_S370:           tmp="IBM System/370"; break;
170
                case EM_MIPS_RS3_LE:    tmp="MIPS R3000 little-endian"; break;
171
                case EM_PARISC:         tmp="HPPA"; break;
172
                case EM_VPP500:         tmp="Fujitsu VPP500"; break;
173
                case EM_SPARC32PLUS:    tmp="Sun's v8plus"; break;
174
                case EM_960:            tmp="Intel 80960"; break;
175
                case EM_PPC:            tmp="PowerPC"; break;
176
                case EM_PPC64:          tmp="PowerPC 64-bit"; break;
177
                case EM_S390:           tmp="IBM S390"; break;
178
                case EM_V800:           tmp="NEC V800 series"; break;
179
                case EM_FR20:           tmp="Fujitsu FR20"; break;
180
                case EM_RH32:           tmp="TRW RH-32"; break;
181
                case EM_RCE:            tmp="Motorola RCE"; break;
182
                case EM_ARM:            tmp="ARM"; break;
183
                case EM_FAKE_ALPHA:     tmp="Digital Alpha"; break;
184
                case EM_SH:                     tmp="Renesas SH"; break;
185
                case EM_SPARCV9:        tmp="SPARC v9 64-bit"; break;
186
                case EM_TRICORE:        tmp="Siemens Tricore"; break;
187
                case EM_ARC:            tmp="Argonaut RISC Core"; break;
188
                case EM_H8_300:         tmp="Renesas H8/300"; break;
189
                case EM_H8_300H:        tmp="Renesas H8/300H"; break;
190
                case EM_H8S:            tmp="Renesas H8S"; break;
191
                case EM_H8_500:         tmp="Renesas H8/500"; break;
192
                case EM_IA_64:          tmp="Intel Merced"; break;
193
                case EM_MIPS_X:         tmp="Stanford MIPS-X"; break;
194
                case EM_COLDFIRE:       tmp="Motorola Coldfire"; break;
195
                case EM_68HC12:         tmp="Motorola M68HC12"; break;
196
                case EM_MMA:            tmp="Fujitsu MMA Multimedia Accelerator"; break;
197
                case EM_PCP:            tmp="Siemens PCP"; break;
198
                case EM_NCPU:           tmp="Sony nCPU embeeded RISC"; break;
199
                case EM_NDR1:           tmp="Denso NDR1 microprocessor"; break;
200
                case EM_STARCORE:       tmp="Motorola Start*Core processor"; break;
201
                case EM_ME16:           tmp="Toyota ME16 processor"; break;
202
                case EM_ST100:          tmp="STMicroelectronic ST100 processor"; break;
203
                case EM_TINYJ:          tmp="Advanced Logic Corp. Tinyj emb.fam"; break;
204
                case EM_X86_64:         tmp="AMD x86-64 architecture"; break;
205
                case EM_PDSP:           tmp="Sony DSP Processor"; break;
206
                case EM_FX66:           tmp="Siemens FX66 microcontroller"; break;
207
                case EM_ST9PLUS:        tmp="STMicroelectronics ST9+ 8/16 mc"; break;
208
                case EM_ST7:            tmp="STmicroelectronics ST7 8 bit mc"; break;
209
                case EM_68HC16:         tmp="Motorola MC68HC16 microcontroller"; break;
210
                case EM_68HC11:         tmp="Motorola MC68HC11 microcontroller"; break;
211
                case EM_68HC08:         tmp="Motorola MC68HC08 microcontroller"; break;
212
                case EM_68HC05:         tmp="Motorola MC68HC05 microcontroller"; break;
213
                case EM_SVX:            tmp="Silicon Graphics SVx"; break;
214
                case EM_AT19:           tmp="STMicroelectronics ST19 8 bit mc"; break;
215
                case EM_VAX:            tmp="Digital VAX"; break;
216
                case EM_CRIS:           tmp="Axis Communications 32-bit embedded processor"; break;
217
                case EM_JAVELIN:        tmp="Infineon Technologies 32-bit embedded processor"; break;
218
                case EM_FIREPATH:       tmp="Element 14 64-bit DSP Processor"; break;
219
                case EM_ZSP:            tmp="LSI Logic 16-bit DSP Processor"; break;
220
                case EM_MMIX:           tmp="Donald Knuth's educational 64-bit processor"; break;
221
                case EM_HUANY:          tmp="Harvard University machine-independent object files"; break;
222
                case EM_PRISM:          tmp="SiTera Prism"; break;
223
                case EM_AVR:            tmp="Atmel AVR 8-bit microcontroller"; break;
224
                case EM_FR30:           tmp="Fujitsu FR30"; break;
225
                case EM_D10V:           tmp="Mitsubishi D10V"; break;
226
                case EM_D30V:           tmp="Mitsubishi D30V"; break;
227
                case EM_V850:           tmp="NEC v850"; break;
228
                case EM_M32R:           tmp="Renesas M32R"; break;
229
                case EM_MN10300:        tmp="Matsushita MN10300"; break;
230
                case EM_MN10200:        tmp="Matsushita MN10200"; break;
231
                case EM_PJ:                     tmp="picoJava"; break;
232
                default:                        tmp="unknown";
233
        }
234
        printf( "Machine:\t%s\n", tmp);
235
 
236
        switch (ehdr->e_ident[EI_CLASS]) {
237
                case ELFCLASSNONE: tmp = "Invalid class";  break;
238
                case ELFCLASS32:   tmp = "ELF32"; break;
239
                case ELFCLASS64:   tmp = "ELF64"; break;
240
                default:           tmp = "Unknown";
241
        }
242
        printf( "Class:\t\t%s\n", tmp);
243
 
244
        switch (ehdr->e_ident[EI_DATA]) {
245
                case ELFDATANONE:  tmp = "Invalid data encoding"; break;
246
                case ELFDATA2LSB:  tmp = "2's complement, little endian"; break;
247
                case ELFDATA2MSB:  tmp = "2's complement, big endian"; break;
248
                default:           tmp = "Unknown";
249
        }
250
        printf( "Data:\t\t%s\n", tmp);
251
 
252
        printf( "Version:\t%d %s\n", ehdr->e_ident[EI_VERSION],
253
                        (ehdr->e_ident[EI_VERSION]==EV_CURRENT)?
254
                        "(current)" : "(unknown: %lx)");
255
 
256
        switch (ehdr->e_ident[EI_OSABI]) {
257
                case ELFOSABI_SYSV:       tmp ="UNIX - System V"; break;
258
                case ELFOSABI_HPUX:       tmp ="UNIX - HP-UX"; break;
259
                case ELFOSABI_NETBSD:     tmp ="UNIX - NetBSD"; break;
260
                case ELFOSABI_LINUX:      tmp ="UNIX - Linux"; break;
261
                case ELFOSABI_HURD:       tmp ="GNU/Hurd"; break;
262
                case ELFOSABI_SOLARIS:    tmp ="UNIX - Solaris"; break;
263
                case ELFOSABI_AIX:        tmp ="UNIX - AIX"; break;
264
                case ELFOSABI_IRIX:       tmp ="UNIX - IRIX"; break;
265
                case ELFOSABI_FREEBSD:    tmp ="UNIX - FreeBSD"; break;
266
                case ELFOSABI_TRU64:      tmp ="UNIX - TRU64"; break;
267
                case ELFOSABI_MODESTO:    tmp ="Novell - Modesto"; break;
268
                case ELFOSABI_OPENBSD:    tmp ="UNIX - OpenBSD"; break;
269
                case ELFOSABI_STANDALONE: tmp ="Standalone App"; break;
270
                case ELFOSABI_ARM:        tmp ="ARM"; break;
271
                default:                  tmp = "Unknown";
272
        }
273
        printf( "OS/ABI:\t\t%s\n", tmp);
274
 
275
        printf( "ABI Version:\t%d\n", ehdr->e_ident[EI_ABIVERSION]);
276
}
277
 
278
static void list_needed_libraries(Elf32_Dyn* dynamic, char *strtab)
279
{
280
        Elf32_Dyn  *dyns;
281
 
282
        printf("Dependancies:\n");
283
        for (dyns=dynamic; byteswap32_to_host(dyns->d_tag)!=DT_NULL; ++dyns) {
284
                if (dyns->d_tag == DT_NEEDED) {
285
                        printf("\t%s\n", (char*)strtab + byteswap32_to_host(dyns->d_un.d_val));
286
                }
287
        }
288
}
289
 
290
static void describe_elf_interpreter(Elf32_Ehdr* ehdr)
291
{
292
        Elf32_Phdr *phdr;
293
        phdr = elf_find_phdr_type(PT_INTERP, ehdr);
294
        if (phdr) {
295
                printf("Interpreter:\t%s\n", (char*)ehdr + byteswap32_to_host(phdr->p_offset));
296
        }
297
}
298
 
299
int main( int argc, char** argv)
300
{
301
        /* map the .so, and locate interesting pieces */
302
        char *dynstr;
303
        char *thefilename = argv[1];
304
        FILE *thefile;
305
        struct stat statbuf;
306
        Elf32_Ehdr *ehdr = 0;
307
        Elf32_Shdr *dynsec;
308
        Elf32_Dyn *dynamic;
309
 
310
        if (argc < 2 || !thefilename) {
311
                fprintf(stderr, "No filename specified.\n");
312
                exit(EXIT_FAILURE);
313
        }
314
        if (!(thefile = fopen(thefilename, "r"))) {
315
                perror(thefilename);
316
                exit(EXIT_FAILURE);
317
        }
318
        if (fstat(fileno(thefile), &statbuf) < 0) {
319
                perror(thefilename);
320
                exit(EXIT_FAILURE);
321
        }
322
 
323
        if ((size_t)statbuf.st_size < sizeof(Elf32_Ehdr))
324
                goto foo;
325
 
326
        /* mmap the file to make reading stuff from it effortless */
327
        ehdr = (Elf32_Ehdr *)mmap(0, statbuf.st_size,
328
                        PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(thefile), 0);
329
 
330
foo:
331
        /* Check if this looks legit */
332
        if (check_elf_header(ehdr)) {
333
                fprintf(stderr, "This does not appear to be an ELF file.\n");
334
                exit(EXIT_FAILURE);
335
        }
336
        describe_elf_hdr(ehdr);
337
        describe_elf_interpreter(ehdr);
338
 
339
        dynsec = elf_find_section_type(SHT_DYNAMIC, ehdr);
340
        if (dynsec) {
341
                dynamic = (Elf32_Dyn*)(byteswap32_to_host(dynsec->sh_offset) + (intptr_t)ehdr);
342
                dynstr = (char *)elf_find_dynamic(DT_STRTAB, dynamic, ehdr, 0);
343
                list_needed_libraries(dynamic, dynstr);
344
        }
345
 
346
        return 0;
347
}
348
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.