diff options
author | Mehdi Amini <mehdi.amini@apple.com> | 2016-07-11 23:10:18 +0000 |
---|---|---|
committer | Mehdi Amini <mehdi.amini@apple.com> | 2016-07-11 23:10:18 +0000 |
commit | e75aa6f674ce90570fba9e5a3600535cba12a016 (patch) | |
tree | 8f2b3cbf8ccbda75c65ceaa416d8c99ca2061acc /llvm/lib/Bitcode/Reader/BitcodeReader.cpp | |
parent | c9c5405b52dd8063c4a2253f1824bcaf519a39ca (diff) | |
download | bcm5719-llvm-e75aa6f674ce90570fba9e5a3600535cba12a016.tar.gz bcm5719-llvm-e75aa6f674ce90570fba9e5a3600535cba12a016.zip |
Add a libLTO API to query a memory buffer and check if it contains ObjC categories
The linker supports a feature to force load an object from a static
archive if it defines an Objective-C category.
This API supports this feature by looking at every section in the
module to find if a category is defined in the module.
llvm-svn: 275125
Diffstat (limited to 'llvm/lib/Bitcode/Reader/BitcodeReader.cpp')
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 9aaf3500cad..73a30c61eca 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -313,6 +313,10 @@ public: /// Cheap mechanism to just extract the identification block out of bitcode. ErrorOr<std::string> parseIdentificationBlock(); + /// Peak at the module content and return true if any ObjC category or class + /// is found. + ErrorOr<bool> hasObjCCategory(); + static uint64_t decodeSignRotatedValue(uint64_t V); /// Materialize any deferred Metadata block. @@ -450,6 +454,7 @@ private: ArrayRef<uint64_t> Record); std::error_code parseMetadataAttachment(Function &F); ErrorOr<std::string> parseModuleTriple(); + ErrorOr<bool> hasObjCCategoryInModule(); std::error_code parseUseLists(); std::error_code initStream(std::unique_ptr<DataStreamer> Streamer); std::error_code initStreamFromBuffer(); @@ -4195,6 +4200,81 @@ std::error_code BitcodeReader::parseGlobalObjectAttachment( return std::error_code(); } +ErrorOr<bool> BitcodeReader::hasObjCCategory() { + if (std::error_code EC = initStream(nullptr)) + return EC; + + // Sniff for the signature. + if (!hasValidBitcodeHeader(Stream)) + return error("Invalid bitcode signature"); + + // We expect a number of well-defined blocks, though we don't necessarily + // need to understand them all. + while (1) { + BitstreamEntry Entry = Stream.advance(); + + switch (Entry.Kind) { + case BitstreamEntry::Error: + return error("Malformed block"); + case BitstreamEntry::EndBlock: + return std::error_code(); + + case BitstreamEntry::SubBlock: + if (Entry.ID == bitc::MODULE_BLOCK_ID) + return hasObjCCategoryInModule(); + + // Ignore other sub-blocks. + if (Stream.SkipBlock()) + return error("Malformed block"); + continue; + + case BitstreamEntry::Record: + Stream.skipRecord(Entry.ID); + continue; + } + } +} + +ErrorOr<bool> BitcodeReader::hasObjCCategoryInModule() { + if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID)) + return error("Invalid record"); + + SmallVector<uint64_t, 64> Record; + // Read all the records for this module. + while (1) { + BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + + switch (Entry.Kind) { + case BitstreamEntry::SubBlock: // Handled for us already. + case BitstreamEntry::Error: + return error("Malformed block"); + case BitstreamEntry::EndBlock: + return false; + case BitstreamEntry::Record: + // The interesting case. + break; + } + + // Read a record. + switch (Stream.readRecord(Entry.ID, Record)) { + default: + break; // Default behavior, ignore unknown content. + case bitc::MODULE_CODE_SECTIONNAME: { // SECTIONNAME: [strchr x N] + std::string S; + if (convertToString(Record, 0, S)) + return error("Invalid record"); + // Check for the i386 and other (x86_64, ARM) conventions + if (S.find("__DATA, __objc_catlist") != std::string::npos || + S.find("__OBJC,__category") != std::string::npos) + return true; + break; + } + } + Record.clear(); + } + llvm_unreachable("Exit infinite loop"); +} + /// Parse metadata attachments. std::error_code BitcodeReader::parseMetadataAttachment(Function &F) { if (Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID)) @@ -6548,6 +6628,16 @@ std::string llvm::getBitcodeTargetTriple(MemoryBufferRef Buffer, return Triple.get(); } +bool llvm::isBitcodeContainingObjCCategory(MemoryBufferRef Buffer, + LLVMContext &Context) { + std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false); + auto R = llvm::make_unique<BitcodeReader>(Buf.release(), Context); + ErrorOr<bool> hasObjCCategory = R->hasObjCCategory(); + if (hasObjCCategory.getError()) + return false; + return hasObjCCategory.get(); +} + std::string llvm::getBitcodeProducerString(MemoryBufferRef Buffer, LLVMContext &Context) { std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false); |