Ejemplo n.º 1
0
        // Loads a single table, returns pointer to table in memory.
        public static void *LoadSingleTable(tMetaData *pThis, tRVA *pRVA, int tableID, void **ppTable)
        {
            int             numRows = (int)pThis->tables.numRows[tableID];
            int             rowLen = tableRowSize[tableID];
            int             i, row;
            /*char**/ byte *pDef   = tableDefs[tableID];
            int             defLen = (int)S.strlen(pDef);
            void *          pRet;
            byte *          pSource = (byte *)*ppTable;
            byte *          pDest;
            uint            v = 0;
            SIZE_T          p = 0;

            // Allocate memory for destination table
            pRet  = Mem.malloc((SIZE_T)(numRows * rowLen));
            pDest = (byte *)pRet;

            // Load table
            int srcLen = 0;

            for (row = 0; row < numRows; row++)
            {
                byte *pSrcStart = pSource;
                for (i = 0; i < defLen; i += 2)
                {
                    byte d = pDef[i];
                    if (d < MAX_TABLES)
                    {
                        if (pThis->tables.numRows[d] < 0x10000)
                        {
                            // Use 16-bit offset
                            v        = GetU16(pSource);
                            pSource += 2;
                        }
                        else
                        {
                            // Use 32-bit offset
                            v        = GetU32(pSource);
                            pSource += 4;
                        }
                        v |= (uint)d << 24;
                    }
                    else
                    {
                        switch ((char)d)
                        {
                        case 'c':                         // 8-bit value
                            v = *(byte *)pSource;
                            pSource++;
                            break;

                        case 's':                         // 16-bit short
                            v        = GetU16(pSource);
                            pSource += 2;
                            break;

                        case 'i':                         // 32-bit int
                            v        = GetU32(pSource);
                            pSource += 4;
                            break;

                        case '0':
                        case '1':
                        case '2':
                        case '3':
                        case '4':
                        case '5':
                        case '6':
                        case '7':
                        case '8':
                        case '9':
                        case ':':
                        case ';':
                        case '<':
                        {
                            int            ofs            = pDef[i] - '0';
                            /*char*/ byte *pCoding        = codedTags[ofs];
                            int            tagBits        = codedTagBits[ofs];
                            byte           tag            = (byte)(*pSource & ((1 << tagBits) - 1));
                            int            idxIntoTableID = pCoding[tag];                          // The actual table index that we're looking for
                            if (idxIntoTableID < 0 || idxIntoTableID > MAX_TABLES)
                            {
                                Sys.Crash("Error: Bad table index: 0x%02x\n", idxIntoTableID);
                            }
                            if (pThis->tables.codedIndex32Bit[ofs] != 0)
                            {
                                // Use 32-bit number
                                v        = GetU32(pSource) >> tagBits;
                                pSource += 4;
                            }
                            else
                            {
                                // Use 16-bit number
                                v        = GetU16(pSource) >> tagBits;
                                pSource += 2;
                            }
                            v |= (uint)idxIntoTableID << 24;
                        }
                        break;

                        case 'S':                         // index into string heap
                            if (pThis->index32BitString != 0)
                            {
                                v        = GetU32(pSource);
                                pSource += 4;
                            }
                            else
                            {
                                v        = GetU16(pSource);
                                pSource += 2;
                            }
                            p = (PTR)(pThis->strings.pStart + v);
                            // NOTE: Quick way to validate metadata loading, check if all strings are valid!
                            if (S.isvalidstr((byte *)p) == 0)
                            {
                                Sys.Crash("Invalid string %s", (PTR)p);
                            }
                            break;

                        case 'G':                         // index into GUID heap
                            if (pThis->index32BitGUID != 0)
                            {
                                v        = GetU32(pSource);
                                pSource += 4;
                            }
                            else
                            {
                                v        = GetU16(pSource);
                                pSource += 2;
                            }
                            p = (PTR)(pThis->GUIDs.pGUID1 + ((v - 1) * 16));
                            break;

                        case 'B':                         // index into BLOB heap
                            if (pThis->index32BitBlob != 0)
                            {
                                v        = GetU32(pSource);
                                pSource += 4;
                            }
                            else
                            {
                                v        = GetU16(pSource);
                                pSource += 2;
                            }
                            p = (PTR)(pThis->blobs.pStart + v);
                            break;

                        case '^':                         // RVA to convert to pointer
                            v        = GetU32(pSource);
                            pSource += 4;
                            p        = (PTR)RVA.FindData(pRVA, v);
                            break;

                        case 'm':                         // Pointer to this metadata
                            p = (PTR)pThis;
                            break;

                        case 'l':                         // Is this the last table entry?
                            v = (row == numRows - 1) ? (uint)1 : (uint)0;
                            break;

                        case 'I':                         // Original table index
                            v = MetaData.MAKE_TABLE_INDEX((uint)tableID, (uint)(row + 1));
                            break;

                        case 'x':                         // Nothing, use 0
                            v = 0;
                            p = 0;
                            break;

                        default:
                            Sys.Crash("Cannot handle MetaData source definition character '%c' (0x%02X)\n", d, d);
                            break;
                        }
                    }
                    switch ((char)pDef[i + 1])
                    {
                    case '*':
                        *(SIZE_T *)pDest = p;
                        pDest           += sizeof(SIZE_T);
                        break;

                    case 'i':
                        *(uint *)pDest = v;
                        pDest         += 4;
                        break;

                    case 's':
                        *(ushort *)pDest = (ushort)v;
                        pDest           += 2;
                        break;

                    case 'c':
                        *(byte *)pDest = (byte)v;
                        pDest++;
                        break;

                    case 'x':
                        // Do nothing
                        break;

                    default:
                        Sys.Crash("Cannot handle MetaData destination definition character '%c'\n", pDef[i + 1]);
                        break;
                    }
                }
                if (srcLen == 0)
                {
                    srcLen = (int)(pSource - pSrcStart);
                }
            }

            Sys.log_f(1, "Loaded MetaData table 0x%02X; %d rows %d len\n", tableID, numRows, srcLen);

            // Update the parameter to the position after this table
            *ppTable = pSource;
            // Return new table information
            return(pRet);
        }
