cosmopolitan/libc/elf/tinyelf.internal.h
2024-06-01 16:30:43 -04:00

99 lines
2.7 KiB
C

#ifndef COSMOPOLITAN_LIBC_ELF_TINYELF_INTERNAL_H_
#define COSMOPOLITAN_LIBC_ELF_TINYELF_INTERNAL_H_
#include "libc/elf/def.h"
#include "libc/elf/struct/ehdr.h"
#include "libc/elf/struct/phdr.h"
#include "libc/elf/struct/shdr.h"
#include "libc/elf/struct/sym.h"
#include "libc/limits.h"
#include "libc/log/libfatal.internal.h"
#include "libc/serialize.h"
COSMOPOLITAN_C_START_
#define GetStr(tab, rva) ((char *)(tab) + (rva))
#define GetSection(e, s) ((void *)((intptr_t)(e) + (size_t)(s)->sh_offset))
#define GetShstrtab(e) GetSection(e, GetShdr(e, (e)->e_shstrndx))
#define GetSectionName(e, s) GetStr(GetShstrtab(e), (s)->sh_name)
#define GetPhdr(e, i) \
((Elf64_Phdr *)((intptr_t)(e) + (e)->e_phoff + \
(unsigned)(e)->e_phentsize * (i)))
#define GetShdr(e, i) \
((Elf64_Shdr *)((intptr_t)(e) + (e)->e_shoff + \
(unsigned)(e)->e_shentsize * (i)))
static inline char *GetStrtab(const Elf64_Ehdr *e, size_t *n) {
int i;
char *name;
Elf64_Shdr *shdr;
for (i = 0; i < e->e_shnum; ++i) {
shdr = GetShdr(e, i);
if (shdr->sh_type == SHT_STRTAB) {
name = GetSectionName(e, GetShdr(e, i));
if (name && READ64LE(name) == READ64LE(".strtab")) {
if (n)
*n = shdr->sh_size;
return GetSection(e, shdr);
}
}
}
return 0;
}
static inline Elf64_Sym *GetSymtab(const Elf64_Ehdr *e, Elf64_Xword *n) {
int i;
Elf64_Shdr *shdr;
for (i = e->e_shnum; i-- > 0;) {
shdr = GetShdr(e, i);
if (shdr->sh_type == SHT_SYMTAB) {
if (n)
*n = shdr->sh_size / sizeof(Elf64_Sym);
return GetSection(e, shdr);
}
}
return 0;
}
static inline void GetImageRange(const Elf64_Ehdr *elf, intptr_t *x,
intptr_t *y) {
unsigned i;
const Elf64_Phdr *phdr;
intptr_t start, end, pstart, pend;
start = INTPTR_MAX;
end = 0;
for (i = 0; i < elf->e_phnum; ++i) {
phdr = GetPhdr(elf, i);
if (phdr->p_type != PT_LOAD)
continue;
pstart = phdr->p_vaddr;
pend = phdr->p_vaddr + phdr->p_memsz;
if (pstart < start)
start = pstart;
if (pend > end)
end = pend;
}
if (x)
*x = start;
if (y)
*y = end;
}
static inline bool GetElfSymbolValue(const Elf64_Ehdr *ehdr, const char *name,
uint64_t *res) {
Elf64_Xword i, n;
const char *stab;
const Elf64_Sym *st;
if (!(stab = GetStrtab(ehdr, 0)))
return false;
if (!(st = GetSymtab(ehdr, &n)))
return false;
for (i = 0; i < n; ++i) {
if (!__strcmp(GetStr(stab, st[i].st_name), name)) {
*res = st[i].st_value;
return true;
}
}
return false;
}
COSMOPOLITAN_C_END_
#endif /* COSMOPOLITAN_LIBC_ELF_TINYELF_INTERNAL_H_ */