Usermode/ld-acess - Implemented R_836_COPY and R_X86_64_COPY
authorJohn Hodge <[email protected]>
Wed, 19 Oct 2011 04:29:12 +0000 (12:29 +0800)
committerJohn Hodge <[email protected]>
Wed, 19 Oct 2011 04:29:12 +0000 (12:29 +0800)
Usermode/Libraries/ld-acess.so_src/common.h
Usermode/Libraries/ld-acess.so_src/elf.c
Usermode/Libraries/ld-acess.so_src/lib.c
Usermode/Libraries/ld-acess.so_src/loadlib.c
Usermode/Libraries/ld-acess.so_src/main.c
Usermode/Libraries/ld-acess.so_src/pe.c

index d44008f..379efc1 100644 (file)
@@ -39,8 +39,8 @@ extern void   *DoRelocate(void *Base, char **envp, const char *Filename);
 // === Library/Symbol Manipulation ==
 extern void    *LoadLibrary(const char *Filename, const char *SearchDir, char **envp);
 extern void    AddLoaded(const char *File, void *base);
-extern void    *GetSymbol(const char *name);
-extern int     GetSymbolFromBase(void *base, const char *name, void **ret);
+extern void    *GetSymbol(const char *name, size_t *size);
+extern int     GetSymbolFromBase(void *base, const char *name, void **ret, size_t *size);
 
 // === Library Functions ===
 extern char    *strcpy(char *dest, const char *src);
@@ -48,6 +48,7 @@ extern char   *strcat(char *dest, const char *src);
 extern int     strcmp(const char *s1, const char *s2);
 extern int     strlen(const char *str);
 extern int     file_exists(const char *filename);
+extern void    *memcpy(void *dest, const void *src, size_t len);
 
 // === System Calls ===
 extern void    _exit(int retval);
@@ -60,9 +61,11 @@ extern int   open(const char *filename, int flags);
 extern int     close(int fd);
 
 // === ELF Loader ===
-extern int     ElfGetSymbol(void *Base, const char *name, void **ret);
+extern void    *ElfRelocate(void *Base, char **envp, const char *Filename);
+extern int     ElfGetSymbol(void *Base, const char *name, void **ret, size_t *Size);
 
 // === PE Loader ===
-extern int     PE_GetSymbol(void *Base, const char *Name, void **ret);
+extern void    *PE_Relocate(void *Base, char **envp, const char *Filename);
+extern int     PE_GetSymbol(void *Base, const char *Name, void **ret, size_t *Size);
 
 #endif
index f14205e..582c67a 100644 (file)
@@ -27,12 +27,12 @@ static const char   *csaR_NAMES[] = {"R_386_NONE", "R_386_32", "R_386_PC32", "R_38
 
 // === PROTOTYPES ===
 void   *ElfRelocate(void *Base, char **envp, const char *Filename);
- int   ElfGetSymbol(void *Base, const char *Name, void **Ret);
+ int   ElfGetSymbol(void *Base, const char *Name, void **Ret, size_t *Size);
 void   *Elf32Relocate(void *Base, char **envp, const char *Filename);
- int   Elf32GetSymbol(void *Base, const char *Name, void **Ret);
+ int   Elf32GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size);
 #ifdef SUPPORT_ELF64
 void   *Elf64Relocate(void *Base, char **envp, const char *Filename);
- int   Elf64GetSymbol(void *Base, const char *Name, void **Ret);
+ int   Elf64GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size);
 #endif
 Uint32 ElfHashString(const char *name);
 
@@ -62,17 +62,17 @@ void *ElfRelocate(void *Base, char **envp, const char *Filename)
 /**
  * \fn int ElfGetSymbol(Uint Base, const char *name, void **ret)
  */
