AcessNative - Work on the ELF Loader
[tpg/acess2.git] / AcessNative / ld-acess.so_src / binary.c
index 8378c6c..7f97edd 100644 (file)
@@ -1,9 +1,221 @@
 /*
  * AcessNative
  */
+#include "common.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#define LIBRARY_PATH   "../Usermode/Output/i386/Libs"
+
+// === TYPES ===
+typedef struct sBinary {
+       struct sBinary  *Next;
+       void    *Base;
+        int    Ready;
+       tBinFmt *Format;
+       char    Path[];
+}      tBinary;
+
+// === IMPORTS ===
+extern void    *Elf_Load(FILE *FP);
+extern uintptr_t       Elf_Relocate(void *Base);
+extern int     Elf_GetSymbol(void *Base, char *Name, uintptr_t *ret);
+extern int     ciNumBuiltinSymbols;
+extern tSym    caBuiltinSymbols[];
+
+// === PROTOTYPES ===
+void   Binary_AddToList(const char *Filename, void *Base, tBinFmt *Format);
+
+// === GLOBALS ===
+tBinFmt        gElf_FormatDef = {
+//     .Mask = 0xFFFFFFFF,
+//     .Magic = "\x7F""ELF",
+       .Name = "ELF32",
+       .Load = Elf_Load,
+       .Relocate = Elf_Relocate,
+       .GetSymbol = Elf_GetSymbol
+       };
+tBinary        *gLoadedBinaries;
 
 // === CODE ===
-int Binary_GetSymbol(const char *SymbolName, intptr_t *Value)
+char *Binary_LocateLibrary(const char *Name)
+{
+       char    *envPath = getenv("ACESS_LIBRARY_PATH");
+        int    nameLen = strlen(Name);
+       FILE    *fp;
+       
+       // Try the environment ACESS_LIBRARY_PATH
+       if( envPath && envPath[0] != '\0' )
+       {
+                int    len = strlen(envPath)+1+nameLen+1;
+               char    tmp[len];
+
+               strcpy(tmp, envPath);
+               strcat(tmp, "/");
+               strcat(tmp, Name);
+               
+               fp = fopen(tmp, "r");
+               if(fp) {
+                       fclose(fp);
+                       return strdup(tmp);
+               }
+       }               
+
+       {
+                int    len = strlen(LIBRARY_PATH)+1+nameLen+1;
+               char    tmp[len];
+
+               strcpy(tmp, LIBRARY_PATH);
+               strcat(tmp, "/");
+               strcat(tmp, Name);
+               
+               printf("Binary_LocateLibrary: tmp = '%s'\n", tmp);
+
+               fp = fopen(tmp, "r");
+               if(fp) {
+                       fclose(fp);
+                       return strdup(tmp);
+               }
+       }               
+
+       fprintf(stderr, "Unable to locate library '%s'\n", Name);
+
+       return NULL;
+}
+
+void *Binary_LoadLibrary(const char *Name)
+{
+       char    *path;
+       void    *ret;
+        int    (*entry)(int,char*[],char**) = NULL;
+
+       // Find File
+       path = Binary_LocateLibrary(Name);
+       printf("Binary_LoadLibrary: path = '%s'\n", path);
+       if( !path ) {
+               return NULL;
+       }
+
+       ret = Binary_Load(path, (uintptr_t*)&entry);
+       free(path);
+       
+       printf("Binary_LoadLibrary: ret = %p, entry = %p\n", ret, entry);
+       if( entry ) {
+               char    *argv[] = {NULL};
+               entry(0, argv, NULL);
+       }
+
+       return ret;
+}
+
+void *Binary_Load(const char *Filename, uintptr_t *EntryPoint)
 {
+       FILE    *fp;
+       uint32_t        dword;
+       void    *ret;
+       uintptr_t       entry = 0;
+       tBinFmt *fmt;
+
+       {
+               tBinary *bin;
+               for(bin = gLoadedBinaries; bin; bin = bin->Next)
+               {
+                       if( strcmp(Filename, bin->Path) == 0 ) {
+                               return bin->Base;
+                       }
+               }
+       }
+
+       fp = fopen(Filename, "r");
+       if( !fp ) {
+               // TODO: Handle libary directories
+               perror("Opening binary");
+               return NULL;
+       }
+
+       fread(&dword, 1, 4, fp);
+       fseek(fp, 0, SEEK_SET);
+       printf("dword = %08x\n", dword);
+       
+       if( memcmp(&dword, "\x7F""ELF", 4) == 0 ) {
+               fmt = &gElf_FormatDef;
+       }
+       else {
+               fclose(fp);
+               return NULL;
+       }
+
+       ret = fmt->Load(fp);
+       printf("fmt->Load(%p): %p\n", fp, ret);
+       if( !ret ) {
+               fclose(fp);
+               return NULL;
+       }
+       
+       Binary_AddToList(Filename, ret, fmt);
+
+       entry = fmt->Relocate(ret);
+       printf("fmt->Relocate(%p): %p\n", ret, (void*)entry);
+       if( !entry ) {
+               // TODO: Clean up
+               return NULL;
+       }
+       
+       if( EntryPoint )
+               *EntryPoint = entry;
+
+       fclose(fp);
+
+       Binary_SetReadyToUse(ret);
+
+       return ret;
+}
+
+void Binary_AddToList(const char *Filename, void *Base, tBinFmt *Format)
+{
+       tBinary *bin = malloc(sizeof(tBinary) + strlen(Filename) + 1);
+       bin->Base = Base;
+       bin->Format = Format;
+       strcpy(bin->Path, Filename);
+       bin->Ready = 0;
+       
+       bin->Next = gLoadedBinaries;
+       gLoadedBinaries = bin;
+}
+
+void Binary_SetReadyToUse(void *Base)
+{
+       tBinary *bin;
+       for(bin = gLoadedBinaries; bin; bin = bin->Next)
+       {
+               if( bin->Base != Base ) continue ;
+               bin->Ready = 1;
+       }
+}
+
+int Binary_GetSymbol(const char *SymbolName, uintptr_t *Value)
+{
+        int    i;
+       tBinary *bin;
+       
+       // TODO: Search list of loaded binaries
+       for(bin = gLoadedBinaries; bin; bin = bin->Next)
+       {
+               if( !bin->Ready )       continue;
+               printf("Binary_GetSymbol: bin = %p{%p, %s}\n", bin, bin->Base, bin->Path);
+               if( bin->Format->GetSymbol(bin->Base, (char*)SymbolName, Value) )
+                       return 1;
+       }
+
+       // Search builtins
+       for( i = 0; i < ciNumBuiltinSymbols; i ++ )
+       {
+               if( strcmp(caBuiltinSymbols[i].Name, SymbolName) == 0 ) {
+                       *Value = (uintptr_t)caBuiltinSymbols[i].Value;
+                       return 1;
+               }
+       }
+
        return 0;
 }

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