Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Debugging -- Enable debugging scripts with the VS Debugger. #14537

Merged
merged 14 commits into from
Feb 14, 2023
30 changes: 15 additions & 15 deletions src/Compiler/AbstractIL/ilsign.fs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ let check _action hresult =
[<Struct; StructLayout(LayoutKind.Explicit)>]
type ByteArrayUnion =
[<FieldOffset(0)>]
val UnderlyingArray: byte[]
val UnderlyingArray: byte array

[<FieldOffset(0)>]
val ImmutableArray: ImmutableArray<byte>
Expand Down Expand Up @@ -81,7 +81,7 @@ let hashAssembly (peReader: PEReader) (hashAlgorithm: IncrementalHash) =
peHeaderOffset + peHeaderSize + int peHeaders.CoffHeader.NumberOfSections * 0x28 // sizeof(IMAGE_SECTION_HEADER)

let allHeaders =
let array: byte[] = Array.zeroCreate<byte> allHeadersSize
let array = Array.zeroCreate<byte> allHeadersSize
peReader.GetEntireImage().GetContent().CopyTo(0, array, 0, allHeadersSize)
array

Expand Down Expand Up @@ -129,9 +129,9 @@ let hashAssembly (peReader: PEReader) (hashAlgorithm: IncrementalHash) =
hashAlgorithm.GetHashAndReset()

type BlobReader =
val mutable _blob: byte[]
val mutable _blob: byte array
val mutable _offset: int
new(blob: byte[]) = { _blob = blob; _offset = 0 }
new(blob: byte array) = { _blob = blob; _offset = 0 }

member x.ReadInt32() : int =
let offset = x._offset
Expand All @@ -142,13 +142,13 @@ type BlobReader =
||| (int x._blob[offset + 2] <<< 16)
||| (int x._blob[offset + 3] <<< 24)

member x.ReadBigInteger(length: int) : byte[] =
let arr: byte[] = Array.zeroCreate<byte> length
member x.ReadBigInteger(length: int) : byte array =
let arr = Array.zeroCreate<byte> length
Array.Copy(x._blob, x._offset, arr, 0, length)
x._offset <- x._offset + length
arr |> Array.rev

let RSAParamatersFromBlob (blob: byte[]) keyType =
let RSAParamatersFromBlob blob keyType =
let mutable reader = BlobReader blob

if reader.ReadInt32() <> 0x00000207 && keyType = KeyType.KeyPair then
Expand Down Expand Up @@ -177,14 +177,14 @@ let RSAParamatersFromBlob (blob: byte[]) keyType =
key.D <- reader.ReadBigInteger byteLen
key

let validateRSAField (field: byte[] MaybeNull) expected (name: string) =
let validateRSAField (field: byte array MaybeNull) expected (name: string) =
match field with
| Null -> ()
| NonNull field ->
if field.Length <> expected then
raise (CryptographicException(String.Format(getResourceString (FSComp.SR.ilSignInvalidRSAParams ()), name)))

let toCLRKeyBlob (rsaParameters: RSAParameters) (algId: int) : byte[] =
let toCLRKeyBlob (rsaParameters: RSAParameters) (algId: int) : byte array =

// The original FCall this helper emulates supports other algId's - however, the only algid we need to support is CALG_RSA_KEYX. We will not port the codepaths dealing with other algid's.
if algId <> CALG_RSA_KEYX then
Expand Down Expand Up @@ -257,7 +257,7 @@ let toCLRKeyBlob (rsaParameters: RSAParameters) (algId: int) : byte[] =

key

let createSignature (hash: byte[]) (keyBlob: byte[]) keyType =
let createSignature hash keyBlob keyType =
use rsa = RSA.Create()
rsa.ImportParameters(RSAParamatersFromBlob keyBlob keyType)

Expand All @@ -266,7 +266,7 @@ let createSignature (hash: byte[]) (keyBlob: byte[]) keyType =

