mirror of
https://github.com/ptitSeb/box64.git
synced 2024-11-23 06:30:22 +00:00
[BOX32] Added 32bits elf reloc type rel handling
This commit is contained in:
parent
c845d0cf81
commit
683e44baf9
@ -365,6 +365,7 @@ if(NOT STATICBUILD)
|
||||
endif()
|
||||
if(BOX32)
|
||||
list(APPEND ELFLOADER_SRC
|
||||
"${BOX64_ROOT}/src/elfs/elfhash32.c"
|
||||
"${BOX64_ROOT}/src/elfs/elfloader32.c"
|
||||
"${BOX64_ROOT}/src/elfs/elfparser32.c"
|
||||
"${BOX64_ROOT}/src/elfs/elfload_dump32.c"
|
||||
|
@ -374,6 +374,11 @@ static void new_elf_hash_dump(elfheader_t* h)
|
||||
printf_log(LOG_NONE, "\n===============\n");
|
||||
}
|
||||
|
||||
#ifndef BOX32
|
||||
Elf32_Sym* ElfLookup32(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt) { return NULL; }
|
||||
Elf32_Sym* ElfSymTabLookup32(elfheader_t* h, const char* symname) { return NULL; }
|
||||
Elf32_Sym* ElfDynSymLookup32(elfheader_t* h, const char* symname) { return NULL; }
|
||||
#endif
|
||||
Elf64_Sym* ElfLookup64(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt)
|
||||
{
|
||||
if(h->gnu_hash)
|
||||
|
190
src/elfs/elfhash32.c
Normal file
190
src/elfs/elfhash32.c
Normal file
@ -0,0 +1,190 @@
|
||||
#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"
|
||||
|
||||
static int SymbolMatch(elfheader_t* h, uint32_t i, int ver, const char* vername, int local, int veropt)
|
||||
{
|
||||
int version = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1;
|
||||
if(version!=-1) version &=0x7fff;
|
||||
const char* symvername = GetSymbolVersion(h, version);
|
||||
Elf32_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>1 && flags==0) // flag is not WEAK, so global works
|
||||
return 1;
|
||||
if(ver<2 || !symvername)
|
||||
return 0;
|
||||
return strcmp(vername, symvername)?0:1;
|
||||
}
|
||||
|
||||
static Elf32_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._32[i].st_name;
|
||||
if (!strcmp(symname, name) && SymbolMatch(h, i, ver, vername, local, veropt)) {
|
||||
return &h->DynSym._32[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static 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._32[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");
|
||||
}
|
||||
|
||||
static Elf32_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._32[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._32[symidx];
|
||||
}
|
||||
if(symhash&1)
|
||||
return NULL;
|
||||
symidx++;
|
||||
}
|
||||
}
|
||||
|
||||
static 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._32[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");
|
||||
}
|
||||
|
||||
Elf32_Sym* ElfLookup32(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);
|
||||
}
|
||||
|
||||
Elf32_Sym* ElfSymTabLookup32(elfheader_t* h, const char* symname)
|
||||
{
|
||||
if(!h->SymTab._32)
|
||||
return 0;
|
||||
for(size_t i=0; i<h->numSymTab; ++i) {
|
||||
Elf32_Sym* sym = &h->SymTab._32[i];
|
||||
int type = ELF32_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;
|
||||
}
|
||||
|
||||
Elf32_Sym* ElfDynSymLookup32(elfheader_t* h, const char* symname)
|
||||
{
|
||||
if(!h->DynSym._32)
|
||||
return 0;
|
||||
for(size_t i=0; i<h->numDynSym; ++i) {
|
||||
Elf32_Sym* sym = &h->DynSym._32[i];
|
||||
int type = ELF32_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;
|
||||
}
|
@ -46,7 +46,7 @@ void* my__IO_2_1_stdin_ = NULL;
|
||||
void* my__IO_2_1_stdout_ = NULL;
|
||||
|
||||
// return the index of header (-1 if it doesn't exist)
|
||||
int getElfIndex(box64context_t* ctx, elfheader_t* head) {
|
||||
static int getElfIndex(box64context_t* ctx, elfheader_t* head) {
|
||||
for (int i=0; i<ctx->elfsize; ++i)
|
||||
if(ctx->elfs[i]==head)
|
||||
return i;
|
||||
@ -463,17 +463,10 @@ static int IsSymInElfSpace(const elfheader_t* h, Elf64_Sym* sym)
|
||||
if(!h || !sym)
|
||||
return 0;
|
||||
uintptr_t addr = (uintptr_t)sym;
|
||||
if(box64_is32bits) {
|
||||
if(h->SymTab._32 && addr>=(uintptr_t)h->SymTab._32 && addr<(uintptr_t)&h->SymTab._32[h->numSymTab])
|
||||
return 1;
|
||||
if(h->DynSym._32 && addr>=(uintptr_t)h->DynSym._32 && addr<(uintptr_t)&h->DynSym._32[h->numDynSym])
|
||||
return 1;
|
||||
} else {
|
||||
if(h->SymTab._64 && addr>=(uintptr_t)h->SymTab._64 && addr<(uintptr_t)&h->SymTab._64[h->numSymTab])
|
||||
return 1;
|
||||
if(h->DynSym._64 && addr>=(uintptr_t)h->DynSym._64 && addr<(uintptr_t)&h->DynSym._64[h->numDynSym])
|
||||
return 1;
|
||||
}
|
||||
if(h->SymTab._64 && addr>=(uintptr_t)h->SymTab._64 && addr<(uintptr_t)&h->SymTab._64[h->numSymTab])
|
||||
return 1;
|
||||
if(h->DynSym._64 && addr>=(uintptr_t)h->DynSym._64 && addr<(uintptr_t)&h->DynSym._64[h->numDynSym])
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
static elfheader_t* FindElfSymbol(box64context_t *context, Elf64_Sym* sym)
|
||||
@ -487,7 +480,7 @@ static elfheader_t* FindElfSymbol(box64context_t *context, Elf64_Sym* sym)
|
||||
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)
|
||||
static 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;
|
||||
@ -535,7 +528,7 @@ EXPORT uintptr_t my__dl_tlsdesc_undefweak(x64emu_t* emu)
|
||||
return td->arg;
|
||||
}
|
||||
|
||||
void GrabX64CopyMainElfReloc(elfheader_t* head)
|
||||
static void GrabX64CopyMainElfReloc(elfheader_t* head)
|
||||
{
|
||||
if(head->rela) {
|
||||
int cnt = head->relasz / head->relaent;
|
||||
@ -557,21 +550,6 @@ void GrabX64CopyMainElfReloc(elfheader_t* head)
|
||||
}
|
||||
}
|
||||
}
|
||||
void CheckGNUUniqueBindings(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, "Checking for symbol with STB_GNU_UNIQUE bindingsfor %s\n", head->name);
|
||||
for (int i=0; i<cnt; ++i) {
|
||||
int bind = ELF64_ST_BIND(rela[i].r_info);
|
||||
if(bind == STB_GNU_UNIQUE) {
|
||||
head->gnuunique = 1;
|
||||
return; // can stop searching
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static elfheader_t* checkElfLib(elfheader_t* h, library_t* lib)
|
||||
{
|
||||
@ -857,7 +835,12 @@ static int RelocateElfRELR(elfheader_t *head, int cnt, Elf64_Relr *relr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RelocateElf32(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head) { /* TODO */ return -1; }
|
||||
int RelocateElf32(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head)
|
||||
#ifndef BOX32
|
||||
{ return -1; }
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
int RelocateElf64(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head)
|
||||
{
|
||||
if((head->flags&DF_BIND_NOW) && !bindnow) {
|
||||
|
@ -42,6 +42,24 @@
|
||||
#include "x64tls.h"
|
||||
#include "box32.h"
|
||||
|
||||
// return the index of header (-1 if it doesn't exist)
|
||||
static int getElfIndex(box64context_t* ctx, elfheader_t* head) {
|
||||
for (int i=0; i<ctx->elfsize; ++i)
|
||||
if(ctx->elfs[i]==head)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static elfheader_t* checkElfLib(elfheader_t* h, library_t* lib)
|
||||
{
|
||||
if(h && lib) {
|
||||
if(!h->needed)
|
||||
h->needed = new_neededlib(1);
|
||||
add1libref_neededlib(h->needed, lib);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin)
|
||||
{
|
||||
ptr_t offs = 0;
|
||||
@ -247,3 +265,362 @@ int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int IsSymInElfSpace(const elfheader_t* h, Elf32_Sym* sym)
|
||||
{
|
||||
if(!h || !sym)
|
||||
return 0;
|
||||
uintptr_t addr = (uintptr_t)sym;
|
||||
if(h->SymTab._32 && addr>=(uintptr_t)h->SymTab._32 && addr<(uintptr_t)&h->SymTab._32[h->numSymTab])
|
||||
return 1;
|
||||
if(h->DynSym._32 && addr>=(uintptr_t)h->DynSym._32 && addr<(uintptr_t)&h->DynSym._32[h->numDynSym])
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
static elfheader_t* FindElfSymbol(box64context_t *context, Elf32_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;
|
||||
}
|
||||
|
||||
void GrabR386CopyMainElfReloc(elfheader_t* head)
|
||||
{
|
||||
if(head->rela) {
|
||||
int cnt = head->relasz / head->relaent;
|
||||
Elf32_Rel* rel = (Elf32_Rel *)(head->rela + head->delta);
|
||||
printf_dump(LOG_DEBUG, "Grabbing R_386_COPY Relocation(s) in advance for %s\n", head->name);
|
||||
for (int i=0; i<cnt; ++i) {
|
||||
int t = ELF32_R_TYPE(rel[i].r_info);
|
||||
if(t == R_386_COPY) {
|
||||
Elf32_Sym *sym = &head->DynSym._32[ELF32_R_SYM(rel[i].r_info)];
|
||||
const char* symname = SymName32(head, sym);
|
||||
int version = head->VerSym?((Elf32_Half*)((uintptr_t)head->VerSym+head->delta))[ELF32_R_SYM(rel[i].r_info)]:-1;
|
||||
if(version!=-1) version &=0x7fff;
|
||||
const char* vername = GetSymbolVersion(head, version);
|
||||
Elf32_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int FindR386COPYRel(elfheader_t* h, const char* name, ptr_t *offs, uint32_t** p, size_t size, int version, const char* vername, int veropt)
|
||||
{
|
||||
if(!h)
|
||||
return 0;
|
||||
if(!h->rel)
|
||||
return 0;
|
||||
if(h->relent) {
|
||||
Elf32_Rel * rel = (Elf32_Rel *)(h->rel + h->delta);
|
||||
int cnt = h->relsz / h->relent;
|
||||
for (int i=0; i<cnt; ++i) {
|
||||
int t = ELF32_R_TYPE(rel[i].r_info);
|
||||
Elf32_Sym *sym = &h->DynSym._32[ELF32_R_SYM(rel[i].r_info)];
|
||||
const char* symname = SymName32(h, sym);
|
||||
if((t==R_386_COPY) && symname && !strcmp(symname, name) && (sym->st_size==size)) {
|
||||
int version2 = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[ELF32_R_SYM(rel[i].r_info)]:-1;
|
||||
if(version2!=-1) version2 &= 0x7fff;
|
||||
if(version && !version2) version2=-1; // match a versionned symbol against a global "local" symbol
|
||||
const char* vername2 = GetSymbolVersion(h, version2);
|
||||
Elf32_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 = (uint32_t*)(rel[i].r_offset + h->delta);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head, int cnt, Elf32_Rel *rel, int* need_resolv)
|
||||
{
|
||||
int ret_ok = 0;
|
||||
for (int i=0; i<cnt; ++i) {
|
||||
int t = ELF32_R_TYPE(rel[i].r_info);
|
||||
Elf32_Sym *sym = &head->DynSym._32[ELF32_R_SYM(rel[i].r_info)];
|
||||
int bind = ELF32_ST_BIND(sym->st_info);
|
||||
//uint32_t ndx = sym->st_shndx;
|
||||
const char* symname = SymName32(head, sym);
|
||||
uint32_t *p = (uint32_t*)(rel[i].r_offset + head->delta);
|
||||
uintptr_t offs = 0;
|
||||
uintptr_t end = 0;
|
||||
size_t size = sym->st_size;
|
||||
elfheader_t* sym_elf = NULL;
|
||||
elfheader_t* last_elf = NULL;
|
||||
int version = head->VerSym?((Elf32_Half*)((uintptr_t)head->VerSym+head->delta))[ELF32_R_SYM(rel[i].r_info)]:-1;
|
||||
if(version!=-1) version &=0x7fff;
|
||||
const char* vername = GetSymbolVersion(head, version);
|
||||
Elf32_Half flags = GetSymbolVersionFlag(head, version);
|
||||
int veropt = flags?0:1;
|
||||
Elf32_Sym* elfsym = NULL;
|
||||
int vis = ELF64_ST_VISIBILITY(sym->st_other);
|
||||
if(vis==STV_PROTECTED) {
|
||||
elfsym = ElfDynSymLookup32(head, symname);
|
||||
printf_log(LOG_DEBUG, "Symbol %s from %s is PROTECTED\n", symname, head->name);
|
||||
} else {
|
||||
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 = ElfDynSymLookup32(head, symname);
|
||||
if(elfsym && elfsym->st_shndx) {
|
||||
offs = elfsym->st_value + head->delta;
|
||||
end = offs + elfsym->st_size;
|
||||
}
|
||||
if(!offs && !end && local_maplib && deepbind)
|
||||
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, veropt, (void**)&elfsym);
|
||||
if(!offs && !end)
|
||||
GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, veropt, (void**)&elfsym);
|
||||
if(!offs && !end && local_maplib && !deepbind)
|
||||
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);
|
||||
}
|
||||
}
|
||||
sym_elf = FindElfSymbol(my_context, elfsym);
|
||||
if(elfsym && (ELF32_ST_TYPE(elfsym->st_info)==STT_TLS))
|
||||
offs = elfsym->st_value;
|
||||
uintptr_t globoffs, globend;
|
||||
uint32_t* globp;
|
||||
uintptr_t tmp = 0;
|
||||
intptr_t delta;
|
||||
switch(t) {
|
||||
case R_386_NONE:
|
||||
// can be ignored
|
||||
printf_dump(LOG_NEVER, "Ignoring [%d] %s %p (%p)\n", i, DumpRelType32(t), p, from_ptrv(p?(*p):0));
|
||||
break;
|
||||
case R_386_PC32:
|
||||
if (!offs) {
|
||||
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_386_PC32 %p (%p) in %s\n", symname, p, from_ptrv(*p), head->name);
|
||||
ret_ok = 1;
|
||||
}
|
||||
if(offs)
|
||||
printf_dump(LOG_NEVER, "Apply [%d] %s R_386_PC32 %p with sym=%s (ver=%d/%s), (%p -> %p/%p)\n", i, (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, version, vername?vername:"(none)", from_ptrv(*(ptr_t*)p), from_ptrv(*(ptr_t*)p+(offs-to_ptrv(p))), from_ptrv(offs));
|
||||
offs = (offs - to_ptrv(p));
|
||||
*p += offs;
|
||||
break;
|
||||
case R_386_RELATIVE:
|
||||
printf_dump(LOG_NEVER, "Apply [%d] %s R_386_RELATIVE %p (%p -> %p)\n", i, (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, from_ptrv(*p), (void*)((*p)+head->delta));
|
||||
*p += head->delta;
|
||||
break;
|
||||
case R_386_COPY:
|
||||
globoffs = offs;
|
||||
globend = end;
|
||||
offs = end = 0;
|
||||
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, 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_386_COPY @%p with sym=%s (%sver=%d/%s), @%p size=%ld\n", p, symname, veropt?"opt":"", version, vername?vername:"(none)", from_ptrv(offs), sym->st_size);
|
||||
if(p!=from_ptrv(offs))
|
||||
memmove(p, from_ptrv(offs), sym->st_size);
|
||||
sym_elf = FindElfAddress(my_context, offs);
|
||||
if(sym_elf && sym_elf!=last_elf && sym_elf!=head) last_elf = checkElfLib(head, sym_elf->lib);
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply REL R_386_COPY @%p (%p) in %s\n", symname, p, from_ptrv(*p), head->name);
|
||||
}
|
||||
break;
|
||||
case R_386_GLOB_DAT:
|
||||
if(GetSymbolStartEnd(my_context->globdata, symname, &globoffs, &globend, version, vername, 1, veropt)) {
|
||||
globp = (uint32_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, from_ptrv(p?(*p):0),
|
||||
from_ptrv(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 (!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_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 (%sver=%d/%s, elf=%s)\n", BindSym(bind), p, from_ptrv(p?(*p):0), from_ptrv(offs), symname, veropt?"opt":"", version, vername?vername:"(none)", sym_elf?sym_elf->name:"(native)");
|
||||
*p = offs;
|
||||
if(sym_elf && sym_elf!=last_elf && sym_elf!=head) last_elf = checkElfLib(head, sym_elf->lib);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case R_386_JMP_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))
|
||||
|| ((symname && strstr(symname, "__pthread_unwind_next")==symname))
|
||||
|| !tmp
|
||||
|| !((tmp>=head->plt && tmp<head->plt_end) || (tmp>=head->gotplt && tmp<head->gotplt_end))
|
||||
|| !need_resolv
|
||||
|| bindnow
|
||||
) {
|
||||
if (!offs) {
|
||||
if(bind==STB_WEAK) {
|
||||
printf_log(LOG_INFO, "Warning: Weak Symbol %s not found, cannot apply R_386_JMP_SLOT %p (%p)\n", symname, p, from_ptrv(*p));
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_JMP_SLOT %p (%p) in %s\n", symname, p, from_ptrv(*p), head->name);
|
||||
ret_ok = 1;
|
||||
}
|
||||
} else {
|
||||
if(p) {
|
||||
printf_dump(LOG_NEVER, "Apply %s R_386_JMP_SLOT %p with sym=%s(%s%s%s) (%p -> %p)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, symname, vername?"@":"", vername?vername:"", from_ptrv(*p), from_ptrv(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_386_JMP_SLOT %p (0x%x->0x%0x) with sym=%s(%s%s%s/version %d) to be apply later\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, *p, *p+head->delta, symname, symname, vername?"@":"", vername?vername:"", version);
|
||||
*p += head->delta;
|
||||
*need_resolv = 1;
|
||||
}
|
||||
break;
|
||||
case R_386_32:
|
||||
if (!offs) {
|
||||
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start")) {
|
||||
printf_log(LOG_NONE, "Error: Symbol sym=%s(%s%s%s/version %d) not found, cannot apply R_386_32 %p (%p) in %s\n", symname, symname, vername?"@":"", vername?vername:"", version, p, from_ptrv(*p), head->name);
|
||||
ret_ok = 1;
|
||||
}
|
||||
} else {
|
||||
printf_dump(LOG_NEVER, "Apply %s R_386_32 %p with sym=%s (ver=%d/%s) (%p -> %p)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, version, vername?vername:"(none)", from_ptrv(*p), from_ptrv(offs+*p));
|
||||
*p += offs;
|
||||
}
|
||||
break;
|
||||
case R_386_TLS_TPOFF:
|
||||
// Negated offset in static TLS block
|
||||
{
|
||||
if(!symname || !symname[0]) {
|
||||
sym_elf = head;
|
||||
offs = sym->st_value;
|
||||
}
|
||||
if(sym_elf) {
|
||||
delta = *(int32_t*)p;
|
||||
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%d -> %d+%d, size=%d)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType32(t), symname, p, delta, sym_elf->tlsbase, (int32_t)offs, end-offs);
|
||||
*p = (uintptr_t)((int32_t)offs + sym_elf->tlsbase);
|
||||
} else {
|
||||
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%d), no elf_header found\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType32(t), symname, p, (int32_t)offs);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case R_386_TLS_TPOFF32:
|
||||
// Non-negated offset in static TLS block???
|
||||
{
|
||||
if(!symname || !symname[0]) {
|
||||
sym_elf = head;
|
||||
offs = sym->st_value;
|
||||
}
|
||||
if(sym_elf) {
|
||||
delta = *(int32_t*)p;
|
||||
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%d -> %d+%d, size=%d)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType32(t), symname, p, delta, -sym_elf->tlsbase, (int32_t)offs, end-offs);
|
||||
*p = (uintptr_t)((int32_t)offs - sym_elf->tlsbase);
|
||||
} else {
|
||||
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%d), no elf_header found\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType32(t), symname, p, (int32_t)offs);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case R_386_TLS_DTPMOD32:
|
||||
// ID of module containing symbol
|
||||
if(!symname || symname[0]=='\0' || bind==STB_LOCAL) {
|
||||
offs = getElfIndex(my_context, head);
|
||||
sym_elf = head;
|
||||
} else {
|
||||
offs = getElfIndex(my_context, sym_elf);
|
||||
}
|
||||
if(p) {
|
||||
printf_dump(LOG_NEVER, "Apply %s %s %p with sym=%s (%p -> %p)\n", "R_386_TLS_DTPMOD32", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, from_ptrv(*p), from_ptrv(offs));
|
||||
*p = offs;
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Warning, Symbol %s or Elf not found, but R_386_TLS_DTPMOD32 Slot Offset is NULL \n", symname);
|
||||
}
|
||||
break;
|
||||
case R_386_TLS_DTPOFF32:
|
||||
// Offset in TLS block
|
||||
if (!offs && !end) {
|
||||
if(bind==STB_WEAK) {
|
||||
printf_log(LOG_INFO, "Warning: Weak Symbol %s not found, cannot apply R_386_TLS_DTPOFF32 %p (%p)\n", symname, p, from_ptrv(*p));
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_TLS_DTPOFF32 %p (%p) in %s\n", symname, p, from_ptrv(*p), head->name);
|
||||
}
|
||||
} else {
|
||||
if(!symname || !symname[0]) {
|
||||
offs = (uintptr_t)((intptr_t)(head->tlsaddr + head->delta) - (intptr_t)offs); // negative offset
|
||||
}
|
||||
if(p) {
|
||||
printf_dump(LOG_NEVER, "Apply %s R_386_TLS_DTPOFF32 %p with sym=%s (ver=%d/%s) (%zd -> %zd)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, version, vername?vername:"(none)", (intptr_t)*p, (intptr_t)offs);
|
||||
*p = offs;
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Warning, Symbol %s found, but R_386_TLS_DTPOFF32 Slot Offset is NULL \n", symname);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf_log(LOG_INFO, "Warning, don't know of to handle rel #%d %s (%p) for %s\n", i, DumpRelType32(ELF32_R_TYPE(rel[i].r_info)), p, symname?symname:"(nil)");
|
||||
}
|
||||
}
|
||||
return bindnow?ret_ok:0;
|
||||
}
|
||||
|
||||
static int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head, int cnt, Elf32_Rela *rela, int* need_resolv)
|
||||
{
|
||||
printf_log(LOG_NONE, "Error: RELA type of Relocation unsupported (only REL)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int RelocateElfRELR(elfheader_t *head, int cnt, Elf32_Relr *relr)
|
||||
{
|
||||
printf_log(LOG_NONE, "Error: RELR type of Relocation unsupported (only REL)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int RelocateElf32(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head)
|
||||
{
|
||||
if(0 && (head->flags&DF_BIND_NOW) && !bindnow) { // disable for now, needs more symbol in a fow libs like gtk and nss3
|
||||
bindnow = 1;
|
||||
printf_log(LOG_DEBUG, "Forcing %s to Bind Now\n", head->name);
|
||||
}
|
||||
if(head->relr) {
|
||||
int cnt = head->relrsz / head->relrent;
|
||||
DumpRelRTable32(head, cnt, (Elf32_Relr *)(head->relr + head->delta), "RelR");
|
||||
printf_log(LOG_DEBUG, "Applying %d Relocation(s) with Addend for %s\n", cnt, head->name);
|
||||
if(RelocateElfRELR(head, cnt, (Elf32_Relr *)(head->relr + head->delta)))
|
||||
return -1;
|
||||
}
|
||||
if(head->rel) {
|
||||
int cnt = head->relsz / head->relent;
|
||||
DumpRelTable32(head, cnt, (Elf32_Rel *)(head->rel + head->delta), "Rel");
|
||||
printf_log(LOG_DEBUG, "Applying %d Relocation(s) for %s\n", cnt, head->name);
|
||||
if(RelocateElfREL(maplib, local_maplib, bindnow, deepbind, head, cnt, (Elf32_Rel *)(head->rel + head->delta), NULL))
|
||||
return -1;
|
||||
}
|
||||
if(head->rela) {
|
||||
int cnt = head->relasz / head->relaent;
|
||||
DumpRelATable32(head, cnt, (Elf32_Rela *)(head->rela + head->delta), "RelA");
|
||||
printf_log(LOG_DEBUG, "Applying %d Relocation(s) with Addend for %s\n", cnt, head->name);
|
||||
if(RelocateElfRELA(maplib, local_maplib, bindnow, deepbind, head, cnt, (Elf32_Rela *)(head->rela + head->delta), NULL))
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -203,11 +203,15 @@ elfheader_t* ParseElfHeader64(FILE* f, const char* name, int exec);
|
||||
|
||||
const char* BindSym(int bind);
|
||||
|
||||
Elf64_Half GetSymbolVersionFlag(elfheader_t* h, int index);
|
||||
uint16_t GetSymbolVersionFlag(elfheader_t* h, int index);
|
||||
|
||||
uint32_t old_elf_hash(const char* name);
|
||||
uint32_t new_elf_hash(const char *name);
|
||||
|
||||
Elf32_Sym* ElfLookup32(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt);
|
||||
Elf32_Sym* ElfSymTabLookup32(elfheader_t* h, const char* symname);
|
||||
Elf32_Sym* ElfDynSymLookup32(elfheader_t* h, const char* symname);
|
||||
|
||||
Elf64_Sym* ElfLookup64(elfheader_t* h, const char* symname, int ver, const char* vername, int local, int veropt);
|
||||
Elf64_Sym* ElfSymTabLookup64(elfheader_t* h, const char* symname);
|
||||
Elf64_Sym* ElfDynSymLookup64(elfheader_t* h, const char* symname);
|
||||
|
@ -45,7 +45,6 @@ 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);
|
||||
|
Loading…
Reference in New Issue
Block a user