X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FLibraries%2Fld-acess.so_src%2Floadlib.c;h=31dcbd8acfa23840d954df1e2b555c7a78fee44f;hb=5cab4c07bc13888dc7956194ef9595508072a4eb;hp=5cfa26e8c29750f17d38bd4e805a6dfc59bd03e3;hpb=775bf8013abe9fe4ef3d4883ea2e43bba2a84da1;p=tpg%2Facess2.git diff --git a/Usermode/Libraries/ld-acess.so_src/loadlib.c b/Usermode/Libraries/ld-acess.so_src/loadlib.c index 5cfa26e8..31dcbd8a 100644 --- a/Usermode/Libraries/ld-acess.so_src/loadlib.c +++ b/Usermode/Libraries/ld-acess.so_src/loadlib.c @@ -1,227 +1,318 @@ -/* - AcessOS 1 - Dynamic Loader - By thePowersGang -*/ -#include "common.h" - -#define DEBUG 0 - -#if DEBUG -# define DEBUGS(v...) SysDebug(v) -#else -# define DEBUGS(v...) -#endif - -// === CONSTANTS === -#define MAX_LOADED_LIBRARIES 64 -#define MAX_STRINGS_BYTES 4096 -#define SYSTEM_LIB_DIR "/Acess/Libs/" - -// === PROTOTYPES === -Uint IsFileLoaded(char *file); - int GetSymbolFromBase(Uint base, char *name, Uint *ret); - -// === GLOABLS === -struct { - Uint Base; - char *Name; -} gLoadedLibraries[MAX_LOADED_LIBRARIES]; -char gsLoadedStrings[MAX_STRINGS_BYTES]; -char *gsNextAvailString = gsLoadedStrings; -//tLoadLib *gpLoadedLibraries = NULL; - -// === CODE === -char *FindLibrary(char *DestBuf, char *SoName, char *ExtraSearchDir) -{ - // -- #1: Executable Specified - if(ExtraSearchDir) - { - strcpy(DestBuf, ExtraSearchDir); - strcat(DestBuf, "/"); - strcat(DestBuf, SoName); - if(file_exists(DestBuf)) return DestBuf; - } - - // -- #2: System - strcpy(DestBuf, SYSTEM_LIB_DIR); - strcat(DestBuf, SoName); - if(file_exists(DestBuf)) return DestBuf; - - // -- #3: Current Directory - if(file_exists(SoName)) return SoName; - - return NULL; -} - -/** - */ -Uint LoadLibrary(char *SoName, char *SearchDir, char **envp) -{ - char sTmpName[1024]; - char *filename; - Uint iArg; - void (*fEntry)(int, int, char *[], char**); - - DEBUGS("LoadLibrary: (filename='%s', envp=0x%x)\n", filename, envp); - - // Create Temp Name - filename = FindLibrary(sTmpName, SoName, SearchDir); - if(filename == NULL) { - DEBUGS("LoadLibrary: RETURN 0\n"); - return 0; - } - DEBUGS(" LoadLibrary: filename='%s'\n", filename); - - if( (iArg = IsFileLoaded(filename)) ) - return iArg; - - // Load Library - iArg = SysLoadBin(filename, (Uint*)&fEntry); - if(iArg == 0) { - DEBUGS("LoadLibrary: RETURN 0\n"); - return 0; - } - - DEBUGS(" LoadLibrary: iArg=0x%x, iEntry=0x%x\n", iArg, fEntry); - - // Load Symbols - fEntry = (void*)DoRelocate( iArg, envp, filename ); - - // Call Entrypoint - DEBUGS(" LoadLibrary: '%s' Entry 0x%x\n", SoName, fEntry); - fEntry(iArg, 0, NULL, envp); - - DEBUGS("LoadLibrary: RETURN 1\n"); - return iArg; +/* + AcessOS 1 - Dynamic Loader + By thePowersGang +*/ +#include "common.h" +#include +#include +#include + +#define DEBUG 0 + +#if DEBUG +# define DEBUGS(v...) SysDebug(v) +#else +# define DEBUGS(v...) +#endif + +#define MAX_QUEUED_ENTRYPOINTS 8 + +// === IMPORTS === +extern const struct { + void *Value; + char *Name; +} caLocalExports[]; +extern const int ciNumLocalExports; +extern char **gEnvP; +extern char gLinkedBase[]; + +// === TYPES === +typedef void tLibEntry(void *, int, char *[], char**); + +// === PROTOTYPES === +void *IsFileLoaded(const char *file); + +// === GLOABLS === +tLoadedLib gLoadedLibraries[MAX_LOADED_LIBRARIES]; +char gsLoadedStrings[MAX_STRINGS_BYTES]; +char *gsNextAvailString = gsLoadedStrings; +struct sQueuedEntry { + void *Base; + tLibEntry *Entry; +} gaQueuedEntrypoints[MAX_QUEUED_ENTRYPOINTS]; + int giNumQueuedEntrypoints; +//tLoadLib *gpLoadedLibraries = NULL; + +// === CODE === +void ldacess_DumpLoadedLibraries(void) +{ + for( int i = 0; i < MAX_LOADED_LIBRARIES; i ++ ) + { + if(gLoadedLibraries[i].Base == 0) break; // Last entry has Base set to NULL + _SysDebug("%p: %s", + gLoadedLibraries[i].Base, + gLoadedLibraries[i].Name + ); + } } - -/** - * \fn Uint IsFileLoaded(char *file) - * \brief Determine if a file is already loaded - */ -Uint IsFileLoaded(char *file) -{ - int i; - DEBUGS("IsFileLoaded: (file='%s')", file); - for( i = 0; i < MAX_LOADED_LIBRARIES; i++ ) - { - if(gLoadedLibraries[i].Base == 0) break; // Last entry has Base set to NULL - DEBUGS(" strcmp('%s', '%s')", gLoadedLibraries[i].Name, file); - if(strcmp(gLoadedLibraries[i].Name, file) == 0) { - DEBUGS("IsFileLoaded: Found %i (0x%x)", i, gLoadedLibraries[i].Base); - return gLoadedLibraries[i].Base; - } - } - DEBUGS("IsFileLoaded: Not Found"); - return 0; -} - -/** - * \fn void AddLoaded(char *File, Uint base) - * \brief Add a file to the loaded list + +/** + * \brief Call queued up entry points (after relocations completed) */ -void AddLoaded(char *File, Uint base) -{ - int i, length; - char *name = gsNextAvailString; - - DEBUGS("AddLoaded: (File='%s', base=0x%x)", File, base); - - // Find a free slot - for( i = 0; i < MAX_LOADED_LIBRARIES; i ++ ) - { - if(gLoadedLibraries[i].Base == 0) break; - } - if(i == MAX_LOADED_LIBRARIES) { - SysDebug("ERROR - ld-acess.so has run out of load slots!"); - return; - } - - // Check space in string buffer - length = strlen(File); - if(&name[length+1] >= &gsLoadedStrings[MAX_STRINGS_BYTES]) { - SysDebug("ERROR - ld-acess.so has run out of string buffer memory!"); - return; - } - - // Set information - gLoadedLibraries[i].Base = base; - strcpy(name, File); - gLoadedLibraries[i].Name = name; - gsNextAvailString = &name[length+1]; - DEBUGS("'%s' (0x%x) loaded as %i\n", name, base, i); +void CallQueuedEntrypoints(char **EnvP) +{ + while( giNumQueuedEntrypoints ) + { + giNumQueuedEntrypoints --; + const struct sQueuedEntry *qe = &gaQueuedEntrypoints[giNumQueuedEntrypoints]; + DEBUGS("Calling EP %p for %p", qe->Entry, qe->Base); + qe->Entry(qe->Base, 0, NULL, EnvP); + } +} + +const char *FindLibrary(char *DestBuf, const char *SoName, const char *ExtraSearchDir) +{ + // -- #1: Executable Specified + if(ExtraSearchDir) + { + strcpy(DestBuf, ExtraSearchDir); + strcat(DestBuf, "/"); + strcat(DestBuf, SoName); + if(file_exists(DestBuf)) return DestBuf; + } + + // -- #2: System + strcpy(DestBuf, SYSTEM_LIB_DIR); + strcat(DestBuf, SoName); + if(file_exists(DestBuf)) return DestBuf; + + // -- #3: Current Directory + if(file_exists(SoName)) return SoName; + + return NULL; +} + +/** + */ +void *LoadLibrary(const char *SoName, const char *SearchDir, char **envp) +{ + char sTmpName[1024]; + void *base; + + DEBUGS("LoadLibrary: (SoName='%s', SearchDir='%s', envp=%p)", SoName, SearchDir, envp); + + // Create Temp Name + const char *filename = FindLibrary(sTmpName, SoName, SearchDir); + if(filename == NULL) { + DEBUGS("LoadLibrary: RETURN 0"); + return 0; + } + DEBUGS(" LoadLibrary: filename='%s'", filename); + + if( (base = IsFileLoaded(filename)) ) + return base; + + DEBUGS(" LoadLibrary: SysLoadBin()"); + // Load Library + tLibEntry *fEntry; + base = _SysLoadBin(filename, (void**)&fEntry); + if(!base) { + DEBUGS("LoadLibrary: RETURN 0"); + return 0; + } + + DEBUGS(" LoadLibrary: iArg=%p, fEntry=%p", base, fEntry); + + // Load Symbols + fEntry = DoRelocate( base, envp, filename ); + if( !fEntry ) { + return 0; + } + + // Call Entrypoint + // - TODO: Queue entrypoint calls + if( giNumQueuedEntrypoints >= MAX_QUEUED_ENTRYPOINTS ) { + SysDebug("ERROR - Maximum number of queued entrypoints exceeded on %p '%s'", + base, SoName); + return 0; + } + gaQueuedEntrypoints[giNumQueuedEntrypoints].Base = base; + gaQueuedEntrypoints[giNumQueuedEntrypoints].Entry = fEntry; + giNumQueuedEntrypoints ++; + + DEBUGS("LoadLibrary: RETURN success"); + return base; +} + +/** + * \fn Uint IsFileLoaded(char *file) + * \brief Determine if a file is already loaded + */ +void *IsFileLoaded(const char *file) +{ + int i; + DEBUGS("IsFileLoaded: (file='%s')", file); + + // Applications link against either libld-acess.so or ld-acess.so + if( strcmp(file, "/Acess/Libs/libld-acess.so") == 0 + || strcmp(file, "/Acess/Libs/ld-acess.so") == 0 ) + { + DEBUGS("IsFileLoaded: Found local (%p)", &gLinkedBase); + return &gLinkedBase; + } + + for( i = 0; i < MAX_LOADED_LIBRARIES; i++ ) + { + if(gLoadedLibraries[i].Base == 0) break; // Last entry has Base set to NULL + DEBUGS(" strcmp('%s', '%s')", gLoadedLibraries[i].Name, file); + if(strcmp(gLoadedLibraries[i].Name, file) == 0) { + DEBUGS("IsFileLoaded: Found %i (%p)", i, gLoadedLibraries[i].Base); + return gLoadedLibraries[i].Base; + } + } + DEBUGS("IsFileLoaded: Not Found"); + return 0; +} + +/** + * \fn void AddLoaded(char *File, Uint base) + * \brief Add a file to the loaded list + */ +void AddLoaded(const char *File, void *base) +{ + int i, length; + char *name = gsNextAvailString; + + DEBUGS("AddLoaded: (File='%s', base=%p)", File, base); + + // Find a free slot + for( i = 0; i < MAX_LOADED_LIBRARIES; i ++ ) + { + if(gLoadedLibraries[i].Base == 0) break; + } + if(i == MAX_LOADED_LIBRARIES) { + SysDebug("ERROR - ld-acess.so has run out of load slots!"); + return; + } + + // Check space in string buffer + length = strlen(File); + if(&name[length+1] >= &gsLoadedStrings[MAX_STRINGS_BYTES]) { + SysDebug("ERROR - ld-acess.so has run out of string buffer memory!"); + return; + } + + // Set information + gLoadedLibraries[i].Base = base; + strcpy(name, File); + gLoadedLibraries[i].Name = name; + gsNextAvailString = &name[length+1]; + DEBUGS("'%s' (%p) loaded as %i", name, base, i); return; -} - -/** - * \fn void Unload(Uint Base) - */ -void Unload(Uint Base) -{ - int i, j; - int id; - char *str; - for( id = 0; id < MAX_LOADED_LIBRARIES; id++ ) - { - if(gLoadedLibraries[id].Base == Base) break; - } - if(id == MAX_LOADED_LIBRARIES) return; - - // Unload Binary - SysUnloadBin( Base ); - // Save String Pointer - str = gLoadedLibraries[id].Name; - - // Compact Loaded List - j = id; - for( i = j + 1; i < MAX_LOADED_LIBRARIES; i++, j++ ) - { - if(gLoadedLibraries[i].Base == 0) break; - // Compact String - strcpy(str, gLoadedLibraries[i].Name); - str += strlen(str)+1; - // Compact Entry - gLoadedLibraries[j].Base = gLoadedLibraries[i].Base; - gLoadedLibraries[j].Name = str; - } - - // NULL Last Entry - gLoadedLibraries[j].Base = 0; - gLoadedLibraries[j].Name = NULL; - // Save next string - gsNextAvailString = str; -} - +} + /** - \fn Uint GetSymbol(char *name) + * \fn void Unload(Uint Base) + */ +void Unload(void *Base) +{ + int i, j; + int id; + char *str; + for( id = 0; id < MAX_LOADED_LIBRARIES; id++ ) + { + if(gLoadedLibraries[id].Base == Base) break; + } + if(id == MAX_LOADED_LIBRARIES) return; + + // Unload Binary + _SysUnloadBin( Base ); + // Save String Pointer + str = gLoadedLibraries[id].Name; + + // Compact Loaded List + j = id; + for( i = j + 1; i < MAX_LOADED_LIBRARIES; i++, j++ ) + { + if(gLoadedLibraries[i].Base == 0) break; + // Compact String + strcpy(str, gLoadedLibraries[i].Name); + str += strlen(str)+1; + // Compact Entry + gLoadedLibraries[j].Base = gLoadedLibraries[i].Base; + gLoadedLibraries[j].Name = str; + } + + // NULL Last Entry + gLoadedLibraries[j].Base = 0; + gLoadedLibraries[j].Name = NULL; + // Save next string + gsNextAvailString = str; +} + +/** + \fn Uint GetSymbol(const char *name) \brief Gets a symbol value from a loaded library */ -Uint GetSymbol(char *name) -{ - int i; - Uint ret; - for(i=0;i