193 lines · cpp
1//===- tools/dsymutil/SwiftModule.cpp -------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/Bitcode/BitcodeReader.h"10#include "llvm/Bitcode/LLVMBitCodes.h"11#include "llvm/Bitstream/BitCodes.h"12#include "llvm/Bitstream/BitstreamReader.h"13 14namespace {15// Copied from swift/lib/Serialization/ModuleFormat.h16constexpr unsigned char SWIFTMODULE_SIGNATURE[] = {0xE2, 0x9C, 0xA8, 0x0E};17constexpr uint16_t expectedMajorVersion = 0;18constexpr unsigned MODULE_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID;19constexpr unsigned CONTROL_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID + 1;20constexpr unsigned METADATA = 1;21constexpr unsigned OPTIONS_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID + 8;22constexpr unsigned IS_BUILT_FROM_INTERFACE = 11;23 24llvm::Error checkModuleSignature(llvm::BitstreamCursor &cursor,25 llvm::ArrayRef<unsigned char> signature) {26 for (unsigned char byte : signature) {27 if (cursor.AtEndOfStream())28 return llvm::createStringError("malformed bitstream");29 llvm::Expected<llvm::SimpleBitstreamCursor::word_t> maybeRead =30 cursor.Read(8);31 if (!maybeRead)32 return maybeRead.takeError();33 if (maybeRead.get() != byte)34 return llvm::createStringError("malformed bitstream");35 }36 return llvm::Error::success();37}38 39llvm::Error enterTopLevelModuleBlock(llvm::BitstreamCursor &cursor,40 unsigned ID) {41 llvm::Expected<llvm::BitstreamEntry> maybeNext = cursor.advance();42 if (!maybeNext)43 return maybeNext.takeError();44 llvm::BitstreamEntry next = maybeNext.get();45 46 if (next.Kind != llvm::BitstreamEntry::SubBlock)47 return llvm::createStringError("malformed bitstream");48 49 if (next.ID == llvm::bitc::BLOCKINFO_BLOCK_ID) {50 if (cursor.SkipBlock())51 return llvm::createStringError("malformed bitstream");52 return enterTopLevelModuleBlock(cursor, ID);53 }54 55 if (next.ID != ID)56 return llvm::createStringError("malformed bitstream");57 58 if (llvm::Error Err = cursor.EnterSubBlock(ID))59 return Err;60 61 return llvm::Error::success();62}63 64llvm::Expected<bool>65readOptionsBlock(llvm::BitstreamCursor &cursor,66 llvm::SmallVectorImpl<uint64_t> &scratch) {67 bool is_built_from_interface = false;68 while (!cursor.AtEndOfStream()) {69 llvm::Expected<llvm::BitstreamEntry> maybeEntry = cursor.advance();70 if (!maybeEntry)71 return maybeEntry.takeError();72 73 llvm::BitstreamEntry entry = maybeEntry.get();74 if (entry.Kind == llvm::BitstreamEntry::EndBlock)75 break;76 77 if (entry.Kind == llvm::BitstreamEntry::Error)78 return llvm::createStringError("malformed bitstream");79 80 if (entry.Kind == llvm::BitstreamEntry::SubBlock) {81 if (cursor.SkipBlock())82 return llvm::createStringError("malformed bitstream");83 continue;84 }85 86 scratch.clear();87 llvm::StringRef blobData;88 llvm::Expected<unsigned> maybeKind =89 cursor.readRecord(entry.ID, scratch, &blobData);90 if (!maybeKind)91 return maybeKind.takeError();92 unsigned kind = maybeKind.get();93 switch (kind) {94 case IS_BUILT_FROM_INTERFACE:95 is_built_from_interface = true;96 continue;97 default:98 continue;99 }100 }101 return is_built_from_interface;102}103 104llvm::Expected<bool>105parseControlBlock(llvm::BitstreamCursor &cursor,106 llvm::SmallVectorImpl<uint64_t> &scratch) {107 // The control block is malformed until we've at least read a major version108 // number.109 bool versionSeen = false;110 111 while (!cursor.AtEndOfStream()) {112 llvm::Expected<llvm::BitstreamEntry> maybeEntry = cursor.advance();113 if (!maybeEntry)114 return maybeEntry.takeError();115 116 llvm::BitstreamEntry entry = maybeEntry.get();117 if (entry.Kind == llvm::BitstreamEntry::EndBlock)118 break;119 120 if (entry.Kind == llvm::BitstreamEntry::Error)121 return llvm::createStringError("malformed bitstream");122 123 if (entry.Kind == llvm::BitstreamEntry::SubBlock) {124 if (entry.ID == OPTIONS_BLOCK_ID) {125 if (llvm::Error Err = cursor.EnterSubBlock(OPTIONS_BLOCK_ID))126 return Err;127 128 return readOptionsBlock(cursor, scratch);129 } else {130 // Unknown metadata sub-block, possibly for use by a future version of131 // the module format.132 if (cursor.SkipBlock())133 return llvm::createStringError("malformed bitstream");134 }135 continue;136 }137 138 scratch.clear();139 llvm::StringRef blobData;140 llvm::Expected<unsigned> maybeKind =141 cursor.readRecord(entry.ID, scratch, &blobData);142 if (!maybeKind)143 return maybeKind.takeError();144 145 unsigned kind = maybeKind.get();146 if (kind == METADATA) {147 if (versionSeen)148 return llvm::createStringError("multiple metadata blocks");149 150 uint16_t versionMajor = scratch[0];151 if (versionMajor != expectedMajorVersion)152 return llvm::createStringError("unsupported module version");153 154 versionSeen = true;155 }156 }157 return llvm::createStringError("could not find control block");158}159 160} // namespace161 162llvm::Expected<bool> IsBuiltFromSwiftInterface(llvm::StringRef data) {163 llvm::BitstreamCursor cursor(data);164 if (llvm::Error Err = checkModuleSignature(cursor, SWIFTMODULE_SIGNATURE))165 return llvm::joinErrors(166 llvm::createStringError("could not check signature"), std::move(Err));167 if (llvm::Error Err = enterTopLevelModuleBlock(cursor, MODULE_BLOCK_ID))168 return llvm::joinErrors(169 llvm::createStringError("could not enter top level block"),170 std::move(Err));171 172 llvm::BitstreamEntry topLevelEntry;173 llvm::SmallVector<uint64_t, 32> scratch;174 175 while (!cursor.AtEndOfStream()) {176 llvm::Expected<llvm::BitstreamEntry> maybeEntry =177 cursor.advance(llvm::BitstreamCursor::AF_DontPopBlockAtEnd);178 if (!maybeEntry)179 return maybeEntry.takeError();180 181 topLevelEntry = maybeEntry.get();182 if (topLevelEntry.Kind != llvm::BitstreamEntry::SubBlock)183 break;184 185 if (topLevelEntry.ID == CONTROL_BLOCK_ID) {186 if (llvm::Error Err = cursor.EnterSubBlock(CONTROL_BLOCK_ID))187 return Err;188 return parseControlBlock(cursor, scratch);189 }190 }191 return llvm::createStringError("no control block found");192}193