blob: 9f56820aeddfe9a867156338d6fb742dfc88dcde [file] [log] [blame]
Juan Cespedesc9a48b91997-08-17 02:45:40 +02001/*
2 * This file contains functions specific to ELF binaries
3 */
4
Juan Cespedes96935a91997-08-09 23:45:39 +02005#include <stdio.h>
6#include <errno.h>
7#include <stdlib.h>
Juan Cespedes96935a91997-08-09 23:45:39 +02008#include <sys/types.h>
Juan Cespedes96935a91997-08-09 23:45:39 +02009#include <sys/stat.h>
10#include <fcntl.h>
11#include <linux/elf.h>
12#include <sys/mman.h>
13#include <string.h>
Juan Cespedes96935a91997-08-09 23:45:39 +020014
15#include "elf.h"
16#include "ltrace.h"
Juan Cespedesc9a48b91997-08-17 02:45:40 +020017#include "symbols.h"
Juan Cespedes96935a91997-08-09 23:45:39 +020018
19int read_elf(const char *filename)
20{
21 struct stat sbuf;
22 int fd;
23 void * addr;
24 struct elf32_hdr * hdr;
25 Elf32_Shdr * shdr;
26 struct elf32_sym * symtab = NULL;
27 int i;
28 char * strtab = NULL;
29 u_long symtab_len = 0;
30
Juan Cespedes1afec691997-08-23 21:31:46 +020031 if (opt_d>0) {
32 fprintf(output, "Reading symbol table from %s...\n", filename);
33 }
34
Juan Cespedes96935a91997-08-09 23:45:39 +020035 fd = open(filename, O_RDONLY);
36 if (fd==-1) {
37 fprintf(stderr, "Can't open \"%s\": %s\n", filename, sys_errlist[errno]);
38 exit(1);
39 }
40 if (fstat(fd, &sbuf)==-1) {
41 fprintf(stderr, "Can't stat \"%s\": %s\n", filename, sys_errlist[errno]);
42 exit(1);
43 }
44 if (sbuf.st_size < sizeof(struct elf32_hdr)) {
45 fprintf(stderr, "\"%s\" is not an ELF object\n", filename);
46 exit(1);
47 }
48 addr = mmap(NULL, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
49 if (addr==(void*)-1) {
50 fprintf(stderr, "Can't mmap \"%s\": %s\n", filename, sys_errlist[errno]);
51 exit(1);
52 }
53 hdr = addr;
54 if (strncmp(hdr->e_ident, ELFMAG, SELFMAG)) {
55 fprintf(stderr, "\"%s\" is not an ELF object\n", filename);
56 exit(1);
57 }
58 for(i=0; i<hdr->e_shnum; i++) {
59 shdr = addr + hdr->e_shoff + i*hdr->e_shentsize;
60 if (shdr->sh_type == SHT_DYNSYM) {
61 if (!symtab) {
62#if 0
63 symtab = (struct elf32_sym *)shdr->sh_addr;
64#else
65 symtab = (struct elf32_sym *)(addr + shdr->sh_offset);
66#endif
67 symtab_len = shdr->sh_size;
68 }
69 }
70 if (shdr->sh_type == SHT_STRTAB) {
71 if (!strtab) {
Juan Cespedes96935a91997-08-09 23:45:39 +020072 strtab = (char *)(addr + shdr->sh_offset);
Juan Cespedes96935a91997-08-09 23:45:39 +020073 }
74 }
75 }
Juan Cespedes1afec691997-08-23 21:31:46 +020076 if (opt_d>1) {
Juan Cespedes96935a91997-08-09 23:45:39 +020077 fprintf(output, "symtab: 0x%08x\n", (unsigned)symtab);
78 fprintf(output, "symtab_len: %lu\n", symtab_len);
79 fprintf(output, "strtab: 0x%08x\n", (unsigned)strtab);
80 }
81 if (!symtab) {
82 return 0;
83 }
84 for(i=0; i<symtab_len/sizeof(struct elf32_sym); i++) {
85 if (!((symtab+i)->st_shndx) && (symtab+i)->st_value) {
86 struct library_symbol * tmp = library_symbols;
87
88 library_symbols = malloc(sizeof(struct library_symbol));
89 if (!library_symbols) {
90 perror("malloc");
91 exit(1);
92 }
93 library_symbols->addr = ((symtab+i)->st_value);
94 library_symbols->name = strtab+(symtab+i)->st_name;
95 library_symbols->next = tmp;
Juan Cespedes1afec691997-08-23 21:31:46 +020096 if (opt_d>1) {
Juan Cespedes96935a91997-08-09 23:45:39 +020097 fprintf(output, "addr: 0x%08x, symbol: \"%s\"\n",
98 (unsigned)((symtab+i)->st_value),
99 (strtab+(symtab+i)->st_name));
100 }
101 }
102 }
103 return 1;
104}
105