[ELFLOADER] Huge refactor of elfloader and symbol resolution. Some more cleaning need to be done, but that's a first step (should help #422, #360, #1046 and probably others)

This commit is contained in:
ptitSeb 2024-02-15 18:11:57 +01:00
parent 549e042e67
commit c5a6875de9
30 changed files with 1031 additions and 1151 deletions

View File

@ -325,6 +325,7 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/dynarec/dynarec.c"
"${BOX64_ROOT}/src/elfs/elfloader.c"
"${BOX64_ROOT}/src/elfs/elfparser.c"
"${BOX64_ROOT}/src/elfs/elfhash.c"
"${BOX64_ROOT}/src/elfs/elfload_dump.c"
"${BOX64_ROOT}/src/elfs/elfdwarf_private.c"
"${BOX64_ROOT}/src/emu/x64compstrings.c"

View File

@ -212,8 +212,8 @@ box64context_t *NewBox64Context(int argc)
init_custommem_helper(context);
context->maplib = NewLibrarian(context, 1);
context->local_maplib = NewLibrarian(context, 1);
context->maplib = NewLibrarian(context);
context->local_maplib = NewLibrarian(context);
context->versym = NewDictionnary();
context->system = NewBridge();
// Cannot use Bridge name as the map is not initialized yet
@ -263,6 +263,7 @@ box64context_t *NewBox64Context(int argc)
context->segtls[4].is32bits = 1;
context->globdata = NewMapSymbols();
context->uniques = NewMapSymbols();
initAllHelpers(context);
@ -363,6 +364,7 @@ void FreeBox64Context(box64context_t** context)
FreeX64Emu(&ctx->emu_sig);
FreeMapSymbols(&ctx->globdata);
FreeMapSymbols(&ctx->uniques);
#ifdef DYNAREC
//dynarec_log(LOG_INFO, "BOX64 Dynarec at exit: Max DB=%d, righter=%d\n", ctx->max_db_size, rb_get_righter(ctx->db_sizes));

354
src/elfs/elfhash.c Normal file
View File

@ -0,0 +1,354 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <elf.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <link.h>
#include <unistd.h>
#include <errno.h>
#include "custommem.h"
#include "box64version.h"
#include "elfloader.h"
#include "debug.h"
#include "elfload_dump.h"
#include "elfloader_private.h"
const char* GetSymbolVersion(elfheader_t* h, int version)
{
if(version<2)
return NULL;
/*if(version==1)
return "*";*/
if(h->VerNeed) {
Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta);
while(ver) {
Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux);
for(int j=0; j<ver->vn_cnt; ++j) {
if(aux->vna_other==version)
return h->DynStr+aux->vna_name;
aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next);
}
ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
}
}
return GetParentSymbolVersion(h, version); // if symbol is "internal", use Def table instead
}
const char* GetParentSymbolVersion(elfheader_t* h, int index)
{
if(!h->VerDef || (index<1))
return NULL;
Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef + h->delta);
while(def) {
if(def->vd_ndx==index) {
if(def->vd_cnt<1)
return NULL;
/*if(def->vd_flags&VER_FLG_BASE)
return NULL;*/
Elf64_Verdaux *aux = (Elf64_Verdaux*)((uintptr_t)def + def->vd_aux);
return h->DynStr+aux->vda_name; // return Parent, so 1st aux
}
def = def->vd_next?((Elf64_Verdef*)((uintptr_t)def + def->vd_next)):NULL;
}
return NULL;
}
Elf64_Half GetParentSymbolVersionFlag(elfheader_t* h, int index)
{
if(!h->VerDef || (index<1))
return (Elf64_Half)-1;
Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef + h->delta);
while(def) {
if(def->vd_ndx==index) {
return def->vd_flags;
}
def = def->vd_next?((Elf64_Verdef*)((uintptr_t)def + def->vd_next)):NULL;
}
return (Elf64_Half)-1;
}
Elf64_Half GetSymbolVersionFlag(elfheader_t* h, int version)
{
if(version<2)
return (Elf64_Half)-1;
if(h->VerNeed) {
Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta);
while(ver) {
Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux);
for(int j=0; j<ver->vn_cnt; ++j) {
if(aux->vna_other==version)
return aux->vna_flags;
aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next);
}
ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
}
}
return GetParentSymbolVersionFlag(h, version); // if symbol is "internal", use Def table instead
}
int GetVersionIndice(elfheader_t* h, const char* vername)
{
if(!vername)
return 0;
if(h->VerDef) {
Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef + h->delta);
while(def) {
Elf64_Verdaux *aux = (Elf64_Verdaux*)((uintptr_t)def + def->vd_aux);
if(!strcmp(h->DynStr+aux->vda_name, vername))
return def->vd_ndx;
def = def->vd_next?((Elf64_Verdef*)((uintptr_t)def + def->vd_next)):NULL;
}
}
return 0;
}
int GetNeededVersionCnt(elfheader_t* h, const char* libname)
{
if(!libname)
return 0;
if(h->VerNeed) {
Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta);
while(ver) {
char *filename = h->DynStr + ver->vn_file;
if(!strcmp(filename, libname))
return ver->vn_cnt;
ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
}
}
return 0;
}
const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx)
{
if(!libname)
return 0;
if(h->VerNeed) {
Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta);
while(ver) {
char *filename = h->DynStr + ver->vn_file;
Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux);
if(!strcmp(filename, libname)) {
for(int j=0; j<ver->vn_cnt; ++j) {
if(j==idx)
return h->DynStr+aux->vna_name;
aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next);
}
return NULL; // idx out of bound, return NULL...
}
ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
}
}
return NULL;
}
int GetNeededVersionForLib(elfheader_t* h, const char* libname, const char* ver)
{
if(!libname || !ver)
return 0;
int n = GetNeededVersionCnt(h, libname);
if(!n)
return 0;
for(int i=0; i<n; ++i) {
const char* vername = GetNeededVersionString(h, libname, i);
if(vername && !strcmp(ver, vername))
return 1;
}
return 0;
}
static int SymbolMatch(elfheader_t* h, uint32_t i, int ver, const char* vername, int local, int veropt)
{
int version = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1;
if(version!=-1) version &=0x7fff;
const char* symvername = GetSymbolVersion(h, version);
Elf64_Half flags = GetSymbolVersionFlag(h, version);
if(ver==-1 || version==-1)
return 1;
if(version==0 && !local)
return 0;
if(version<2 && ver>1 && veropt)
return 1;
if(ver==0 && version<2)
return 1;
if(ver==1 && version<2)
return 1;
if(ver<2 && version>2 && flags==0) // flag is not WEAK, so global works
return 1;
if(ver<2 || !symvername)
return 0;
return strcmp(vername, symvername)?0:1;
}
uint32_t old_elf_hash(const char* name)
{
uint32_t h = 0, g;
for (unsigned char c = *name; c; c = *++name) {
h = (h << 4) + c;
if (g = h & 0xf0000000) {
h ^= g >> 24;
}
h &= ~g;
}
return h;
}
Elf64_Sym* old_elf_lookup(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt)
{
// Prepare hash table
const uint32_t *hashtab = (uint32_t*)(h->hash + h->delta);
const uint32_t nbuckets = hashtab[0];
const uint32_t nchains = hashtab[1];
const uint32_t *buckets = &hashtab[2];
const uint32_t *chains = &buckets[nbuckets];
// get hash from symname to lookup
const uint32_t hash = old_elf_hash(symname);
// Search for it
for (uint32_t i = buckets[hash % nbuckets]; i; i = chains[i]) {
const char* name = h->DynStr + h->DynSym[i].st_name;
if (!strcmp(symname, name) && SymbolMatch(h, i, ver, vername, local, veropt)) {
return &h->DynSym[i];
}
}
return NULL;
}
void old_elf_hash_dump(elfheader_t* h)
{
// Prepare hash table
const uint32_t *hashtab = (uint32_t*)(h->hash + h->delta);
const uint32_t nbuckets = hashtab[0];
const uint32_t nchains = hashtab[1];
const uint32_t *buckets = &hashtab[2];
const uint32_t *chains = &buckets[nbuckets];
printf_log(LOG_NONE, "------------ Dump HASH from %s\n", h->name);
printf_log(LOG_NONE, "Buckets[%d] = \n", nbuckets);
for(uint32_t i=0; i<nbuckets; ++i) {
const char* name = h->DynStr + h->DynSym[buckets[i]].st_name;
printf_log(LOG_NONE, "%d: %s\n", buckets[i], name);
}
printf_log(LOG_NONE,"Chains[%d] = ", nchains);
for (uint32_t i = 0; i<nchains; ++i)
printf_log(LOG_NONE, "%d ", chains[i]);
printf_log(LOG_NONE, "\n------------\n");
}
uint32_t new_elf_hash(const char *name)
{
uint32_t h = 5381;
for (unsigned char c = *name; c; c = *++name)
h = h * 33 + c;
return h;
}
Elf64_Sym* new_elf_lookup(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt)
{
// Prepare hash table
const uint32_t *hashtab = (uint32_t*)(h->gnu_hash + h->delta);
const uint32_t nbuckets = hashtab[0];
const uint32_t symoffset = hashtab[1];
const uint32_t bloom_size = hashtab[2];
const uint32_t bloom_shift = hashtab[3];
const uint64_t *blooms = (uint64_t*)&hashtab[4];
const uint32_t *buckets = (uint32_t*)&blooms[bloom_size];
const uint32_t *chains = &buckets[nbuckets];
// get hash from symname to lookup
const uint32_t hash = new_elf_hash(symname);
// early check with bloom: if at least one bit is not set, a symbol is surely missing.
uint64_t word = blooms[(hash/64)%bloom_size];
uint64_t mask = 0
| 1LL << (hash%64)
| 1LL << ((hash>>bloom_shift)%64);
if ((word & mask) != mask) {
return NULL;
}
// now look at the bucket chain for the symbol
uint32_t symidx = buckets[hash%nbuckets];
if (symidx < symoffset)
return NULL;
while(1) {
const char* name = h->DynStr + h->DynSym[symidx].st_name;
const uint32_t symhash = chains[symidx-symoffset];
if ((hash|1) == (symhash|1) && !strcmp(name, symname) && SymbolMatch(h, symidx, ver, vername, local, veropt)) {
return &h->DynSym[symidx];
}
if(symhash&1)
return NULL;
symidx++;
}
}
void new_elf_hash_dump(elfheader_t* h)
{
// Prepare hash table
const uint32_t *hashtab = (uint32_t*)(h->gnu_hash + h->delta);
const uint32_t nbuckets = hashtab[0];
const uint32_t symoffset = hashtab[1];
const uint32_t bloom_size = hashtab[2];
const uint32_t bloom_shift = hashtab[3];
const uint64_t *blooms = (uint64_t*)&hashtab[4];
const uint32_t *buckets = (uint32_t*)&blooms[bloom_size];
const uint32_t *chains = &buckets[nbuckets];
printf_log(LOG_NONE, "===============Dump GNU_HASH from %s\n", h->name);
printf_log(LOG_NONE, "Bloom: size=%d, shift=%d\n", bloom_size, bloom_shift);
printf_log(LOG_NONE, "Buckets[%d] offset=%d = \n", nbuckets, symoffset);
for(uint32_t i=0; i<nbuckets; ++i) {
uint32_t symidx = buckets[i];
printf_log(LOG_NONE, "%d:", symidx);
while(symidx>=symoffset) {
const char* name = h->DynStr + h->DynSym[symidx].st_name;
const uint32_t hash = chains[symidx-symoffset];
if(hash&1)
symidx=0;
else
symidx++;
printf_log(LOG_NONE, " %s (%x) -> %d", name, hash, symidx);
}
printf_log(LOG_NONE, "\n");
}
printf_log(LOG_NONE, "\n===============\n");
}
Elf64_Sym* ElfLookup(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt)
{
if(h->gnu_hash)
return new_elf_lookup(h, symname, ver, vername, local, veropt);
return old_elf_lookup(h, symname, ver, vername, local, veropt);
}
Elf64_Sym* ElfSymTabLookup(elfheader_t* h, const char* symname)
{
if(!h->SymTab)
return 0;
for(int i=0; i<h->numSymTab; ++i) {
Elf64_Sym* sym = &h->SymTab[i];
int type = ELF64_ST_TYPE(sym->st_info);
if(type==STT_FUNC || type==STT_TLS || type==STT_OBJECT) {
const char * name = h->StrTab+sym->st_name;
if(name && !strcmp(symname, name))
return sym;
}
}
return NULL;
}
Elf64_Sym* ElfDynSymLookup(elfheader_t* h, const char* symname)
{
if(!h->DynSym)
return 0;
for(int i=0; i<h->numDynSym; ++i) {
Elf64_Sym* sym = &h->DynSym[i];
int type = ELF64_ST_TYPE(sym->st_info);
if(type==STT_FUNC || type==STT_TLS || type==STT_OBJECT) {
const char * name = h->DynStr+sym->st_name;
if(name && !strcmp(symname, name))
return sym;
}
}
return NULL;
}

View File

@ -231,10 +231,11 @@ const char* DumpSym(elfheader_t *h, Elf64_Sym* sym, int version)
{
static char buff[4096];
const char* vername = (version==-1)?"(none)":((version==0)?"*local*":((version==1)?"*global*":GetSymbolVersion(h, version)));
int veropt = GetSymbolVersionFlag(h, version)?0:1;
memset(buff, 0, sizeof(buff));
sprintf(buff, "\"%s\", value=%p, size=%ld, info/other=%d/%d index=%d (ver=%d/%s)",
sprintf(buff, "\"%s\", value=%p, size=%ld, info/other=%d/%d index=%d (%sver=%d/%s)",
h->DynStr+sym->st_name, (void*)sym->st_value, sym->st_size,
sym->st_info, sym->st_other, sym->st_shndx, version, vername);
sym->st_info, sym->st_other, sym->st_shndx, veropt?"opt":"", version, vername);
return buff;
}

View File

