VirtualBox

儲存庫 kStuff 的更動 22


忽略:
時間撮記:
2009-1-30 上午06:29:43 (16 年 以前)
作者:
bird
訊息:

kLdrModMachO.c: Initial 64-bit support (MH_OBJECT).

檔案:
修改 1 筆資料

圖例:

未更動
新增
刪除
  • trunk/kLdr/kLdrModMachO.c

    r2 r22  
    5555#endif
    5656
     57/** @def KLDRMODMACHO_CHECK_RETURN
     58 * Checks that an expression is true and return if it isn't.
     59 * This is a debug aid.
     60 */
     61#ifdef KLDRMODMACHO_STRICT2
     62# define KLDRMODMACHO_CHECK_RETURN(expr, rc)  kHlpAssertReturn(expr, rc)
     63#else
     64# define KLDRMODMACHO_CHECK_RETURN(expr, rc)  do { if (!(expr)) { return (rc); } } while (0)
     65#endif
     66
    5767
    5868/*******************************************************************************
     
    121131    /** The size of the mapped image. */
    122132    KLDRADDR                cbImage;
     133    /** The RVA of the Global Offset Table.  */
     134    KLDRADDR                GotRVA;
     135    /** Whether we're creating a global offset table segment.
     136     * This dependes on the cputype and image type. */
     137    KBOOL                   fMakeGot;
    123138    /** When set the sections in the load command segments must be used when
    124139     * mapping or loading the image. */
    125     int                     fMapUsingLoadCommandSections;
    126 
     140    KBOOL                   fMapUsingLoadCommandSections;
    127141    /** Pointer to the load commands. (endian converted) */
    128142    KU8                    *pbLoadCommands;
     
    178192                                           KU32 cchStrings, KLDRADDR BaseAddress, KU32 iSymbol, const char *pchSymbol,
    179193                                           KSIZE cchSymbol, PKLDRADDR puValue, KU32 *pfKind);
     194static int  kldrModMachODoQuerySymbol64Bit(PKLDRMODMACHO pModMachO, const macho_nlist_64_t *paSyms, KU32 cSyms, const char *pchStrings,
     195                                           KU32 cchStrings, KLDRADDR BaseAddress, KU32 iSymbol, const char *pchSymbol,
     196                                           KSIZE cchSymbol, PKLDRADDR puValue, KU32 *pfKind);
    180197static int  kldrModMachODoEnumSymbols32Bit(PKLDRMODMACHO pModMachO, const macho_nlist_32_t *paSyms, KU32 cSyms,
     198                                           const char *pchStrings, KU32 cchStrings, KLDRADDR BaseAddress,
     199                                           KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser);
     200static int  kldrModMachODoEnumSymbols64Bit(PKLDRMODMACHO pModMachO, const macho_nlist_64_t *paSyms, KU32 cSyms,
    181201                                           const char *pchStrings, KU32 cchStrings, KLDRADDR BaseAddress,
    182202                                           KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser);
     
    185205static int  kldrModMachOFixupSectionGeneric32Bit(PKLDRMODMACHO pModMachO, KU8 *pbSectBits, PKLDRMODMACHOSECT pFixupSect,
    186206                                                 macho_nlist_32_t *paSyms, KU32 cSyms, KLDRADDR NewBaseAddress);
     207static int  kldrModMachOFixupSectionAMD64(PKLDRMODMACHO pModMachO, KU8 *pbSectBits, PKLDRMODMACHOSECT pFixupSect,
     208                                          macho_nlist_64_t *paSyms, KU32 cSyms, KLDRADDR NewBaseAddress);
     209
     210static int  kldrModMachOMakeGOT(PKLDRMODMACHO pModMachO, void *pvBits, KLDRADDR NewBaseAddress);
    187211
    188212/*static int  kldrModMachODoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress);
     
    227251
    228252/**
    229  * Separate function for reading creating the PE module instance to
     253 * Separate function for reading creating the Mach-O module instance to
    230254 * simplify cleanup on failure.
    231255 */
     
    245269    KSIZE cchFilename;
    246270    KSIZE cb;
     271    KBOOL fMakeGot;
    247272    int rc;
    248273    *ppModMachO = NULL;
     274
     275    kHlpAssert(&s.Hdr32.magic == &s.Hdr64.magic);
     276    kHlpAssert(&s.Hdr32.flags == &s.Hdr64.flags);
    249277
    250278    /*
     
    254282    if (rc)
    255283        return rc;
    256     if (s.Hdr32.magic != IMAGE_MACHO32_SIGNATURE)
     284    if (    s.Hdr32.magic != IMAGE_MACHO32_SIGNATURE
     285        &&  s.Hdr32.magic != IMAGE_MACHO64_SIGNATURE
     286        )
    257287    {
    258288        if (    s.Hdr32.magic == IMAGE_MACHO32_SIGNATURE_OE
    259289            ||  s.Hdr32.magic == IMAGE_MACHO64_SIGNATURE_OE)
    260290            return KLDR_ERR_MACHO_OTHER_ENDIAN_NOT_SUPPORTED;
    261         if (s.Hdr32.magic == IMAGE_MACHO64_SIGNATURE)
    262             return KLDR_ERR_MACHO_64BIT_NOT_SUPPORTED;
    263291        return KLDR_ERR_UNKNOWN_FORMAT;
    264292    }
     
    272300    {
    273301        case CPU_TYPE_X86:
     302            fMakeGot = K_FALSE;
     303            break;
    274304        case CPU_TYPE_X86_64:
     305            fMakeGot = s.Hdr32.filetype == MH_OBJECT;
    275306            break;
    276307        default:
     
    297328        return rc;
    298329    }
     330    cSegments += fMakeGot;
    299331
    300332
     
    361393            pMod->enmArch = KCPUARCH_AMD64;
    362394            pMod->enmEndian = KLDRENDIAN_LITTLE;
    363             switch (s.Hdr32.cpusubtype)
     395            switch (s.Hdr32.cpusubtype & ~CPU_SUBTYPE_MASK)
    364396            {
    365397                case CPU_SUBTYPE_X86_64_ALL:        pMod->enmCpu = KCPU_AMD64_BLEND; break;
     
    394426    pModMachO->LinkAddress = 0;
    395427    pModMachO->cbImage = 0;
    396     pModMachO->fMapUsingLoadCommandSections = 0;
     428    pModMachO->GotRVA = NIL_KLDRADDR;
     429    pModMachO->fMakeGot = fMakeGot;
     430    pModMachO->fMapUsingLoadCommandSections = K_FALSE;
    397431    pModMachO->offSymbols = 0;
    398432    pModMachO->cSymbols = 0;
     
    577611                        case S_LAZY_SYMBOL_POINTERS:
    578612                        case S_SYMBOL_STUBS:
     613                            return KLDR_ERR_MACHO_UNSUPPORTED_SECTION;
    579614                        case S_MOD_INIT_FUNC_POINTERS:
     615                            return KLDR_ERR_MACHO_UNSUPPORTED_INIT_SECTION;
    580616                        case S_MOD_TERM_FUNC_POINTERS:
    581                             return KLDR_ERR_MACHO_UNSUPPORTED_SECTION;
     617                            return KLDR_ERR_MACHO_UNSUPPORTED_TERM_SECTION;
    582618
    583619                        default:
     
    625661                                ||  kHlpStrNComp(pSect->segname, (pSect - 1)->segname, sizeof(pSect->segname)))
    626662                            {
    627 #if 0 /** @todo This  doesn't work because of BSS. */
     663#if 0 /** @todo This doesn't work because of BSS. */
    628664                                /* verify that the linker/assembler has ordered sections correctly. */
    629665                                section_32_t *pCur = (pSect - 2);
     
    653689            }
    654690
    655             /*case LC_SEGMENT_64:
    656                  copy 32-bit code
     691            case LC_SEGMENT_64:
     692            {
     693                section_64_t *pSect;
     694                section_64_t *pFirstSect;
     695                KU32 cSectionsLeft;
     696
     697                /* convert and verify*/
     698                if (u.pLoadCmd->cmdsize < sizeof(segment_command_64_t))
     699                    return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;
     700                if (    pHdr->magic != IMAGE_MACHO64_SIGNATURE_OE
     701                    &&  pHdr->magic != IMAGE_MACHO64_SIGNATURE)
     702                    return KLDR_ERR_MACHO_BIT_MIX;
     703                if (fConvertEndian)
     704                {
     705                    u.pSeg64->vmaddr   = K_E2E_U64(u.pSeg64->vmaddr);
     706                    u.pSeg64->vmsize   = K_E2E_U64(u.pSeg64->vmsize);
     707                    u.pSeg64->fileoff  = K_E2E_U64(u.pSeg64->fileoff);
     708                    u.pSeg64->filesize = K_E2E_U64(u.pSeg64->filesize);
     709                    u.pSeg64->maxprot  = K_E2E_U32(u.pSeg64->maxprot);
     710                    u.pSeg64->initprot = K_E2E_U32(u.pSeg64->initprot);
     711                    u.pSeg64->nsects   = K_E2E_U32(u.pSeg64->nsects);
     712                    u.pSeg64->flags    = K_E2E_U32(u.pSeg64->flags);
     713                }
     714
     715                if (    u.pSeg64->filesize
     716                    &&  (   u.pSeg64->fileoff > cbFile
     717                         || u.pSeg64->fileoff + u.pSeg64->filesize > cbFile))
     718                    return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;
     719                if (!u.pSeg64->filesize && u.pSeg64->fileoff)
     720                    return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;
     721                if (u.pSeg64->vmsize < u.pSeg64->filesize)
     722                    return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;
     723                if ((u.pSeg64->maxprot & u.pSeg64->initprot) != u.pSeg64->initprot)
     724                    return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;
     725                if (u.pSeg64->flags & ~(SG_HIGHVM | SG_FVMLIB | SG_NORELOC | SG_PROTECTED_VERSION_1))
     726                    return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;
     727                if (u.pSeg64->nsects * sizeof(section_64_t) > u.pLoadCmd->cmdsize - sizeof(segment_command_64_t))
     728                    return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;
     729                if (    pHdr->filetype == MH_OBJECT
     730                    &&  cSegmentCommands > 0)
     731                    return KLDR_ERR_MACHO_BAD_OBJECT_FILE;
     732                cSegmentCommands++;
     733
     734                /*
     735                 * convert, validate and parse the sections.
     736                 */
     737                cSectionsLeft = u.pSeg64->nsects;
     738                pFirstSect = pSect = (section_64_t *)(u.pSeg64 + 1);
     739                while (cSectionsLeft-- > 0)
     740                {
     741                    int fFileBits;
     742
     743                    if (fConvertEndian)
     744                    {
     745                        pSect->addr      = K_E2E_U64(pSect->addr);
     746                        pSect->size      = K_E2E_U64(pSect->size);
     747                        pSect->offset    = K_E2E_U32(pSect->offset);
     748                        pSect->align     = K_E2E_U32(pSect->align);
     749                        pSect->reloff    = K_E2E_U32(pSect->reloff);
     750                        pSect->nreloc    = K_E2E_U32(pSect->nreloc);
     751                        pSect->flags     = K_E2E_U32(pSect->flags);
     752                        pSect->reserved1 = K_E2E_U32(pSect->reserved1);
     753                        pSect->reserved2 = K_E2E_U32(pSect->reserved2);
     754                    }
     755
     756                    /* validate */
     757                    switch (pSect->flags & SECTION_TYPE)
     758                    {
     759                        case S_ZEROFILL:
     760                            if (pSect->reserved1 || pSect->reserved2)
     761                                return KLDR_ERR_MACHO_BAD_SECTION;
     762                            fFileBits = 0;
     763                            break;
     764                        case S_REGULAR:
     765                        case S_CSTRING_LITERALS:
     766                        case S_COALESCED:
     767                        case S_4BYTE_LITERALS:
     768                        case S_8BYTE_LITERALS:
     769                        case S_16BYTE_LITERALS:
     770                            if (pSect->reserved1 || pSect->reserved2)
     771                                return KLDR_ERR_MACHO_BAD_SECTION;
     772                            fFileBits = 1;
     773                            break;
     774
     775                        case S_LITERAL_POINTERS:
     776                        case S_INTERPOSING:
     777                        case S_GB_ZEROFILL:
     778                        case S_NON_LAZY_SYMBOL_POINTERS:
     779                        case S_LAZY_SYMBOL_POINTERS:
     780                        case S_SYMBOL_STUBS:
     781                            return KLDR_ERR_MACHO_UNSUPPORTED_SECTION;
     782#if 1 /** @todo this requires a query API or flag... */
     783                        case S_MOD_INIT_FUNC_POINTERS:
     784                            return KLDR_ERR_MACHO_UNSUPPORTED_INIT_SECTION;
     785                        case S_MOD_TERM_FUNC_POINTERS:
     786                            return KLDR_ERR_MACHO_UNSUPPORTED_TERM_SECTION;
     787#else
     788                        case S_MOD_INIT_FUNC_POINTERS:
     789                        case S_MOD_TERM_FUNC_POINTERS:
     790                            fFileBits = 1;
     791                            break; /* ignored */
     792#endif
     793
     794                        default:
     795                            return KLDR_ERR_MACHO_UNKNOWN_SECTION;
     796                    }
     797                    if (pSect->flags & ~(  S_ATTR_PURE_INSTRUCTIONS | S_ATTR_NO_TOC | S_ATTR_STRIP_STATIC_SYMS
     798                                         | S_ATTR_NO_DEAD_STRIP | S_ATTR_LIVE_SUPPORT | S_ATTR_SELF_MODIFYING_CODE
     799                                         | S_ATTR_DEBUG | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_EXT_RELOC
     800                                         | S_ATTR_LOC_RELOC | SECTION_TYPE))
     801                        return KLDR_ERR_MACHO_BAD_SECTION;
     802                    if (    pSect->addr - u.pSeg64->vmaddr > u.pSeg64->vmsize
     803                        ||  pSect->addr - u.pSeg64->vmaddr + pSect->size > u.pSeg64->vmsize)
     804                        return KLDR_ERR_MACHO_BAD_SECTION;
     805                    if (    pSect->align >= 31
     806                        ||  (((1 << pSect->align) - 1) & pSect->addr)
     807                        ||  (((1 << pSect->align) - 1) & u.pSeg64->vmaddr))
     808                        return KLDR_ERR_MACHO_BAD_SECTION;
     809                    if (    fFileBits
     810                        &&  (   pSect->offset > cbFile
     811                             || (KU64)pSect->offset + pSect->size > cbFile))
     812                        return KLDR_ERR_MACHO_BAD_SECTION;
     813                    if (!fFileBits && pSect->offset)
     814                        return KLDR_ERR_MACHO_BAD_SECTION;
     815                    if (!pSect->nreloc && pSect->reloff)
     816                        return KLDR_ERR_MACHO_BAD_SECTION;
     817                    if (    pSect->nreloc
     818                        &&  (   pSect->reloff > cbFile
     819                             || (KU64)pSect->reloff + (KLDRFOFF)pSect->nreloc * sizeof(macho_relocation_info_t)) > cbFile)
     820                        return KLDR_ERR_MACHO_BAD_SECTION;
     821
     822
     823                    /* count segments and strings */
     824                    switch (pHdr->filetype)
     825                    {
     826                        case MH_OBJECT:
     827                        {
     828                            cSections++;
     829
     830                            /* Don't load debug symbols. (test this) */
     831                            if (pSect->flags & S_ATTR_DEBUG)
     832                                break;
     833
     834                            /* a new segment? */
     835                            if (    !cSegments
     836                                ||  kHlpStrNComp(pSect->segname, (pSect - 1)->segname, sizeof(pSect->segname)))
     837                            {
     838#if 0 /** @todo This doesn't work because of BSS. */
     839                                /* verify that the linker/assembler has ordered sections correctly. */
     840                                section_64_t *pCur = (pSect - 2);
     841                                while ((KUPTR)pCur >= (KUPTR)pFirstSect)
     842                                {
     843                                    if (!kHlpStrNComp(pCur->segname, pSect->segname, sizeof(pSect->segname)))
     844                                        return KLDR_ERR_MACHO_BAD_SECTION_ORDER;
     845                                    pCur--;
     846                                }
     847#endif
     848
     849                                /* ok. count it and the string. */
     850                                cSegments++;
     851                                cbStringPool += kHlpStrNLen(&pSect->segname[0], sizeof(pSect->segname)) + 1;
     852                            }
     853                            break;
     854                        }
     855
     856                        default:
     857                            return KERR_INVALID_PARAMETER;
     858                    }
     859
     860                    /* next */
     861                    pSect++;
     862                }
    657863                break;
    658             */
     864            } /* LC_SEGMENT_64 */
     865
    659866
    660867            case LC_SYMTAB:
     
    732939                break;
    733940
    734             case LC_SEGMENT_64:
    735941            case LC_LOADFVMLIB:
    736942            case LC_IDFVMLIB:
     
    9181124
    9191125                                        pSeg[-1].cbFile = pSeg[-1].offFile = -1;
    920                                         pModMachO->fMapUsingLoadCommandSections = 1;
     1126                                        pModMachO->fMapUsingLoadCommandSections = K_TRUE;
     1127                                    }
     1128                                }
     1129                                pSeg[-1].cb = pSect->addr - pSeg[-1].LinkAddress + pSect->size;
     1130
     1131                                /** @todo update the protection... */
     1132                            }
     1133                            pSectExtra++;
     1134                            break;
     1135                        }
     1136
     1137                        default:
     1138                            return KERR_INVALID_PARAMETER;
     1139                    }
     1140
     1141                    /* next */
     1142                    pSect++;
     1143                }
     1144                break;
     1145            }
     1146
     1147            case LC_SEGMENT_64:
     1148            {
     1149                section_64_t *pSect;
     1150                section_64_t *pFirstSect;
     1151                KU32 cSectionsLeft;
     1152
     1153                pModMachO->LinkAddress = u.pSeg64->vmaddr;
     1154
     1155                /*
     1156                 * convert, validate and parse the sections.
     1157                 */
     1158                cSectionsLeft = u.pSeg64->nsects;
     1159                pFirstSect = pSect = (section_64_t *)(u.pSeg64 + 1);
     1160                while (cSectionsLeft-- > 0)
     1161                {
     1162                    switch (pModMachO->Hdr.filetype)
     1163                    {
     1164                        case MH_OBJECT:
     1165                        {
     1166                            /* Section data extract. */
     1167                            pSectExtra->cb = pSect->size;
     1168                            pSectExtra->RVA = pSect->addr;
     1169                            pSectExtra->LinkAddress = pSect->addr;
     1170                            pSectExtra->offFile = pSect->offset ? pSect->offset : -1;
     1171                            pSectExtra->cFixups = pSect->nreloc;
     1172                            pSectExtra->paFixups = NULL;
     1173                            pSectExtra->offFixups = pSect->nreloc ? pSect->reloff : -1;
     1174                            pSectExtra->fFlags = pSect->flags;
     1175                            pSectExtra->iSegment = pSegExtra - &pModMachO->aSegments[0];
     1176                            pSectExtra->pvMachoSection = pSect;
     1177
     1178                            /* Don't load debug symbols. (test this!) */
     1179                            if (pSect->flags & S_ATTR_DEBUG)
     1180                            {
     1181                                pSectExtra++;
     1182                                /** @todo */
     1183                                break;
     1184                            }
     1185
     1186                            if (    fFirstSegment
     1187                                ||  kHlpStrNComp(pSect->segname, (pSect - 1)->segname, sizeof(pSect->segname)))
     1188                            {
     1189                                /* close the previous segment */
     1190                                if (pSegExtra != &pModMachO->aSegments[0])
     1191                                    pSegExtra[-1].cSections = pSectExtra - pSegExtra[-1].paSections;
     1192
     1193                                /* new segment. */
     1194                                pSeg->pvUser = NULL;
     1195                                pSeg->pchName = pbStringPool;
     1196                                pSeg->cchName = (KU32)kHlpStrNLen(&pSect->segname[0], sizeof(pSect->sectname));
     1197                                kHlpMemCopy(pbStringPool, &pSect->segname[0], pSeg->cchName);
     1198                                pbStringPool += pSeg->cchName;
     1199                                *pbStringPool++ = '\0';
     1200                                pSeg->SelFlat = 0;
     1201                                pSeg->Sel16bit = 0;
     1202                                pSeg->fFlags = 0;
     1203                                pSeg->enmProt = KPROT_EXECUTE_WRITECOPY; /** @todo fixme! */
     1204                                pSeg->cb = pSect->size;
     1205                                pSeg->Alignment = (1 << pSect->align);
     1206                                pSeg->LinkAddress = pSect->addr;
     1207                                pSeg->offFile = pSect->offset ? pSect->offset : -1;
     1208                                pSeg->cbFile  = pSect->offset ? pSect->size : -1;
     1209                                pSeg->RVA = pSect->addr - pModMachO->LinkAddress;
     1210                                pSeg->cbMapped = 0;
     1211                                pSeg->MapAddress = 0;
     1212
     1213                                pSegExtra->cSections = 0;
     1214                                pSegExtra->paSections = pSectExtra;
     1215
     1216                                pSeg++;
     1217                                pSegExtra++;
     1218                                fFirstSegment = 0;
     1219                            }
     1220                            else
     1221                            {
     1222                                /* update exiting segment */
     1223                                if (pSeg[-1].Alignment < (1 << pSect->align))
     1224                                    pSeg[-1].Alignment = (1 << pSect->align);
     1225                                if (pSect->addr < pSeg[-1].LinkAddress)
     1226                                    return KLDR_ERR_MACHO_BAD_SECTION; /** @todo move up! */
     1227
     1228                                /* If there are file bits, ensure they are in the current flow.
     1229                                   (yes, we are very very careful here, I know.) */
     1230                                if (    pSect->offset
     1231                                    &&  pSeg[-1].cbFile == pSeg[-1].cb)
     1232                                {
     1233                                    int fOk = pSeg[-1].offFile + (pSect->addr - pSeg[-1].LinkAddress) == pSect->offset
     1234                                           && pSect[-1].offset
     1235                                           && pSeg[-1].offFile + pSeg[-1].cbFile == pSect[-1].offset + pSect[-1].size;
     1236                                    /* more checks? */
     1237                                    if (fOk)
     1238                                        pSeg[-1].cbFile = (KLDRFOFF)(pSect->addr - pSeg[-1].LinkAddress) + pSect->size;
     1239                                    else
     1240                                    {
     1241
     1242                                        pSeg[-1].cbFile = pSeg[-1].offFile = -1;
     1243                                        pModMachO->fMapUsingLoadCommandSections = K_TRUE;
    9211244                                    }
    9221245                                }
     
    9631286
    9641287    /*
     1288     * Make the GOT segment if necessary.
     1289     */
     1290    if (pModMachO->fMakeGot)
     1291    {
     1292        KSIZE cbPtr = (   pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
     1293                       || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE)
     1294                    ? sizeof(KU32)
     1295                    : sizeof(KU64);
     1296
     1297        if (pSeg != &pModMachO->pMod->aSegments[0])
     1298            pModMachO->GotRVA = pSeg[-1].RVA + KLDR_ALIGN_ADDR(pSeg[-1].cb, pSeg[-1].Alignment);
     1299        else
     1300            pModMachO->GotRVA = 0;
     1301
     1302        pSeg->pvUser = NULL;
     1303        pSeg->pchName = "GOT";
     1304        pSeg->cchName = 3;
     1305        pSeg->SelFlat = 0;
     1306        pSeg->Sel16bit = 0;
     1307        pSeg->fFlags = 0;
     1308        pSeg->enmProt = KPROT_READONLY;
     1309        pSeg->cb = cbPtr * pModMachO->cSymbols;
     1310        pSeg->Alignment = 64;
     1311        pSeg->LinkAddress = pModMachO->LinkAddress + pModMachO->GotRVA;
     1312        pSeg->offFile = -1;
     1313        pSeg->cbFile  = -1;
     1314        pSeg->RVA = pModMachO->GotRVA;
     1315        pSeg->cbMapped = 0;
     1316        pSeg->MapAddress = 0;
     1317
     1318        pSegExtra->cSections = 0;
     1319        pSegExtra->paSections = NULL;
     1320    }
     1321
     1322    /*
    9651323     * Adjust mapping addresses calculating the image size.
    9661324     */
     
    9871345        }
    9881346    }
     1347
    9891348
    9901349    return 0;
     
    10701429     * Refuse segmented requests for now.
    10711430     */
    1072     if (    pfKind
    1073         &&  (*pfKind & KLDRSYMKIND_REQ_TYPE_MASK) != KLDRSYMKIND_REQ_FLAT)
    1074         return KLDR_ERR_TODO;
     1431    KLDRMODMACHO_CHECK_RETURN(   !pfKind
     1432                              || (*pfKind & KLDRSYMKIND_REQ_TYPE_MASK) == KLDRSYMKIND_REQ_FLAT,
     1433                              KLDR_ERR_TODO);
    10751434
    10761435    /*
     
    10881447                                                    cchSymbol, puValue, pfKind);
    10891448            else
    1090                 rc = KLDR_ERR_TODO; /** @todo duplicate kldrModMachOQuerySymbol32 for parsing 64-bit symbols when everything is working. */
    1091                 /*rc = kldrModMachODoQuerySymbol64Bit(pModMachO, (macho_nlist_64_t *)pModMachO->pvaSymbols, pModMachO->cSymbols,
     1449                rc = kldrModMachODoQuerySymbol64Bit(pModMachO, (macho_nlist_64_t *)pModMachO->pvaSymbols, pModMachO->cSymbols,
    10921450                                                    pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, iSymbol, pchSymbol,
    1093                                                     cchSymbol, puValue, pfKind);*/
    1094 
     1451                                                    cchSymbol, puValue, pfKind);
    10951452        }
    10961453    }
     
    11001457    return rc;
    11011458}
    1102 
    11031459
    11041460
     
    12221578            /** @todo implement indirect and prebound symbols. */
    12231579        default:
    1224             KLDRMODMACHO_ASSERT(0);
    1225             return KLDR_ERR_TODO;
     1580            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
     1581    }
     1582
     1583    return 0;
     1584}
     1585
     1586
     1587/**
     1588 * Lookup a symbol in a 64-bit symbol table.
     1589 *
     1590 * @returns See kLdrModQuerySymbol.
     1591 * @param   pModMachO
     1592 * @param   paSyms      Pointer to the symbol table.
     1593 * @param   cSyms       Number of symbols in the table.
     1594 * @param   pchStrings  Pointer to the string table.
     1595 * @param   cchStrings  Size of the string table.
     1596 * @param   BaseAddress Adjusted base address, see kLdrModQuerySymbol.
     1597 * @param   iSymbol     See kLdrModQuerySymbol.
     1598 * @param   pchSymbol   See kLdrModQuerySymbol.
     1599 * @param   cchSymbol   See kLdrModQuerySymbol.
     1600 * @param   puValue     See kLdrModQuerySymbol.
     1601 * @param   pfKind      See kLdrModQuerySymbol.
     1602 */
     1603static int kldrModMachODoQuerySymbol64Bit(PKLDRMODMACHO pModMachO, const macho_nlist_64_t *paSyms, KU32 cSyms, const char *pchStrings,
     1604                                          KU32 cchStrings, KLDRADDR BaseAddress, KU32 iSymbol, const char *pchSymbol, KSIZE cchSymbol,
     1605                                          PKLDRADDR puValue, KU32 *pfKind)
     1606{
     1607    /*
     1608     * Find a valid symbol matching the search criteria.
     1609     */
     1610    if (iSymbol == NIL_KLDRMOD_SYM_ORDINAL)
     1611    {
     1612        /* simplify validation. */
     1613        if (cchStrings <= cchSymbol)
     1614            return KLDR_ERR_SYMBOL_NOT_FOUND;
     1615        cchStrings -= cchSymbol;
     1616
     1617        /* external symbols are usually at the end, so search the other way. */
     1618        for (iSymbol = cSyms - 1; iSymbol != KU32_MAX; iSymbol--)
     1619        {
     1620            const char *psz;
     1621
     1622            /* Skip irrellevant and non-public symbols. */
     1623            if (paSyms[iSymbol].n_type & MACHO_N_STAB)
     1624                continue;
     1625            if ((paSyms[iSymbol].n_type & MACHO_N_TYPE) == MACHO_N_UNDF)
     1626                continue;
     1627            if (!(paSyms[iSymbol].n_type & MACHO_N_EXT)) /*??*/
     1628                continue;
     1629            if (paSyms[iSymbol].n_type & MACHO_N_PEXT) /*??*/
     1630                continue;
     1631
     1632            /* get name */
     1633            if (!paSyms[iSymbol].n_un.n_strx)
     1634                continue;
     1635            if ((KU32)paSyms[iSymbol].n_un.n_strx >= cchStrings)
     1636                continue;
     1637            psz = &pchStrings[paSyms[iSymbol].n_un.n_strx];
     1638            if (psz[cchSymbol])
     1639                continue;
     1640            if (kHlpMemComp(psz, pchSymbol, cchSymbol))
     1641                continue;
     1642
     1643            /* match! */
     1644            break;
     1645        }
     1646        if (iSymbol == KU32_MAX)
     1647            return KLDR_ERR_SYMBOL_NOT_FOUND;
     1648    }
     1649    else
     1650    {
     1651        if (iSymbol >= cSyms)
     1652            return KLDR_ERR_SYMBOL_NOT_FOUND;
     1653        if (paSyms[iSymbol].n_type & MACHO_N_STAB)
     1654            return KLDR_ERR_SYMBOL_NOT_FOUND;
     1655        if ((paSyms[iSymbol].n_type & MACHO_N_TYPE) == MACHO_N_UNDF)
     1656            return KLDR_ERR_SYMBOL_NOT_FOUND;
     1657    }
     1658
     1659    /*
     1660     * Calc the return values.
     1661     */
     1662    if (pfKind)
     1663    {
     1664        if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
     1665            ||  pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE)
     1666            *pfKind = KLDRSYMKIND_32BIT | KLDRSYMKIND_NO_TYPE;
     1667        else
     1668            *pfKind = KLDRSYMKIND_64BIT | KLDRSYMKIND_NO_TYPE;
     1669        if (paSyms[iSymbol].n_desc & N_WEAK_DEF)
     1670            *pfKind |= KLDRSYMKIND_WEAK;
     1671    }
     1672
     1673    switch (paSyms[iSymbol].n_type & MACHO_N_TYPE)
     1674    {
     1675        case MACHO_N_SECT:
     1676        {
     1677            PKLDRMODMACHOSECT pSect;
     1678            KLDRADDR RVA;
     1679            if ((KU32)(paSyms[iSymbol].n_sect - 1) >= pModMachO->cSections)
     1680                return KLDR_ERR_MACHO_BAD_SYMBOL;
     1681            pSect = &pModMachO->paSections[paSyms[iSymbol].n_sect - 1];
     1682
     1683            RVA = paSyms[iSymbol].n_value - pModMachO->LinkAddress;
     1684            if (RVA - pSect->RVA >= pSect->cb)
     1685                return KLDR_ERR_MACHO_BAD_SYMBOL;
     1686            if (puValue)
     1687                *puValue = RVA + BaseAddress;
     1688
     1689            if (    pfKind
     1690                &&  (pSect->fFlags & (S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SELF_MODIFYING_CODE)))
     1691                *pfKind = (*pfKind & ~KLDRSYMKIND_TYPE_MASK) | KLDRSYMKIND_CODE;
     1692            break;
     1693        }
     1694
     1695        case MACHO_N_ABS:
     1696            if (puValue)
     1697                *puValue = paSyms[iSymbol].n_value;
     1698            /*if (pfKind)
     1699                pfKind |= KLDRSYMKIND_ABS;*/
     1700            break;
     1701
     1702        case MACHO_N_PBUD:
     1703        case MACHO_N_INDR:
     1704            /** @todo implement indirect and prebound symbols. */
     1705        default:
     1706            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
    12261707    }
    12271708
     
    12581739                                                    fFlags, pfnCallback, pvUser);
    12591740            else
    1260                 rc = KLDR_ERR_TODO; /** @todo duplicate kldrModMachOQuerySymbol32 for parsing 64-bit symbols when everything is working. */
    1261                 /*rc = kldrModMachODoEnumSymbols32Bit(pModMachO, (macho_nlist_32_t *)pModMachO->pvaSymbols, pModMachO->cSymbols,
    1262                                                     pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, pfnCallback, pvUser);*/
     1741                rc = kldrModMachODoEnumSymbols64Bit(pModMachO, (macho_nlist_64_t *)pModMachO->pvaSymbols, pModMachO->cSymbols,
     1742                                                    pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress,
     1743                                                    fFlags, pfnCallback, pvUser);
    12631744        }
    12641745    }
    12651746    else
    1266         rc = KLDR_ERR_TODO;
     1747        KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
    12671748
    12681749    return rc;
     
    12881769                                          KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser)
    12891770{
    1290     const KU32 fKindBase = pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
    1291                             || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE
    1292                              ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT;
     1771    const KU32 fKindBase =    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
     1772                           || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE
     1773                         ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT;
    12931774    KU32 iSym;
    12941775    int rc;
     
    13671848                /** @todo implement indirect and prebound symbols. */
    13681849            default:
    1369                 KLDRMODMACHO_ASSERT(0);
    1370                 return KLDR_ERR_TODO;
     1850                KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
     1851        }
     1852
     1853        /*
     1854         * Do callback.
     1855         */
     1856        rc = pfnCallback(pModMachO->pMod, iSym, psz, cch, NULL, uValue, fKind, pvUser);
     1857        if (rc)
     1858            return rc;
     1859    }
     1860    return 0;
     1861}
     1862
     1863
     1864/**
     1865 * Enum a 64-bit symbol table.
     1866 *
     1867 * @returns See kLdrModQuerySymbol.
     1868 * @param   pModMachO
     1869 * @param   paSyms      Pointer to the symbol table.
     1870 * @param   cSyms       Number of symbols in the table.
     1871 * @param   pchStrings  Pointer to the string table.
     1872 * @param   cchStrings  Size of the string table.
     1873 * @param   BaseAddress Adjusted base address, see kLdrModEnumSymbols.
     1874 * @param   fFlags      See kLdrModEnumSymbols.
     1875 * @param   pfnCallback See kLdrModEnumSymbols.
     1876 * @param   pvUser      See kLdrModEnumSymbols.
     1877 */
     1878static int kldrModMachODoEnumSymbols64Bit(PKLDRMODMACHO pModMachO, const macho_nlist_64_t *paSyms, KU32 cSyms,
     1879                                          const char *pchStrings, KU32 cchStrings, KLDRADDR BaseAddress,
     1880                                          KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser)
     1881{
     1882    const KU32 fKindBase =    pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE
     1883                           || pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE_OE
     1884                         ? KLDRSYMKIND_64BIT : KLDRSYMKIND_32BIT;
     1885    KU32 iSym;
     1886    int rc;
     1887
     1888    /*
     1889     * Iterate the symbol table.
     1890     */
     1891    for (iSym = 0; iSym < cSyms; iSym++)
     1892    {
     1893        KU32 fKind;
     1894        KLDRADDR uValue;
     1895        const char *psz;
     1896        KSIZE cch;
     1897
     1898        /* Skip debug symbols and undefined symbols. */
     1899        if (paSyms[iSym].n_type & MACHO_N_STAB)
     1900            continue;
     1901        if ((paSyms[iSym].n_type & MACHO_N_TYPE) == MACHO_N_UNDF)
     1902            continue;
     1903
     1904        /* Skip non-public symbols unless they are requested explicitly. */
     1905        if (!(fFlags & KLDRMOD_ENUM_SYMS_FLAGS_ALL))
     1906        {
     1907            if (!(paSyms[iSym].n_type & MACHO_N_EXT)) /*??*/
     1908                continue;
     1909            if (paSyms[iSym].n_type & MACHO_N_PEXT) /*??*/
     1910                continue;
     1911            if (!paSyms[iSym].n_un.n_strx)
     1912                continue;
     1913        }
     1914
     1915        /*
     1916         * Gather symbol info
     1917         */
     1918
     1919        /* name */
     1920        if ((KU32)paSyms[iSym].n_un.n_strx >= cchStrings)
     1921            return KLDR_ERR_MACHO_BAD_SYMBOL;
     1922        psz = &pchStrings[paSyms[iSym].n_un.n_strx];
     1923        cch = kHlpStrLen(psz);
     1924        if (!cch)
     1925            psz = NULL;
     1926
     1927        /* kind & value */
     1928        fKind = fKindBase;
     1929        if (paSyms[iSym].n_desc & N_WEAK_DEF)
     1930            fKind |= KLDRSYMKIND_WEAK;
     1931        switch (paSyms[iSym].n_type & MACHO_N_TYPE)
     1932        {
     1933            case MACHO_N_SECT:
     1934            {
     1935                PKLDRMODMACHOSECT pSect;
     1936                if ((KU32)(paSyms[iSym].n_sect - 1) >= pModMachO->cSections)
     1937                    return KLDR_ERR_MACHO_BAD_SYMBOL;
     1938                pSect = &pModMachO->paSections[paSyms[iSym].n_sect - 1];
     1939
     1940                uValue = paSyms[iSym].n_value - pModMachO->LinkAddress;
     1941                if (uValue - pSect->RVA >= pSect->cb)
     1942                    return KLDR_ERR_MACHO_BAD_SYMBOL;
     1943                uValue += BaseAddress;
     1944
     1945                if (pSect->fFlags & (S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SELF_MODIFYING_CODE))
     1946                    fKind |= KLDRSYMKIND_CODE;
     1947                else
     1948                    fKind |= KLDRSYMKIND_NO_TYPE;
     1949                break;
     1950            }
     1951
     1952            case MACHO_N_ABS:
     1953                uValue = paSyms[iSym].n_value;
     1954                fKind |= KLDRSYMKIND_NO_TYPE /*KLDRSYMKIND_ABS*/;
     1955                break;
     1956
     1957            case MACHO_N_PBUD:
     1958            case MACHO_N_INDR:
     1959                /** @todo implement indirect and prebound symbols. */
     1960            default:
     1961                KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
    13711962        }
    13721963
     
    15742165    /* try do the prepare */
    15752166    if (pModMachO->fMapUsingLoadCommandSections)
    1576         return KLDR_ERR_TODO; /* deal with this if it ever occurs. */
     2167        KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); /* deal with this if it ever occurs. */
    15772168    else
    15782169    {
     
    16132204     */
    16142205    if (pModMachO->fMapUsingLoadCommandSections)
    1615         return KLDR_ERR_TODO; /* deal with this if it ever occurs. */
     2206        KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); /* deal with this if it ever occurs. */
    16162207    else
    16172208    {
     
    16842275     */
    16852276    if (pModMachO->fMapUsingLoadCommandSections)
    1686         return KLDR_ERR_TODO; /* deal with this if it ever occurs. */
     2277        KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); /* deal with this if it ever occurs. */
    16872278    else
    16882279    {
     
    17542345
    17552346                /** @todo Implement N_REF_TO_WEAK. */
    1756                 if (paSyms[iSym].n_desc & N_REF_TO_WEAK)
    1757                     return KLDR_ERR_TODO;
     2347                KLDRMODMACHO_CHECK_RETURN(!(paSyms[iSym].n_desc & N_REF_TO_WEAK), KLDR_ERR_TODO);
    17582348
    17592349                /* Get the symbol name and try resolve it. */
     
    18052395
    18062396                /** @todo Implement N_REF_TO_WEAK. */
    1807                 if (paSyms[iSym].n_desc & N_REF_TO_WEAK)
    1808                     return KLDR_ERR_TODO;
    1809 
    1810                 /* Get the symbol name and try resolve it. */
     2397                KLDRMODMACHO_CHECK_RETURN(!(paSyms[iSym].n_desc & N_REF_TO_WEAK), KLDR_ERR_TODO);
     2398
     2399                 /* Get the symbol name and try resolve it. */
    18112400                if (paSyms[iSym].n_un.n_strx >= pModMachO->cchStrings)
    18122401                    return KLDR_ERR_MACHO_BAD_SYMBOL;
     
    18982487                                                          (macho_nlist_32_t *)pModMachO->pvaSymbols,
    18992488                                                          pModMachO->cSymbols, NewBaseAddress);
     2489            else if (   pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE
     2490                     && pModMachO->Hdr.cputype == CPU_TYPE_X86_64)
     2491                rc = kldrModMachOFixupSectionAMD64(pModMachO, pbSectBits, pSect,
     2492                                                   (macho_nlist_64_t *)pModMachO->pvaSymbols,
     2493                                                   pModMachO->cSymbols, NewBaseAddress);
    19002494            else
    1901                 rc = KLDR_ERR_TODO; /* save space for now. */
     2495                KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
    19022496            if (rc)
    19032497                break;
     
    20132607                    case MACHO_N_INDR:
    20142608                    case MACHO_N_PBUD:
    2015                         return KLDR_ERR_TODO;
     2609                        KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
    20162610                    default:
    2017                         return KLDR_ERR_MACHO_BAD_SYMBOL;
     2611                        KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_MACHO_BAD_SYMBOL);
    20182612                }
    20192613            }
     
    21132707
    21142708/**
     2709 * Applies AMD64 fixups to a section.
     2710 *
     2711 * @returns 0 on success, non-zero kLdr status code on failure.
     2712 * @param   pModMachO       The Mach-O module interpreter instance.
     2713 * @param   pbSectBits      Pointer to the section bits.
     2714 * @param   pFixupSect      The section being fixed up.
     2715 * @param   NewBaseAddress  The new base image address.
     2716 */
     2717static int  kldrModMachOFixupSectionAMD64(PKLDRMODMACHO pModMachO, KU8 *pbSectBits, PKLDRMODMACHOSECT pFixupSect,
     2718                                          macho_nlist_64_t *paSyms, KU32 cSyms, KLDRADDR NewBaseAddress)
     2719{
     2720    const macho_relocation_info_t *paFixups = pFixupSect->paFixups;
     2721    const KU32 cFixups = pFixupSect->cFixups;
     2722    KSIZE cbSectBits = (KSIZE)pFixupSect->cb;
     2723    const KU8 *pbSectVirginBits;
     2724    KU32 iFixup;
     2725    KLDRPU uFixVirgin;
     2726    KLDRPU uFix;
     2727    KLDRADDR SymAddr;
     2728    int rc;
     2729
     2730    /*
     2731     * Find the virgin bits.
     2732     */
     2733    if (pFixupSect->offFile != -1)
     2734    {
     2735        rc = kldrModMachOMapVirginBits(pModMachO);
     2736        if (rc)
     2737            return rc;
     2738        pbSectVirginBits = (const KU8 *)pModMachO->pvBits + pFixupSect->offFile;
     2739    }
     2740    else
     2741        pbSectVirginBits = NULL;
     2742
     2743    /*
     2744     * Iterate the fixups and apply them.
     2745     */
     2746    for (iFixup = 0; iFixup < cFixups; iFixup++)
     2747    {
     2748        union
     2749        {
     2750            macho_relocation_info_t     r;
     2751            scattered_relocation_info_t s;
     2752        } Fixup;
     2753        Fixup.r = paFixups[iFixup];
     2754
     2755        /* AMD64 doesn't use scattered fixups. */
     2756        KLDRMODMACHO_CHECK_RETURN(!(Fixup.r.r_address & R_SCATTERED), KLDR_ERR_BAD_FIXUP);
     2757
     2758        /* sanity */
     2759        KLDRMODMACHO_CHECK_RETURN((KU32)Fixup.r.r_address < cbSectBits, KLDR_ERR_BAD_FIXUP);
     2760
     2761        /* calc fixup addresses. */
     2762        uFix.pv = pbSectBits + Fixup.r.r_address;
     2763        uFixVirgin.pv = pbSectVirginBits ? (KU8 *)pbSectVirginBits + Fixup.r.r_address : 0;
     2764
     2765        /*
     2766         * Calc the symbol value.
     2767         */
     2768        /* Calc the linked symbol address / addend. */
     2769        switch (Fixup.r.r_length)
     2770        {
     2771            /** @todo Deal with unaligned accesses on non x86 platforms. */
     2772            case 2: SymAddr = *uFixVirgin.pi32; break;
     2773            case 3: SymAddr = *uFixVirgin.pi64; break;
     2774            default:
     2775                KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_BAD_FIXUP);
     2776        }
     2777        if (Fixup.r.r_pcrel)
     2778            SymAddr += Fixup.r.r_address + pFixupSect->LinkAddress;
     2779
     2780        /* Add symbol / section address. */
     2781        if (Fixup.r.r_extern)
     2782        {
     2783            const macho_nlist_64_t *pSym;
     2784
     2785            KLDRMODMACHO_CHECK_RETURN(Fixup.r.r_symbolnum < cSyms, KLDR_ERR_BAD_FIXUP);
     2786            pSym = &paSyms[Fixup.r.r_symbolnum];
     2787            KLDRMODMACHO_CHECK_RETURN(!(pSym->n_type & MACHO_N_STAB), KLDR_ERR_BAD_FIXUP);
     2788
     2789            switch (Fixup.r.r_type)
     2790            {
     2791                /* GOT references just needs to have their symbol verified.
     2792                   Later, we'll optimize GOT building here using a parallel sym->got array. */
     2793                case X86_64_RELOC_GOT_LOAD:
     2794                case X86_64_RELOC_GOT:
     2795                    switch (pSym->n_type & MACHO_N_TYPE)
     2796                    {
     2797                        case MACHO_N_SECT:
     2798                        case MACHO_N_UNDF:
     2799                        case MACHO_N_ABS:
     2800                            break;
     2801                        case MACHO_N_INDR:
     2802                        case MACHO_N_PBUD:
     2803                            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
     2804                        default:
     2805                            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_MACHO_BAD_SYMBOL);
     2806                    }
     2807                    SymAddr = sizeof(KU64) * Fixup.r.r_symbolnum + pModMachO->GotRVA + NewBaseAddress;
     2808                    break;
     2809
     2810                /* Verify the r_pcrel field for signed fixups on the way into the default case. */
     2811                case X86_64_RELOC_BRANCH:
     2812                case X86_64_RELOC_SIGNED:
     2813                case X86_64_RELOC_SIGNED_1:
     2814                case X86_64_RELOC_SIGNED_2:
     2815                case X86_64_RELOC_SIGNED_4:
     2816                    KLDRMODMACHO_CHECK_RETURN(Fixup.r.r_pcrel, KLDR_ERR_BAD_FIXUP);
     2817                default:
     2818                {
     2819                    /* Adjust with fixup specific addend and vierfy unsigned/r_pcrel. */
     2820                    switch (Fixup.r.r_type)
     2821                    {
     2822                        case X86_64_RELOC_UNSIGNED:
     2823                            KLDRMODMACHO_CHECK_RETURN(!Fixup.r.r_pcrel, KLDR_ERR_BAD_FIXUP);
     2824                            break;
     2825                        case X86_64_RELOC_SIGNED:
     2826                            break;
     2827                        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                            }
     2835                            break;
     2836                        case X86_64_RELOC_SIGNED_1: SymAddr -= 1; break;
     2837                        case X86_64_RELOC_SIGNED_2: SymAddr -= 2; break;
     2838                        case X86_64_RELOC_SIGNED_4: SymAddr -= 4; break;
     2839                        default:
     2840                            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_BAD_FIXUP);
     2841                    }
     2842
     2843                    switch (pSym->n_type & MACHO_N_TYPE)
     2844                    {
     2845                        case MACHO_N_SECT:
     2846                        {
     2847                            PKLDRMODMACHOSECT pSymSect;
     2848                            KLDRMODMACHO_CHECK_RETURN((KU32)pSym->n_sect - 1 <= pModMachO->cSections, KLDR_ERR_MACHO_BAD_SYMBOL);
     2849                            pSymSect = &pModMachO->paSections[pSym->n_sect - 1];
     2850                            SymAddr += pSym->n_value - pSymSect->LinkAddress + pSymSect->RVA + NewBaseAddress;
     2851                            break;
     2852                        }
     2853
     2854                        case MACHO_N_UNDF:
     2855                        case MACHO_N_ABS:
     2856                            SymAddr += pSym->n_value;
     2857                            break;
     2858
     2859                        case MACHO_N_INDR:
     2860                        case MACHO_N_PBUD:
     2861                            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
     2862                        default:
     2863                            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_MACHO_BAD_SYMBOL);
     2864                    }
     2865                    break;
     2866                }
     2867
     2868                /*
     2869                 * This is a weird customer, it will always be follows by an UNSIGNED fixup.
     2870                 */
     2871                case X86_64_RELOC_SUBTRACTOR:
     2872                {
     2873                    macho_relocation_info_t Fixup2;
     2874
     2875                    /* Deal with the SUBTRACT symbol first, by subtracting it from SymAddr. */
     2876                    switch (pSym->n_type & MACHO_N_TYPE)
     2877                    {
     2878                        case MACHO_N_SECT:
     2879                        {
     2880                            PKLDRMODMACHOSECT pSymSect;
     2881                            KLDRMODMACHO_CHECK_RETURN((KU32)pSym->n_sect - 1 <= pModMachO->cSections, KLDR_ERR_MACHO_BAD_SYMBOL);
     2882                            pSymSect = &pModMachO->paSections[pSym->n_sect - 1];
     2883                            SymAddr -= pSym->n_value - pSymSect->LinkAddress + pSymSect->RVA + NewBaseAddress;
     2884                            break;
     2885                        }
     2886
     2887                        case MACHO_N_UNDF:
     2888                        case MACHO_N_ABS:
     2889                            SymAddr -= pSym->n_value;
     2890                            break;
     2891
     2892                        case MACHO_N_INDR:
     2893                        case MACHO_N_PBUD:
     2894                            KLDRMODMACHO_CHECK_RETURN(0,KLDR_ERR_TODO);
     2895                        default:
     2896                            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_MACHO_BAD_SYMBOL);
     2897                    }
     2898
     2899                    /* Load the 2nd fixup, check sanity. */
     2900                    iFixup++;
     2901                    KLDRMODMACHO_CHECK_RETURN(!Fixup.r.r_pcrel && iFixup < cFixups, KLDR_ERR_BAD_FIXUP);
     2902                    Fixup2 = paFixups[iFixup];
     2903                    KLDRMODMACHO_CHECK_RETURN(   Fixup2.r_address == Fixup.r.r_address
     2904                                              && Fixup2.r_length == Fixup.r.r_length
     2905                                              && Fixup2.r_type == X86_64_RELOC_UNSIGNED
     2906                                              && !Fixup2.r_pcrel
     2907                                              && Fixup2.r_extern /*??*/
     2908                                              && Fixup2.r_symbolnum < cSyms,
     2909                                              KLDR_ERR_BAD_FIXUP);
     2910
     2911                    pSym = &paSyms[Fixup.r.r_symbolnum];
     2912                    KLDRMODMACHO_CHECK_RETURN(!(pSym->n_type & MACHO_N_STAB), KLDR_ERR_BAD_FIXUP);
     2913
     2914                    /* Add it's value to SymAddr. */
     2915                    switch (pSym->n_type & MACHO_N_TYPE)
     2916                    {
     2917                        case MACHO_N_SECT:
     2918                        {
     2919                            PKLDRMODMACHOSECT pSymSect;
     2920                            KLDRMODMACHO_CHECK_RETURN((KU32)pSym->n_sect - 1 <= pModMachO->cSections, KLDR_ERR_MACHO_BAD_SYMBOL);
     2921                            pSymSect = &pModMachO->paSections[pSym->n_sect - 1];
     2922                            SymAddr += pSym->n_value - pSymSect->LinkAddress + pSymSect->RVA + NewBaseAddress;
     2923                            break;
     2924                        }
     2925
     2926                        case MACHO_N_UNDF:
     2927                        case MACHO_N_ABS:
     2928                            SymAddr += pSym->n_value;
     2929                            break;
     2930
     2931                        case MACHO_N_INDR:
     2932                        case MACHO_N_PBUD:
     2933                            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
     2934                        default:
     2935                            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_MACHO_BAD_SYMBOL);
     2936                    }
     2937                }
     2938                break;
     2939            }
     2940        }
     2941        else
     2942        {
     2943            /* verify against fixup type */
     2944            switch (Fixup.r.r_type)
     2945            {
     2946                case X86_64_RELOC_UNSIGNED:
     2947                case X86_64_RELOC_SIGNED:
     2948                case X86_64_RELOC_BRANCH:
     2949                /*case X86_64_RELOC_GOT_LOAD:*/
     2950                /*case X86_64_RELOC_GOT: */
     2951                /*case X86_64_RELOC_SUBTRACTOR: - ???*/
     2952                case X86_64_RELOC_SIGNED_1:
     2953                case X86_64_RELOC_SIGNED_2:
     2954                case X86_64_RELOC_SIGNED_4:
     2955                    break;
     2956                default:
     2957                    KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_BAD_FIXUP);
     2958            }
     2959            if (Fixup.r.r_symbolnum != R_ABS)
     2960            {
     2961                PKLDRMODMACHOSECT pSymSect;
     2962                KLDRMODMACHO_CHECK_RETURN(Fixup.r.r_symbolnum <= pModMachO->cSections, KLDR_ERR_BAD_FIXUP);
     2963                pSymSect = &pModMachO->paSections[Fixup.r.r_symbolnum - 1];
     2964
     2965                SymAddr -= pSymSect->LinkAddress;
     2966                SymAddr += pSymSect->RVA + NewBaseAddress;
     2967            }
     2968        }
     2969
     2970        /* adjust for PC relative */
     2971        if (Fixup.r.r_pcrel)
     2972            SymAddr -= Fixup.r.r_address + pFixupSect->RVA + NewBaseAddress;
     2973
     2974        /*
     2975         * Write back the fixed up value.
     2976         */
     2977        switch (Fixup.r.r_length)
     2978        {
     2979            case 3:
     2980                *uFix.pu64 = (KU64)SymAddr;
     2981                break;
     2982            case 2:
     2983                KLDRMODMACHO_CHECK_RETURN(Fixup.r.r_pcrel || Fixup.r.r_type == X86_64_RELOC_SUBTRACTOR, KLDR_ERR_BAD_FIXUP);
     2984                KLDRMODMACHO_CHECK_RETURN((KI32)SymAddr == (KI64)SymAddr, KLDR_ERR_ADDRESS_OVERFLOW);
     2985                *uFix.pu32 = (KU32)SymAddr;
     2986                break;
     2987            default:
     2988                KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_BAD_FIXUP);
     2989        }
     2990    }
     2991
     2992    return 0;
     2993}
     2994
     2995
     2996/**
    21152997 * Loads the symbol table for a MH_OBJECT file.
    21162998 *
     
    21333015
    21343016        /* sanity */
    2135         if (    !pModMachO->offSymbols
    2136             ||  (pModMachO->cchStrings && !pModMachO->offStrings))
    2137             return KLDR_ERR_MACHO_BAD_OBJECT_FILE;
     3017        KLDRMODMACHO_CHECK_RETURN(   pModMachO->offSymbols
     3018                                  && (!pModMachO->cchStrings || pModMachO->offStrings),
     3019                                  KLDR_ERR_MACHO_BAD_OBJECT_FILE);
    21383020
    21393021        /* allocate */
     
    21433025             : sizeof(macho_nlist_64_t);
    21443026        cbSyms = pModMachO->cSymbols * cbSym;
    2145         if (cbSyms / cbSym != pModMachO->cSymbols)
    2146             return KLDR_ERR_SIZE_OVERFLOW;
     3027        KLDRMODMACHO_CHECK_RETURN(cbSyms / cbSym == pModMachO->cSymbols, KLDR_ERR_SIZE_OVERFLOW);
    21473028        rc = KERR_NO_MEMORY;
    21483029        pvSyms = kHlpAlloc(cbSyms);
     
    22223103    /* allocate the memory. */
    22233104    cbFixups = cFixups * sizeof(*paFixups);
    2224     if (cbFixups / sizeof(*paFixups) != cFixups)
    2225         return KLDR_ERR_SIZE_OVERFLOW;
     3105    KLDRMODMACHO_CHECK_RETURN(cbFixups / sizeof(*paFixups) == cFixups, KLDR_ERR_SIZE_OVERFLOW);
    22263106    paFixups = (macho_relocation_info_t *)kHlpAlloc(cbFixups);
    22273107    if (!paFixups)
     
    23173197     */
    23183198    if (pModMachO->fMapUsingLoadCommandSections)
    2319         return KLDR_ERR_TODO; /* deal with this if it ever occurs. */
     3199        KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); /* deal with this if it ever occurs. */
    23203200    else
    23213201    {
     
    23293209                continue;
    23303210            rc = kRdrRead(pMod->pRdr,
    2331                              (KU8 *)pvBits + (pMod->aSegments[i].LinkAddress - pModMachO->LinkAddress),
    2332                              pMod->aSegments[i].cbFile,
    2333                              pMod->aSegments[i].offFile);
     3211                          (KU8 *)pvBits + (pMod->aSegments[i].LinkAddress - pModMachO->LinkAddress),
     3212                          pMod->aSegments[i].cbFile,
     3213                          pMod->aSegments[i].offFile);
    23343214            if (rc)
    23353215                return rc;
     
    23403220     * Perform relocations.
    23413221     */
    2342     return kldrModMachORelocateBits(pMod, pvBits, BaseAddress, pModMachO->LinkAddress, pfnGetImport, pvUser);
     3222    rc = kldrModMachORelocateBits(pMod, pvBits, BaseAddress, pModMachO->LinkAddress, pfnGetImport, pvUser);
     3223    if (rc)
     3224        return rc;
     3225
     3226    /*
     3227     * Construct the global offset table if necessary, it's always the last
     3228     * segment when present.
     3229     */
     3230    if (pModMachO->fMakeGot)
     3231        rc = kldrModMachOMakeGOT(pModMachO, pvBits, BaseAddress);
     3232    return rc;
     3233}
     3234
     3235
     3236/**
     3237 * Builds the GOT.
     3238 *
     3239 * Assumes the symbol table has all external symbols resolved correctly and that
     3240 * the bits has been cleared up front.
     3241 */
     3242static int kldrModMachOMakeGOT(PKLDRMODMACHO pModMachO, void *pvBits, KLDRADDR NewBaseAddress)
     3243{
     3244    KU32  iSym = pModMachO->cSymbols;
     3245    if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
     3246        ||  pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE)
     3247    {
     3248        macho_nlist_32_t const *paSyms = (macho_nlist_32_t const *)pModMachO->pvaSymbols;
     3249        KU32 *paGOT = (KU32 *)((KU8 *)pvBits + pModMachO->GotRVA);
     3250        while (iSym-- > 0)
     3251            switch (paSyms[iSym].n_type & MACHO_N_TYPE)
     3252            {
     3253                case MACHO_N_SECT:
     3254                {
     3255                    PKLDRMODMACHOSECT pSymSect;
     3256                    KLDRMODMACHO_CHECK_RETURN((KU32)paSyms[iSym].n_sect - 1 <= pModMachO->cSections, KLDR_ERR_MACHO_BAD_SYMBOL);
     3257                    pSymSect = &pModMachO->paSections[paSyms[iSym].n_sect - 1];
     3258                    paGOT[iSym] = paSyms[iSym].n_value - pSymSect->LinkAddress + pSymSect->RVA + NewBaseAddress;
     3259                    break;
     3260                }
     3261
     3262                case MACHO_N_UNDF:
     3263                case MACHO_N_ABS:
     3264                    paGOT[iSym] = paSyms[iSym].n_value;
     3265                    break;
     3266            }
     3267    }
     3268    else
     3269    {
     3270        macho_nlist_64_t const *paSyms = (macho_nlist_64_t const *)pModMachO->pvaSymbols;
     3271        KU64 *paGOT = (KU64 *)((KU8 *)pvBits + pModMachO->GotRVA);
     3272        while (iSym-- > 0)
     3273            switch (paSyms[iSym].n_type & MACHO_N_TYPE)
     3274            {
     3275                case MACHO_N_SECT:
     3276                {
     3277                    PKLDRMODMACHOSECT pSymSect;
     3278                    KLDRMODMACHO_CHECK_RETURN((KU32)paSyms[iSym].n_sect - 1 <= pModMachO->cSections, KLDR_ERR_MACHO_BAD_SYMBOL);
     3279                    pSymSect = &pModMachO->paSections[paSyms[iSym].n_sect - 1];
     3280                    paGOT[iSym] = paSyms[iSym].n_value - pSymSect->LinkAddress + pSymSect->RVA + NewBaseAddress;
     3281                    break;
     3282                }
     3283
     3284                case MACHO_N_UNDF:
     3285                case MACHO_N_ABS:
     3286                    paGOT[iSym] = paSyms[iSym].n_value;
     3287                    break;
     3288            }
     3289    }
     3290    return 0;
    23433291}
    23443292
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

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