diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-03-06 10:02:14 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-03-06 10:02:14 +0100 |
| commit | bee17de8a4f1a6056158807df5b7fc9c1f914b9b (patch) | |
| tree | 66c3c01a1ea9344335ce612115085f9fbb6599b5 /src | |
| parent | 75468d0c4c40c2ee2926c75d0ef0472cde982c23 (diff) | |
| download | box64-bee17de8a4f1a6056158807df5b7fc9c1f914b9b.tar.gz box64-bee17de8a4f1a6056158807df5b7fc9c1f914b9b.zip | |
More work on elfloader and relocation (and tls)
Diffstat (limited to 'src')
| -rwxr-xr-x | src/elfs/elfload_dump.c | 25 | ||||
| -rwxr-xr-x | src/elfs/elfloader.c | 83 | ||||
| -rwxr-xr-x | src/elfs/elfloader_private.h | 61 |
3 files changed, 148 insertions, 21 deletions
diff --git a/src/elfs/elfload_dump.c b/src/elfs/elfload_dump.c index 4ddbfbf8..459ac0b9 100755 --- a/src/elfs/elfload_dump.c +++ b/src/elfs/elfload_dump.c @@ -193,7 +193,32 @@ const char* DumpRelType(int t) GO(R_X86_64_PC16); GO(R_X86_64_8); GO(R_X86_64_PC8); + GO(R_X86_64_DTPMOD64); + GO(R_X86_64_DTPOFF64); + GO(R_X86_64_TPOFF64); + GO(R_X86_64_TLSGD); + GO(R_X86_64_TLSLD); + GO(R_X86_64_DTPOFF32); + GO(R_X86_64_GOTTPOFF); + GO(R_X86_64_TPOFF32); GO(R_X86_64_PC64); + GO(R_X86_64_GOTOFF64); + GO(R_X86_64_GOTPC32); + GO(R_X86_64_GOT64); + GO(R_X86_64_GOTPCREL64); + GO(R_X86_64_GOTPC64); + GO(R_X86_64_GOTPLT64); + GO(R_X86_64_PLTOFF64); + GO(R_X86_64_SIZE32); + GO(R_X86_64_SIZE64); + GO(R_X86_64_GOTPC32_TLSDESC); + GO(R_X86_64_TLSDESC_CALL); + GO(R_X86_64_TLSDESC); + GO(R_X86_64_IRELATIVE); + GO(R_X86_64_RELATIVE64); + GO(R_X86_64_GOTPCRELX); + GO(R_X86_64_REX_GOTPCRELX); + GO(R_X86_64_NUM); #undef GO default: sprintf(buff, "type: 0x%x (unknown)", t); break; } diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index d34a1283..24d20bab 100755 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -477,7 +477,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_X86_64_64 @%p (%p) in %s\n", symname, p, *(void**)p, head->name); // return -1; } else { - printf_log(LOG_DUMP, "Apply %s R_X86_64_64 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(offs+*(uint32_t*)p)); + printf_log(LOG_DUMP, "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; @@ -521,12 +521,34 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cnt, Elf64_Rela *rela) { 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)]; int bind = ELF64_ST_BIND(sym->st_info); + uint64_t ndx = sym->st_shndx; const char* symname = SymName(head, sym); uint64_t *p = (uint64_t*)(rela[i].r_offset + head->delta); uintptr_t offs = 0; uintptr_t end = 0; + elfheader_t* h_tls = head; + if(bind==STB_LOCAL) { + offs = sym->st_value + head->delta; + end = offs + sym->st_size; + } else { + // this is probably very very wrong. A proprer way to get reloc need to be writen, 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(!offs && !end) { + h_tls = NULL; + if(local_maplib) + GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end); + if(!offs && !end) + GetGlobalSymbolStartEnd(maplib, symname, &offs, &end); + } + } uintptr_t globoffs, globend; uint64_t* globp; uintptr_t tmp = 0; @@ -602,7 +624,58 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c printf_log(LOG_DUMP, "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); *p += head->delta; } - break; default: + break; + case R_X86_64_64: + if (!offs) { + printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_X86_64_64 @%p (%p) in %s\n", symname, p, *(void**)p, head->name); +// return -1; + } else { + printf_log(LOG_DUMP, "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; + case R_X86_64_DTPMOD64: + // ID of module containing symbol + 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); + if(!h_tls) + h_tls = GetGlobalSymbolElf(maplib, symname); + } + offs = getElfIndex(my_context, h_tls); + } + if(p) { + printf_log(LOG_DUMP, "Apply %s %s @%p with sym=%s (%p -> %p)\n", "R_X86_64_DTPMOD64", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs); + *p = offs; + } else { + printf_log(LOG_NONE, "Warning, Symbol %s or Elf not found, but R_X86_64_DTPMOD64 Slot Offset is NULL \n", symname); + } + break; + case R_X86_64_DTPOFF64: + // Offset in TLS block + if (!offs && !end) { + 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 { + printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_X86_64_DTPOFF64 @%p (%p) in %s\n", symname, p, *(void**)p, head->name); + } +// return -1; + } else { + if(h_tls) + offs = sym->st_value; + if(p) { + int64_t tlsoffset = offs; // it's not an offset in elf memory + printf_log(LOG_DUMP, "Apply %s R_X86_64_DTPOFF64 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)tlsoffset, (void*)offs); + *p = tlsoffset; + } else { + printf_log(LOG_NONE, "Warning, Symbol %s found, but R_X86_64_DTPOFF64 Slot Offset is NULL \n", symname); + } + } + break; + default: printf_log(LOG_INFO, "Warning, don't know of to handle rela #%d %s on %s\n", i, DumpRelType(ELF64_R_TYPE(rela[i].r_info)), symname); } } @@ -909,8 +982,10 @@ void RunElfInit(elfheader_t* h, x64emu_t *emu) // and check init array now Elf64_Addr *addr = (Elf64_Addr*)(h->initarray + h->delta); for (int i=0; i<h->initarray_sz; ++i) { - printf_log(LOG_DEBUG, "Calling Init[%d] for %s @%p\n", i, ElfName(h), (void*)addr[i]); - RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 3, context->argc, context->argv, context->envv); + if(addr[i]) { + printf_log(LOG_DEBUG, "Calling Init[%d] for %s @%p\n", i, ElfName(h), (void*)addr[i]); + RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 3, context->argc, context->argv, context->envv); + } } h->init_done = 1; diff --git a/src/elfs/elfloader_private.h b/src/elfs/elfloader_private.h index 8e95175d..a02fcca3 100755 --- a/src/elfs/elfloader_private.h +++ b/src/elfs/elfloader_private.h @@ -86,23 +86,50 @@ struct elfheader_s { needed_libs_t *neededlibs; }; -#define R_X86_64_NONE 0 /* No reloc */ -#define R_X86_64_64 1 /* Direct 64 bit */ -#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ -#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ -#define R_X86_64_PLT32 4 /* 32 bit PLT address */ -#define R_X86_64_COPY 5 /* Copy symbol at runtime */ -#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ -#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ -#define R_X86_64_RELATIVE 8 /* Adjust by program base */ -#define R_X86_64_GOTPCREL 9 /* 32 bit signed pc relative offset to GOT */ -#define R_X86_64_32 10 /* Direct 32 bit zero extended */ -#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ -#define R_X86_64_16 12 /* Direct 16 bit zero extended */ -#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ -#define R_X86_64_8 14 /* Direct 8 bit sign extended */ -#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ -#define R_X86_64_PC64 24 /* Place relative 64-bit signed */ +#define R_X86_64_NONE 0 /* No reloc */ +#define R_X86_64_64 1 /* Direct 64 bit */ +#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ +#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ +#define R_X86_64_PLT32 4 /* 32 bit PLT address */ +#define R_X86_64_COPY 5 /* Copy symbol at runtime */ +#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ +#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ +#define R_X86_64_RELATIVE 8 /* Adjust by program base */ +#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative offset to GOT */ +#define R_X86_64_32 10 /* Direct 32 bit zero extended */ +#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ +#define R_X86_64_16 12 /* Direct 16 bit zero extended */ +#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ +#define R_X86_64_8 14 /* Direct 8 bit sign extended */ +#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */ +#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset to two GOT entries for GD symbol */ +#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset to two GOT entries for LD symbol */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset to GOT entry for IE symbol */ +#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ +#define R_X86_64_PC64 24 /* PC relative 64 bit */ +#define R_X86_64_GOTOFF64 25 /* 64 bit offset to GOT */ +#define R_X86_64_GOTPC32 26 /* 32 bit signed pc relative offset to GOT */ +#define R_X86_64_GOT64 27 /* 64-bit GOT entry offset */ +#define R_X86_64_GOTPCREL64 28 /* 64-bit PC relative offset to GOT entry */ +#define R_X86_64_GOTPC64 29 /* 64-bit PC relative offset to GOT */ +#define R_X86_64_GOTPLT64 30 /* like GOT64, says PLT entry needed */ +#define R_X86_64_PLTOFF64 31 /* 64-bit GOT relative offset to PLT entry */ +#define R_X86_64_SIZE32 32 /* Size of symbol plus 32-bit addend */ +#define R_X86_64_SIZE64 33 /* Size of symbol plus 64-bit addend */ +#define R_X86_64_GOTPC32_TLSDESC 34 /* GOT offset for TLS descriptor. */ +#define R_X86_64_TLSDESC_CALL 35 /* Marker for call through TLS descriptor. */ +#define R_X86_64_TLSDESC 36 /* TLS descriptor. */ +#define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */ +#define R_X86_64_RELATIVE64 38 /* 64-bit adjust by program base */ + /* 39 Reserved was R_X86_64_PC32_BND */ + /* 40 Reserved was R_X86_64_PLT32_BND */ +#define R_X86_64_GOTPCRELX 41 /* Load from 32 bit signed pc relative offset to GOT entry without REX prefix, relaxable. */ +#define R_X86_64_REX_GOTPCRELX 42 /* Load from 32 bit signed pc relative offset to GOT entry with REX prefix, relaxable. */ +#define R_X86_64_NUM 43 elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec); |