blob: f28501172acc719224b463314dcb6d5a50de7355 [file] [log] [blame]
/*
* This file contains functions specific to ELF binaries
*/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <elf.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
#include "ltrace.h"
#include "elf.h"
#include "options.h"
#include "output.h"
struct library_symbol * read_elf(const char *filename)
{
struct library_symbol * library_symbols = NULL;
struct stat sbuf;
int fd;
void * addr;
Elf32_Ehdr * hdr;
Elf32_Shdr * shdr;
Elf32_Sym * symtab = NULL;
int i;
char * strtab = NULL;
u_long symtab_len = 0;
if (opt_d>0) {
output_line(0, "Reading symbol table from %s...", filename);
}
fd = open(filename, O_RDONLY);
if (fd==-1) {
fprintf(stderr, "Can't open \"%s\": %s\n", filename, sys_errlist[errno]);
exit(1);
}
if (fstat(fd, &sbuf)==-1) {
fprintf(stderr, "Can't stat \"%s\": %s\n", filename, sys_errlist[errno]);
exit(1);
}
if (sbuf.st_size < sizeof(Elf32_Ehdr)) {
fprintf(stderr, "\"%s\" is not an ELF binary object\n", filename);
exit(1);
}
addr = mmap(NULL, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (addr==(void*)-1) {
fprintf(stderr, "Can't mmap \"%s\": %s\n", filename, sys_errlist[errno]);
exit(1);
}
hdr = addr;
if (strncmp(hdr->e_ident, ELFMAG, SELFMAG)) {
fprintf(stderr, "\"%s\" is not an ELF binary object\n", filename);
exit(1);
}
for(i=0; i<hdr->e_shnum; i++) {
shdr = addr + hdr->e_shoff + i*hdr->e_shentsize;
if (shdr->sh_type == SHT_DYNSYM) {
if (!symtab) {
#if 0
symtab = (Elf32_Sym *)shdr->sh_addr;
#else
symtab = (Elf32_Sym *)(addr + shdr->sh_offset);
#endif
symtab_len = shdr->sh_size;
}
}
if (shdr->sh_type == SHT_STRTAB) {
if (!strtab) {
strtab = (char *)(addr + shdr->sh_offset);
}
}
}
if (opt_d>1) {
output_line(0, "symtab: 0x%08x", (unsigned)symtab);
output_line(0, "symtab_len: %lu", symtab_len);
output_line(0, "strtab: 0x%08x", (unsigned)strtab);
}
if (!symtab) {
close(fd);
return NULL;
}
for(i=0; i<symtab_len/sizeof(Elf32_Sym); i++) {
if (!((symtab+i)->st_shndx) && (symtab+i)->st_value) {
struct library_symbol * tmp = library_symbols;
library_symbols = malloc(sizeof(struct library_symbol));
if (!library_symbols) {
perror("malloc");
exit(1);
}
library_symbols->brk.addr = (void *)((symtab+i)->st_value);
library_symbols->brk.enabled = 0;
library_symbols->name = strtab+(symtab+i)->st_name;
library_symbols->next = tmp;
if (opt_d>1) {
output_line(0, "addr: 0x%08x, symbol: \"%s\"",
(unsigned)((symtab+i)->st_value),
(strtab+(symtab+i)->st_name));
}
}
}
close(fd);
return library_symbols;
}