Changeset 2845
- Timestamp:
- Nov 1, 2006, 2:39:03 AM (19 years ago)
- Location:
- trunk/kLdr
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kLdr/kLdr.h
r2843 r2845 557 557 558 558 int kLdrModOpen(const char *pszFilename, PPKLDRMOD ppMod); 559 int kLdrModOpenFromRdr(PKLDRRDR pRdr, PPKLDRMOD ppMod); 560 int kLdrModOpenNative(const char *pszFilename, PPKLDRMOD ppMod); 559 561 int kLdrModClose(PKLDRMOD pMod); 560 562 int kLdrModGetSymbol(PKLDRMOD pMod, const void *pvBits, uintmax_t BaseAddress, const char *pszSymbol, uintmax_t *pValue, uint32_t *pfKind); -
trunk/kLdr/kLdrDyld.c
r2843 r2845 168 168 static int kldrDyldStackAddModule(PKLDRDYLDMOD pMod); 169 169 static int kldrDyldStackFrameCompleted(void); 170 static void kldrDyldStackCleanupOne(PKLDRDYLDMOD pMod, int rc); 170 171 static void kldrDyldStackDropFrame(uint32_t iLoad1st, uint32_t iLoadEnd, int rc); 171 172 /** @} */ … … 627 628 rc = kldrDyldDoLoad2(*ppMod, pszPrefix, pszSuffix, enmSearch, fFlags); 628 629 else 629 { 630 /** @todo this is probably not quite right. */ 631 /* If the reference count is 0 do a quick ref/deref to trigger destruction. */ 632 kldrDyldModAddRef(*ppMod); 633 kldrDyldModDeref(*ppMod); 634 } 630 kldrDyldStackCleanupOne(*ppMod, rc); 635 631 636 632 /* … … 656 652 int rc = kldrDyldDoLoadPrerequisites(pLoadedMod, pszPrefix, pszSuffix, enmSearch, fFlags); 657 653 uint32_t iLoadEnd = kldrDyldStackFrameCompleted(); 654 if (rc) 655 kldrDyldStackCleanupOne(pLoadedMod, rc); /* in case it didn't get pushed onto the stack. */ 658 656 659 657 /* … … 954 952 if (!rc) 955 953 { 956 rc = kldrDyldModAddDep(pMod, pDep); 957 if (!rc) 958 *ppMod = pMod; 954 kldrDyldModAddDep(pMod, pDep); 955 *ppMod = pMod; 959 956 } 960 957 return rc; … … 1023 1020 static int kldrDyldStackAddModule(PKLDRDYLDMOD pMod) 1024 1021 { 1025 int rc;1026 1027 1022 /* 1028 1023 * Grow the stack if necessary. … … 1043 1038 * Add a reference and push the module onto the stack. 1044 1039 */ 1045 rc = kldrDyldModAddRef(pMod); 1046 if (!rc) 1047 g_papStackMods[g_cStackMods++] = pMod; 1048 return rc; 1040 kldrDyldModAddRef(pMod); 1041 g_papStackMods[g_cStackMods++] = pMod; 1042 return 0; 1049 1043 } 1050 1044 … … 1058 1052 { 1059 1053 return g_cStackMods; 1054 } 1055 1056 1057 /** 1058 * Worker routine for kldrDyldStackDropFrame() and kldrDyldDoLoad(). 1059 * 1060 * @param pMod The module to perform cleanups on. 1061 * @param rc Used for state verification. 1062 */ 1063 static void kldrDyldStackCleanupOne(PKLDRDYLDMOD pMod, int rc) 1064 { 1065 switch (pMod->enmState) 1066 { 1067 /* 1068 * Just push it along to the PENDING_DESTROY state. 1069 */ 1070 case KLDRSTATE_MAPPED: 1071 KLDRDYLD_ASSERT(rc); 1072 kldrDyldModUnmap(pMod); 1073 KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY); 1074 break; 1075 1076 /* 1077 * Move back to PENDING_GC. 1078 */ 1079 case KLDRSTATE_RELOADED: 1080 KLDRDYLD_ASSERT(rc); 1081 pMod->enmState = KLDRSTATE_PENDING_GC; 1082 break; 1083 1084 /* 1085 * Unload prerequisites and unmap the modules. 1086 */ 1087 case KLDRSTATE_LOADED_PREREQUISITES: 1088 case KLDRSTATE_FIXED_UP: 1089 KLDRDYLD_ASSERT(rc); 1090 kldrDyldModUnloadPrerequisites(pMod); 1091 KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY); 1092 kldrDyldModUnmap(pMod); 1093 KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY); 1094 break; 1095 1096 /* 1097 * Unload prerequisites and push it back to PENDING_GC. 1098 */ 1099 case KLDRSTATE_RELOADED_LOADED_PREREQUISITES: 1100 case KLDRSTATE_RELOADED_FIXED_UP: 1101 kldrDyldModUnloadPrerequisites(pMod); 1102 KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_GC); 1103 break; 1104 1105 /* 1106 * Nothing to do, just asserting sanity. 1107 */ 1108 case KLDRSTATE_INITIALIZING: 1109 /* Implies there is another load going on. */ 1110 KLDRDYLD_ASSERT(g_cActiveLoadCalls > 1); 1111 break; 1112 case KLDRSTATE_TERMINATING: 1113 /* GC in progress. */ 1114 KLDRDYLD_ASSERT(g_fActiveGC); 1115 break; 1116 case KLDRSTATE_PENDING_TERMINATION: 1117 case KLDRSTATE_PENDING_INITIALIZATION: 1118 case KLDRSTATE_PENDING_GC: 1119 case KLDRSTATE_PENDING_DESTROY: 1120 KLDRDYLD_ASSERT(rc); 1121 break; 1122 case KLDRSTATE_GOOD: 1123 break; 1124 1125 /* 1126 * Bad states. 1127 */ 1128 default: 1129 KLDRDYLD_ASSERT(!"drop frame bad state (a)"); 1130 break; 1131 } 1060 1132 } 1061 1133 … … 1080 1152 { 1081 1153 PKLDRDYLDMOD pMod = g_papStackMods[--iLoad1st]; 1082 switch (pMod->enmState) 1083 { 1084 /* 1085 * Just push it along to the PENDING_DESTROY state. 1086 */ 1087 case KLDRSTATE_MAPPED: 1088 KLDRDYLD_ASSERT(rc); 1089 kldrDyldModUnmap(pMod); 1090 KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY); 1091 break; 1092 1093 /* 1094 * Move back to PENDING_GC. 1095 */ 1096 case KLDRSTATE_RELOADED: 1097 KLDRDYLD_ASSERT(rc); 1098 pMod->enmState = KLDRSTATE_PENDING_GC; 1099 break; 1100 1101 /* 1102 * Unload prerequisites and unmap the modules. 1103 */ 1104 case KLDRSTATE_LOADED_PREREQUISITES: 1105 case KLDRSTATE_FIXED_UP: 1106 KLDRDYLD_ASSERT(rc); 1107 kldrDyldModUnloadPrerequisites(pMod); 1108 KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY); 1109 kldrDyldModUnmap(pMod); 1110 KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY); 1111 break; 1112 1113 /* 1114 * Unload prerequisites and push it back to PENDING_GC. 1115 */ 1116 case KLDRSTATE_RELOADED_LOADED_PREREQUISITES: 1117 case KLDRSTATE_RELOADED_FIXED_UP: 1118 kldrDyldModUnloadPrerequisites(pMod); 1119 KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_GC); 1120 break; 1121 1122 /* 1123 * Nothing to do, just asserting sanity. 1124 */ 1125 case KLDRSTATE_INITIALIZING: 1126 /* Implies there is another load going on. */ 1127 KLDRDYLD_ASSERT(g_cActiveLoadCalls > 1); 1128 break; 1129 case KLDRSTATE_TERMINATING: 1130 /* GC in progress. */ 1131 KLDRDYLD_ASSERT(g_fActiveGC); 1132 break; 1133 case KLDRSTATE_PENDING_TERMINATION: 1134 case KLDRSTATE_PENDING_INITIALIZATION: 1135 case KLDRSTATE_PENDING_GC: 1136 case KLDRSTATE_PENDING_DESTROY: 1137 KLDRDYLD_ASSERT(rc); 1138 break; 1139 case KLDRSTATE_GOOD: 1140 break; 1141 1142 /* 1143 * Bad states. 1144 */ 1145 default: 1146 KLDRDYLD_ASSERT(!"drop frame bad state (a)"); 1147 break; 1148 } 1154 kldrDyldStackCleanupOne(pMod, rc); 1149 1155 } 1150 1156 … … 1277 1283 { 1278 1284 PKLDRDYLDMOD pNext = pMod->Load.pNext; 1285 kldrDyldModAddRef(pMod); 1286 1279 1287 switch (pMod->enmState) 1280 1288 { … … 1284 1292 pMod->enmState = KLDRSTATE_GC; 1285 1293 kldrDyldModUnmap(pMod); 1294 KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY); 1286 1295 kldrDyldModDestroy(pMod); 1296 KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_DESTROYED); 1287 1297 break; 1288 1298 … … 1293 1303 break; 1294 1304 } 1305 1306 kldrDyldModDeref(pMod); 1295 1307 1296 1308 /* next */ -
trunk/kLdr/kLdrDyldMod.c
r2842 r2845 38 38 * Defined Constants And Macros * 39 39 *******************************************************************************/ 40 /** @def KLDRDYLDMOD_STRICT 41 * Define KLDRDYLDMOD_STRICT to enabled strict checks in kLdrDyld. */ 42 #define KLDRDYLDMOD_STRICT 1 43 40 44 /** @def KLDRDYLDMOD_ASSERT 41 45 * Assert that an expression is true when KLDRDYLD_STRICT is defined. 42 46 */ 43 #ifdef KLDRDYLD _STRICT47 #ifdef KLDRDYLDMOD_STRICT 44 48 # define KLDRDYLDMOD_ASSERT(expr) kldrHlpAssert(expr) 45 49 #else … … 50 54 51 55 /** 56 * Creates a module from the specified file provider instance. 57 * 58 * @returns 0 on success and *ppMod pointing to the new instance. 59 * On failure a non-zero kLdr status code is returned. 60 * @param pRdr The file provider instance. 61 * @param ppMod Where to put the pointer to the new module on success. 62 */ 63 int kldrDyldModCreate(PKLDRRDR pRdr, PPKLDRDYLDMOD ppMod) 64 { 65 PKLDRDYLDMOD pMod; 66 PKLDRMOD pRawMod; 67 int rc; 68 69 *ppMod = NULL; 70 71 /* 72 * Try open an module interpreter. 73 */ 74 rc = kLdrModOpenFromRdr(pRdr, &pRawMod); 75 if (rc) 76 return kldrDyldFailure(rc, "%s: %rc", kLdrRdrName(pRdr), rc); 77 78 /* 79 * Allocate a new dyld module. 80 */ 81 pMod = (PKLDRDYLDMOD)kldrHlpAlloc(sizeof(*pMod)); 82 if (pMod) 83 { 84 pMod->enmState = KLDRSTATE_OPEN; 85 pMod->pMod = pRawMod; 86 pMod->hMod = pMod; 87 pMod->cDepRefs = pMod->cDynRefs = pMod->cRefs = 0; 88 pMod->fExecutable = 0; 89 switch (pRawMod->enmType) 90 { 91 case KLDRTYPE_EXECUTABLE_FIXED: 92 case KLDRTYPE_EXECUTABLE_RELOCATABLE: 93 case KLDRTYPE_EXECUTABLE_PIC: 94 pMod->fExecutable = 1; 95 break; 96 } 97 pMod->fGlobalOrSpecific = 0; 98 pMod->fBindable = 0; 99 pMod->fInitList = 0; 100 pMod->fAlreadySeen = 0; 101 pMod->fMapped = 0; 102 pMod->f26Reserved = 0; 103 pMod->InitTerm.pNext = NULL; 104 pMod->InitTerm.pPrev = NULL; 105 pMod->Bind.pNext = NULL; 106 pMod->Bind.pPrev = NULL; 107 pMod->cPrereqs = 0; 108 pMod->papPrereqs = NULL; 109 pMod->u32MagicHead = KLDRDYMOD_MAGIC; 110 pMod->u32MagicTail = KLDRDYMOD_MAGIC; 111 112 /* it. */ 113 pMod->Load.pNext = NULL; 114 pMod->Load.pPrev = kLdrDyldTail; 115 if (kLdrDyldTail) 116 kLdrDyldTail->Load.pNext = pMod; 117 else 118 kLdrDyldHead = pMod; 119 kLdrDyldTail = pMod; 120 121 /* we're good. */ 122 *ppMod = pMod; 123 rc = 0; 124 } 125 else 126 { 127 kLdrModClose(pRawMod); 128 rc = KLDR_ERR_NO_MEMORY; 129 } 130 return rc; 131 } 132 133 134 /** 135 * Creates a module for a native module. 136 * 137 * @returns 0 on success and *ppMod pointing to the new instance. 138 * On failure a non-zero kLdr status code is returned. 139 * @param hNativeModule The native handle. 140 * @param ppMod Where to put the pointer to the new module on success. 141 * @remark This function ain't finalized yet. 142 */ 143 int kldrDyldModCreateNative(uintptr_t hNativeModule) 144 { 145 #if 0 146 /* 147 * Check if this module is already loaded by the native OS loader. 148 */ 149 rc = kld 150 { 151 #ifdef __OS2__ 152 HMODULE hmod = NULLHANDLE; 153 APIRET rc = DosQueryModuleHandle(kLdrRdrName(pRdr), &hmod); 154 if (!rc) 155 156 #elif defined(__WIN__) 157 HMODULE hmod = NULL; 158 if (GetModuleHandle(kLdrRdrName(pRdr)) 159 160 #else 161 # error "Port me" 162 #endif 163 } 164 #endif 165 return -1; 166 } 167 168 169 /** 170 * Destroys a module pending destruction. 171 * 172 * @param pMod The module in question. 173 */ 174 void kldrDyldModDestroy(PKLDRDYLDMOD pMod) 175 { 176 /* 177 * Validate the state. 178 */ 179 switch (pMod->enmState) 180 { 181 case KLDRSTATE_PENDING_DESTROY: 182 case KLDRSTATE_GC: 183 break; 184 default: 185 KLDRDYLDMOD_ASSERT(!"Invalid state"); 186 break; 187 } 188 KLDRDYLDMOD_ASSERT(!pMod->fInitList); 189 KLDRDYLDMOD_ASSERT(!pMod->cDynRefs); 190 KLDRDYLDMOD_ASSERT(!pMod->cDepRefs); 191 192 193 /* 194 * Ensure that the module is unmapped. 195 */ 196 if (pMod->fMapped) 197 kldrDyldModUnmap(pMod); 198 } 199 200 201 /** 202 * Unlinks the module from any list it might be in. 203 * It is assumed that the module is at least linked into the load list. 204 * 205 * @param pMod The moduel. 206 */ 207 static void kldrDyldModUnlink(PKLDRDYLDMOD pMod) 208 { 209 /* load list */ 210 if (pMod->Load.pNext) 211 pMod->Load.pNext->Load.pPrev = pMod->Load.pPrev; 212 else 213 kLdrDyldTail = pMod->Load.pPrev; 214 if (pMod->Load.pPrev) 215 pMod->Load.pPrev->Load.pNext = pMod->Load.pNext; 216 else 217 kLdrDyldHead = pMod->Load.pNext; 218 219 /* bind list */ 220 if (pMod->fBindable) 221 kldrDyldModClearBindable(pMod); 222 223 /* init term */ 224 if (pMod->fInitList) 225 { 226 KLDRDYLDMOD_ASSERT(pMod->enmState < KLDRSTATE_INITIALIZATION_FAILED); 227 pMod->fInitList = 0; 228 if (pMod->InitTerm.pNext) 229 pMod->InitTerm.pNext->InitTerm.pPrev = pMod->InitTerm.pPrev; 230 else 231 g_pkLdrDyldInitTail = pMod->InitTerm.pPrev; 232 if (pMod->InitTerm.pPrev) 233 pMod->InitTerm.pPrev->InitTerm.pNext = pMod->InitTerm.pNext; 234 else 235 g_pkLdrDyldInitHead = pMod->InitTerm.pNext; 236 } 237 else if (pMod->enmState > KLDRSTATE_INITIALIZATION_FAILED) 238 { 239 KLDRDYLDMOD_ASSERT(pMod->enmState >= KLDRSTATE_GOOD); 240 if (pMod->InitTerm.pNext) 241 pMod->InitTerm.pNext->InitTerm.pPrev = pMod->InitTerm.pPrev; 242 else 243 g_pkLdrDyldTermTail = pMod->InitTerm.pPrev; 244 if (pMod->InitTerm.pPrev) 245 pMod->InitTerm.pPrev->InitTerm.pNext = pMod->InitTerm.pNext; 246 else 247 g_pkLdrDyldTermHead = pMod->InitTerm.pNext; 248 } 249 pMod->InitTerm.pNext = NULL; 250 pMod->InitTerm.pPrev = NULL; 251 } 252 253 254 /** 255 * Adds a reference to the module making sure it won't be freed just yet. 256 * 257 * @param pMod The module. 258 */ 259 void kldrDyldModAddRef(PKLDRDYLDMOD pMod) 260 { 261 pMod->cRefs++; 262 } 263 264 265 /** 266 * Dereference a module. 267 * 268 * @param pMod 269 */ 270 void kldrDyldModDeref(PKLDRDYLDMOD pMod) 271 { 272 /* validate input */ 273 KLDRDYLDMOD_ASSERT(pMod->cRefs > 0); 274 KLDRDYLDMOD_ASSERT(pMod->cRefs >= pMod->cDepRefs + pMod->cDynRefs); 275 KLDRDYLDMOD_ASSERT(pMod->enmState > KLDRSTATE_INVALID && pMod->enmState <= KLDRSTATE_END); 276 277 /* decrement. */ 278 if (pMod->cRefs > 0) 279 pMod->cRefs--; 280 281 /* execute delayed freeing. */ 282 if ( pMod->enmState == KLDRSTATE_DESTROYED 283 && !pMod->cRefs) 284 kldrHlpFree(pMod); 285 } 286 287 288 /** 289 * Increment the count of modules depending on this module. 290 * 291 * @param pMod The module. 292 * @param pDep The module which depends on us. 293 */ 294 void kldrDyldModAddDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep) 295 { 296 (void)pDep; 297 298 /* validate state */ 299 switch (pMod->enmState) 300 { 301 case KLDRSTATE_MAPPED: 302 case KLDRSTATE_RELOADED: 303 case KLDRSTATE_LOADED_PREREQUISITES: 304 case KLDRSTATE_RELOADED_LOADED_PREREQUISITES: 305 case KLDRSTATE_PENDING_INITIALIZATION: 306 case KLDRSTATE_INITIALIZING: 307 case KLDRSTATE_GOOD: 308 break; 309 default: 310 KLDRDYLDMOD_ASSERT(!"invalid state"); 311 break; 312 313 } 314 KLDRDYLDMOD_ASSERT(pMod->enmState > KLDRSTATE_INVALID && pMod->enmState <= KLDRSTATE_END); 315 pMod->cRefs++; 316 pMod->cDepRefs++; 317 } 318 319 320 /** 321 * Drop a dependency. 322 * 323 * @param pMod The module. 324 * @param pDep The module which depends on us. 325 */ 326 void kldrDyldModRemoveDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep) 327 { 328 KLDRDYLDMOD_ASSERT(pMod->cDepRefs > 0); 329 if (pMod->cDepRefs == 0) 330 return; 331 KLDRDYLDMOD_ASSERT(pMod->cDepRefs <= pMod->cRefs); 332 KLDRDYLDMOD_ASSERT(pMod->enmState >= KLDRSTATE_MAPPED && pMod->enmState <= KLDRSTATE_PENDING_DESTROY); 333 334 pMod->cRefs--; 335 pMod->cDepRefs--; 336 if ( pMod->cDepRefs > 0 337 || pMod->cDynRefs > 0) 338 return; 339 340 /* 341 * The module should be unloaded. 342 */ 343 kldrDyldModUnloadPrerequisites(pMod); 344 } 345 346 347 /** 348 * Increment the dynamic load count. 349 * 350 * @returns 0 351 * @param pMod The module. 352 */ 353 int kldrDyldModDynamicLoad(PKLDRDYLDMOD pMod) 354 { 355 KLDRDYLDMOD_ASSERT( pMod->enmState == KLDRSTATE_GOOD 356 || pMod->enmState == KLDRSTATE_PENDING_INITIALIZATION 357 || pMod->enmState == KLDRSTATE_INITIALIZING); 358 pMod->cRefs++; 359 pMod->cDynRefs++; 360 return 0; 361 } 362 363 364 /** 52 365 * Decrement the dynamic load count of the module and unload the module 53 366 * if the total reference count reaches zero. … … 69 382 pMod->cRefs--; 70 383 pMod->cDynRefs--; 71 if (pMod->cRefs > 0) 384 if ( pMod->cDynRefs > 0 385 || pMod->cDepRefs > 0) 72 386 return 0; 73 387 … … 150 464 * of all affected modules. 151 465 * 152 * This function will cause a state transition otPENDING_DESTROY, PENDING_GC466 * This function will cause a state transition to PENDING_DESTROY, PENDING_GC 153 467 * or PENDING_TERMINATION depending on the module state. There is one exception 154 468 * to this, and that's INITIALIZATION_FAILED, where the state will not be changed. … … 194 508 195 509 196 197 198 199 void kldrDyldModDeref(PKLDRDYLDMOD pMod) 200 { 201 /* validate input */ 202 KLDRDYLDMOD_ASSERT(pMod->enmState > KLDRSTATE_INVALID && pMod->enmState < KLDRSTATE_END); 510 int kldrDyldModLoadPrerequisites(PKLDRDYLDMOD pMod, const char *pszPrefix, const char *pszSuffix, 511 KLDRDYLDSEARCH enmSearch, unsigned fFlags) 512 { 513 return -1; 514 } 515 516 517 int kldrDyldModCheckPrerequisites(PKLDRDYLDMOD pMod) 518 { 519 return -1; 520 } 521 522 523 /** 524 * Marks the module as global instead of being specific. 525 * 526 * A global module can be a matching result when the request 527 * doesn't specify a path. A specific module will not match 528 * unless the path also matches. 529 * 530 * @param pMod The module. 531 */ 532 void kldrDyldModMarkGlobal(PKLDRDYLDMOD pMod) 533 { 534 pMod->fGlobalOrSpecific = 1; 535 } 536 537 /** 538 * Marks the module as specific instead of global. 539 * 540 * See kldrDyldModMarkGlobal for an explanation of the two terms. 541 * 542 * @param pMod The module. 543 */ 544 void kldrDyldModMarkSpecific(PKLDRDYLDMOD pMod) 545 { 546 pMod->fGlobalOrSpecific = 0; 547 } 548 549 550 /** 551 * Marks a module as bindable, i.e. it'll be considered when 552 * resolving names the unix way. 553 * 554 * @param pMod The module. 555 * @param fDeep When set the module will be inserted at the head of the 556 * module list used to resolve symbols. This means that the 557 * symbols in this module will be prefered of all the other 558 * modules. 559 */ 560 void kldrDyldModSetBindable(PKLDRDYLDMOD pMod, unsigned fDeep) 561 { 562 KLDRDYLDMOD_ASSERT(pMod->enmState >= KLDRSTATE_OPEN && pMod->enmState < KLDRSTATE_PENDING_GC); 563 if (!pMod->fBindable) 564 { 565 pMod->fBindable = 1; 566 if (!fDeep) 567 { 568 pMod->Bind.pNext = NULL; 569 pMod->Bind.pPrev = g_pkLdrDyldBindTail; 570 if (g_pkLdrDyldBindTail) 571 g_pkLdrDyldBindTail->Bind.pNext = pMod; 572 else 573 g_pkLdrDyldBindHead = pMod; 574 g_pkLdrDyldBindTail = pMod; 575 } 576 else 577 { 578 pMod->Bind.pPrev = NULL; 579 pMod->Bind.pNext = g_pkLdrDyldBindHead; 580 if (g_pkLdrDyldBindHead) 581 g_pkLdrDyldBindHead->Bind.pPrev = pMod; 582 else 583 g_pkLdrDyldBindTail = pMod; 584 g_pkLdrDyldBindHead = pMod; 585 } 586 } 587 } 588 589 590 /** 591 * Marks a module as not bindable, i.e. it will not be considered when 592 * resolving names the unix way. 593 * 594 * @param pMod The module. 595 */ 596 void kldrDyldModClearBindable(PKLDRDYLDMOD pMod) 597 { 598 KLDRDYLDMOD_ASSERT(pMod->enmState >= KLDRSTATE_OPEN && pMod->enmState < KLDRSTATE_PENDING_DESTROY); 599 if (pMod->fBindable) 600 { 601 pMod->fBindable = 0; 602 if (pMod->Bind.pPrev) 603 pMod->Bind.pPrev->Bind.pNext = pMod->Bind.pNext; 604 else 605 g_pkLdrDyldBindHead = pMod->Bind.pNext; 606 if (pMod->Bind.pNext) 607 pMod->Bind.pNext->Bind.pPrev = pMod->Bind.pPrev; 608 else 609 g_pkLdrDyldBindTail = pMod->Bind.pPrev; 610 pMod->Bind.pNext = NULL; 611 pMod->Bind.pPrev = NULL; 612 } 613 } 614 615 616 /** 617 * Maps an open module. 618 * 619 * On success the module will be in the MAPPED state. 620 * 621 * @returns 0 on success, non-zero native OS or kLdr status code on failure. 622 * @param pMod The module which needs to be unmapped and set pending for destruction. 623 */ 624 int kldrDyldModMap(PKLDRDYLDMOD pMod) 625 { 626 int rc; 627 628 /* sanity */ 203 629 KLDRDYLDMOD_ASSERT(pMod->cRefs > 0); 204 KLDRDYLDMOD_ASSERT(pMod->cRefs >= pMod->cDepRefs + pMod->cDynRefs); 205 206 /* decrement. */ 207 if (pMod->cRefs > 0) 208 pMod->cRefs--; 209 210 /* 211 * Drop prerequisites for stats that implies that no recursion can have taken place yet. 212 * This ASSUMES that we're only dereferencing modules when an operation completes. 213 * (This is *required* for the reloaded state.) 214 */ 630 KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_OPEN); 631 KLDRDYLDMOD_ASSERT(!pMod->fMapped); 632 if (pMod->fMapped) 633 return 0; 634 635 /* do the job. */ 636 rc = kLdrModMap(pMod->pMod); 637 if (!rc) 638 { 639 pMod->fMapped = 1; 640 pMod->enmState = KLDRSTATE_MAPPED; 641 } 642 return rc; 643 } 644 645 646 /** 647 * Unmaps the module, unlinks it from everywhere marks it PENDING_DESTROY. 648 * 649 * @returns 0 on success, non-zero native OS or kLdr status code on failure. 650 * @param pMod The module which needs to be unmapped and set pending for destruction. 651 */ 652 int kldrDyldModUnmap(PKLDRDYLDMOD pMod) 653 { 654 int rc; 655 656 /* sanity */ 657 KLDRDYLDMOD_ASSERT(pMod->cRefs > 0); 658 KLDRDYLDMOD_ASSERT(pMod->fMapped); 215 659 switch (pMod->enmState) 216 660 { 217 661 case KLDRSTATE_MAPPED: 218 case KLDRSTATE_LOADED_PREREQUISITES:219 case KLDRSTATE_FIXED_UP:220 case KLDRSTATE_RELOADED:221 kldrDyldModUnloadPrerequisites(pMod);222 pMod->enmState = KLDRSTATE_PENDING_GC;223 break;224 225 case KLDRSTATE_PENDING_INITIALIZATION:226 case KLDRSTATE_INITIALIZING:227 case KLDRSTATE_GOOD:228 case KLDRSTATE_PENDING_TERMINATION:229 case KLDRSTATE_TERMINATING:230 case KLDRSTATE_PENDING_GC:231 662 case KLDRSTATE_GC: 232 663 case KLDRSTATE_PENDING_DESTROY: 233 664 break; 234 235 665 default: 236 KLDRDYLDMOD_ASSERT(!" Invalid derefstate");237 break;238 } 239 240 /* 241 * Also drop prerequisites if noone is referencing the module.242 */243 if (!pMod->cDepRefs && !pMod->cDynRefs)244 {245 switch (pMod->enmState)666 KLDRDYLDMOD_ASSERT(!"invalid state"); 667 return -1; 668 } 669 670 /* do the job. */ 671 rc = kLdrModUnmap(pMod->pMod); 672 if (!rc) 673 { 674 pMod->fMapped = 0; 675 if (pMod->enmState < KLDRSTATE_PENDING_DESTROY) 246 676 { 247 case KLDRSTATE_MAPPED: 248 case KLDRSTATE_LOADED_PREREQUISITES: 249 case KLDRSTATE_FIXED_UP: 250 case KLDRSTATE_RELOADED: 251 /* already dropped. */ 252 break; 253 254 case KLDRSTATE_PENDING_INITIALIZATION: 255 kldrDyldModUnloadPrerequisites(pMod); 256 pMod->enmState = KLDRSTATE_PENDING_GC; 257 break; 258 259 case KLDRSTATE_GOOD: 260 pMod->enmState = KLDRSTATE_PENDING_TERMINATION; 261 case KLDRSTATE_PENDING_TERMINATION: 262 case KLDRSTATE_PENDING_GC: 263 kldrDyldModUnloadPrerequisites(pMod); 264 break; 265 266 case KLDRSTATE_TERMINATING: 267 case KLDRSTATE_GC: 268 case KLDRSTATE_PENDING_DESTROY: 269 break; 270 271 default: 272 KLDRDYLDMOD_ASSERT(!"Invalid deref state (b)"); 273 break; 677 pMod->enmState = KLDRSTATE_PENDING_DESTROY; 678 kldrDyldModUnlink(pMod); 274 679 } 275 680 } 276 277 /* 278 * If there are no references whatsoever now and the module 279 * is pending destruction, destroy it. 280 */ 281 if ( !pMod->cRefs 282 && ( pMod->enmState == KLDRSTATE_PENDING_DESTROY 283 || pMod->enmState == KLDRSTATE_GC)) 284 kldrDyldModDestroy(pMod); 285 } 681 return rc; 682 } 683 684 685 /** 686 * Applies fixups to a module which prerequisistes has been 687 * successfully loaded. 688 * 689 * @returns 0 on success, non-zero native OS or kLdr status code on failure. 690 * @param pMod The module which needs to be unmapped and set pending for destruction. 691 */ 692 int kldrDyldModFixup(PKLDRDYLDMOD pMod) 693 { 694 int rc; 695 696 /* sanity */ 697 KLDRDYLDMOD_ASSERT(pMod->cRefs > 0); 698 KLDRDYLDMOD_ASSERT( pMod->enmState == KLDRSTATE_LOADED_PREREQUISITES 699 || pMod->enmState == KLDRSTATE_RELOADED_LOADED_PREREQUISITES); 700 701 /* do the job */ 702 rc = kLdrModFixupMapping(pMod->pMod, NULL, NULL);/// @todo fixme. 703 if (!rc) 704 pMod->enmState = KLDRSTATE_FIXED_UP; 705 return rc; 706 } 707 708 709 int kldrDyldModCallInit(PKLDRDYLDMOD pMod); 710 void kldrDyldModCallTerm(PKLDRDYLDMOD pMod); 711 712 int kldrDyldModReload(PKLDRDYLDMOD pMod); 713 int kldrDyldModAttachThread(PKLDRDYLDMOD pMod); 714 int kldrDyldModDetachThread(PKLDRDYLDMOD pMod); 715 int kldrDyldModGetStackInfo(PKLDRDYLDMOD pMod, void **ppvStack, size_t *pcbStack); 716 int kldrDyldModStartExe(PKLDRDYLDMOD pMod); 717 718 int kldrDyldModGetName(PKLDRDYLDMOD pMod, char *pszName, size_t cchName); 719 int kldrDyldModGetFilename(PKLDRDYLDMOD pMod, char *pszFilename, size_t cchFilename); 720 int kldrDyldModQuerySymbol(PKLDRDYLDMOD pMod, uint32_t uSymbolOrdinal, const char *pszSymbolName, uintptr_t *pValue, uint32_t *pfKind); 721 722 -
trunk/kLdr/kLdrInternal.h
r2843 r2845 201 201 KLDRSTATE_PENDING_DESTROY, 202 202 203 /** The module has been destroyed and is no longer valid. 203 /** The module has been destroyed but not freed yet. 204 * 205 * This happens when a module ends up being destroyed when cRefs > 0. The 206 * module structure will be freed when cRefs reaches 0. 204 207 * 205 208 * Prev state: GC, PENDING_DESTROY … … 246 249 * this module is already seen and shouldn't be processed again. */ 247 250 uint32_t fAlreadySeen : 1; 251 /** Set if the module is currently mapped. 252 * This is used to avoid unnecessary calls to kLdrModUnmap during cleanup. */ 253 uint32_t fMapped : 1; 248 254 /** Reserved for future use. */ 249 uint32_t f Reserved : 27;255 uint32_t f26Reserved : 26; 250 256 /** The load list linkage. */ 251 257 struct … … 312 318 313 319 int kldrDyldModCreate(PKLDRRDR pRdr, PPKLDRDYLDMOD ppMod); 314 intkldrDyldModDestroy(PKLDRDYLDMOD pMod);315 intkldrDyldModAddRef(PKLDRDYLDMOD pMod);320 void kldrDyldModDestroy(PKLDRDYLDMOD pMod); 321 void kldrDyldModAddRef(PKLDRDYLDMOD pMod); 316 322 void kldrDyldModDeref(PKLDRDYLDMOD pMod); 317 intkldrDyldModAddDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep);323 void kldrDyldModAddDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep); 318 324 void kldrDyldModRemoveDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep); 319 325 int kldrDyldModDynamicLoad(PKLDRDYLDMOD pMod); 320 326 int kldrDyldModDynamicUnload(PKLDRDYLDMOD pMod); 321 int kldrDyldModMarkGlobal(PKLDRDYLDMOD pMod); 322 int kldrDyldModMarkSpecific(PKLDRDYLDMOD pMod); 323 int kldrDyldModSetBindable(PKLDRDYLDMOD pMod); 324 int kldrDyldModClearBindable(PKLDRDYLDMOD pMod); 325 int kldrDyldModSetDeepBindable(PKLDRDYLDMOD pMod); 326 int kldrDyldModClearDeepBindable(PKLDRDYLDMOD pMod); 327 void kldrDyldModMarkGlobal(PKLDRDYLDMOD pMod); 328 void kldrDyldModMarkSpecific(PKLDRDYLDMOD pMod); 329 void kldrDyldModSetBindable(PKLDRDYLDMOD pMod, unsigned fDeep); 330 void kldrDyldModClearBindable(PKLDRDYLDMOD pMod); 327 331 int kldrDyldModMap(PKLDRDYLDMOD pMod); 328 332 int kldrDyldModUnmap(PKLDRDYLDMOD pMod); … … 345 349 346 350 347 int kldrDyldFailure(int rc, const char *pszF ilename, ...);351 int kldrDyldFailure(int rc, const char *pszFormat, ...); 348 352 int kldrInit(void); 349 353 void kldrTerm(void); … … 356 360 * (This is exported, so no prefix.) */ 357 361 extern PKLDRDYLDMOD kLdrDyldTail; 362 /** Pointer to the head module of the initialization list. 363 * The outermost load call will pop elements from this list in LIFO order (i.e. 364 * from the tail). The list is only used during non-recursive initialization 365 * and may therefore share the pNext/pPrev members with the termination list 366 * since we don't push a module onto the termination list untill it has been 367 * successfully initialized. */ 368 extern PKLDRDYLDMOD g_pkLdrDyldInitHead; 369 /** Pointer to the tail module of the initalization list. */ 370 extern PKLDRDYLDMOD g_pkLdrDyldInitTail; 358 371 /** Pointer to the head module of the termination order list. */ 359 372 extern PKLDRDYLDMOD g_pkLdrDyldTermHead;
Note:
See TracChangeset
for help on using the changeset viewer.