X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FLibraries%2Fld-acess.so_src%2Floadlib.c;h=2a0830302c923e33b1d1bda9717817d6b9e89070;hb=230612b2efeeb769f1d96193ec01b10bd36d9873;hp=88297d5f17ad7ccd9279ace490fbd2ccb736d418;hpb=5114cd4c1f8e36f62744a8efa346d619c99bdaf6;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 88297d5f..2a083030 100644 --- a/Usermode/Libraries/ld-acess.so_src/loadlib.c +++ b/Usermode/Libraries/ld-acess.so_src/loadlib.c @@ -3,6 +3,9 @@ By thePowersGang */ #include "common.h" +#include +#include +#include #define DEBUG 0 @@ -12,25 +15,57 @@ # define DEBUGS(v...) #endif -// === PROTOTYPES === -void *IsFileLoaded(char *file); - int GetSymbolFromBase(void *base, const char *name, void **ret); +#define MAX_QUEUED_ENTRYPOINTS 8 // === IMPORTS === -extern const struct { - void *Value; - char *Name; -} caLocalExports[]; +extern const tLocalExport 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 === -char *FindLibrary(char *DestBuf, char *SoName, char *ExtraSearchDir) +void ldacess_DumpLoadedLibraries(void) +{ + for( int i = 0; i < MAX_LOADED_LIBRARIES; i ++ ) + { + const tLoadedLib* ll = &gLoadedLibraries[i]; + if(ll->Base == 0) break; // Last entry has Base set to NULL + _SysDebug("%p: %s", ll->Base, ll->Name); + } +} + +/** + * \brief Call queued up entry points (after relocations completed) + */ +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) @@ -54,43 +89,53 @@ char *FindLibrary(char *DestBuf, char *SoName, char *ExtraSearchDir) /** */ -void *LoadLibrary(char *SoName, char *SearchDir, char **envp) +void *LoadLibrary(const char *SoName, const char *SearchDir, char **envp) { char sTmpName[1024]; - char *filename; void *base; - void (*fEntry)(void *, int, char *[], char**); - DEBUGS("LoadLibrary: (filename='%s', envp=0x%x)\n", filename, envp); + DEBUGS("LoadLibrary: (SoName='%s', SearchDir='%s', envp=%p)", SoName, SearchDir, envp); // Create Temp Name - filename = FindLibrary(sTmpName, SoName, SearchDir); + const char *filename = FindLibrary(sTmpName, SoName, SearchDir); if(filename == NULL) { - DEBUGS("LoadLibrary: RETURN 0\n"); + DEBUGS("LoadLibrary: RETURN 0"); return 0; } - DEBUGS(" LoadLibrary: filename='%s'\n", filename); + DEBUGS(" LoadLibrary: filename='%s'", filename); if( (base = IsFileLoaded(filename)) ) return base; - + + DEBUGS(" LoadLibrary: SysLoadBin()"); // Load Library - base = SysLoadBin(filename, (void**)&fEntry); + tLibEntry *fEntry; + base = _SysLoadBin(filename, (void**)&fEntry); if(!base) { - DEBUGS("LoadLibrary: RETURN 0\n"); + DEBUGS("LoadLibrary: RETURN 0"); return 0; } - DEBUGS(" LoadLibrary: iArg=%p, iEntry=0x%x\n", base, fEntry); + DEBUGS(" LoadLibrary: iArg=%p, fEntry=%p", base, fEntry); // Load Symbols fEntry = DoRelocate( base, envp, filename ); + if( !fEntry ) { + return 0; + } // Call Entrypoint - DEBUGS(" LoadLibrary: '%s' Entry 0x%x\n", SoName, fEntry); - fEntry(base, 0, NULL, envp); + // - 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 1\n"); + DEBUGS("LoadLibrary: RETURN success"); return base; } @@ -98,16 +143,24 @@ void *LoadLibrary(char *SoName, char *SearchDir, char **envp) * \fn Uint IsFileLoaded(char *file) * \brief Determine if a file is already loaded */ -void *IsFileLoaded(char *file) +void *IsFileLoaded(const char *file) { - int i; DEBUGS("IsFileLoaded: (file='%s')", file); - for( i = 0; i < MAX_LOADED_LIBRARIES; i++ ) + + // 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( int 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); + DEBUGS("IsFileLoaded: Found %i (%p)", i, gLoadedLibraries[i].Base); return gLoadedLibraries[i].Base; } } @@ -119,12 +172,12 @@ void *IsFileLoaded(char *file) * \fn void AddLoaded(char *File, Uint base) * \brief Add a file to the loaded list */ -void AddLoaded(char *File, void *base) +void AddLoaded(const char *File, void *base) { int i, length; char *name = gsNextAvailString; - DEBUGS("AddLoaded: (File='%s', base=0x%x)", File, base); + DEBUGS("AddLoaded: (File='%s', base=%p)", File, base); // Find a free slot for( i = 0; i < MAX_LOADED_LIBRARIES; i ++ ) @@ -148,7 +201,7 @@ void AddLoaded(char *File, void *base) strcpy(name, File); gLoadedLibraries[i].Name = name; gsNextAvailString = &name[length+1]; - DEBUGS("'%s' (0x%x) loaded as %i\n", name, base, i); + DEBUGS("'%s' (%p) loaded as %i", name, base, i); return; } @@ -157,7 +210,6 @@ void AddLoaded(char *File, void *base) */ void Unload(void *Base) { - int i, j; int id; char *str; for( id = 0; id < MAX_LOADED_LIBRARIES; id++ ) @@ -167,13 +219,13 @@ void Unload(void *Base) if(id == MAX_LOADED_LIBRARIES) return; // Unload Binary - SysUnloadBin( Base ); + _SysUnloadBin( Base ); // Save String Pointer str = gLoadedLibraries[id].Name; // Compact Loaded List - j = id; - for( i = j + 1; i < MAX_LOADED_LIBRARIES; i++, j++ ) + int j = id; + for( int i = j + 1; i < MAX_LOADED_LIBRARIES; i++, j++ ) { if(gLoadedLibraries[i].Base == 0) break; // Compact String @@ -195,42 +247,72 @@ void Unload(void *Base) \fn Uint GetSymbol(const char *name) \brief Gets a symbol value from a loaded library */ -void *GetSymbol(const char *name) +int GetSymbol(const char *name, void **Value, size_t *Size, void *IgnoreBase) { - int i; - void *ret; - - //SysDebug("ciNumLocalExports = %i", ciNumLocalExports); - for(i=0;iName, name) == 0 ) { + *Value = le->Value; + if(Size) + *Size = 0; + DEBUGS("'%s' = Local %p+%#x", name, le->Value, 0); + return 1; + } } - - // Entry 0 is ld-acess, ignore it - for(i = 1; i < MAX_LOADED_LIBRARIES; i ++) + + bool have_weak = false; + for(int i = 0; i < MAX_LOADED_LIBRARIES && gLoadedLibraries[i].Base != 0; i ++) { - if(gLoadedLibraries[i].Base == 0) break; + const tLoadedLib* ll = &gLoadedLibraries[i]; + // Allow ignoring the current module + if( ll->Base == IgnoreBase ) { + //SysDebug("GetSymbol: Ignore %p", gLoadedLibraries[i].Base); + continue ; + } - //SysDebug(" GetSymbol: Trying 0x%x, '%s'", - // gLoadedLibraries[i].Base, gLoadedLibraries[i].Name); - if(GetSymbolFromBase(gLoadedLibraries[i].Base, name, &ret)) return ret; + //SysDebug(" GetSymbol: Trying 0x%x, '%s'", ll->Base, ll->Name); + void *tmpval; + size_t tmpsize; + int rv = GetSymbolFromBase(ll->Base, name, &tmpval, &tmpsize); + if(rv) + { + *Value = tmpval; + *Size = tmpsize; + if( rv == 1 ) { + DEBUGS("'%s' = %p '%s' Strong %p+%#x", name, ll->Base, ll->Name, *Value, *Size); + return 1; + } + have_weak = true; + } + } + if(have_weak) { + DEBUGS("'%s' = Weak %p+%#x", name, *Value, *Size); + return 2; + } + else { + DEBUGS("'%s' = ?", name); + return 0; } - SysDebug("GetSymbol: === Symbol '%s' not found ===", name); - return 0; } /** \fn int GetSymbolFromBase(Uint base, char *name, Uint *ret) \breif Gets a symbol from a specified library */ -int GetSymbolFromBase(void *base, const char *name, void **ret) +int GetSymbolFromBase(void *base, const char *name, void **ret, size_t *Size) { - if(*(Uint32*)base == (0x7F|('E'<<8)|('L'<<16)|('F'<<24))) - return ElfGetSymbol(base, name, ret); - if(*(Uint16*)base == ('M'|('Z'<<8))) - return PE_GetSymbol(base, name, ret); - SysDebug("Unknown type at %p", base); + uint8_t *hdr = base; + if(hdr[0] == 0x7F && hdr[1] == 'E' && hdr[2] == 'L' && hdr[3] == 'F') + return ElfGetSymbol(base, name, ret, Size); + if(hdr[0] == 'M' && hdr[1] == 'Z') + return PE_GetSymbol(base, name, ret, Size); + SysDebug("Unknown type at %p (%02x %02x %02x %02x)", base, + hdr[0], hdr[1], hdr[2], hdr[3]); return 0; }