Usermode/libc - Fixing some bugs in environment handling
[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/x86/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(int fd);
22 extern uintptr_t        ElfRelocate(void *Base);
23 extern int      ElfGetSymbol(void *Base, char *Name, uintptr_t *ret, size_t *size);
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 = ElfRelocate,
37         .GetSymbol = ElfGetSymbol
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          int    fd;
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                 fd = acess_open(tmp, 4);        // OPENFLAG_EXEC
63                 if(fd != -1) {
64                         acess_close(fd);
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                 #if DEBUG
78                 printf("Binary_LocateLibrary: tmp = '%s'\n", tmp);
79                 #endif
80
81                 fd = acess_open(tmp, 4);        // OPENFLAG_EXEC
82                 if(fd != -1) {
83                         acess_close(fd);
84                         return strdup(tmp);
85                 }
86         }               
87
88         #if DEBUG
89         fprintf(stderr, "Unable to locate library '%s'\n", Name);
90         #endif
91
92         return NULL;
93 }
94
95 void *Binary_LoadLibrary(const char *Name)
96 {
97         char    *path;
98         void    *ret;
99          int    (*entry)(void *,int,char*[],char**) = NULL;
100
101         // Find File
102         path = Binary_LocateLibrary(Name);
103         #if DEBUG
104         printf("Binary_LoadLibrary: path = '%s'\n", path);
105         #endif
106         if( !path ) {
107                 return NULL;
108         }
109
110         ret = Binary_Load(path, (uintptr_t*)&entry);
111         printf("LOADED '%s' to %p (Entry=%p)\n", path, ret, entry);
112         free(path);
113         
114         #if DEBUG
115         printf("Binary_LoadLibrary: ret = %p, entry = %p\n", ret, entry);
116         #endif
117         if( entry ) {
118                 char    *argv[] = {NULL};
119                 #if DEBUG
120                 printf("Calling '%s' entry point %p\n", Name, entry);
121                 #endif
122                 entry(ret, 0, argv, NULL);
123         }
124
125         return ret;
126 }
127
128 void *Binary_Load(const char *Filename, uintptr_t *EntryPoint)
129 {
130          int    fd;
131         uint32_t        dword = 0xFA17FA17;
132         void    *ret;
133         uintptr_t       entry = 0;
134         tBinFmt *fmt;
135
136         // Ignore loading ld-acess
137         if( strcmp(Filename, "libld-acess.so") == 0 ) {
138                 *EntryPoint = 0;
139                 return (void*)-1;
140         }
141
142         {
143                 tBinary *bin;
144                 for(bin = gLoadedBinaries; bin; bin = bin->Next)
145                 {
146                         if( strcmp(Filename, bin->Path) == 0 ) {
147                                 return bin->Base;
148                         }
149                 }
150         }
151
152         fd = acess_open(Filename, 2|1); // Execute and Read
153         if( fd == -1 ) {
154                 // TODO: Handle libary directories
155                 perror("Opening binary");
156                 return NULL;
157         }
158
159         acess_read(fd, &dword, 4);
160         acess_seek(fd, 0, ACESS_SEEK_SET);
161         
162         if( memcmp(&dword, "\x7F""ELF", 4) == 0 ) {
163                 fmt = &gElf_FormatDef;
164         }
165         else {
166                 fprintf(stderr, "Unknown executable format (0x%08x)\n", dword);
167                 acess_close(fd);
168                 return NULL;
169         }
170         
171         #if DEBUG
172         printf("fmt->Load(%i)...\n", fd);
173         #endif
174         ret = fmt->Load(fd);
175         acess_close(fd);
176         #if DEBUG
177         printf("fmt->Load(%p): %p\n", fd, ret);
178         #endif
179         if( !ret ) {
180                 return NULL;
181         }
182         
183         Binary_AddToList(Filename, ret, fmt);
184
185         entry = fmt->Relocate(ret);
186         #if DEBUG
187         printf("fmt->Relocate(%p): %p\n", ret, (void*)entry);
188         #endif
189         if( !entry ) {
190                 // TODO: Clean up
191                 return NULL;
192         }
193         
194         if( EntryPoint )
195                 *EntryPoint = entry;
196
197         Binary_SetReadyToUse(ret);
198
199         return ret;
200 }
201
202 void Binary_AddToList(const char *Filename, void *Base, tBinFmt *Format)
203 {
204         tBinary *bin = malloc(sizeof(tBinary) + strlen(Filename) + 1);
205         bin->Base = Base;
206         bin->Format = Format;
207         strcpy(bin->Path, Filename);
208         bin->Ready = 0;
209         
210         bin->Next = gLoadedBinaries;
211         gLoadedBinaries = bin;
212 }
213
214 void Binary_SetReadyToUse(void *Base)
215 {
216         tBinary *bin;
217         for(bin = gLoadedBinaries; bin; bin = bin->Next)
218         {
219                 if( bin->Base != Base ) continue ;
220                 bin->Ready = 1;
221         }
222 }
223
224 int Binary_GetSymbol(const char *SymbolName, uintptr_t *Value, size_t *Size)
225 {
226          int    i;
227         tBinary *bin;
228         
229         //printf("Binary_GetSymbol: (SymbolName='%s', Value=%p)\n",
230         //      SymbolName, Value);
231
232         // Search builtins
233         // - Placed first to override smartarses that define their own versions
234         //   of system calls
235         for( i = 0; i < ciNumBuiltinSymbols; i ++ )
236         {
237                 if( strcmp(caBuiltinSymbols[i].Name, SymbolName) == 0 ) {
238                         *Value = (uintptr_t)caBuiltinSymbols[i].Value;
239                         if(Size)        *Size = 0;
240                         return 1;
241                 }
242         }
243         
244         // Search list of loaded binaries
245         for(bin = gLoadedBinaries; bin; bin = bin->Next)
246         {
247                 if( !bin->Ready )       continue;
248                 //printf(" Binary_GetSymbol: bin = %p{%p, %s}\n", bin, bin->Base, bin->Path);
249                 if( bin->Format->GetSymbol(bin->Base, (char*)SymbolName, Value, Size) )
250                         return 1;
251         }
252
253         //printf("Binary_GetSymbol: RETURN 0, not found\n");
254         
255         return 0;
256 }

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