1//===- tools/dsymutil/DebugMap.cpp - Generic debug map representation -----===//
2//
3//                             The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#include "DebugMap.h"
10#include "llvm/ADT/STLExtras.h"
11#include "llvm/ADT/iterator_range.h"
12#include "llvm/Support/DataTypes.h"
13#include "llvm/Support/Format.h"
14#include "llvm/Support/raw_ostream.h"
15#include <algorithm>
16
17namespace llvm {
18namespace dsymutil {
19
20using namespace llvm::object;
21
22DebugMapObject::DebugMapObject(StringRef ObjectFilename)
23    : Filename(ObjectFilename) {}
24
25bool DebugMapObject::addSymbol(StringRef Name, uint64_t ObjectAddress,
26                               uint64_t LinkedAddress, uint32_t Size) {
27  auto InsertResult = Symbols.insert(
28      std::make_pair(Name, SymbolMapping(ObjectAddress, LinkedAddress, Size)));
29
30  if (InsertResult.second)
31    AddressToMapping[ObjectAddress] = &*InsertResult.first;
32  return InsertResult.second;
33}
34
35void DebugMapObject::print(raw_ostream &OS) const {
36  OS << getObjectFilename() << ":\n";
37  // Sort the symbols in alphabetical order, like llvm-nm (and to get
38  // deterministic output for testing).
39  typedef std::pair<StringRef, SymbolMapping> Entry;
40  std::vector<Entry> Entries;
41  Entries.reserve(Symbols.getNumItems());
42  for (const auto &Sym : make_range(Symbols.begin(), Symbols.end()))
43    Entries.push_back(std::make_pair(Sym.getKey(), Sym.getValue()));
44  std::sort(
45      Entries.begin(), Entries.end(),
46      [](const Entry &LHS, const Entry &RHS) { return LHS.first < RHS.first; });
47  for (const auto &Sym : Entries) {
48    OS << format("\t%016" PRIx64 " => %016" PRIx64 "+0x%x\t%s\n",
49                 Sym.second.ObjectAddress, Sym.second.BinaryAddress,
50                 Sym.second.Size, Sym.first.data());
51  }
52  OS << '\n';
53}
54
55#ifndef NDEBUG
56void DebugMapObject::dump() const { print(errs()); }
57#endif
58
59DebugMapObject &DebugMap::addDebugMapObject(StringRef ObjectFilePath) {
60  Objects.emplace_back(new DebugMapObject(ObjectFilePath));
61  return *Objects.back();
62}
63
64const DebugMapObject::DebugMapEntry *
65DebugMapObject::lookupSymbol(StringRef SymbolName) const {
66  StringMap<SymbolMapping>::const_iterator Sym = Symbols.find(SymbolName);
67  if (Sym == Symbols.end())
68    return nullptr;
69  return &*Sym;
70}
71
72const DebugMapObject::DebugMapEntry *
73DebugMapObject::lookupObjectAddress(uint64_t Address) const {
74  auto Mapping = AddressToMapping.find(Address);
75  if (Mapping == AddressToMapping.end())
76    return nullptr;
77  return Mapping->getSecond();
78}
79
80void DebugMap::print(raw_ostream &OS) const {
81  OS << "DEBUG MAP: " << BinaryTriple.getTriple()
82     << "\n\tobject addr =>  executable addr\tsymbol name\n";
83  for (const auto &Obj : objects())
84    Obj->print(OS);
85  OS << "END DEBUG MAP\n";
86}
87
88#ifndef NDEBUG
89void DebugMap::dump() const { print(errs()); }
90#endif
91}
92}
93