|
23 | 23 | #include "llvm/ADT/StringSet.h"
|
24 | 24 | #include "llvm/ADT/StringSwitch.h"
|
25 | 25 | #include "llvm/ADT/Triple.h"
|
| 26 | +#include "llvm/IR/LLVMContext.h" |
26 | 27 | #include "llvm/Object/Archive.h"
|
27 | 28 | #include "llvm/Object/ArchiveWriter.h"
|
28 | 29 | #include "llvm/Object/Binary.h"
|
@@ -121,6 +122,9 @@ static cl::opt<unsigned>
|
121 | 122 | /// Prefix of an added section name with bundle size.
|
122 | 123 | #define SIZE_SECTION_PREFIX "__CLANG_OFFLOAD_BUNDLE_SIZE__"
|
123 | 124 |
|
| 125 | +/// Section name which holds target symbol names. |
| 126 | +#define SYMBOLS_SECTION_NAME ".tgtsym" |
| 127 | + |
124 | 128 | /// The index of the host input in the list of inputs.
|
125 | 129 | static unsigned HostInputIndex = ~0u;
|
126 | 130 |
|
@@ -546,6 +550,62 @@ class ObjectFileHandler final : public FileHandler {
|
546 | 550 | /// Input sizes.
|
547 | 551 | SmallVector<uint64_t, 16u> InputSizes;
|
548 | 552 |
|
| 553 | + // Return a buffer with symbol names that are defined in target objects. |
| 554 | + // Each symbol name is prefixed by a target name <kind>-<triple> to uniquely |
| 555 | + // identify the target it belongs to, and symbol names are separated from each |
| 556 | + // other by '\0' characters. |
| 557 | + Expected<SmallVector<char, 0>> makeTargetSymbolTable() { |
| 558 | + SmallVector<char, 0> SymbolsBuf; |
| 559 | + raw_svector_ostream SymbolsOS(SymbolsBuf); |
| 560 | + |
| 561 | + for (unsigned I = 0; I < NumberOfInputs; ++I) { |
| 562 | + if (I == HostInputIndex) |
| 563 | + continue; |
| 564 | + |
| 565 | + // Get the list of symbols defined in the target object. Open file and |
| 566 | + // check if it is a symbolic file. |
| 567 | + ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = |
| 568 | + MemoryBuffer::getFileOrSTDIN(InputFileNames[I]); |
| 569 | + if (!BufOrErr) |
| 570 | + return createFileError(InputFileNames[I], BufOrErr.getError()); |
| 571 | + |
| 572 | + LLVMContext Context; |
| 573 | + Expected<std::unique_ptr<Binary>> BinOrErr = |
| 574 | + createBinary(BufOrErr.get()->getMemBufferRef(), &Context); |
| 575 | + |
| 576 | + // If it is not a symbolic file just ignore it since we cannot do anything |
| 577 | + // with it. |
| 578 | + if (!BinOrErr) { |
| 579 | + if (auto Err = isNotObjectErrorInvalidFileType(BinOrErr.takeError())) |
| 580 | + return std::move(Err); |
| 581 | + continue; |
| 582 | + } |
| 583 | + auto *SF = dyn_cast<SymbolicFile>(&**BinOrErr); |
| 584 | + if (!SF) |
| 585 | + continue; |
| 586 | + |
| 587 | + for (BasicSymbolRef Symbol : SF->symbols()) { |
| 588 | + Expected<uint32_t> FlagsOrErr = Symbol.getFlags(); |
| 589 | + if (!FlagsOrErr) |
| 590 | + return FlagsOrErr.takeError(); |
| 591 | + |
| 592 | + // We are interested in externally visible and defined symbols only, so |
| 593 | + // ignore it if this is not such a symbol. |
| 594 | + bool Undefined = *FlagsOrErr & SymbolRef::SF_Undefined; |
| 595 | + bool Global = *FlagsOrErr & SymbolRef::SF_Global; |
| 596 | + if (Undefined || !Global) |
| 597 | + continue; |
| 598 | + |
| 599 | + // Add symbol name with the target prefix to the buffer. |
| 600 | + SymbolsOS << TargetNames[I] << "."; |
| 601 | + if (Error Err = Symbol.printName(SymbolsOS)) |
| 602 | + return std::move(Err); |
| 603 | + SymbolsOS << '\0'; |
| 604 | + } |
| 605 | + } |
| 606 | + return SymbolsBuf; |
| 607 | + } |
| 608 | + |
549 | 609 | public:
|
550 | 610 | ObjectFileHandler(std::unique_ptr<ObjectFile> ObjIn)
|
551 | 611 | : FileHandler(), Obj(std::move(ObjIn)),
|
@@ -793,6 +853,25 @@ class ObjectFileHandler final : public FileHandler {
|
793 | 853 | SIZE_SECTION_PREFIX + TargetNames[I] + "=" +
|
794 | 854 | *SizeFileOrErr));
|
795 | 855 | }
|
| 856 | + |
| 857 | + // Add a section with symbol names that are defined in target objects to the |
| 858 | + // output fat object. |
| 859 | + Expected<SmallVector<char, 0>> SymbolsOrErr = makeTargetSymbolTable(); |
| 860 | + if (!SymbolsOrErr) |
| 861 | + return SymbolsOrErr.takeError(); |
| 862 | + |
| 863 | + if (!SymbolsOrErr->empty()) { |
| 864 | + // Add section with symbols names to fat object. |
| 865 | + Expected<StringRef> SymbolsFileOrErr = |
| 866 | + TempFiles.Create(makeArrayRef(*SymbolsOrErr)); |
| 867 | + if (!SymbolsFileOrErr) |
| 868 | + return SymbolsFileOrErr.takeError(); |
| 869 | + |
| 870 | + ObjcopyArgs.push_back(SS.save(Twine("--add-section=") + |
| 871 | + SYMBOLS_SECTION_NAME + "=" + |
| 872 | + *SymbolsFileOrErr)); |
| 873 | + } |
| 874 | + |
796 | 875 | ObjcopyArgs.push_back(InputFileNames[HostInputIndex]);
|
797 | 876 | ObjcopyArgs.push_back(IntermediateObj);
|
798 | 877 |
|
|
0 commit comments