-
Notifications
You must be signed in to change notification settings - Fork 786
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
6 changed files
with
333 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
tests/FSharp.Compiler.ComponentTests/EmittedIL/Platform/AssemblyHasMvidSection.fs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
module AssemblyHasMvidSection | ||
|
||
open System | ||
open System.IO | ||
open System.Reflection | ||
open FSharp.Compiler.ComponentTests.EmittedIL | ||
|
||
let pathToDll = | ||
let d = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) | ||
Path.Combine(d, "SimpleFsProgram.dll") | ||
|
||
Console.WriteLine($"Verify mvid section for: {pathToDll}"); | ||
let stream = File.OpenRead(pathToDll); | ||
let mvid = MvidReader.ReadAssemblyMvidOrEmpty(stream) | ||
|
||
let message = $"Mvid for {pathToDll} = {mvid}" | ||
printfn $"{message}" | ||
|
||
if mvid = Guid.Empty then failwith message |
207 changes: 207 additions & 0 deletions
207
tests/FSharp.Compiler.ComponentTests/EmittedIL/Platform/MvidReader.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
using System; | ||
using System.IO; | ||
|
||
namespace FSharp.Compiler.ComponentTests.EmittedIL | ||
{ | ||
public static class MvidReader | ||
{ | ||
private static readonly Guid s_empty = Guid.Empty; | ||
|
||
public static Guid ReadAssemblyMvidOrEmpty(Stream stream) | ||
{ | ||
return ReadAssemblyMvidOrEmpty(new BinaryReader(stream)); | ||
} | ||
|
||
private static Guid ReadAssemblyMvidOrEmpty(BinaryReader reader) | ||
{ | ||
// DOS Header: Magic number (2) | ||
if (!ReadUInt16(reader, out ushort magicNumber) || magicNumber != 0x5a4d) // "MZ" | ||
{ | ||
return s_empty; | ||
} | ||
|
||
// DOS Header: Address of PE Signature (at 0x3C) | ||
if (!MoveTo(0x3C, reader)) | ||
{ | ||
return s_empty; | ||
} | ||
if (!ReadUInt32(reader, out uint pointerToPeSignature)) | ||
{ | ||
return s_empty; | ||
} | ||
|
||
// jump over the MS DOS Stub to the PE Signature | ||
if (!MoveTo(pointerToPeSignature, reader)) | ||
{ | ||
return s_empty; | ||
} | ||
|
||
// PE Signature ('P' 'E' null null) | ||
if (!ReadUInt32(reader, out uint peSig) || peSig != 0x00004550) | ||
{ | ||
return s_empty; | ||
} | ||
|
||
// COFF Header: Machine (2) | ||
if (!Skip(2, reader)) | ||
{ | ||
return s_empty; | ||
} | ||
|
||
// COFF Header: NumberOfSections (2) | ||
if (!ReadUInt16(reader, out ushort sections)) | ||
{ | ||
return s_empty; | ||
} | ||
|
||
// COFF Header: TimeDateStamp (4), PointerToSymbolTable (4), NumberOfSymbols (4) | ||
if (!Skip(12, reader)) | ||
{ | ||
return s_empty; | ||
} | ||
|
||
// COFF Header: OptionalHeaderSize (2) | ||
if (!ReadUInt16(reader, out ushort optionalHeaderSize)) | ||
{ | ||
return s_empty; | ||
} | ||
|
||
// COFF Header: Characteristics (2) | ||
if (!Skip(2, reader)) | ||
{ | ||
return s_empty; | ||
} | ||
|
||
// Optional header | ||
if (!Skip(optionalHeaderSize, reader)) | ||
{ | ||
return s_empty; | ||
} | ||
|
||
// Section headers | ||
return FindMvidInSections(sections, reader); | ||
} | ||
|
||
private static Guid FindMvidInSections(ushort count, BinaryReader reader) | ||
{ | ||
for (int i = 0; i < count; i++) | ||
{ | ||
// Section: Name (8) | ||
if (!ReadBytes(reader, 8, out byte[] name)) | ||
{ | ||
return s_empty; | ||
} | ||
|
||
if (name!.Length == 8 && name[0] == '.' && | ||
name[1] == 'm' && name[2] == 'v' && name[3] == 'i' && name[4] == 'd' && name[5] == '\0') | ||
{ | ||
// Section: VirtualSize (4) | ||
if (!ReadUInt32(reader, out uint virtualSize) || virtualSize != 16) | ||
{ | ||
// The .mvid section only stores a Guid | ||
return s_empty; | ||
} | ||
|
||
// Section: VirtualAddress (4), SizeOfRawData (4) | ||
if (!Skip(8, reader)) | ||
{ | ||
return s_empty; | ||
} | ||
|
||
// Section: PointerToRawData (4) | ||
if (!ReadUInt32(reader, out uint pointerToRawData)) | ||
{ | ||
return s_empty; | ||
} | ||
|
||
return ReadMvidSection(reader, pointerToRawData); | ||
} | ||
else | ||
{ | ||
// Section: VirtualSize (4), VirtualAddress (4), SizeOfRawData (4), | ||
// PointerToRawData (4), PointerToRelocations (4), PointerToLineNumbers (4), | ||
// NumberOfRelocations (2), NumberOfLineNumbers (2), Characteristics (4) | ||
if (!Skip(4 + 4 + 4 + 4 + 4 + 4 + 2 + 2 + 4, reader)) | ||
{ | ||
return s_empty; | ||
} | ||
} | ||
} | ||
|
||
return s_empty; | ||
} | ||
|
||
private static Guid ReadMvidSection(BinaryReader reader, uint pointerToMvidSection) | ||
{ | ||
if (!MoveTo(pointerToMvidSection, reader)) | ||
{ | ||
return s_empty; | ||
} | ||
|
||
if (!ReadBytes(reader, 16, out byte[] guidBytes)) | ||
{ | ||
return s_empty; | ||
} | ||
|
||
return new Guid(guidBytes!); | ||
} | ||
|
||
private static bool ReadUInt16(BinaryReader reader, out ushort output) | ||
{ | ||
if (reader.BaseStream.Position + 2 >= reader.BaseStream.Length) | ||
{ | ||
output = 0; | ||
return false; | ||
} | ||
|
||
output = reader.ReadUInt16(); | ||
return true; | ||
} | ||
|
||
private static bool ReadUInt32(BinaryReader reader, out uint output) | ||
{ | ||
if (reader.BaseStream.Position + 4 >= reader.BaseStream.Length) | ||
{ | ||
output = 0; | ||
return false; | ||
} | ||
|
||
output = reader.ReadUInt32(); | ||
return true; | ||
} | ||
|
||
private static bool ReadBytes(BinaryReader reader, int count, out byte[] output) | ||
{ | ||
if (reader.BaseStream.Position + count >= reader.BaseStream.Length) | ||
{ | ||
output = null; | ||
return false; | ||
} | ||
|
||
output = reader.ReadBytes(count); | ||
return true; | ||
} | ||
|
||
private static bool Skip(int bytes, BinaryReader reader) | ||
{ | ||
if (reader.BaseStream.Position + bytes >= reader.BaseStream.Length) | ||
{ | ||
return false; | ||
} | ||
|
||
reader.BaseStream.Seek(bytes, SeekOrigin.Current); | ||
return true; | ||
} | ||
|
||
private static bool MoveTo(uint position, BinaryReader reader) | ||
{ | ||
if (position >= reader.BaseStream.Length) | ||
{ | ||
return false; | ||
} | ||
|
||
reader.BaseStream.Seek(position, SeekOrigin.Begin); | ||
return true; | ||
} | ||
} | ||
} |
Oops, something went wrong.