Skip to content

Instantly share code, notes, and snippets.

@lvzixun

lvzixun/elfaddr.c Secret

Last active Dec 13, 2019
Embed
What would you like to do?
#include "lstate.h"
#include "lobject.h"
#define __USE_GNU
#include <dlfcn.h>
#include <elf.h>
#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>
#define MAX_ELF_SYM_COUNT 128
struct elf_syminfo {
int fd;
size_t sz;
const char* elf_path;
Elf64_Sym* symtab;
char *strtab;
size_t symcnt;
Elf64_Ehdr *header;
} ELF_SYM_LIST[MAX_ELF_SYM_COUNT] = {0};
static struct elf_syminfo*
_get_syminfo(const char* elf_path) {
size_t i=0;
struct elf_syminfo* p = NULL;
for(i=0; i<MAX_ELF_SYM_COUNT; i++) {
p = &ELF_SYM_LIST[i];
if(!p->elf_path) {
break;
}
if(strcmp(p->elf_path, elf_path) == 0) {
return p;
}
}
if(i== MAX_ELF_SYM_COUNT) {
return NULL;
}
int fd = open(elf_path, O_RDONLY);
if(fd <0) {
return NULL;
}
size_t sz = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
Elf64_Ehdr *header = NULL;
Elf64_Shdr* symtab_section = NULL;
Elf64_Shdr* str_section = NULL;
header = mmap(NULL, sz, PROT_READ, MAP_PRIVATE, fd, 0);
if (header == MAP_FAILED ||
memcmp(header->e_ident, ELFMAG, SELFMAG) != 0 ||
header->e_ident[EI_DATA] != 1 ||
header->e_ident[EI_CLASS] != 2) {
close(fd);
return NULL;
}
uint8_t* elf_header = (uint8_t*)header;
uint16_t e_shnum = header->e_shnum;
uint64_t e_shoff = header->e_shoff;
Elf64_Shdr* sections = (Elf64_Shdr*)(elf_header + e_shoff);
for(i=0; i<e_shnum; i++) {
if(sections[i].sh_type == SHT_SYMTAB) {
symtab_section = &sections[i];
break;
}
}
Elf64_Sym* symtab = (Elf64_Sym*)(elf_header + symtab_section->sh_offset);
size_t symcnt = symtab_section->sh_size / sizeof(*symtab);
str_section = sections + symtab_section->sh_link;
char *strtab = (char*)(elf_header + str_section->sh_offset);
p->fd = fd;
p->sz = sz;
p->elf_path = elf_path;
p->symtab = symtab;
p->strtab = strtab;
p->symcnt = symcnt;
p->header = header;
return p;
}
static int
elfaddr(const void *addr, Dl_info *info) {
int ret = dladdr(addr, info);
if(ret ==0) {
return 0;
}
// get function from .dynsym
if(info->dli_sname && info->dli_saddr) {
return 1;
}
// get function from .symtab
const char* elf_path = info->dli_fname;
struct elf_syminfo* syminfo_p = _get_syminfo(elf_path);
if(!syminfo_p) {
return 1;
}
Elf64_Sym* symtab = syminfo_p->symtab;
size_t symcnt = syminfo_p->symcnt;
char *strtab = syminfo_p->strtab;
Elf64_Addr target_addr = (Elf64_Addr)addr - (Elf64_Addr)info->dli_fbase;
if(syminfo_p->header->e_type == ET_EXEC) {
target_addr = (Elf64_Addr)addr;
}
size_t i=0;
for(i=0; i<symcnt; i++) {
Elf64_Sym* p = &symtab[i];
if(p->st_value == target_addr) {
info->dli_sname = &(strtab[p->st_name]);
info->dli_saddr = (void*)addr;
break;
}
}
return 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.