1 //===- DWARF.cpp ----------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "lld/Common/DWARF.h"
10 #include "lld/Common/ErrorHandler.h"
16 DWARFCache::DWARFCache(std::unique_ptr
<llvm::DWARFContext
> d
)
17 : dwarf(std::move(d
)) {
18 for (std::unique_ptr
<DWARFUnit
> &cu
: dwarf
->compile_units()) {
19 auto report
= [](Error err
) {
20 handleAllErrors(std::move(err
),
21 [](ErrorInfoBase
&info
) { warn(info
.message()); });
23 Expected
<const DWARFDebugLine::LineTable
*> expectedLT
=
24 dwarf
->getLineTableForUnit(cu
.get(), report
);
25 const DWARFDebugLine::LineTable
*lt
= nullptr;
29 report(expectedLT
.takeError());
32 lineTables
.push_back(lt
);
34 // Loop over variable records and insert them to variableLoc.
35 for (const auto &entry
: cu
->dies()) {
36 DWARFDie
die(cu
.get(), &entry
);
37 // Skip all tags that are not variables.
38 if (die
.getTag() != dwarf::DW_TAG_variable
)
41 // Skip if a local variable because we don't need them for generating
42 // error messages. In general, only non-local symbols can fail to be
44 if (!dwarf::toUnsigned(die
.find(dwarf::DW_AT_external
), 0))
47 // Get the source filename index for the variable.
48 unsigned file
= dwarf::toUnsigned(die
.find(dwarf::DW_AT_decl_file
), 0);
49 if (!lt
->hasFileAtIndex(file
))
52 // Get the line number on which the variable is declared.
53 unsigned line
= dwarf::toUnsigned(die
.find(dwarf::DW_AT_decl_line
), 0);
55 // Here we want to take the variable name to add it into variableLoc.
56 // Variable can have regular and linkage name associated. At first, we try
57 // to get linkage name as it can be different, for example when we have
58 // two variables in different namespaces of the same object. Use common
59 // name otherwise, but handle the case when it also absent in case if the
60 // input object file lacks some debug info.
62 dwarf::toString(die
.find(dwarf::DW_AT_linkage_name
),
63 dwarf::toString(die
.find(dwarf::DW_AT_name
), ""));
65 variableLoc
.insert({name
, {lt
, file
, line
}});
70 // Returns the pair of file name and line number describing location of data
71 // object (variable, array, etc) definition.
72 Optional
<std::pair
<std::string
, unsigned>>
73 DWARFCache::getVariableLoc(StringRef name
) {
74 // Return if we have no debug information about data object.
75 auto it
= variableLoc
.find(name
);
76 if (it
== variableLoc
.end())
79 // Take file name string from line table.
81 if (!it
->second
.lt
->getFileNameByIndex(
83 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath
, fileName
))
86 return std::make_pair(fileName
, it
->second
.line
);
89 // Returns source line information for a given offset
90 // using DWARF debug info.
91 Optional
<DILineInfo
> DWARFCache::getDILineInfo(uint64_t offset
,
92 uint64_t sectionIndex
) {
94 for (const llvm::DWARFDebugLine::LineTable
*lt
: lineTables
) {
95 if (lt
->getFileLineInfoForAddress(
96 {offset
, sectionIndex
}, nullptr,
97 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath
, info
))