AcessNative - Fix compile errors from API changes (and from compiler upgrade)
[tpg/acess2.git] / AcessNative / ld-acess_src / binary.c
1 /*
2  * AcessNative Dynamic Linker
3  * - By John Hodge (thePowersGang)
4  * 
5  * binary.c
6  * - Provides binary loading and type abstraction
7  */
8 #define DEBUG   0
9 #define _POSIX_C_SOURCE 200809L // needed for strdup
10 #include "common.h"
11 #include <stdint.h>
12 #include <stdio.h>
13 #include <string.h>
14
15 #define LIBRARY_PATH    "$$$$../Usermode/Output/x86_64/Libs"
16
17 // === TYPES ===
18 typedef struct sBinary {
19         struct sBinary  *Next;
20         void    *Base;
21          int    Ready;
22         tBinFmt *Format;
23         char    Path[];
24 }       tBinary;
25
26 // === IMPORTS ===
27 extern void     *Elf_Load(int fd);
28 extern uintptr_t        ElfRelocate(void *Base);
29 extern int      ElfGetSymbol(void *Base, char *Name, uintptr_t *ret, size_t *size);
30 extern int      ciNumBuiltinSymbols;
31 extern tSym     caBuiltinSymbols[];
32 extern char     **gEnvP;
33
34 // === PROTOTYPES ===
35 void    Binary_AddToList(const char *Filename, void *Base, tBinFmt *Format);
36
37 // === GLOBALS ===
38 tBinFmt gElf_FormatDef = {
39 //      .Mask = 0xFFFFFFFF,
40 //      .Magic = "\x7F""ELF",
41         .Name = "ELF32",
42         .Load = Elf_Load,
43         .Relocate = ElfRelocate,
44         .GetSymbol = ElfGetSymbol
45         };
46 tBinary *gLoadedBinaries;
47
48 // === CODE ===
49 char *Binary_LocateLibrary(const char *Name)
50 {
51         char    *envPath = getenv("ACESS_LIBRARY_PATH");
52          int    nameLen = strlen(Name);
53          int    fd;
54         
55         if( strcmp(Name, "libld-acess.so") == 0 ) {
56                 return strdup("libld-acess.so");
57         }
58         
59         // Try the environment ACESS_LIBRARY_PATH
60         if( envPath && envPath[0] != '\0' )
61         {
62                  int    len = strlen(envPath)+1+nameLen+1;
63                 char    tmp[len];
64
65                 strcpy(tmp, envPath);
66                 strcat(tmp, "/");
67                 strcat(tmp, Name);
68                 
69                 fd = acess__SysOpen(tmp, 4);    // OPENFLAG_EXEC
70                 if(fd != -1) {
71                         acess__SysClose(fd);
72                         return strdup(tmp);
73                 }
74         }               
75
76         {
77                  int    len = strlen(LIBRARY_PATH)+1+nameLen+1;
78                 char    tmp[len];
79
80                 strcpy(tmp, LIBRARY_PATH);
81                 strcat(tmp, "/");
82                 strcat(tmp, Name);
83                 
84                 #if DEBUG
85                 printf("Binary_LocateLibrary: tmp = '%s'\n", tmp);
86                 #endif
87
88                 fd = acess__SysOpen(tmp, 4);    // OPENFLAG_EXEC
89                 if(fd != -1) {
90                         acess__SysClose(fd);
91                         return strdup(tmp);
92                 }
93         }               
94
95         #if DEBUG
96         fprintf(stderr, "Unable to locate library '%s'\n", Name);
97         #endif
98
99         return NULL;
100 }
101
102 void *Binary_LoadLibrary(const char *Name)
103 {
104         char    *path;
105         void    *ret;
106          int    (*entry)(void *,int,char*[],char**) = NULL;
107
108         // Find File
109         path = Binary_LocateLibrary(Name);
110         #if DEBUG
111         printf("Binary_LoadLibrary: path = '%s'\n", path);
112         #endif
113         if( !path ) {
114                 return NULL;
115         }
116
117         ret = Binary_Load(path, (uintptr_t*)&entry);
118         if( ret != (void*)-1 )
119                 Debug("LOADED '%s' to %p (Entry=%p)", path, ret, entry);
120         free(path);
121         
122         #if DEBUG
123         printf("Binary_LoadLibrary: ret = %p, entry = %p\n", ret, entry);
124         #endif
125         if( entry ) {
126                 char    *argv[] = {NULL};
127                 #if DEBUG
128                 printf("Calling '%s' entry point %p\n", Name, entry);
129                 #endif
130                 entry(ret, 0, argv, gEnvP);
131         }
132
133         return ret;
134 }
135
136 void *Binary_Load(const char *Filename, uintptr_t *EntryPoint)
137 {
138          int    fd;
139         uint32_t        dword = 0xFA17FA17;
140         void    *ret;
141         uintptr_t       entry = 0;
142         tBinFmt *fmt;
143
144         // Ignore loading ld-acess
145         if( strcmp(Filename, "libld-acess.so") == 0 ) {
146                 *EntryPoint = 0;
147                 return (void*)-1;
148         }
149
150         {
151                 tBinary *bin;
152                 for(bin = gLoadedBinaries; bin; bin = bin->Next)
153                 {
154                         if( strcmp(Filename, bin->Path) == 0 ) {
155                                 return bin->Base;
156                         }
157                 }
158         }
159
160         fd = acess__SysOpen(Filename, 2|1);     // Execute and Read
161         if( fd == -1 ) {
162                 // TODO: Handle libary directories
163                 perror("Opening binary");
164                 return NULL;
165         }
166
167         acess__SysRead(fd, &dword, 4);
168         acess__SysSeek(fd, 0, ACESS_SEEK_SET);
169         
170         if( memcmp(&dword, "\x7F""ELF", 4) == 0 ) {
171                 fmt = &gElf_FormatDef;
172         }
173         else {
174                 fprintf(stderr, "Unknown executable format (0x%08x)\n", dword);
175                 acess__SysClose(fd);
176                 return NULL;
177         }
178         
179         #if DEBUG
180         printf("fmt->Load(0x%x)...\n", fd);
181         #endif
182         ret = fmt->Load(fd);
183         acess__SysClose(fd);
184         #if DEBUG
185         printf("fmt->Load(0x%x): %p\n", fd, ret);
186         #endif
187         if( !ret ) {
188                 return NULL;
189         }
190         
191         Binary_AddToList(Filename, ret, fmt);
192
193         entry = fmt->Relocate(ret);
194         #if DEBUG
195         printf("fmt->Relocate(%p): %p\n", ret, (void*)entry);
196         #endif
197         if( !entry ) {
198                 // TODO: Clean up
199                 return NULL;
200         }
201         
202         if( EntryPoint )
203                 *EntryPoint = entry;
204
205         Binary_SetReadyToUse(ret);
206
207         return ret;
208 }
209
210 void Binary_AddToList(const char *Filename, void *Base, tBinFmt *Format)
211 {
212         tBinary *bin = malloc(sizeof(tBinary) + strlen(Filename) + 1);
213         bin->Base = Base;
214         bin->Format = Format;
215         strcpy(bin->Path, Filename);
216         bin->Ready = 0;
217         
218         bin->Next = gLoadedBinaries;
219         gLoadedBinaries = bin;
220 }
221
222 void Binary_SetReadyToUse(void *Base)
223 {
224         tBinary *bin;
225         for(bin = gLoadedBinaries; bin; bin = bin->Next)
226         {
227                 if( bin->Base != Base ) continue ;
228                 bin->Ready = 1;
229         }
230 }
231
232 int Binary_GetSymbol(const char *SymbolName, uintptr_t *Value, size_t *Size, void *IgnoreBase)
233 {
234          int    i;
235         tBinary *bin;
236         
237         //printf("Binary_GetSymbol: (SymbolName='%s', Value=%p)\n",
238         //      SymbolName, Value);
239
240         // Search builtins
241         // - Placed first to override smartarses that define their own versions
242         //   of system calls
243         for( i = 0; i < ciNumBuiltinSymbols; i ++ )
244         {
245                 if( strcmp(caBuiltinSymbols[i].Name, SymbolName) == 0 ) {
246                         *Value = (uintptr_t)caBuiltinSymbols[i].Value;
247                         if(Size)        *Size = 0;
248                         return 1;
249                 }
250         }
251         
252         // Search list of loaded binaries
253         for(bin = gLoadedBinaries; bin; bin = bin->Next)
254         {
255                 if( bin->Base == IgnoreBase )   continue ;
256                 if( !bin->Ready )       continue;
257                 //printf(" Binary_GetSymbol: bin = %p{%p, %s}\n", bin, bin->Base, bin->Path);
258                 if( bin->Format->GetSymbol(bin->Base, (char*)SymbolName, Value, Size) )
259                         return 1;
260         }
261
262         //printf("Binary_GetSymbol: RETURN 0, not found\n");
263         printf("--- ERROR: Unable to find symbol '%s'\n", SymbolName);
264
265         exit( -1 );
266         return 0;
267 }

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