@ -64,11 +64,6 @@ elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec)
h->path[0] = '\0';
}
h->mapsymbols = NewMapSymbols();
h->weaksymbols = NewMapSymbols();
h->localsymbols = NewMapSymbols();
h->globaldefver = NewDefaultVersion();
h->weakdefver = NewDefaultVersion();
h->refcnt = 1;
h->file = f;
@ -94,12 +89,6 @@ void FreeElfHeader(elfheader_t** head)
box_free(h->SymTab);
box_free(h->DynSym);
FreeMapSymbols(&h->mapsymbols);
FreeMapSymbols(&h->weaksymbols);
FreeMapSymbols(&h->localsymbols);
FreeDefaultVersion(&h->globaldefver);
FreeDefaultVersion(&h->weakdefver);
FreeElfMemory(h);
box_free(h->name);
@ -259,7 +248,7 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
try_mmap = 0;
if(e->p_offset&(box64_pagesize-1))
try_mmap = 0;
if(e->p_memsz-e->p_filesz>(box64_pagesize-1))
if(ALIGN(e->p_memsz)!=ALIGN(e->p_filesz))
try_mmap = 0;
if(!e->p_filesz)
try_mmap = 0;
@ -279,8 +268,8 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
try_mmap = 0;
printf_dump(log_level, "Mapping failed, using regular mmap+read");
} else {
/*if(e->p_memsz>e->p_filesz)
memset((void*)((uintptr_t)p + e->p_filesz), 0, e->p_memsz-e->p_filesz);*/ // already zero'd by the mmap
if(e->p_memsz>e->p_filesz && (prot&PROT_WRITE))
memset((void*)((uintptr_t)p + e->p_filesz), 0, e->p_memsz-e->p_filesz);
setProtection_elf((uintptr_t)p, head->multiblocks[n].asize, prot);
head->multiblocks[n].p = p;
@ -418,7 +407,29 @@ int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verne
return 1;
}
int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t** p, size_t size, int version, const char* vername)
static int IsSymInElfSpace(const elfheader_t* h, Elf64_Sym* sym)
{
if(!h || !sym)
return 0;
uintptr_t addr = (uintptr_t)sym;
if(h->SymTab && addr>=(uintptr_t)h->SymTab && addr<(uintptr_t)&h->SymTab[h->numSymTab])
return 1;
if(h->DynSym && addr>=(uintptr_t)h->DynSym && addr<(uintptr_t)&h->DynSym[h->numDynSym])
return 1;
return 0;
}
static elfheader_t* FindElfSymbol(box64context_t *context, Elf64_Sym* sym)
{
if(!sym)
return NULL;
for (int i=0; i<context->elfsize; ++i)
if(IsSymInElfSpace(context->elfs[i], sym))
return context->elfs[i];
return NULL;
}
int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t** p, size_t size, int version, const char* vername, int veropt)
{
if(!h)
return 0;
@ -435,7 +446,9 @@ int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t**
if(version2!=-1) version2 &= 0x7fff;
if(version && !version2) version2=-1; // match a versioned symbol against a global "local" symbol
const char* vername2 = GetSymbolVersion(h, version2);
if(SameVersionedSymbol(name, version, vername, symname, version2, vername2)) {
Elf64_Half flags = GetSymbolVersionFlag(h, version2);
int veropt2 = flags?0:1;
if(SameVersionedSymbol(name, version, vername, veropt, symname, version2, vername2, veropt2)) {
if(offs) *offs = sym->st_value + h->delta;
if(p) *p = (uint64_t*)(rela[i].r_offset + h->delta + rela[i].r_addend);
return 1;
@ -447,184 +460,8 @@ int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t**
int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head, int cnt, Elf64_Rel *rel)
{
int ret_ok = 0;
for (int i=0; i<cnt; ++i) {
int t = ELF64_R_TYPE(rel[i].r_info);
Elf64_Sym *sym = &head->DynSym[ELF64_R_SYM(rel[i].r_info)];
int bind = ELF64_ST_BIND(sym->st_info);
const char* symname = SymName(head, sym);
//uint64_t ndx = sym->st_shndx;
uint64_t *p = (uint64_t*)(rel[i].r_offset + head->delta);
uintptr_t offs = 0;
uintptr_t end = 0;
size_t size = sym->st_size;
//uintptr_t tmp = 0;
int version = head->VerSym?((Elf64_Half*)((uintptr_t)head->VerSym+head->delta))[ELF64_R_SYM(rel[i].r_info)]:-1;
if(version!=-1) version &=0x7fff;
const char* vername = GetSymbolVersion(head, version);
const char* globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(maplib, local_maplib, 0, deepbind, symname);
const char* weakdefver = (bind==STB_WEAK || !globdefver)?GetMaplibDefaultVersion(maplib, local_maplib, 1, deepbind, symname):NULL;
if(bind==STB_LOCAL) {
if(!symname || !symname[0]) {
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
} else {
if(!offs && !end && local_maplib && deepbind)
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
if(!offs && !end)
GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
if(!offs && !end && local_maplib && !deepbind)
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
}
} else {
// this is probably very very wrong. A proprer way to get reloc need to be written, but this hack seems ok for now
// at least it work for half-life, unreal, ut99, zsnes, Undertale, ColinMcRae Remake, FTL, ShovelKnight...
/*if(bind==STB_GLOBAL && (ndx==10 || ndx==19) && t!=R_X86_64_GLOB_DAT) {
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
}*/
// so weak symbol are the one left
if(bind==STB_WEAK) {
if(!offs && !end) {
if(!offs && !end && local_maplib && deepbind)
GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
if(!offs && !end)
GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
if(!offs && !end && local_maplib && !deepbind)
GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
}
} else {
if(!offs && !end) {
if(!offs && !end && local_maplib && deepbind)
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
if(!offs && !end)
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
if(!offs && !end && local_maplib && !deepbind)
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
}
}
}
uintptr_t globoffs, globend;
uint64_t* globp;
switch(t) {
case R_X86_64_NONE:
// can be ignored
printf_dump(LOG_NEVER, "Ignoring %s @%p (%p)\n", DumpRelType(t), p, (void*)(p?(*p):0));
break;
case R_X86_64_PC32:
if (!offs) {
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_X86_64_PC32 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
ret_ok = 1;
}
offs = (offs - (uintptr_t)p);
if(!offs)
printf_dump(LOG_NEVER, "Apply %s R_X86_64_PC32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(*(uintptr_t*)p+offs));
*p += offs;
break;
case R_X86_64_GLOB_DAT:
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername, globdefver) && FindR64COPYRel(my_context->elfs[0], symname, &globoffs, &globp, size, version, vername)) {
// set global offs / size for the symbol
offs = sym->st_value;
end = offs + sym->st_size;
if(sym->st_size && offs) {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) size=%ld on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)(offs + head->delta), (void*)globoffs, sym->st_size, symname);
memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
AddUniqueSymbol(GetGlobalData(maplib), symname, globoffs, sym->st_size, version, vername);
AddUniqueSymbol(my_context->globdata, symname, offs + head->delta, sym->st_size, version, vername);
} else {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) null sized on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, symname);
}
*p = globoffs;
} else {
if((size==0) && GetSymbolStartEnd(GetGlobalData(maplib), symname, &globoffs, &globend, version, vername, 0, globdefver)) {
offs = globoffs;
}
if (!offs) {
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start") && strcmp(symname, "collector_func_load"))
printf_log(LOG_NONE, "%s: Global Symbol %s (ver=%d/%s) not found, cannot apply R_X86_64_GLOB_DAT @%p (%p) in %s\n", (bind==STB_WEAK)?"Warning":"Error", symname, version, vername?vername:"(none)", p, *(void**)p, head->name);
} else {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT @%p (%p -> %p) on sym=%s (ver=%d/%s)\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname, version, vername?vername:"(none)");
*p = offs;
}
}
break;
case R_X86_64_COPY:
if(offs) {
uintptr_t old_offs = offs;
uintptr_t old_end = end;
offs = 0;
GetSizedSymbolStartEnd(my_context->globdata, symname, &offs, &end, size, version, vername, 1, globdefver); // try globaldata symbols first
if(offs==0) {
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, size, version, vername, globdefver, weakdefver); // get original copy if any
if(!offs && local_maplib)
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername, globdefver, weakdefver);
}
if(!offs) {
offs = old_offs;
end = old_end;
}
printf_dump(LOG_NEVER, "Apply %s R_X86_64_COPY @%p with sym=%s, @%p size=%ld (", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)offs, sym->st_size);
memmove(p, (void*)offs, sym->st_size);
if(box64_dump) {
uint64_t *k = (uint64_t*)p;
for (unsigned j=0; j<((sym->st_size>128u)?128u:sym->st_size); j+=8, ++k)
printf_dump(LOG_NEVER, "%s0x%016lX", j?" ":"", *k);
printf_dump(LOG_NEVER, "%s)\n", (sym->st_size>128u)?" ...":"");
}
} else {
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_X86_64_COPY @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
}
break;
case R_X86_64_RELATIVE:
printf_dump(LOG_NEVER, "Apply %s R_X86_64_RELATIVE @%p (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)((*p)+head->delta));
*p += head->delta;
break;
case R_X86_64_64:
if (!offs) {
printf_log(LOG_NONE, "%s: Symbol %s not found, cannot apply R_X86_64_64 @%p (%p) in %s\n", (bind==STB_GLOBAL)?"Error":"Warning", symname, p, *(void**)p, head->name);
if(bind==STB_GLOBAL)
ret_ok = 1;
// return -1;
} else {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_64 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(offs+*(uint64_t*)p));
*p += offs;
}
break;
#if 0
case R_X86_64_JUMP_SLOT:
// apply immediatly for gobject closure marshal or for LOCAL binding. Also, apply immediatly if it doesn't jump in the got
tmp = (uintptr_t)(*p);
if (bind==STB_LOCAL
|| ((symname && strstr(symname, "g_cclosure_marshal_")==symname))
|| !tmp
|| !((tmp>=head->plt && tmp<head->plt_end) || (tmp>=head->gotplt && tmp<head->gotplt_end))
) {
if (!offs) {
if(bind==STB_WEAK) {
printf_log(LOG_INFO, "Warning: Weak Symbol %s not found, cannot apply R_X86_64_JUMP_SLOT @%p (%p)\n", symname, p, *(void**)p);
} else {
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_X86_64_JUMP_SLOT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
}
// return -1;
} else {
if(p) {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_JUMP_SLOT @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs);
*p = offs;
} else {
printf_log(LOG_NONE, "Warning, Symbol %s found, but Jump Slot Offset is NULL \n", symname);
}
}
} else {
printf_dump(LOG_NEVER, "Preparing (if needed) %s R_X86_64_JUMP_SLOT @%p (0x%lx->0x%0lx) with sym=%s to be apply later\n", (bind==STB_LOCAL)?"Local":"Global", p, *p, *p+head->delta, symname);
*p += head->delta;
}
break;
#endif
default:
printf_log(LOG_INFO, "Warning, don't know how to handle rel #%d %s (%p)\n", i, DumpRelType(ELF64_R_TYPE(rel[i].r_info)), p);
}
}
return bindnow?ret_ok:0;
printf_log(LOG_NONE, "Error: REL type of Relocation unsupported (only RELA)\n");
return 1;
}
struct tlsdesc
@ -640,17 +477,32 @@ EXPORT uintptr_t _dl_tlsdesc_undefweak(x64emu_t* emu)
return td->arg;
}
void GrabX64CopyMainElfReloc(elfheader_t* head)
{
if(head->rela) {
int cnt = head->relasz / head->relaent;
Elf64_Rela* rela = (Elf64_Rela *)(head->rela + head->delta);
printf_dump(LOG_DEBUG, "Grabbing R_X86_64_COPY Relocation(s) in advance for %s\n", head->name);
for (int i=0; i<cnt; ++i) {
int t = ELF64_R_TYPE(rela[i].r_info);
if(t == R_X86_64_COPY) {
Elf64_Sym *sym = &head->DynSym[ELF64_R_SYM(rela[i].r_info)];
const char* symname = SymName(head, sym);
int version = head->VerSym?((Elf64_Half*)((uintptr_t)head->VerSym+head->delta))[ELF64_R_SYM(rela[i].r_info)]:-1;
if(version!=-1) version &=0x7fff;
const char* vername = GetSymbolVersion(head, version);
Elf64_Half flags = GetSymbolVersionFlag(head, version);
int veropt = flags?0:1;
uintptr_t offs = sym->st_value + head->delta;
AddUniqueSymbol(my_context->globdata, symname, offs, sym->st_size, version, vername, veropt);
}
}
}
}
int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head, int cnt, Elf64_Rela *rela, int* need_resolv)
{
int ret_ok = 0;
const char* old_globdefver = NULL;
const char* old_weakdefver = NULL;
int old_bind = -1;
const char* old_symname = NULL;
uintptr_t old_offs = 0;
uintptr_t old_end = 0;
int old_version = -1;
for (int i=0; i<cnt; ++i) {
int t = ELF64_R_TYPE(rela[i].r_info);
Elf64_Sym *sym = &head->DynSym[ELF64_R_SYM(rela[i].r_info)];
@ -661,74 +513,51 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin
uintptr_t offs = 0;
uintptr_t end = 0;
size_t size = sym->st_size;
elfheader_t* h_tls = NULL;//head;
elfheader_t* sym_elf = NULL;
int version = head->VerSym?((Elf64_Half*)((uintptr_t)head->VerSym+head->delta))[ELF64_R_SYM(rela[i].r_info)]:-1;
if(version!=-1) version &=0x7fff;
const char* vername = GetSymbolVersion(head, version);
const char* globdefver = NULL;
const char* weakdefver = NULL;
if(old_bind==bind && old_symname==symname) {
globdefver = old_globdefver;
weakdefver = old_weakdefver;
Elf64_Half flags = GetSymbolVersionFlag(head, version);
int veropt = flags?0:1;
Elf64_Sym* elfsym = NULL;
int vis = ELF64_ST_VISIBILITY(sym->st_other);
if(vis==STV_PROTECTED) {
elfsym = ElfDynSymLookup(head, symname);
printf_log(LOG_INFO, "Symbol %s from %s is PROTECTED\n", symname, head);
} else {
old_globdefver = globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(maplib, local_maplib, 0, deepbind, symname);
old_weakdefver = weakdefver = (bind==STB_WEAK || !globdefver)?GetMaplibDefaultVersion(maplib, local_maplib, 1, deepbind, symname):NULL;
}
if(bind==STB_LOCAL) {
if(!symname || !symname[0]) {
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
} else {
if(old_version==version && old_bind==bind && old_symname==symname) {
offs = old_offs;
end = old_end;
} else {
if(local_maplib && deepbind)
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
if(!offs && !end)
GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
if(!offs && !end && local_maplib && !deepbind)
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
}
}
} else {
// this is probably very very wrong. A proprer way to get reloc need to be written, but this hack seems ok for now
// at least it work for half-life, unreal, ut99, zsnes, Undertale, ColinMcRae Remake, FTL, ShovelKnight...
/*if(bind==STB_GLOBAL && (ndx==10 || ndx==19) && t!=R_X86_64_GLOB_DAT) {
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
}*/
// so weak symbol are the one left
if(bind==STB_WEAK) {
if(old_version==version && old_bind==bind && old_symname==symname) {
offs = old_offs;
end = old_end;
} else {
if(local_maplib && deepbind)
GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
else
GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
if(!offs && !end && local_maplib && !deepbind)
GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
}
} else {
if(old_version==version && old_bind==bind && old_symname==symname) {
offs = old_offs;
end = old_end;
if(bind==STB_GNU_UNIQUE) {
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, veropt, (void**)&elfsym);
if(!offs && !end && local_maplib)
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, veropt, (void**)&elfsym);
} else if(bind==STB_LOCAL) {
if(!symname || !symname[0]) {
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
} else {
elfsym = ElfDynSymLookup(head, symname);
if(elfsym && elfsym->st_shndx) {
offs = elfsym->st_value + head->delta;
end = offs + elfsym->st_size;
}
if(!offs && !end && local_maplib && deepbind)
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, veropt, (void**)&elfsym);
if(!offs && !end)
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, veropt, (void**)&elfsym);
if(!offs && !end && local_maplib && !deepbind)
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, veropt, (void**)&elfsym);
}
} else {
if(!offs && !end && local_maplib && deepbind)
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, veropt, (void**)&elfsym);
if(!offs && !end)
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, veropt, (void**)&elfsym);
if(!offs && !end && local_maplib && !deepbind)
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, veropt, (void**)&elfsym);
}
}
old_bind = bind;
old_symname = symname;
old_offs = offs;
old_end = end;
sym_elf = FindElfSymbol(my_context, elfsym);
if(elfsym && (ELF64_ST_TYPE(elfsym->st_info)==STT_TLS))
offs = elfsym->st_value;
uintptr_t globoffs, globend;
uint64_t* globp;
uintptr_t tmp = 0;
@ -741,14 +570,14 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin
// can be ignored
break;
case R_X86_64_RELATIVE:
printf_dump(LOG_NEVER, "Apply %s R_X86_64_RELATIVE @%p (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)(head->delta+ rela[i].r_addend));
printf_dump(LOG_NEVER, "Apply %s R_X86_64_RELATIVE @%p (%p -> %p)\n", BindSym(bind), p, *(void**)p, (void*)(head->delta+ rela[i].r_addend));
*p = head->delta+ rela[i].r_addend;
break;
case R_X86_64_IRELATIVE:
{
x64emu_t* emu = thread_get_emu();
EmuCall(emu, head->delta+rela[i].r_addend);
printf_dump(LOG_NEVER, "Apply %s R_X86_64_IRELATIVE @%p (%p -> %p()=%p)\n", (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)(head->delta+ rela[i].r_addend), (void*)(R_RAX));
printf_dump(LOG_NEVER, "Apply %s R_X86_64_IRELATIVE @%p (%p -> %p()=%p)\n", BindSym(bind), p, *(void**)p, (void*)(head->delta+ rela[i].r_addend), (void*)(R_RAX));
*p = R_RAX;
}
break;
@ -756,15 +585,16 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin
globoffs = offs;
globend = end;
offs = end = 0;
GetSizedSymbolStartEnd(my_context->globdata, symname, &offs, &end, size, version, vername, 1, globdefver); // try globaldata symbols first
if(!offs && local_maplib)
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername, globdefver, weakdefver);
if(!offs && local_maplib && deepbind)
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername, veropt, NULL);
if(!offs)
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, size, version, vername, globdefver, weakdefver);
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, size, version, vername, veropt, NULL);
if(!offs && local_maplib && !deepbind)
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername, veropt, NULL);
if(!offs) {offs = globoffs; end = globend;}
if(offs) {
// add r_addend to p?
printf_dump(LOG_NEVER, "Apply R_X86_64_COPY @%p with sym=%s (ver=%d/%s), @%p+0x%lx size=%ld\n", p, symname, version, vername?vername:"(none)", (void*)offs, rela[i].r_addend, sym->st_size);
printf_dump(LOG_NEVER, "Apply R_X86_64_COPY @%p with sym=%s (%sver=%d/%s), @%p+0x%lx size=%ld\n", p, symname, veropt?"opt":"", version, vername?vername:"(none)", (void*)offs, rela[i].r_addend, sym->st_size);
if(p!=(void*)(offs+rela[i].r_addend))
memmove(p, (void*)(offs+rela[i].r_addend), sym->st_size);
} else {
@ -772,33 +602,20 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin
}
break;
case R_X86_64_GLOB_DAT:
if((head!=my_context->elfs[0]) && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername, globdefver) && FindR64COPYRel(my_context->elfs[0], symname, &globoffs, &globp, size, version, vername)) {
// set global offs / size for the symbol
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
if(sym->st_size && offs) {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) size=%zd on sym=%s (ver=%d/%s) \n",
(bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0),
(void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname, version, vername?vername:"(none)");
//memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
AddUniqueSymbol(GetGlobalData(maplib), symname, globoffs, sym->st_size, version, vername);
AddUniqueSymbol(my_context->globdata, symname, offs, sym->st_size, version, vername);
} else {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) null sized on sym=%s (ver=%d/%s)\n",
(bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0),
(void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, symname, version, vername?vername:"(none)");
}
if(GetSymbolStartEnd(my_context->globdata, symname, &globoffs, &globend, version, vername, 1, veropt)) {
globp = (uint64_t*)globoffs;
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) size=%zd on sym=%s (%sver=%d/%s) \n",
BindSym(bind), p, globp, (void*)(p?(*p):0),
(void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname, veropt?"opt":"", version, vername?vername:"(none)");
sym_elf = my_context->elfs[0];
*p = globoffs;
} else {
if((size==0) && GetSymbolStartEnd(GetGlobalData(maplib), symname, &globoffs, &globend, version, vername, 0, globdefver)) {
offs = globoffs;
}
if (!offs) {
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start") && strcmp(symname, "collector_func_load"))
printf_log((bind==STB_WEAK)?LOG_INFO:LOG_NONE, "%s: Global Symbol %s not found, cannot apply R_X86_64_GLOB_DAT @%p (%p) in %s\n", (bind==STB_WEAK)?"Warning":"Error", symname, p, *(void**)p, head->name);
printf_log((bind==STB_WEAK)?LOG_DEBUG:LOG_NONE, "%s: Global Symbol %s not found, cannot apply R_X86_64_GLOB_DAT @%p (%p) in %s\n", (bind==STB_WEAK)?"Warning":"Error", symname, p, *(void**)p, head->name);
} else {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT @%p (%p -> %p) on sym=%s (ver=%d/%s)\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname, version, vername?vername:"(none)");
*p = offs/* + rela[i].r_addend*/; // not addend it seems
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT @%p (%p -> %p) on sym=%s (%sver=%d/%s, elf=%s)\n", BindSym(bind), p, (void*)(p?(*p):0), (void*)(offs + rela[i].r_addend), symname, veropt?"opt":"", version, vername?vername:"(none)", sym_elf?sym_elf->name:"(native)");
*p = offs + rela[i].r_addend;
}
}
break;
@ -823,8 +640,9 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin
// return -1;
} else {
if(p) {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_JUMP_SLOT @%p with sym=%s (%p -> %p)\n",
(bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(offs+rela[i].r_addend));
elfheader_t* sym_elf = FindElfAddress(my_context, offs);
printf_dump(LOG_NEVER, "Apply %s R_X86_64_JUMP_SLOT @%p with sym=%s (%p -> %p / %s (%sver=%d / %s))\n",
BindSym(bind), p, symname, *(void**)p, (void*)(offs+rela[i].r_addend), sym_elf?sym_elf->name:"native", veropt?"opt":"", version, vername?vername:"(none)");
*p = offs + rela[i].r_addend;
} else {
printf_log(LOG_INFO, "Warning, Symbol %s found, but Jump Slot Offset is NULL \n", symname);
@ -832,13 +650,13 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin
}
} else {
printf_dump(LOG_NEVER, "Preparing (if needed) %s R_X86_64_JUMP_SLOT @%p (0x%lx->0x%0lx) with sym=%s to be apply later (addend=%ld)\n",
(bind==STB_LOCAL)?"Local":"Global", p, *p, *p+head->delta, symname, rela[i].r_addend);
BindSym(bind), p, *p, *p+head->delta, symname, rela[i].r_addend);
*p += head->delta;
*need_resolv = 1;
}
break;
case R_X86_64_64:
if (!offs) {
if (!offs && !elfsym) {
if(symname && !strcmp(symname, "__gxx_personality_v0")) {
printf_dump(LOG_NEVER, "Warning: Symbol %s not found, cannot apply R_X86_64_64 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
} else {
@ -848,8 +666,8 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin
// return -1;
}
} else {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_64 @%p with sym=%s (ver=%d/%s) addend=0x%lx (%p -> %p)\n",
(bind==STB_LOCAL)?"Local":"Global", p, symname, version, vername?vername:"(none)", rela[i].r_addend, *(void**)p, (void*)(offs+rela[i].r_addend/*+*(uint64_t*)p*/));
printf_dump(LOG_NEVER, "Apply %s R_X86_64_64 @%p with sym=%s (%sver=%d/%s) addend=0x%lx (%p -> %p)\n",
BindSym(bind), p, symname, veropt?"opt":"", version, vername?vername:"(none)", rela[i].r_addend, *(void**)p, (void*)(offs+rela[i].r_addend/*+*(uint64_t*)p*/));
*p /*+*/= offs+rela[i].r_addend;
}
break;
@ -857,21 +675,15 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin
// Negated offset in static TLS block
{
if(!symname || !symname[0]) {
h_tls = head;
sym_elf = head;
offs = sym->st_value;
} else {
h_tls = NULL;
if(local_maplib)
h_tls = GetGlobalSymbolElf(local_maplib, symname, version, vername);
if(!h_tls)
h_tls = GetGlobalSymbolElf(maplib, symname, version, vername);
}
if(h_tls) {
if(sym_elf) {
delta = *(int64_t*)p;
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%ld -> %ld+%ld+%ld, size=%ld)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, h_tls->tlsbase, (int64_t)offs, rela[i].r_addend, end-offs);
*p = (uintptr_t)((int64_t)offs + rela[i].r_addend + h_tls->tlsbase);
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%ld -> %ld+%ld+%ld, size=%ld)\n", BindSym(bind), DumpRelType(t), symname, p, delta, sym_elf->tlsbase, (int64_t)offs, rela[i].r_addend, end-offs);
*p = (uintptr_t)((int64_t)offs + rela[i].r_addend + sym_elf->tlsbase);
} else {
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%ld), no elf_header found\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, (int64_t)offs);
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%ld), no elf_header found\n", BindSym(bind), DumpRelType(t), symname, p, (int64_t)offs);
}
}
break;
@ -880,16 +692,10 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin
if(!symname || symname[0]=='\0' || bind==STB_LOCAL)
offs = getElfIndex(my_context, head);
else {
if(!h_tls) {
if(local_maplib)
h_tls = GetGlobalSymbolElf(local_maplib, symname, version, vername);
if(!h_tls)
h_tls = GetGlobalSymbolElf(maplib, symname, version, vername);
}
offs = getElfIndex(my_context, h_tls);
offs = getElfIndex(my_context, sym_elf);
}
if(p) {
printf_dump(LOG_NEVER, "Apply %s %s @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", "R_X86_64_DTPMOD64", p, symname, *(void**)p, (void*)offs);
printf_dump(LOG_NEVER, "Apply %s %s @%p with sym=%s (%p -> %p)\n", BindSym(bind), "R_X86_64_DTPMOD64", p, symname, *(void**)p, (void*)offs);
*p = offs;
} else {
printf_log(LOG_INFO, "Warning, Symbol %s or Elf not found, but R_X86_64_DTPMOD64 Slot Offset is NULL \n", symname);
@ -897,7 +703,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin
break;
case R_X86_64_DTPOFF64:
// Offset in TLS block
if (!offs && !end) {
if (!offs && !sym_elf) {
if(bind==STB_WEAK) {
printf_log(LOG_INFO, "Warning: Weak Symbol %s not found, cannot apply R_X86_64_DTPOFF64 @%p (%p)\n", symname, p, *(void**)p);
} else {
@ -908,8 +714,8 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin
if(!symname || symname[0]=='\0')
offs = sym->st_value;
if(p) {
int64_t tlsoffset = offs; // it's not an offset in elf memory
printf_dump(LOG_NEVER, "Apply %s R_X86_64_DTPOFF64 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)tlsoffset, (void*)offs);
int64_t tlsoffset = (int64_t)offs; // it's not an offset in elf memory
printf_dump(LOG_NEVER, "Apply %s R_X86_64_DTPOFF64 @%p with sym=%s (%p -> %p)\n", BindSym(bind), p, symname, (void*)tlsoffset, (void*)offs);
*p = tlsoffset;
} else {
printf_log(LOG_INFO, "Warning, Symbol %s found, but R_X86_64_DTPOFF64 Slot Offset is NULL \n", symname);
@ -918,7 +724,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin
break;
case R_X86_64_TLSDESC:
if(!symname || !symname[0]) {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_TLSDESC @%p with addend=%zu\n", (bind==STB_LOCAL)?"Local":"Global", p, rela[i].r_addend);
printf_dump(LOG_NEVER, "Apply %s R_X86_64_TLSDESC @%p with addend=%zu\n", BindSym(bind), p, rela[i].r_addend);
struct tlsdesc volatile *td = (struct tlsdesc volatile *)p;
if(!tlsdescUndefweak)
tlsdescUndefweak = AddBridge(my_context->system, pFE, _dl_tlsdesc_undefweak, 0, "_dl_tlsdesc_undefweak");
@ -1067,93 +873,13 @@ uintptr_t GetLastByte(elfheader_t* h)
#endif
void checkHookedSymbols(elfheader_t* h); // in mallochook.c
void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h)
void AddSymbols(lib_t *maplib, elfheader_t* h)
{
//if(box64_dump && h->hash) old_elf_hash_dump(h);
//if(box64_dump && h->gnu_hash) new_elf_hash_dump(h);
if(box64_dump && h->DynSym) DumpDynSym(h);
printf_dump(LOG_NEVER, "Will look for Symbol to add in SymTable(%zu)\n", h->numSymTab);
for (size_t i=0; i<h->numSymTab; ++i) {
const char * symname = h->StrTab+h->SymTab[i].st_name;
int bind = ELF64_ST_BIND(h->SymTab[i].st_info);
int type = ELF64_ST_TYPE(h->SymTab[i].st_info);
int vis = h->SymTab[i].st_other&0x3;
size_t sz = h->SymTab[i].st_size;
if((type==STT_OBJECT || type==STT_FUNC || type==STT_COMMON || type==STT_TLS || type==STT_NOTYPE)
&& (vis==STV_DEFAULT || vis==STV_PROTECTED || (vis==STV_HIDDEN && bind==STB_LOCAL)) && (h->SymTab[i].st_shndx!=0)) {
if(sz && strstr(symname, "@@")) {
char symnameversioned[strlen(symname)+1];
strcpy(symnameversioned, symname);
// extact symname@@vername
char* p = strchr(symnameversioned, '@');
*p=0;
p+=2;
symname = AddDictionnary(my_context->versym, symnameversioned);
const char* vername = AddDictionnary(my_context->versym, p);
AddDefaultVersion((bind==STB_WEAK)?h->weakdefver:h->globaldefver, symname, vername);
if((bind==STB_GNU_UNIQUE /*|| (bind==STB_GLOBAL && type==STT_FUNC)*/) && FindGlobalSymbol(maplib, symname, 2, p))
continue;
uintptr_t offs = (type==STT_TLS)?h->SymTab[i].st_value:(h->SymTab[i].st_value + h->delta);
printf_dump(LOG_NEVER, "Adding Default Versioned Symbol(bind=%s) \"%s@%s\" with offset=%p sz=%zu\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, vername, (void*)offs, sz);
if(bind==STB_LOCAL)
AddSymbol(localsymbols, symname, offs, sz, 2, vername);
else // add in local and global map
if(bind==STB_WEAK) {
AddSymbol(weaksymbols, symname, offs, sz, 2, vername);
} else {
AddSymbol(mapsymbols, symname, offs, sz, 2, vername);
}
} else {
int to_add = 1;
if(!to_add || (bind==STB_GNU_UNIQUE && FindGlobalSymbol(maplib, symname, -1, NULL)))
continue;
uintptr_t offs = (type==STT_TLS)?h->SymTab[i].st_value:(h->SymTab[i].st_value + h->delta);
printf_dump(LOG_NEVER, "Adding Symbol(bind=%s) \"%s\" with offset=%p sz=%zu\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, (void*)offs, sz);
if(bind==STB_LOCAL)
AddSymbol(localsymbols, symname, offs, sz, 1, NULL);
else // add in local and global map
if(bind==STB_WEAK) {
AddSymbol(weaksymbols, symname, offs, sz, 1, NULL);
} else {
AddSymbol(mapsymbols, symname, offs, sz, 1, NULL);
}
}
}
}
int deepbind = 0;
if(h && h->lib)
deepbind = GetDeepBind(h->lib);
printf_dump(LOG_NEVER, "Will look for Symbol to add in DynSym (%zu)\n", h->numDynSym);
for (size_t i=0; i<h->numDynSym; ++i) {
const char * symname = h->DynStr+h->DynSym[i].st_name;
int bind = ELF64_ST_BIND(h->DynSym[i].st_info);
int type = ELF64_ST_TYPE(h->DynSym[i].st_info);
int vis = h->DynSym[i].st_other&0x3;
if((type==STT_OBJECT || type==STT_FUNC || type==STT_COMMON || type==STT_TLS || type==STT_NOTYPE)
&& (vis==STV_DEFAULT || vis==STV_PROTECTED || (vis==STV_HIDDEN && bind==STB_LOCAL)) && (h->DynSym[i].st_shndx!=0 && h->DynSym[i].st_shndx<=65521)) {
uintptr_t offs = (type==STT_TLS)?h->DynSym[i].st_value:(h->DynSym[i].st_value + h->delta);
size_t sz = h->DynSym[i].st_size;
int version = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1;
int add_default = (version!=-1 && (version&0x7fff)>1 && !(version&0x8000) && !GetMaplibDefaultVersion(my_context->maplib, (maplib==my_context->maplib)?NULL:maplib, (bind==STB_WEAK)?1:0, deepbind, symname))?1:0;
if(version!=-1) version &= 0x7fff;
const char* vername = GetSymbolVersion(h, version);
if(add_default) {
AddDefaultVersion((bind==STB_WEAK)?h->weakdefver:h->globaldefver, symname, vername);
printf_dump(LOG_NEVER, "Adding Default Version \"%s\" for Symbol\"%s\"\n", vername, symname);
}
int to_add = 1;
if(!to_add || (bind==STB_GNU_UNIQUE && FindGlobalSymbol(maplib, symname, version, vername)))
continue;
printf_dump(LOG_NEVER, "Adding Versioned Symbol(bind=%s) \"%s\" (ver=%d/%s) with offset=%p sz=%zu\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, version, vername?vername:"(none)", (void*)offs, sz);
if(bind==STB_LOCAL)
AddSymbol(localsymbols, symname, offs, sz, version, vername);
else // add in local and global map
if(bind==STB_WEAK) {
AddSymbol(weaksymbols, symname, offs, sz, version, vername);
} else {
AddSymbol(mapsymbols, symname, offs, sz, version?version:1, vername);
}
}
}
if(h==my_context->elfs[0])
GrabX64CopyMainElfReloc(h);
checkHookedSymbols(h);
}
@ -1297,39 +1023,6 @@ void MarkElfInitDone(elfheader_t* h)
h->init_done = 1;
}
void startMallocHook();
void RunElfInitPltResolver(elfheader_t* h, x64emu_t *emu)
{
if(!h || h->init_done)
return;
uintptr_t p = h->initentry + h->delta;
h->init_done = 1;
for(int i=0; i<h->needed->size; ++i) {
library_t *lib = h->needed->libs[i];
elfheader_t *lib_elf = GetElf(lib);
if(lib_elf)
RunElfInitPltResolver(lib_elf, emu);
}
printf_dump(LOG_DEBUG, "Calling Init for %s @%p\n", ElfName(h), (void*)p);
if(h->initentry)
RunSafeFunction(p, 3, my_context->argc, my_context->argv, my_context->envv);
printf_dump(LOG_DEBUG, "Done Init for %s\n", ElfName(h));
// and check init array now
Elf64_Addr *addr = (Elf64_Addr*)(h->initarray + h->delta);
for (size_t i=0; i<h->initarray_sz; ++i) {
if(addr[i]) {
printf_dump(LOG_DEBUG, "Calling Init[%zu] for %s @%p\n", i, ElfName(h), (void*)addr[i]);
RunSafeFunction((uintptr_t)addr[i], 3, my_context->argc, my_context->argv, my_context->envv);
}
}
if(h->malloc_hook_2)
startMallocHook();
h->fini_done = 0; // can be fini'd now (in case it was re-inited)
printf_dump(LOG_DEBUG, "All Init Done for %s\n", ElfName(h));
return;
}
void RunElfInit(elfheader_t* h, x64emu_t *emu)
{
if(!h || h->init_done)
@ -1551,7 +1244,7 @@ const char* VersionedName(const char* name, int ver, const char* vername)
return AddDictionnary(my_context->versym, buf);
}
int SameVersionedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2)
int SameVersionedSymbol(const char* name1, int ver1, const char* vername1, int veropt1, const char* name2, int ver2, const char* vername2, int veropt2)
{
if(strcmp(name1, name2)) //name are different, no need to go further
return 0;
@ -1563,6 +1256,10 @@ int SameVersionedSymbol(const char* name1, int ver1, const char* vername1, const
return 0;
if(ver1==1 || ver2==1) // one if global, ok
return 1;
if(ver1<2 && ver2>1 && veropt2)
return 1;
if(ver2<2 && ver1>1 && veropt1)
return 1;
if(!strcmp(vername1, vername2)) // same vername
return 1;
return 0;
@ -1783,23 +1480,70 @@ void ElfAttachLib(elfheader_t* head, library_t* lib)
head->lib = lib;
}
kh_mapsymbols_t* GetMapSymbols(elfheader_t* h)
Elf64_Sym* ElfLocateSymbol(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt)
{
if(!h)
Elf64_Sym* sym = ElfLookup(head, symname, *ver, *vername, local, *veropt);
if(!sym) return NULL;
if(head->VerSym && !*veropt) {
int idx = ((uintptr_t)sym - (uintptr_t)head->DynSym)/sizeof(Elf64_Sym);
int version = ((Elf64_Half*)((uintptr_t)head->VerSym+head->delta))[idx];
if(version!=-1) version &=0x7fff;
const char* symvername = GetSymbolVersion(head, version);
Elf64_Half flags = GetSymbolVersionFlag(head, version);
if(version>1 && *ver<2 && (flags==0)) {
*ver = version;
*vername = symvername;
*veropt = 1;
} else if(flags==0 && !*veropt && version>1 && *ver>1 && !strcmp(symvername, *vername)) {
*veropt = 1;
}
}
if(!sym->st_shndx) return NULL;
int vis = ELF64_ST_VISIBILITY(sym->st_other);
if(vis==STV_HIDDEN && !local)
return NULL;
return h->mapsymbols;
return sym;
}
kh_mapsymbols_t* GetWeakSymbols(elfheader_t* h)
void* ElfGetLocalSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt)
{
if(!h)
return NULL;
return h->weaksymbols;
Elf64_Sym* sym = ElfLocateSymbol(head, offs, end, symname, ver, vername, local, veropt);
if(!sym) return NULL;
int bind = ELF64_ST_BIND(sym->st_info);
if(bind!=STB_LOCAL) return 0;
if(offs) *offs = sym->st_value + head->delta;
if(end) *end = sym->st_value + head->delta + sym->st_size;
return sym;
}
kh_mapsymbols_t* GetLocalSymbols(elfheader_t* h)
void* ElfGetGlobalSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt)
{
if(!h)
return NULL;
return h->localsymbols;
Elf64_Sym* sym = ElfLocateSymbol(head, offs, end, symname, ver, vername, local, veropt);
if(!sym) return NULL;
int bind = ELF64_ST_BIND(sym->st_info);
if(bind!=STB_GLOBAL && bind!=STB_GNU_UNIQUE) return 0;
if(offs) *offs = sym->st_value + head->delta;
if(end) *end = sym->st_value + head->delta + sym->st_size;
return sym;
}
void* ElfGetWeakSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname, int* ver, const char** vername, int local, int* veropt)
{
Elf64_Sym* sym = ElfLocateSymbol(head, offs, end, symname, ver, vername, local, veropt);
if(!sym) return NULL;
int bind = ELF64_ST_BIND(sym->st_info);
if(bind!=STB_WEAK) return 0;
if(offs) *offs = sym->st_value + head->delta;
if(end) *end = sym->st_value + head->delta + sym->st_size;
return sym;
}
int ElfGetSymTabStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname)
{
Elf64_Sym* sym = ElfSymTabLookup(head, symname);
if(!sym) return 0;
if(!sym->st_shndx) return 0;
if(!sym->st_size) return 0; //needed?
if(offs) *offs = sym->st_value + head->delta;
if(end) *end = sym->st_value + head->delta + sym->st_size;
return 1;
}
typedef struct search_symbol_s{
@ -1873,23 +1617,16 @@ void* GetNativeSymbolUnversioned(void* lib, const char* name)
return s.addr;
}
kh_defaultversion_t* GetGlobalDefaultVersion(elfheader_t* h)
{
return h?h->globaldefver:NULL;
}
kh_defaultversion_t* GetWeakDefaultVersion(elfheader_t* h)
{
return h?h->weakdefver:NULL;
}
uintptr_t pltResolver = ~0LL;
EXPORT void PltResolver(x64emu_t* emu)
{
uintptr_t addr = Pop64(emu);
int slot = (int)Pop64(emu);
elfheader_t *h = (elfheader_t*)addr;
printf_dump(LOG_DEBUG, "PltResolver: Addr=%p, Slot=%d Return=%p: elf is %s (VerSym=%p)\n", (void*)addr, slot, *(void**)(R_RSP), h->name, h->VerSym);
library_t* lib = h->lib;
lib_t* local_maplib = GetMaplib(lib);
int deepbind = GetDeepBind(lib);
printf_dump(LOG_DEBUG, "PltResolver: Addr=%p, Slot=%d Return=%p(%s): elf is %s (VerSym=%p, deepbind=%d, local_maplib=%p) func param: %p, %p...\n", (void*)addr, slot, *(void**)(R_RSP), getAddrFunctionName(*(uintptr_t*)R_RSP),h->name, h->VerSym, deepbind, local_maplib, (void*)R_RDI, (void*)R_RSI);
Elf64_Rela * rel = (Elf64_Rela *)(h->jmprel + h->delta) + slot;
@ -1899,42 +1636,53 @@ EXPORT void PltResolver(x64emu_t* emu)
int version = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[ELF64_R_SYM(rel->r_info)]:-1;
if(version!=-1) version &= 0x7fff;
const char* vername = GetSymbolVersion(h, version);
Elf64_Half flags = GetSymbolVersionFlag(h, version);
int veropt = flags?0:1;
uint64_t *p = (uint64_t*)(rel->r_offset + h->delta);
uintptr_t offs = 0;
uintptr_t end = 0;
library_t* lib = h->lib;
lib_t* local_maplib = GetMaplib(lib);
int deepbind = GetDeepBind(lib);
const char* globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==local_maplib)?NULL:local_maplib, 0, deepbind, symname);
const char* weakdefver = (bind==STB_WEAK)?GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==local_maplib)?NULL:local_maplib, 1, deepbind, symname):NULL;
if(!offs && !end && local_maplib && deepbind)
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, globdefver, weakdefver);
else
GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, version, vername, globdefver, weakdefver);
if(!offs && !end && local_maplib && !deepbind) {
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, globdefver, weakdefver);
Elf64_Sym *elfsym = NULL;
if(bind==STB_LOCAL) {
elfsym = ElfDynSymLookup(h, symname);
if(elfsym && elfsym->st_shndx) {
offs = elfsym->st_value + h->delta;
end = offs + elfsym->st_size;
}
if(!offs && !end && local_maplib && deepbind)
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym);
if(!offs && !end)
GetLocalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym);
if(!offs && !end && local_maplib && !deepbind)
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym);
} else if(bind==STB_WEAK) {
if(local_maplib && deepbind)
GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym);
else
GetGlobalWeakSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym);
if(!offs && !end && local_maplib && !deepbind)
GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym);
} else {
if(!offs && !end && local_maplib && deepbind)
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym);
if(!offs && !end)
GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym);
if(!offs && !end && local_maplib && !deepbind)
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym);
}
if(!offs && !end && !version)
GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, -1, NULL, globdefver, weakdefver);
if (!offs) {
printf_log(LOG_NONE, "Error: PltResolver: Symbol %s(ver %d: %s%s%s) not found, cannot apply R_X86_64_JUMP_SLOT %p (%p) in %s\n", symname, version, symname, vername?"@":"", vername?vername:"", p, *(void**)p, h->name);
printf_log(LOG_NONE, "Error: PltResolver: Symbol %s(%sver %d: %s%s%s) not found, cannot apply R_X86_64_JUMP_SLOT %p (%p) in %s\n", symname, veropt?"opt":"", version, symname, vername?"@":"", vername?vername:"", p, *(void**)p, h->name);
emu->quit = 1;
return;
} else {
elfheader_t* sym_elf = FindElfAddress(my_context, offs);
if(sym_elf && sym_elf!=my_context->elfs[0] && !sym_elf->init_done) {
printf_dump(LOG_DEBUG, "symbol %s from %s but elf not initialized yet, run Init now (from %s)\n", symname, ElfName(sym_elf), ElfName(h));
RunElfInitPltResolver(sym_elf, emu);
}
elfheader_t* sym_elf = FindElfSymbol(my_context, elfsym);
offs = (uintptr_t)getAlternate((void*)offs);
if(p) {
printf_dump(LOG_DEBUG, " Apply %s R_X86_64_JUMP_SLOT %p with sym=%s(ver %d: %s%s%s) (%p -> %p / %s)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, version, symname, vername?"@":"", vername?vername:"",*(void**)p, (void*)offs, ElfName(sym_elf));
printf_dump(LOG_DEBUG, " Apply %s R_X86_64_JUMP_SLOT %p with sym=%s(%sver %d: %s%s%s) (%p -> %p / %s)\n", BindSym(bind), p, symname, veropt?"opt":"", version, symname, vername?"@":"", vername?vername:"",*(void**)p, (void*)offs, ElfName(sym_elf));
*p = offs;
} else {
printf_log(LOG_NONE, "PltResolver: Warning, Symbol %s(ver %d: %s%s%s) found, but Jump Slot Offset is NULL \n", symname, version, symname, vername?"@":"", vername?vername:"");
printf_log(LOG_NONE, "PltResolver: Warning, Symbol %s(%sver %d: %s%s%s) found, but Jump Slot Offset is NULL \n", symname, veropt?"opt":"", version, symname, vername?"@":"", vername?vername:"");
}
}

View File

@ -3,8 +3,6 @@
typedef struct library_s library_t;
typedef struct needed_libs_s needed_libs_t;
typedef struct kh_mapsymbols_s kh_mapsymbols_t;
typedef struct kh_defaultversion_s kh_defaultversion_t;
typedef struct cleanup_s cleanup_t;
#include <elf.h>
@ -48,6 +46,8 @@ typedef struct elfheader_s {
int szVerDef;
int e_type;
uint32_t flags;
uintptr_t hash;
uintptr_t gnu_hash;
intptr_t delta; // should be 0
void* image; // base of the elf image
@ -117,11 +117,6 @@ typedef struct elfheader_s {
int clean_sz;
int clean_cap;
kh_mapsymbols_t *mapsymbols;
kh_mapsymbols_t *weaksymbols;
kh_mapsymbols_t *localsymbols;
kh_defaultversion_t *globaldefver; // the global default version for symbols (the XXX@@vvvv of symbols)
kh_defaultversion_t *weakdefver; // the weak default version for symbols (the XXX@@vvvv of symbols)
} elfheader_t;
#define R_X86_64_NONE 0 /* No reloc */
@ -171,4 +166,19 @@ typedef struct elfheader_s {
elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec);
const char* BindSym(int bind);
Elf64_Half GetSymbolVersionFlag(elfheader_t* h, int index);
uint32_t old_elf_hash(const char* name);
Elf64_Sym* old_elf_lookup(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt);
void old_elf_hash_dump(elfheader_t* h);
uint32_t new_elf_hash(const char *name);
Elf64_Sym* new_elf_lookup(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt);
void new_elf_hash_dump(elfheader_t* h);
Elf64_Sym* ElfLookup(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt);
Elf64_Sym* ElfSymTabLookup(elfheader_t* h, const char* symname);
Elf64_Sym* ElfDynSymLookup(elfheader_t* h, const char* symname);
#endif //__ELFLOADER_PRIVATE_H_

View File

@ -13,6 +13,9 @@
#ifndef PN_XNUM
#define PN_XNUM (0xffff)
#endif
#ifndef DT_GNU_HASH
#define DT_GNU_HASH 0x6ffffef5
#endif
int LoadSH(FILE *f, Elf64_Shdr *s, void** SH, const char* name, uint32_t type)
{
@ -284,6 +287,14 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
h->flags = val;
printf_dump(LOG_DEBUG, "The DT_FLAGS is 0x%x\n", h->flags);
break;
case DT_HASH:
h->hash = ptr;
printf_dump(LOG_DEBUG, "The DT_HASH is at address %p\n", (void*)h->hash);
break;
case DT_GNU_HASH:
h->gnu_hash = ptr;
printf_dump(LOG_DEBUG, "The DT_GNU_HASH is at address %p\n", (void*)h->gnu_hash);
break;
}
}
if(h->rel) {
@ -374,112 +385,15 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
return h;
}
const char* GetSymbolVersion(elfheader_t* h, int version)
const char* BindSym(int bind)
{
if(version<2)
return NULL;
/*if(version==1)
return "*";*/
if(h->VerNeed) {
Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta);
while(ver) {
Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux);
for(int j=0; j<ver->vn_cnt; ++j) {
if(aux->vna_other==version)
return h->DynStr+aux->vna_name;
aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next);
}
ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
}
switch(bind) {
case STB_GLOBAL: return "STB_GLOBAL";
case STB_WEAK: return "STB_WEAK";
case STB_LOCAL: return "STB_LOCAL";
case STB_GNU_UNIQUE: return "STB_GNU_UNIQUE";
}
return GetParentSymbolVersion(h, version); // if symbol is "internal", use Def table instead
}
const char* GetParentSymbolVersion(elfheader_t* h, int index)
{
if(!h->VerDef || (index<1))
return NULL;
Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef + h->delta);
while(def) {
if(def->vd_ndx==index) {
if(def->vd_cnt<1)
return NULL;
/*if(def->vd_flags&VER_FLG_BASE)
return NULL;*/
Elf64_Verdaux *aux = (Elf64_Verdaux*)((uintptr_t)def + def->vd_aux);
return h->DynStr+aux->vda_name; // return Parent, so 1st aux
}
def = def->vd_next?((Elf64_Verdef*)((uintptr_t)def + def->vd_next)):NULL;
}
return NULL;
}
int GetVersionIndice(elfheader_t* h, const char* vername)
{
if(!vername)
return 0;
if(h->VerDef) {
Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef + h->delta);
while(def) {
Elf64_Verdaux *aux = (Elf64_Verdaux*)((uintptr_t)def + def->vd_aux);
if(!strcmp(h->DynStr+aux->vda_name, vername))
return def->vd_ndx;
def = def->vd_next?((Elf64_Verdef*)((uintptr_t)def + def->vd_next)):NULL;
}
}
return 0;
}
int GetNeededVersionCnt(elfheader_t* h, const char* libname)
{
if(!libname)
return 0;
if(h->VerNeed) {
Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta);
while(ver) {
char *filename = h->DynStr + ver->vn_file;
if(!strcmp(filename, libname))
return ver->vn_cnt;
ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
}
}
return 0;
}
const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx)
{
if(!libname)
return 0;
if(h->VerNeed) {
Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta);
while(ver) {
char *filename = h->DynStr + ver->vn_file;
Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux);
if(!strcmp(filename, libname)) {
for(int j=0; j<ver->vn_cnt; ++j) {
if(j==idx)
return h->DynStr+aux->vna_name;
aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next);
}
return NULL; // idx out of bound, return NULL...
}
ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
}
}
return NULL;
}
int GetNeededVersionForLib(elfheader_t* h, const char* libname, const char* ver)
{
if(!libname || !ver)
return 0;
int n = GetNeededVersionCnt(h, libname);
if(!n)
return 0;
for(int i=0; i<n; ++i) {
const char* vername = GetNeededVersionString(h, libname, i);
if(vername && !strcmp(ver, vername))
return 1;
}
return 0;
}
static char tmp[50];
sprintf(tmp, "??? 0x%x", bind);
return tmp;
}

