Lots of work on the AcessNative kernel
[tpg/acess2.git] / AcessNative / ld-acess_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         if( strcmp(Name, "libld-acess.so") == 0 ) {
49                 return strdup("libld-acess.so");
50         }
51         
52         // Try the environment ACESS_LIBRARY_PATH
53         if( envPath && envPath[0] != '\0' )
54         {
55                  int    len = strlen(envPath)+1+nameLen+1;
56                 char    tmp[len];
57
58                 strcpy(tmp, envPath);
59                 strcat(tmp, "/");
60                 strcat(tmp, Name);
61                 
62                 fp = fopen(tmp, "r");
63                 if(fp) {
64                         fclose(fp);
65                         return strdup(tmp);
66                 }
67         }               
68
69         {
70                  int    len = strlen(LIBRARY_PATH)+1+nameLen+1;
71                 char    tmp[len];
72
73                 strcpy(tmp, LIBRARY_PATH);
74                 strcat(tmp, "/");
75                 strcat(tmp, Name);
76                 
77                 printf("Binary_LocateLibrary: tmp = '%s'\n", tmp);
78
79                 fp = fopen(tmp, "r");
80                 if(fp) {
81                         fclose(fp);
82                         return strdup(tmp);
83                 }
84         }               
85
86         fprintf(stderr, "Unable to locate library '%s'\n", Name);
87
88         return NULL;
89 }
90
91 void *Binary_LoadLibrary(const char *Name)
92 {
93         char    *path;
94         void    *ret;
95          int    (*entry)(int,char*[],char**) = NULL;
96
97         // Find File
98         path = Binary_LocateLibrary(Name);
99         printf("Binary_LoadLibrary: path = '%s'\n", path);
100         if( !path ) {
101                 return NULL;
102         }
103
104         ret = Binary_Load(path, (uintptr_t*)&entry);
105         free(path);
106         
107         printf("Binary_LoadLibrary: ret = %p, entry = %p\n", ret, entry);
108         if( entry ) {
109                 char    *argv[] = {NULL};
110                 printf("Calling '%s' entry point %p\n", Name, entry);
111                 entry(0, argv, NULL);
112         }
113
114         return ret;
115 }
116
117 void *Binary_Load(const char *Filename, uintptr_t *EntryPoint)
118 {
119         FILE    *fp;
120         uint32_t        dword;
121         void    *ret;
122         uintptr_t       entry = 0;
123         tBinFmt *fmt;
124
125         // Ignore loading ld-acess
126         if( strcmp(Filename, "libld-acess.so") == 0 ) {
127                 *EntryPoint = 0;
128                 return (void*)-1;
129         }
130
131         {
132                 tBinary *bin;
133                 for(bin = gLoadedBinaries; bin; bin = bin->Next)
134                 {
135                         if( strcmp(Filename, bin->Path) == 0 ) {
136                                 return bin->Base;
137                         }
138                 }
139         }
140
141         fp = fopen(Filename, "r");
142         if( !fp ) {
143                 // TODO: Handle libary directories
144                 perror("Opening binary");
145                 return NULL;
146         }
147
148         fread(&dword, 1, 4, fp);
149         fseek(fp, 0, SEEK_SET);
150         
151         if( memcmp(&dword, "\x7F""ELF", 4) == 0 ) {
152                 fmt = &gElf_FormatDef;
153         }
154         else {
155                 fclose(fp);
156                 return NULL;
157         }
158         
159         printf("fmt->Load(%p)...\n", fp);
160         ret = fmt->Load(fp);
161         printf("fmt->Load(%p): %p\n", fp, ret);
162         if( !ret ) {
163                 fclose(fp);
164                 return NULL;
165         }
166         
167         Binary_AddToList(Filename, ret, fmt);
168
169         entry = fmt->Relocate(ret);
170         printf("fmt->Relocate(%p): %p\n", ret, (void*)entry);
171         if( !entry ) {
172                 // TODO: Clean up
173                 return NULL;
174         }
175         
176         if( EntryPoint )
177                 *EntryPoint = entry;
178
179         fclose(fp);
180
181         Binary_SetReadyToUse(ret);
182
183         return ret;
184 }
185
186 void Binary_AddToList(const char *Filename, void *Base, tBinFmt *Format)
187 {
188         tBinary *bin = malloc(sizeof(tBinary) + strlen(Filename) + 1);
189         bin->Base = Base;
190         bin->Format = Format;
191         strcpy(bin->Path, Filename);
192         bin->Ready = 0;
193         
194         bin->Next = gLoadedBinaries;
195         gLoadedBinaries = bin;
196 }
197
198 void Binary_SetReadyToUse(void *Base)
199 {
200         tBinary *bin;
201         for(bin = gLoadedBinaries; bin; bin = bin->Next)
202         {
203                 if( bin->Base != Base ) continue ;
204                 bin->Ready = 1;
205         }
206 }
207
208 int Binary_GetSymbol(const char *SymbolName, uintptr_t *Value)
209 {
210          int    i;
211         tBinary *bin;
212         
213         //printf("Binary_GetSymbol: (SymbolName='%s', Value=%p)\n",
214         //      SymbolName, Value);
215
216         // Search builtins
217         // - Placed first to override smartarses that define their own versions
218         //   of system calls
219         for( i = 0; i < ciNumBuiltinSymbols; i ++ )
220         {
221                 if( strcmp(caBuiltinSymbols[i].Name, SymbolName) == 0 ) {
222                         *Value = (uintptr_t)caBuiltinSymbols[i].Value;
223                         return 1;
224                 }
225         }
226         
227         // TODO: Search list of loaded binaries
228         for(bin = gLoadedBinaries; bin; bin = bin->Next)
229         {
230                 if( !bin->Ready )       continue;
231                 //printf(" Binary_GetSymbol: bin = %p{%p, %s}\n", bin, bin->Base, bin->Path);
232                 if( bin->Format->GetSymbol(bin->Base, (char*)SymbolName, Value) )
233                         return 1;
234         }
235
236         //printf("Binary_GetSymbol: RETURN 0, not found\n");
237         
238         return 0;
239 }

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