- Timestamp:
- Jan 31, 2009 1:52:14 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kLdr/kLdrModMachO.c
r22 r23 131 131 /** The size of the mapped image. */ 132 132 KLDRADDR cbImage; 133 /** The RVA of the Global Offset Table. */134 KLDRADDR GotRVA;135 133 /** Whether we're creating a global offset table segment. 136 134 * This dependes on the cputype and image type. */ 137 135 KBOOL fMakeGot; 136 /** The size of a indirect GOT jump stub entry. 137 * This is 0 if not needed. */ 138 KU8 cbJmpStub; 138 139 /** When set the sections in the load command segments must be used when 139 140 * mapping or loading the image. */ … … 157 158 /** Pointer to the loaded string table. */ 158 159 char *pchStrings; 160 161 /** The RVA of the Global Offset Table. */ 162 KLDRADDR GotRVA; 163 /** The RVA of the indirect GOT jump stubs. */ 164 KLDRADDR JmpStubsRVA; 159 165 160 166 /** The number of sections. */ … … 270 276 KSIZE cb; 271 277 KBOOL fMakeGot; 278 KU8 cbJmpStub; 272 279 int rc; 273 280 *ppModMachO = NULL; … … 301 308 case CPU_TYPE_X86: 302 309 fMakeGot = K_FALSE; 310 cbJmpStub = 0; 303 311 break; 304 312 case CPU_TYPE_X86_64: 305 313 fMakeGot = s.Hdr32.filetype == MH_OBJECT; 314 cbJmpStub = fMakeGot ? 8 : 0; 306 315 break; 307 316 default: … … 426 435 pModMachO->LinkAddress = 0; 427 436 pModMachO->cbImage = 0; 428 pModMachO->GotRVA = NIL_KLDRADDR;429 437 pModMachO->fMakeGot = fMakeGot; 438 pModMachO->cbJmpStub = cbJmpStub; 430 439 pModMachO->fMapUsingLoadCommandSections = K_FALSE; 431 440 pModMachO->offSymbols = 0; … … 435 444 pModMachO->cchStrings = 0; 436 445 pModMachO->pchStrings = NULL; 446 pModMachO->GotRVA = NIL_KLDRADDR; 447 pModMachO->JmpStubsRVA = NIL_KLDRADDR; 437 448 pModMachO->cSections = cSections; 438 449 pModMachO->paSections = (PKLDRMODMACHOSECT)&pModMachO->aSegments[pModMachO->pMod->cSegments]; … … 1294 1305 ? sizeof(KU32) 1295 1306 : sizeof(KU64); 1307 KU32 cbGot = pModMachO->cSymbols * cbPtr; 1308 KU32 cbJmpStubs; 1296 1309 1297 1310 if (pSeg != &pModMachO->pMod->aSegments[0]) … … 1299 1312 else 1300 1313 pModMachO->GotRVA = 0; 1314 1315 if (pModMachO->cbJmpStub) 1316 { 1317 cbGot = K_ALIGN_Z(cbGot, 64); 1318 pModMachO->JmpStubsRVA = pModMachO->GotRVA + cbGot; 1319 cbJmpStubs = pModMachO->cbJmpStub * pModMachO->cSymbols; 1320 } 1321 else 1322 { 1323 pModMachO->JmpStubsRVA = NIL_KLDRADDR; 1324 cbJmpStubs = 0; 1325 } 1301 1326 1302 1327 pSeg->pvUser = NULL; … … 1307 1332 pSeg->fFlags = 0; 1308 1333 pSeg->enmProt = KPROT_READONLY; 1309 pSeg->cb = cb Ptr * pModMachO->cSymbols;1334 pSeg->cb = cbGot + cbJmpStubs; 1310 1335 pSeg->Alignment = 64; 1311 1336 pSeg->LinkAddress = pModMachO->LinkAddress + pModMachO->GotRVA; … … 2775 2800 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_BAD_FIXUP); 2776 2801 } 2777 if (Fixup.r.r_pcrel)2778 SymAddr += Fixup.r.r_address + pFixupSect->LinkAddress;2779 2802 2780 2803 /* Add symbol / section address. */ … … 2806 2829 } 2807 2830 SymAddr = sizeof(KU64) * Fixup.r.r_symbolnum + pModMachO->GotRVA + NewBaseAddress; 2831 KLDRMODMACHO_CHECK_RETURN(Fixup.r.r_length == 2, KLDR_ERR_BAD_FIXUP); 2832 SymAddr -= 4; 2808 2833 break; 2809 2834 … … 2823 2848 KLDRMODMACHO_CHECK_RETURN(!Fixup.r.r_pcrel, KLDR_ERR_BAD_FIXUP); 2824 2849 break; 2825 case X86_64_RELOC_SIGNED:2826 break;2827 2850 case X86_64_RELOC_BRANCH: 2828 switch (Fixup.r.r_length) 2829 { 2830 case 0: SymAddr -= 1; break; 2831 case 1: SymAddr -= 2; break; 2832 case 2: SymAddr -= 4; break; 2833 case 3: SymAddr -= 8; break; 2834 } 2851 KLDRMODMACHO_CHECK_RETURN(Fixup.r.r_length == 2, KLDR_ERR_BAD_FIXUP); 2852 SymAddr -= 4; 2835 2853 break; 2836 2854 case X86_64_RELOC_SIGNED_1: SymAddr -= 1; break; 2837 2855 case X86_64_RELOC_SIGNED_2: SymAddr -= 2; break; 2856 case X86_64_RELOC_SIGNED: 2838 2857 case X86_64_RELOC_SIGNED_4: SymAddr -= 4; break; 2839 2858 default: … … 2853 2872 2854 2873 case MACHO_N_UNDF: 2874 /* branch to an external symbol may have to take a short detour. */ 2875 if ( Fixup.r.r_type == X86_64_RELOC_BRANCH 2876 && SymAddr + Fixup.r.r_address + pFixupSect->RVA + NewBaseAddress 2877 - pSym->n_value 2878 + KU64_C(0x80000000) 2879 >= KU64_C(0xffffff20)) 2880 SymAddr += pModMachO->cbJmpStub * Fixup.r.r_symbolnum + pModMachO->JmpStubsRVA + NewBaseAddress; 2881 else 2882 SymAddr += pSym->n_value; 2883 break; 2884 2855 2885 case MACHO_N_ABS: 2856 2886 SymAddr += pSym->n_value; … … 3220 3250 * Perform relocations. 3221 3251 */ 3222 rc = kldrModMachORelocateBits(pMod, pvBits, BaseAddress, pModMachO->LinkAddress, pfnGetImport, pvUser); 3223 if (rc) 3224 return rc; 3252 return kldrModMachORelocateBits(pMod, pvBits, BaseAddress, pModMachO->LinkAddress, pfnGetImport, pvUser); 3253 } 3254 3255 3256 /** @copydoc kLdrModRelocateBits */ 3257 static int kldrModMachORelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress, 3258 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser) 3259 { 3260 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData; 3261 int rc; 3262 3263 /* 3264 * Call workers to do the jobs. 3265 */ 3266 if (pModMachO->Hdr.filetype == MH_OBJECT) 3267 { 3268 rc = kldrModMachOObjDoImports(pModMachO, pfnGetImport, pvUser); 3269 if (!rc) 3270 rc = kldrModMachOObjDoFixups(pModMachO, pvBits, NewBaseAddress); 3271 3272 } 3273 else 3274 rc = KLDR_ERR_TODO; 3275 /*{ 3276 rc = kldrModMachODoFixups(pModMachO, pvBits, NewBaseAddress, OldBaseAddress, pfnGetImport, pvUser); 3277 if (!rc) 3278 rc = kldrModMachODoImports(pModMachO, pvBits, pfnGetImport, pvUser); 3279 }*/ 3225 3280 3226 3281 /* … … 3228 3283 * segment when present. 3229 3284 */ 3230 if (pModMachO->fMakeGot) 3231 rc = kldrModMachOMakeGOT(pModMachO, pvBits, BaseAddress); 3285 if (!rc && pModMachO->fMakeGot) 3286 rc = kldrModMachOMakeGOT(pModMachO, pvBits, NewBaseAddress); 3287 3232 3288 return rc; 3233 3289 } … … 3271 3327 KU64 *paGOT = (KU64 *)((KU8 *)pvBits + pModMachO->GotRVA); 3272 3328 while (iSym-- > 0) 3329 { 3273 3330 switch (paSyms[iSym].n_type & MACHO_N_TYPE) 3274 3331 { … … 3287 3344 break; 3288 3345 } 3346 } 3347 3348 if (pModMachO->JmpStubsRVA != NIL_KLDRADDR) 3349 { 3350 KU32 iSym = pModMachO->cSymbols; 3351 switch (pModMachO->Hdr.cputype) 3352 { 3353 /* 3354 * AMD64 is simple since the GOT and the indirect jmps are parallel 3355 * arrays with entries of the same size. The relative offset will 3356 * be the the same for each entry, kind of nice. :-) 3357 */ 3358 case CPU_TYPE_X86_64: 3359 { 3360 KU64 *paJmps = (KU64 *)((KU8 *)pvBits + pModMachO->JmpStubsRVA); 3361 KI32 off; 3362 KU64 u64Tmpl; 3363 union 3364 { 3365 KU8 ab[8]; 3366 KU64 u64; 3367 } Tmpl; 3368 3369 /* create the template. */ 3370 off = pModMachO->GotRVA - (pModMachO->JmpStubsRVA + 6); 3371 Tmpl.ab[0] = 0xff; /* jmp [GOT-entry wrt RIP] */ 3372 Tmpl.ab[1] = 0x25; 3373 Tmpl.ab[2] = off & 0xff; 3374 Tmpl.ab[3] = (off >> 8) & 0xff; 3375 Tmpl.ab[4] = (off >> 16) & 0xff; 3376 Tmpl.ab[5] = (off >> 24) & 0xff; 3377 Tmpl.ab[6] = 0xcc; 3378 Tmpl.ab[7] = 0xcc; 3379 u64Tmpl = Tmpl.u64; 3380 3381 /* copy the template to every jmp table entry. */ 3382 while (iSym-- > 0) 3383 paJmps[iSym] = u64Tmpl; 3384 break; 3385 } 3386 3387 default: 3388 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); 3389 } 3390 } 3289 3391 } 3290 3392 return 0; 3291 }3292 3293 3294 /** @copydoc kLdrModRelocateBits */3295 static int kldrModMachORelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,3296 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)3297 {3298 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;3299 int rc;3300 3301 /*3302 * Call workers to do the jobs.3303 */3304 if (pModMachO->Hdr.filetype == MH_OBJECT)3305 {3306 rc = kldrModMachOObjDoImports(pModMachO, pfnGetImport, pvUser);3307 if (!rc)3308 rc = kldrModMachOObjDoFixups(pModMachO, pvBits, NewBaseAddress);3309 3310 }3311 else3312 rc = KLDR_ERR_TODO;3313 /*{3314 rc = kldrModMachODoFixups(pModMachO, pvBits, NewBaseAddress, OldBaseAddress, pfnGetImport, pvUser);3315 if (!rc)3316 rc = kldrModMachODoImports(pModMachO, pvBits, pfnGetImport, pvUser);3317 }*/3318 3319 return rc;3320 3393 } 3321 3394
Note:
See TracChangeset
for help on using the changeset viewer.