30
30
#include " llvm/Support/Error.h"
31
31
#include " llvm/Support/ErrorOr.h"
32
32
#include " llvm/Support/FileSystem.h"
33
+ #include " llvm/Support/FileUtilities.h"
33
34
#include " llvm/Support/MemoryBuffer.h"
34
35
#include " llvm/Support/Path.h"
35
36
#include " llvm/Support/Program.h"
@@ -463,6 +464,15 @@ class ObjectFileHandler final : public FileHandler {
463
464
if (NumberOfProcessedInputs != NumberOfInputs)
464
465
return Error::success ();
465
466
467
+ // We will use llvm-objcopy to add target objects sections to the output
468
+ // fat object. These sections should have 'exclude' flag set which tells
469
+ // link editor to remove them from linker inputs when linking executable or
470
+ // shared library. llvm-objcopy currently does not support adding new
471
+ // section and changing flags for the added section in one invocation, and
472
+ // because of that we have to run it two times. First run adds sections and
473
+ // the second changes flags.
474
+ // TODO: change it to one run once llvm-objcopy starts supporting that.
475
+
466
476
// Find llvm-objcopy in order to create the bundle binary.
467
477
ErrorOr<std::string> Objcopy = sys::findProgramByName (
468
478
" llvm-objcopy" , sys::path::parent_path (BundlerExecutable));
@@ -476,7 +486,15 @@ class ObjectFileHandler final : public FileHandler {
476
486
// to pass down to llvm-objcopy.
477
487
OS.close ();
478
488
479
- // Compose command line for the objcopy tool.
489
+ // Create an intermediate temporary file to save object after the first
490
+ // llvm-objcopy run.
491
+ SmallString<128u > IntermediateObj;
492
+ if (std::error_code EC = sys::fs::createTemporaryFile (
493
+ " clang-offload-bundler" , " tmp" , IntermediateObj))
494
+ return createFileError (IntermediateObj, EC);
495
+ FileRemover IntermediateObjRemover (IntermediateObj);
496
+
497
+ // Compose llvm-objcopy command line for add target objects' sections.
480
498
BumpPtrAllocator Alloc;
481
499
StringSaver SS{Alloc};
482
500
SmallVector<StringRef, 8u > ObjcopyArgs{" llvm-objcopy" };
@@ -485,25 +503,44 @@ class ObjectFileHandler final : public FileHandler {
485
503
OFFLOAD_BUNDLER_MAGIC_STR + TargetNames[I] +
486
504
" =" + InputFileNames[I]));
487
505
ObjcopyArgs.push_back (InputFileNames[HostInputIndex]);
506
+ ObjcopyArgs.push_back (IntermediateObj);
507
+
508
+ if (Error Err = executeObjcopy (*Objcopy, ObjcopyArgs))
509
+ return Err;
510
+
511
+ // And run llvm-objcopy for the second time to update section flags.
512
+ ObjcopyArgs.resize (1 );
513
+ for (unsigned I = 0 ; I < NumberOfInputs; ++I)
514
+ ObjcopyArgs.push_back (SS.save (Twine (" --set-section-flags=" ) +
515
+ OFFLOAD_BUNDLER_MAGIC_STR + TargetNames[I] +
516
+ " =readonly,exclude" ));
517
+ ObjcopyArgs.push_back (IntermediateObj);
488
518
ObjcopyArgs.push_back (OutputFileNames.front ());
489
519
490
- // If the user asked for the commands to be printed out, we do that instead
491
- // of executing it.
520
+ if (Error Err = executeObjcopy (*Objcopy, ObjcopyArgs))
521
+ return Err;
522
+
523
+ return Error::success ();
524
+ }
525
+
526
+ Error WriteBundle (raw_fd_ostream &OS, MemoryBuffer &Input) final {
527
+ return Error::success ();
528
+ }
529
+
530
+ private:
531
+ static Error executeObjcopy (StringRef Objcopy, ArrayRef<StringRef> Args) {
532
+ // If the user asked for the commands to be printed out, we do that
533
+ // instead of executing it.
492
534
if (PrintExternalCommands) {
493
- errs () << " \" " << * Objcopy << " \" " ;
494
- for (StringRef Arg : drop_begin (ObjcopyArgs , 1 ))
535
+ errs () << " \" " << Objcopy << " \" " ;
536
+ for (StringRef Arg : drop_begin (Args , 1 ))
495
537
errs () << " \" " << Arg << " \" " ;
496
538
errs () << " \n " ;
497
539
} else {
498
- if (sys::ExecuteAndWait (* Objcopy, ObjcopyArgs ))
540
+ if (sys::ExecuteAndWait (Objcopy, Args ))
499
541
return createStringError (inconvertibleErrorCode (),
500
542
" 'llvm-objcopy' tool failed" );
501
543
}
502
-
503
- return Error::success ();
504
- }
505
-
506
- Error WriteBundle (raw_fd_ostream &OS, MemoryBuffer &Input) final {
507
544
return Error::success ();
508
545
}
509
546
};
0 commit comments