summaryrefslogtreecommitdiffstats
path: root/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp
blob: efd28bca4696322d0256eeda399ed186bfd29bd0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//===- PDBSymbolExe.cpp - ---------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"

#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#include "llvm/DebugInfo/PDB/PDBExtras.h"
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <utility>

#include <utility>

using namespace llvm;

#define SKIP_SYMBOL_IF_FLAG_UNSET(Tag, Flag)                                   \
  case PDB_SymType::Tag:                                                       \
    if ((Flags & Flag) == 0)                                                   \
      continue;                                                                \
    break;

PDBSymbolExe::PDBSymbolExe(const IPDBSession &PDBSession,
                           std::unique_ptr<IPDBRawSymbol> Symbol)
    : PDBSymbol(PDBSession, std::move(Symbol)) {}

void PDBSymbolExe::dump(raw_ostream &OS, int Indent,
                        PDB_DumpLevel Level, PDB_DumpFlags Flags) const {
  std::string FileName(getSymbolsFileName());

  OS << stream_indent(Indent) << "Summary for " << FileName << "\n";

  uint64_t FileSize = 0;
  if (!llvm::sys::fs::file_size(FileName, FileSize))
    OS << stream_indent(Indent + 2) << "Size: " << FileSize << " bytes\n";
  else
    OS << stream_indent(Indent + 2) << "Size: (Unable to obtain file size)\n";
  PDB_UniqueId Guid = getGuid();
  OS << stream_indent(Indent + 2) << "Guid: " << Guid << "\n";
  OS << stream_indent(Indent + 2) << "Age: " << getAge() << "\n";
  OS << stream_indent(Indent + 2) << "Attributes: ";
  if (hasCTypes())
    OS << "HasCTypes ";
  if (hasPrivateSymbols())
    OS << "HasPrivateSymbols ";
  OS << "\n";

  if (Flags & PDB_DF_Children) {
    OS << stream_indent(Indent + 2) << "Dumping types\n";
    if (Flags & PDB_DF_Hidden) {
      // For some reason, for each SymTag T, this dumps more items of type T
      // than are dumped by calling dumpChildren(T).  In other words, there are
      // "hidden" symbols.  For example, it causes functions to be dumped which
      // have no address information, whereas specifically dumping only
      // functions will not find those symbols.
      //
      // My suspicion is that in the underlying DIA call, when you call
      // findChildren, passing a value of SymTagNone means all children
      // recursively, whereas passing a concrete tag value means only immediate
      // children of the global scope.  So perhaps we need to find these
      // mysterious missing values by recursing through the hierarchy.
      //
      // On the other hand, there may just be some symbols that DIA tries to
      // hide from you because it thinks you don't care about them.  However
      // experimentation shows that even vtables, for example, can't be found
      // without an exhaustive search.
      auto ChildrenEnum = findAllChildren();
      OS << stream_indent(Indent + 2) << ChildrenEnum->getChildCount()
         << " symbols";

      while (auto Child = ChildrenEnum->getNext()) {
        switch (Child->getSymTag()) {
          SKIP_SYMBOL_IF_FLAG_UNSET(Function, PDB_DF_Functions)
          SKIP_SYMBOL_IF_FLAG_UNSET(Data, PDB_DF_Data)
          SKIP_SYMBOL_IF_FLAG_UNSET(Label, PDB_DF_Labels)
          SKIP_SYMBOL_IF_FLAG_UNSET(PublicSymbol, PDB_DF_PublicSyms)
          SKIP_SYMBOL_IF_FLAG_UNSET(UDT, PDB_DF_Classes)
          SKIP_SYMBOL_IF_FLAG_UNSET(Enum, PDB_DF_Enums)
          SKIP_SYMBOL_IF_FLAG_UNSET(FunctionSig, PDB_DF_Funcsigs)
          SKIP_SYMBOL_IF_FLAG_UNSET(VTable, PDB_DF_VTables)
          SKIP_SYMBOL_IF_FLAG_UNSET(Thunk, PDB_DF_Thunks)
          SKIP_SYMBOL_IF_FLAG_UNSET(Compiland, PDB_DF_ObjFiles)
        default:
          continue;
        }
        PDB_DumpLevel ChildLevel = (Level == PDB_DumpLevel::Detailed)
                                       ? PDB_DumpLevel::Normal
                                       : PDB_DumpLevel::Compact;
        OS << "\n";
        Child->dump(OS, Indent + 4, ChildLevel, PDB_DF_Children);
      }
    } else {
      if (Flags & PDB_DF_ObjFiles)
        dumpChildren(OS, "Compilands", PDB_SymType::Compiland, Indent + 4);
      if (Flags & PDB_DF_Functions)
        dumpChildren(OS, "Functions", PDB_SymType::Function, Indent + 4);
      if (Flags & PDB_DF_Data)
        dumpChildren(OS, "Data", PDB_SymType::Data, Indent + 4);
      if (Flags & PDB_DF_Labels)
        dumpChildren(OS, "Labels", PDB_SymType::Label, Indent + 4);
      if (Flags & PDB_DF_PublicSyms)
        dumpChildren(OS, "Public Symbols", PDB_SymType::PublicSymbol,
                     Indent + 4);
      if (Flags & PDB_DF_Classes)
        dumpChildren(OS, "UDTs", PDB_SymType::UDT, Indent + 4);
      if (Flags & PDB_DF_Enums)
        dumpChildren(OS, "Enums", PDB_SymType::Enum, Indent + 4);
      if (Flags & PDB_DF_Funcsigs)
        dumpChildren(OS, "Function Signatures", PDB_SymType::FunctionSig,
                     Indent + 4);
      if (Flags & PDB_DF_Typedefs)
        dumpChildren(OS, "Typedefs", PDB_SymType::Typedef, Indent + 4);
      if (Flags & PDB_DF_VTables)
        dumpChildren(OS, "VTables", PDB_SymType::VTable, Indent + 4);
      if (Flags & PDB_DF_Thunks)
        dumpChildren(OS, "Thunks", PDB_SymType::Thunk, Indent + 4);
    }
  }
}

void PDBSymbolExe::dumpChildren(raw_ostream &OS, StringRef Label,
                                PDB_SymType ChildType, int Indent) const {
  auto ChildrenEnum = findAllChildren(ChildType);
  OS << stream_indent(Indent) << Label << ": (" << ChildrenEnum->getChildCount()
     << " items)\n";
  while (auto Child = ChildrenEnum->getNext()) {
    Child->dump(OS, Indent + 2, PDB_DumpLevel::Normal, PDB_DF_None);
    OS << "\n";
  }
}
OpenPOWER on IntegriCloud