Skip to content

3. Basic CLI MetaData reader

DKorablin edited this page Jan 2, 2024 · 1 revision

Common Language Infrastructure introduced by ECMA-335 and consists from 44 MetaData tables, #Strings, #US, #GUID and #Blob heaps.

How to enumerate all declared types and methods

if(file.Header.IsValid == false) return;

StreamTables tables = file.ComDescriptor?.MetaData?.StreamTables;
if(tables == null) return;

foreach(TypeDefRow typeDef in tables.TypeDef)
{
	String fullName = typeDef.TypeNamespace + "." + typeDef.TypeName;
	foreach(MethodDefRow methodDef in typeDef.MethodList)
	{
		String methodName = methodDef.Name;
	}
}

How to read referenced assemblies

if(file.Header.IsValid == false) return;

StreamTables tables = file.ComDescriptor?.MetaData?.StreamTables;
if(tables == null) return;

foreach(AssemblyRefRow assemblyRef in tables.AssemblyRef)
{
    AssemblyName asmName = assemblyRef.AssemblyName;
    AssemblyNameFlags asmFlags = assemblyRef.Flags;
    Version asmVersion = assemblyRef.Version;
    Byte[] publicKeyOrToken = assemblyRef.PublicKeyOrToken;
}

How to find interface implementation

if(file.Header.IsValid == false) return;

StreamTables tables = file.ComDescriptor?.MetaData?.StreamTables;
if(tables == null) return;

foreach(InterfaceImplRow interfaceImpl in tables.InterfaceImpl)
{
    TypeRefRow typeRef = tables.TypeRef[interfaceImpl.Interface.RowIndex.Value];
    String interfaceFullName = typeRef.TypeNamespace + "." + typeRef.TypeName;
}

How to read attributes description

Note: Some attribute signature values can't be read without resolve reference assembly right now. It's related to Enum and non Int32 values.

if(file.Header.IsValid == false) return;

StreamTables tables = file.ComDescriptor?.MetaData?.StreamTables;
if(tables == null) return;

foreach(CustomAttributeRow attribute in tables.CustomAttribute)
{
	foreach(MemberArgument arg in attribute.FixedArgs)
	{// List of all constructor arguments for the attribute
		String name = arg.Name;
		ElementType type = arg.Type;
		Object value = arg.Value;
	}

	foreach(MemberElement prop in attribute.NamedArgs)
	{// List of all properties that are set in the attribute
		String propertyOrFieldName = prop.Name;
		ElementType type = arg.Type;
		Object value = arg.Value;
	}
}