-int ElfGetSymbol(void *Base, const char *Name, void **ret)
+int ElfGetSymbol(void *Base, const char *Name, void **ret, size_t *Size)
 {
        Elf32_Ehdr      *hdr = Base;
 
        switch(hdr->e_ident[4])
        {
        case ELFCLASS32:
-               return Elf32GetSymbol(Base, Name, ret);
+               return Elf32GetSymbol(Base, Name, ret, Size);
 #ifdef SUPPORT_ELF64
        case ELFCLASS64:
-               return Elf64GetSymbol(Base, Name, ret);
+               return Elf64GetSymbol(Base, Name, ret, Size);
 #endif
        default:
                SysDebug("ld-acess - ElfRelocate: Unknown file class %i", hdr->e_ident[4]);
@@ -155,26 +155,26 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
                        DEBUGS(" elf_relocate: DYNAMIC Symbol Table 0x%x (0x%x)",
                                dynamicTab[j].d_val, dynamicTab[j].d_val + iBaseDiff);
                        if(iBaseDiff != 0)      dynamicTab[j].d_val += iBaseDiff;
-                       dynsymtab = (void*)(dynamicTab[j].d_val);
+                       dynsymtab = (void*)(intptr_t)dynamicTab[j].d_val;
                        break;
                // --- String Table ---
                case DT_STRTAB:
                        DEBUGS(" elf_relocate: DYNAMIC String Table 0x%x (0x%x)",
                                dynamicTab[j].d_val, dynamicTab[j].d_val + iBaseDiff);
                        if(iBaseDiff != 0)      dynamicTab[j].d_val += iBaseDiff;
-                       dynstrtab = (void*)(dynamicTab[j].d_val);
+                       dynstrtab = (void*)(intptr_t)dynamicTab[j].d_val;
                        break;
                // --- Hash Table --
                case DT_HASH:
                        if(iBaseDiff != 0)      dynamicTab[j].d_val += iBaseDiff;
-                       iSymCount = ((Elf32_Word*)(dynamicTab[j].d_val))[1];
+                       iSymCount = ((Elf32_Word*)(intptr_t)dynamicTab[j].d_val)[1];
                        break;
                }
        }
 
        if(dynsymtab == NULL) {
                SysDebug("ld-acess.so - WARNING: No Dynamic Symbol table in %p, returning", hdr);
-               return (void *) hdr->entrypoint + iBaseDiff;
+               return (void *)(intptr_t) (hdr->entrypoint + iBaseDiff);
        }
 
        // === Add to loaded list (can be imported now) ===
@@ -244,7 +244,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
                {
                // Standard 32 Bit Relocation (S+A)
                case R_386_32:
-                       val = (intptr_t) GetSymbol( Sym );
+                       val = (intptr_t) GetSymbol(Sym, NULL);
                        DEBUGS(" elf_doRelocate: R_386_32 *0x%x += 0x%x('%s')",
                                        ptr, val, Sym);
                        *ptr = val + addend;
@@ -253,7 +253,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
                // 32 Bit Relocation wrt. Offset (S+A-P)
                case R_386_PC32:
                        DEBUGS(" elf_doRelocate: '%s'", Sym);
-                       val = (intptr_t) GetSymbol( Sym );
+                       val = (intptr_t) GetSymbol(Sym, NULL);
                        DEBUGS(" elf_doRelocate: R_386_PC32 *0x%x = 0x%x + 0x%x - 0x%x",
                                ptr, *ptr, val, (intptr_t)ptr );
                        *ptr = val + addend - (intptr_t)ptr;
@@ -264,7 +264,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
                case R_386_GLOB_DAT:
                case R_386_JMP_SLOT:
                        DEBUGS(" elf_doRelocate: '%s'", Sym);
-                       val = (intptr_t) GetSymbol( Sym );
+                       val = (intptr_t) GetSymbol( Sym, NULL );
                        DEBUGS(" elf_doRelocate: %s *0x%x = 0x%x", csaR_NAMES[type], ptr, val);
                        *ptr = val;
                        break;
@@ -274,7 +274,14 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
                        DEBUGS(" elf_doRelocate: R_386_RELATIVE *0x%x = 0x%x + 0x%x", ptr, iBaseDiff, addend);
                        *ptr = iBaseDiff + addend;
                        break;
-                       
+       
+               case R_386_COPY: {
+                       size_t  size;
+                       void    *src = GetSymbol(Sym, &size);
+                       DEBUGS(" elf_doRelocate_386: R_386_COPY (%p, %p, %i)", ptr, val, size);
+                       memcpy(ptr, src, size);
+                       break; }
+       
                default:
                        SysDebug("elf_doRelocate_386: Unknown relocation %i", type);
                        break;
@@ -289,7 +296,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
                // (S + A) | T
                case R_ARM_GLOB_DAT:
                case R_ARM_JUMP_SLOT:
-                       val = (intptr_t)GetSymbol(Sym);
+                       val = (intptr_t)GetSymbol(Sym, NULL);
                        *ptr = val + addend;
                        break;
                default:
@@ -375,10 +382,10 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
        }
        
        DEBUGS("ElfRelocate: RETURN 0x%x", hdr->entrypoint + iBaseDiff);
