/* elfsym.c Read symbol addresses from a .elf file. Based on libelf-howto.c from: http://em386.blogspot.com Unit test with: gcc elfsym.c -o elfsym -D__UNITTEST__ -Wall -lelf ./elfsym elf_file.elf */ #include #include #include #include #include #include #include #include #include #include "elfsym.h" #define ERR -1 int elfsym_open(char file[]) { int fd; /* File Descriptor */ char *base_ptr; /* ptr to our object in memory */ struct stat elf_stats; /* fstat struct */ if((fd = open(file, O_RDWR)) == ERR) { printf("couldn't open %s\n", file); return ERR; } if((fstat(fd, &elf_stats))) { printf("could not fstat %s\n", file); close(fd); return ERR; } if((base_ptr = (char *) malloc(elf_stats.st_size)) == NULL) { fprintf(stderr, "could not malloc\n"); close(fd); return ERR; } if((read(fd, base_ptr, elf_stats.st_size)) < elf_stats.st_size) { fprintf(stderr, "could not read %s\n", file); free(base_ptr); close(fd); return ERR; } /* Check libelf version first */ if(elf_version(EV_CURRENT) == EV_NONE) { fprintf(stderr, "WARNING Elf Library is out of date!\n"); } free(base_ptr); return fd; } void elfsym_close(int fd) { close(fd); } unsigned int elfsym_get_symbol_address(int fd, char symbol_name[]) { Elf_Scn *scn; /* Section Descriptor */ Elf_Data *edata; /* Data Descriptor */ GElf_Sym sym; /* Symbol */ GElf_Shdr shdr; /* Section Header */ Elf *elf; /* Our Elf pointer for libelf */ unsigned int symbol_address; int symbol_count; int i; /* Iterate through section headers, stop when we find symbols, and check for match */ elf = elf_begin(fd, ELF_C_READ, NULL); if (elf == 0) { fprintf(stderr, "could not elf_begin\n"); } symbol_address = 0; scn = NULL; while((scn = elf_nextscn(elf, scn)) != 0) { gelf_getshdr(scn, &shdr); // When we find a section header marked SHT_SYMTAB stop and get symbols edata = NULL; if(shdr.sh_type == SHT_SYMTAB) { // edata points to our symbol table edata = elf_getdata(scn, edata); // how many symbols are there? this number comes from the size of // the section divided by the entry size symbol_count = shdr.sh_size / shdr.sh_entsize; // loop through to grab all symbols for(i = 0; i < symbol_count; i++) { // libelf grabs the symbol data using gelf_getsym() gelf_getsym(edata, i, &sym); if (strcmp(symbol_name, elf_strptr(elf, shdr.sh_link, sym.st_name)) == 0) { symbol_address = sym.st_value; } } } } return symbol_address; } #ifdef __UNITTEST__ int main(int argc, char *argv[]) { int fd; unsigned int flag_addr, ptr_addr, file_addr, len_addr; fd = elfsym_open(argv[1]); flag_addr = elfsym_get_symbol_address(fd, "syscalls_gdb_flag"); ptr_addr = elfsym_get_symbol_address(fd, "syscalls_gdb_ptr"); file_addr = elfsym_get_symbol_address(fd, "syscalls_gdb_file"); len_addr = elfsym_get_symbol_address(fd, "syscalls_gdb_len"); elfsym_close(fd); printf("flag_addr: 0x%x\n", flag_addr); printf("ptr_addr: 0x%x\n", ptr_addr); printf("file_addr: 0x%x\n", file_addr); printf("len_addr: 0x%x\n", len_addr); return 0; } #endif