mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
99 lines
2.7 KiB
C
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_ */
|