-       return (void*)hdr->entrypoint + iBaseDiff;
+       return (void*)(intptr_t)( hdr->entrypoint + iBaseDiff );
 }
 
-int Elf32GetSymbol(void *Base, const char *Name, void **ret)
+int Elf32GetSymbol(void *Base, const char *Name, void **ret, size_t *Size)
 {
        Elf32_Ehdr      *hdr = Base;
        Elf32_Sym       *symtab;
@@ -440,6 +447,7 @@ int Elf32GetSymbol(void *Base, const char *Name, void **ret)
        i = pBuckets[ iNameHash ];
        if(symtab[i].shndx != SHN_UNDEF && strcmp(dynstrtab + symtab[i].nameOfs, Name) == 0) {
                *ret = (void*) (intptr_t) symtab[ i ].value + iBaseDiff;
+               if(Size)        *Size = symtab[i].size;
                return 1;
        }
        
@@ -448,6 +456,7 @@ int Elf32GetSymbol(void *Base, const char *Name, void **ret)
                i = pChains[i];
                if(symtab[i].shndx != SHN_UNDEF && strcmp(dynstrtab + symtab[ i ].nameOfs, Name) == 0) {
                        *ret = (void*)(intptr_t)symtab[ i ].value + iBaseDiff;
+                       if(Size)        *Size = symtab[i].size;
                        return 1;
                }
        }
@@ -606,15 +615,18 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename)
                case R_X86_64_NONE:
                        break;
                case R_X86_64_64:
-                       *(uint64_t*)ptr = (uint64_t)GetSymbol(symname) + addend;
-                       break;
-               case R_X86_64_COPY:
+                       *(uint64_t*)ptr = (uint64_t)GetSymbol(symname, NULL) + addend;
                        break;
+               case R_X86_64_COPY: {
+                       size_t  size;
+                       void    *sym = GetSymbol(symname, &size);
+                       memcpy(ptr, sym, size);
+                       } break;
                case R_X86_64_GLOB_DAT:
-                       *(uint64_t*)ptr = (uint64_t)GetSymbol(symname);
+                       *(uint64_t*)ptr = (uint64_t)GetSymbol(symname, NULL);
                        break;
                case R_X86_64_JUMP_SLOT:
-                       *(uint64_t*)ptr = (uint64_t)GetSymbol(symname);
+                       *(uint64_t*)ptr = (uint64_t)GetSymbol(symname, NULL);
                        break;
                case R_X86_64_RELATIVE:
                        *(uint64_t*)ptr = (intptr_t)Base + addend;
@@ -671,7 +683,7 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename)
        return (void *)(hdr->e_entry + baseDiff);
 }
 
