20
20
#include " Symbols.h"
21
21
#include " llvm/ADT/Optional.h"
22
22
#include " llvm/ADT/StringSwitch.h"
23
- #include " llvm/BinaryFormat/COFF.h"
24
23
#include " llvm/Object/COFF.h"
25
24
#include " llvm/Object/WindowsResource.h"
26
25
#include " llvm/Option/Arg.h"
27
26
#include " llvm/Option/ArgList.h"
28
27
#include " llvm/Option/Option.h"
29
28
#include " llvm/Support/CommandLine.h"
30
29
#include " llvm/Support/FileUtilities.h"
31
- #include " llvm/Support/MathExtras.h"
32
30
#include " llvm/Support/Process.h"
33
31
#include " llvm/Support/Program.h"
34
32
#include " llvm/Support/raw_ostream.h"
@@ -44,9 +42,6 @@ namespace lld {
44
42
namespace coff {
45
43
namespace {
46
44
47
- const uint16_t SUBLANG_ENGLISH_US = 0x0409 ;
48
- const uint16_t RT_MANIFEST = 24 ;
49
-
50
45
class Executor {
51
46
public:
52
47
explicit Executor (StringRef S) : Prog(Saver.save(S)) {}
@@ -266,6 +261,26 @@ void parseManifestUAC(StringRef Arg) {
266
261
}
267
262
}
268
263
264
+ // Quote each line with "". Existing double-quote is converted
265
+ // to two double-quotes.
266
+ static void quoteAndPrint (raw_ostream &Out, StringRef S) {
267
+ while (!S.empty ()) {
268
+ StringRef Line;
269
+ std::tie (Line, S) = S.split (" \n " );
270
+ if (Line.empty ())
271
+ continue ;
272
+ Out << ' \" ' ;
273
+ for (int I = 0 , E = Line.size (); I != E; ++I) {
274
+ if (Line[I] == ' \" ' ) {
275
+ Out << " \"\" " ;
276
+ } else {
277
+ Out << Line[I];
278
+ }
279
+ }
280
+ Out << " \"\n " ;
281
+ }
282
+ }
283
+
269
284
// An RAII temporary file class that automatically removes a temporary file.
270
285
namespace {
271
286
class TemporaryFile {
@@ -379,64 +394,38 @@ static std::string createManifestXml() {
379
394
return readFile (File2.Path );
380
395
}
381
396
382
- static std::unique_ptr<MemoryBuffer>
383
- createMemoryBufferForManifestRes (size_t ManifestSize) {
384
- size_t ResSize = alignTo (object::WIN_RES_MAGIC_SIZE +
385
- object::WIN_RES_NULL_ENTRY_SIZE +
386
- sizeof (object::WinResHeaderPrefix) +
387
- sizeof (object::WinResIDs) +
388
- sizeof (object::WinResHeaderSuffix) +
389
- ManifestSize,
390
- object::WIN_RES_DATA_ALIGNMENT);
391
- return MemoryBuffer::getNewMemBuffer (ResSize);
392
- }
393
-
394
- static void writeResFileHeader (char *&Buf) {
395
- memcpy (Buf, COFF::WinResMagic, sizeof (COFF::WinResMagic));
396
- Buf += sizeof (COFF::WinResMagic);
397
- memset (Buf, 0 , object::WIN_RES_NULL_ENTRY_SIZE);
398
- Buf += object::WIN_RES_NULL_ENTRY_SIZE;
399
- }
400
-
401
- static void writeResEntryHeader (char *&Buf, size_t ManifestSize) {
402
- // Write the prefix.
403
- auto *Prefix = reinterpret_cast <object::WinResHeaderPrefix *>(Buf);
404
- Prefix->DataSize = ManifestSize;
405
- Prefix->HeaderSize = sizeof (object::WinResHeaderPrefix) +
406
- sizeof (object::WinResIDs) +
407
- sizeof (object::WinResHeaderSuffix);
408
- Buf += sizeof (object::WinResHeaderPrefix);
409
-
410
- // Write the Type/Name IDs.
411
- auto *IDs = reinterpret_cast <object::WinResIDs *>(Buf);
412
- IDs->setType (RT_MANIFEST);
413
- IDs->setName (Config->ManifestID );
414
- Buf += sizeof (object::WinResIDs);
415
-
416
- // Write the suffix.
417
- auto *Suffix = reinterpret_cast <object::WinResHeaderSuffix *>(Buf);
418
- Suffix->DataVersion = 0 ;
419
- Suffix->MemoryFlags = object::WIN_RES_PURE_MOVEABLE;
420
- Suffix->Language = SUBLANG_ENGLISH_US;
421
- Suffix->Version = 0 ;
422
- Suffix->Characteristics = 0 ;
423
- Buf += sizeof (object::WinResHeaderSuffix);
424
- }
425
-
426
397
// Create a resource file containing a manifest XML.
427
398
std::unique_ptr<MemoryBuffer> createManifestRes () {
428
- std::string Manifest = createManifestXml ();
429
-
430
- std::unique_ptr<MemoryBuffer> Res =
431
- createMemoryBufferForManifestRes (Manifest.size ());
399
+ // Create a temporary file for the resource script file.
400
+ TemporaryFile RCFile (" manifest" , " rc" );
432
401
433
- char *Buf = const_cast <char *>(Res->getBufferStart ());
434
- writeResFileHeader (Buf);
435
- writeResEntryHeader (Buf, Manifest.size ());
436
-
437
- // Copy the manifest data into the .res file.
438
- std::copy (Manifest.begin (), Manifest.end (), Buf);
439
- return Res;
402
+ // Open the temporary file for writing.
403
+ std::error_code EC;
404
+ raw_fd_ostream Out (RCFile.Path , EC, sys::fs::F_Text);
405
+ if (EC)
406
+ fatal (EC, " failed to open " + RCFile.Path );
407
+
408
+ // Write resource script to the RC file.
409
+ Out << " #define LANG_ENGLISH 9\n "
410
+ << " #define SUBLANG_DEFAULT 1\n "
411
+ << " #define APP_MANIFEST " << Config->ManifestID << " \n "
412
+ << " #define RT_MANIFEST 24\n "
413
+ << " LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT\n "
414
+ << " APP_MANIFEST RT_MANIFEST {\n " ;
415
+ quoteAndPrint (Out, createManifestXml ());
416
+ Out << " }\n " ;
417
+ Out.close ();
418
+
419
+ // Create output resource file.
420
+ TemporaryFile ResFile (" output-resource" , " res" );
421
+
422
+ Executor E (" rc.exe" );
423
+ E.add (" /fo" );
424
+ E.add (ResFile.Path );
425
+ E.add (" /nologo" );
426
+ E.add (RCFile.Path );
427
+ E.run ();
428
+ return ResFile.getMemoryBuffer ();
440
429
}
441
430
442
431
void createSideBySideManifest () {
0 commit comments