From a7ac2facce91c15940e466f67a4ba9a31f687a1a Mon Sep 17 00:00:00 2001 From: Kevin Ransom Date: Sun, 3 Sep 2017 17:00:18 -0700 Subject: [PATCH 1/3] Fix MethodDebugTable for portablePDBs --- src/absil/ilwritepdb.fs | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/absil/ilwritepdb.fs b/src/absil/ilwritepdb.fs index 009d39f653..3d68edee38 100644 --- a/src/absil/ilwritepdb.fs +++ b/src/absil/ilwritepdb.fs @@ -330,17 +330,22 @@ let generatePortablePdb (embedAllSource:bool) (embedSourceList:string list) (sou | None -> Array.empty | Some (_,_) -> minfo.SequencePoints - let getDocumentHandle d = - if docs.Length = 0 || d < 0 || d > docs.Length then - Unchecked.defaultof - else - match documentIndex.TryGetValue(docs.[d].File) with - | false, _ -> Unchecked.defaultof - | true, h -> h - - if sps.Length = 0 then + let builder = new BlobBuilder() + builder.WriteCompressedInteger(minfo.LocalSignatureToken) + + if sps = Array.empty then + builder.WriteCompressedInteger( 0 ) + builder.WriteCompressedInteger( 0 ) Unchecked.defaultof, Unchecked.defaultof else + let getDocumentHandle d = + if docs.Length = 0 || d < 0 || d > docs.Length then + Unchecked.defaultof + else + match documentIndex.TryGetValue(docs.[d].File) with + | false, _ -> Unchecked.defaultof + | true, h -> h + // Return a document that the entire method body is declared within. // If part of the method body is in another document returns nil handle. let tryGetSingleDocumentIndex = @@ -350,12 +355,8 @@ let generatePortablePdb (embedAllSource:bool) (embedSourceList:string list) (sou singleDocumentIndex <- -1 singleDocumentIndex - let builder = new BlobBuilder() - builder.WriteCompressedInteger(minfo.LocalSignatureToken) - // Initial document: When sp's spread over more than one document we put the initial document here. let singleDocumentIndex = tryGetSingleDocumentIndex - if singleDocumentIndex = -1 then builder.WriteCompressedInteger( MetadataTokens.GetRowNumber(DocumentHandle.op_Implicit(getDocumentHandle (sps.[0].Document))) ) From 01d3e175e7e5c8c554c92bf121adba44e1287f9a Mon Sep 17 00:00:00 2001 From: Kevin Ransom Date: Tue, 5 Sep 2017 02:59:55 -0700 Subject: [PATCH 2/3] ensure that pdb gets a record for abstract methods --- src/absil/ilread.fs | 1 - src/absil/ilsupp.fs | 3 -- src/absil/ilsupp.fsi | 1 - src/absil/ilwrite.fs | 17 +++++-- src/absil/ilwritepdb.fs | 113 ++++++++++++++++++++++++++--------------------- src/absil/ilwritepdb.fsi | 2 +- 6 files changed, 77 insertions(+), 60 deletions(-) diff --git a/src/absil/ilread.fs b/src/absil/ilread.fs index c7a435291c..2d42a6abd8 100644 --- a/src/absil/ilread.fs +++ b/src/absil/ilread.fs @@ -2903,7 +2903,6 @@ and seekReadMethodRVA ctxt (idx,nm,_internalcall,noinline,aggressiveinline,numty try let pdbm = pdbReaderGetMethod pdbr (uncodedToken TableNames.Method idx) - //let rootScope = pdbMethodGetRootScope pdbm let sps = pdbMethodGetSequencePoints pdbm (*dprintf "#sps for 0x%x = %d\n" (uncodedToken TableNames.Method idx) (Array.length sps) *) (* let roota,rootb = pdbScopeGetOffsets rootScope in *) diff --git a/src/absil/ilsupp.fs b/src/absil/ilsupp.fs index c95480bc06..66a1a6aa16 100644 --- a/src/absil/ilsupp.fs +++ b/src/absil/ilsupp.fs @@ -1230,9 +1230,6 @@ let pdbMethodGetToken (meth:PdbMethod) : int32 = let token = meth.symMethod.Token token.GetToken() -let pdbMethodGetRootScope (meth:PdbMethod) : PdbMethodScope = - { symScope = meth.symMethod.RootScope } - let pdbMethodGetSequencePoints (meth:PdbMethod) : PdbSequencePoint array = let pSize = meth.symMethod.SequencePointCount let offsets = Array.zeroCreate pSize diff --git a/src/absil/ilsupp.fsi b/src/absil/ilsupp.fsi index 15da0aa215..3a3748c6d2 100644 --- a/src/absil/ilsupp.fsi +++ b/src/absil/ilsupp.fsi @@ -73,7 +73,6 @@ val pdbDocumentGetLanguageVendor: PdbDocument -> byte[] (* guid *) val pdbDocumentFindClosestLine: PdbDocument -> int -> int val pdbMethodGetToken: PdbMethod -> int32 -val pdbMethodGetRootScope: PdbMethod -> PdbMethodScope val pdbMethodGetSequencePoints: PdbMethod -> PdbSequencePoint array val pdbScopeGetChildren: PdbMethodScope -> PdbMethodScope array diff --git a/src/absil/ilwrite.fs b/src/absil/ilwrite.fs index 838b78783b..3b10ff4340 100644 --- a/src/absil/ilwrite.fs +++ b/src/absil/ilwrite.fs @@ -2577,7 +2577,7 @@ let GenMethodDefAsRow cenv env midx (md: ILMethodDef) = MethName=md.Name LocalSignatureToken=localToken Params= [| |] (* REVIEW *) - RootScope = rootScope + RootScope = Some rootScope Range= match ilmbody.SourceMarker with | Some m when cenv.generatePdb -> @@ -2592,9 +2592,20 @@ let GenMethodDefAsRow cenv env midx (md: ILMethodDef) = Column=m.EndColumn }) | _ -> None SequencePoints=seqpoints } - cenv.AddCode code - addr + addr + | MethodBody.Abstract -> + // Now record the PDB record for this method - we write this out later. + if cenv.generatePdb then + cenv.pdbinfo.Add + { MethToken = getUncodedToken TableNames.Method midx + MethName = md.Name + LocalSignatureToken = 0x0 // No locals it's abstract + Params = [| |] + RootScope = None + Range = None + SequencePoints = [| |] } + 0x0000 | MethodBody.Native -> failwith "cannot write body of native method - Abstract IL cannot roundtrip mixed native/managed binaries" | _ -> 0x0000) diff --git a/src/absil/ilwritepdb.fs b/src/absil/ilwritepdb.fs index 3d68edee38..996110e9b7 100644 --- a/src/absil/ilwritepdb.fs +++ b/src/absil/ilwritepdb.fs @@ -81,7 +81,7 @@ type PdbMethodData = MethName:string LocalSignatureToken: int32 Params: PdbLocalVar array - RootScope: PdbMethodScope + RootScope: PdbMethodScope option Range: (PdbSourceLoc * PdbSourceLoc) option SequencePoints: PdbSequencePoint array } @@ -224,7 +224,7 @@ let generatePortablePdb (embedAllSource:bool) (embedSourceList:string list) (sou let externalRowCounts = getRowCounts info.TableRowCounts let docs = match info.Documents with - | null -> Array.empty + | null -> Array.empty | _ -> info.Documents let metadata = MetadataBuilder() @@ -324,16 +324,16 @@ let generatePortablePdb (embedAllSource:bool) (embedSourceList:string list) (sou let docHandle, sequencePointBlob = let sps = match minfo.SequencePoints with - | null -> Array.empty + | null -> Array.empty | _ -> match minfo.Range with - | None -> Array.empty + | None -> Array.empty | Some (_,_) -> minfo.SequencePoints let builder = new BlobBuilder() builder.WriteCompressedInteger(minfo.LocalSignatureToken) - if sps = Array.empty then + if sps.Length = 0 then builder.WriteCompressedInteger( 0 ) builder.WriteCompressedInteger( 0 ) Unchecked.defaultof, Unchecked.defaultof @@ -407,38 +407,41 @@ let generatePortablePdb (embedAllSource:bool) (embedSourceList:string list) (sou // Write the scopes let nextHandle handle = MetadataTokens.LocalVariableHandle(MetadataTokens.GetRowNumber(LocalVariableHandle.op_Implicit(handle)) + 1) let writeMethodScope scope = - let scopeSorter (scope1:PdbMethodScope) (scope2:PdbMethodScope) = - if scope1.StartOffset > scope2.StartOffset then 1 - elif scope1.StartOffset < scope2.StartOffset then -1 - elif (scope1.EndOffset - scope1.StartOffset) > (scope2.EndOffset - scope2.StartOffset) then -1 - elif (scope1.EndOffset - scope1.StartOffset) < (scope2.EndOffset - scope2.StartOffset) then 1 - else 0 - - let collectScopes scope = - let list = new List() - let rec toList scope = - list.Add scope - scope.Children |> Seq.iter(fun s -> toList s) - toList scope - list.ToArray() |> Array.sortWith scopeSorter - - collectScopes scope |> Seq.iter(fun s -> - if s.Children.Length = 0 then - metadata.AddLocalScope(MetadataTokens.MethodDefinitionHandle(minfo.MethToken), - Unchecked.defaultof, - nextHandle lastLocalVariableHandle, - Unchecked.defaultof, - 0, s.EndOffset - s.StartOffset ) |>ignore - else - metadata.AddLocalScope(MetadataTokens.MethodDefinitionHandle(minfo.MethToken), - Unchecked.defaultof, - nextHandle lastLocalVariableHandle, - Unchecked.defaultof, - s.StartOffset, s.EndOffset - s.StartOffset) |>ignore - - for localVariable in s.Locals do - lastLocalVariableHandle <- metadata.AddLocalVariable(LocalVariableAttributes.None, localVariable.Index, metadata.GetOrAddString(localVariable.Name)) - ) + match scope with + | Some scope -> + let scopeSorter (scope1:PdbMethodScope) (scope2:PdbMethodScope) = + if scope1.StartOffset > scope2.StartOffset then 1 + elif scope1.StartOffset < scope2.StartOffset then -1 + elif (scope1.EndOffset - scope1.StartOffset) > (scope2.EndOffset - scope2.StartOffset) then -1 + elif (scope1.EndOffset - scope1.StartOffset) < (scope2.EndOffset - scope2.StartOffset) then 1 + else 0 + + let collectScopes scope = + let list = new List() + let rec toList scope = + list.Add scope + scope.Children |> Seq.iter(fun s -> toList s) + toList scope + list.ToArray() |> Array.sortWith scopeSorter + + collectScopes scope |> Seq.iter(fun s -> + if s.Children.Length = 0 then + metadata.AddLocalScope(MetadataTokens.MethodDefinitionHandle(minfo.MethToken), + Unchecked.defaultof, + nextHandle lastLocalVariableHandle, + Unchecked.defaultof, + 0, s.EndOffset - s.StartOffset ) |>ignore + else + metadata.AddLocalScope(MetadataTokens.MethodDefinitionHandle(minfo.MethToken), + Unchecked.defaultof, + nextHandle lastLocalVariableHandle, + Unchecked.defaultof, + s.StartOffset, s.EndOffset - s.StartOffset) |>ignore + + for localVariable in s.Locals do + lastLocalVariableHandle <- metadata.AddLocalVariable(LocalVariableAttributes.None, localVariable.Index, metadata.GetOrAddString(localVariable.Name)) + ) + | None -> () writeMethodScope minfo.RootScope ) let entryPoint = @@ -554,18 +557,20 @@ let writePdbInfo showTimes f fpdb info cvChunk = // Write the scopes let rec writePdbScope parent sco = - if parent = None || sco.Locals.Length <> 0 || sco.Children.Length <> 0 then - // Only nest scopes if the child scope is a different size from - let nested = - match parent with - | Some p -> sco.StartOffset <> p.StartOffset || sco.EndOffset <> p.EndOffset - | None -> true - if nested then pdbOpenScope !pdbw sco.StartOffset - sco.Locals |> Array.iter (fun v -> pdbDefineLocalVariable !pdbw v.Name v.Signature v.Index) - sco.Children |> Array.iter (writePdbScope (if nested then Some sco else parent)) - if nested then pdbCloseScope !pdbw sco.EndOffset - - writePdbScope None minfo.RootScope + if parent = None || sco.Locals.Length <> 0 || sco.Children.Length <> 0 then + // Only nest scopes if the child scope is a different size from + let nested = + match parent with + | Some p -> sco.StartOffset <> p.StartOffset || sco.EndOffset <> p.EndOffset + | None -> true + if nested then pdbOpenScope !pdbw sco.StartOffset + sco.Locals |> Array.iter (fun v -> pdbDefineLocalVariable !pdbw v.Name v.Signature v.Index) + sco.Children |> Array.iter (writePdbScope (if nested then Some sco else parent)) + if nested then pdbCloseScope !pdbw sco.EndOffset + + match minfo.RootScope with + | None -> () + | Some rootscope -> writePdbScope None rootscope pdbCloseMethod !pdbw end) reportTime showTimes "PDB: Wrote methods" @@ -675,7 +680,10 @@ let writeMdbInfo fmdb f info = for child in scope.Children do writeScope(child) wr?CloseScope(scope.EndOffset) - writeScope(meth.RootScope) + match meth.RootScope with + | None -> () + | Some rootscope -> writeScope(rootscope) + // Finished generating debug information for the curretn method wr?CloseMethod() @@ -722,5 +730,8 @@ let logDebugInfo (outfile:string) (info:PdbData) = if scope.Locals.Length > 0 then fprintfn sw " %s Locals: %A" offs [ for p in scope.Locals -> sprintf "%d: %s" p.Index p.Name ] for child in scope.Children do writeScope (offs + " ") child - writeScope "" meth.RootScope + + match meth.RootScope with + | None -> () + | Some rootscope -> writeScope "" rootscope fprintfn sw "" diff --git a/src/absil/ilwritepdb.fsi b/src/absil/ilwritepdb.fsi index e5d1c8d03a..af9f16be9e 100644 --- a/src/absil/ilwritepdb.fsi +++ b/src/absil/ilwritepdb.fsi @@ -44,7 +44,7 @@ type PdbMethodData = MethName:string LocalSignatureToken: int32 Params: PdbLocalVar array - RootScope: PdbMethodScope + RootScope: PdbMethodScope option Range: (PdbSourceLoc * PdbSourceLoc) option SequencePoints: PdbSequencePoint array } From 64ecadb27b24c1486610deb32c3044ad0b3449ae Mon Sep 17 00:00:00 2001 From: Kevin Ransom Date: Tue, 5 Sep 2017 03:13:04 -0700 Subject: [PATCH 3/3] minimise diff --- src/absil/ilwritepdb.fs | 92 ++++++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/src/absil/ilwritepdb.fs b/src/absil/ilwritepdb.fs index 996110e9b7..f8baa3aea4 100644 --- a/src/absil/ilwritepdb.fs +++ b/src/absil/ilwritepdb.fs @@ -407,42 +407,42 @@ let generatePortablePdb (embedAllSource:bool) (embedSourceList:string list) (sou // Write the scopes let nextHandle handle = MetadataTokens.LocalVariableHandle(MetadataTokens.GetRowNumber(LocalVariableHandle.op_Implicit(handle)) + 1) let writeMethodScope scope = - match scope with - | Some scope -> - let scopeSorter (scope1:PdbMethodScope) (scope2:PdbMethodScope) = - if scope1.StartOffset > scope2.StartOffset then 1 - elif scope1.StartOffset < scope2.StartOffset then -1 - elif (scope1.EndOffset - scope1.StartOffset) > (scope2.EndOffset - scope2.StartOffset) then -1 - elif (scope1.EndOffset - scope1.StartOffset) < (scope2.EndOffset - scope2.StartOffset) then 1 - else 0 - - let collectScopes scope = - let list = new List() - let rec toList scope = - list.Add scope - scope.Children |> Seq.iter(fun s -> toList s) - toList scope - list.ToArray() |> Array.sortWith scopeSorter - - collectScopes scope |> Seq.iter(fun s -> - if s.Children.Length = 0 then - metadata.AddLocalScope(MetadataTokens.MethodDefinitionHandle(minfo.MethToken), - Unchecked.defaultof, - nextHandle lastLocalVariableHandle, - Unchecked.defaultof, - 0, s.EndOffset - s.StartOffset ) |>ignore - else - metadata.AddLocalScope(MetadataTokens.MethodDefinitionHandle(minfo.MethToken), - Unchecked.defaultof, - nextHandle lastLocalVariableHandle, - Unchecked.defaultof, - s.StartOffset, s.EndOffset - s.StartOffset) |>ignore - - for localVariable in s.Locals do - lastLocalVariableHandle <- metadata.AddLocalVariable(LocalVariableAttributes.None, localVariable.Index, metadata.GetOrAddString(localVariable.Name)) - ) - | None -> () - writeMethodScope minfo.RootScope ) + let scopeSorter (scope1:PdbMethodScope) (scope2:PdbMethodScope) = + if scope1.StartOffset > scope2.StartOffset then 1 + elif scope1.StartOffset < scope2.StartOffset then -1 + elif (scope1.EndOffset - scope1.StartOffset) > (scope2.EndOffset - scope2.StartOffset) then -1 + elif (scope1.EndOffset - scope1.StartOffset) < (scope2.EndOffset - scope2.StartOffset) then 1 + else 0 + + let collectScopes scope = + let list = new List() + let rec toList scope = + list.Add scope + scope.Children |> Seq.iter(fun s -> toList s) + toList scope + list.ToArray() |> Array.sortWith scopeSorter + + collectScopes scope |> Seq.iter(fun s -> + if s.Children.Length = 0 then + metadata.AddLocalScope(MetadataTokens.MethodDefinitionHandle(minfo.MethToken), + Unchecked.defaultof, + nextHandle lastLocalVariableHandle, + Unchecked.defaultof, + 0, s.EndOffset - s.StartOffset ) |>ignore + else + metadata.AddLocalScope(MetadataTokens.MethodDefinitionHandle(minfo.MethToken), + Unchecked.defaultof, + nextHandle lastLocalVariableHandle, + Unchecked.defaultof, + s.StartOffset, s.EndOffset - s.StartOffset) |>ignore + + for localVariable in s.Locals do + lastLocalVariableHandle <- metadata.AddLocalVariable(LocalVariableAttributes.None, localVariable.Index, metadata.GetOrAddString(localVariable.Name)) + ) + + match minfo.RootScope with + | None -> () + | Some scope -> writeMethodScope scope ) let entryPoint = match info.EntryPoint with @@ -557,16 +557,16 @@ let writePdbInfo showTimes f fpdb info cvChunk = // Write the scopes let rec writePdbScope parent sco = - if parent = None || sco.Locals.Length <> 0 || sco.Children.Length <> 0 then - // Only nest scopes if the child scope is a different size from - let nested = - match parent with - | Some p -> sco.StartOffset <> p.StartOffset || sco.EndOffset <> p.EndOffset - | None -> true - if nested then pdbOpenScope !pdbw sco.StartOffset - sco.Locals |> Array.iter (fun v -> pdbDefineLocalVariable !pdbw v.Name v.Signature v.Index) - sco.Children |> Array.iter (writePdbScope (if nested then Some sco else parent)) - if nested then pdbCloseScope !pdbw sco.EndOffset + if parent = None || sco.Locals.Length <> 0 || sco.Children.Length <> 0 then + // Only nest scopes if the child scope is a different size from + let nested = + match parent with + | Some p -> sco.StartOffset <> p.StartOffset || sco.EndOffset <> p.EndOffset + | None -> true + if nested then pdbOpenScope !pdbw sco.StartOffset + sco.Locals |> Array.iter (fun v -> pdbDefineLocalVariable !pdbw v.Name v.Signature v.Index) + sco.Children |> Array.iter (writePdbScope (if nested then Some sco else parent)) + if nested then pdbCloseScope !pdbw sco.EndOffset match minfo.RootScope with | None -> ()