View File

@ -1227,7 +1227,7 @@ const char* getAddrFunctionName(uintptr_t addr)
else if(addr==start)
sprintf(ret, "%s/%s", ElfName(elf), symbname);
else
sprintf(ret, "%s/%s + %ld", ElfName(elf), symbname, addr - start);
sprintf(ret, "%s/%s + 0x%lx", ElfName(elf), symbname, addr - start);
} else {
if(elf) {
sprintf(ret, "%s + 0x%lx", ElfName(elf), addr - (uintptr_t)GetBaseAddress(elf));

View File

@ -121,6 +121,7 @@ typedef struct box64context_s {
lib_t *local_maplib; // libs and symbols openned has local (only collection of libs, no symbols)
dic_t *versym; // dictionnary of versioned symbols
kh_mapsymbols_t *globdata; // GLOBAL_DAT relocation for COPY mapping in main elf
kh_mapsymbols_t *uniques; // symbols with STB_GNU_UNIQUE bindings
kh_threadstack_t *stacksizes; // stack sizes attributes for thread (temporary)
bridge_t *system; // other bridges

View File

@ -26,12 +26,13 @@ int CalcLoadAddr(elfheader_t* head);
int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin);
void FreeElfMemory(elfheader_t* head);
int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded);
void GrabX64CopyMainElfReloc(elfheader_t* head);
int RelocateElf(lib_t *maplib, lib_t* local_maplib, int bindnow, int deepbind, elfheader_t* head);
int RelocateElfPlt(lib_t *maplib, lib_t* local_maplib, int bindnow, int deepbind, elfheader_t* head);
void CalcStack(elfheader_t* h, uint64_t* stacksz, size_t* stackalign);
uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h);
uintptr_t GetLastByte(elfheader_t* h);
void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h);
void AddSymbols(lib_t *maplib, elfheader_t* h);
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, int deepbind, box64context_t *box64, x64emu_t* emu);
uintptr_t GetElfInit(elfheader_t* h);
uintptr_t GetElfFini(elfheader_t* h);
@ -62,17 +63,16 @@ int ElfCheckIfUseTCMallocMinimal(elfheader_t* h); // return 1 if tcmalloc is u
const char* GetSymbolVersion(elfheader_t* h, int version);
const char* GetParentSymbolVersion(elfheader_t* h, int index);
const char* VersionedName(const char* name, int ver, const char* vername);
int SameVersionedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2);
int SameVersionedSymbol(const char* name1, int ver1, const char* vername1, int veropt1, const char* name2, int ver2, const char* vername2, int veropt2);
int GetVersionIndice(elfheader_t* h, const char* vername);
int GetNeededVersionCnt(elfheader_t* h, const char* libname);
const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx);
int GetNeededVersionForLib(elfheader_t* h, const char* libname, const char* ver);
kh_mapsymbols_t* GetMapSymbols(elfheader_t* h);
kh_mapsymbols_t* GetWeakSymbols(elfheader_t* h);
kh_mapsymbols_t* GetLocalSymbols(elfheader_t* h);
kh_defaultversion_t* GetGlobalDefaultVersion(elfheader_t* h);
kh_defaultversion_t* GetWeakDefaultVersion(elfheader_t* h);
void* ElfGetLocalSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *sz, const char* symname, int* ver, const char** vername, int local, int* veropt);
void* ElfGetGlobalSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *sz, const char* symname, int* ver, const char** vername, int local, int* veropt);
void* ElfGetWeakSymbolStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *sz, const char* symname, int* ver, const char** vername, int local, int* veropt);
int ElfGetSymTabStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *end, const char* symname);
void* GetNativeSymbolUnversioned(void* lib, const char* name);

