Skip to content

Commit fb94219

Browse files
KevinRansombaronfel
authored andcommitted
Enable hash algorithm selection (#7252)
* Enable hash algorithm selection * Feedback * More feedback * Revert "Feedback" This reverts commit 6ab1b077b413712f552bad9b2562aeb63994ad4c. * feedback
1 parent 9c5a21e commit fb94219

File tree

9 files changed

+203
-97
lines changed

9 files changed

+203
-97
lines changed

src/absil/ilwrite.fs

Lines changed: 78 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -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)
30293030
let nochunk next = ({addr= 0x0;size= 0x0; }, next)
30303031

30313032
let count f arr =
@@ -3516,7 +3517,7 @@ let writeBytes (os: BinaryWriter) (chunk: byte[]) = os.Write(chunk, 0, chunk.Len
35163517

35173518
let 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 0uy
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] ||| 128uy) <<< 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 0x0uy)
41354160
write (Some (textV2P debugDataChunk.addr)) os "debug data" (Array.create debugDataChunk.size 0x0uy)
4161+
write (Some (textV2P debugChecksumPdbChunk.addr)) os "debug checksum" (Array.create debugChecksumPdbChunk.size 0x0uy)
41364162

41374163
if embeddedPDB then
41384164
write (Some (textV2P debugEmbeddedPdbChunk.addr)) os "debug data" (Array.create debugEmbeddedPdbChunk.size 0x0uy)
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

42904319
let 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

src/absil/ilwrite.fsi

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
22

33
/// The IL Binary writer.
4-
module internal FSharp.Compiler.AbstractIL.ILBinaryWriter
4+
module internal FSharp.Compiler.AbstractIL.ILBinaryWriter
55

66
open Internal.Utilities
7-
open FSharp.Compiler.AbstractIL
8-
open FSharp.Compiler.AbstractIL.Internal
9-
open FSharp.Compiler.AbstractIL.IL
7+
open FSharp.Compiler.AbstractIL
8+
open FSharp.Compiler.AbstractIL.Internal
9+
open FSharp.Compiler.AbstractIL.IL
10+
open FSharp.Compiler.AbstractIL.ILPdbWriter
1011

1112
[<Sealed>]
1213
type ILStrongNameSigner =
@@ -24,6 +25,7 @@ type options =
2425
embedAllSource: bool
2526
embedSourceList: string list
2627
sourceLink: string
28+
checksumAlgorithm: HashAlgorithm
2729
signer : ILStrongNameSigner option
2830
emitTailcalls: bool
2931
deterministic: bool

0 commit comments

Comments
 (0)