ä¸é¢ï¼æä»¬å°±å¼å§åææ¿å¨äººå¿çMetaDataäºã
é¦å
ï¼æ¯å¨IMAGE_COR20_HEADER䏿 ¹æ®å为MetaDataçIMAGE_DATA_DIRECTORYé¡¹æ¥æ¾MetaData表çä½ç½®ï¼è®¡ç®æ¹æ³è·ä¸ææå°çæ¾COM Headerä½ç½®çæ¹æ³æ¯ä¸æ ·çï¼æä»¬å¯ä»¥ç®å¾ï¼MetaData表çä½ç½®æ¯ï¼0x00002148 – 0x00002000 + 0x00000200 = 0x00000348ã
MetaDataçåºæ¬è®¾è®¡æ¹æ³æ¯éç¨äºç®åçå¤åææ¡£ï¼Compound documentï¼ãåºæ¬çç»ç»ç»æå¦ä¸ï¼
// +——————-+
// | Signature |
// +——————-+
// | Stream 1, 2, [] |
// +——————-+
// | STORAGEHEADER |
// | Extra data |
// | STORAGESTREAM[] |
// +——————-+
// | offset |
// +——————-+
å¨clr\src\md\inc\MdFileFormat.hä¸ï¼å®ä¹å¦ä¸ï¼
struct STORAGESIGNATURE
{
public:
//Ingored many getter and setter function
private:
ULONG m_lSignature; // “Magic” signature.0x424a5342
USHORT m_iMajorVer; // Major file version.0x0001
USHORT m_iMinorVer; // Minor file version.0x0001
ULONG m_lExtraData; // Offset to next structure of information 0x0
ULONG m_lVersionStringLength; // Length of version string0x00000008
BYTE m_pVersion[0]; // Version string”v1.0.0″
};
struct STORAGEHEADER
{
BYTE fFlags; // STGHDR_xxx flags.0x00
BYTE pad;0x00
USHORT iStreams; // How many streams are there.0x0005
// function ignored
};
å
¶ä¸fFlagsçå«ä¹å¦ä¸ï¼
enum
{
STGHDR_NORMAL = 0x00, // Normal default flags.
STGHDR_EXTRADATA = 0x01, // Additional data exists after header.
};
ç´§æ¥çSTORAGEHEADERä¸é¢æ¯STORAGESTREAMå卿µçä¿¡æ¯ï¼ä»å¤´é¨æä»¬ç¥éæäºä¸ªæµï¼SSCLIä¸å®ä¹äºå¸é¢ç彿°æ¥å¾å°æµï¼
STORAGESTREAM MDFormat::GetFirstStream(// Return pointer to the first stream.
STORAGEHEADER pHeader, // Return copy of header struct.
const void pvMd) // Pointer to the full file.
{
const BYTE pbMd; // Working pointer.
// Header data starts after signature.
pbMd = (const BYTE *) pvMd;
pbMd += sizeof(STORAGESIGNATURE);
pbMd += ((STORAGESIGNATURE*)pvMd)->VersionStringLength();
STORAGEHEADER \*pHdr = (STORAGEHEADER \*) pbMd;
\*pHeader = \*pHdr;
pbMd += sizeof(STORAGEHEADER);
// If there is extra data, skip over it.
if (pHdr->fFlags & STGHDR_EXTRADATA)
pbMd = pbMd + sizeof(ULONG) + VAL32(\*(ULONG \*) pbMd);
// The pointer is now at the first stream in the list.
return ((STORAGESTREAM *) pbMd);
}
inline STORAGESTREAM *NextStream()
{
int iLen = (int)(strlen(rcName) + 1);
iLen = ALIGN4BYTE(iLen);
return ((STORAGESTREAM \*) (((BYTE\*)this) + (sizeof(ULONG) * 2) + iLen));
}
Metadata Streamæäºç§å¸¸è§ç±»åï¼#String, #Blob, #Guid, #US(User String)å#~æµï¼æ¯ç§ç±»åæµæå¤åªè½åºç°ä¸æ¬¡ï¼#USå#Blobæµå¯çç¥ãä¸é¢ä»¥æ¤ä»ç»æ¯ä¸ä¸ªæµï¼å 为~#æµæå¤æï¼å æ¤æ¾å¨æåä»ç»ã
Stringsæµå#USæµï¼
struct STORAGESTREAM
{
ULONG ulOffset; // Offset in file for this stream.0x000001D0
ULONG ulSize; // Size of the file.0x000000CC
char rcName[MAXSTREAMNAME]; // Start of name, null terminated.”#Strings”
};
struct 
;STORAGESTREAM
{
ULONG ulOffset; // Offset in file for this stream.0x0000029C
ULONG ulSize; // Size of the file.0x00000044
char rcName[MAXSTREAMNAME]; // Start of name, null terminated.”#US”
};
è¿ä¸¤ä¸ªæµåæ¾ç齿¯å符串ã#Stringæµåå¨çæ¯å符串ï¼ä»£ç ä¸çä¸åæè¿°ç¬¦å符串é½ä¿åå¨
è¿éã以#0å符åéãæµçå¼å§æ»æä¸ä¸ª\0å符代表ä¸ä¸ªç©ºå符串ã#USæµåå¨çæ¯ç¨æ·å®ä¹çå符串ï¼å符串以UTF8ç¼ç ä¿åãå¨è®¿é®Streamä¸çå符串æ¶ï¼mdtStringçRID代表ç䏿¯è¡å·ï¼èæ¯å符å¨Streamä¸çåç§»ãæä»¬ä¸¾ä¸¤ä¸ªä¾åççï¼
使ç¨ILDASMå·¥å
·åæ±ç¼Hello.exeï¼ç¶åéæ©âæ¾ç¤ºæ è®°å¼âå°±å¯ä»¥çå°ææçTokenäºï¼æä»¬é便æ¾å°ä¸¤ä¸ªå符串Tokenï¼å嫿¯0x70000017å0x7000002Fï¼ç¶åçå®ä»¬æä»£è¡¨çå¼ãé¦å
ï¼æä»¬è¦ç®åº#USçé¦å°åï¼è½å¨åæ±ç¼éæ¾å°çTokenè¯å®æ¯ç¨æ·å®ä¹çå符串ï¼ç³»ç»ç¨çæ¯ä¸ä¼è®©æä»¬çå°çãï¼ï¼è®¡ç®å
¬å¼æ¯æµçé¦å°åå ä¸åç§» = 0x00000348 + 0x0000029C = 0x000005E4ãç¶ååå«å ä¸ä¸¤ä¸ªå符串çé¦å°ååç§»é0x17å0x2Fï¼å°±æ¯ä¸¤ä¸ªå符串çåç§»ï¼0x000005FBå0x00000613ãæä»¬å¯ä»¥ä»¥çå°ï¼å®ä»¬å嫿¯ï¼âHello WorldâåâEcho: {0}âï¼æ£æ¯æä»¬ç¨åºä¸åºç°çå符ã
GUIDæµï¼
struct STORAGESTREAM
{
ULONG ulOffset; // Offset in file for this stream.0x000002E0
ULONG ulSize; // Size of the file.0x00000010
char rcName[MAXSTREAMNAME]; // Start of name, null terminated.”#GUID”
};
GUIDæµå°±æ¯ä¸ä¸ªGUIDçæ°ç»ï¼æ°ç»ä¸å
ç´ ç个æ°å°±æ¯ï¼STORAGESTREAM.ulSize / sizeof(GUID)ã妿è¿ç¯æç« 读è
è½ä»ç»çå°è¿éï¼é£ä¹ä½ ä¸å®å¯¹GUIDè³çè½è¯¦ï¼å®ä¹å¦ä¸ï¼
typedef struct _GUID
{
ULONG Data1; // NOTE: diff from Win32, for LP64
USHORT Data2;
USHORT Data3;
UCHAR Data4[ 8 ];
} GUID;
å¯¹äºæ¬æä»¶ä¸çGUIDï¼æä»¬å¯ä»¥çå°ï¼å
¶èµ·å§ä½ç½® = 0x00000348 + 0x000002E0 = 0x00000628ãæ°ç»ä¸åªæä¸ä¸ªGUIDï¼å 为 0x10 / sizeof(GUID) = 1ãå
¶å¼ä¸ºï¼{6BE151AB-E2FF-3D10-5CA8-7B77DA98426C}
Blobæµï¼
struct STORAGESTREAM
{
ULONG ulOffset; // Offset in file for this stream.0x000002F0
ULONG ulSize; // Size of the file.0x00000040
char rcName[MAXSTREAMNAME]; // Start of name, null terminated.”#Blob”
};
BLOB æ¯äºè¿å¶å¤§å¯¹è±¡ï¼binary large objectï¼çé¦åæ¯ç¼©åï¼é¡¾åæä¹#Blobæµåæ¾çæ¯å¤§å®çäºè¿å¶æ°æ®ãæ¬ä¾ä¸ï¼èµ·å§ä½ç½® = 0x00000348 + 0x000002F0 = 0x00000638ã
~æµï¼
struct STORAGESTREAM
{
ULONG ulOffset; // Offset in file for this stream.0x00000068
ULONG ulSize; // Size of the file.0x00000168
char rcName[MAXSTREAMNAME]; // Start of name, null terminated.”#~”
};
~æµæ¯åæ¾MetaDataçå°æ¹ã该Assemblyä¸å 乿æçæè¿°ä¿¡æ¯é½æ¾å¨è¿éï¼å æ¤ï¼è¿æ¯å 个æµä¸æéè¦çä¸ä¸ªãMetaData齿¯ä»¥è¡¨çå½¢å¼åæ¾çãæµçèµ·å§ä½ç½® = 0x00000348 + 0x00000068 = 0x000003B0ãæ¤å¤èµ·è¿ç»åæ¾çCMiniMdSchemaBaseç±»åCMiniMdSchemaç±»ï¼å®ä¹å¨clr\src\md\inc\Metamodel.hä¸ï¼ãæ¾å¾æå¥½è¦å¥½è¦å:â( ä½è¿æ¯ç»ææåºæ¥äº:-ï¼ã
class CMiniMdSchemaBase
{
public:
ULONG m_ulReserved; // Reserved, must be zero.0x00000000
BYTE m_major; // Version numbers.0x01
BYTE m_minor;0x00
BYTE m_heaps; // Bits for heap sizes.0x00
BYTE m_rid; // log-base-2 of largest rid.0x01
unsigned _int64 m_maskvalid;// Bit mask of present table counts.0x9`01a21557
unsigned _int64 m_sorted; // Bit mask of sorted tables.0x200`3301fa00
};
class CMiniMdSchema : public CMiniMdSchemaBase
{
public:
ULONG m_cRecs[TBL_COUNT]; // Counts of various tables.
ULONG m_ulExtra; &nb
sp; // Extra data, only persisted if non-zero.
};
å ¶ä¸TBL_COUNTæ¯ä¸ä¸ªæä¸¾ï¼åè¯æä»¬å¨MetaDataä¸ä¸å ±æå¤å°ç§è¡¨ï¼è¡¨æ¯Metadataä¸ç¸å½éè¦çä¸ä¸ªæ¦å¿µï¼æä»¬å¨ä¸æä¸ä¼è¯¦ç»æ¢è®¨ã该æä¸¾å®ä¹å¨clr\src\inc\metamodelpub.hä¸ï¼åå®ä¹æä¸ªå®ï¼å±å¼åæ¯è¿æ ·çãå æ¤æä»¬å¯ä»¥ç¥éTBL_COUNTå¨SSCLIä¸çå®é 弿¯42ãæä»¬ä¹å¯ä»¥çå°ï¼è¿ä¸ªæä¸¾å ¶å®æ¯ä¸æååºçCorTokenTypeæä¸¾çè¶ éã
enum
{
TBL_Module, // 0
TBL_TypeRef,
TBL_TypeDef,
TBL_FieldPtr,
TBL_Field,
TBL_MethodPtr,
TBL_Method,
TBL_ParamPtr,
TBL_Param,
TBL_InterfaceImpl,
TBL_MemberRef,// 10
TBL_Constant,
TBL_CustomAttribute,
TBL_FieldMarshal,
TBL_DeclSecurity,
TBL_ClassLayout,
TBL_FieldLayout,
TBL_StandAloneSig,
TBL_EventMap,
TBL_EventPtr,
TBL_Event,// 20
TBL_PropertyMap,
TBL_PropertyPtr,
TBL_Property,
TBL_MethodSemantics,
TBL_MethodImpl,
TBL_ModuleRef,
TBL_TypeSpec,
TBL_ImplMap,
TBL_FieldRVA,
TBL_ENCLog,// 30
TBL_ENCMap,
TBL_Assembly,
TBL_AssemblyProcessor,
TBL_AssemblyOS,
TBL_AssemblyRef,
TBL_AssemblyRefProcessor,
TBL_AssemblyRefOS,
TBL_File,
TBL_ExportedType,
TBL_ManifestResource,
TBL_NestedClass,
TBL_COUNT// 42
};
CMiniMdSchemaBase ä¸m_heapsæ¯ä¸ä¸ªä½å¾ï¼è¡¨ç¤ºæåæä¸ªå çç´¢å¼çé¿åº¦ã第ä¸ä½è¡¨ç¤º#Stringsæµï¼
第äºä½è¡¨ç¤º#Guidæµï¼ç¬¬ä¸ä½æ²¡ç¨ï¼ç¬¬åä½è¡¨ç¤º#Blobæµãå¦ç¸åºä½è®¾ç½
®ä¸º1ï¼åè¡¨ç¤ºå¯¹åºæµç¨4åèç´¢å¼ãæ¬ä¾ä¸ï¼m_heaps为0ï¼è¡¨ç¤ºææçæµåç¨2åèç´¢å¼ã代ç å¨clr\src\md\runtime\metamodel.cppçCMiniMdBase::SchemaPopulate2ä¸ï¼å¦ä¸ï¼
m_iStringsMask = (m_Schema.m_heaps & CMiniMdSchema::HEAP_STRING_4) ? 0xffffffff : 0xffff;
m_iGuidsMask = (m_Schema.m_heaps & CMiniMdSchema::HEAP_GUID_4) ? 0xffffffff : 0xffff;
m_iBlobsMask = (m_Schema.m_heaps & CMiniMdSchema::HEAP_BLOB_4) ? 0xffffffff : 0xffff;
CMiniMdSchemaBase ä¸çm_maskvalidåm_sortedæ¯ä¸¤ä¸ª64bitçä½å¾ãç¨æ¥æ è¯ç¸å¯¹åºçä½ç表çç¶æï¼å
¶ä¸m_maskvalid表示表表æ¯å¦åå¨ï¼m_sorted表示表æ¯å¦æåºãä¾å¦m_maskvalidçæä½ä½ä¸º1表示TBL_Module表åå¨ãm_sorted第10ä½ä¸º0表示TBL_MemberRef表没ææåºãè¿éå¼å¾ä¸æçæ¯CMiniMdSchemaç±»ä¸çå®ä¹m_cRecs[TBL_COUNT];åªæ¯å
åä¸çéåï¼å¨PEæä»¶ä¸ä¸ºäºèç空é´ï¼å½ç¶è¦èç空é´ï¼Assembly设计ç坿¯å¯ä»¥éè¿ç½ç»å³æ¶ä¸è½½çï¼å¸¦å®½åâ¦â¦ï¼ï¼å¹¶æ²¡æå®é
åæ¾42个ULONGï¼èåªæ¯åæ¾åå¨çULONGãæ¯ä¸ªULONG表示对åºç表æå è¡ãå¨clr\src\md\runtime\Metamodel.cppä¸çCMiniMdSchema::LoadFromä¸ï¼å è½½m_cRecsçä»£ç æ¯ä¸é¢çæ ·åï¼
unsigned __int64 maskvalid = m_maskvalid;
for (iSrc=0, iDst=0; iDst
{
if (maskvalid & 1)
{
m_cRecs[iDst] = VAL32(pSource->m_cRecs[iSrc++]);
}
}
è¿æ®µä»£ç å©ç¨m_maskvalidåä¸çä½å¾ï¼æåå¨è¡¨é¡¹å è½½å°äºç¸åºçå
åæ°ç»ä¸ã卿¬ä¾ä¸ï¼m_maskvalidçå¼ä¸º0x901a21557ï¼å
å«27个1ï¼å æ¤å¨PEæä»¶ä¸ï¼m_cRecså¤åªåå¨14个ULONGãæ ¹æ®m_maskvalidï¼0x901a21557转æäºè¿å¶ä¸º100100000001101000100001010101010111ï¼æä»¬ç¥éä»ä»¬çå¼å嫿¯ï¼
// Module – 0x00000001
// TypeRef – 0x00000004
// TypeDef – 0x00000003
// Field – 0x00000001
// Method – 0x00000006
// Param – 0x00000002
// MemberRef – 0x00000004
// CustomAttribute- 0x00000001
// StandAloneSig – 0x00000002
// PropertyMap – 0x00000001
// Property – 0x00000001
// MethodSemantic- 0x00000002
// Assembly – 0x00000001
// AssemblyRef – 0x00000001
ç´§æ¥çä¸é¢æ¯éå æ°æ®ï¼å¯¹åºçæ¯CMiniMdSchemaä¸çm_ulExtraã使¯è¯¥åä¸ä¸å®åå¨ï¼å¤ææ¯å¦æéå æ°æ®æ¯çCMiniMdSchemaBaseçm_heapsç第7个bitæ¯å¦ä¸º1ã卿¬ä¾ä¸ï¼m_heaps为0ï¼æä»¥ä¸åå¨éå æ°æ®ãSSCLIä¸å¯¹åºç代ç ä¹å¨CMiniMdSchema::LoadFromä¸ï¼å¦ä¸ï¼
enum
{
EXTRA_DATA = 0x40, // If set, schema persists an extra 4 bytes of data.
}
// Retrieve the extra data.
if (m_heaps & EXTRA_DATA)
{
m_ulExtra = (VAL32(*reinterpret_cast
ulData += sizeof(ULONG);
}
ç´§æ¥çéå æ°æ®çå°±æ¯å æ°æ®è¡¨ï¼Metadata Tableï¼ã读è 妿çæå ³ç³»åæ°æ®åºç论ï¼ä¼åç°è¿éçå æ°æ®è¡¨ä¸å ³ç³»åæ°æ®åºä¸ç表é常ç¸ä¼¼ï¼æ¯ä¸ªè¡¨ç±è¥å¹²è¡è¥å¹²åææï¼æ¯ä¸è¡è¡¨ç¤ºä¸ä¸ªè®°å½ï¼æ¯ä¸ …