The Metadata API gives developers low-level access to the information encoded in CLI modules: type and methods definitions encoded in metadata as well as access to the CIL code and embedded resources.
Managed developers access this information using either the System.Reflection API or a library like Cecil.
To start using the Metadata API it is necessary to open an assembly or a CIL image (a .dll or .exe file) using one of the CIL image opening API calls.
ECMA CLI images contain four heaps that store different kinds of information, these are:
The ECMA file format also has an extra section called the "#~" stream, this stream is the one that holds the metadata tables. There is a high-level API to get access to the contents of this API, described in the section Metadata Tables.
Metadata is encoded in a number of tables included on every CIL image. These tables contain type definitions, member definitions and so on, these constants are defined in the ECMA 335 specification Partition II section 22. The following table shows the C constants defined in the Mono runtime and how they map to the equivalent ECMA CLI metadata table:
ECMA CLI Table Name | C Constant Name | Table Schema (Array Size + Columns Constants) | Assembly | MONO_TABLE_ASSEMBLY |
Array size:
MONO_ASSEMBLY_SIZE
|
AssemblyOS | MONO_TABLE_ASSEMBLYOS |
Array size:
MONO_ASSEMBLYOS_SIZE
|
AssemblyProcessor | MONO_TABLE_ASSEMBLYPROCESSOR | Array
size: MONO_ASSEMBLYPROCESSOR_SIZE
|
AssemblyRef | MONO_TABLE_ASSEMBLYREF |
Array size:
MONO_ASSEMBLYREF_SIZE
|
AssemblyRefProcessor | MONO_TABLE_ASSEMBLYREFPROCESSOR | Array
size: MONO_ASSEMBLYREFPROC_SIZE
|
AssemblyRefOS | MONO_TABLE_ASSEMBLYREFOS |
Array size:
|
ClassLayout | MONO_TABLE_CLASSLAYOUT |
Array size:
MONO_CLASSLAYOUT_SIZE
|
Constant | MONO_TABLE_CONSTANT |
Array size:
MONO_CONSTANT_SIZE
|
CustomAttribute | MONO_TABLE_CUSTOMATTRIBUTE |
Array size:
MONO_CUSTOM_ATTR_SIZE
|
DeclSecurity | MONO_TABLE_DECLSECURITY |
Array size:
MONO_DECL_SECURITY_SIZE
|
EventMap | MONO_TABLE_EVENTMAP |
Array size:
MONO_EVENT_MAP_SIZE
|
EventPtr | MONO_TABLE_EVENT_POINTER |
Array size:
MONO_EVENT_POINTER_SIZE
|
Event | MONO_TABLE_EVENT |
Array size: MONO_EVENT_SIZE
|
ExportedType | MONO_TABLE_EXPORTEDTYPE |
Array size:
MONO_EXPORTEDTYPE_SIZE
|
Field | MONO_TABLE_FIELD |
Array size: MONO_FIELD_SIZE
|
FieldLayoutt | MONO_TABLE_FIELDLAYOUT |
Array size:
MONO_FIELDLAYOUT_SIZE
|
FieldMarshal | MONO_TABLE_FIELDMARSHAL |
Array size:
MONO_FIELD_MARSHAL_SIZE
|
FieldPtr | MONO_TABLE_FIELD_POINTER |
Array size:
MONO_FIELD_POINTER_SIZE
|
FieldRVA | MONO_TABLE_FIELDRVA |
Array size:
MONO_FIELDRVA_SIZE
|
File | MONO_TABLE_FILE |
Array size: MONO_FILE_SIZE
|
GenericParam | MONO_TABLE_GENERICPARAM |
Array size:
MONO_GENERICPARAM_SIZE
|
GenericParamConstraint | MONO_TABLE_GENERICPARAMCONSTRAINT | Array
size: MONO_GENERICPARAMCONSTRAINT_SIZE
|
ImplMap | MONO_TABLE_IMPLMAP |
Array size:
MONO_IMPLMAP_SIZE
|
InterfaceImpl | MONO_TABLE_INTERFACEIMPL |
Array size:
|
ManifestResource | MONO_TABLE_MANIFESTRESOURCE | Array
size: MONO_MANIFESTRESOURCE_SIZE
|
MemberRef | MONO_TABLE_MEMBERREF |
Array size:
MONO_MEMBERREF_SIZE
|
MethodImpl | MONO_TABLE_METHODIMPL |
Array size:
MONO_METHODIMPL_SIZE
|
MethodSpec | MONO_TABLE_METHODSPEC |
Array size:
MONO_METHODSPEC_SIZE
|
MethodSemantics | MONO_TABLE_METHODSEMANTICS | Array
size: MONO_METHOD_SEMA_SIZE
|
Moduleref | MONO_TABLE_MODULEREF |
Array size:
MONO_MODULEREF_SIZE
|
Module | MONO_TABLE_MODULE |
Array size:
MONO_MODULE_SIZE
Columns:
|
TypeRef | MONO_TABLE_TYPEREF |
Array size:
MONO_TYPEREF_SIZE
|
MethodPtr | MONO_TABLE_METHOD_POINTER |
Array size:
MONO_METHOD_POINTER_SIZE
|
Method | MONO_TABLE_METHOD |
Array size:
MONO_METHOD_SIZE
|
NestedClass | MONO_TABLE_NESTEDCLASS |
Array size:
MONO_NESTEDCLASS_SIZE
|
ParamPtr | MONO_TABLE_PARAM_POINTER |
Array size:
MONO_PARAM_POINTER_SIZE
|
Param | MONO_TABLE_PARAM |
Array size: MONO_PARAM_SIZE
|
PropertyMap | MONO_TABLE_PROPERTYMAP |
Array size:
MONO_PROPERTY_MAP_SIZE
|
PropertyPtr | MONO_TABLE_PROPERTY_POINTER | Array
size: MONO_PROPERTY_POINTER_SIZE
|
Property | MONO_TABLE_PROPERTY |
Array size:
MONO_PROPERTY_SIZE
|
StandaloneSig | MONO_TABLE_STANDALONESIG |
Array size:
|
TypeDef | MONO_TABLE_TYPEDEF |
Array size:
MONO_TYPEDEF_SIZE
|
TypeSpec | MONO_TABLE_TYPESPEC |
Array size:
MONO_TYPESPEC_SIZE
|
Each table can contain zero or more rows, you must call the mono_metadata_table_rows to obtain the number of rows in a table, and then you can extract individual row values by using the mono_metadata_decode_row or the mono_metadata_decode_row_col. When decoding rows you must provide an guint32 array large enough to hold as many columns as the table contains.
The metadata tables are stored in the MonoImage, you obtain a pointer to the MonoTableInfo by calling the mono_image_get_table_info and then you can scan those tables, for example:
/* * Dumps a few fields from the AssemblyRef table */ void DumpAssemblyRefs (MonoImage *image) { /* Get a pointer to the AssemblyRef metadata table */ MonoTableInfo *t = mono_image_get_table_info (image, MONO_TABLE_ASSEMBLYREF); /* Fetch the number of rows available in the table */ int rows = mono_table_info_get_rows (t); int i; /* For each row, print some of its values */ for (i = 0; i < rows; i++){ /* Space where we extract one row from the metadata table */ guint32 cols [MONO_ASSEMBLYREF_SIZE]; /* Extract the row into the array cols */ mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE); fprintf (output, "%d: Version=%d.%d.%d.%d\n\tName=%s\n", i + 1, cols [MONO_ASSEMBLYREF_MAJOR_VERSION], cols [MONO_ASSEMBLYREF_MINOR_VERSION], cols [MONO_ASSEMBLYREF_BUILD_NUMBER], cols [MONO_ASSEMBLYREF_REV_NUMBER], mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])); } }
The above program shows the following output when ran on the C# compiler:
1: Version=1.0.5000.0 Name=mscorlib 2: Version=1.0.5000.0 Name=System 3: Version=1.0.5000.0 Name=System.Xml
These are the APIs for dealing with tables:
This is the low-level API for accessing the metadata images.