-int Elf64GetSymbol(void *Base, const char *Name, void **Ret)
+int Elf64GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size)
 {
        Elf64_Ehdr      *hdr = Base;
        Elf64_Sym       *symtab;
@@ -744,6 +756,7 @@ int Elf64GetSymbol(void *Base, const char *Name, void **Ret)
        i = pBuckets[ iNameHash ];
        if(symtab[i].st_shndx != SHN_UNDEF && strcmp(dynstrtab + symtab[i].st_name, Name) == 0) {
                *Ret = (void*) (intptr_t) symtab[i].st_value + iBaseDiff;
+               if(Size)        *Size = symtab[i].st_size;
                DEBUGS("%s = %p", Name, *Ret);
                return 1;
        }
@@ -753,6 +766,7 @@ int Elf64GetSymbol(void *Base, const char *Name, void **Ret)
                i = pChains[i];
                if(symtab[i].st_shndx != SHN_UNDEF && strcmp(dynstrtab + symtab[i].st_name, Name) == 0) {
                        *Ret = (void*)(intptr_t)symtab[i].st_value + iBaseDiff;
+                       if(Size)        *Size = symtab[i].st_size;
                        DEBUGS("%s = %p", Name, *Ret);
                        return 1;
                }
index 7c8005b..a3192bc 100644 (file)
@@ -58,6 +58,13 @@ int memcmp(const void *p1, const void *p2, int len)
        return 0;
 }
 
+void *memcpy(void *dest, const void *src, size_t len)
+{
+       uint8_t *d=dest, *s=src;
+       while(len--)    *d++ = *s++;
+       return dest;
+}
+
 /**
  * \fn int file_exists(char *filename)
  * \brief Checks if a file exists
index b6637c2..eec3dee 100644 (file)
@@ -15,7 +15,7 @@
 
 // === PROTOTYPES ===
 void   *IsFileLoaded(const char *file);
- int   GetSymbolFromBase(void *base, const char *name, void **ret);
+ int   GetSymbolFromBase(void *base, const char *name, void **ret, size_t *size);
 
 // === IMPORTS ===
 extern const struct {
@@ -197,7 +197,7 @@ void Unload(void *Base)
  \fn Uint GetSymbol(const char *name)
  \brief Gets a symbol value from a loaded library
 */
-void *GetSymbol(const char *name)
+void *GetSymbol(const char *name, size_t *Size)
 {
         int    i;
        void    *ret;
@@ -216,7 +216,7 @@ void *GetSymbol(const char *name)
                
                //SysDebug(" GetSymbol: Trying 0x%x, '%s'",
                //      gLoadedLibraries[i].Base, gLoadedLibraries[i].Name);
-               if(GetSymbolFromBase(gLoadedLibraries[i].Base, name, &ret))     return ret;
+               if(GetSymbolFromBase(gLoadedLibraries[i].Base, name, &ret, Size))       return ret;
        }
        SysDebug("GetSymbol: === Symbol '%s' not found ===", name);
        return 0;
@@ -226,13 +226,13 @@ void *GetSymbol(const char *name)
  \fn int GetSymbolFromBase(Uint base, char *name, Uint *ret)
  \breif Gets a symbol from a specified library
 */
