Bugfixing initrd and ld-acess
[tpg/acess2.git] / Usermode / Libraries / ld-acess.so_src / loadlib.c
1 /*\r
2  AcessOS 1 - Dynamic Loader\r
3  By thePowersGang\r
4 */\r
5 #include "common.h"\r
6 \r
7 #define DEBUG   0\r
8 \r
9 #if DEBUG\r
10 # define DEBUGS(v...)   SysDebug(v)\r
11 #else\r
12 # define DEBUGS(v...)   \r
13 #endif\r
14 \r
15 // === CONSTANTS ===\r
16 #define MAX_LOADED_LIBRARIES    64\r
17 #define MAX_STRINGS_BYTES       4096\r
18 #define SYSTEM_LIB_DIR  "/Acess/Libs/"\r
19 \r
20 // === PROTOTYPES ===\r
21 Uint    IsFileLoaded(char *file);
22  int    GetSymbolFromBase(Uint base, char *name, Uint *ret);\r
23 \r
24 // === GLOABLS ===\r
25 struct {\r
26         Uint    Base;\r
27         char    *Name;\r
28 }       gLoadedLibraries[MAX_LOADED_LIBRARIES];\r
29 char    gsLoadedStrings[MAX_STRINGS_BYTES];\r
30 char    *gsNextAvailString = gsLoadedStrings;\r
31 //tLoadLib      *gpLoadedLibraries = NULL;\r
32 \r
33 // === CODE ===\r
34 char *FindLibrary(char *DestBuf, char *SoName, char *ExtraSearchDir)\r
35 {       \r
36         // -- #1: Executable Specified\r
37         if(ExtraSearchDir)\r
38         {\r
39                 strcpy(DestBuf, ExtraSearchDir);\r
40                 strcat(DestBuf, "/");\r
41                 strcat(DestBuf, SoName);\r
42                 if(file_exists(DestBuf))        return DestBuf;\r
43         }\r
44         \r
45         // -- #2: System\r
46         strcpy(DestBuf, SYSTEM_LIB_DIR);\r
47         strcat(DestBuf, SoName);\r
48         if(file_exists(DestBuf))        return DestBuf;\r
49         \r
50         // -- #3: Current Directory\r
51         if(file_exists(SoName)) return SoName;\r
52         \r
53         return NULL;\r
54 }\r
55 \r
56 /**\r
57  */\r
58 Uint LoadLibrary(char *SoName, char *SearchDir, char **envp)\r
59 {\r
60         char    sTmpName[1024];\r
61         char    *filename;\r
62         Uint    iArg;\r
63         void    (*fEntry)(int, int, char *[], char**);\r
64         \r
65         DEBUGS("LoadLibrary: (filename='%s', envp=0x%x)\n", filename, envp);\r
66         \r
67         // Create Temp Name\r
68         filename = FindLibrary(sTmpName, SoName, SearchDir);\r
69         if(filename == NULL) {\r
70                 DEBUGS("LoadLibrary: RETURN 0\n");\r
71                 return 0;\r
72         }\r
73         DEBUGS(" LoadLibrary: filename='%s'\n", filename);\r
74         \r
75         if( (iArg = IsFileLoaded(filename)) )\r
76                 return iArg;\r
77         \r
78         // Load Library\r
79         iArg = SysLoadBin(filename, (Uint*)&fEntry);\r
80         if(iArg == 0) {\r
81                 DEBUGS("LoadLibrary: RETURN 0\n");\r
82                 return 0;\r
83         }\r
84         \r
85         DEBUGS(" LoadLibrary: iArg=0x%x, iEntry=0x%x\n", iArg, fEntry);\r
86         \r
87         // Load Symbols\r
88         fEntry = (void*)DoRelocate( iArg, envp, filename );\r
89         \r
90         // Call Entrypoint\r
91         DEBUGS(" LoadLibrary: '%s' Entry 0x%x\n", SoName, fEntry);\r
92         fEntry(iArg, 0, NULL, envp);\r
93         \r
94         DEBUGS("LoadLibrary: RETURN 1\n");\r
95         return iArg;\r
96 }
97 \r
98 /**\r
99  * \fn Uint IsFileLoaded(char *file)\r
100  * \brief Determine if a file is already loaded\r
101  */\r
102 Uint IsFileLoaded(char *file)\r
103 {\r
104          int    i;\r
105         DEBUGS("IsFileLoaded: (file='%s')", file);\r
106         for( i = 0; i < MAX_LOADED_LIBRARIES; i++ )\r
107         {\r
108                 if(gLoadedLibraries[i].Base == 0)       break;  // Last entry has Base set to NULL\r
109                 DEBUGS(" strcmp('%s', '%s')", gLoadedLibraries[i].Name, file);\r
110                 if(strcmp(gLoadedLibraries[i].Name, file) == 0) {\r
111                         DEBUGS("IsFileLoaded: Found %i (0x%x)", i, gLoadedLibraries[i].Base);\r
112                         return gLoadedLibraries[i].Base;\r
113                 }\r
114         }\r
115         DEBUGS("IsFileLoaded: Not Found");\r
116         return 0;\r
117 }\r
118 \r
119 /**\r
120  * \fn void AddLoaded(char *File, Uint base)\r
121  * \brief Add a file to the loaded list\r
122  */
123 void AddLoaded(char *File, Uint base)
124 {\r
125          int    i, length;\r
126         char    *name = gsNextAvailString;\r
127         \r
128         DEBUGS("AddLoaded: (File='%s', base=0x%x)", File, base);\r
129         \r
130         // Find a free slot\r
131         for( i = 0; i < MAX_LOADED_LIBRARIES; i ++ )\r
132         {\r
133                 if(gLoadedLibraries[i].Base == 0)       break;\r
134         }\r
135         if(i == MAX_LOADED_LIBRARIES) {\r
136                 SysDebug("ERROR - ld-acess.so has run out of load slots!");\r
137                 return;\r
138         }\r
139         \r
140         // Check space in string buffer\r
141         length = strlen(File);\r
142         if(&name[length+1] >= &gsLoadedStrings[MAX_STRINGS_BYTES]) {\r
143                 SysDebug("ERROR - ld-acess.so has run out of string buffer memory!");\r
144                 return;\r
145         }\r
146         \r
147         // Set information\r
148         gLoadedLibraries[i].Base = base;\r
149         strcpy(name, File);\r
150         gLoadedLibraries[i].Name = name;\r
151         gsNextAvailString = &name[length+1];\r
152         DEBUGS("'%s' (0x%x) loaded as %i\n", name, base, i);\r
153         return;
154 }\r
155 \r
156 /**\r
157  * \fn void Unload(Uint Base)\r
158  */\r
159 void Unload(Uint Base)\r
160 {       \r
161          int    i, j;\r
162          int    id;\r
163         char    *str;\r
164         for( id = 0; id < MAX_LOADED_LIBRARIES; id++ )\r
165         {\r
166                 if(gLoadedLibraries[id].Base == Base)   break;\r
167         }\r
168         if(id == MAX_LOADED_LIBRARIES)  return;\r
169         \r
170         // Unload Binary\r
171         SysUnloadBin( Base );\r
172         // Save String Pointer\r
173         str = gLoadedLibraries[id].Name;\r
174         \r
175         // Compact Loaded List\r
176         j = id;\r
177         for( i = j + 1; i < MAX_LOADED_LIBRARIES; i++, j++ )\r
178         {\r
179                 if(gLoadedLibraries[i].Base == 0)       break;\r
180                 // Compact String\r
181                 strcpy(str, gLoadedLibraries[i].Name);\r
182                 str += strlen(str)+1;\r
183                 // Compact Entry\r
184                 gLoadedLibraries[j].Base = gLoadedLibraries[i].Base;\r
185                 gLoadedLibraries[j].Name = str;\r
186         }\r
187         \r
188         // NULL Last Entry\r
189         gLoadedLibraries[j].Base = 0;\r
190         gLoadedLibraries[j].Name = NULL;\r
191         // Save next string\r
192         gsNextAvailString = str;\r
193 }\r
194 \r
195 /**
196  \fn Uint GetSymbol(char *name)
197  \brief Gets a symbol value from a loaded library
198 */
199 Uint GetSymbol(char *name)
200 {\r
201          int    i;
202         Uint    ret;\r
203         for(i=0;i<sizeof(gLoadedLibraries)/sizeof(gLoadedLibraries[0]);i++)\r
204         {\r
205                 if(gLoadedLibraries[i].Base == 0)       break;\r
206                 
207                 //SysDebug(" GetSymbol: Trying 0x%x, '%s'\n",\r
208                 //      gLoadedLibraries[i].Base, gLoadedLibraries[i].Name);
209                 if(GetSymbolFromBase(gLoadedLibraries[i].Base, name, &ret))     return ret;\r
210         }\r
211         SysDebug("GetSymbol: === Symbol '%s' not found ===\n", name);\r
212         return 0;
213 }
214
215 /**
216  \fn int GetSymbolFromBase(Uint base, char *name, Uint *ret)
217  \breif Gets a symbol from a specified library
218 */
219 int GetSymbolFromBase(Uint base, char *name, Uint *ret)
220 {
221         if(*(Uint32*)base == (0x7F|('E'<<8)|('L'<<16)|('F'<<24)))
222                 return ElfGetSymbol(base, name, ret);
223         if(*(Uint16*)base == ('M'|('Z'<<8)))
224                 return PE_GetSymbol(base, name, ret);
225         return 0;
226 }
227

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