View File

@ -12,9 +12,10 @@ typedef struct x64emu_s x64emu_t;
typedef struct elfheader_s elfheader_t;
typedef struct needed_libs_s needed_libs_t;
typedef struct kh_mapoffsets_s kh_mapoffsets_t;
typedef enum symbol_type_s symbol_type_t;
typedef char* cstr_t;
lib_t *NewLibrarian(box64context_t* context, int ownlibs);
lib_t *NewLibrarian(box64context_t* context);
void FreeLibrarian(lib_t **maplib, x64emu_t* emu);
dlprivate_t *NewDLPrivate(void);
void FreeDLPrivate(dlprivate_t **lib);
@ -27,20 +28,19 @@ library_t* GetLibMapLib(lib_t* maplib, const char* name);
library_t* GetLibInternal(const char* name);
void promoteLocalLibGlobal(library_t* lib);
int isLibLocal(library_t* lib);
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername);
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername, const char* globdefver, const char* weakdefver);
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver);
int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver);
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, const char* defver);
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver);
elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername);
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername, const char* defver);
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername, int veropt);
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername, int veropt, void** elfsym);
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, int veropt, void** elfsym);
int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, int veropt, void** elfsym);
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int veropt, void** elfsym);
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, int veropt, void** elfsym);
elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername, int veropt);
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername, int veropt);
int GetSymTabStartEnd(lib_t* maplib, const char* name, uintptr_t* start, uintptr_t* end);
void MapLibRemoveLib(lib_t* maplib, library_t* lib);
void MapLibPrependLib(lib_t* maplib, library_t* lib, library_t* ref);
const char* GetMaplibDefaultVersion(lib_t *maplib, lib_t *local_maplib, int isweak, int deepbind, const char* symname);
const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint64_t* sz, const char** libname, void** base, library_t** lib);
void AddOffsetSymbol(lib_t *maplib, void* offs, const char* name);

