brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.3 KiB · 7b21f30 Raw
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