Juan Cespedes | c9a48b9 | 1997-08-17 02:45:40 +0200 | [diff] [blame] | 1 | /* |
| 2 | * This file contains functions specific to ELF binaries |
| 3 | */ |
| 4 | |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 5 | #include <stdio.h> |
| 6 | #include <errno.h> |
| 7 | #include <stdlib.h> |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 8 | #include <sys/types.h> |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 9 | #include <sys/stat.h> |
| 10 | #include <fcntl.h> |
Juan Cespedes | 5e01f65 | 1998-03-08 22:31:44 +0100 | [diff] [blame^] | 11 | #include <elf.h> |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 12 | #include <sys/mman.h> |
| 13 | #include <string.h> |
Juan Cespedes | 5e01f65 | 1998-03-08 22:31:44 +0100 | [diff] [blame^] | 14 | #include <unistd.h> |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 15 | |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 16 | #include "ltrace.h" |
Juan Cespedes | 5e01f65 | 1998-03-08 22:31:44 +0100 | [diff] [blame^] | 17 | #include "elf.h" |
| 18 | #include "options.h" |
Juan Cespedes | 3268a16 | 1997-08-25 16:45:22 +0200 | [diff] [blame] | 19 | #include "output.h" |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 20 | |
Juan Cespedes | 5e01f65 | 1998-03-08 22:31:44 +0100 | [diff] [blame^] | 21 | struct library_symbol * read_elf(const char *filename) |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 22 | { |
Juan Cespedes | 5e01f65 | 1998-03-08 22:31:44 +0100 | [diff] [blame^] | 23 | struct library_symbol * library_symbols = NULL; |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 24 | struct stat sbuf; |
| 25 | int fd; |
| 26 | void * addr; |
Juan Cespedes | 5e01f65 | 1998-03-08 22:31:44 +0100 | [diff] [blame^] | 27 | Elf32_Ehdr * hdr; |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 28 | Elf32_Shdr * shdr; |
Juan Cespedes | 5e01f65 | 1998-03-08 22:31:44 +0100 | [diff] [blame^] | 29 | Elf32_Sym * symtab = NULL; |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 30 | int i; |
| 31 | char * strtab = NULL; |
| 32 | u_long symtab_len = 0; |
| 33 | |
Juan Cespedes | 1afec69 | 1997-08-23 21:31:46 +0200 | [diff] [blame] | 34 | if (opt_d>0) { |
Juan Cespedes | 5e01f65 | 1998-03-08 22:31:44 +0100 | [diff] [blame^] | 35 | output_line(0, "Reading symbol table from %s...", filename); |
Juan Cespedes | 1afec69 | 1997-08-23 21:31:46 +0200 | [diff] [blame] | 36 | } |
| 37 | |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 38 | 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 Cespedes | 5e01f65 | 1998-03-08 22:31:44 +0100 | [diff] [blame^] | 47 | if (sbuf.st_size < sizeof(Elf32_Ehdr)) { |
| 48 | fprintf(stderr, "\"%s\" is not an ELF binary object\n", filename); |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 49 | 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 Cespedes | 5e01f65 | 1998-03-08 22:31:44 +0100 | [diff] [blame^] | 58 | fprintf(stderr, "\"%s\" is not an ELF binary object\n", filename); |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 59 | 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 Cespedes | 5e01f65 | 1998-03-08 22:31:44 +0100 | [diff] [blame^] | 66 | symtab = (Elf32_Sym *)shdr->sh_addr; |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 67 | #else |
Juan Cespedes | 5e01f65 | 1998-03-08 22:31:44 +0100 | [diff] [blame^] | 68 | symtab = (Elf32_Sym *)(addr + shdr->sh_offset); |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 69 | #endif |
| 70 | symtab_len = shdr->sh_size; |
| 71 | } |
| 72 | } |
| 73 | if (shdr->sh_type == SHT_STRTAB) { |
| 74 | if (!strtab) { |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 75 | strtab = (char *)(addr + shdr->sh_offset); |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 76 | } |
| 77 | } |
| 78 | } |
Juan Cespedes | 1afec69 | 1997-08-23 21:31:46 +0200 | [diff] [blame] | 79 | if (opt_d>1) { |
Juan Cespedes | 5e01f65 | 1998-03-08 22:31:44 +0100 | [diff] [blame^] | 80 | 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 Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 83 | } |
| 84 | if (!symtab) { |
Juan Cespedes | 5e01f65 | 1998-03-08 22:31:44 +0100 | [diff] [blame^] | 85 | close(fd); |
| 86 | return NULL; |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 87 | } |
Juan Cespedes | 5e01f65 | 1998-03-08 22:31:44 +0100 | [diff] [blame^] | 88 | for(i=0; i<symtab_len/sizeof(Elf32_Sym); i++) { |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 89 | 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 Cespedes | 5e01f65 | 1998-03-08 22:31:44 +0100 | [diff] [blame^] | 97 | library_symbols->brk.addr = (void *)((symtab+i)->st_value); |
| 98 | library_symbols->brk.enabled = 0; |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 99 | library_symbols->name = strtab+(symtab+i)->st_name; |
| 100 | library_symbols->next = tmp; |
Juan Cespedes | 1afec69 | 1997-08-23 21:31:46 +0200 | [diff] [blame] | 101 | if (opt_d>1) { |
Juan Cespedes | 5e01f65 | 1998-03-08 22:31:44 +0100 | [diff] [blame^] | 102 | output_line(0, "addr: 0x%08x, symbol: \"%s\"", |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 103 | (unsigned)((symtab+i)->st_value), |
| 104 | (strtab+(symtab+i)->st_name)); |
| 105 | } |
| 106 | } |
| 107 | } |
Juan Cespedes | 5e01f65 | 1998-03-08 22:31:44 +0100 | [diff] [blame^] | 108 | close(fd); |
| 109 | return library_symbols; |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 110 | } |
| 111 | |