View File

@ -21,9 +21,9 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, int deepbi
char* GetNameLib(library_t *lib);
int IsSameLib(library_t* lib, const char* path); // check if lib is same (path -> name)
int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver);
int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver);
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver);
int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym);
int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym);
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym);
char** GetNeededLibsNames(library_t* lib);
int GetNeededLibsN(library_t* lib);
library_t* GetNeededLib(library_t* lib, int idx);

View File

@ -13,22 +13,14 @@ kh_mapsymbols_t* NewMapSymbols(void);
void FreeMapSymbols(kh_mapsymbols_t** map);
// replace if already there
void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername);
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local, const char* defver);
void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername, int veropt);
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local, int veropt);
// Update addr and sz of existing symbols
void ForceUpdateSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz);
// don't add if already there
void AddUniqueSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername);
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local, const char* defver);
int GetSizedSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int ver, const char* vername, int local, const char* defver);
void AddUniqueSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername, int veropt);
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local, int veropt);
int GetSizedSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int ver, const char* vername, int local, int veropt);
const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* offs, uint32_t* sz, const char** vername);
// default version handling
KHASH_MAP_DECLARE_STR(defaultversion, const char*)
kh_defaultversion_t* NewDefaultVersion(void);
void FreeDefaultVersion(kh_defaultversion_t** def);
void AddDefaultVersion(kh_defaultversion_t* def, const char* symname, const char* vername);
const char* GetDefaultVersion(kh_defaultversion_t* def, const char* symname);
#endif //__SYMBOLS_PRIVATE_H_

View File

@ -7,7 +7,7 @@ typedef struct box64context_s box64context_t;
typedef int (*wrappedlib_init_t)(library_t * lib, box64context_t* box64); // 0 = success
typedef void (*wrappedlib_fini_t)(library_t * lib);
typedef int (*wrappedlib_get_t)(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t size, int* weak, int version, const char* vername, int local, const char* defver);
typedef int (*wrappedlib_get_t)(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym);
void setNeededLibs(library_t* lib, int n, ...);
#define SETALT0(v) #v

View File

@ -17,21 +17,21 @@
// workaround for Globals symbols
#define GLOB(A, B) \
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, NULL)) { \
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, 0, NULL)) { \
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p <- %p\n", (void*)globoffs, &A); \
memcpy((void*)globoffs, &A, sizeof(A)); \
} \
if (B && GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, B)) { \
if (B && GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, 2, B, 1, NULL)) { \
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p <- %p\n", (void*)globoffs, &A); \
memcpy((void*)globoffs, &A, sizeof(A)); \
}
#define TOGLOB(A, B) \
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, NULL)) { \
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, 0, NULL)) { \
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p -> %p\n", (void*)globoffs, &A); \
memcpy(&A, (void*)globoffs, sizeof(A)); \
} \
if (B && GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, B)) { \
if (B && GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, 2, B, 1, NULL)) { \
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p -> %p\n", (void*)globoffs, &A); \
memcpy(&A, (void*)globoffs, sizeof(A)); \
}
@ -50,7 +50,7 @@ void my_setGlobalGThreadsInit()
{
int val = 1;
uintptr_t globoffs, globend;
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, "g_threads_got_initialized", &globoffs, &globend, -1, NULL, NULL)) {
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, "g_threads_got_initialized", &globoffs, &globend, -1, NULL, 0, NULL)) {
printf_log(LOG_DEBUG, "Global g_threads_got_initialized workaround, @%p <= %d\n", (void*)globoffs, val);
memcpy((void*)globoffs, &val, sizeof(val));
}

View File

