public static tRVA_Item *Create(tRVA *pThis, void *pFile, void *pSectionHeader) { tRVA_Item *pRet; uint rawOfs; uint rawSize; pRet = ((tRVA_Item *)Mem.malloc((SIZE_T)sizeof(tRVA_Item))); pRet->baseAddress = *(uint *)&((byte *)pSectionHeader)[12]; pRet->size = *(uint *)&((byte *)pSectionHeader)[8]; pRet->pData = Mem.malloc(pRet->size); Mem.memset(pRet->pData, 0, pRet->size); pRet->pNext = pThis->pFirstRVA; pThis->pFirstRVA = pRet; rawOfs = *(uint *)&((byte *)pSectionHeader)[20]; rawSize = *(uint *)&((byte *)pSectionHeader)[16]; if (rawOfs > 0) { if (rawSize > pRet->size) { rawSize = pRet->size; } Mem.memcpy(pRet->pData, ((byte *)pFile) + rawOfs, rawSize); } return(pRet); }
public static void *FindData(tRVA *pThis, uint rva) { tRVA_Item *pRVA; if (rva == 0) { return(null); } pRVA = pThis->pFirstRVA; while (pRVA != null) { if (rva >= pRVA->baseAddress && rva < pRVA->baseAddress + pRVA->size) { return((byte *)(pRVA->pData) + (rva - pRVA->baseAddress)); } pRVA = pRVA->pNext; } return(null); }
public static void LoadTables(tMetaData *pThis, tRVA *pRVA, void *pStream, uint streamLen) { ulong valid, j; byte c; int i, k, numTables; void *pTable; c = *(byte *)&((byte *)pStream)[6]; pThis->index32BitString = (c & 1) > 0 ? (byte)1 : (byte)0; pThis->index32BitGUID = (c & 2) > 0 ? (byte)1 : (byte)0; pThis->index32BitBlob = (c & 4) > 0 ? (byte)1 : (byte)0; valid = *(ulong *)&((byte *)pStream)[8]; // Count how many tables there are, and read in all the number of rows of each table. numTables = 0; for (i = 0, j = 1; i < MAX_TABLES; i++, j <<= 1) { if ((valid & j) != 0) { pThis->tables.numRows[i] = *(uint *)&((byte *)pStream)[24 + numTables * 4]; numTables++; } else { pThis->tables.numRows[i] = 0; pThis->tables.data[i] = /*null*/ 0; } } // Determine if each coded index lookup type needs to use 16 or 32 bit indexes for (i = 0; i < 13; i++) { /*char*/ byte *pCoding = codedTags[i]; int tagBits = codedTagBits[i]; // Discover max table size uint maxTableLen = 0; for (k = 0; k < (1 << tagBits); k++) { byte t = pCoding[k]; if (t != 'z') { if (pThis->tables.numRows[t] > maxTableLen) { maxTableLen = pThis->tables.numRows[t]; } } } if (maxTableLen < (uint)(1 << (16 - tagBits))) { // Use 16-bit number pThis->tables.codedIndex32Bit[i] = 0; } else { // Use 32-bit number pThis->tables.codedIndex32Bit[i] = 1; } } pTable = &((byte *)pStream)[24 + numTables * 4]; for (i = 0; i < MAX_TABLES; i++) { if (pThis->tables.numRows[i] > 0) { if (i >= TABLEDEFS_LENGTH || tableDefs[i] == null) { Sys.Crash("No table definition for MetaData table 0x%02x\n", i); } pThis->tables.data[i] = (PTR)LoadSingleTable(pThis, pRVA, i, &pTable); } } }
// 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); }