xref: /llvm-project/lld/Common/DWARF.cpp (revision 0886440ef0ed0ad553522b731c841b81dc36944c)
1908b7809SMartin Storsjo //===- DWARF.cpp ----------------------------------------------------------===//
2908b7809SMartin Storsjo //
3908b7809SMartin Storsjo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4908b7809SMartin Storsjo // See https://llvm.org/LICENSE.txt for license information.
5908b7809SMartin Storsjo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6908b7809SMartin Storsjo //
7908b7809SMartin Storsjo //===----------------------------------------------------------------------===//
8908b7809SMartin Storsjo 
9908b7809SMartin Storsjo #include "lld/Common/DWARF.h"
10908b7809SMartin Storsjo #include "lld/Common/ErrorHandler.h"
11908b7809SMartin Storsjo 
12908b7809SMartin Storsjo using namespace llvm;
13908b7809SMartin Storsjo 
14908b7809SMartin Storsjo namespace lld {
15908b7809SMartin Storsjo 
16908b7809SMartin Storsjo DWARFCache::DWARFCache(std::unique_ptr<llvm::DWARFContext> d)
17908b7809SMartin Storsjo     : dwarf(std::move(d)) {
18908b7809SMartin Storsjo   for (std::unique_ptr<DWARFUnit> &cu : dwarf->compile_units()) {
19908b7809SMartin Storsjo     auto report = [](Error err) {
20908b7809SMartin Storsjo       handleAllErrors(std::move(err),
21908b7809SMartin Storsjo                       [](ErrorInfoBase &info) { warn(info.message()); });
22908b7809SMartin Storsjo     };
23908b7809SMartin Storsjo     Expected<const DWARFDebugLine::LineTable *> expectedLT =
24908b7809SMartin Storsjo         dwarf->getLineTableForUnit(cu.get(), report);
25908b7809SMartin Storsjo     const DWARFDebugLine::LineTable *lt = nullptr;
26908b7809SMartin Storsjo     if (expectedLT)
27908b7809SMartin Storsjo       lt = *expectedLT;
28908b7809SMartin Storsjo     else
29908b7809SMartin Storsjo       report(expectedLT.takeError());
30908b7809SMartin Storsjo     if (!lt)
31908b7809SMartin Storsjo       continue;
32908b7809SMartin Storsjo     lineTables.push_back(lt);
33908b7809SMartin Storsjo 
34908b7809SMartin Storsjo     // Loop over variable records and insert them to variableLoc.
35908b7809SMartin Storsjo     for (const auto &entry : cu->dies()) {
36908b7809SMartin Storsjo       DWARFDie die(cu.get(), &entry);
37908b7809SMartin Storsjo       // Skip all tags that are not variables.
38908b7809SMartin Storsjo       if (die.getTag() != dwarf::DW_TAG_variable)
39908b7809SMartin Storsjo         continue;
40908b7809SMartin Storsjo 
41908b7809SMartin Storsjo       // Skip if a local variable because we don't need them for generating
42908b7809SMartin Storsjo       // error messages. In general, only non-local symbols can fail to be
43908b7809SMartin Storsjo       // linked.
44908b7809SMartin Storsjo       if (!dwarf::toUnsigned(die.find(dwarf::DW_AT_external), 0))
45908b7809SMartin Storsjo         continue;
46908b7809SMartin Storsjo 
47908b7809SMartin Storsjo       // Get the source filename index for the variable.
48908b7809SMartin Storsjo       unsigned file = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_file), 0);
49908b7809SMartin Storsjo       if (!lt->hasFileAtIndex(file))
50908b7809SMartin Storsjo         continue;
51908b7809SMartin Storsjo 
52908b7809SMartin Storsjo       // Get the line number on which the variable is declared.
53908b7809SMartin Storsjo       unsigned line = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_line), 0);
54908b7809SMartin Storsjo 
55908b7809SMartin Storsjo       // Here we want to take the variable name to add it into variableLoc.
56908b7809SMartin Storsjo       // Variable can have regular and linkage name associated. At first, we try
57908b7809SMartin Storsjo       // to get linkage name as it can be different, for example when we have
58908b7809SMartin Storsjo       // two variables in different namespaces of the same object. Use common
59908b7809SMartin Storsjo       // name otherwise, but handle the case when it also absent in case if the
60908b7809SMartin Storsjo       // input object file lacks some debug info.
61908b7809SMartin Storsjo       StringRef name =
62908b7809SMartin Storsjo           dwarf::toString(die.find(dwarf::DW_AT_linkage_name),
63908b7809SMartin Storsjo                           dwarf::toString(die.find(dwarf::DW_AT_name), ""));
64908b7809SMartin Storsjo       if (!name.empty())
65908b7809SMartin Storsjo         variableLoc.insert({name, {lt, file, line}});
66908b7809SMartin Storsjo     }
67908b7809SMartin Storsjo   }
68908b7809SMartin Storsjo }
69908b7809SMartin Storsjo 
70908b7809SMartin Storsjo // Returns the pair of file name and line number describing location of data
71908b7809SMartin Storsjo // object (variable, array, etc) definition.
72c33511c8SFangrui Song std::optional<std::pair<std::string, unsigned>>
73908b7809SMartin Storsjo DWARFCache::getVariableLoc(StringRef name) {
74908b7809SMartin Storsjo   // Return if we have no debug information about data object.
75908b7809SMartin Storsjo   auto it = variableLoc.find(name);
76908b7809SMartin Storsjo   if (it == variableLoc.end())
77c33511c8SFangrui Song     return std::nullopt;
78908b7809SMartin Storsjo 
79908b7809SMartin Storsjo   // Take file name string from line table.
80908b7809SMartin Storsjo   std::string fileName;
81908b7809SMartin Storsjo   if (!it->second.lt->getFileNameByIndex(
82908b7809SMartin Storsjo           it->second.file, {},
83908b7809SMartin Storsjo           DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, fileName))
84c33511c8SFangrui Song     return std::nullopt;
85908b7809SMartin Storsjo 
86908b7809SMartin Storsjo   return std::make_pair(fileName, it->second.line);
87908b7809SMartin Storsjo }
88908b7809SMartin Storsjo 
89908b7809SMartin Storsjo // Returns source line information for a given offset
90908b7809SMartin Storsjo // using DWARF debug info.
91c33511c8SFangrui Song std::optional<DILineInfo> DWARFCache::getDILineInfo(uint64_t offset,
92908b7809SMartin Storsjo                                                     uint64_t sectionIndex) {
93908b7809SMartin Storsjo   DILineInfo info;
94908b7809SMartin Storsjo   for (const llvm::DWARFDebugLine::LineTable *lt : lineTables) {
95908b7809SMartin Storsjo     if (lt->getFileLineInfoForAddress(
96*0886440eSAmit Kumar Pandey             {offset, sectionIndex}, false, nullptr,
97908b7809SMartin Storsjo             DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, info))
98908b7809SMartin Storsjo       return info;
99908b7809SMartin Storsjo   }
100c33511c8SFangrui Song   return std::nullopt;
101908b7809SMartin Storsjo }
102908b7809SMartin Storsjo 
103908b7809SMartin Storsjo } // namespace lld
104