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
typesetItemList(ArrayRef<std::string> Opts,uint32_t IndentLevel,uint32_t GroupSize,StringRef Sep)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
typesetStringList(uint32_t IndentLevel,ArrayRef<StringRef> Strings)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
formatChunkKind(DebugSubsectionKind Kind,bool Friendly)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
formatSymbolKind(SymbolKind K)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
formatTypeLeafKind(TypeLeafKind K)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
formatSegmentOffset(uint16_t Segment,uint32_t Offset)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
formatSectionCharacteristics(uint32_t IndentLevel,uint32_t C,uint32_t FlagsPerLine,StringRef Separator,CharacteristicStyle Style)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