AcessNative - Work on the ELF Loader
[tpg/acess2.git] / AcessNative / ld-acess.so_src / binary.c
1 /*
2  * AcessNative
3  */
4 #include "common.h"
5 #include <stdint.h>
6 #include <stdio.h>
7 #include <string.h>
8
9 #define LIBRARY_PATH    "../Usermode/Output/i386/Libs"
10
11 // === TYPES ===
12 typedef struct sBinary {
13         struct sBinary  *Next;
14         void    *Base;
15          int    Ready;
16         tBinFmt *Format;
17         char    Path[];
18 }       tBinary;
19
20 // === IMPORTS ===
21 extern void     *Elf_Load(FILE *FP);
22 extern uintptr_t        Elf_Relocate(void *Base);
23 extern int      Elf_GetSymbol(void *Base, char *Name, uintptr_t *ret);
24 extern int      ciNumBuiltinSymbols;
25 extern tSym     caBuiltinSymbols[];
26
27 // === PROTOTYPES ===
28 void    Binary_AddToList(const char *Filename, void *Base, tBinFmt *Format);
29
30 // === GLOBALS ===
31 tBinFmt gElf_FormatDef = {
32 //      .Mask = 0xFFFFFFFF,
33 //      .Magic = "\x7F""ELF",
34         .Name = "ELF32",
35         .Load = Elf_Load,
36         .Relocate = Elf_Relocate,
37         .GetSymbol = Elf_GetSymbol
38         };
39 tBinary *gLoadedBinaries;
40
41 // === CODE ===
42 char *Binary_LocateLibrary(const char *Name)
43 {
44         char    *envPath = getenv("ACESS_LIBRARY_PATH");
45          int    nameLen = strlen(Name);
46         FILE    *fp;
47         
48         // Try the environment ACESS_LIBRARY_PATH
49         if( envPath && envPath[0] != '\0' )
50         {
51                  int    len = strlen(envPath)+1+nameLen+1;
52                 char    tmp[len];
53
54                 strcpy(tmp, envPath);
55                 strcat(tmp, "/");
56                 strcat(tmp, Name);
57                 
58                 fp = fopen(tmp, "r");
59                 if(fp) {
60                         fclose(fp);
61                         return strdup(tmp);
62                 }
63         }               
64
65         {
66                  int    len = strlen(LIBRARY_PATH)+1+nameLen+1;
67                 char    tmp[len];
68
69                 strcpy(tmp, LIBRARY_PATH);
70                 strcat(tmp, "/");
71                 strcat(tmp, Name);
72                 
73                 printf("Binary_LocateLibrary: tmp = '%s'\n", tmp);
74
75                 fp = fopen(tmp, "r");
76                 if(fp) {
77                         fclose(fp);
78                         return strdup(tmp);
79                 }
80         }               
81
82         fprintf(stderr, "Unable to locate library '%s'\n", Name);
83
84         return NULL;
85 }
86
87 void *Binary_LoadLibrary(const char *Name)
88 {
89         char    *path;
90         void    *ret;
91          int    (*entry)(int,char*[],char**) = NULL;
92
93         // Find File
94         path = Binary_LocateLibrary(Name);
95         printf("Binary_LoadLibrary: path = '%s'\n", path);
96         if( !path ) {
97                 return NULL;
98         }
99
100         ret = Binary_Load(path, (uintptr_t*)&entry);
101         free(path);
102         
103         printf("Binary_LoadLibrary: ret = %p, entry = %p\n", ret, entry);
104         if( entry ) {
105                 char    *argv[] = {NULL};
106                 entry(0, argv, NULL);
107         }
108
109         return ret;
110 }
111
112 void *Binary_Load(const char *Filename, uintptr_t *EntryPoint)
113 {
114         FILE    *fp;
115         uint32_t        dword;
116         void    *ret;
117         uintptr_t       entry = 0;
118         tBinFmt *fmt;
119
120         {
121                 tBinary *bin;
122                 for(bin = gLoadedBinaries; bin; bin = bin->Next)
123                 {
124                         if( strcmp(Filename, bin->Path) == 0 ) {
125                                 return bin->Base;
126                         }
127                 }
128         }
129
130         fp = fopen(Filename, "r");
131         if( !fp ) {
132                 // TODO: Handle libary directories
133                 perror("Opening binary");
134                 return NULL;
135         }
136
137         fread(&dword, 1, 4, fp);
138         fseek(fp, 0, SEEK_SET);
139         printf("dword = %08x\n", dword);
140         
141         if( memcmp(&dword, "\x7F""ELF", 4) == 0 ) {
142                 fmt = &gElf_FormatDef;
143         }
144         else {
145                 fclose(fp);
146                 return NULL;
147         }
148
149         ret = fmt->Load(fp);
150         printf("fmt->Load(%p): %p\n", fp, ret);
151         if( !ret ) {
152                 fclose(fp);
153                 return NULL;
154         }
155         
156         Binary_AddToList(Filename, ret, fmt);
157
158         entry = fmt->Relocate(ret);
159         printf("fmt->Relocate(%p): %p\n", ret, (void*)entry);
160         if( !entry ) {
161                 // TODO: Clean up
162                 return NULL;
163         }
164         
165         if( EntryPoint )
166                 *EntryPoint = entry;
167
168         fclose(fp);
169
170         Binary_SetReadyToUse(ret);
171
172         return ret;
173 }
174
175 void Binary_AddToList(const char *Filename, void *Base, tBinFmt *Format)
176 {
177         tBinary *bin = malloc(sizeof(tBinary) + strlen(Filename) + 1);
178         bin->Base = Base;
179         bin->Format = Format;
180         strcpy(bin->Path, Filename);
181         bin->Ready = 0;
182         
183         bin->Next = gLoadedBinaries;
184         gLoadedBinaries = bin;
185 }
186
187 void Binary_SetReadyToUse(void *Base)
188 {
189         tBinary *bin;
190         for(bin = gLoadedBinaries; bin; bin = bin->Next)
191         {
192                 if( bin->Base != Base ) continue ;
193                 bin->Ready = 1;
194         }
195 }
196
197 int Binary_GetSymbol(const char *SymbolName, uintptr_t *Value)
198 {
199          int    i;
200         tBinary *bin;
201         
202         // TODO: Search list of loaded binaries
203         for(bin = gLoadedBinaries; bin; bin = bin->Next)
204         {
205                 if( !bin->Ready )       continue;
206                 printf("Binary_GetSymbol: bin = %p{%p, %s}\n", bin, bin->Base, bin->Path);
207                 if( bin->Format->GetSymbol(bin->Base, (char*)SymbolName, Value) )
208                         return 1;
209         }
210
211         // Search builtins
212         for( i = 0; i < ciNumBuiltinSymbols; i ++ )
213         {
214                 if( strcmp(caBuiltinSymbols[i].Name, SymbolName) == 0 ) {
215                         *Value = (uintptr_t)caBuiltinSymbols[i].Value;
216                         return 1;
217                 }
218         }
219
220         return 0;
221 }

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