signature |> Array.rev

let patchSignature (stream: Stream) (peReader: PEReader) (signature: byte[]) =
let patchSignature (stream: Stream) (peReader: PEReader) (signature: byte array) =
let peHeaders = peReader.PEHeaders
let signatureDirectory = peHeaders.CorHeader.StrongNameSignatureDirectory

Expand Down Expand Up @@ -297,7 +297,7 @@ let signStream stream keyBlob =
let signature = createSignature hash keyBlob KeyType.KeyPair
patchSignature stream peReader signature

let signatureSize (pk: byte[]) =
let signatureSize (pk: byte array) =
if pk.Length < 25 then
raise (CryptographicException(getResourceString (FSComp.SR.ilSignInvalidPKBlob ())))

Expand All @@ -321,9 +321,9 @@ let getPublicKeyForKeyPair keyBlob =

// Key signing
type keyContainerName = string
type keyPair = byte[]
type pubkey = byte[]
type pubkeyOptions = byte[] * bool
type keyPair = byte array
type pubkey = byte array
type pubkeyOptions = byte array * bool

let signerOpenPublicKeyFile filePath =
FileSystem.OpenFileForReadShim(filePath).ReadAllBytes()
Expand Down
8 changes: 4 additions & 4 deletions src/Compiler/AbstractIL/ilsign.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ open System.IO
//---------------------------------------------------------------------
[<Sealed>]
type ILStrongNameSigner =
member PublicKey: byte[]
member PublicKey: byte array
static member OpenPublicKeyOptions: byte array -> bool -> ILStrongNameSigner
static member OpenPublicKey: byte[] -> ILStrongNameSigner
static member OpenKeyPairFile: byte[] -> ILStrongNameSigner
static member OpenPublicKey: byte array -> ILStrongNameSigner
static member OpenKeyPairFile: byte array -> ILStrongNameSigner
static member OpenKeyContainer: string -> ILStrongNameSigner
member IsFullySigned: bool
member PublicKey: byte[]
member PublicKey: byte array
member SignatureSize: int
member SignStream: Stream -> unit
2 changes: 1 addition & 1 deletion src/Compiler/AbstractIL/ilwrite.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3744,7 +3744,6 @@ let writePdb (
stream.WriteTo fs
getInfoForPortablePdb contentId pdbfile pathMap debugDataChunk debugDeterministicPdbChunk debugChecksumPdbChunk algorithmName checkSum embeddedPDB deterministic
| None -> [| |]
reportTime "Generate PDB Info"

// Now we have the debug data we can go back and fill in the debug directory in the image
use fs2 = reopenOutput()
Expand Down Expand Up @@ -3772,6 +3771,7 @@ let writePdb (
reportTime "Finalize PDB"
signImage ()
os2.Dispose()
reportTime "Generate PDB Info"
with exn ->
failwith ("Error while writing debug directory entry: " + exn.Message)
(try os2.Dispose(); FileSystem.FileDeleteShim outfile with _ -> ())
Expand Down
108 changes: 69 additions & 39 deletions src/Compiler/Interactive/fsi.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1328,6 +1328,36 @@ let internal mkBoundValueTypedImpl tcGlobals m moduleName name ty =
let qname = QualifiedNameOfFile.QualifiedNameOfFile(Ident(moduleName, m))
entity, v, CheckedImplFile.CheckedImplFile(qname, [], mty, contents, false, false, StampMap.Empty, Map.empty)


let scriptingSymbolsPath =
let createDirectory path =
lazy
try
if not (Directory.Exists(path)) then
KevinRansom marked this conversation as resolved.
Show resolved Hide resolved
Directory.CreateDirectory(path) |> ignore

path
with _ ->
path

createDirectory (Path.Combine(Path.GetTempPath(), $"{DateTime.Now:s}-{Guid.NewGuid():n}".Replace(':', '-')))

let deleteScriptingSymbols () =
try
#if !DEBUG
if scriptingSymbolsPath.IsValueCreated then
if Directory.Exists(scriptingSymbolsPath.Value) then
Directory.Delete(scriptingSymbolsPath.Value, true)
#else
()
#endif
with _ ->
()

AppDomain.CurrentDomain.ProcessExit |> Event.add (fun _ -> deleteScriptingSymbols ())
KevinRansom marked this conversation as resolved.
Show resolved Hide resolved

let dynamicCcuName = "FSI-ASSEMBLY"

/// Encapsulates the coordination of the typechecking, optimization and code generation
/// components of the F# compiler for interactively executed fragments of code.
///
Expand All @@ -1350,12 +1380,12 @@ type internal FsiDynamicCompiler(

let outfile = "TMPFSCI.exe"
KevinRansom marked this conversation as resolved.
Show resolved Hide resolved

let dynamicCcuName = "FSI-ASSEMBLY"

let valueBoundEvent = Control.Event<_>()

let mutable fragmentId = 0
KevinRansom marked this conversation as resolved.
Show resolved Hide resolved

static let mutable dynamicAssemblyId = 0

static let maxVersion = int Int16.MaxValue

let mutable prevIt : ValRef option = None
Expand Down Expand Up @@ -1387,7 +1417,8 @@ type internal FsiDynamicCompiler(
/// Add attributes
let CreateModuleFragment (tcConfigB: TcConfigBuilder, dynamicCcuName, codegenResults) =
if progress then fprintfn fsiConsoleOutput.Out "Creating main module..."
let mainModule = mkILSimpleModule dynamicCcuName (GetGeneratedILModuleName tcConfigB.target dynamicCcuName) (tcConfigB.target = CompilerTarget.Dll) tcConfigB.subsystemVersion tcConfigB.useHighEntropyVA (mkILTypeDefs codegenResults.ilTypeDefs) None None 0x0 (mkILExportedTypes []) ""
let mainModule =
mkILSimpleModule dynamicCcuName (GetGeneratedILModuleName tcConfigB.target dynamicCcuName) (tcConfigB.target = CompilerTarget.Dll) tcConfigB.subsystemVersion tcConfigB.useHighEntropyVA (mkILTypeDefs codegenResults.ilTypeDefs) None None 0x0 (mkILExportedTypes []) ""
{ mainModule
with Manifest =
(let man = mainModule.ManifestOfAssembly
Expand All @@ -1402,7 +1433,7 @@ type internal FsiDynamicCompiler(
let manifest =
let manifest = ilxMainModule.Manifest.Value
let attrs = [
tcGlobals.MakeInternalsVisibleToAttribute(ilxMainModule.ManifestOfAssembly.Name)
tcGlobals.MakeInternalsVisibleToAttribute(dynamicCcuName)
yield! manifest.CustomAttrs.AsList()
]
{ manifest with
Expand All @@ -1412,7 +1443,7 @@ type internal FsiDynamicCompiler(
CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs attrs)
}

// The name of the assembly is "FSI-ASSEMBLY" for all submissions. This number is used for the Version
// The name of the assembly is "FSI-ASSEMBLY" for all submissions. This number is used for the Version
dynamicAssemblyId <- (dynamicAssemblyId + 1) % maxVersion

let ilxMainModule = { ilxMainModule with Manifest = Some manifest }
Expand All @@ -1421,44 +1452,43 @@ type internal FsiDynamicCompiler(
let ilxMainModule =
ilxMainModule |> Morphs.morphILTypeRefsInILModuleMemoized emEnv.MapTypeRef

let opts =
{ ilg = tcGlobals.ilg
// This is not actually written, because we are writing to a stream,
// but needs to be set for some logic of ilwrite to function.
outfile = multiAssemblyName + ".dll"
// This is not actually written, because we embed debug info,
// but needs to be set for some logic of ilwrite to function.
pdbfile = (if tcConfig.debuginfo then Some (multiAssemblyName + ".pdb") else None)
emitTailcalls = tcConfig.emitTailcalls
deterministic = tcConfig.deterministic
// we always use portable for F# Interactive debug emit
portablePDB = true
// we don't use embedded for F# Interactive debug emit
embeddedPDB = false
embedAllSource = tcConfig.embedAllSource
embedSourceList = tcConfig.embedSourceList
// we don't add additional source files to the debug document set
allGivenSources = []
sourceLink = tcConfig.sourceLink
checksumAlgorithm = tcConfig.checksumAlgorithm
signer = None
dumpDebugInfo = tcConfig.dumpDebugInfo
referenceAssemblyOnly = false
referenceAssemblyAttribOpt = None
pathMap = tcConfig.pathMap }

let normalizeAssemblyRefs = id

let assemblyBytes, pdbBytes = WriteILBinaryInMemory (opts, ilxMainModule, normalizeAssemblyRefs)
let opts = {
ilg = tcGlobals.ilg
outfile = multiAssemblyName + ".dll"
pdbfile = Some (Path.Combine(scriptingSymbolsPath.Value, $"{multiAssemblyName}-{dynamicAssemblyId}.pdb"))
emitTailcalls = tcConfig.emitTailcalls
deterministic = tcConfig.deterministic
portablePDB = true
embeddedPDB = false
embedAllSource = false
embedSourceList = []
allGivenSources = []
sourceLink = tcConfig.sourceLink
checksumAlgorithm = tcConfig.checksumAlgorithm
signer = None
dumpDebugInfo = tcConfig.dumpDebugInfo
referenceAssemblyOnly = false
referenceAssemblyAttribOpt = None
pathMap = tcConfig.pathMap
}

let assemblyBytes, pdbBytes = WriteILBinaryInMemory (opts, ilxMainModule, id)

let asm =
match opts.pdbfile, pdbBytes with
| (Some pdbfile), (Some pdbBytes) ->
File.WriteAllBytes(pdbfile, pdbBytes)
| _ -> ()

match pdbBytes with
| None -> Assembly.Load(assemblyBytes)
| Some pdbBytes -> Assembly.Load(assemblyBytes, pdbBytes)
dynamicAssemblies.Add(asm)

let loadedTypes = [ for t in asm.GetTypes() -> t]
ignore loadedTypes
// Force generated types to load
do [ for t in asm.GetTypes() -> t] |> ignore
KevinRansom marked this conversation as resolved.
Show resolved Hide resolved

// remember this assembly
dynamicAssemblies.Add(asm)

let ilScopeRef = ILScopeRef.Assembly (ILAssemblyRef.FromAssemblyName(asm.GetName()))

Expand All @@ -1475,7 +1505,7 @@ type internal FsiDynamicCompiler(
let execs =
[ for edef in entries do
if edef.ArgCount = 0 then
yield (fun () ->
yield (fun () ->
let typ = asm.GetType(edef.DeclaringTypeRef.BasicQualifiedName)
try
ignore (typ.InvokeMember (edef.Name, BindingFlags.InvokeMethod ||| BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlags.Static, null, null, [| |], Globalization.CultureInfo.InvariantCulture))
Expand Down Expand Up @@ -2513,7 +2543,7 @@ type internal MagicAssemblyResolution () =
let res = CommitOperationResult overallSearchResult
match res with
| Choice1Of2 assemblyName ->
if simpleAssemName <> "Mono.Posix" then fsiConsoleOutput.uprintfn "%s" (FSIstrings.SR.fsiBindingSessionTo(assemblyName))
if simpleAssemName <> "Mono.Posix" && progress then fsiConsoleOutput.uprintfn "%s" (FSIstrings.SR.fsiBindingSessionTo(assemblyName))
if isRunningOnCoreClr then
assemblyLoadFrom assemblyName
else
Expand Down