@ -17,15 +17,13 @@
KHASH_MAP_IMPL_INT(mapoffsets, cstr_t);
lib_t *NewLibrarian(box64context_t* context, int ownlibs)
lib_t *NewLibrarian(box64context_t* context)
{
lib_t *maplib = (lib_t*)box_calloc(1, sizeof(lib_t));
maplib->mapoffsets = kh_init(mapoffsets);
maplib->globaldata = NewMapSymbols();
maplib->ownlibs = ownlibs;
return maplib;
}
@ -37,11 +35,9 @@ void FreeLibrarian(lib_t **maplib, x64emu_t *emu)
library_t* owner = (*maplib)->owner;
(*maplib)->owner = NULL; // to avoid recursive free...
if((*maplib)->ownlibs && (*maplib)->libsz) {
for(int i=0; i<(*maplib)->libsz; ++i) {
printf_dump(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
DecRefCount(&(*maplib)->libraries[i], emu);
}
for(int i=0; i<(*maplib)->libsz; ++i) {
printf_dump(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
DecRefCount(&(*maplib)->libraries[i], emu);
}
box_free((*maplib)->libraries);
(*maplib)->libraries = NULL;
@ -131,12 +127,6 @@ static void MapLibAddMapLib(lib_t* dest, library_t* lib_src, lib_t* src)
library_t* lib = src->libraries[i];
if(!lib || libraryInMapLib(dest, lib)) continue;
MapLibAddLib(dest, lib);
if(lib->maplib && src!=lib->maplib && dest!=lib->maplib) {
MapLibAddMapLib(dest, lib, lib->maplib);
MapLibRemoveLib(src, lib);
if(lib->maplib)
lib->maplib = (dest==my_context->maplib)?NULL:dest;
}
}
if(lib_src == owner)
FreeLibrarian(&src, NULL);
@ -179,9 +169,13 @@ void promoteLocalLibGlobal(library_t* lib)
return;
// promote lib from local to global...
// for add the depending local libs...
if(lib->maplib) {
MapLibAddMapLib(my_context->maplib, lib, lib->maplib);
if(lib->maplib && !lib->maplib_ref) {
lib_t* maplib = lib->maplib;
lib->maplib = NULL;
MapLibAddMapLib(my_context->maplib, lib, maplib);
}
lib->maplib = NULL;
lib->maplib_ref = 0;
if(!libraryInMapLib(my_context->maplib, lib))
MapLibAddLib(my_context->maplib, lib);
MapLibRemoveMapLib(my_context->local_maplib, my_context->maplib);
@ -203,6 +197,8 @@ static int AddNeededLib_add(lib_t** maplib, int local, needed_libs_t* needed, in
if(lib) {
IncRefCount(lib, emu); // increment cntref
needed->libs[n] = lib;
if(local && *maplib)
MapLibAddLib(*maplib, lib);
printf_dump(LOG_DEBUG, "Already present in maplib => success\n");
return 0;
}
@ -215,10 +211,7 @@ static int AddNeededLib_add(lib_t** maplib, int local, needed_libs_t* needed, in
if(local) {
// add lib to maplib...
if(*maplib) {
if(!libraryInMapLib(*maplib, lib))
MapLibPrependLib(*maplib, lib, NULL); // todo: Also insert libs needed by lib, after lib? But current lib->maplib is probably not the solution
if((*maplib)->ownlibs)
MapLibRemoveMapLib(my_context->local_maplib, *maplib);
MapLibAddLib(*maplib, lib);
}
} else {
// promote lib from local to global...
@ -239,7 +232,7 @@ static int AddNeededLib_add(lib_t** maplib, int local, needed_libs_t* needed, in
if(*maplib) {
MapLibAddLib(*maplib, lib);
} else {
lib->maplib = NewLibrarian(box64, 0);
lib->maplib = NewLibrarian(box64);
MapLibAddLib(lib->maplib, lib);
}
} else {
@ -249,6 +242,11 @@ static int AddNeededLib_add(lib_t** maplib, int local, needed_libs_t* needed, in
if(!*maplib)
*maplib = (local)?lib->maplib:my_context->maplib;
if(local && !lib->maplib) {
lib->maplib = *maplib;
lib->maplib_ref = 1;
}
if(AddSymbolsLibrary(*maplib, lib, emu)) { // also add needed libs
printf_dump(LOG_DEBUG, "Failure to Add lib => fail\n");
return 1;
@ -266,6 +264,7 @@ static int AddNeededLib_add(lib_t** maplib, int local, needed_libs_t* needed, in
lm->l_name = lib->name;
lm->l_ld = GetDynamicSection(lib->e.elf);
}
IncRefCount(lib, emu);
return 0;
}
@ -283,29 +282,10 @@ int AddNeededLib_init(lib_t* maplib, int local, int bindnow, int deepbind, libra
} else {
// it's an emulated lib,
// load dependancies and launch init sequence
if(LoadNeededLibs(mainelf, maplib, 0, bindnow, deepbind, box64, emu)) {
if(LoadNeededLibs(mainelf, maplib, local, bindnow, deepbind, box64, emu)) {
printf_dump(LOG_DEBUG, "Failure to Add dependant lib => fail\n");
return 1;
}
// some special case, where dependancies may not be correct
if(!strcmp(GetNameLib(lib), "libCgGL.so")) {
char* names[] = {"libGL.so.1"}; // TODO: it will never be uninit...
library_t* libs[] = { NULL };
needed_libs_t tmp = {0};
tmp.size = tmp.cap = 1;
tmp.names = names;
tmp.libs = libs;
AddNeededLib(maplib, 0, 0, deepbind, &tmp, verneeded, box64, emu);
}
if(!strcmp(GetNameLib(lib), "libmss.so.6")) {
char* names[] = {"libSDL-1.2.so.0", "libdl.so.2"}; // TODO: they will never be uninit...
library_t* libs[] = { NULL, NULL };
needed_libs_t tmp = {0};
tmp.size = tmp.cap = 2;
tmp.names = names;
tmp.libs = libs;
AddNeededLib(maplib, 0, 0, deepbind, &tmp, verneeded, box64, emu);
}
// finalize the lib
if(FinalizeLibrary(lib, local?maplib:NULL, bindnow, deepbind, emu)) {
@ -347,9 +327,11 @@ int AddNeededLib(lib_t* maplib, int local, int bindnow, int deepbind, needed_lib
if(ret) {
return ret;
}
// add dependant libs and init them
for (int i=0; i<needed->size; ++i)
if(AddNeededLib_init(maplib, local, bindnow, deepbind, needed->libs[i], verneeded, box64, emu)) {
int n = needed->size;
for (int i=0; i<n; ++i)
if(AddNeededLib_init(maplib, local, bindnow, deepbind, needed->libs[n-i-1], verneeded, box64, emu)) {
printf_log(LOG_INFO, "Error initializing needed lib %s\n", needed->names[i]);
if(!allow_missing_libs) ret = 1;
}
@ -383,12 +365,10 @@ library_t* GetLibInternal(const char* name)
}
EXPORTDYN
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername)
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername, int veropt)
{
uintptr_t start = 0, end = 0;
const char *globdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 0, 0, name);
const char *weakdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 1, 0, name);
if(GetGlobalSymbolStartEnd(maplib, name, &start, &end, (void*)1, version, vername, globdefver, weakdefver))
if(GetGlobalSymbolStartEnd(maplib, name, &start, &end, (void*)1, version, vername, veropt, NULL))
return start;
return 0;
}
@ -414,220 +394,99 @@ static void CheckNeededLibs(needed_libs_t* needed)
}
}
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername, const char* globdefver, const char* weakdefver)
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername, int veropt, void** elfsym)
{
assert(self); // need self for this one
//search for the self, to start "next"
int go = -1;
int weak = 0;
for(int i=0; i<maplib->libsz && (go==-1); ++i) {
if(GetElfIndex(maplib->libraries[i])!=-1 && (GetElf(maplib->libraries[i])==self))
go = i+1;
}
if(go<0)
go = 0; // not found...
if(maplib)
for(int i=go; i<maplib->libsz; ++i) {
if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self))
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 0, globdefver))
if(*start)
return 1;
}
if(maplib)
for(int i=go; i<maplib->libsz; ++i)
if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self))
GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 0, weakdefver);
// loop done, weak symbol found
if(weak && *start)
return 1;
// if self defined, give it another chance with self...
if(self) {
if(my_context->elfs[0]!=self) {
if(GetSizedSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, size, version, vername, 1, globdefver))
if(*start)
return 1;
if(GetSizedSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, size, version, vername, 1, weakdefver))
if(*start)
weak = 1;
}
for(int i=0; i<go; ++i) {
if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self))
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, globdefver))
if(*start)
return 1;
}
if(maplib)
for(int i=0; i<go; ++i) {
if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self))
GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, weakdefver);
}
if(weak && *start)
return 1;
}
// nope, not found
return 0;
}
static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver)
{
int weak = 0;
size_t size = 0;
void* sym;
// search in needed libs from preloaded first, in order
if(my_context->preload)
for(int i=0; i<my_context->preload->size; ++i)
if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->preload->libs[i]), globdefver))
if(*start) {
return 1;
}
if(maplib==my_context->maplib) {
// search non-weak symbol, from older to newer (first GLOBAL object wins, starting with self)
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, globdefver))
if(*start) {
if(self!=GetElf(my_context->preload->libs[i]) && GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, &version, &vername, 0, &veropt, elfsym)) {
return 1;
}
// This kind-of create a map to search lib only 1 time, and in order of needed...
if(my_context->neededlibs)
CheckNeededLibs(my_context->neededlibs);
// search in needed libs from neededlibs first, in order
if(my_context->neededlibs)
for(int i=0; i<my_context->neededlibs->size; ++i)
if(GetLibGlobalSymbolStartEnd(my_context->neededlibs->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs->libs[i]), globdefver))
if(*start) {
return 1;
}
if(maplib==my_context->maplib) {
// search non-weak symbol
if(self!=my_context->elfs[0] && (sym = ElfGetGlobalSymbolStartEnd(my_context->elfs[0], start, end, name, &version, &vername, 0, &veropt))) {
if(elfsym) *elfsym = sym;
return 1;
}
}
// search in global symbols
if(maplib) {
if((maplib==my_context->maplib) && self && self!=my_context->elfs[0] && self!=(void*)1)
if(GetSymbolStartEnd(GetMapSymbols(self), name, start, end, version, vername, 1, globdefver))
if(*start) {
return 1;
}
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), globdefver))
if(*start) {
return 1;
}
if(self!=GetElf(maplib->libraries[i]) && GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, &version, &vername, 0, &veropt, elfsym))
return 1;
}
}
// check with default version...
int ok = 0;
// GetSymbolStartEnd should not change start/end if symbol is not found
if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, weakdefver))
if(*start) {
ok = 1;
}
// search in needed libs from neededlibs first, in order
if(my_context->neededlibs)
for(int i=0; i<my_context->neededlibs->size; ++i)
if(GetLibWeakSymbolStartEnd(my_context->neededlibs->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs->libs[i]), weakdefver))
if(*start) {
return 1;
}
if(self!=my_context->elfs[0] && (sym = ElfGetWeakSymbolStartEnd(my_context->elfs[0], start, end, name, &version, &vername, 0, &veropt))) {
if(elfsym) *elfsym = sym;
weak = 1;
}
if(maplib)
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), weakdefver))
if(*start) {
ok = 1;
}
}
// nope, not found
return (ok && *start)?1:0;
}
void** my_GetGTKDisplay();
void** my_GetGthreadsGotInitialized();
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver)
{
if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end, self, version, vername, globdefver, weakdefver)) {
if(start && end && *end==*start) { // object is of 0 sized, try to see an "_END" object of null size
uintptr_t start2, end2;
char* buff = (char*)malloc(strlen(name) + strlen("_END") + 1);
strcpy(buff, name);
strcat(buff, "_END");
if(GetGlobalSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, version, vername, globdefver, weakdefver)) {
if(end2>*end && start2==end2)
*end = end2;
}
box_free(buff);
if(self!=GetElf(maplib->libraries[i]) && GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, &version, &vername, 0, &veropt, elfsym)) {
weak = 1;
}
return 1;
}
// some special case symbol, defined inside box64 itself
if(!strcmp(name, "gdk_display")) {
*start = (uintptr_t)my_GetGTKDisplay();
*end = *start+sizeof(void*);
printf_log(LOG_INFO, "Using global gdk_display for gdk-x11 (%p:%p)\n", start, *(void**)start);
return 1;
}
if(!strcmp(name, "g_threads_got_initialized")) {
*start = (uintptr_t)my_GetGthreadsGotInitialized();
*end = *start+sizeof(int);
printf_log(LOG_INFO, "Using global g_threads_got_initialized for gthread2 (%p:%p)\n", start, *(void**)start);
return 1;
}
// not found...
return 0;
}
static int GetGlobalWeakSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver)
// nope, not found
return weak;
}
static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int* version, const char** vername, int* veropt, void** elfsym)
{
int weak = 0;
size_t size = 0;
void* sym;
// search in needed libs from preloaded first, in order
if(my_context->preload)
for(int i=0; i<my_context->preload->size; ++i)
if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->preload->libs[i]), globdefver))
if(*start)
return 1;
// search non-weak symbol, from older to newer (first GLOBAL object wins)
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, globdefver))
if(*start)
return 1;
// This kind-of create a map to search lib only 1 time, and in order of needed...
if(my_context->neededlibs)
CheckNeededLibs(my_context->neededlibs);
// search in needed libs from neededlibs first, in order
if(my_context->neededlibs)
for(int i=0; i<my_context->neededlibs->size; ++i)
if(GetLibGlobalSymbolStartEnd(my_context->neededlibs->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs->libs[i]), globdefver))
if(*start)
return 1;
// search in global symbols
if(maplib)
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), globdefver))
if(*start)
if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->preload->libs[i]), veropt, elfsym)) {
return 1;
}
if(maplib==my_context->maplib) {
// search non-weak symbol, from older to newer (first GLOBAL object wins, starting with self)
if((sym = ElfGetGlobalSymbolStartEnd(my_context->elfs[0], start, end, name, version, vername, (my_context->elfs[0]==self || !self)?1:0, veropt))) {
if(elfsym) *elfsym = sym;
return 1;
}
}
// search in global symbols
if(maplib) {
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), veropt, elfsym))
return 1;
}
}
// check with default version...
int ok = 0;
// GetSymbolStartEnd should not change start/end if symbol is not found
if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, weakdefver))
if(*start)
ok = 1;
if((sym = ElfGetWeakSymbolStartEnd(my_context->elfs[0], start, end, name, version, vername, (my_context->elfs[0]==self || !self)?1:0, veropt))) {
if(elfsym) *elfsym = sym;
weak = 1;
}
if(maplib)
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), weakdefver))
if(*start)
ok = 1;
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), veropt, elfsym)) {
weak = 1;
}
}
// nope, not found
return (ok && *start)?1:0;
return weak;
}
int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver)
void** my_GetGTKDisplay();
void** my_GetGthreadsGotInitialized();
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, int veropt, void** elfsym)
{
if(GetGlobalWeakSymbolStartEnd_internal(maplib, name, start, end, self, version, vername, globdefver, weakdefver)) {
if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end, self, &version, &vername, &veropt, elfsym)) {
if(start && end && *end==*start) { // object is of 0 sized, try to see an "_END" object of null size
uintptr_t start2, end2;
char* buff = (char*)malloc(strlen(name) + strlen("_END") + 1);
strcpy(buff, name);
strcat(buff, "_END");
if(GetGlobalWeakSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, version, vername, globdefver, weakdefver)) {
if(GetGlobalSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, &version, &vername, &veropt, elfsym)) {
if(end2>*end && start2==end2)
*end = end2;
}
@ -652,31 +511,80 @@ int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* star
return 0;
}
static const char* internal_GetMaplibDefaultVersion(lib_t* maplib, int isweak, const char* symname)
static int GetGlobalWeakSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int* version, const char** vername, int* veropt, void** elfsym)
{
const char* ret = NULL;
for(int i=0; maplib && i<maplib->libsz; ++i) {
elfheader_t *h = GetElf(maplib->libraries[i]);
if(h)
ret = GetDefaultVersion(isweak?GetWeakDefaultVersion(h):GetGlobalDefaultVersion(h), symname);
if(ret)
return ret;
int weak = 0;
size_t size = 0;
void* sym;
// search in needed libs from preloaded first, in order
if(my_context->preload)
for(int i=0; i<my_context->preload->size; ++i)
if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->preload->libs[i]), veropt, elfsym))
return 1;
// search non-weak symbol, from older to newer (first GLOBAL object wins)
if((sym = ElfGetGlobalSymbolStartEnd(my_context->elfs[0], start, end, name, version, vername, (my_context->elfs[0]==self || !self)?1:0, veropt))) {
if(elfsym) *elfsym = sym;
return 1;
}
return ret;
}
const char* GetMaplibDefaultVersion(lib_t *maplib, lib_t* local_maplib, int isweak, int deepbind, const char* symname)
{
const char* ret = GetDefaultVersion(isweak?GetWeakDefaultVersion(my_context->elfs[0]):GetGlobalDefaultVersion(my_context->elfs[0]), symname);
if(ret)
return ret;
ret = internal_GetMaplibDefaultVersion(deepbind?local_maplib:maplib, isweak, symname);
if(ret)
return ret;
ret = internal_GetMaplibDefaultVersion(deepbind?maplib:local_maplib, isweak, symname);
return ret;
if(maplib)
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), veropt, elfsym))
return 1;
}
// check with default version...
int ok = 0;
// GetSymbolStartEnd should not change start/end if symbol is not found
if(( sym = ElfGetWeakSymbolStartEnd(my_context->elfs[0], start, end, name, version, vername, (my_context->elfs[0]==self || !self)?1:0, veropt))) {
if(elfsym) *elfsym = sym;
ok = 1;
}
if(maplib)
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), veropt, elfsym))
ok = 1;
}
// nope, not found
return ok;
}
elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername)
int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, int veropt, void** elfsym)
{
if(GetGlobalWeakSymbolStartEnd_internal(maplib, name, start, end, self, &version, &vername, &veropt, elfsym)) {
if(start && end && *end==*start) { // object is of 0 sized, try to see an "_END" object of null size
uintptr_t start2, end2;
char* buff = (char*)malloc(strlen(name) + strlen("_END") + 1);
strcpy(buff, name);
strcat(buff, "_END");
if(GetGlobalWeakSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, &version, &vername, &veropt, elfsym)) {
if(end2>*end && start2==end2)
*end = end2;
}
box_free(buff);
}
return 1;
}
// some special case symbol, defined inside box64 itself
if(!strcmp(name, "gdk_display")) {
*start = (uintptr_t)my_GetGTKDisplay();
*end = *start+sizeof(void*);
if(elfsym) *elfsym = NULL;
printf_log(LOG_INFO, "Using global gdk_display for gdk-x11 (%p:%p)\n", start, *(void**)start);
return 1;
}
if(!strcmp(name, "g_threads_got_initialized")) {
*start = (uintptr_t)my_GetGthreadsGotInitialized();
*end = *start+sizeof(int);
if(elfsym) *elfsym = NULL;
printf_log(LOG_INFO, "Using global g_threads_got_initialized for gthread2 (%p:%p)\n", start, *(void**)start);
return 1;
}
// not found...
return 0;
}
elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername, int veropt)
{
uintptr_t start = 0;
uintptr_t end = 0;
@ -684,12 +592,10 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co
int weak = 0;
elfheader_t* ret = NULL;
// check with default version...
const char* defver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 0, 0, name);
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, &start, &end, version, vername, 1, defver))
if(ElfGetGlobalSymbolStartEnd(my_context->elfs[0], &start, &end, name, &version, &vername, 1, &veropt))
return my_context->elfs[0];
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1, defver)) {
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, &version, &vername, 1, &veropt, NULL)) {
elfheader_t* h = GetElf(maplib->libraries[i]);
if(!h) {
printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i]));
@ -702,11 +608,10 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co
}
}
defver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 1, 0, name);
if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, &start, &end, version, vername, 1, defver))
if(ElfGetWeakSymbolStartEnd(my_context->elfs[0], &start, &end, name, &version, &vername, 1, &veropt))
ret = my_context->elfs[0];
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1, defver)) {
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, &version, &vername, 1, &veropt, NULL)) {
elfheader_t* h = GetElf(maplib->libraries[i]);
if(!h) {
printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i]));
@ -722,27 +627,29 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co
return ret;
}
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, const char* defver)
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int veropt, void** elfsym)
{
int weak = 0;
size_t size = 0;
void* sym;
// check global GLOB_DAT kind of symbols
if(GetSymbolStartEnd(GetGlobalData(maplib), name, start, end, version, vername, 1, defver))
if(*start || *end)
return 1;
if(GetSymbolStartEnd(GetGlobalData(maplib), name, start, end, version, vername, 1, veropt)) {
if(elfsym) *elfsym = NULL;
return 1;
}
// check with default version...
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, 1, defver))
if(*start || *end)
return 1;
if((sym = ElfGetGlobalSymbolStartEnd(my_context->elfs[0], start, end, name, &version, &vername, 1, &veropt))) {
if(elfsym) *elfsym = sym;
return 1;
}
for(int i=0; i<maplib->libsz; ++i)
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, defver))
if(*start || *end)
return 1;
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, &version, &vername, 1, &veropt, elfsym))
return 1;
// nope, not found
return 0;
}
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername, const char* defver)
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername, int veropt)
{
uintptr_t start, end;
size_t size = 0;
@ -750,33 +657,31 @@ int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, c
// check with default version...
for(int i=0; i<maplib->libsz; ++i)
if(GetElfIndex(maplib->libraries[i])==-1)
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1, defver))
if(start || end)
return 1;
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, &version, &vername, 1, &veropt, NULL))
return 1;
// nope, not found
return 0;
}
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver)
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, int veropt, void** elfsym)
{
// check with default version...
int weak;
size_t size = 0;
const char* defver = globdefver?globdefver:weakdefver;
void* sym;
if(my_context->elfs[0]==self || !self) {
if(GetSymbolStartEnd(GetLocalSymbols(my_context->elfs[0]), name, start, end, version, vername, 1, defver))
if(*start || *end)
return 1;
if((sym = ElfGetLocalSymbolStartEnd(my_context->elfs[0], start, end, name, &version, &vername, 1, &veropt))) {
if(elfsym) *elfsym = sym;
return 1;
}
if(self)
return 0;
}
for(int i=0; i<maplib->libsz; ++i) {
if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || GetElf(maplib->libraries[i])==self)) {
if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, defver))
if(*start || *end)
return 1;
if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, &version, &vername, 1, &veropt, elfsym))
return 1;
if(self)
return 0;
}
@ -785,6 +690,18 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui
return 0;
}
int GetSymTabStartEnd(lib_t* maplib, const char* name, uintptr_t* start, uintptr_t* end)
{
if(!maplib)
return 0;
for(int i=0; i<maplib->libsz; ++i) {
elfheader_t* h = GetElf(maplib->libraries[i]);
if(h && ElfGetSymTabStartEnd(h, start, end, name))
return 1;
}
return 0;
}
const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint64_t* sz, const char** libname, void** base, library_t** lib)
{

View File

@ -18,7 +18,6 @@ typedef struct lib_s {
library_t **libraries;
int libsz;
int libcap;
int ownlibs;
library_t *owner; // in case that maplib is owned by a lib
} lib_t;

View File

@ -43,14 +43,6 @@ wrappedlib_t wrappedlibs[] = {
};
#undef GO
typedef struct bridged_s {
char* name;
uintptr_t start;
uintptr_t end;
} bridged_t;
KHASH_MAP_INIT_STR(bridgemap, bridged_t)
KHASH_MAP_IMPL_STR(symbolmap, symbol1_t)
KHASH_MAP_IMPL_STR(symbol2map, symbol2_t)
KHASH_MAP_IMPL_STR(datamap, uint64_t)
@ -123,13 +115,13 @@ void DummyLib_Fini(library_t* lib)
{
}
int WrappedLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver)
int WrappedLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym)
{
// ignoring asked size on wrapped libs
uintptr_t addr = 0;
uintptr_t size = 0;
int wk = 0;
if (!getSymbolInMaps(lib, name, 0, &addr, &size, &wk, version, vername, local)) {
if (!getSymbolInMaps(lib, name, 0, &addr, &size, &wk, *version, *vername, local, *veropt)) {
return 0;
}
if(!addr && !size)
@ -139,34 +131,37 @@ int WrappedLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uintpt
*offs = addr;
*sz = size;
*weak = wk;
if(elfsym) *elfsym = NULL;
return 1;
}
int EmuLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int*weak, int version, const char* vername, int local, const char* defver)
int EmuLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym)
{
// symbols...
uintptr_t start, end;
// weak symbols...
if(GetSizedSymbolStartEnd(GetWeakSymbols(lib->e.elf), name, &start, &end, asked_size, version, vername, local, defver))
void* sym;
if((sym = ElfGetWeakSymbolStartEnd(lib->e.elf, &start, &end, name, version, vername, local, veropt)))
{
*offs = start;
*sz = end-start;
*weak = 1;
if(elfsym) *elfsym = sym;
return 1;
}
return 0;
}
int DummyLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver)
int DummyLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym)
{
return 0;
}
int WrappedLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver)
int WrappedLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym)
{
// ignoring asked size on wrapped libs
uintptr_t addr = 0;
uintptr_t size = 0;
int wk = 0;
if (!getSymbolInMaps(lib, name, 1, &addr, &size, &wk, version, vername, local)) {
if (!getSymbolInMaps(lib, name, 1, &addr, &size, &wk, *version, *vername, local, *veropt)) {
return 0;
}
if(!addr && !size)
@ -176,44 +171,49 @@ int WrappedLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uint
*offs = addr;
*sz = size;
*weak = 0;
if(elfsym) *elfsym = NULL;
return 1;
}
int EmuLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver)
int EmuLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym)
{
uintptr_t start, end;
if(GetSizedSymbolStartEnd(GetMapSymbols(lib->e.elf), name, &start, &end, asked_size, version, vername, local, defver))
void* sym;
if((sym = ElfGetGlobalSymbolStartEnd(lib->e.elf, &start, &end, name, version, vername, local, veropt)))
{
*offs = start;
*sz = end-start;
*weak = 0;
if(elfsym) *elfsym = sym;
return 1;
}
return 0;
}
int DummyLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver)
int DummyLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym)
{
return 0;
}
int EmuLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver)
int EmuLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym)
{
// ignoring asked size on wrapped libs
uintptr_t start, end;
if(GetSymbolStartEnd(GetLocalSymbols(lib->e.elf), name, &start, &end, version, vername, local, defver))
void* sym;
if((sym = ElfGetLocalSymbolStartEnd(lib->e.elf, &start, &end, name, version, vername, local, veropt)))
{
*offs = start;
*sz = end-start;
*weak = 0;
if(elfsym) *elfsym = sym;
return 1;
}
return 0;
}
int WrappedLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver)
int WrappedLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym)
{
(void)lib; (void)name; (void)offs; (void)sz; (void)version; (void)vername; (void)local;
return 0;
}
int DummyLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver)
int DummyLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym)
{
(void)lib; (void)name; (void)offs; (void)sz; (void)version; (void)vername; (void)local;
return 0;
@ -483,9 +483,6 @@ library_t *NewLibrary(const char* path, box64context_t* context, elfheader_t* ve
//box_free(lib);
return NULL;
}
lib->gbridgemap = kh_init(bridgemap);
lib->wbridgemap = kh_init(bridgemap);
lib->lbridgemap = kh_init(bridgemap);
return lib;
}
@ -496,7 +493,7 @@ int AddSymbolsLibrary(lib_t *maplib, library_t* lib, x64emu_t* emu)
if(lib->type==LIB_EMULATED) {
elfheader_t *elf_header = lib->e.elf;
// add symbols
AddSymbols(maplib, GetMapSymbols(lib->e.elf), GetWeakSymbols(lib->e.elf), GetLocalSymbols(lib->e.elf), elf_header);
AddSymbols(maplib, elf_header);
}
return 0;
}
@ -522,12 +519,14 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, int deepbi
#ifdef HAVE_TRACE
if(trace_func) {
int weak;
if (GetGlobalSymbolStartEnd(local_maplib, trace_func, &trace_start, &trace_end, elf_header, -1, NULL, NULL, NULL)) {
int ver = -1, veropt = 0;
const char* vername = NULL;
if (GetGlobalSymbolStartEnd(local_maplib, trace_func, &trace_start, &trace_end, elf_header, ver, vername, veropt, NULL)) {
SetTraceEmu(trace_start, trace_end);
printf_dump(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end);
box_free(trace_func);
trace_func = NULL;
} else if(GetLibLocalSymbolStartEnd(lib, trace_func, &trace_start, &trace_end, 0, &weak, -1, NULL, 0, NULL)) {
} else if(GetLibLocalSymbolStartEnd(lib, trace_func, &trace_start, &trace_end, 0, &weak, &ver, &vername, 0, &veropt, NULL)) {
SetTraceEmu(trace_start, trace_end);
printf_dump(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end);
box_free(trace_func);
@ -565,42 +564,33 @@ void Free1Library(library_t **the_lib, x64emu_t* emu)
MapLibRemoveLib(my_context->local_maplib, lib);
}
// free elf is relevant
if(lib->type==LIB_EMULATED) {
int lib_type = lib->type;
// Handle needed for cleaning
needed_libs_t* needed = (lib_type==LIB_EMULATED && lib->e.elf)?lib->e.elf->needed:((lib_type==LIB_WRAPPED)?lib->w.needed:NULL);
// handle needed libs now
if(needed)
for(int i=0; i<needed->size; ++i)
DecRefCount(&needed->libs[i], emu);
// free elf
if(lib_type==LIB_EMULATED) {
FreeElfHeader(&lib->e.elf);
}
// No "Fini" logic here, only memory handling
if(lib->maplib)
FreeLibrarian(&lib->maplib, emu);
if(lib->type!=LIB_UNNKNOW && lib->fini) {
if(lib->maplib && !lib->maplib_ref) {
lib_t* maplib = lib->maplib;
lib->maplib = NULL;
FreeLibrarian(&maplib, emu);
}
lib->maplib = NULL;
lib->maplib_ref = 0;
if(lib_type!=LIB_UNNKNOW && lib->fini) {
lib->fini(lib);
}
box_free(lib->name);
box_free(lib->path);
if(lib->gbridgemap) {
bridged_t *br;
kh_foreach_value_ref(lib->gbridgemap, br,
box_free(br->name);
);
kh_destroy(bridgemap, lib->gbridgemap);
}
if(lib->wbridgemap) {
bridged_t *br;
kh_foreach_value_ref(lib->wbridgemap, br,
box_free(br->name);
);
kh_destroy(bridgemap, lib->wbridgemap);
}
if(lib->lbridgemap) {
bridged_t *br;
kh_foreach_value_ref(lib->lbridgemap, br,
box_free(br->name);
);
kh_destroy(bridgemap, lib->lbridgemap);
}
if(lib->type == LIB_WRAPPED) {
if(lib_type == LIB_WRAPPED) {
if(lib->w.symbolmap)
kh_destroy(symbolmap, lib->w.symbolmap);
if(lib->w.wsymbolmap)
@ -671,81 +661,37 @@ int IsSameLib(library_t* lib, const char* path)
box_free(name);
return ret;
}
int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver)
int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym)
{
if(!name[0] || !lib || (lib->type==LIB_UNNKNOW))
return 0;
khint_t k;
kh_bridgemap_t *map = local?lib->lbridgemap:((*weak)?lib->wbridgemap:lib->gbridgemap);
// check first if already in the map
k = kh_get(bridgemap, map, VersionedName(name, version, vername));
if(k!=kh_end(map)) {
*start = kh_value(map, k).start;
*end = kh_value(map, k).end;
return 1;
}
// get a new symbol
if(lib->getweak(lib, name, start, end, size, weak, version, vername, local, defver)) {
if(lib->getweak(lib, name, start, end, size, weak, version, vername, local, veropt, elfsym)) {
*end += *start; // lib->get(...) gives size, not end
char* symbol = box_strdup(VersionedName(name, version, vername));
int ret;
k = kh_put(bridgemap, map, symbol, &ret);
kh_value(map, k).name = symbol;
kh_value(map, k).start = *start;
kh_value(map, k).end = *end;
return 1;
}
// nope
return 0;
}
int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver)
int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym)
{
if(!name[0] || !lib || (lib->type==LIB_UNNKNOW))
return 0;
khint_t k;
kh_bridgemap_t *map = local?lib->lbridgemap:((*weak)?lib->wbridgemap:lib->gbridgemap);
// check if already in the map
k = kh_get(bridgemap, map, VersionedName(name, version, vername));
if(k!=kh_end(map)) {
*start = kh_value(map, k).start;
*end = kh_value(map, k).end;
return 1;
}
// get a new symbol
if(lib->getglobal(lib, name, start, end, size, weak, version, vername, local, defver)) {
if(lib->getglobal(lib, name, start, end, size, weak, version, vername, local, veropt, elfsym)) {
*end += *start; // lib->get(...) gives size, not end
char* symbol = box_strdup(VersionedName(name, version, vername));
int ret;
k = kh_put(bridgemap, map, symbol, &ret);
kh_value(map, k).name = symbol;
kh_value(map, k).start = *start;
kh_value(map, k).end = *end;
return 1;
}
// nope
return 0;
}
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver)
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int* version, const char** vername, int local, int* veropt, void** elfsym)
{
if(!name[0] || !lib || (lib->type==LIB_UNNKNOW))
return 0;
khint_t k;
// check first if already in the map
k = kh_get(bridgemap, lib->lbridgemap, VersionedName(name, version, vername));
if(k!=kh_end(lib->lbridgemap)) {
*start = kh_value(lib->lbridgemap, k).start;
*end = kh_value(lib->lbridgemap, k).end;
return 1;
}
// get a new symbol
if(lib->getlocal(lib, name, start, end, size, weak, version, vername, local, defver)) {
if(lib->getlocal(lib, name, start, end, size, weak, version, vername, local, veropt, elfsym)) {
*end += *start; // lib->get(...) gives size, not end
char* symbol = box_strdup(VersionedName(name, version, vername));
int ret;
k = kh_put(bridgemap, lib->lbridgemap, symbol, &ret);
kh_value(lib->lbridgemap, k).name = symbol;
kh_value(lib->lbridgemap, k).start = *start;
kh_value(lib->lbridgemap, k).end = *end;
return 1;
}
// nope
@ -981,7 +927,7 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui
return 0;
}
int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size, int* weak, int version, const char* vername, int local)
int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size, int* weak, int version, const char* vername, int local, int veropt)
{
if(version==-2) // don't send global native symbol for a version==-2 search
return 0;
@ -1191,18 +1137,11 @@ void IncRefCount(library_t* lib, x64emu_t* emu)
if(lib->w.refcnt==LIB_MAXCNT)
return;
++lib->w.refcnt;
if(lib->w.needed)
for(int i=0; i<lib->w.needed->size; ++i) {
IncRefCount(lib->w.needed->libs[i], emu);
}
break;
case LIB_EMULATED:
if(lib->e.elf->refcnt==LIB_MAXCNT)
return;
++lib->e.elf->refcnt;
if(lib->e.elf->needed)
for(int i=0; i<lib->e.elf->needed->size; ++i) // some libs may not be loaded yet
IncRefCount(lib->e.elf->needed->libs[i], emu);
}
}
@ -1215,39 +1154,29 @@ int DecRefCount(library_t** lib, x64emu_t* emu)
return 0;
}
int ret = 1;
needed_libs_t* needed = NULL;
int freed = 0;
switch ((*lib)->type) {
case LIB_WRAPPED:
if((*lib)->w.refcnt==LIB_MAXCNT)
return ret;
needed = (*lib)->w.needed;
ret=--(*lib)->w.refcnt;
if(!ret) {
needed = copy_neededlib(needed);
freed=1;
Free1Library(lib, emu);
}
break;
case LIB_EMULATED:
if((*lib)->e.elf->refcnt==LIB_MAXCNT)
return ret;
needed = (*lib)->e.elf->needed;
ret=--(*lib)->e.elf->refcnt;
if(!(*lib)->e.elf)
ret = 0;
else {
if((*lib)->e.elf->refcnt==LIB_MAXCNT)
return ret;
ret=--(*lib)->e.elf->refcnt;
}
if(!ret) {
needed = copy_neededlib(needed);
freed=1;
removeLinkMapLib(*lib);
FiniLibrary(*lib, emu);
Free1Library(lib, emu);
}
break;
}
if(needed)
for(int i=0; i<needed->size; ++i)
DecRefCount(&needed->libs[i], emu);
if(freed)
free_neededlib(needed);
return ret;
}

