Files
clang-p2996/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp
Zachary Turner 7999b4fa48 [PDB] Refactor the PDB symbol classes to fix a reuse bug.
The way DIA SDK works is that when you request a symbol, it
gets assigned an internal identifier that is unique for the
life of the session.  You can then use this identifier to
get back the same symbol, with all of the same internal state
that it had before, even if you "destroyed" the original
copy of the object you had.

This didn't work properly in our native implementation, and
if you destroyed an object for a particular symbol, then
requested the same symbol again, it would get assigned a new
ID and you'd get a fresh copy of the object.  In order to fix
this some refactoring had to happen to properly reuse cached
objects.  Some unittests are added to verify that symbol
reuse is taking place, making use of the new unittest input
feature.

llvm-svn: 341503
2018-09-05 23:30:38 +00:00

117 lines
3.5 KiB
C++

//===- PDBSymbolFunc.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/PDBSymbolFunc.h"
#include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include <unordered_set>
#include <utility>
#include <vector>
using namespace llvm;
using namespace llvm::pdb;
namespace {
class FunctionArgEnumerator : public IPDBEnumChildren<PDBSymbolData> {
public:
typedef ConcreteSymbolEnumerator<PDBSymbolData> ArgEnumeratorType;
FunctionArgEnumerator(const IPDBSession &PDBSession,
const PDBSymbolFunc &PDBFunc)
: Session(PDBSession), Func(PDBFunc) {
// Arguments can appear multiple times if they have live range
// information, so we only take the first occurrence.
std::unordered_set<std::string> SeenNames;
auto DataChildren = Func.findAllChildren<PDBSymbolData>();
while (auto Child = DataChildren->getNext()) {
if (Child->getDataKind() == PDB_DataKind::Param) {
std::string Name = Child->getName();
if (SeenNames.find(Name) != SeenNames.end())
continue;
Args.push_back(std::move(Child));
SeenNames.insert(Name);
}
}
reset();
}
uint32_t getChildCount() const override { return Args.size(); }
std::unique_ptr<PDBSymbolData>
getChildAtIndex(uint32_t Index) const override {
if (Index >= Args.size())
return nullptr;
return Session.getConcreteSymbolById<PDBSymbolData>(
Args[Index]->getSymIndexId());
}
std::unique_ptr<PDBSymbolData> getNext() override {
if (CurIter == Args.end())
return nullptr;
const auto &Result = **CurIter;
++CurIter;
return Session.getConcreteSymbolById<PDBSymbolData>(Result.getSymIndexId());
}
void reset() override { CurIter = Args.empty() ? Args.end() : Args.begin(); }
FunctionArgEnumerator *clone() const override {
return new FunctionArgEnumerator(Session, Func);
}
private:
typedef std::vector<std::unique_ptr<PDBSymbolData>> ArgListType;
const IPDBSession &Session;
const PDBSymbolFunc &Func;
ArgListType Args;
ArgListType::const_iterator CurIter;
};
}
std::unique_ptr<IPDBEnumChildren<PDBSymbolData>>
PDBSymbolFunc::getArguments() const {
return llvm::make_unique<FunctionArgEnumerator>(Session, *this);
}
void PDBSymbolFunc::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
bool PDBSymbolFunc::isDestructor() const {
std::string Name = getName();
if (Name.empty())
return false;
if (Name[0] == '~')
return true;
if (Name == "__vecDelDtor")
return true;
return false;
}
std::unique_ptr<IPDBEnumLineNumbers> PDBSymbolFunc::getLineNumbers() const {
auto Len = RawSymbol->getLength();
return Session.findLineNumbersByAddress(RawSymbol->getVirtualAddress(),
Len ? Len : 1);
}
uint32_t PDBSymbolFunc::getCompilandId() const {
if (auto Lines = getLineNumbers()) {
if (auto FirstLine = Lines->getNext()) {
return FirstLine->getCompilandId();
}
}
return 0;
}