blob: f28501172acc719224b463314dcb6d5a50de7355 [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>
Juan Cespedes5e01f651998-03-08 22:31:44 +010011#include <elf.h>
Juan Cespedes96935a91997-08-09 23:45:39 +020012#include <sys/mman.h>
13#include <string.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +010014#include <unistd.h>
Juan Cespedes96935a91997-08-09 23:45:39 +020015
Juan Cespedes96935a91997-08-09 23:45:39 +020016#include "ltrace.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +010017#include "elf.h"
18#include "options.h"
Juan Cespedes3268a161997-08-25 16:45:22 +020019#include "output.h"
Juan Cespedes96935a91997-08-09 23:45:39 +020020
Juan Cespedes5e01f651998-03-08 22:31:44 +010021struct library_symbol * read_elf(const char *filename)
Juan Cespedes96935a91997-08-09 23:45:39 +020022{
Juan Cespedes5e01f651998-03-08 22:31:44 +010023 struct library_symbol * library_symbols = NULL;
Juan Cespedes96935a91997-08-09 23:45:39 +020024 struct stat sbuf;
25 int fd;
26 void * addr;
Juan Cespedes5e01f651998-03-08 22:31:44 +010027 Elf32_Ehdr * hdr;
Juan Cespedes96935a91997-08-09 23:45:39 +020028 Elf32_Shdr * shdr;
Juan Cespedes5e01f651998-03-08 22:31:44 +010029 Elf32_Sym * symtab = NULL;
Juan Cespedes96935a91997-08-09 23:45:39 +020030 int i;
31 char * strtab = NULL;
32 u_long symtab_len = 0;
33
Juan Cespedes1afec691997-08-23 21:31:46 +020034 if (opt_d>0) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010035 output_line(0, "Reading symbol table from %s...", filename);
Juan Cespedes1afec691997-08-23 21:31:46 +020036 }
37
Juan Cespedes96935a91997-08-09 23:45:39 +020038 fd = open(filename, O_RDONLY);
39 if (fd==-1) {
40 fprintf(stderr, "Can't open \"%s\": %s\n", filename, sys_errlist[errno]);
41 exit(1);
42 }
43 if (fstat(fd, &sbuf)==-1) {
44 fprintf(stderr, "Can't stat \"%s\": %s\n", filename, sys_errlist[errno]);
45 exit(1);
46 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010047 if (sbuf.st_size < sizeof(Elf32_Ehdr)) {
48 fprintf(stderr, "\"%s\" is not an ELF binary object\n", filename);
Juan Cespedes96935a91997-08-09 23:45:39 +020049 exit(1);
50 }
51 addr = mmap(NULL, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
52 if (addr==(void*)-1) {
53 fprintf(stderr, "Can't mmap \"%s\": %s\n", filename, sys_errlist[errno]);
54 exit(1);
55 }
56 hdr = addr;
57 if (strncmp(hdr->e_ident, ELFMAG, SELFMAG)) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010058 fprintf(stderr, "\"%s\" is not an ELF binary object\n", filename);
Juan Cespedes96935a91997-08-09 23:45:39 +020059 exit(1);
60 }
61 for(i=0; i<hdr->e_shnum; i++) {
62 shdr = addr + hdr->e_shoff + i*hdr->e_shentsize;
63 if (shdr->sh_type == SHT_DYNSYM) {
64 if (!symtab) {
65#if 0
Juan Cespedes5e01f651998-03-08 22:31:44 +010066 symtab = (Elf32_Sym *)shdr->sh_addr;
Juan Cespedes96935a91997-08-09 23:45:39 +020067#else
Juan Cespedes5e01f651998-03-08 22:31:44 +010068 symtab = (Elf32_Sym *)(addr + shdr->sh_offset);
Juan Cespedes96935a91997-08-09 23:45:39 +020069#endif
70 symtab_len = shdr->sh_size;
71 }
72 }
73 if (shdr->sh_type == SHT_STRTAB) {
74 if (!strtab) {
Juan Cespedes96935a91997-08-09 23:45:39 +020075 strtab = (char *)(addr + shdr->sh_offset);
Juan Cespedes96935a91997-08-09 23:45:39 +020076 }
77 }
78 }
Juan Cespedes1afec691997-08-23 21:31:46 +020079 if (opt_d>1) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010080 output_line(0, "symtab: 0x%08x", (unsigned)symtab);
81 output_line(0, "symtab_len: %lu", symtab_len);
82 output_line(0, "strtab: 0x%08x", (unsigned)strtab);
Juan Cespedes96935a91997-08-09 23:45:39 +020083 }
84 if (!symtab) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010085 close(fd);
86 return NULL;
Juan Cespedes96935a91997-08-09 23:45:39 +020087 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010088 for(i=0; i<symtab_len/sizeof(Elf32_Sym); i++) {
Juan Cespedes96935a91997-08-09 23:45:39 +020089 if (!((symtab+i)->st_shndx) && (symtab+i)->st_value) {
90 struct library_symbol * tmp = library_symbols;
91
92 library_symbols = malloc(sizeof(struct library_symbol));
93 if (!library_symbols) {
94 perror("malloc");
95 exit(1);
96 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010097 library_symbols->brk.addr = (void *)((symtab+i)->st_value);
98 library_symbols->brk.enabled = 0;
Juan Cespedes96935a91997-08-09 23:45:39 +020099 library_symbols->name = strtab+(symtab+i)->st_name;
100 library_symbols->next = tmp;
Juan Cespedes1afec691997-08-23 21:31:46 +0200101 if (opt_d>1) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100102 output_line(0, "addr: 0x%08x, symbol: \"%s\"",
Juan Cespedes96935a91997-08-09 23:45:39 +0200103 (unsigned)((symtab+i)->st_value),
104 (strtab+(symtab+i)->st_name));
105 }
106 }
107 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100108 close(fd);
109 return library_symbols;
Juan Cespedes96935a91997-08-09 23:45:39 +0200110}
111