blob: c833fb7cfaefc4087d366edb1af2b6c436124954 [file] [log] [blame]
Juan Cespedesd44c6b81998-09-25 14:48:42 +02001#if HAVE_CONFIG_H
2#include "config.h"
3#endif
4
Juan Cespedesc9a48b91997-08-17 02:45:40 +02005/*
6 * This file contains functions specific to ELF binaries
7 */
8
Juan Cespedes96935a91997-08-09 23:45:39 +02009#include <stdio.h>
10#include <errno.h>
11#include <stdlib.h>
Juan Cespedes96935a91997-08-09 23:45:39 +020012#include <sys/types.h>
Juan Cespedes96935a91997-08-09 23:45:39 +020013#include <sys/stat.h>
14#include <fcntl.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +010015#include <elf.h>
Juan Cespedes96935a91997-08-09 23:45:39 +020016#include <sys/mman.h>
17#include <string.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +010018#include <unistd.h>
Juan Cespedes96935a91997-08-09 23:45:39 +020019
Juan Cespedes96935a91997-08-09 23:45:39 +020020#include "ltrace.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +010021#include "elf.h"
22#include "options.h"
Juan Cespedes3268a161997-08-25 16:45:22 +020023#include "output.h"
Juan Cespedes96935a91997-08-09 23:45:39 +020024
Juan Cespedes5e01f651998-03-08 22:31:44 +010025struct library_symbol * read_elf(const char *filename)
Juan Cespedes96935a91997-08-09 23:45:39 +020026{
Juan Cespedes5e01f651998-03-08 22:31:44 +010027 struct library_symbol * library_symbols = NULL;
Juan Cespedes96935a91997-08-09 23:45:39 +020028 struct stat sbuf;
29 int fd;
30 void * addr;
Juan Cespedes5e01f651998-03-08 22:31:44 +010031 Elf32_Ehdr * hdr;
Juan Cespedes96935a91997-08-09 23:45:39 +020032 Elf32_Shdr * shdr;
Juan Cespedes5e01f651998-03-08 22:31:44 +010033 Elf32_Sym * symtab = NULL;
Juan Cespedes96935a91997-08-09 23:45:39 +020034 int i;
35 char * strtab = NULL;
36 u_long symtab_len = 0;
37
Juan Cespedes1afec691997-08-23 21:31:46 +020038 if (opt_d>0) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010039 output_line(0, "Reading symbol table from %s...", filename);
Juan Cespedes1afec691997-08-23 21:31:46 +020040 }
41
Juan Cespedes96935a91997-08-09 23:45:39 +020042 fd = open(filename, O_RDONLY);
43 if (fd==-1) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020044 fprintf(stderr, "Can't open \"%s\": %s\n", filename, strerror(errno));
Juan Cespedes96935a91997-08-09 23:45:39 +020045 exit(1);
46 }
47 if (fstat(fd, &sbuf)==-1) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020048 fprintf(stderr, "Can't stat \"%s\": %s\n", filename, strerror(errno));
Juan Cespedes96935a91997-08-09 23:45:39 +020049 exit(1);
50 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010051 if (sbuf.st_size < sizeof(Elf32_Ehdr)) {
52 fprintf(stderr, "\"%s\" is not an ELF binary object\n", filename);
Juan Cespedes96935a91997-08-09 23:45:39 +020053 exit(1);
54 }
55 addr = mmap(NULL, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
56 if (addr==(void*)-1) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020057 fprintf(stderr, "Can't mmap \"%s\": %s\n", filename, strerror(errno));
Juan Cespedes96935a91997-08-09 23:45:39 +020058 exit(1);
59 }
60 hdr = addr;
61 if (strncmp(hdr->e_ident, ELFMAG, SELFMAG)) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010062 fprintf(stderr, "\"%s\" is not an ELF binary object\n", filename);
Juan Cespedes96935a91997-08-09 23:45:39 +020063 exit(1);
64 }
65 for(i=0; i<hdr->e_shnum; i++) {
66 shdr = addr + hdr->e_shoff + i*hdr->e_shentsize;
67 if (shdr->sh_type == SHT_DYNSYM) {
68 if (!symtab) {
69#if 0
Juan Cespedes5e01f651998-03-08 22:31:44 +010070 symtab = (Elf32_Sym *)shdr->sh_addr;
Juan Cespedes96935a91997-08-09 23:45:39 +020071#else
Juan Cespedes5e01f651998-03-08 22:31:44 +010072 symtab = (Elf32_Sym *)(addr + shdr->sh_offset);
Juan Cespedes96935a91997-08-09 23:45:39 +020073#endif
74 symtab_len = shdr->sh_size;
75 }
76 }
77 if (shdr->sh_type == SHT_STRTAB) {
78 if (!strtab) {
Juan Cespedes96935a91997-08-09 23:45:39 +020079 strtab = (char *)(addr + shdr->sh_offset);
Juan Cespedes96935a91997-08-09 23:45:39 +020080 }
81 }
82 }
Juan Cespedes1afec691997-08-23 21:31:46 +020083 if (opt_d>1) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010084 output_line(0, "symtab: 0x%08x", (unsigned)symtab);
85 output_line(0, "symtab_len: %lu", symtab_len);
86 output_line(0, "strtab: 0x%08x", (unsigned)strtab);
Juan Cespedes96935a91997-08-09 23:45:39 +020087 }
88 if (!symtab) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010089 close(fd);
90 return NULL;
Juan Cespedes96935a91997-08-09 23:45:39 +020091 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010092 for(i=0; i<symtab_len/sizeof(Elf32_Sym); i++) {
Juan Cespedes96935a91997-08-09 23:45:39 +020093 if (!((symtab+i)->st_shndx) && (symtab+i)->st_value) {
94 struct library_symbol * tmp = library_symbols;
95
96 library_symbols = malloc(sizeof(struct library_symbol));
97 if (!library_symbols) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020098 perror("ltrace: malloc");
Juan Cespedes96935a91997-08-09 23:45:39 +020099 exit(1);
100 }
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200101 library_symbols->enter_addr = (void *)((symtab+i)->st_value);
Juan Cespedes96935a91997-08-09 23:45:39 +0200102 library_symbols->name = strtab+(symtab+i)->st_name;
103 library_symbols->next = tmp;
Juan Cespedes1afec691997-08-23 21:31:46 +0200104 if (opt_d>1) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100105 output_line(0, "addr: 0x%08x, symbol: \"%s\"",
Juan Cespedes96935a91997-08-09 23:45:39 +0200106 (unsigned)((symtab+i)->st_value),
107 (strtab+(symtab+i)->st_name));
108 }
109 }
110 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100111 close(fd);
112 return library_symbols;
Juan Cespedes96935a91997-08-09 23:45:39 +0200113}