-int GetSymbolFromBase(void *base, const char *name, void **ret)
+int GetSymbolFromBase(void *base, const char *name, void **ret, size_t *Size)
 {
        uint8_t *hdr = base;
        if(hdr[0] == 0x7F && hdr[1] == 'E' && hdr[2] == 'L' && hdr[3] == 'F')
-               return ElfGetSymbol(base, name, ret);
+               return ElfGetSymbol(base, name, ret, Size);
        if(hdr[0] == 'M' && hdr[1] == 'Z')
-               return PE_GetSymbol(base, name, ret);
+               return PE_GetSymbol(base, name, ret, Size);
        SysDebug("Unknown type at %p (%02x %02x %02x %02x)", base,
                hdr[0], hdr[1], hdr[2], hdr[3]);
        return 0;
index 6ccdc0c..ff715bb 100644 (file)
@@ -9,8 +9,6 @@
 // === PROTOTYPES ===\r
 void   *DoRelocate(void *base, char **envp, const char *Filename);\r
  int   CallUser(void *Entry, void *SP);\r
-void   *ElfRelocate(void *Base, char **envp, const char *Filename);\r
-void   *PE_Relocate(void *Base, char **envp, const char *Filename);\r
 \r
 // === Imports ===\r
 extern char    gLinkedBase[];\r
index d567ed1..057345c 100644 (file)
 #endif\r
 \r
 // === PROTOTYPES ===\r
- int   PE_Relocate(void *Base, char **envp, char *Filename);\r
+void   *PE_Relocate(void *Base, char **envp, const char *Filename);\r
 char   *PE_int_GetTrueFile(char *file);\r
  int   PE_int_GetForwardSymbol(char *Fwd, void **Value);\r
 \r
 // === CODE ===\r
-int PE_Relocate(void *Base, char *envp[], char *Filename)\r
+void *PE_Relocate(void *Base, char **envp, const char *Filename)\r
 {\r
        tPE_DOS_HEADER          *dosHdr = Base;\r
        tPE_IMAGE_HEADERS       *peHeaders;\r
@@ -67,7 +67,8 @@ int PE_Relocate(void *Base, char *envp[], char *Filename)
                                void    *symPtr = 0;\r
                                name = (void*)( iBase + importTab[j] );\r
                                DEBUGS(" PE_Relocate: Import Name '%s', Hint 0x%x\n", name->Name, name->Hint);\r
-                               if( GetSymbolFromBase(pLibBase, name->Name, symPtr) == 0 ) {\r
+                               if( GetSymbolFromBase(pLibBase, name->Name, symPtr, NULL) == 0 )\r
+                               {\r
                                        SysDebug("Unable to find symbol '%s' in library '%s'\n", name->Name, impDir[i].DLLName);\r
                                        return 0;\r
                                }\r
@@ -85,13 +86,13 @@ int PE_Relocate(void *Base, char *envp[], char *Filename)
        \r
        DEBUGS("PE_Relocate: RETURN 0x%x\n", iBase + peHeaders->OptHeader.EntryPoint);\r
        \r
-       return iBase + peHeaders->OptHeader.EntryPoint;\r
+       return (void*)( iBase + peHeaders->OptHeader.EntryPoint );\r
 }\r
 \r
 /**\r
  * \fn int PE_GetSymbol(Uint Base, const char *Name, Uint *Ret)\r
  */\r
-int PE_GetSymbol(void *Base, const char *Name, void **Ret)\r
+int PE_GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size)\r
 {\r
        tPE_DOS_HEADER          *dosHdr = Base;\r
        tPE_IMAGE_HEADERS       *peHeaders;\r
@@ -129,6 +130,7 @@ int PE_GetSymbol(void *Base, const char *Name, void **Ret)
                                return PE_int_GetForwardSymbol(fwd, Ret);\r
                        }\r
                        *Ret = (void*)retVal;\r
+                       if(Size)        *Size = 0;\r
                        return 1;\r
                }\r
        }\r
@@ -174,9 +176,10 @@ int PE_int_GetForwardSymbol(char *Fwd, void **Value)
        DEBUGS(" PE_int_GetForwardSymbol: Get '%s' from '%s'\n", sym, libname);\r
        \r
        libbase = LoadLibrary(libname, DLL_BASE_PATH, NULL);\r
-       ret = GetSymbolFromBase(libbase, sym, Value);\r
+       ret = GetSymbolFromBase(libbase, sym, Value, NULL);\r
        if(!ret) {\r
                SysDebug(" PE_int_GetForwardSymbol: Unable to find '%s' in '%s'\n", sym, libname);\r
+               return 0;\r
        }\r
        Fwd[i] = '.';\r
        return ret;\r

UCC git Repository :: git.ucc.asn.au