mirror of https://github.com/ptitSeb/box64.git
[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:
parent
549e042e67
commit
c5a6875de9
|
@ -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"
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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:"");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
68
src/main.c
68
src/main.c
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
BIN
tests/test01
BIN
tests/test01
Binary file not shown.
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue