about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-06 10:02:14 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-06 10:02:14 +0100
commitbee17de8a4f1a6056158807df5b7fc9c1f914b9b (patch)
tree66c3c01a1ea9344335ce612115085f9fbb6599b5 /src
parent75468d0c4c40c2ee2926c75d0ef0472cde982c23 (diff)
downloadbox64-bee17de8a4f1a6056158807df5b7fc9c1f914b9b.tar.gz
box64-bee17de8a4f1a6056158807df5b7fc9c1f914b9b.zip
More work on elfloader and relocation (and tls)
Diffstat (limited to 'src')
-rwxr-xr-xsrc/elfs/elfload_dump.c25
-rwxr-xr-xsrc/elfs/elfloader.c83
-rwxr-xr-xsrc/elfs/elfloader_private.h61
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);