@@ -3025,7 +3025,8 @@ let generateIL requiredDataFixups (desiredMetadataVersion, generatePdb, ilg : IL
30253025//=====================================================================
30263026// TABLES+BLOBS --> PHYSICAL METADATA+BLOBS
30273027//=====================================================================
3028- let chunk sz next = ({ addr= next; size= sz}, next + sz)
3028+ let chunk sz next = ({ addr= next; size= sz}, next + sz)
3029+ let emptychunk next = ({ addr= next; size= 0 }, next)
30293030let nochunk next = ({ addr= 0x0 ; size= 0x0 ; }, next)
30303031
30313032let count f arr =
@@ -3516,7 +3517,7 @@ let writeBytes (os: BinaryWriter) (chunk: byte[]) = os.Write(chunk, 0, chunk.Len
35163517
35173518let writeBinaryAndReportMappings ( outfile ,
35183519 ilg : ILGlobals , pdbfile : string option , signer : ILStrongNameSigner option , portablePDB , embeddedPDB ,
3519- embedAllSource , embedSourceList , sourceLink , emitTailcalls , deterministic , showTimes , dumpDebugInfo , pathMap )
3520+ embedAllSource , embedSourceList , sourceLink , checksumAlgorithm , emitTailcalls , deterministic , showTimes , dumpDebugInfo , pathMap )
35203521 modul normalizeAssemblyRefs =
35213522 // Store the public key from the signer into the manifest. This means it will be written
35223523 // to the binary and also acts as an indicator to leave space for delay sign
@@ -3565,7 +3566,7 @@ let writeBinaryAndReportMappings (outfile,
35653566 with e ->
35663567 failwith ( " Could not open file for writing (binary mode): " + outfile)
35673568
3568- let pdbData , pdbOpt , debugDirectoryChunk , debugDataChunk , debugEmbeddedPdbChunk , textV2P , mappings =
3569+ let pdbData , pdbOpt , debugDirectoryChunk , debugDataChunk , debugChecksumPdbChunk , debugEmbeddedPdbChunk , debugDeterministicPdbChunk , textV2P , mappings =
35693570 try
35703571
35713572 let imageBaseReal = modul.ImageBase // FIXED CHOICE
@@ -3670,42 +3671,61 @@ let writeBinaryAndReportMappings (outfile,
36703671 let pdbOpt =
36713672 match portablePDB with
36723673 | true ->
3673- let ( uncompressedLength , contentId , stream ) as pdbStream =
3674- generatePortablePdb embedAllSource embedSourceList sourceLink showTimes pdbData deterministic pathMap
3674+ let ( uncompressedLength , contentId , stream , algorithmName , checkSum ) as pdbStream =
3675+ generatePortablePdb embedAllSource embedSourceList sourceLink checksumAlgorithm showTimes pdbData pathMap
36753676
3676- if embeddedPDB then Some ( compressPortablePdbStream uncompressedLength contentId stream)
3677+ if embeddedPDB then
3678+ let uncompressedLength , contentId , stream = compressPortablePdbStream uncompressedLength contentId stream
3679+ Some ( uncompressedLength, contentId, stream, algorithmName, checkSum)
36773680 else Some pdbStream
36783681
36793682 | _ -> None
36803683
3681- let debugDirectoryChunk , next =
3682- chunk ( if pdbfile = None then
3683- 0x0
3684- else if embeddedPDB && portablePDB then
3685- sizeof_ IMAGE_ DEBUG_ DIRECTORY * 2
3684+ let debugDirectoryChunk , next =
3685+ chunk ( if pdbfile = None then
3686+ 0x0
36863687 else
3687- sizeof_ IMAGE_ DEBUG_ DIRECTORY
3688+ sizeof_ IMAGE_ DEBUG_ DIRECTORY * 2 +
3689+ ( if embeddedPDB then sizeof_ IMAGE_ DEBUG_ DIRECTORY else 0 ) +
3690+ ( if deterministic then sizeof_ IMAGE_ DEBUG_ DIRECTORY else 0 )
36883691 ) next
3692+
36893693 // The debug data is given to us by the PDB writer and appears to
36903694 // typically be the type of the data plus the PDB file name. We fill
36913695 // this in after we've written the binary. We approximate the size according
36923696 // to what PDB writers seem to require and leave extra space just in case...
36933697 let debugDataJustInCase = 40
3694- let debugDataChunk , next =
3698+ let debugDataChunk , next =
36953699 chunk ( align 0x4 ( match pdbfile with
36963700 | None -> 0
36973701 | Some f -> ( 24
36983702 + System.Text.Encoding.Unicode.GetByteCount f // See bug 748444
36993703 + debugDataJustInCase))) next
37003704
3701- let debugEmbeddedPdbChunk , next =
3702- let streamLength =
3703- match pdbOpt with
3704- | Some (_, _, stream) -> int stream.Length
3705- | None -> 0
3706- chunk ( align 0x4 ( match embeddedPDB with
3707- | true -> 8 + streamLength
3708- | _ -> 0 )) next
3705+ let debugChecksumPdbChunk , next =
3706+ chunk ( align 0x4 ( match pdbOpt with
3707+ | Some (_, _, _, algorithmName, checkSum) ->
3708+ let alg = System.Text.Encoding.UTF8.GetBytes( algorithmName)
3709+ let size = alg.Length + 1 + checkSum.Length
3710+ size
3711+ | None -> 0 )) next
3712+
3713+ let debugEmbeddedPdbChunk , next =
3714+ if embeddedPDB then
3715+ let streamLength =
3716+ match pdbOpt with
3717+ | Some (_, _, stream, _, _) -> int stream.Length
3718+ | None -> 0
3719+ chunk ( align 0x4 ( match embeddedPDB with
3720+ | true -> 8 + streamLength
3721+ | _ -> 0 )) next
3722+ else
3723+ nochunk next
3724+
3725+ let debugDeterministicPdbChunk , next =
3726+ if deterministic then emptychunk next
3727+ else nochunk next
3728+
37093729
37103730 let textSectionSize = next - textSectionAddr
37113731 let nextPhys = align alignPhys ( textSectionPhysLoc + textSectionSize)
@@ -3804,35 +3824,39 @@ let writeBinaryAndReportMappings (outfile,
38043824 if pCurrent <> pExpected then
38053825 failwith ( " warning: " + chunkName+ " not where expected, pCurrent = " + string pCurrent+ " , p.addr = " + string pExpected)
38063826 writeBytes os chunk
3807-
3827+
38083828 let writePadding ( os : BinaryWriter ) _comment sz =
38093829 if sz < 0 then failwith " writePadding: size < 0"
38103830 for i = 0 to sz - 1 do
38113831 os.Write 0 uy
3812-
3832+
38133833 // Now we've computed all the offsets, write the image
3814-
3834+
38153835 write ( Some msdosHeaderChunk.addr) os " msdos header" msdosHeader
3816-
3836+
38173837 write ( Some peSignatureChunk.addr) os " pe signature" [| |]
3818-
3838+
38193839 writeInt32 os 0x4550
3820-
3840+
38213841 write ( Some peFileHeaderChunk.addr) os " pe file header" [| |]
3822-
3842+
38233843 if ( modul.Platform = Some AMD64) then
38243844 writeInt32AsUInt16 os 0x8664 // Machine - IMAGE_FILE_MACHINE_AMD64
38253845 elif isItanium then
38263846 writeInt32AsUInt16 os 0x200
38273847 else
38283848 writeInt32AsUInt16 os 0x014c // Machine - IMAGE_FILE_MACHINE_I386
3829-
3849+
38303850 writeInt32AsUInt16 os numSections
38313851
3832- let pdbData =
3852+ let pdbData =
3853+ // Hash code, data and metadata
38333854 if deterministic then
3834- // Hash code, data and metadata
3835- use sha = System.Security.Cryptography.SHA1.Create() // IncrementalHash is core only
3855+ use sha =
3856+ match checksumAlgorithm with
3857+ | HashAlgorithm.Sha1 -> System.Security.Cryptography.SHA1.Create() :> System.Security.Cryptography.HashAlgorithm
3858+ | HashAlgorithm.Sha256 -> System.Security.Cryptography.SHA256.Create() :> System.Security.Cryptography.HashAlgorithm
3859+
38363860 let hCode = sha.ComputeHash code
38373861 let hData = sha.ComputeHash data
38383862 let hMeta = sha.ComputeHash metadata
@@ -3848,6 +3872,7 @@ let writeBinaryAndReportMappings (outfile,
38483872 // Use last 4 bytes for timestamp - High bit set, to stop tool chains becoming confused
38493873 let timestamp = int final.[ 16 ] ||| ( int final.[ 17 ] <<< 8 ) ||| ( int final.[ 18 ] <<< 16 ) ||| ( int ( final.[ 19 ] ||| 128 uy) <<< 24 )
38503874 writeInt32 os timestamp
3875+
38513876 // Update pdbData with new guid and timestamp. Portable and embedded PDBs don't need the ModuleID
38523877 // Full and PdbOnly aren't supported under deterministic builds currently, they rely on non-determinsitic Windows native code
38533878 { pdbData with ModuleID = final.[ 0 .. 15 ] ; Timestamp = timestamp }
@@ -4133,10 +4158,14 @@ let writeBinaryAndReportMappings (outfile,
41334158 if pdbfile.IsSome then
41344159 write ( Some ( textV2P debugDirectoryChunk.addr)) os " debug directory" ( Array.create debugDirectoryChunk.size 0x0 uy)
41354160 write ( Some ( textV2P debugDataChunk.addr)) os " debug data" ( Array.create debugDataChunk.size 0x0 uy)
4161+ write ( Some ( textV2P debugChecksumPdbChunk.addr)) os " debug checksum" ( Array.create debugChecksumPdbChunk.size 0x0 uy)
41364162
41374163 if embeddedPDB then
41384164 write ( Some ( textV2P debugEmbeddedPdbChunk.addr)) os " debug data" ( Array.create debugEmbeddedPdbChunk.size 0x0 uy)
41394165
4166+ if deterministic then
4167+ write ( Some ( textV2P debugDeterministicPdbChunk.addr)) os " debug deterministic" Array.empty
4168+
41404169 writePadding os " end of .text" ( dataSectionPhysLoc - textSectionPhysLoc - textSectionSize)
41414170
41424171 // DATA SECTION
@@ -4182,7 +4211,7 @@ let writeBinaryAndReportMappings (outfile,
41824211 FileSystemUtilites.setExecutablePermission outfile
41834212 with _ ->
41844213 ()
4185- pdbData, pdbOpt, debugDirectoryChunk, debugDataChunk, debugEmbeddedPdbChunk, textV2P, mappings
4214+ pdbData, pdbOpt, debugDirectoryChunk, debugDataChunk, debugChecksumPdbChunk , debugEmbeddedPdbChunk, debugDeterministicPdbChunk , textV2P, mappings
41864215
41874216 // Looks like a finally
41884217 with e ->
@@ -4207,11 +4236,11 @@ let writeBinaryAndReportMappings (outfile,
42074236 try
42084237 let idd =
42094238 match pdbOpt with
4210- | Some ( originalLength, contentId, stream) ->
4239+ | Some ( originalLength, contentId, stream, algorithmName , checkSum ) ->
42114240 if embeddedPDB then
4212- embedPortablePdbInfo originalLength contentId stream showTimes fpdb debugDataChunk debugEmbeddedPdbChunk
4241+ embedPortablePdbInfo originalLength contentId stream showTimes fpdb debugDataChunk debugEmbeddedPdbChunk debugDeterministicPdbChunk debugChecksumPdbChunk algorithmName checkSum embeddedPDB deterministic
42134242 else
4214- writePortablePdbInfo contentId stream showTimes fpdb pathMap debugDataChunk
4243+ writePortablePdbInfo contentId stream showTimes fpdb pathMap debugDataChunk debugDeterministicPdbChunk debugChecksumPdbChunk algorithmName checkSum embeddedPDB deterministic
42154244 | None ->
42164245#if FX_ NO_ PDB_ WRITER
42174246 Array.empty< idd>
@@ -4232,16 +4261,17 @@ let writeBinaryAndReportMappings (outfile,
42324261 writeInt32AsUInt16 os2 i.iddMajorVersion
42334262 writeInt32AsUInt16 os2 i.iddMinorVersion
42344263 writeInt32 os2 i.iddType
4235- writeInt32 os2 i.iddData.Length // IMAGE_DEBUG_DIRECTORY.SizeOfData
4236- writeInt32 os2 i.iddChunk.addr // IMAGE_DEBUG_DIRECTORY.AddressOfRawData
4237- writeInt32 os2 ( textV2P i.iddChunk.addr) // IMAGE_DEBUG_DIRECTORY.PointerToRawData
4264+ writeInt32 os2 i.iddData.Length // IMAGE_DEBUG_DIRECTORY.SizeOfData
4265+ writeInt32 os2 i.iddChunk.addr // IMAGE_DEBUG_DIRECTORY.AddressOfRawData
4266+ writeInt32 os2 ( textV2P i.iddChunk.addr) // IMAGE_DEBUG_DIRECTORY.PointerToRawData
42384267
42394268 // Write the Debug Data
42404269 for i in idd do
4241- // write the debug raw data as given us by the PDB writer
4242- os2.BaseStream.Seek ( int64 ( textV2P i.iddChunk.addr), SeekOrigin.Begin) |> ignore
4243- if i.iddChunk.size < i.iddData.Length then failwith " Debug data area is not big enough. Debug info may not be usable"
4244- writeBytes os2 i.iddData
4270+ if i.iddChunk.size <> 0 then
4271+ // write the debug raw data as given us by the PDB writer
4272+ os2.BaseStream.Seek ( int64 ( textV2P i.iddChunk.addr), SeekOrigin.Begin) |> ignore
4273+ if i.iddChunk.size < i.iddData.Length then failwith " Debug data area is not big enough. Debug info may not be usable"
4274+ writeBytes os2 i.iddData
42454275 os2.Dispose()
42464276 with e ->
42474277 failwith ( " Error while writing debug directory entry: " + e.Message)
@@ -4250,9 +4280,7 @@ let writeBinaryAndReportMappings (outfile,
42504280 with e ->
42514281 reraise()
42524282
4253- end
4254- ignore debugDataChunk
4255- ignore debugEmbeddedPdbChunk
4283+ end
42564284 reportTime showTimes " Finalize PDB"
42574285
42584286 /// Sign the binary. No further changes to binary allowed past this point!
@@ -4280,15 +4308,16 @@ type options =
42804308 embedAllSource: bool
42814309 embedSourceList: string list
42824310 sourceLink: string
4311+ checksumAlgorithm: HashAlgorithm
42834312 signer: ILStrongNameSigner option
4284- emitTailcalls : bool
4285- deterministic : bool
4313+ emitTailcalls: bool
4314+ deterministic: bool
42864315 showTimes: bool
42874316 dumpDebugInfo: bool
42884317 pathMap: PathMap }
42894318
42904319let WriteILBinary ( outfile , ( args : options ), modul , normalizeAssemblyRefs ) =
42914320 writeBinaryAndReportMappings ( outfile,
42924321 args.ilg, args.pdbfile, args.signer, args.portablePDB, args.embeddedPDB, args.embedAllSource,
4293- args.embedSourceList, args.sourceLink, args.emitTailcalls, args.deterministic, args.showTimes, args.dumpDebugInfo, args.pathMap) modul normalizeAssemblyRefs
4322+ args.embedSourceList, args.sourceLink, args.checksumAlgorithm , args. emitTailcalls, args.deterministic, args.showTimes, args.dumpDebugInfo, args.pathMap) modul normalizeAssemblyRefs
42944323 |> ignore
0 commit comments