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

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