VirtualBox

Changeset 23 in kStuff for trunk


Ignore:
Timestamp:
Jan 31, 2009 1:52:14 AM (16 years ago)
Author:
bird
Message:

kLdrModMachO.c: (Re-)Make the GOT in the right place, generate indirect GOT jumps and send AMD64 BRANCH fixups there if the displacement is to large, some AMD64 fixup bugfixes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kLdr/kLdrModMachO.c

    r22 r23  
    131131    /** The size of the mapped image. */
    132132    KLDRADDR                cbImage;
    133     /** The RVA of the Global Offset Table.  */
    134     KLDRADDR                GotRVA;
    135133    /** Whether we're creating a global offset table segment.
    136134     * This dependes on the cputype and image type. */
    137135    KBOOL                   fMakeGot;
     136    /** The size of a indirect GOT jump stub entry.
     137     * This is 0 if not needed. */
     138    KU8                     cbJmpStub;
    138139    /** When set the sections in the load command segments must be used when
    139140     * mapping or loading the image. */
     
    157158    /** Pointer to the loaded string table. */
    158159    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;
    159165
    160166    /** The number of sections. */
     
    270276    KSIZE cb;
    271277    KBOOL fMakeGot;
     278    KU8 cbJmpStub;
    272279    int rc;
    273280    *ppModMachO = NULL;
     
    301308        case CPU_TYPE_X86:
    302309            fMakeGot = K_FALSE;
     310            cbJmpStub = 0;
    303311            break;
    304312        case CPU_TYPE_X86_64:
    305313            fMakeGot = s.Hdr32.filetype == MH_OBJECT;
     314            cbJmpStub = fMakeGot ? 8 : 0;
    306315            break;
    307316        default:
     
    426435    pModMachO->LinkAddress = 0;
    427436    pModMachO->cbImage = 0;
    428     pModMachO->GotRVA = NIL_KLDRADDR;
    429437    pModMachO->fMakeGot = fMakeGot;
     438    pModMachO->cbJmpStub = cbJmpStub;
    430439    pModMachO->fMapUsingLoadCommandSections = K_FALSE;
    431440    pModMachO->offSymbols = 0;
     
    435444    pModMachO->cchStrings = 0;
    436445    pModMachO->pchStrings = NULL;
     446    pModMachO->GotRVA = NIL_KLDRADDR;
     447    pModMachO->JmpStubsRVA = NIL_KLDRADDR;
    437448    pModMachO->cSections = cSections;
    438449    pModMachO->paSections = (PKLDRMODMACHOSECT)&pModMachO->aSegments[pModMachO->pMod->cSegments];
     
    12941305                    ? sizeof(KU32)
    12951306                    : sizeof(KU64);
     1307        KU32 cbGot = pModMachO->cSymbols * cbPtr;
     1308        KU32 cbJmpStubs;
    12961309
    12971310        if (pSeg != &pModMachO->pMod->aSegments[0])
     
    12991312        else
    13001313            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        }
    13011326
    13021327        pSeg->pvUser = NULL;
     
    13071332        pSeg->fFlags = 0;
    13081333        pSeg->enmProt = KPROT_READONLY;
    1309         pSeg->cb = cbPtr * pModMachO->cSymbols;
     1334        pSeg->cb = cbGot + cbJmpStubs;
    13101335        pSeg->Alignment = 64;
    13111336        pSeg->LinkAddress = pModMachO->LinkAddress + pModMachO->GotRVA;
     
    27752800                KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_BAD_FIXUP);
    27762801        }
    2777         if (Fixup.r.r_pcrel)
    2778             SymAddr += Fixup.r.r_address + pFixupSect->LinkAddress;
    27792802
    27802803        /* Add symbol / section address. */
     
    28062829                    }
    28072830                    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;
    28082833                    break;
    28092834
     
    28232848                            KLDRMODMACHO_CHECK_RETURN(!Fixup.r.r_pcrel, KLDR_ERR_BAD_FIXUP);
    28242849                            break;
    2825                         case X86_64_RELOC_SIGNED:
    2826                             break;
    28272850                        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;
    28352853                            break;
    28362854                        case X86_64_RELOC_SIGNED_1: SymAddr -= 1; break;
    28372855                        case X86_64_RELOC_SIGNED_2: SymAddr -= 2; break;
     2856                        case X86_64_RELOC_SIGNED:
    28382857                        case X86_64_RELOC_SIGNED_4: SymAddr -= 4; break;
    28392858                        default:
     
    28532872
    28542873                        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
    28552885                        case MACHO_N_ABS:
    28562886                            SymAddr += pSym->n_value;
     
    32203250     * Perform relocations.
    32213251     */
    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 */
     3257static 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    }*/
    32253280
    32263281    /*
     
    32283283     * segment when present.
    32293284     */
    3230     if (pModMachO->fMakeGot)
    3231         rc = kldrModMachOMakeGOT(pModMachO, pvBits, BaseAddress);
     3285    if (!rc && pModMachO->fMakeGot)
     3286        rc = kldrModMachOMakeGOT(pModMachO, pvBits, NewBaseAddress);
     3287
    32323288    return rc;
    32333289}
     
    32713327        KU64 *paGOT = (KU64 *)((KU8 *)pvBits + pModMachO->GotRVA);
    32723328        while (iSym-- > 0)
     3329        {
    32733330            switch (paSyms[iSym].n_type & MACHO_N_TYPE)
    32743331            {
     
    32873344                    break;
    32883345            }
     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        }
    32893391    }
    32903392    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     else
    3312         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;
    33203393}
    33213394
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette