Path: blob/main/contrib/llvm-project/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp
35291 views
//===- BitcodeAnalyzer.cpp - Internal BitcodeAnalyzer implementation ------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/Bitcode/BitcodeAnalyzer.h"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#include "llvm/Support/Format.h"14#include "llvm/Support/SHA1.h"15#include <optional>1617using namespace llvm;1819static Error reportError(StringRef Message) {20return createStringError(std::errc::illegal_byte_sequence, Message.data());21}2223/// Return a symbolic block name if known, otherwise return null.24static std::optional<const char *>25GetBlockName(unsigned BlockID, const BitstreamBlockInfo &BlockInfo,26CurStreamTypeType CurStreamType) {27// Standard blocks for all bitcode files.28if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) {29if (BlockID == bitc::BLOCKINFO_BLOCK_ID)30return "BLOCKINFO_BLOCK";31return std::nullopt;32}3334// Check to see if we have a blockinfo record for this block, with a name.35if (const BitstreamBlockInfo::BlockInfo *Info =36BlockInfo.getBlockInfo(BlockID)) {37if (!Info->Name.empty())38return Info->Name.c_str();39}4041if (CurStreamType != LLVMIRBitstream)42return std::nullopt;4344switch (BlockID) {45default:46return std::nullopt;47case bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID:48return "OPERAND_BUNDLE_TAGS_BLOCK";49case bitc::MODULE_BLOCK_ID:50return "MODULE_BLOCK";51case bitc::PARAMATTR_BLOCK_ID:52return "PARAMATTR_BLOCK";53case bitc::PARAMATTR_GROUP_BLOCK_ID:54return "PARAMATTR_GROUP_BLOCK_ID";55case bitc::TYPE_BLOCK_ID_NEW:56return "TYPE_BLOCK_ID";57case bitc::CONSTANTS_BLOCK_ID:58return "CONSTANTS_BLOCK";59case bitc::FUNCTION_BLOCK_ID:60return "FUNCTION_BLOCK";61case bitc::IDENTIFICATION_BLOCK_ID:62return "IDENTIFICATION_BLOCK_ID";63case bitc::VALUE_SYMTAB_BLOCK_ID:64return "VALUE_SYMTAB";65case bitc::METADATA_BLOCK_ID:66return "METADATA_BLOCK";67case bitc::METADATA_KIND_BLOCK_ID:68return "METADATA_KIND_BLOCK";69case bitc::METADATA_ATTACHMENT_ID:70return "METADATA_ATTACHMENT_BLOCK";71case bitc::USELIST_BLOCK_ID:72return "USELIST_BLOCK_ID";73case bitc::GLOBALVAL_SUMMARY_BLOCK_ID:74return "GLOBALVAL_SUMMARY_BLOCK";75case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID:76return "FULL_LTO_GLOBALVAL_SUMMARY_BLOCK";77case bitc::MODULE_STRTAB_BLOCK_ID:78return "MODULE_STRTAB_BLOCK";79case bitc::STRTAB_BLOCK_ID:80return "STRTAB_BLOCK";81case bitc::SYMTAB_BLOCK_ID:82return "SYMTAB_BLOCK";83}84}8586/// Return a symbolic code name if known, otherwise return null.87static std::optional<const char *>88GetCodeName(unsigned CodeID, unsigned BlockID,89const BitstreamBlockInfo &BlockInfo,90CurStreamTypeType CurStreamType) {91// Standard blocks for all bitcode files.92if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) {93if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {94switch (CodeID) {95default:96return std::nullopt;97case bitc::BLOCKINFO_CODE_SETBID:98return "SETBID";99case bitc::BLOCKINFO_CODE_BLOCKNAME:100return "BLOCKNAME";101case bitc::BLOCKINFO_CODE_SETRECORDNAME:102return "SETRECORDNAME";103}104}105return std::nullopt;106}107108// Check to see if we have a blockinfo record for this record, with a name.109if (const BitstreamBlockInfo::BlockInfo *Info =110BlockInfo.getBlockInfo(BlockID)) {111for (const std::pair<unsigned, std::string> &RN : Info->RecordNames)112if (RN.first == CodeID)113return RN.second.c_str();114}115116if (CurStreamType != LLVMIRBitstream)117return std::nullopt;118119#define STRINGIFY_CODE(PREFIX, CODE) \120case bitc::PREFIX##_##CODE: \121return #CODE;122switch (BlockID) {123default:124return std::nullopt;125case bitc::MODULE_BLOCK_ID:126switch (CodeID) {127default:128return std::nullopt;129STRINGIFY_CODE(MODULE_CODE, VERSION)130STRINGIFY_CODE(MODULE_CODE, TRIPLE)131STRINGIFY_CODE(MODULE_CODE, DATALAYOUT)132STRINGIFY_CODE(MODULE_CODE, ASM)133STRINGIFY_CODE(MODULE_CODE, SECTIONNAME)134STRINGIFY_CODE(MODULE_CODE, DEPLIB) // Deprecated, present in old bitcode135STRINGIFY_CODE(MODULE_CODE, GLOBALVAR)136STRINGIFY_CODE(MODULE_CODE, FUNCTION)137STRINGIFY_CODE(MODULE_CODE, ALIAS)138STRINGIFY_CODE(MODULE_CODE, GCNAME)139STRINGIFY_CODE(MODULE_CODE, COMDAT)140STRINGIFY_CODE(MODULE_CODE, VSTOFFSET)141STRINGIFY_CODE(MODULE_CODE, METADATA_VALUES_UNUSED)142STRINGIFY_CODE(MODULE_CODE, SOURCE_FILENAME)143STRINGIFY_CODE(MODULE_CODE, HASH)144}145case bitc::IDENTIFICATION_BLOCK_ID:146switch (CodeID) {147default:148return std::nullopt;149STRINGIFY_CODE(IDENTIFICATION_CODE, STRING)150STRINGIFY_CODE(IDENTIFICATION_CODE, EPOCH)151}152case bitc::PARAMATTR_BLOCK_ID:153switch (CodeID) {154default:155return std::nullopt;156// FIXME: Should these be different?157case bitc::PARAMATTR_CODE_ENTRY_OLD:158return "ENTRY";159case bitc::PARAMATTR_CODE_ENTRY:160return "ENTRY";161}162case bitc::PARAMATTR_GROUP_BLOCK_ID:163switch (CodeID) {164default:165return std::nullopt;166case bitc::PARAMATTR_GRP_CODE_ENTRY:167return "ENTRY";168}169case bitc::TYPE_BLOCK_ID_NEW:170switch (CodeID) {171default:172return std::nullopt;173STRINGIFY_CODE(TYPE_CODE, NUMENTRY)174STRINGIFY_CODE(TYPE_CODE, VOID)175STRINGIFY_CODE(TYPE_CODE, FLOAT)176STRINGIFY_CODE(TYPE_CODE, DOUBLE)177STRINGIFY_CODE(TYPE_CODE, LABEL)178STRINGIFY_CODE(TYPE_CODE, OPAQUE)179STRINGIFY_CODE(TYPE_CODE, INTEGER)180STRINGIFY_CODE(TYPE_CODE, POINTER)181STRINGIFY_CODE(TYPE_CODE, HALF)182STRINGIFY_CODE(TYPE_CODE, ARRAY)183STRINGIFY_CODE(TYPE_CODE, VECTOR)184STRINGIFY_CODE(TYPE_CODE, X86_FP80)185STRINGIFY_CODE(TYPE_CODE, FP128)186STRINGIFY_CODE(TYPE_CODE, PPC_FP128)187STRINGIFY_CODE(TYPE_CODE, METADATA)188STRINGIFY_CODE(TYPE_CODE, X86_MMX)189STRINGIFY_CODE(TYPE_CODE, STRUCT_ANON)190STRINGIFY_CODE(TYPE_CODE, STRUCT_NAME)191STRINGIFY_CODE(TYPE_CODE, STRUCT_NAMED)192STRINGIFY_CODE(TYPE_CODE, FUNCTION)193STRINGIFY_CODE(TYPE_CODE, TOKEN)194STRINGIFY_CODE(TYPE_CODE, BFLOAT)195}196197case bitc::CONSTANTS_BLOCK_ID:198switch (CodeID) {199default:200return std::nullopt;201STRINGIFY_CODE(CST_CODE, SETTYPE)202STRINGIFY_CODE(CST_CODE, NULL)203STRINGIFY_CODE(CST_CODE, UNDEF)204STRINGIFY_CODE(CST_CODE, INTEGER)205STRINGIFY_CODE(CST_CODE, WIDE_INTEGER)206STRINGIFY_CODE(CST_CODE, FLOAT)207STRINGIFY_CODE(CST_CODE, AGGREGATE)208STRINGIFY_CODE(CST_CODE, STRING)209STRINGIFY_CODE(CST_CODE, CSTRING)210STRINGIFY_CODE(CST_CODE, CE_BINOP)211STRINGIFY_CODE(CST_CODE, CE_CAST)212STRINGIFY_CODE(CST_CODE, CE_GEP)213STRINGIFY_CODE(CST_CODE, CE_INBOUNDS_GEP)214STRINGIFY_CODE(CST_CODE, CE_SELECT)215STRINGIFY_CODE(CST_CODE, CE_EXTRACTELT)216STRINGIFY_CODE(CST_CODE, CE_INSERTELT)217STRINGIFY_CODE(CST_CODE, CE_SHUFFLEVEC)218STRINGIFY_CODE(CST_CODE, CE_CMP)219STRINGIFY_CODE(CST_CODE, INLINEASM)220STRINGIFY_CODE(CST_CODE, CE_SHUFVEC_EX)221STRINGIFY_CODE(CST_CODE, CE_UNOP)222STRINGIFY_CODE(CST_CODE, DSO_LOCAL_EQUIVALENT)223STRINGIFY_CODE(CST_CODE, NO_CFI_VALUE)224STRINGIFY_CODE(CST_CODE, PTRAUTH)225case bitc::CST_CODE_BLOCKADDRESS:226return "CST_CODE_BLOCKADDRESS";227STRINGIFY_CODE(CST_CODE, DATA)228}229case bitc::FUNCTION_BLOCK_ID:230switch (CodeID) {231default:232return std::nullopt;233STRINGIFY_CODE(FUNC_CODE, DECLAREBLOCKS)234STRINGIFY_CODE(FUNC_CODE, INST_BINOP)235STRINGIFY_CODE(FUNC_CODE, INST_CAST)236STRINGIFY_CODE(FUNC_CODE, INST_GEP_OLD)237STRINGIFY_CODE(FUNC_CODE, INST_INBOUNDS_GEP_OLD)238STRINGIFY_CODE(FUNC_CODE, INST_SELECT)239STRINGIFY_CODE(FUNC_CODE, INST_EXTRACTELT)240STRINGIFY_CODE(FUNC_CODE, INST_INSERTELT)241STRINGIFY_CODE(FUNC_CODE, INST_SHUFFLEVEC)242STRINGIFY_CODE(FUNC_CODE, INST_CMP)243STRINGIFY_CODE(FUNC_CODE, INST_RET)244STRINGIFY_CODE(FUNC_CODE, INST_BR)245STRINGIFY_CODE(FUNC_CODE, INST_SWITCH)246STRINGIFY_CODE(FUNC_CODE, INST_INVOKE)247STRINGIFY_CODE(FUNC_CODE, INST_UNOP)248STRINGIFY_CODE(FUNC_CODE, INST_UNREACHABLE)249STRINGIFY_CODE(FUNC_CODE, INST_CLEANUPRET)250STRINGIFY_CODE(FUNC_CODE, INST_CATCHRET)251STRINGIFY_CODE(FUNC_CODE, INST_CATCHPAD)252STRINGIFY_CODE(FUNC_CODE, INST_PHI)253STRINGIFY_CODE(FUNC_CODE, INST_ALLOCA)254STRINGIFY_CODE(FUNC_CODE, INST_LOAD)255STRINGIFY_CODE(FUNC_CODE, INST_VAARG)256STRINGIFY_CODE(FUNC_CODE, INST_STORE)257STRINGIFY_CODE(FUNC_CODE, INST_EXTRACTVAL)258STRINGIFY_CODE(FUNC_CODE, INST_INSERTVAL)259STRINGIFY_CODE(FUNC_CODE, INST_CMP2)260STRINGIFY_CODE(FUNC_CODE, INST_VSELECT)261STRINGIFY_CODE(FUNC_CODE, DEBUG_LOC_AGAIN)262STRINGIFY_CODE(FUNC_CODE, INST_CALL)263STRINGIFY_CODE(FUNC_CODE, DEBUG_LOC)264STRINGIFY_CODE(FUNC_CODE, INST_GEP)265STRINGIFY_CODE(FUNC_CODE, OPERAND_BUNDLE)266STRINGIFY_CODE(FUNC_CODE, INST_FENCE)267STRINGIFY_CODE(FUNC_CODE, INST_ATOMICRMW)268STRINGIFY_CODE(FUNC_CODE, INST_LOADATOMIC)269STRINGIFY_CODE(FUNC_CODE, INST_STOREATOMIC)270STRINGIFY_CODE(FUNC_CODE, INST_CMPXCHG)271STRINGIFY_CODE(FUNC_CODE, INST_CALLBR)272STRINGIFY_CODE(FUNC_CODE, BLOCKADDR_USERS)273STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_DECLARE)274STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_VALUE)275STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_ASSIGN)276STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_VALUE_SIMPLE)277STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_LABEL)278}279case bitc::VALUE_SYMTAB_BLOCK_ID:280switch (CodeID) {281default:282return std::nullopt;283STRINGIFY_CODE(VST_CODE, ENTRY)284STRINGIFY_CODE(VST_CODE, BBENTRY)285STRINGIFY_CODE(VST_CODE, FNENTRY)286STRINGIFY_CODE(VST_CODE, COMBINED_ENTRY)287}288case bitc::MODULE_STRTAB_BLOCK_ID:289switch (CodeID) {290default:291return std::nullopt;292STRINGIFY_CODE(MST_CODE, ENTRY)293STRINGIFY_CODE(MST_CODE, HASH)294}295case bitc::GLOBALVAL_SUMMARY_BLOCK_ID:296case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID:297switch (CodeID) {298default:299return std::nullopt;300STRINGIFY_CODE(FS, PERMODULE)301STRINGIFY_CODE(FS, PERMODULE_PROFILE)302STRINGIFY_CODE(FS, PERMODULE_RELBF)303STRINGIFY_CODE(FS, PERMODULE_GLOBALVAR_INIT_REFS)304STRINGIFY_CODE(FS, PERMODULE_VTABLE_GLOBALVAR_INIT_REFS)305STRINGIFY_CODE(FS, COMBINED)306STRINGIFY_CODE(FS, COMBINED_PROFILE)307STRINGIFY_CODE(FS, COMBINED_GLOBALVAR_INIT_REFS)308STRINGIFY_CODE(FS, ALIAS)309STRINGIFY_CODE(FS, COMBINED_ALIAS)310STRINGIFY_CODE(FS, COMBINED_ORIGINAL_NAME)311STRINGIFY_CODE(FS, VERSION)312STRINGIFY_CODE(FS, FLAGS)313STRINGIFY_CODE(FS, TYPE_TESTS)314STRINGIFY_CODE(FS, TYPE_TEST_ASSUME_VCALLS)315STRINGIFY_CODE(FS, TYPE_CHECKED_LOAD_VCALLS)316STRINGIFY_CODE(FS, TYPE_TEST_ASSUME_CONST_VCALL)317STRINGIFY_CODE(FS, TYPE_CHECKED_LOAD_CONST_VCALL)318STRINGIFY_CODE(FS, VALUE_GUID)319STRINGIFY_CODE(FS, CFI_FUNCTION_DEFS)320STRINGIFY_CODE(FS, CFI_FUNCTION_DECLS)321STRINGIFY_CODE(FS, TYPE_ID)322STRINGIFY_CODE(FS, TYPE_ID_METADATA)323STRINGIFY_CODE(FS, BLOCK_COUNT)324STRINGIFY_CODE(FS, PARAM_ACCESS)325STRINGIFY_CODE(FS, PERMODULE_CALLSITE_INFO)326STRINGIFY_CODE(FS, PERMODULE_ALLOC_INFO)327STRINGIFY_CODE(FS, COMBINED_CALLSITE_INFO)328STRINGIFY_CODE(FS, COMBINED_ALLOC_INFO)329STRINGIFY_CODE(FS, STACK_IDS)330}331case bitc::METADATA_ATTACHMENT_ID:332switch (CodeID) {333default:334return std::nullopt;335STRINGIFY_CODE(METADATA, ATTACHMENT)336}337case bitc::METADATA_BLOCK_ID:338switch (CodeID) {339default:340return std::nullopt;341STRINGIFY_CODE(METADATA, STRING_OLD)342STRINGIFY_CODE(METADATA, VALUE)343STRINGIFY_CODE(METADATA, NODE)344STRINGIFY_CODE(METADATA, NAME)345STRINGIFY_CODE(METADATA, DISTINCT_NODE)346STRINGIFY_CODE(METADATA, KIND) // Older bitcode has it in a MODULE_BLOCK347STRINGIFY_CODE(METADATA, LOCATION)348STRINGIFY_CODE(METADATA, OLD_NODE)349STRINGIFY_CODE(METADATA, OLD_FN_NODE)350STRINGIFY_CODE(METADATA, NAMED_NODE)351STRINGIFY_CODE(METADATA, GENERIC_DEBUG)352STRINGIFY_CODE(METADATA, SUBRANGE)353STRINGIFY_CODE(METADATA, ENUMERATOR)354STRINGIFY_CODE(METADATA, BASIC_TYPE)355STRINGIFY_CODE(METADATA, FILE)356STRINGIFY_CODE(METADATA, DERIVED_TYPE)357STRINGIFY_CODE(METADATA, COMPOSITE_TYPE)358STRINGIFY_CODE(METADATA, SUBROUTINE_TYPE)359STRINGIFY_CODE(METADATA, COMPILE_UNIT)360STRINGIFY_CODE(METADATA, SUBPROGRAM)361STRINGIFY_CODE(METADATA, LEXICAL_BLOCK)362STRINGIFY_CODE(METADATA, LEXICAL_BLOCK_FILE)363STRINGIFY_CODE(METADATA, NAMESPACE)364STRINGIFY_CODE(METADATA, TEMPLATE_TYPE)365STRINGIFY_CODE(METADATA, TEMPLATE_VALUE)366STRINGIFY_CODE(METADATA, GLOBAL_VAR)367STRINGIFY_CODE(METADATA, LOCAL_VAR)368STRINGIFY_CODE(METADATA, EXPRESSION)369STRINGIFY_CODE(METADATA, OBJC_PROPERTY)370STRINGIFY_CODE(METADATA, IMPORTED_ENTITY)371STRINGIFY_CODE(METADATA, MODULE)372STRINGIFY_CODE(METADATA, MACRO)373STRINGIFY_CODE(METADATA, MACRO_FILE)374STRINGIFY_CODE(METADATA, STRINGS)375STRINGIFY_CODE(METADATA, GLOBAL_DECL_ATTACHMENT)376STRINGIFY_CODE(METADATA, GLOBAL_VAR_EXPR)377STRINGIFY_CODE(METADATA, INDEX_OFFSET)378STRINGIFY_CODE(METADATA, INDEX)379STRINGIFY_CODE(METADATA, ARG_LIST)380}381case bitc::METADATA_KIND_BLOCK_ID:382switch (CodeID) {383default:384return std::nullopt;385STRINGIFY_CODE(METADATA, KIND)386}387case bitc::USELIST_BLOCK_ID:388switch (CodeID) {389default:390return std::nullopt;391case bitc::USELIST_CODE_DEFAULT:392return "USELIST_CODE_DEFAULT";393case bitc::USELIST_CODE_BB:394return "USELIST_CODE_BB";395}396397case bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID:398switch (CodeID) {399default:400return std::nullopt;401case bitc::OPERAND_BUNDLE_TAG:402return "OPERAND_BUNDLE_TAG";403}404case bitc::STRTAB_BLOCK_ID:405switch (CodeID) {406default:407return std::nullopt;408case bitc::STRTAB_BLOB:409return "BLOB";410}411case bitc::SYMTAB_BLOCK_ID:412switch (CodeID) {413default:414return std::nullopt;415case bitc::SYMTAB_BLOB:416return "BLOB";417}418}419#undef STRINGIFY_CODE420}421422static void printSize(raw_ostream &OS, double Bits) {423OS << format("%.2f/%.2fB/%luW", Bits, Bits / 8, (unsigned long)(Bits / 32));424}425static void printSize(raw_ostream &OS, uint64_t Bits) {426OS << format("%lub/%.2fB/%luW", (unsigned long)Bits, (double)Bits / 8,427(unsigned long)(Bits / 32));428}429430static Expected<CurStreamTypeType> ReadSignature(BitstreamCursor &Stream) {431auto tryRead = [&Stream](char &Dest, size_t size) -> Error {432if (Expected<SimpleBitstreamCursor::word_t> MaybeWord = Stream.Read(size))433Dest = MaybeWord.get();434else435return MaybeWord.takeError();436return Error::success();437};438439char Signature[6];440if (Error Err = tryRead(Signature[0], 8))441return std::move(Err);442if (Error Err = tryRead(Signature[1], 8))443return std::move(Err);444445// Autodetect the file contents, if it is one we know.446if (Signature[0] == 'C' && Signature[1] == 'P') {447if (Error Err = tryRead(Signature[2], 8))448return std::move(Err);449if (Error Err = tryRead(Signature[3], 8))450return std::move(Err);451if (Signature[2] == 'C' && Signature[3] == 'H')452return ClangSerializedASTBitstream;453} else if (Signature[0] == 'D' && Signature[1] == 'I') {454if (Error Err = tryRead(Signature[2], 8))455return std::move(Err);456if (Error Err = tryRead(Signature[3], 8))457return std::move(Err);458if (Signature[2] == 'A' && Signature[3] == 'G')459return ClangSerializedDiagnosticsBitstream;460} else if (Signature[0] == 'R' && Signature[1] == 'M') {461if (Error Err = tryRead(Signature[2], 8))462return std::move(Err);463if (Error Err = tryRead(Signature[3], 8))464return std::move(Err);465if (Signature[2] == 'R' && Signature[3] == 'K')466return LLVMBitstreamRemarks;467} else {468if (Error Err = tryRead(Signature[2], 4))469return std::move(Err);470if (Error Err = tryRead(Signature[3], 4))471return std::move(Err);472if (Error Err = tryRead(Signature[4], 4))473return std::move(Err);474if (Error Err = tryRead(Signature[5], 4))475return std::move(Err);476if (Signature[0] == 'B' && Signature[1] == 'C' && Signature[2] == 0x0 &&477Signature[3] == 0xC && Signature[4] == 0xE && Signature[5] == 0xD)478return LLVMIRBitstream;479}480return UnknownBitstream;481}482483static Expected<CurStreamTypeType> analyzeHeader(std::optional<BCDumpOptions> O,484BitstreamCursor &Stream) {485ArrayRef<uint8_t> Bytes = Stream.getBitcodeBytes();486const unsigned char *BufPtr = (const unsigned char *)Bytes.data();487const unsigned char *EndBufPtr = BufPtr + Bytes.size();488489// If we have a wrapper header, parse it and ignore the non-bc file490// contents. The magic number is 0x0B17C0DE stored in little endian.491if (isBitcodeWrapper(BufPtr, EndBufPtr)) {492if (Bytes.size() < BWH_HeaderSize)493return reportError("Invalid bitcode wrapper header");494495if (O) {496unsigned Magic = support::endian::read32le(&BufPtr[BWH_MagicField]);497unsigned Version = support::endian::read32le(&BufPtr[BWH_VersionField]);498unsigned Offset = support::endian::read32le(&BufPtr[BWH_OffsetField]);499unsigned Size = support::endian::read32le(&BufPtr[BWH_SizeField]);500unsigned CPUType = support::endian::read32le(&BufPtr[BWH_CPUTypeField]);501502O->OS << "<BITCODE_WRAPPER_HEADER"503<< " Magic=" << format_hex(Magic, 10)504<< " Version=" << format_hex(Version, 10)505<< " Offset=" << format_hex(Offset, 10)506<< " Size=" << format_hex(Size, 10)507<< " CPUType=" << format_hex(CPUType, 10) << "/>\n";508}509510if (SkipBitcodeWrapperHeader(BufPtr, EndBufPtr, true))511return reportError("Invalid bitcode wrapper header");512}513514// Use the cursor modified by skipping the wrapper header.515Stream = BitstreamCursor(ArrayRef<uint8_t>(BufPtr, EndBufPtr));516517return ReadSignature(Stream);518}519520static bool canDecodeBlob(unsigned Code, unsigned BlockID) {521return BlockID == bitc::METADATA_BLOCK_ID && Code == bitc::METADATA_STRINGS;522}523524Error BitcodeAnalyzer::decodeMetadataStringsBlob(StringRef Indent,525ArrayRef<uint64_t> Record,526StringRef Blob,527raw_ostream &OS) {528if (Blob.empty())529return reportError("Cannot decode empty blob.");530531if (Record.size() != 2)532return reportError(533"Decoding metadata strings blob needs two record entries.");534535unsigned NumStrings = Record[0];536unsigned StringsOffset = Record[1];537OS << " num-strings = " << NumStrings << " {\n";538539StringRef Lengths = Blob.slice(0, StringsOffset);540SimpleBitstreamCursor R(Lengths);541StringRef Strings = Blob.drop_front(StringsOffset);542do {543if (R.AtEndOfStream())544return reportError("bad length");545546uint32_t Size;547if (Error E = R.ReadVBR(6).moveInto(Size))548return E;549if (Strings.size() < Size)550return reportError("truncated chars");551552OS << Indent << " '";553OS.write_escaped(Strings.slice(0, Size), /*hex=*/true);554OS << "'\n";555Strings = Strings.drop_front(Size);556} while (--NumStrings);557558OS << Indent << " }";559return Error::success();560}561562BitcodeAnalyzer::BitcodeAnalyzer(StringRef Buffer,563std::optional<StringRef> BlockInfoBuffer)564: Stream(Buffer) {565if (BlockInfoBuffer)566BlockInfoStream.emplace(*BlockInfoBuffer);567}568569Error BitcodeAnalyzer::analyze(std::optional<BCDumpOptions> O,570std::optional<StringRef> CheckHash) {571if (Error E = analyzeHeader(O, Stream).moveInto(CurStreamType))572return E;573574Stream.setBlockInfo(&BlockInfo);575576// Read block info from BlockInfoStream, if specified.577// The block info must be a top-level block.578if (BlockInfoStream) {579BitstreamCursor BlockInfoCursor(*BlockInfoStream);580if (Error E = analyzeHeader(O, BlockInfoCursor).takeError())581return E;582583while (!BlockInfoCursor.AtEndOfStream()) {584Expected<unsigned> MaybeCode = BlockInfoCursor.ReadCode();585if (!MaybeCode)586return MaybeCode.takeError();587if (MaybeCode.get() != bitc::ENTER_SUBBLOCK)588return reportError("Invalid record at top-level in block info file");589590Expected<unsigned> MaybeBlockID = BlockInfoCursor.ReadSubBlockID();591if (!MaybeBlockID)592return MaybeBlockID.takeError();593if (MaybeBlockID.get() == bitc::BLOCKINFO_BLOCK_ID) {594std::optional<BitstreamBlockInfo> NewBlockInfo;595if (Error E =596BlockInfoCursor.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true)597.moveInto(NewBlockInfo))598return E;599if (!NewBlockInfo)600return reportError("Malformed BlockInfoBlock in block info file");601BlockInfo = std::move(*NewBlockInfo);602break;603}604605if (Error Err = BlockInfoCursor.SkipBlock())606return Err;607}608}609610// Parse the top-level structure. We only allow blocks at the top-level.611while (!Stream.AtEndOfStream()) {612Expected<unsigned> MaybeCode = Stream.ReadCode();613if (!MaybeCode)614return MaybeCode.takeError();615if (MaybeCode.get() != bitc::ENTER_SUBBLOCK)616return reportError("Invalid record at top-level");617618Expected<unsigned> MaybeBlockID = Stream.ReadSubBlockID();619if (!MaybeBlockID)620return MaybeBlockID.takeError();621622if (Error E = parseBlock(MaybeBlockID.get(), 0, O, CheckHash))623return E;624++NumTopBlocks;625}626627return Error::success();628}629630void BitcodeAnalyzer::printStats(BCDumpOptions O,631std::optional<StringRef> Filename) {632uint64_t BufferSizeBits = Stream.getBitcodeBytes().size() * CHAR_BIT;633// Print a summary of the read file.634O.OS << "Summary ";635if (Filename)636O.OS << "of " << Filename->data() << ":\n";637O.OS << " Total size: ";638printSize(O.OS, BufferSizeBits);639O.OS << "\n";640O.OS << " Stream type: ";641switch (CurStreamType) {642case UnknownBitstream:643O.OS << "unknown\n";644break;645case LLVMIRBitstream:646O.OS << "LLVM IR\n";647break;648case ClangSerializedASTBitstream:649O.OS << "Clang Serialized AST\n";650break;651case ClangSerializedDiagnosticsBitstream:652O.OS << "Clang Serialized Diagnostics\n";653break;654case LLVMBitstreamRemarks:655O.OS << "LLVM Remarks\n";656break;657}658O.OS << " # Toplevel Blocks: " << NumTopBlocks << "\n";659O.OS << "\n";660661// Emit per-block stats.662O.OS << "Per-block Summary:\n";663for (const auto &Stat : BlockIDStats) {664O.OS << " Block ID #" << Stat.first;665if (std::optional<const char *> BlockName =666GetBlockName(Stat.first, BlockInfo, CurStreamType))667O.OS << " (" << *BlockName << ")";668O.OS << ":\n";669670const PerBlockIDStats &Stats = Stat.second;671O.OS << " Num Instances: " << Stats.NumInstances << "\n";672O.OS << " Total Size: ";673printSize(O.OS, Stats.NumBits);674O.OS << "\n";675double pct = (Stats.NumBits * 100.0) / BufferSizeBits;676O.OS << " Percent of file: " << format("%2.4f%%", pct) << "\n";677if (Stats.NumInstances > 1) {678O.OS << " Average Size: ";679printSize(O.OS, Stats.NumBits / (double)Stats.NumInstances);680O.OS << "\n";681O.OS << " Tot/Avg SubBlocks: " << Stats.NumSubBlocks << "/"682<< Stats.NumSubBlocks / (double)Stats.NumInstances << "\n";683O.OS << " Tot/Avg Abbrevs: " << Stats.NumAbbrevs << "/"684<< Stats.NumAbbrevs / (double)Stats.NumInstances << "\n";685O.OS << " Tot/Avg Records: " << Stats.NumRecords << "/"686<< Stats.NumRecords / (double)Stats.NumInstances << "\n";687} else {688O.OS << " Num SubBlocks: " << Stats.NumSubBlocks << "\n";689O.OS << " Num Abbrevs: " << Stats.NumAbbrevs << "\n";690O.OS << " Num Records: " << Stats.NumRecords << "\n";691}692if (Stats.NumRecords) {693double pct = (Stats.NumAbbreviatedRecords * 100.0) / Stats.NumRecords;694O.OS << " Percent Abbrevs: " << format("%2.4f%%", pct) << "\n";695}696O.OS << "\n";697698// Print a histogram of the codes we see.699if (O.Histogram && !Stats.CodeFreq.empty()) {700std::vector<std::pair<unsigned, unsigned>> FreqPairs; // <freq,code>701for (unsigned i = 0, e = Stats.CodeFreq.size(); i != e; ++i)702if (unsigned Freq = Stats.CodeFreq[i].NumInstances)703FreqPairs.push_back(std::make_pair(Freq, i));704llvm::stable_sort(FreqPairs);705std::reverse(FreqPairs.begin(), FreqPairs.end());706707O.OS << "\tRecord Histogram:\n";708O.OS << "\t\t Count # Bits b/Rec % Abv Record Kind\n";709for (const auto &FreqPair : FreqPairs) {710const PerRecordStats &RecStats = Stats.CodeFreq[FreqPair.second];711712O.OS << format("\t\t%7d %9lu", RecStats.NumInstances,713(unsigned long)RecStats.TotalBits);714715if (RecStats.NumInstances > 1)716O.OS << format(" %9.1f",717(double)RecStats.TotalBits / RecStats.NumInstances);718else719O.OS << " ";720721if (RecStats.NumAbbrev)722O.OS << format(" %7.2f", (double)RecStats.NumAbbrev /723RecStats.NumInstances * 100);724else725O.OS << " ";726727O.OS << " ";728if (std::optional<const char *> CodeName = GetCodeName(729FreqPair.second, Stat.first, BlockInfo, CurStreamType))730O.OS << *CodeName << "\n";731else732O.OS << "UnknownCode" << FreqPair.second << "\n";733}734O.OS << "\n";735}736}737}738739Error BitcodeAnalyzer::parseBlock(unsigned BlockID, unsigned IndentLevel,740std::optional<BCDumpOptions> O,741std::optional<StringRef> CheckHash) {742std::string Indent(IndentLevel * 2, ' ');743uint64_t BlockBitStart = Stream.GetCurrentBitNo();744745// Get the statistics for this BlockID.746PerBlockIDStats &BlockStats = BlockIDStats[BlockID];747748BlockStats.NumInstances++;749750// BLOCKINFO is a special part of the stream.751bool DumpRecords = O.has_value();752if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {753if (O && !O->DumpBlockinfo)754O->OS << Indent << "<BLOCKINFO_BLOCK/>\n";755std::optional<BitstreamBlockInfo> NewBlockInfo;756if (Error E = Stream.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true)757.moveInto(NewBlockInfo))758return E;759if (!NewBlockInfo)760return reportError("Malformed BlockInfoBlock");761BlockInfo = std::move(*NewBlockInfo);762if (Error Err = Stream.JumpToBit(BlockBitStart))763return Err;764// It's not really interesting to dump the contents of the blockinfo765// block, so only do it if the user explicitly requests it.766DumpRecords = O && O->DumpBlockinfo;767}768769unsigned NumWords = 0;770if (Error Err = Stream.EnterSubBlock(BlockID, &NumWords))771return Err;772773// Keep it for later, when we see a MODULE_HASH record774uint64_t BlockEntryPos = Stream.getCurrentByteNo();775776std::optional<const char *> BlockName;777if (DumpRecords) {778O->OS << Indent << "<";779if ((BlockName = GetBlockName(BlockID, BlockInfo, CurStreamType)))780O->OS << *BlockName;781else782O->OS << "UnknownBlock" << BlockID;783784if (!O->Symbolic && BlockName)785O->OS << " BlockID=" << BlockID;786787O->OS << " NumWords=" << NumWords788<< " BlockCodeSize=" << Stream.getAbbrevIDWidth() << ">\n";789}790791SmallVector<uint64_t, 64> Record;792793// Keep the offset to the metadata index if seen.794uint64_t MetadataIndexOffset = 0;795796// Read all the records for this block.797while (true) {798if (Stream.AtEndOfStream())799return reportError("Premature end of bitstream");800801uint64_t RecordStartBit = Stream.GetCurrentBitNo();802803BitstreamEntry Entry;804if (Error E = Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs)805.moveInto(Entry))806return E;807808switch (Entry.Kind) {809case BitstreamEntry::Error:810return reportError("malformed bitcode file");811case BitstreamEntry::EndBlock: {812uint64_t BlockBitEnd = Stream.GetCurrentBitNo();813BlockStats.NumBits += BlockBitEnd - BlockBitStart;814if (DumpRecords) {815O->OS << Indent << "</";816if (BlockName)817O->OS << *BlockName << ">\n";818else819O->OS << "UnknownBlock" << BlockID << ">\n";820}821return Error::success();822}823824case BitstreamEntry::SubBlock: {825uint64_t SubBlockBitStart = Stream.GetCurrentBitNo();826if (Error E = parseBlock(Entry.ID, IndentLevel + 1, O, CheckHash))827return E;828++BlockStats.NumSubBlocks;829uint64_t SubBlockBitEnd = Stream.GetCurrentBitNo();830831// Don't include subblock sizes in the size of this block.832BlockBitStart += SubBlockBitEnd - SubBlockBitStart;833continue;834}835case BitstreamEntry::Record:836// The interesting case.837break;838}839840if (Entry.ID == bitc::DEFINE_ABBREV) {841if (Error Err = Stream.ReadAbbrevRecord())842return Err;843++BlockStats.NumAbbrevs;844continue;845}846847Record.clear();848849++BlockStats.NumRecords;850851StringRef Blob;852uint64_t CurrentRecordPos = Stream.GetCurrentBitNo();853unsigned Code;854if (Error E = Stream.readRecord(Entry.ID, Record, &Blob).moveInto(Code))855return E;856857// Increment the # occurrences of this code.858if (BlockStats.CodeFreq.size() <= Code)859BlockStats.CodeFreq.resize(Code + 1);860BlockStats.CodeFreq[Code].NumInstances++;861BlockStats.CodeFreq[Code].TotalBits +=862Stream.GetCurrentBitNo() - RecordStartBit;863if (Entry.ID != bitc::UNABBREV_RECORD) {864BlockStats.CodeFreq[Code].NumAbbrev++;865++BlockStats.NumAbbreviatedRecords;866}867868if (DumpRecords) {869O->OS << Indent << " <";870std::optional<const char *> CodeName =871GetCodeName(Code, BlockID, BlockInfo, CurStreamType);872if (CodeName)873O->OS << *CodeName;874else875O->OS << "UnknownCode" << Code;876if (!O->Symbolic && CodeName)877O->OS << " codeid=" << Code;878const BitCodeAbbrev *Abbv = nullptr;879if (Entry.ID != bitc::UNABBREV_RECORD) {880Expected<const BitCodeAbbrev *> MaybeAbbv = Stream.getAbbrev(Entry.ID);881if (!MaybeAbbv)882return MaybeAbbv.takeError();883Abbv = MaybeAbbv.get();884O->OS << " abbrevid=" << Entry.ID;885}886887for (unsigned i = 0, e = Record.size(); i != e; ++i)888O->OS << " op" << i << "=" << (int64_t)Record[i];889890// If we found a metadata index, let's verify that we had an offset891// before and validate its forward reference offset was correct!892if (BlockID == bitc::METADATA_BLOCK_ID) {893if (Code == bitc::METADATA_INDEX_OFFSET) {894if (Record.size() != 2)895O->OS << "(Invalid record)";896else {897auto Offset = Record[0] + (Record[1] << 32);898MetadataIndexOffset = Stream.GetCurrentBitNo() + Offset;899}900}901if (Code == bitc::METADATA_INDEX) {902O->OS << " (offset ";903if (MetadataIndexOffset == RecordStartBit)904O->OS << "match)";905else906O->OS << "mismatch: " << MetadataIndexOffset << " vs "907<< RecordStartBit << ")";908}909}910911// If we found a module hash, let's verify that it matches!912if (BlockID == bitc::MODULE_BLOCK_ID && Code == bitc::MODULE_CODE_HASH &&913CheckHash) {914if (Record.size() != 5)915O->OS << " (invalid)";916else {917// Recompute the hash and compare it to the one in the bitcode918SHA1 Hasher;919std::array<uint8_t, 20> Hash;920Hasher.update(*CheckHash);921{922int BlockSize = (CurrentRecordPos / 8) - BlockEntryPos;923auto Ptr = Stream.getPointerToByte(BlockEntryPos, BlockSize);924Hasher.update(ArrayRef<uint8_t>(Ptr, BlockSize));925Hash = Hasher.result();926}927std::array<uint8_t, 20> RecordedHash;928int Pos = 0;929for (auto &Val : Record) {930assert(!(Val >> 32) && "Unexpected high bits set");931support::endian::write32be(&RecordedHash[Pos], Val);932Pos += 4;933}934if (Hash == RecordedHash)935O->OS << " (match)";936else937O->OS << " (!mismatch!)";938}939}940941O->OS << "/>";942943if (Abbv) {944for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i != e; ++i) {945const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);946if (!Op.isEncoding() || Op.getEncoding() != BitCodeAbbrevOp::Array)947continue;948assert(i + 2 == e && "Array op not second to last");949std::string Str;950bool ArrayIsPrintable = true;951for (unsigned j = i - 1, je = Record.size(); j != je; ++j) {952if (!isPrint(static_cast<unsigned char>(Record[j]))) {953ArrayIsPrintable = false;954break;955}956Str += (char)Record[j];957}958if (ArrayIsPrintable)959O->OS << " record string = '" << Str << "'";960break;961}962}963964if (Blob.data()) {965if (canDecodeBlob(Code, BlockID)) {966if (Error E = decodeMetadataStringsBlob(Indent, Record, Blob, O->OS))967return E;968} else {969O->OS << " blob data = ";970if (O->ShowBinaryBlobs) {971O->OS << "'";972O->OS.write_escaped(Blob, /*hex=*/true) << "'";973} else {974bool BlobIsPrintable = true;975for (char C : Blob)976if (!isPrint(static_cast<unsigned char>(C))) {977BlobIsPrintable = false;978break;979}980981if (BlobIsPrintable)982O->OS << "'" << Blob << "'";983else984O->OS << "unprintable, " << Blob.size() << " bytes.";985}986}987}988989O->OS << "\n";990}991992// Make sure that we can skip the current record.993if (Error Err = Stream.JumpToBit(CurrentRecordPos))994return Err;995if (Expected<unsigned> Skipped = Stream.skipRecord(Entry.ID))996; // Do nothing.997else998return Skipped.takeError();999}1000}1001100210031004