Ejemplo n.º 2
0
        private static tCLIFile *LoadPEFile(byte[] image)
        {
            tCLIFile *pRet = ((tCLIFile *)Mem.malloc((SIZE_T)sizeof(tCLIFile)));

            System.Runtime.InteropServices.GCHandle handle = System.Runtime.InteropServices.GCHandle.Alloc(image, GCHandleType.Pinned);
            byte *pData = (byte *)handle.AddrOfPinnedObject();

            byte *pMSDOSHeader = (byte *)&(((byte *)pData)[0]);
            byte *pPEHeader;
            byte *pPEOptionalHeader;
            byte *pPESectionHeaders;
            byte *pCLIHeader;
            byte *pRawMetaData;

            int    i;
            uint   lfanew;
            ushort machine;
            int    numSections;
            //uint imageBase;
            //int fileAlignment;
            uint cliHeaderRVA;
            //uint cliHeaderSize;
            uint metaDataRVA;
            //uint metaDataSize;
            tMetaData *pMetaData;

            pRet->pRVA      = RVA.New();
            pRet->gcHandle  = (PTR)(System.IntPtr)handle;
            pRet->pMetaData = pMetaData = MetaData.New();

            lfanew            = *(uint *)&(pMSDOSHeader[0x3c]);
            pPEHeader         = pMSDOSHeader + lfanew + 4;
            pPEOptionalHeader = pPEHeader + 20;
            pPESectionHeaders = pPEOptionalHeader + 224;

            machine = *(ushort *)&(pPEHeader[0]);
            if (machine != DOT_NET_MACHINE)
            {
                return(null);
            }
            numSections = *(ushort *)&(pPEHeader[2]);

            //imageBase = *(uint*)&(pPEOptionalHeader[28]);
            //fileAlignment = *(int*)&(pPEOptionalHeader[36]);

            for (i = 0; i < numSections; i++)
            {
                byte *pSection = pPESectionHeaders + i * 40;
                RVA.Create(pRet->pRVA, pData, pSection);
            }

            cliHeaderRVA = *(uint *)&(pPEOptionalHeader[208]);
            //cliHeaderSize = *(uint*)&(pPEOptionalHeader[212]);

            pCLIHeader = (byte *)RVA.FindData(pRet->pRVA, cliHeaderRVA);

            metaDataRVA = *(uint *)&(pCLIHeader[8]);
            //metaDataSize = *(uint*)&(pCLIHeader[12]);
            pRet->entryPoint = *(uint *)&(pCLIHeader[20]);
            pRawMetaData     = (byte *)RVA.FindData(pRet->pRVA, metaDataRVA);

            // Load all metadata
            {
                uint  versionLen = *(uint *)&(pRawMetaData[12]);
                uint  ofs, numberOfStreams;
                void *pTableStream    = null;
                uint  tableStreamSize = 0;
                pRet->pVersion = &(pRawMetaData[16]);
                Sys.log_f(1, "CLI version: %s\n", (PTR)pRet->pVersion);
                ofs             = 16 + versionLen;
                numberOfStreams = *(ushort *)&(pRawMetaData[ofs + 2]);
                ofs            += 4;

                for (i = 0; i < (int)numberOfStreams; i++)
                {
                    uint  streamOffset = *(uint *)&pRawMetaData[ofs];
                    uint  streamSize   = *(uint *)&pRawMetaData[ofs + 4];
                    byte *pStreamName  = &pRawMetaData[ofs + 8];
                    void *pStream      = pRawMetaData + streamOffset;
                    ofs += (uint)((S.strlen(pStreamName) + 4) & (~0x3)) + 8;
                    if (S.strcasecmp(pStreamName, "#Strings") == 0)
                    {
                        MetaData.LoadStrings(pMetaData, pStream, streamSize);
                    }
                    else if (S.strcasecmp(pStreamName, "#US") == 0)
                    {
                        MetaData.LoadUserStrings(pMetaData, pStream, streamSize);
                    }
                    else if (S.strcasecmp(pStreamName, "#Blob") == 0)
                    {
                        MetaData.LoadBlobs(pMetaData, pStream, streamSize);
                    }
                    else if (S.strcasecmp(pStreamName, "#GUID") == 0)
                    {
                        MetaData.LoadGUIDs(pMetaData, pStream, streamSize);
                    }
                    else if (S.strcasecmp(pStreamName, "#~") == 0)
                    {
                        pTableStream    = pStream;
                        tableStreamSize = streamSize;
                    }
                }
                // Must load tables last
                if (pTableStream != null)
                {
                    MetaData.LoadTables(pMetaData, pRet->pRVA, pTableStream, (uint)tableStreamSize);
                }
            }

            // Mark all generic definition type and methods as such
            for (i = (int)pMetaData->tables.numRows[MetaDataTable.MD_TABLE_GENERICPARAM]; i > 0; i--)
            {
                tMD_GenericParam * pGenericParam;
                /*IDX_TABLE*/ uint ownerIdx;

                pGenericParam = (tMD_GenericParam *)MetaData.GetTableRow
                                    (pMetaData, MetaData.MAKE_TABLE_INDEX(MetaDataTable.MD_TABLE_GENERICPARAM, (uint)i));
                ownerIdx = pGenericParam->owner;
                switch (MetaData.TABLE_ID(ownerIdx))
                {
                case MetaDataTable.MD_TABLE_TYPEDEF:
                {
                    tMD_TypeDef *pTypeDef = (tMD_TypeDef *)MetaData.GetTableRow(pMetaData, ownerIdx);
                    pTypeDef->isGenericDefinition = 1;
                }
                break;

                case MetaDataTable.MD_TABLE_METHODDEF:
                {
                    tMD_MethodDef *pMethodDef = (tMD_MethodDef *)MetaData.GetTableRow(pMetaData, ownerIdx);
                    pMethodDef->isGenericDefinition = 1;
                }
                break;

                default:
                    Sys.Crash("Wrong generic parameter owner: 0x%08x", ownerIdx);
                    break;
                }
            }

            // Mark all nested classes as such
            for (i = (int)pMetaData->tables.numRows[MetaDataTable.MD_TABLE_NESTEDCLASS]; i > 0; i--)
            {
                tMD_NestedClass *pNested;
                tMD_TypeDef *    pParent;
                tMD_TypeDef *    pChild;

                pNested           = (tMD_NestedClass *)MetaData.GetTableRow(pMetaData, MetaData.MAKE_TABLE_INDEX(MetaDataTable.MD_TABLE_NESTEDCLASS, (uint)i));
                pParent           = (tMD_TypeDef *)MetaData.GetTableRow(pMetaData, pNested->enclosingClass);
                pChild            = (tMD_TypeDef *)MetaData.GetTableRow(pMetaData, pNested->nestedClass);
                pChild->pNestedIn = pParent;
            }

            return(pRet);
        }