1 /*
2 elfsym.c
3
4 Read symbol adresses from a .elf file.
5
6 Based on libelf-howto.c from: http://em386.blogspot.com
7
8 Unit test with:
9
10 gcc elfsym.c -o elfsym -D__UNITTEST__ -Wall -lelf
11 ./elfsym elf_file.elf
12 */
13
14 #include <stdio.h>
15 #include <string.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <libelf.h>
22 #include <gelf.h>
23 #include "elfsym.h"
24
25 #define ERR -1
26
elfsym_open(char file[])27 int elfsym_open(char file[]) {
28 int fd; /* File Descriptor */
29 char *base_ptr; /* ptr to our object in memory */
30 struct stat elf_stats; /* fstat struct */
31
32 if((fd = open(file, O_RDWR)) == ERR) {
33 printf("couldnt open %s\n", file);
34 return ERR;
35 }
36
37 if((fstat(fd, &elf_stats))) {
38 printf("could not fstat %s\n", file);
39 close(fd);
40 return ERR;
41 }
42
43 if((base_ptr = (char *) malloc(elf_stats.st_size)) == NULL) {
44 fprintf(stderr, "could not malloc\n");
45 close(fd);
46 return ERR;
47 }
48
49 if((read(fd, base_ptr, elf_stats.st_size)) < elf_stats.st_size) {
50 fprintf(stderr, "could not read %s\n", file);
51 free(base_ptr);
52 close(fd);
53 return ERR;
54 }
55
56 /* Check libelf version first */
57
58 if(elf_version(EV_CURRENT) == EV_NONE) {
59 fprintf(stderr, "WARNING Elf Library is out of date!\n");
60 }
61
62 free(base_ptr);
63
64 return fd;
65 }
66
67
elfsym_close(int fd)68 void elfsym_close(int fd) {
69 close(fd);
70 }
71
elfsym_get_symbol_address(int fd,char symbol_name[])72 unsigned int elfsym_get_symbol_address(int fd, char symbol_name[])
73 {
74 Elf_Scn *scn; /* Section Descriptor */
75 Elf_Data *edata; /* Data Descriptor */
76 GElf_Sym sym; /* Symbol */
77 GElf_Shdr shdr; /* Section Header */
78 Elf *elf; /* Our Elf pointer for libelf */
79 unsigned int symbol_address;
80 int symbol_count;
81 int i;
82
83 /* Iterate through section headers, stop when we find symbols,
84 and check for match */
85
86 elf = elf_begin(fd, ELF_C_READ, NULL);
87 if (elf == 0) {
88 fprintf(stderr, "could not elf_begin\n");
89 }
90 symbol_address = 0;
91 scn = NULL;
92
93 while((scn = elf_nextscn(elf, scn)) != 0) {
94 gelf_getshdr(scn, &shdr);
95
96 // When we find a section header marked SHT_SYMTAB stop and get symbols
97 edata = NULL;
98 if(shdr.sh_type == SHT_SYMTAB) {
99 // edata points to our symbol table
100 edata = elf_getdata(scn, edata);
101
102 // how many symbols are there? this number comes from the size of
103 // the section divided by the entry size
104 symbol_count = shdr.sh_size / shdr.sh_entsize;
105
106 // loop through to grab all symbols
107 for(i = 0; i < symbol_count; i++) {
108 // libelf grabs the symbol data using gelf_getsym()
109 gelf_getsym(edata, i, &sym);
110
111 if (strcmp(symbol_name,
112 elf_strptr(elf, shdr.sh_link, sym.st_name)) == 0) {
113 symbol_address = sym.st_value;
114 }
115 }
116
117 }
118 }
119
120 return symbol_address;
121 }
122
123 #ifdef __UNITTEST__
124
main(int argc,char * argv[])125 int main(int argc, char *argv[])
126 {
127 int fd;
128 unsigned int flag_addr, ptr_addr, file_addr, len_addr;
129
130 fd = elfsym_open(argv[1]);
131 flag_addr = elfsym_get_symbol_address(fd, "syscalls_gdb_flag");
132 ptr_addr = elfsym_get_symbol_address(fd, "syscalls_gdb_ptr");
133 file_addr = elfsym_get_symbol_address(fd, "syscalls_gdb_file");
134 len_addr = elfsym_get_symbol_address(fd, "syscalls_gdb_len");
135 elfsym_close(fd);
136
137 printf("flag_addr: 0x%x\n", flag_addr);
138 printf("ptr_addr: 0x%x\n", ptr_addr);
139 printf("file_addr: 0x%x\n", file_addr);
140 printf("len_addr: 0x%x\n", len_addr);
141
142 return 0;
143 }
144
145 #endif
146