Skip to content

Commit 997d016

Browse files
KevinRansombaronfel
authored andcommitted
Remove FX_NO_LINKED_RESOURCES (#7480)
1 parent 6a4ba7f commit 997d016

12 files changed

Lines changed: 400 additions & 606 deletions

FSharp.Profiles.props

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
<DefineConstants>$(DefineConstants);FX_NO_CORHOST_SIGNER</DefineConstants>
2121
<DefineConstants>$(DefineConstants);FX_NO_EVENTWAITHANDLE_IDISPOSABLE</DefineConstants>
2222
<DefineConstants>$(DefineConstants);FX_NO_EXIT_CONTEXT_FLAGS</DefineConstants>
23-
<DefineConstants>$(DefineConstants);FX_NO_LINKEDRESOURCES</DefineConstants>
2423
<DefineConstants>$(DefineConstants);FX_NO_PARAMETERIZED_THREAD_START</DefineConstants>
2524
<DefineConstants>$(DefineConstants);FX_NO_PDB_READER</DefineConstants>
2625
<DefineConstants>$(DefineConstants);FX_NO_PDB_WRITER</DefineConstants>

fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
<DefineConstants>$(DefineConstants);FX_NO_PDB_READER</DefineConstants>
3636
<DefineConstants>$(DefineConstants);FX_NO_PDB_WRITER</DefineConstants>
3737
<DefineConstants>$(DefineConstants);FX_NO_SYMBOLSTORE</DefineConstants>
38-
<DefineConstants>$(DefineConstants);FX_NO_LINKEDRESOURCES</DefineConstants>
3938
<DefineConstants>$(DefineConstants);FX_NO_APP_DOMAINS</DefineConstants>
4039
<DefineConstants>$(DefineConstants);FX_NO_RUNTIMEENVIRONMENT</DefineConstants>
4140
<DefineConstants>$(DefineConstants);FX_NO_WIN_REGISTRY</DefineConstants>
@@ -228,17 +227,11 @@
228227
</Compile>
229228
</ItemGroup>
230229
<ItemGroup>
231-
<Compile Include="$(FSharpSourcesRoot)/absil/writenativeres.fsi">
232-
<Link>AbsIL/writenativeres.fsi</Link>
230+
<Compile Include="$(FSharpSourcesRoot)/absil/ilnativeres.fsi">
231+
<Link>AbsIL/ilnativeres.fsi</Link>
233232
</Compile>
234-
<Compile Include="$(FSharpSourcesRoot)/absil/writenativeres.fs">
235-
<Link>AbsIL/writenativeres.fs</Link>
236-
</Compile>
237-
<Compile Include="$(FSharpSourcesRoot)/absil/cvtres.fsi">
238-
<Link>AbsIL/cvtres.fsi</Link>
239-
</Compile>
240-
<Compile Include="$(FSharpSourcesRoot)/absil/cvtres.fs">
241-
<Link>AbsIL/cvtres.fs</Link>
233+
<Compile Include="$(FSharpSourcesRoot)/absil/ilnativeres.fs">
234+
<Link>AbsIL/ilnativeres.fs</Link>
242235
</Compile>
243236
<Compile Include="$(FSharpSourcesRoot)/absil/ilsupp.fsi">
244237
<Link>AbsIL/ilsupp.fsi</Link>
Lines changed: 344 additions & 157 deletions
Large diffs are not rendered by default.
Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
module internal FSharp.Compiler.AbstractIL.Internal.CVTres
1+
2+
module internal FSharp.Compiler.AbstractIL.Internal.NativeRes
23

34
open System
5+
open System.Collections.Generic
6+
open System.Linq
7+
open System.Diagnostics
48
open System.IO
9+
open System.Reflection.Metadata
510

611
type BYTE = System.Byte
712
type DWORD = System.UInt32
@@ -26,12 +31,32 @@ type RESOURCE =
2631
member Characteristics : DWORD with get, set
2732
member data : byte[] with get, set
2833

34+
type Win32Resource =
35+
new : data:byte [] * codePage: DWORD * languageId: DWORD * id: int *
36+
name: string * typeId:int * typeName : string -> Win32Resource
37+
member CodePage: DWORD
38+
member Data: byte []
39+
member Id: int
40+
member LanguageId : DWORD
41+
member Name: string
42+
member TypeId: int
43+
member TypeName: string
44+
2945
[<Class>]
3046
type CvtResFile =
3147
static member ReadResFile : stream:Stream -> System.Collections.Generic.List<RESOURCE>
3248

3349
[<Class>]
3450
type Win32ResourceConversions =
3551
static member AppendIconToResourceStream : resStream:Stream * iconStream:Stream -> unit
36-
static member AppendVersionToResourceStream : resStream:Stream * isDll:System.Boolean * fileVersion:string * originalFileName:string * internalName:string * productVersion:string * assemblyVersion:Version * ?fileDescription:string * ?legalCopyright:string * ?legalTrademarks:string * ?productName:string * ?comments:string * ?companyName:string -> unit
37-
static member AppendManifestToResourceStream : resStream:Stream * manifestStream:Stream * isDll:System.Boolean -> unit
52+
static member AppendVersionToResourceStream : resStream:Stream * isDll:System.Boolean * fileVersion:string * originalFileName:string * internalName:string * productVersion:string * assemblyVersion:Version * ?fileDescription:string * ?legalCopyright:string * ?legalTrademarks:string * ?productName:string * ?comments:string * ?companyName:string -> unit
53+
static member AppendManifestToResourceStream : resStream:Stream * manifestStream:Stream * isDll:System.Boolean -> unit
54+
55+
// Write native resources
56+
[<Class>]
57+
type NativeResourceWriter =
58+
static member SortResources: resources: IEnumerable<Win32Resource> -> IEnumerable<Win32Resource>
59+
static member SerializeWin32Resources: builder:BlobBuilder * theResources: IEnumerable<Win32Resource> * resourcesRva: int -> unit
60+
(*
61+
static member SerializeWin32Resources (builder : BlobBuilder, resourceSections : ResourceSection, resourcesRva : int) -> unit
62+
()*)

src/absil/ilsupp.fs

Lines changed: 6 additions & 189 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ open FSharp.Compiler.AbstractIL.Internal
88
open FSharp.Compiler.AbstractIL.Internal.Bytes
99
open FSharp.Compiler.AbstractIL.Diagnostics
1010
open FSharp.Compiler.AbstractIL.Internal.Library
11+
open FSharp.Compiler.AbstractIL.Internal.NativeRes
1112
#if FX_NO_CORHOST_SIGNER
1213
open FSharp.Compiler.AbstractIL.Internal.StrongNameSign
1314
#endif
15+
1416
open System
1517
open System.IO
1618
open System.Text
@@ -37,8 +39,6 @@ let check _action (hresult) =
3739
System.Runtime.InteropServices.Marshal.ThrowExceptionForHR hresult
3840
//printf "action = %s, hresult = 0x%nx \n" action hresult
3941

40-
type PEFileType = X86 | X64
41-
4242
let MAX_PATH = 260
4343

4444
let E_FAIL = 0x80004005
@@ -570,207 +570,24 @@ type ResFormatNode(tid: int32, nid: int32, lid: int32, dataOffset: int32, pbLink
570570

571571
!size
572572

573-
let linkNativeResourcesViaCVTres (unlinkedResources: byte[] list) (ulLinkedResourceBaseRVA: int32) (fileType: PEFileType) (outputFilePath: string) =
574-
let nPEFileType = match fileType with X86 -> 0 | X64 -> 2
575-
let mutable tempResFiles: string list = []
576-
let mutable objBytes: byte[] = [||]
577-
578-
let unlinkedResources = unlinkedResources |> List.filter (fun arr -> arr.Length > 0)
579-
if isNil unlinkedResources then // bail if there's nothing to link
580-
objBytes
581-
else
582-
// Part 1: Write unlinked resources to an object file for linking
583-
// check if the first dword is 0x0
584-
let firstDWord = bytesToDWord(unlinkedResources.[0].[0], unlinkedResources.[0].[1], unlinkedResources.[0].[2], unlinkedResources.[0].[3])
585-
if firstDWord = 0 then
586-
// build the command line invocation string for cvtres.exe
587-
let corSystemDir = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()
588-
// We'll use the current dir and a random file name rather than System.IO.Path.GetTempFileName
589-
// to try and prevent the command line invocation string from being > MAX_PATH
590-
591-
let outputFilePaths =
592-
if outputFilePath = "" then
593-
[ FileSystem.GetTempPathShim() ]
594-
else
595-
[ FileSystem.GetTempPathShim() ; (outputFilePath + "\\") ]
596-
597-
// Get a unique random file
598-
let rec GetUniqueRandomFileName path =
599-
let tfn = path + System.IO.Path.GetRandomFileName()
600-
if FileSystem.SafeExists tfn then
601-
GetUniqueRandomFileName path
602-
else
603-
tfn
604-
605-
606-
let machine = if 2 = nPEFileType then "X64" else "X86"
607-
let cmdLineArgsPreamble = sprintf "/NOLOGO /READONLY /MACHINE:%s" machine
608-
609-
let cvtres = corSystemDir + "cvtres.exe "
610-
611-
let createCvtresArgs path =
612-
let tempObjFileName = GetUniqueRandomFileName path
613-
let mutable cmdLineArgs = sprintf "%s \"/Out:%s\"" cmdLineArgsPreamble tempObjFileName
614-
let mutable resFiles: string list = []
615-
616-
for _ulr in unlinkedResources do
617-
let tempResFileName = GetUniqueRandomFileName path
618-
resFiles <- tempResFileName :: resFiles
619-
cmdLineArgs <- cmdLineArgs + " \"" + tempResFileName + "\""
620-
let trf = resFiles
621-
let cmd = cmdLineArgs
622-
cmd, tempObjFileName, trf
623-
624-
let cmdLineArgs, tempObjFileName, tempResFileNames =
625-
let attempts =
626-
outputFilePaths |>
627-
List.map (fun path -> createCvtresArgs path) |>
628-
List.filter (fun ((argstring: string), (_t: string), (_f: string list)) -> (cvtres.Length + argstring.Length) < MAX_PATH)
629-
let invoc, tmp, files =
630-
match attempts with
631-
| [] -> createCvtresArgs ".\\" // hope for the best...
632-
| (i, t, f) :: _rest -> i, t, f // use the first one, since they're listed in order of precedence
633-
tempResFiles <- files
634-
(invoc, tmp, files)
635-
636-
let cvtresInvocation = cvtres + cmdLineArgs
637-
638-
try
639-
let mutable iFiles = 0
640-
641-
for ulr in unlinkedResources do
642-
// REVIEW: What can go wrong here? What happens when the various file calls fail
643-
// dump the unlinked resource bytes into the temp file
644-
System.IO.File.WriteAllBytes(tempResFileNames.[iFiles], ulr)
645-
iFiles <- iFiles + 1
646-
647-
// call cvtres.exe using the full cmd line string we've generated
648-
649-
// check to see if the generated string is too long - if it is, fail with E_FAIL
650-
if cvtresInvocation.Length >= MAX_PATH then
651-
System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(E_FAIL)
652-
653-
// REVIEW: We really shouldn't be calling out to cvtres
654-
let mutable psi = System.Diagnostics.ProcessStartInfo cvtres
655-
psi.Arguments <- cmdLineArgs
656-
psi.CreateNoWindow <- true ; // REVIEW: For some reason, this still creates a window unless WindowStyle is set to hidden
657-
psi.WindowStyle <- System.Diagnostics.ProcessWindowStyle.Hidden
658-
let p = System.Diagnostics.Process.Start psi
659-
660-
// Wait for the process to finish
661-
p.WaitForExit()
662-
663-
check "Process.Start" p.ExitCode // TODO: really need to check against 0
664-
665-
// Conversion was successful, so read the object file
666-
objBytes <- FileSystem.ReadAllBytesShim tempObjFileName
667-
//Array.Copy(objBytes, pbUnlinkedResource, pbUnlinkedResource.Length)
668-
FileSystem.FileDelete tempObjFileName
669-
finally
670-
// clean up the temp files
671-
List.iter (fun tempResFileName -> FileSystem.FileDelete tempResFileName) tempResFiles
672-
673-
// Part 2: Read the COFF file held in pbUnlinkedResource, spit it out into pResBuffer and apply the COFF fixups
674-
// pResBuffer will become the .rsrc section of the PE file
675-
if (objBytes = Unchecked.defaultof<byte[]>) then
676-
System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(E_FAIL)
677-
678-
let hMod = bytesToIFH objBytes 0
679-
680-
if hMod.SizeOfOptionalHeader <> 0s then
681-
System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(E_FAIL)
682-
683-
let rsrc01Name = 0x313024637273722eL // ".rsrc$01"
684-
let rsrc02Name = 0x323024637273722eL // ".rsrc$02"
685-
let nullHdr = Unchecked.defaultof<IMAGE_SECTION_HEADER>
686-
let mutable rsrc01 = nullHdr
687-
let mutable rsrc02 = nullHdr
688-
689-
for i = 0 to int hMod.NumberOfSections do
690-
let pSection = bytesToISH objBytes (IMAGE_FILE_HEADER.Width + (IMAGE_SECTION_HEADER.Width * i))
691-
if pSection.Name = rsrc01Name then
692-
rsrc01 <- pSection
693-
else if pSection.Name = rsrc02Name then
694-
rsrc02 <- pSection
695-
696-
if (nullHdr = rsrc01) || (nullHdr = rsrc02) then
697-
// One of the rsrc sections wasn't found
698-
System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(E_FAIL)
699-
700-
let size = rsrc01.SizeOfRawData + rsrc02.SizeOfRawData
701-
702-
let pResBuffer = Bytes.zeroCreate size
703-
704-
// Copy over the raw data
705-
Bytes.blit objBytes rsrc01.PointerToRawData pResBuffer 0 rsrc01.SizeOfRawData
706-
707-
// map all the relocs in .rsrc$01 using the reloc and symbol tables in the COFF object
708-
let symbolTableHead = hMod.PointerToSymbolTable
709-
let IMAGE_SYM_CLASS_STATIC = 0x3uy
710-
let IMAGE_SYM_TYPE_NULL = 0x0s
711-
712-
let GetSymbolEntry (buffer: byte[]) (idx: int) =
713-
bytesToIS buffer (symbolTableHead + (idx * IMAGE_SYMBOL.Width) )
714-
715-
for iReloc = 0 to int (rsrc01.NumberOfRelocations - 1s) do
716-
let pReloc = bytesToIR objBytes (rsrc01.PointerToRelocations + (iReloc * IMAGE_RELOCATION.Width))
717-
let IdxSymbol = pReloc.SymbolTableIndex
718-
let pSymbolEntry = GetSymbolEntry objBytes IdxSymbol
719-
720-
// Ensure the symbol entry is valid for a resource
721-
if ((pSymbolEntry.StorageClass <> IMAGE_SYM_CLASS_STATIC) ||
722-
(pSymbolEntry.Type <> IMAGE_SYM_TYPE_NULL) ||
723-
(pSymbolEntry.SectionNumber <> 3s)) then
724-
System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(E_FAIL)
725-
726-
// Ensure that RVA is a valid address inside rsrc02
727-
if pSymbolEntry.Value >= rsrc02.SizeOfRawData then
728-
// pSymbolEntry.Value is too big
729-
System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(E_FAIL)
730-
731-
// store the value
732-
let vBuff, vSize = dwToBytes (ulLinkedResourceBaseRVA + rsrc01.SizeOfRawData + pSymbolEntry.Value)
733-
//Bytes.blit objBytes rsrc02.PointerToRawData pResBuffer pReloc.VirtualAddress rsrc02.SizeOfRawData
734-
Bytes.blit vBuff 0 pResBuffer pReloc.VirtualAddress vSize
735-
// Copy $02 (resource raw into pResBuffer
736-
Bytes.blit objBytes rsrc02.PointerToRawData pResBuffer rsrc01.SizeOfRawData rsrc02.SizeOfRawData
737-
738-
// return the buffer
739-
pResBuffer
740-
741-
let linkNativeResourcesManaged (unlinkedResources: byte[] list) (ulLinkedResourceBaseRVA: int32) (fileType: PEFileType) (outputFilePath: string) =
742-
ignore fileType
743-
ignore outputFilePath
744-
573+
let linkNativeResources (unlinkedResources: byte[] list) (ulLinkedResourceBaseRVA: int32) =
745574
let resources =
746575
unlinkedResources
747576
|> Seq.map (fun s -> new MemoryStream(s))
748577
|> Seq.map (fun s ->
749-
let res = CVTres.CvtResFile.ReadResFile s
578+
let res = CvtResFile.ReadResFile s
750579
s.Dispose()
751580
res)
752581
|> Seq.collect id
753582
// See MakeWin32ResourceList https://github.com/dotnet/roslyn/blob/f40b89234db51da1e1153c14af184e618504be41/src/Compilers/Core/Portable/Compilation/Compilation.cs
754583
|> Seq.map (fun r ->
755-
WriteNativeRes.Win32Resource(data = r.data, codePage = 0u, languageId = uint32 r.LanguageId,
584+
Win32Resource(data = r.data, codePage = 0u, languageId = uint32 r.LanguageId,
756585
id = int (int16 r.pstringName.Ordinal), name = r.pstringName.theString,
757586
typeId = int (int16 r.pstringType.Ordinal), typeName = r.pstringType.theString))
758587
let bb = new System.Reflection.Metadata.BlobBuilder()
759-
WriteNativeRes.NativeResourceWriter.SerializeWin32Resources(bb, resources, ulLinkedResourceBaseRVA)
588+
NativeResourceWriter.SerializeWin32Resources(bb, resources, ulLinkedResourceBaseRVA)
760589
bb.ToArray()
761590

762-
let linkNativeResources (unlinkedResources: byte[] list) (ulLinkedResourceBaseRVA: int32) (fileType: PEFileType) (outputFilePath: string) =
763-
#if ENABLE_MONO_SUPPORT
764-
if IL.runningOnMono then
765-
linkNativeResourcesManaged unlinkedResources ulLinkedResourceBaseRVA fileType outputFilePath
766-
else
767-
#endif
768-
#if !FX_NO_LINKEDRESOURCES
769-
linkNativeResourcesViaCVTres unlinkedResources ulLinkedResourceBaseRVA fileType outputFilePath
770-
#else
771-
linkNativeResourcesManaged unlinkedResources ulLinkedResourceBaseRVA fileType outputFilePath
772-
#endif
773-
774591
let unlinkResource (ulLinkedResourceBaseRVA: int32) (pbLinkedResource: byte[]) =
775592
let mutable nResNodes = 0
776593

src/absil/ilsupp.fsi

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,7 @@ type IStream = System.Runtime.InteropServices.ComTypes.IStream
3535
/// The function may be called twice, once with a zero-RVA and
3636
/// arbitrary buffer, and once with the real buffer. The size of the
3737
/// required buffer is returned.
38-
type PEFileType = X86 | X64
39-
40-
val linkNativeResources: unlinkedResources:byte[] list -> rva:int32 -> PEFileType -> tempFilePath:string -> byte[]
38+
val linkNativeResources: unlinkedResources:byte[] list -> rva:int32 -> byte[]
4139
val unlinkResource: int32 -> byte[] -> byte[]
4240

4341
#if !FX_NO_PDB_WRITER

src/absil/ilwrite.fs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3732,27 +3732,24 @@ let writeBinaryAndReportMappings (outfile,
37323732
let nextPhys = align alignPhys (textSectionPhysLoc + textSectionSize)
37333733
let textSectionPhysSize = nextPhys - textSectionPhysLoc
37343734
let next = align alignVirt (textSectionAddr + textSectionSize)
3735-
3736-
// .RSRC SECTION (DATA)
3735+
3736+
// .RSRC SECTION (DATA)
37373737
let dataSectionPhysLoc = nextPhys
37383738
let dataSectionAddr = next
37393739
let dataSectionVirtToPhys v = v - dataSectionAddr + dataSectionPhysLoc
3740-
3741-
let resourceFormat = if modul.Is64Bit then Support.X64 else Support.X86
3742-
3743-
let nativeResources =
3740+
let nativeResources =
37443741
match modul.NativeResources with
37453742
| [] -> [||]
37463743
| resources ->
3747-
let unlinkedResources =
3748-
resources |> List.map (function
3744+
let unlinkedResources =
3745+
resources |> List.map (function
37493746
| ILNativeResource.Out bytes -> bytes
3750-
| ILNativeResource.In (fileName, linkedResourceBase, start, len) ->
3747+
| ILNativeResource.In (fileName, linkedResourceBase, start, len) ->
37513748
let linkedResource = File.ReadBinaryChunk (fileName, start, len)
37523749
unlinkResource linkedResourceBase linkedResource)
3753-
3750+
37543751
begin
3755-
try linkNativeResources unlinkedResources next resourceFormat (Path.GetDirectoryName outfile)
3752+
try linkNativeResources unlinkedResources next
37563753
with e -> failwith ("Linking a native resource failed: "+e.Message+"")
37573754
end
37583755

0 commit comments

Comments
 (0)