#include "DebugMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
namespace llvm {
namespace dsymutil {
using namespace llvm::object;
DebugMapObject::DebugMapObject(StringRef ObjectFilename,
sys::TimeValue Timestamp,
bool SwiftModule)
: Filename(ObjectFilename), Timestamp(Timestamp),
SwiftModule(SwiftModule) {}
bool DebugMapObject::addSymbol(StringRef Name, uint64_t ObjectAddress,
uint64_t LinkedAddress, uint32_t Size,
StringRef Section, bool FromAnotherObjectFile) {
auto InsertResult = Symbols.insert(
std::make_pair(Name, SymbolMapping(ObjectAddress, LinkedAddress, Section,
Size, FromAnotherObjectFile)));
DebugMapEntry &Entry = *InsertResult.first;
if (!Section.empty()) {
DebugMapEntry *&MapEntry = AddressToMapping[ObjectAddress];
if (!MapEntry ||
(LinkedAddress != object::UnknownAddressOrSize &&
MapEntry->getValue().BinaryAddress == object::UnknownAddressOrSize))
MapEntry = &Entry;
}
if (!InsertResult.second) {
if (Size)
Entry.getValue().Size = Size;
if (!FromAnotherObjectFile && Entry.getValue().FromAnotherObjectFile) {
Entry.getValue().ObjectAddress = ObjectAddress;
Entry.getValue().BinaryAddress = LinkedAddress;
}
Entry.getValue().FromAnotherObjectFile = FromAnotherObjectFile;
return Entry.getValue().ObjectAddress == ObjectAddress &&
Entry.getValue().BinaryAddress == LinkedAddress;
}
return true;
}
void DebugMapObject::print(raw_ostream &OS) const {
OS << getObjectFilename() << ":\n";
typedef std::pair<StringRef, SymbolMapping> Entry;
std::vector<Entry> Entries;
Entries.reserve(Symbols.getNumItems());
for (const auto &Sym : make_range(Symbols.begin(), Symbols.end()))
Entries.push_back(std::make_pair(Sym.getKey(), Sym.getValue()));
std::sort(
Entries.begin(), Entries.end(),
[](const Entry &LHS, const Entry &RHS) { return LHS.first < RHS.first; });
for (const auto &Sym : Entries) {
OS << format("\t%016" PRIx64 " => %016" PRIx64,
uint64_t(Sym.second.ObjectAddress),
uint64_t(Sym.second.BinaryAddress))
<< "+" << format_hex(uint32_t(Sym.second.Size), 3)
<< format("\t%s %s",
Sym.first.data(),
Sym.second.FromAnotherObjectFile ? "(other object)" : "");
if (!Sym.second.Section.empty())
OS << "\tin " << Sym.second.Section;
OS << '\n';
}
OS << '\n';
}
#ifndef NDEBUG
void DebugMapObject::dump() const { print(errs()); }
#endif
DebugMapObject &DebugMap::addDebugMapObject(StringRef ObjectFilePath,
sys::TimeValue Timestamp,
bool SwiftModule) {
Objects.emplace_back(new DebugMapObject(ObjectFilePath, Timestamp,
SwiftModule));
return *Objects.back();
}
const DebugMapObject::DebugMapEntry *
DebugMapObject::lookupSymbol(StringRef SymbolName) const {
StringMap<SymbolMapping>::const_iterator Sym = Symbols.find(SymbolName);
if (Sym == Symbols.end())
return nullptr;
return &*Sym;
}
const DebugMapObject::DebugMapEntry *
DebugMapObject::lookupObjectAddress(uint64_t Address,
StringRef Section) const {
auto Mapping = AddressToMapping.upper_bound(Address);
if (Mapping != AddressToMapping.begin())
--Mapping;
if (Mapping == AddressToMapping.end() ||
Mapping->second->getValue().ObjectAddress > Address ||
(!Section.empty() && Mapping->second->getValue().Section != Section))
return nullptr;
return Mapping->second;
}
void DebugMap::print(raw_ostream &OS) const {
OS << "DEBUG MAP: " << BinaryTriple.getTriple()
<< "\n\tobject addr => executable addr\tsymbol name\n";
for (const auto &Obj : objects())
Obj->print(OS);
OS << "END DEBUG MAP\n";
}
#ifndef NDEBUG
void DebugMap::dump() const { print(errs()); }
#endif
}
}