b5fb0a1588a44a0ec9919f4d2a47a1038f3bfd56
[tpg/acess2.git] / 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         DEBUGS(" LoadLibrary: filename='%s'\n", filename);\r
70         \r
71         if( (iArg = IsFileLoaded(filename)) )\r
72                 return iArg;\r
73         \r
74         // Load Library\r
75         iArg = SysLoadBin(filename, (Uint*)&fEntry);\r
76         if(iArg == 0) {\r
77                 DEBUGS("LoadLibrary: RETURN 0\n");\r
78                 return 0;\r
79         }\r
80         \r
81         DEBUGS(" LoadLibrary: iArg=0x%x, iEntry=0x%x\n", iArg, fEntry);\r
82         \r
83         // Load Symbols\r
84         fEntry = (void*)DoRelocate( iArg, envp, filename );\r
85         \r
86         // Call Entrypoint\r
87         DEBUGS(" LoadLibrary: '%s' Entry 0x%x\n", SoName, fEntry);\r
88         fEntry(iArg, 0, NULL, envp);\r
89         \r
90         DEBUGS("LoadLibrary: RETURN 1\n");\r
91         return iArg;\r
92 }
93 \r
94 /**\r
95  * \fn Uint IsFileLoaded(char *file)\r
96  * \brief Determine if a file is already loaded\r
97  */\r
98 Uint IsFileLoaded(char *file)\r
99 {\r
100          int    i;\r
101         DEBUGS("IsFileLoaded: (file='%s')", file);\r
102         for( i = 0; i < MAX_LOADED_LIBRARIES; i++ )\r
103         {\r
104                 if(gLoadedLibraries[i].Base == 0)       break;  // Last entry has Base set to NULL\r
105                 DEBUGS(" strcmp('%s', '%s')", gLoadedLibraries[i].Name, file);\r
106                 if(strcmp(gLoadedLibraries[i].Name, file) == 0) {\r
107                         DEBUGS("IsFileLoaded: Found %i (0x%x)", i, gLoadedLibraries[i].Base);\r
108                         return gLoadedLibraries[i].Base;\r
109                 }\r
110         }\r
111         DEBUGS("IsFileLoaded: Not Found");\r
112         return 0;\r
113 }\r
114 \r
115 /**\r
116  * \fn void AddLoaded(char *File, Uint base)\r
117  * \brief Add a file to the loaded list\r
118  */
119 void AddLoaded(char *File, Uint base)
120 {\r
121          int    i, length;\r
122         char    *name = gsNextAvailString;\r
123         \r
124         DEBUGS("AddLoaded: (File='%s', base=0x%x)", File, base);\r
125         \r
126         // Find a free slot\r
127         for( i = 0; i < MAX_LOADED_LIBRARIES; i ++ )\r
128         {\r
129                 if(gLoadedLibraries[i].Base == 0)       break;\r
130         }\r
131         if(i == MAX_LOADED_LIBRARIES) {\r
132                 SysDebug("ERROR - ld-acess.so has run out of load slots!");\r
133                 return;\r
134         }\r
135         \r
136         // Check space in string buffer\r
137         length = strlen(File);\r
138         if(&name[length+1] >= &gsLoadedStrings[MAX_STRINGS_BYTES]) {\r
139                 SysDebug("ERROR - ld-acess.so has run out of string buffer memory!");\r
140                 return;\r
141         }\r
142         \r
143         // Set information\r
144         gLoadedLibraries[i].Base = base;\r
145         strcpy(name, File);\r
146         gLoadedLibraries[i].Name = name;\r
147         gsNextAvailString = &name[length+1];\r
148         DEBUGS("'%s' (0x%x) loaded as %i\n", name, base, i);\r
149         return;
150 }\r
151 \r
152 /**\r
153  * \fn void Unload(Uint Base)\r
154  */\r
155 void Unload(Uint Base)\r
156 {       \r
157          int    i, j;\r
158          int    id;\r
159         char    *str;\r
160         for( id = 0; id < MAX_LOADED_LIBRARIES; id++ )\r
161         {\r
162                 if(gLoadedLibraries[id].Base == Base)   break;\r
163         }\r
164         if(id == MAX_LOADED_LIBRARIES)  return;\r
165         \r
166         // Unload Binary\r
167         SysUnloadBin( Base );\r
168         // Save String Pointer\r
169         str = gLoadedLibraries[id].Name;\r
170         \r
171         // Compact Loaded List\r
172         j = id;\r
173         for( i = j + 1; i < MAX_LOADED_LIBRARIES; i++, j++ )\r
174         {\r
175                 if(gLoadedLibraries[i].Base == 0)       break;\r
176                 // Compact String\r
177                 strcpy(str, gLoadedLibraries[i].Name);\r
178                 str += strlen(str)+1;\r
179                 // Compact Entry\r
180                 gLoadedLibraries[j].Base = gLoadedLibraries[i].Base;\r
181                 gLoadedLibraries[j].Name = str;\r
182         }\r
183         \r
184         // NULL Last Entry\r
185         gLoadedLibraries[j].Base = 0;\r
186         gLoadedLibraries[j].Name = NULL;\r
187         // Save next string\r
188         gsNextAvailString = str;\r
189 }\r
190 \r
191 /**
192  \fn Uint GetSymbol(char *name)
193  \brief Gets a symbol value from a loaded library
194 */
195 Uint GetSymbol(char *name)
196 {\r
197          int    i;
198         Uint    ret;\r
199         for(i=0;i<sizeof(gLoadedLibraries)/sizeof(gLoadedLibraries[0]);i++)\r
200         {\r
201                 if(gLoadedLibraries[i].Base == 0)       break;\r
202                 
203                 //SysDebug(" GetSymbol: Trying 0x%x, '%s'\n",\r
204                 //      gLoadedLibraries[i].Base, gLoadedLibraries[i].Name);
205                 if(GetSymbolFromBase(gLoadedLibraries[i].Base, name, &ret))     return ret;\r
206         }\r
207         SysDebug("GetSymbol: === Symbol '%s' not found ===\n", name);\r
208         return 0;
209 }
210
211 /**
212  \fn int GetSymbolFromBase(Uint base, char *name, Uint *ret)
213  \breif Gets a symbol from a specified library
214 */
215 int GetSymbolFromBase(Uint base, char *name, Uint *ret)
216 {
217         if(*(Uint32*)base == (0x7F|('E'<<8)|('L'<<16)|('F'<<24)))
218                 return ElfGetSymbol(base, name, ret);
219         if(*(Uint16*)base == ('M'|('Z'<<8)))
220                 return PE_GetSymbol(base, name, ret);
221         return 0;
222 }
223

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