181ad6265SDimitry Andric //===- FormatUtil.cpp ----------------------------------------- *- C++ --*-===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric 981ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/Native/FormatUtil.h" 1081ad6265SDimitry Andric 1181ad6265SDimitry Andric #include "llvm/ADT/STLExtras.h" 12*5f757f3fSDimitry Andric #include "llvm/ADT/STLForwardCompat.h" 1381ad6265SDimitry Andric #include "llvm/ADT/StringExtras.h" 1481ad6265SDimitry Andric #include "llvm/BinaryFormat/COFF.h" 1581ad6265SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeView.h" 1681ad6265SDimitry Andric #include "llvm/Support/FormatAdapters.h" 1781ad6265SDimitry Andric #include "llvm/Support/FormatVariadic.h" 1881ad6265SDimitry Andric 1981ad6265SDimitry Andric using namespace llvm; 2081ad6265SDimitry Andric using namespace llvm::codeview; 2181ad6265SDimitry Andric using namespace llvm::pdb; 2281ad6265SDimitry Andric 2381ad6265SDimitry Andric std::string llvm::pdb::typesetItemList(ArrayRef<std::string> Opts, 2481ad6265SDimitry Andric uint32_t IndentLevel, uint32_t GroupSize, 2581ad6265SDimitry Andric StringRef Sep) { 2681ad6265SDimitry Andric std::string Result; 2781ad6265SDimitry Andric while (!Opts.empty()) { 2881ad6265SDimitry Andric ArrayRef<std::string> ThisGroup; 2981ad6265SDimitry Andric ThisGroup = Opts.take_front(GroupSize); 3081ad6265SDimitry Andric Opts = Opts.drop_front(ThisGroup.size()); 3181ad6265SDimitry Andric Result += join(ThisGroup, Sep); 3281ad6265SDimitry Andric if (!Opts.empty()) { 3381ad6265SDimitry Andric Result += Sep; 3481ad6265SDimitry Andric Result += "\n"; 3581ad6265SDimitry Andric Result += std::string(formatv("{0}", fmt_repeat(' ', IndentLevel))); 3681ad6265SDimitry Andric } 3781ad6265SDimitry Andric } 3881ad6265SDimitry Andric return Result; 3981ad6265SDimitry Andric } 4081ad6265SDimitry Andric 4181ad6265SDimitry Andric std::string llvm::pdb::typesetStringList(uint32_t IndentLevel, 4281ad6265SDimitry Andric ArrayRef<StringRef> Strings) { 4381ad6265SDimitry Andric std::string Result = "["; 4481ad6265SDimitry Andric for (const auto &S : Strings) { 4581ad6265SDimitry Andric Result += std::string(formatv("\n{0}{1}", fmt_repeat(' ', IndentLevel), S)); 4681ad6265SDimitry Andric } 4781ad6265SDimitry Andric Result += "]"; 4881ad6265SDimitry Andric return Result; 4981ad6265SDimitry Andric } 5081ad6265SDimitry Andric 5181ad6265SDimitry Andric std::string llvm::pdb::formatChunkKind(DebugSubsectionKind Kind, 5281ad6265SDimitry Andric bool Friendly) { 5381ad6265SDimitry Andric if (Friendly) { 5481ad6265SDimitry Andric switch (Kind) { 5581ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, None, "none"); 5681ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, Symbols, "symbols"); 5781ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, Lines, "lines"); 5881ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, StringTable, "strings"); 5981ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, FileChecksums, "checksums"); 6081ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, FrameData, "frames"); 6181ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, InlineeLines, "inlinee lines"); 6281ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, CrossScopeImports, "xmi"); 6381ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, CrossScopeExports, "xme"); 6481ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, ILLines, "il lines"); 6581ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, FuncMDTokenMap, "func md token map"); 6681ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, TypeMDTokenMap, "type md token map"); 6781ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, MergedAssemblyInput, 6881ad6265SDimitry Andric "merged assembly input"); 6981ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, CoffSymbolRVA, "coff symbol rva"); 7061cfbce3SDimitry Andric RETURN_CASE(DebugSubsectionKind, XfgHashType, "xfg hash type"); 7161cfbce3SDimitry Andric RETURN_CASE(DebugSubsectionKind, XfgHashVirtual, "xfg hash virtual"); 7281ad6265SDimitry Andric } 7381ad6265SDimitry Andric } else { 7481ad6265SDimitry Andric switch (Kind) { 7581ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, None, "none"); 7681ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, Symbols, "DEBUG_S_SYMBOLS"); 7781ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, Lines, "DEBUG_S_LINES"); 7881ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, StringTable, "DEBUG_S_STRINGTABLE"); 7981ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, FileChecksums, "DEBUG_S_FILECHKSMS"); 8081ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, FrameData, "DEBUG_S_FRAMEDATA"); 8181ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, InlineeLines, "DEBUG_S_INLINEELINES"); 8281ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, CrossScopeImports, 8381ad6265SDimitry Andric "DEBUG_S_CROSSSCOPEIMPORTS"); 8481ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, CrossScopeExports, 8581ad6265SDimitry Andric "DEBUG_S_CROSSSCOPEEXPORTS"); 8681ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, ILLines, "DEBUG_S_IL_LINES"); 8781ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, FuncMDTokenMap, 8881ad6265SDimitry Andric "DEBUG_S_FUNC_MDTOKEN_MAP"); 8981ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, TypeMDTokenMap, 9081ad6265SDimitry Andric "DEBUG_S_TYPE_MDTOKEN_MAP"); 9181ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, MergedAssemblyInput, 9281ad6265SDimitry Andric "DEBUG_S_MERGED_ASSEMBLYINPUT"); 9381ad6265SDimitry Andric RETURN_CASE(DebugSubsectionKind, CoffSymbolRVA, 9481ad6265SDimitry Andric "DEBUG_S_COFF_SYMBOL_RVA"); 9561cfbce3SDimitry Andric RETURN_CASE(DebugSubsectionKind, XfgHashType, 9661cfbce3SDimitry Andric "DEBUG_S_XFGHASH_TYPE"); 9761cfbce3SDimitry Andric RETURN_CASE(DebugSubsectionKind, XfgHashVirtual, 9861cfbce3SDimitry Andric "DEBUG_S_XFGHASH_VIRTUAL"); 9961cfbce3SDimitry Andric 10081ad6265SDimitry Andric } 10181ad6265SDimitry Andric } 10281ad6265SDimitry Andric return formatUnknownEnum(Kind); 10381ad6265SDimitry Andric } 10481ad6265SDimitry Andric 10581ad6265SDimitry Andric std::string llvm::pdb::formatSymbolKind(SymbolKind K) { 10681ad6265SDimitry Andric switch (uint32_t(K)) { 10781ad6265SDimitry Andric #define SYMBOL_RECORD(EnumName, value, name) \ 10881ad6265SDimitry Andric case EnumName: \ 10981ad6265SDimitry Andric return #EnumName; 11081ad6265SDimitry Andric #define CV_SYMBOL(EnumName, value) SYMBOL_RECORD(EnumName, value, EnumName) 11181ad6265SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" 11281ad6265SDimitry Andric } 11381ad6265SDimitry Andric return formatUnknownEnum(K); 11481ad6265SDimitry Andric } 11581ad6265SDimitry Andric 11681ad6265SDimitry Andric std::string llvm::pdb::formatTypeLeafKind(TypeLeafKind K) { 11781ad6265SDimitry Andric switch (K) { 11881ad6265SDimitry Andric #define TYPE_RECORD(EnumName, value, name) \ 11981ad6265SDimitry Andric case EnumName: \ 12081ad6265SDimitry Andric return #EnumName; 12181ad6265SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewTypes.def" 12281ad6265SDimitry Andric default: 123*5f757f3fSDimitry Andric return formatv("UNKNOWN RECORD ({0:X})", llvm::to_underlying(K)).str(); 12481ad6265SDimitry Andric } 12581ad6265SDimitry Andric } 12681ad6265SDimitry Andric 12781ad6265SDimitry Andric std::string llvm::pdb::formatSegmentOffset(uint16_t Segment, uint32_t Offset) { 12881ad6265SDimitry Andric return std::string(formatv("{0:4}:{1:4}", Segment, Offset)); 12981ad6265SDimitry Andric } 13081ad6265SDimitry Andric 13181ad6265SDimitry Andric #define PUSH_CHARACTERISTIC_FLAG(Enum, TheOpt, Value, Style, Descriptive) \ 13281ad6265SDimitry Andric PUSH_FLAG(Enum, TheOpt, Value, \ 13381ad6265SDimitry Andric ((Style == CharacteristicStyle::HeaderDefinition) ? #TheOpt \ 13481ad6265SDimitry Andric : Descriptive)) 13581ad6265SDimitry Andric 13681ad6265SDimitry Andric #define PUSH_MASKED_CHARACTERISTIC_FLAG(Enum, Mask, TheOpt, Value, Style, \ 13781ad6265SDimitry Andric Descriptive) \ 13881ad6265SDimitry Andric PUSH_MASKED_FLAG(Enum, Mask, TheOpt, Value, \ 13981ad6265SDimitry Andric ((Style == CharacteristicStyle::HeaderDefinition) \ 14081ad6265SDimitry Andric ? #TheOpt \ 14181ad6265SDimitry Andric : Descriptive)) 14281ad6265SDimitry Andric 14381ad6265SDimitry Andric std::string llvm::pdb::formatSectionCharacteristics(uint32_t IndentLevel, 14481ad6265SDimitry Andric uint32_t C, 14581ad6265SDimitry Andric uint32_t FlagsPerLine, 14681ad6265SDimitry Andric StringRef Separator, 14781ad6265SDimitry Andric CharacteristicStyle Style) { 14881ad6265SDimitry Andric using SC = COFF::SectionCharacteristics; 14981ad6265SDimitry Andric std::vector<std::string> Opts; 15081ad6265SDimitry Andric if (C == COFF::SC_Invalid) 15181ad6265SDimitry Andric return "invalid"; 15281ad6265SDimitry Andric if (C == 0) 15381ad6265SDimitry Andric return "none"; 15481ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_TYPE_NOLOAD, C, Style, "noload"); 15581ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_TYPE_NO_PAD, C, Style, "no padding"); 15681ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_CNT_CODE, C, Style, "code"); 15781ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_CNT_INITIALIZED_DATA, C, Style, 15881ad6265SDimitry Andric "initialized data"); 15981ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_CNT_UNINITIALIZED_DATA, C, Style, 16081ad6265SDimitry Andric "uninitialized data"); 16181ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_LNK_OTHER, C, Style, "other"); 16281ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_LNK_INFO, C, Style, "info"); 16381ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_LNK_REMOVE, C, Style, "remove"); 16481ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_LNK_COMDAT, C, Style, "comdat"); 16581ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_GPREL, C, Style, "gp rel"); 16681ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_PURGEABLE, C, Style, "purgeable"); 16781ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_16BIT, C, Style, "16-bit"); 16881ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_LOCKED, C, Style, "locked"); 16981ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_PRELOAD, C, Style, "preload"); 17081ad6265SDimitry Andric PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_1BYTES, C, 17181ad6265SDimitry Andric Style, "1 byte align"); 17281ad6265SDimitry Andric PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_2BYTES, C, 17381ad6265SDimitry Andric Style, "2 byte align"); 17481ad6265SDimitry Andric PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_4BYTES, C, 17581ad6265SDimitry Andric Style, "4 byte align"); 17681ad6265SDimitry Andric PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_8BYTES, C, 17781ad6265SDimitry Andric Style, "8 byte align"); 17881ad6265SDimitry Andric PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_16BYTES, C, 17981ad6265SDimitry Andric Style, "16 byte align"); 18081ad6265SDimitry Andric PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_32BYTES, C, 18181ad6265SDimitry Andric Style, "32 byte align"); 18281ad6265SDimitry Andric PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_64BYTES, C, 18381ad6265SDimitry Andric Style, "64 byte align"); 18481ad6265SDimitry Andric PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_128BYTES, C, 18581ad6265SDimitry Andric Style, "128 byte align"); 18681ad6265SDimitry Andric PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_256BYTES, C, 18781ad6265SDimitry Andric Style, "256 byte align"); 18881ad6265SDimitry Andric PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_512BYTES, C, 18981ad6265SDimitry Andric Style, "512 byte align"); 19081ad6265SDimitry Andric PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_1024BYTES, C, 19181ad6265SDimitry Andric Style, "1024 byte align"); 19281ad6265SDimitry Andric PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_2048BYTES, C, 19381ad6265SDimitry Andric Style, "2048 byte align"); 19481ad6265SDimitry Andric PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_4096BYTES, C, 19581ad6265SDimitry Andric Style, "4096 byte align"); 19681ad6265SDimitry Andric PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_8192BYTES, C, 19781ad6265SDimitry Andric Style, "8192 byte align"); 19881ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_LNK_NRELOC_OVFL, C, Style, 19981ad6265SDimitry Andric "noreloc overflow"); 20081ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_DISCARDABLE, C, Style, 20181ad6265SDimitry Andric "discardable"); 20281ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_NOT_CACHED, C, Style, 20381ad6265SDimitry Andric "not cached"); 20481ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_NOT_PAGED, C, Style, "not paged"); 20581ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_SHARED, C, Style, "shared"); 20681ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_EXECUTE, C, Style, 20781ad6265SDimitry Andric "execute permissions"); 20881ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_READ, C, Style, 20981ad6265SDimitry Andric "read permissions"); 21081ad6265SDimitry Andric PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_WRITE, C, Style, 21181ad6265SDimitry Andric "write permissions"); 21281ad6265SDimitry Andric return typesetItemList(Opts, IndentLevel, FlagsPerLine, Separator); 21381ad6265SDimitry Andric } 214