/// <summary> /// Create a <see cref="MetadataBase"/> instance /// </summary> /// <param name="peImage">The PE image</param> /// <param name="verify"><c>true</c> if we should verify that it's a .NET PE file</param> /// <returns>A new <see cref="MetadataBase"/> instance</returns> static MetadataBase Create(IPEImage peImage, bool verify) { MetadataBase md = null; try { var dotNetDir = peImage.ImageNTHeaders.OptionalHeader.DataDirectories[14]; // Mono doesn't check that the Size field is >= 0x48 if (dotNetDir.VirtualAddress == 0) { throw new BadImageFormatException(".NET data directory RVA is 0"); } var cor20HeaderReader = peImage.CreateReader(dotNetDir.VirtualAddress, 0x48); var cor20Header = new ImageCor20Header(ref cor20HeaderReader, verify); if (cor20Header.Metadata.VirtualAddress == 0) { throw new BadImageFormatException(".NET metadata RVA is 0"); } var mdRva = cor20Header.Metadata.VirtualAddress; // Don't use the size field, Mono ignores it. Create a reader that can read to EOF. var mdHeaderReader = peImage.CreateReader(mdRva); var mdHeader = new MetadataHeader(ref mdHeaderReader, verify); if (verify) { foreach (var sh in mdHeader.StreamHeaders) { if ((ulong)sh.Offset + sh.StreamSize > mdHeaderReader.EndOffset) { throw new BadImageFormatException("Invalid stream header"); } } } switch (GetMetadataType(mdHeader.StreamHeaders)) { case MetadataType.Compressed: md = new CompressedMetadata(peImage, cor20Header, mdHeader); break; case MetadataType.ENC: md = new ENCMetadata(peImage, cor20Header, mdHeader); break; default: throw new BadImageFormatException("No #~ or #- stream found"); } md.Initialize(null); return(md); } catch { if (md != null) { md.Dispose(); } throw; } }
/// <summary> /// Create a standalone portable PDB <see cref="MetadataBase"/> instance /// </summary> /// <param name="mdReaderFactory">Metadata stream</param> /// <param name="verify"><c>true</c> if we should verify that it's a .NET PE file</param> /// <returns>A new <see cref="MetadataBase"/> instance</returns> internal static MetadataBase CreateStandalonePortablePDB(DataReaderFactory mdReaderFactory, bool verify) { MetadataBase md = null; try { var reader = mdReaderFactory.CreateReader(); var mdHeader = new MetadataHeader(ref reader, verify); if (verify) { foreach (var sh in mdHeader.StreamHeaders) { if (sh.Offset + sh.StreamSize < sh.Offset || sh.Offset + sh.StreamSize > reader.Length) { throw new BadImageFormatException("Invalid stream header"); } } } switch (GetMetadataType(mdHeader.StreamHeaders)) { case MetadataType.Compressed: md = new CompressedMetadata(mdHeader, true); break; case MetadataType.ENC: md = new ENCMetadata(mdHeader, true); break; default: throw new BadImageFormatException("No #~ or #- stream found"); } md.Initialize(mdReaderFactory); return(md); } catch { md?.Dispose(); throw; } }