View File

@ -11,7 +11,6 @@
typedef struct lib_s lib_t;
typedef struct bridge_s bridge_t;
typedef struct elfheader_s elfheader_t;
typedef struct kh_bridgemap_s kh_bridgemap_t;
typedef struct kh_mapsymbols_s kh_mapsymbols_t;
typedef struct x64emu_s x64emu_t;
@ -80,9 +79,7 @@ typedef struct library_s {
elib_t e;
}; // private lib data
lib_t *maplib; // local maplib, for dlopen'd library with LOCAL binding (most of the dlopen)
kh_bridgemap_t *gbridgemap; // global symbol bridgemap
kh_bridgemap_t *wbridgemap; // weak symbol bridgemap
kh_bridgemap_t *lbridgemap; // local symbol bridgemap
int maplib_ref; // ref to maplib (not owned)
size_t dlopen; // idx to the dlopen idx (or 0 if not dlopen)
} library_t;
@ -104,7 +101,7 @@ typedef struct map_onedata_s {
int weak;
} map_onedata_t;
int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size, int *weak, int version, const char* vername, int local); // Add bridges to functions
int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size, int *weak, int version, const char* vername, int local, int veropt); // Add bridges to functions
typedef struct linkmap_s {
// actual struct link_map

View File

@ -18,6 +18,7 @@ typedef struct onesymbol_s {
typedef struct versymbol_s {
int version; // -1 = no-version, 0=local, 1=global, X=versioned
int veropt;
const char* vername; // NULL or version name if version=X
onesymbol_t sym;
} versymbol_t;
@ -48,10 +49,14 @@ void FreeMapSymbols(kh_mapsymbols_t** map)
}
// Exact same version (ver<2 or vername if ver>=2)
static int SameVersion(versymbol_t* s, int ver, const char* vername)
static int SameVersion(versymbol_t* s, int ver, const char* vername, int veropt)
{
if(ver<2 && s->veropt)
return 1;
if(ver<2)
return (s->version == ver)?1:0;
if(ver>1 && veropt && s->version<2)
return 1;
if(s->vername && !strcmp(s->vername, vername))
return 1;
return 0;
@ -80,9 +85,12 @@ static versymbol_t* FindVersionGlobal(versymbols_t* s, size_t size)
{
if(!s || !s->sz)
return NULL;
for (int i=0; i<s->sz; ++i)
for (int i=0; i<s->sz; ++i) {
if(s->syms[i].version==1 && (!size || (size==s->syms[i].sym.sz)))
return &s->syms[i];
if(s->syms[i].version>1 && s->syms[i].veropt && (!size || (size==s->syms[i].sym.sz)))
return &s->syms[i];
}
return NULL;
}
static versymbol_t* FindVersion(versymbols_t* s, size_t size, const char* vername)
@ -105,7 +113,7 @@ static versymbol_t* FindFirstVersion(versymbols_t* s, size_t size)
}
// Match version (so ver=0:0, ver=1:-1/1/X, ver=-1:any, ver=X:1/"name")
static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername, size_t size, int local, const char* defver)
static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername, size_t size, int local, int veropt)
{
if(!s || !s->sz)
return NULL;
@ -114,14 +122,12 @@ static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername,
if(local) ret = FindVersionLocal(s, size);
if(!ret) ret = FindNoVersion(s, size);
if(!ret) ret = FindVersionGlobal(s, size);
if(!ret && defver) ret = FindVersion(s, size, defver);
return ret;
}
if(ver==-1) {
if(local) ret = FindVersionLocal(s, size);
if(!ret) ret = FindNoVersion(s, size);
if(!ret) ret = FindVersionGlobal(s, size);
if(!ret && defver) ret = FindVersion(s, size, defver);
//if(!ret) ret = FindFirstVersion(s, size);
return ret;
}
@ -134,18 +140,20 @@ static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername,
if(local) ret = FindVersionLocal(s, size);
if(!ret) ret = FindVersionGlobal(s, size);
if(!ret) ret = FindNoVersion(s, size);
if(!ret && defver) ret = FindVersion(s, size, defver);
//if(!ret) ret = FindFirstVersion(s);
return ret;
}
if(veropt && ver>1) {
ret = FindVersionGlobal(s, size);
if(ret) return ret;
}
ret = FindVersion(s, size, vername);
if(local && !ret) ret = FindVersionLocal(s, size);
if(!ret && defver && vername && !strcmp(defver, vername)) ret = FindVersionGlobal(s, size);
//if(!ret) return FindVersionGlobal(s);
return ret;
}
void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername)
void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername, int veropt)
{
int ret;
khint_t k = kh_put(mapsymbols, mapsymbols, name, &ret);
@ -153,7 +161,7 @@ void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, ui
if(ret) {v->sz = v->cap = 0; v->syms = NULL;}
// now check if that version already exist, and update record and exit if yes
for(int i=0; i<v->sz; ++i)
if(SameVersion(&v->syms[i], ver, vername)) {
if(SameVersion(&v->syms[i], ver, vername, veropt)) {
v->syms[i].sym.offs = addr;
v->syms[i].sym.sz = sz;
return;
@ -183,7 +191,7 @@ void ForceUpdateSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t
}
}
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local, const char* defver)
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local, int veropt)
{
if(!mapsymbols)
return 0;
@ -191,13 +199,13 @@ uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, con
if(k==kh_end(mapsymbols))
return 0;
versymbols_t * v = &kh_val(mapsymbols, k);
versymbol_t * s = MatchVersion(v, ver, vername, 0, local, defver);
versymbol_t * s = MatchVersion(v, ver, vername, 0, local, veropt);
if(s)
return s->sym.offs;
return 0;
}
void AddUniqueSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername)
void AddUniqueSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername, int veropt)
{
int ret;
khint_t k = kh_put(mapsymbols, mapsymbols, name, &ret);
@ -205,7 +213,7 @@ void AddUniqueSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t ad
if(ret) {v->sz = v->cap = 0; v->syms = NULL;}
// now check if that version already exist, and exit if yes
for(int i=0; i<v->sz; ++i)
if(SameVersion(&v->syms[i], ver, vername)) {
if(SameVersion(&v->syms[i], ver, vername, veropt)) {
return;
}
// add a new record
@ -218,9 +226,10 @@ void AddUniqueSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t ad
v->syms[idx].vername = vername;
v->syms[idx].sym.offs = addr;
v->syms[idx].sym.sz = sz;
v->syms[idx].veropt = veropt;
}
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local, const char* defver)
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local, int veropt)
{
if(!mapsymbols)
return 0;
@ -228,7 +237,7 @@ int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t*
if(k==kh_end(mapsymbols))
return 0;
versymbols_t * v = &kh_val(mapsymbols, k);
versymbol_t* s = MatchVersion(v, ver, vername, 0, local, defver);
versymbol_t* s = MatchVersion(v, ver, vername, 0, local, veropt);
if(s) {
if(start) *start = s->sym.offs;
if(end) *end = *start + s->sym.sz;
@ -237,7 +246,7 @@ int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t*
return 0;
}
int GetSizedSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int ver, const char* vername, int local, const char* defver)
int GetSizedSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int ver, const char* vername, int local, int veropt)
{
if(!mapsymbols)
return 0;
@ -245,7 +254,7 @@ int GetSizedSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintpt
if(k==kh_end(mapsymbols))
return 0;
versymbols_t * v = &kh_val(mapsymbols, k);
versymbol_t* s = MatchVersion(v, ver, vername, size, local, defver);
versymbol_t* s = MatchVersion(v, ver, vername, size, local, veropt);
if(s) {
*start = s->sym.offs;
*end = *start + s->sym.sz;
@ -270,38 +279,3 @@ const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* start
);
return NULL;
}
KHASH_MAP_IMPL_STR(defaultversion, const char*)
kh_defaultversion_t* NewDefaultVersion()
{
kh_defaultversion_t* ret = kh_init(defaultversion);
return ret;
}
void FreeDefaultVersion(kh_defaultversion_t** def)
{
if(!def || !*def)
return;
const char* v;
kh_foreach_value(*def, v, box_free((char*)v););
kh_destroy(defaultversion, *def);
*def = NULL;
}
void AddDefaultVersion(kh_defaultversion_t* def, const char* symname, const char* vername)
{
int ret;
khint_t k = kh_put(defaultversion, def, symname, &ret);
if(!ret) return; // already set!
kh_value(def, k) = box_strdup(vername);
}
const char* GetDefaultVersion(kh_defaultversion_t* def, const char* symname)
{
khint_t k = kh_get(defaultversion, def, symname);
if(k==kh_end(def))
return NULL;
else
return kh_value(def, k);
}

View File

