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