Changeset 2830
- Timestamp:
- Oct 23, 2006, 10:53:11 PM (19 years ago)
- Location:
- trunk/kLdr
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kLdr/kLdr.c
r2826 r2830 49 49 #include "kLdrHlp.h" 50 50 51 #if 052 /*******************************************************************************53 * Global Variables *54 *******************************************************************************/55 /** Pointer to the head module (the executable).56 * (This is exported, so no prefix.) */57 PKLDRMOD kLdrModuleHead = NULL;58 /** Pointer to the tail module.59 * (This is exported, so no prefix.) */60 PKLDRMOD kLdrModuleTail = NULL;61 /** The Library search path. */62 char kLdrLibraryPath[4096];63 /** The executable flags. */64 uint32_t kLdrFlags;65 /** Bootstrap stack and temporary space. */66 char abStack[8192];67 /** Set if we've initialized the loader. */68 int fInitialized = 0;69 70 51 71 52 /******************************************************************************* 72 * Internal Functions*53 * Header Files * 73 54 *******************************************************************************/ 74 static int kldrInit(void); 75 static int kldrTerm(void); 76 77 78 /** 79 * Initialize the loader.55 /** Flag indicating whether we've initialized the loader or not. 56 * 57 * 0 if not initialized. 58 * -1 if we're initializing or terminating. 59 * 1 if we've successfully initialized it. 60 * -2 if initialization failed. 80 61 */ 81 int kldrInit(void) 82 { 83 if (fInitialized) 84 return 0; 85 /** @todo */ 86 return 0; 87 } 88 89 90 91 void kldrLoadExe(PKLDREXEARGS pArgs) 92 { 93 /* 94 * Copy the arguments into the globals and do load init. 95 */ 96 kLdrFlags = pArgs->fFlags; 97 kLdrMemCopy(kLdrLibraryPath, pArgs->szLibPath, KLDR_MIN(sizeof(pArgs->szLibPath), sizeof(kLdrLibraryPath))); 98 int rc = kldrInit(); 99 if (rc) 100 kldrFailure(rc, "kLdr: Init failure, rc=%d\n", rc); 101 102 /* 103 * Open the executable module. 104 */ 105 PKLDRMOD pExe; 106 kldrOpenExe(pArgs->szExecutable, &pExe); 107 108 /* Map the segments. */ 109 kldrModMapSegments(pExe); 110 111 /* 112 * This is the point where we switch to the executable 113 * stack, allocating it if necessary. 114 */ 115 void *pvBottom; 116 kldrModSetupStack(pExe, &pvBottom); 117 kldrLoadExecSwitchStack(pvBottom); 118 } 119 120 121 void kldrLoadExeOnNewStack(void) 122 { 123 /* 124 * Load all dependant modules. 125 */ 126 PKLDRMOD pCur; 127 do for (pCur = kLdrModuleHead; pCur; pCur = pCur->pNext) 128 { 129 if (pCur->enmState >= KLDRSTATE_DEPS) 130 continue; 131 kldrModLoadDeps(pCur); 132 } 133 while (pCur); 134 135 /* 136 * Do fixups (FIFO). 137 */ 138 for (pCur = kLdrModuleHead; pCur; pCur = pCur->pNext) 139 { 140 if (pCur->enmState >= KLDRSTATE_FIXED) 141 continue; 142 kldrModFixup(pCur, 0); 143 } 144 145 /* 146 * Do module initialization. 147 */ 148 for (pCur = kLdrModuleTail; pCur != kLdrModuleTail; pCur = pCur->pPrev) 149 { 150 if (pCur->enmState >= KLDRSTATE_INITED) 151 continue; 152 kldrModCallInit(pCur); 153 } 154 155 /* 156 * Get the executable start address and commit the work that's been done. 157 */ 158 void *pvEntry; 159 kldrModGetExeEntry(&pvEntry); 160 161 for (pCur = kLdrModuleHead; pCur; pCur = pCur->pNext) 162 if (pCur->enmState == KLDRSTATE_INITED) 163 pCur->enmState = KLDRSTATE_LOADED; 164 165 kldrSemRelease(); 166 167 /* 168 * We're now ready for starting the executable code. 169 */ 170 kldrOSStartExe(pLdrModuleHead, pvEntry); 171 } 172 173 174 int kLdrLoadDll(const char *pszFilename, unsigned fFlags, void *pvmod) 175 { 176 177 return -1; 178 } 179 62 static int volatile g_fInitialized; 180 63 181 64 182 65 183 66 /** 184 * Panic / failure 185 * 186 * @returns rc if we're in a position where we can return. 187 * @param rc Return code. 188 * @param pszFormat Message string. Limited fprintf like formatted. 189 * @param ... Message string arguments. 67 * Initializes the loader. 68 * @returns 0 on success, non-zero OS status code on failure. 190 69 */ 191 int kldr Failure(int rc, const char *pszFormat, ...)70 int kldrInit(void) 192 71 { 193 kldrExit(1); 72 int rc; 73 74 /* check we're already good. */ 75 if (g_fInitialized == 1) 76 return 0; 77 78 /* a tiny serialization effort. */ 79 for (;;) 80 { 81 if (g_fInitialized == 1) 82 return 0; 83 if (g_fInitialized == -2) 84 return -1; 85 /** @todo atomic test and set if we care. */ 86 if (g_fInitialized == 0) 87 { 88 g_fInitialized = -1; 89 break; 90 } 91 kldrHlpSleep(1); 92 } 93 94 /* 95 * Do the initialization. 96 */ 97 rc = kldrHlpHeapInit(); 98 if (!rc) 99 { 100 rc = kldrHlpSemInit(); 101 if (!rc) 102 { 103 g_fInitialized = 1; 104 return 0; 105 } 106 kldrHlpHeapTerm(); 107 } 108 g_fInitialized = -2; 194 109 return rc; 195 110 } 196 111 197 #endif 112 113 /** 114 * Terminates the loader. 115 */ 116 void kldrTerm(void) 117 { 118 /* can't terminate unless it's initialized. */ 119 if (g_fInitialized != 1) 120 return; 121 g_fInitialized = -1; 122 123 /* 124 * Do the termination. 125 */ 126 kldrHlpSemTerm(); 127 kldrHlpHeapTerm(); 128 129 /* done */ 130 g_fInitialized = 0; 131 } 132 -
trunk/kLdr/kLdr.h
r2829 r2830 68 68 KLDRPROT_EXECUTE, 69 69 /** Execute & read. */ 70 KLDRPROT_EXECUTE_READ ONLY,70 KLDRPROT_EXECUTE_READ, 71 71 /** Execute, read & write. */ 72 72 KLDRPROT_EXECUTE_READWRITE, -
trunk/kLdr/kLdrHlp.c
r2828 r2830 41 41 #include <kLdr.h> 42 42 #include "kLdrHlp.h" 43 44 45 /******************************************************************************* 46 * Global Variables * 47 *******************************************************************************/ 48 #ifdef __OS2__ 49 /** The loader sempahore. */ 50 static HMTX g_hmtx; 51 /** The base of the stub object. 52 * The OS/2 exe stub consists of a single data object. When allocating memory 53 * for an executable, we'll have to reuse this. */ 54 static void *g_pvStub = NULL; 55 /** The size of the stub object - 0 if no stub. */ 56 static size_t g_cbStub = 0; 57 58 #elif defined(__WIN__) 59 /** The loader sempahore. */ 60 static CRITICAL_SECTION g_CritSect; 61 /** The system info. */ 62 static SYSTEM_INFO g_SystemInfo; 63 #else 64 # error "port me" 65 #endif 66 67 68 /** 69 * Initializes the loader semaphore. 70 * 71 * @returns 0 on success, non-zero OS status code on failure. 72 */ 73 int kldrHlpSemInit(void) 74 { 75 #ifdef __OS2__ 76 APIRET rc; 77 g_hmtx = NULLHANDLE; 78 rc = DosCreateMutexSem(NULL, &g_hmtx, 0, FALSE); 79 if (rc) 80 return rc; 81 82 #elif defined(__WIN__) 83 InitializeCriticalSection(&g_CritSect); 84 85 #else 86 # error "port me" 87 #endif 88 return 0; 89 } 90 91 92 /** 93 * Terminates the loader semaphore. 94 */ 95 void kldrHlpSemTerm(void) 96 { 97 #ifdef __OS2__ 98 APIRET rc; 99 HMTX hmtx = g_hmtx; 100 g_hmtx = NULLHANDLE; 101 rc = DosCloseMutexSem(hmtx); 102 if (rc) 103 return rc; 104 105 #elif defined(__WIN__) 106 DeleteCriticalSection(&g_CritSect); 107 108 #else 109 # error "port me" 110 #endif 111 } 112 113 114 /** 115 * Requests the loader sempahore ownership. 116 * This can be done recursivly. 117 * 118 * @returns 0 on success, non-zero OS status code on failure. 119 */ 120 int kldrHlpSemRequest(void) 121 { 122 #ifdef __OS2__ 123 APIRET rc = DosRequestMutexSem(g_hmtx, 5000); 124 if (rc == ERROR_TIMEOUT || rc == ERROR_SEM_TIMEOUT || rc == ERROR_INTERRUPT) 125 { 126 unsigned i = 0; 127 do 128 { 129 /** @todo check for deadlocks etc. */ 130 rc = DosRequestMutexSem(g_hmtx, 1000); 131 } while ( ( rc == ERROR_TIMEOUT 132 || rc == ERROR_SEM_TIMEOUT 133 || rc == ERROR_INTERRUPT) 134 && i++ < 120); 135 } 136 return rc; 137 138 #elif defined(__WIN__) 139 EnterCriticalSection(&g_CritSect); 140 return 0; 141 142 #else 143 # error "port me" 144 #endif 145 } 146 147 148 /** 149 * Releases the loader semaphore ownership. 150 * The caller is responsible for making sure it's the semaphore owner! 151 */ 152 void kldrHlpSemRelease(void) 153 { 154 #ifdef __OS2__ 155 APIRET rc = DosReleaseMutexSem(g_hmtx); 156 kldrHlpAssert(!rc); (void)rc; 157 158 #elif defined(__WIN__) 159 LeaveCriticalSection(&g_CritSect); 160 161 #else 162 # error "port me" 163 #endif 164 165 } 166 167 #ifdef __OS2__ 168 static ULONG kldrHlpPageProtToNative(KLDRPROT enmProt) 169 { 170 switch (enmProt) 171 { 172 case KLDRPROT_NOACCESS: return PAG_EXECUTE | PAG_READ | PAG_WRITE; 173 case KLDRPROT_READONLY: return PAG_COMMIT | PAG_READ; 174 case KLDRPROT_READWRITE: return PAG_COMMIT | PAG_READ | PAG_WRITE; 175 case KLDRPROT_EXECUTE: return PAG_COMMIT | PAG_EXECUTE; 176 case KLDRPROT_EXECUTE_READ: return PAG_COMMIT | PAG_EXECUTE | PAG_READ; 177 case KLDRPROT_EXECUTE_READWRITE: return PAG_COMMIT | PAG_EXECUTE | PAG_READ | PAG_WRITE; 178 default: 179 kldrHlpAssert(0); 180 return ~0U; 181 } 182 } 183 #elif defined(__WIN__) 184 static DWORD kldrHlpPageProtToNative(KLDRPROT enmProt) 185 { 186 switch (enmProt) 187 { 188 case KLDRPROT_NOACCESS: return PAGE_NOACCESS; 189 case KLDRPROT_READONLY: return PAGE_READONLY; 190 case KLDRPROT_READWRITE: return PAGE_READWRITE; 191 case KLDRPROT_EXECUTE: return PAGE_EXECUTE; 192 case KLDRPROT_EXECUTE_READ: return PAGE_EXECUTE_READ; 193 case KLDRPROT_EXECUTE_READWRITE: return PAGE_EXECUTE_READWRITE; 194 default: 195 kldrHlpAssert(0); 196 return ~0U; 197 } 198 } 199 #endif 200 201 202 /** 203 * Allocate a chunk of memory with page granularity. 204 * 205 * @returns 0 on success, non-zero OS status code on failure. 206 * @param ppv Where to store the address of the allocated memory. 207 * If fFixed is set, *ppv will on entry contain the desired address (page aligned). 208 * @param cb Number of bytes. Page aligned. 209 * @param enmProt The new protection. Copy-on-write is invalid. 210 */ 211 int kldrHlpPageAlloc(void **ppv, size_t cb, KLDRPROT enmProt, unsigned fFixed) 212 { 213 #ifdef __OS2__ 214 APIRET rc; 215 ULONG fFlags = kldrHlpPageProtToNative(enmProt);; 216 217 if (!fFixed) 218 { 219 /* simple */ 220 rc = DosAllocMem(ppv, cb, fFlags | OBJ_ANY); 221 if (rc == ERROR_INVALID_PARAMETER) 222 rc = DosAllocMem(ppv, cb, fFlags); 223 } 224 else 225 { 226 /* not so simple. */ 227 /** @todo I've got code for this in libc somewhere. */ 228 } 229 if (!rc) 230 return 0; 231 kldrHlpAssert(0); 232 return rc; 233 234 #elif defined(__WIN__) 235 int rc; 236 DWORD fProt = kldrHlpPageProtToNative(enmProt); 237 238 if (!g_SystemInfo.dwPageSize) 239 GetSystemInfo(&g_SystemInfo); 240 241 *ppv = VirtualAlloc(fFixed ? *ppv : NULL, cb, MEM_COMMIT, fProt); 242 if (*ppv == NULL) 243 { 244 rc = GetLastError(); 245 kldrHlpAssert(0); 246 } 247 return rc; 248 249 #else 250 # error "port me" 251 #endif 252 } 253 254 255 /** 256 * Change the protection of one or more pages in an allocation. 257 * 258 * (This will of course only work correctly on memory allocated by kldrHlpPageAlloc().) 259 * 260 * @returns 0 on success, non-zero OS status code on failure. 261 * @param pv First page. Page aligned. 262 * @param cb Number of bytes. Page aligned. 263 * @param enmProt The new protection. Copy-on-write is invalid. 264 */ 265 int kldrHlpPageProtect(void *pv, size_t cb, KLDRPROT enmProt) 266 { 267 #ifdef __OS2__ 268 APIRET rc; 269 uintptr_t offStub; 270 ULONG fFlags = kldrHlpPageProtToNative(enmProt);; 271 272 /* 273 * The non-stub pages. 274 */ 275 rc = DosSetMem(pv, cb, fFlags); 276 if (rc && fFlags != PAG_DECOMMIT) 277 rc = DosSetMem(pv, cb, fFlags | PAG_COMMIT); 278 if (rc) 279 { 280 /* Try page by page. */ 281 while (cb > 0) 282 { 283 rc = DosSetMem(pv, 0x1000, fFlags); 284 if (rc && fFlags != PAG_DECOMMIT) 285 rc = DosSetMem(pv, 0x1000, fFlags | PAG_COMMIT); 286 if (rc) 287 return rc; 288 pv = (void *)((uintptr_t)pv + 0x1000); 289 cb -= 0x1000; 290 } 291 } 292 kldrHlpAssert(!rc); 293 return rc; 294 295 #elif defined(__WIN__) 296 DWORD fOldProt = 0; 297 DWORD fProt = kldrHlpPageProtToNative(enmProt); 298 int rc = 0; 299 300 if (!VirtualProtect(pv, cb, fProt, &fOldProt)) 301 { 302 rc = GetLastError(); 303 kldrHlpAssert(0); 304 } 305 return rc; 306 #else 307 # error "port me" 308 #endif 309 } 310 311 312 /** 313 * Free memory allocated by kldrHlpPageAlloc(). 314 * 315 * @returns 0 on success, non-zero OS status code on failure. 316 * @param pv The address returned by kldrHlpPageAlloc(). 317 * @param cb The byte count requested from kldrHlpPageAlloc(). 318 */ 319 int kldrHlpPageFree(void *pv, size_t cb) 320 { 321 #ifdef __OS2__ 322 APIRET rc; 323 324 /* 325 * Deal with any portion overlapping with the stub. 326 */ 327 uintptr_t offStub = (uintptr_t)pv - (uintptr_t)g_pvStub; 328 if (offStub < g_cbStub) 329 { 330 /* decommit the pages in the stub. */ 331 size_t cbSub = KLDR_MIN(g_cbStub - offStub, cb); 332 rc = DosSetMem(pv, cbStub, PAG_DECOMMIT); 333 if (rc) 334 { 335 /* Page by page, ignoring errors after the first success. */ 336 while (cbSub > 0) 337 { 338 if (!DosSetMem(pv, 0x1000, PAG_DECOMMIT)) 339 rc = 0; 340 pv = (void *)((uintptr_t)pv + 0x1000); 341 cbSub -= 0x1000; 342 cb -= 0x1000; 343 } 344 if (rc) 345 { 346 kldrHlpAssert(!rc); 347 return rc; 348 } 349 } 350 else 351 { 352 cb -= cbSub; 353 if (!cb) 354 return 0; 355 pv = (void *)((uintptr_t)pv + cbSub); 356 } 357 } 358 359 /* 360 * Free the object. 361 */ 362 rc = DosFreeMem(pv); 363 kldrHlpAssert(!rc); 364 return rc; 365 366 #elif defined(__WIN__) 367 /* 368 * Free the object. 369 */ 370 int rc = 0; 371 if (!VirtualFree(pv, 0 /*cb*/, MEM_RELEASE)) 372 { 373 rc = GetLastError(); 374 kldrHlpAssert(0); 375 } 376 return rc; 377 378 #else 379 # error "port me" 380 #endif 381 } 43 382 44 383 … … 137 476 } 138 477 478 479 /** 480 * Sleep for a number of milliseconds. 481 * @param cMillies Number of milliseconds to sleep. 482 */ 483 void kldrHlpSleep(unsigned cMillies) 484 { 485 #ifdef __OS2__ 486 DosSleep(cMillies); 487 #elif defined(__WIN__) 488 Sleep(cMillies); 489 #else 490 usleep(cMillies * 1000); 491 #endif 492 } 493 494 139 495 /** Internal worker for kldrHlpAssertMsg. */ 140 496 static void int2dec(char *pszLine, unsigned iLine) -
trunk/kLdr/kLdrHlp.h
r2828 r2830 112 112 113 113 114 int kldrSemInit(void); 115 int kldrSemTerm(void); 116 int kldrSemRequest(void); 117 int kldrSemRelease(void); 118 int kldrSemGlobalRequest(void); 119 int kldrSemGlobalRelease(void); 114 int kldrHlpSemInit(void); 115 void kldrHlpSemTerm(void); 116 int kldrHlpSemRequest(void); 117 void kldrHlpSemRelease(void); 120 118 121 int kldrPrivateAlloc(void *pv, size_t cb, unsigned fFlags, void **ppv); 122 int kldrPrivateFree(void *pv, size_t cb); 123 int kldrSharedAlloc(void *pv, size_t cb, unsigned fFlags, const char *pszFilename, void *File, void **ppv); 124 int kldrSharedFree(void *pv, size_t cb); 119 int kldrHlpPageAlloc(void **ppv, size_t cb, KLDRPROT enmProt, unsigned fFixed); 120 int kldrHlpPageProtect(void *pv, size_t cb, KLDRPROT enmProt); 121 int kldrHlpPageFree(void *pv, size_t cb); 125 122 126 123 int kldrHlpHeapInit(void); … … 132 129 int kldrHlpGetEnv(const char *pszVar, char *pszVal, size_t *pcchVal); 133 130 void kldrHlpExit(int rc); 131 void kldrHlpSleep(unsigned cMillies); 134 132 void kldrHlpAssertMsg(const char *pszExpr, const char *pszFile, unsigned iLine, const char *pszFunction); 135 133
Note:
See TracChangeset
for help on using the changeset viewer.