@ -121,8 +121,8 @@ static void checkSDL2isNative()
{
if(my_context->sdl2allocrw)
return;
emulated_sdl2allocrw = FindGlobalSymbol(my_context->maplib, "SDL_AllocRW", -1, NULL);
emulated_sdl2freerw = FindGlobalSymbol(my_context->maplib, "SDL_FreeRW", -1, NULL);
emulated_sdl2allocrw = FindGlobalSymbol(my_context->maplib, "SDL_AllocRW", -1, NULL, 0);
emulated_sdl2freerw = FindGlobalSymbol(my_context->maplib, "SDL_FreeRW", -1, NULL, 0);
if(emulated_sdl2allocrw && emulated_sdl2freerw) {
my_context->sdl2allocrw = my_wrapped_sdl2allocrw;
my_context->sdl2freerw = my_wrapped_sdl2freerw;

View File

@ -1386,7 +1386,8 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
dynarec_log(LOG_INFO, "Warning, addr inside current dynablock!\n");
}
// mark stuff as unclean
cleanDBFromAddressRange(((uintptr_t)addr)&~(box64_pagesize-1), box64_pagesize, 0);
if(box64_dynarec)
cleanDBFromAddressRange(((uintptr_t)addr)&~(box64_pagesize-1), box64_pagesize, 0);
static void* glitch_pc = NULL;
static void* glitch_addr = NULL;
static uint32_t glitch_prot = 0;
@ -1511,7 +1512,7 @@ dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for
#error Unsupported Architecture
#endif //arch
#endif //DYNAREC
if(!db && (sig==SIGSEGV) && ((uintptr_t)addr==x64pc-1))
if(!db && (sig==SIGSEGV) && ((uintptr_t)addr==(x64pc-1)))
x64pc--;
if(log_minimum<=box64_log) {
signal_jmpbuf_active = 1;
@ -1632,7 +1633,7 @@ dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for
if(db)
hash = X31_hash_code(db->x64_addr, db->x64_size);
printf_log(log_minimum, "%04d|%s @%p (%s) (x64pc=%p/%s:\"%s\", rsp=%p, stack=%p:%p own=%p fp=%p), for accessing %p (code=%d/prot=%x), db=%p(%p:%p/%p:%p/%s:%s, hash:%x/%x) handler=%p",
GetTID(), signame, pc, name, (void*)x64pc, elfname?elfname:"???", x64name?x64name:"???", rsp,
GetTID(), signame, pc, name, (void*)x64pc, elfname?:"???", x64name?:"???", rsp,
emu->init_stack, emu->init_stack+emu->size_stack, emu->stack2free, (void*)R_RBP,
addr, info->si_code,
prot, db, db?db->block:0, db?(db->block+db->size):0,
@ -1674,7 +1675,7 @@ dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for
#warning TODO
#endif
#else
printf_log(log_minimum, "%04d|%s @%p (%s) (x64pc=%p/%s:\"%s\", rsp=%p), for accessing %p (code=%d)", GetTID(), signame, pc, name, (void*)x64pc, elfname?elfname:"???", x64name?x64name:"???", rsp, addr, info->si_code);
printf_log(log_minimum, "%04d|%s @%p (%s) (x64pc=%p/%s:\"%s\", rsp=%p), for accessing %p (code=%d)", GetTID(), signame, pc, name, (void*)x64pc, elfname?:"???", x64name?:"???", rsp, addr, info->si_code);
#endif
if(!shown_regs) {
for (int i=0; i<16; ++i) {

View File

@ -1221,6 +1221,7 @@ void LoadEnvVars(box64context_t *context)
AddPath("libpng12.so.0", &context->box64_emulated_libs, 0);
AddPath("libcurl.so.4", &context->box64_emulated_libs, 0);
AddPath("libtbbmalloc.so.2", &context->box64_emulated_libs, 0);
AddPath("libtbbmalloc_proxy.so.2", &context->box64_emulated_libs, 0);
if(getenv("BOX64_SSE_FLUSHTO0")) {
if (strcmp(getenv("BOX64_SSE_FLUSHTO0"), "1")==0) {
@ -1312,10 +1313,10 @@ void setupTraceInit()
if(s_trace_start || s_trace_end)
SetTraceEmu(s_trace_start, s_trace_end);
} else {
if (GetGlobalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, NULL, NULL)) {
if (GetGlobalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, 0, NULL)) {
SetTraceEmu(s_trace_start, s_trace_end);
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end);
} else if(GetLocalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, NULL, NULL)) {
} else if(GetLocalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, 0, NULL)) {
SetTraceEmu(s_trace_start, s_trace_end);
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end);
} else {
@ -1332,6 +1333,54 @@ void setupTraceInit()
#endif
}
void setupTraceMapLib(lib_t* maplib)
{
if(!trace_func)
return;
char* p = trace_func;
uintptr_t s_trace_start=0, s_trace_end=0;
if(maplib) {
if (GetGlobalSymbolStartEnd(maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, 0, NULL)) {
SetTraceEmu(s_trace_start, s_trace_end);
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end);
box_free(trace_func);
trace_func = NULL;
return;
} else if(GetLocalSymbolStartEnd(maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, 0, NULL)) {
SetTraceEmu(s_trace_start, s_trace_end);
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end);
box_free(trace_func);
trace_func = NULL;
return;
} else if(GetSymTabStartEnd(maplib, p, &s_trace_start, &s_trace_end)) {
SetTraceEmu(s_trace_start, s_trace_end);
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end);
box_free(trace_func);
trace_func = NULL;
return;
}
}
if (my_context->elfs && GetGlobalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, 0, NULL)) {
SetTraceEmu(s_trace_start, s_trace_end);
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end);
box_free(trace_func);
trace_func = NULL;
} else if(my_context->elfs && GetLocalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, 0, NULL)) {
SetTraceEmu(s_trace_start, s_trace_end);
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end);
box_free(trace_func);
trace_func = NULL;
} else if(GetSymTabStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end)) {
SetTraceEmu(s_trace_start, s_trace_end);
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end);
box_free(trace_func);
trace_func = NULL;
} else {
printf_log(LOG_NONE, "Warning, Symbol to trace (\"%s\") not found. Trying to set trace later\n", p);
SetTraceEmu(0, 1); // disabling trace, mostly
}
}
EXPORTDYN
void setupTrace()
{
@ -1356,10 +1405,10 @@ void setupTrace()
}
}
} else {
if (my_context->elfs && GetGlobalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, NULL, NULL)) {
if (my_context->elfs && GetGlobalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, 0, NULL)) {
SetTraceEmu(s_trace_start, s_trace_end);
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end);
} else if(my_context->elfs && GetLocalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, NULL, NULL)) {
} else if(my_context->elfs && GetLocalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, 0, NULL)) {
SetTraceEmu(s_trace_start, s_trace_end);
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end);
} else {
@ -1981,11 +2030,14 @@ int main(int argc, const char **argv, char **env) {
thread_set_emu(emu);
// export symbols
AddSymbols(my_context->maplib, GetMapSymbols(elf_header), GetWeakSymbols(elf_header), GetLocalSymbols(elf_header), elf_header);
AddSymbols(my_context->maplib, elf_header);
if(wine_preloaded) {
uintptr_t wineinfo = FindSymbol(GetMapSymbols(elf_header), "wine_main_preload_info", -1, NULL, 1, NULL);
if(!wineinfo) wineinfo = FindSymbol(GetWeakSymbols(elf_header), "wine_main_preload_info", -1, NULL, 1, NULL);
if(!wineinfo) wineinfo = FindSymbol(GetLocalSymbols(elf_header), "wine_main_preload_info", -1, NULL, 1, NULL);
uintptr_t wineinfo = 0;
int ver = -1, veropt = 0;
const char* vername = NULL;
if(!ElfGetGlobalSymbolStartEnd(elf_header, &wineinfo, NULL, "wine_main_preload_info", &ver, &vername, 1, &veropt))
if(!ElfGetWeakSymbolStartEnd(elf_header, &wineinfo, NULL, "wine_main_preload_info", &ver, &vername, 1, &veropt))
if(!ElfGetLocalSymbolStartEnd(elf_header, &wineinfo, NULL, "wine_main_preload_info", &ver, &vername, 1, &veropt))
if(!wineinfo) {printf_log(LOG_NONE, "Warning, Symbol wine_main_preload_info not found\n");}
else {
*(void**)wineinfo = get_wine_prereserve();

View File

@ -778,7 +778,8 @@ void checkHookedSymbols(elfheader_t* h)
return;
for (size_t i=0; i<h->numSymTab; ++i) {
int type = ELF64_ST_TYPE(h->SymTab[i].st_info);
if(type==STT_FUNC) {
int sz = ELF64_ST_TYPE(h->SymTab[i].st_size);
if(type==STT_FUNC && sz) {
const char * symname = h->StrTab+h->SymTab[i].st_name;
#define GO(A, B) if(!strcmp(symname, #A)) ++hooked; else if(!strcmp(symname, "__libc_" #A)) ++hooked;
#define GO2(A, B)
@ -824,7 +825,7 @@ void checkHookedSymbols(elfheader_t* h)
#undef GO
#undef GO2
#define GO(A, B) if(!strcmp(symname, #A)) {uintptr_t alt = AddCheckBridge(my_context->system, B, A, 0, #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, #A, h, &real_##A);}
#define GO2(A, B) if(!strcmp(symname, #A)) {uintptr_t alt = AddCheckBridge(my_context->system, B, my_##A, 0, "my_" #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, "my_" #A, h, &real_##A);}
#define GO2(A, B) if(!strcmp(symname, #A) && (box64_malloc_hack>1)) {uintptr_t alt = AddCheckBridge(my_context->system, B, my_##A, 0, "my_" #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, "my_" #A, h, &real_##A);}
SUPER()
#undef GO
#undef GO2
@ -847,7 +848,7 @@ void checkHookedSymbols(elfheader_t* h)
#undef GO
#undef GO2
#define GO(A, B) if(!strcmp(symname, #A)) {uintptr_t alt = AddCheckBridge(my_context->system, B, A, 0, #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, #A, h, &real_##A);}
#define GO2(A, B) if(!strcmp(symname, #A)) {uintptr_t alt = AddCheckBridge(my_context->system, B, my_##A, 0, "my_" #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, "my_" #A, h, &real_##A);}
#define GO2(A, B) if(!strcmp(symname, #A) && (box64_malloc_hack>1)) {uintptr_t alt = AddCheckBridge(my_context->system, B, my_##A, 0, "my_" #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, "my_" #A, h, &real_##A);}
SUPER()
#undef GO
#undef GO2

View File

@ -229,7 +229,7 @@ uintptr_t AddVSyscall(bridge_t* bridge, int num)
const char* getBridgeName(void* addr)
{
onebridge_t* one = (onebridge_t*)(((uintptr_t)addr/sizeof(onebridge_t))*sizeof(onebridge_t)); // align to start of bridge
onebridge_t* one = (onebridge_t*)(((uintptr_t)addr&~(sizeof(onebridge_t)-1))); // align to start of bridge
if(one->C3==0xC3 && one->S=='S' && one->C=='C')
return one->name;
return NULL;

View File

@ -685,7 +685,7 @@ static void my3_gtk_builder_connect_signals_default(void* builder, void* object,
}
// Mixing Native and emulated code... the my_g_signal_* function will handle that (GetNativeFnc does)
if(!func)
func = (void*)FindGlobalSymbol(my_context->maplib, handler_name, 0, NULL);
func = (void*)FindGlobalSymbol(my_context->maplib, handler_name, 0, NULL, 0);
if(!func) {
my->g_log("Gtk", 1<<4, "Could not find signal handler '%s'.", handler_name);

View File

@ -1034,7 +1034,7 @@ static void my_gtk_builder_connect_signals_custom(void* builder,
uintptr_t offs = 0;
uintptr_t end = 0;
GetGlobalSymbolStartEnd(my_context->maplib, handler_name, &offs, &end, NULL, -1, NULL, NULL, NULL);
GetGlobalSymbolStartEnd(my_context->maplib, handler_name, &offs, &end, NULL, -1, NULL, 0, NULL);
if(!offs) {
if (args->module == NULL)
args->my->g_log("Gtk", 1<<2 ,"gtk_builder_connect_signals() requires working GModule");

View File

@ -80,6 +80,7 @@ void RemoveDlopen(library_t** lib, size_t idx)
}
extern int box64_zoom;
void setupTraceMapLib(lib_t* maplib);
// Implementation
void* my_dlopen(x64emu_t* emu, void *filename, int flag)
{
@ -204,6 +205,7 @@ void* my_dlopen(x64emu_t* emu, void *filename, int flag)
my_context->deferredInitCap = old_deferredInitCap;
return NULL;
}
setupTraceMapLib(tmp->libs[0]->maplib);
free_neededlib(tmp);
lib = GetLibInternal(rfilename);
RunDeferredElfInit(emu);
@ -258,7 +260,7 @@ char* my_dlerror(x64emu_t* emu)
KHASH_SET_INIT_INT(libs);
// TODO: deepbind is probably not followed correctly here
int recursive_dlsym_lib(kh_libs_t* collection, library_t* lib, const char* rsymbol, uintptr_t *start, uintptr_t *end, int version, const char* vername, const char* globdefver, const char* weakdefver)
int recursive_dlsym_lib(kh_libs_t* collection, library_t* lib, const char* rsymbol, uintptr_t *start, uintptr_t *end, int* version, const char** vername, int* veropt)
{
if(!lib)
return 0;
@ -270,25 +272,26 @@ int recursive_dlsym_lib(kh_libs_t* collection, library_t* lib, const char* rsymb
// TODO: should use librarian functions instead!
int weak;
// look in the library itself
if(lib->getglobal(lib, rsymbol, start, end, 0, &weak, version, vername, 1, globdefver))
if(lib->getglobal(lib, rsymbol, start, end, 0, &weak, version, vername, 1, veropt, NULL))
return 1;
if(lib->getweak(lib, rsymbol, start, end, 0, &weak, version, vername, 1, weakdefver))
if(lib->getweak(lib, rsymbol, start, end, 0, &weak, version, vername, 1, veropt, NULL))
return 1;
// look in other libs
int n = GetNeededLibsN(lib);
for (int i=0; i<n; ++i) {
library_t *l = GetNeededLib(lib, i);
if(recursive_dlsym_lib(collection, l, rsymbol, start, end, version, vername, globdefver, weakdefver))
if(recursive_dlsym_lib(collection, l, rsymbol, start, end, version, vername, veropt))
return 1;
}
return 0;
}
int my_dlsym_lib(library_t* lib, const char* rsymbol, uintptr_t *start, uintptr_t *end, int version, const char* vername, const char* globdefver, const char* weakdefver)
int my_dlsym_lib(library_t* lib, const char* rsymbol, uintptr_t *start, uintptr_t *end, int version, const char* vername)
{
kh_libs_t *collection = kh_init(libs);
int ret = recursive_dlsym_lib(collection, lib, rsymbol, start, end, version, vername, globdefver, weakdefver);
int veropt = 0;
int ret = recursive_dlsym_lib(collection, lib, rsymbol, start, end, &version, &vername, &veropt);
kh_destroy(libs, collection);
return ret;
@ -306,9 +309,7 @@ void* my_dlsym(x64emu_t* emu, void *handle, void *symbol)
printf_dlsym(LOG_DEBUG, "%04d|Call to dlsym(%p, \"%s\")%s", GetTID(), handle, rsymbol, dlsym_error?"":"\n");
if(handle==NULL) {
// special case, look globably
const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, 0, rsymbol);
const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, 0, rsymbol);
if(GetGlobalSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, NULL, -1, NULL, globdefver, weakdefver)) {
if(GetGlobalSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, NULL, -1, NULL, 0, NULL)) {
printf_dlsym(LOG_NEVER, "%p\n", (void*)start);
pthread_mutex_unlock(&mutex);
return (void*)start;
@ -322,10 +323,8 @@ void* my_dlsym(x64emu_t* emu, void *handle, void *symbol)
}
if(handle==(void*)~0LL) {
// special case, look globably but no self (RTLD_NEXT)
const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, 0, rsymbol);
const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, 0, rsymbol);
elfheader_t *elf = FindElfAddress(my_context, *(uintptr_t*)R_RSP); // use return address to guess "self"
if(GetNoSelfSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, elf, 0, -1, NULL, globdefver, weakdefver)) {
if(GetNoSelfSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, elf, 0, -1, NULL, 0, NULL)) {
printf_dlsym(LOG_NEVER, "%p\n", (void*)start);
pthread_mutex_unlock(&mutex);
return (void*)start;
@ -358,9 +357,7 @@ void* my_dlsym(x64emu_t* emu, void *handle, void *symbol)
}
if(dl->dllibs[nlib].lib) {
int deepbind = GetDeepBind(dl->dllibs[nlib].lib);
const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->dllibs[nlib].lib->maplib)?NULL:dl->dllibs[nlib].lib->maplib, 0, deepbind, rsymbol);
const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->dllibs[nlib].lib->maplib)?NULL:dl->dllibs[nlib].lib->maplib, 1, deepbind, rsymbol);
if(my_dlsym_lib(dl->dllibs[nlib].lib, rsymbol, &start, &end, -1, NULL, globdefver, weakdefver)==0) {
if(my_dlsym_lib(dl->dllibs[nlib].lib, rsymbol, &start, &end, -1, NULL)==0) {
// not found
printf_dlsym(LOG_NEVER, "%p\nCall to dlsym(%s, \"%s\") Symbol not found\n", NULL, GetNameLib(dl->dllibs[nlib].lib), rsymbol);
printf_log(LOG_DEBUG, " Symbol not found\n");
@ -373,9 +370,7 @@ void* my_dlsym(x64emu_t* emu, void *handle, void *symbol)
} else {
// still usefull?
// => look globably
const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, 0, rsymbol);
const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, 0, rsymbol);
if(GetGlobalSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, NULL, -1, NULL, globdefver, weakdefver)) {
if(GetGlobalSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, NULL, -1, NULL, 0, NULL)) {
printf_dlsym(LOG_NEVER, "%p\n", (void*)start);
pthread_mutex_unlock(&mutex);
return (void*)start;
@ -463,9 +458,7 @@ void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, const char *vername)
printf_dlsym(LOG_DEBUG, "Call to dlvsym(%p, \"%s\", %s)%s", handle, rsymbol, vername?vername:"(nil)", dlsym_error?"":"\n");
if(handle==NULL) {
// special case, look globably
const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, 0, rsymbol);
const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, 0, rsymbol);
if(GetGlobalSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, NULL, version, vername, globdefver, weakdefver)) {
if(GetGlobalSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, NULL, version, vername, 0, NULL)) {
printf_dlsym(LOG_NEVER, "%p\n", (void*)start);
return (void*)start;
}
@ -477,10 +470,8 @@ void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, const char *vername)
}
if(handle==(void*)~0LL) {
// special case, look globably but no self (RTLD_NEXT)
const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, 0, rsymbol);
const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, 0, rsymbol);
elfheader_t *elf = FindElfAddress(my_context, *(uintptr_t*)R_RSP); // use return address to guess "self"
if(GetNoSelfSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, elf, 0, version, vername, globdefver, weakdefver)) {
if(GetNoSelfSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, elf, 0, version, vername, 0, NULL)) {
printf_dlsym(LOG_NEVER, "%p\n", (void*)start);
return (void*)start;
}
@ -509,9 +500,7 @@ void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, const char *vername)
}
if(dl->dllibs[nlib].lib) {
int deepbind = GetDeepBind(dl->dllibs[nlib].lib);
const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->dllibs[nlib].lib->maplib)?NULL:dl->dllibs[nlib].lib->maplib, 0, deepbind, rsymbol);
const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==dl->dllibs[nlib].lib->maplib)?NULL:dl->dllibs[nlib].lib->maplib, 1, deepbind, rsymbol);
if(my_dlsym_lib(dl->dllibs[nlib].lib, rsymbol, &start, &end, version, vername, globdefver, weakdefver)==0) {
if(my_dlsym_lib(dl->dllibs[nlib].lib, rsymbol, &start, &end, version, vername)==0) {
// not found
printf_dlsym(LOG_NEVER, "%p\nCall to dlvsym(%s, \"%s\", %s) Symbol not found\n", NULL, GetNameLib(dl->dllibs[nlib].lib), rsymbol, vername?vername:"(nil)");
printf_log(LOG_DEBUG, " Symbol not found\n");
@ -522,9 +511,7 @@ void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, const char *vername)
}
} else {
// still usefull?
const char* globdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 0, 0, rsymbol);
const char* weakdefver = GetMaplibDefaultVersion(my_context->maplib, NULL, 1, 0, rsymbol);
if(GetGlobalSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, NULL, -1, NULL, globdefver, weakdefver)) {
if(GetGlobalSymbolStartEnd(my_context->maplib, rsymbol, &start, &end, NULL, -1, NULL, 0, NULL)) {
printf_dlsym(LOG_NEVER, "%p\n", (void*)start);
return (void*)start;
}

Binary file not shown.

View File

@ -1,8 +1,8 @@
#include <sys/syscall.h>
#include <unistd.h>
int main(int argc, char **argv)
{
#include <sys/syscall.h>
#include <unistd.h>
// build with `gcc test01.c -o test01 -march=core2 -Wl,--hash-style=both`
int main(int argc, char **argv)
{
const char msg[] = "Hello x86_64 World!\n";
//syscall(1, STDOUT_FILENO, msg, sizeof(msg)-1);
asm (
@ -15,5 +15,5 @@ int main(int argc, char **argv)
:"r" (msg)
:"%rax","%rdi","%rsi","%rdx"
);
return 0;
return 0;
}