Skip to content

Commit fe690a8

Browse files
mstorsjocompnerd
authored andcommitted
[LLD] Move duplicated dwarf parsing code to the Common library. NFC.
Differential Revision: https://reviews.llvm.org/D69197 llvm-svn: 375390 (cherry picked from commit 908b780) (cherry picked from commit a18630d8a3a9bce3e9012744de371a5d5768f2db)
1 parent b9e5812 commit fe690a8

File tree

6 files changed

+161
-83
lines changed

6 files changed

+161
-83
lines changed

lld/COFF/InputFiles.h

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define LLD_COFF_INPUT_FILES_H
1111

1212
#include "Config.h"
13+
#include "lld/Common/DWARF.h"
1314
#include "lld/Common/LLVM.h"
1415
#include "llvm/ADT/ArrayRef.h"
1516
#include "llvm/ADT/DenseMap.h"
@@ -258,6 +259,8 @@ class ObjFile : public InputFile {
258259
// index. Nonexistent indices (which are occupied by auxiliary
259260
// symbols in the real symbol table) are filled with null pointers.
260261
std::vector<Symbol *> Symbols;
262+
263+
DWARFCache *dwarf;
261264
};
262265

263266
// This type represents import library members that contain DLL names

lld/Common/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ set_property(SOURCE Version.cpp APPEND PROPERTY
2929

3030
add_lld_library(lldCommon
3131
Args.cpp
32+
DWARF.cpp
3233
ErrorHandler.cpp
3334
Filesystem.cpp
3435
Memory.cpp
@@ -46,6 +47,7 @@ add_lld_library(lldCommon
4647
LINK_COMPONENTS
4748
Codegen
4849
Core
50+
DebugInfoDWARF
4951
Demangle
5052
MC
5153
Option

lld/Common/DWARF.cpp

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//===- DWARF.cpp ----------------------------------------------------------===//
2+
//
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
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "lld/Common/DWARF.h"
10+
#include "lld/Common/ErrorHandler.h"
11+
12+
using namespace llvm;
13+
14+
namespace lld {
15+
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()); });
22+
};
23+
Expected<const DWARFDebugLine::LineTable *> expectedLT =
24+
dwarf->getLineTableForUnit(cu.get(), report);
25+
const DWARFDebugLine::LineTable *lt = nullptr;
26+
if (expectedLT)
27+
lt = *expectedLT;
28+
else
29+
report(expectedLT.takeError());
30+
if (!lt)
31+
continue;
32+
lineTables.push_back(lt);
33+
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)
39+
continue;
40+
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
43+
// linked.
44+
if (!dwarf::toUnsigned(die.find(dwarf::DW_AT_external), 0))
45+
continue;
46+
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))
50+
continue;
51+
52+
// Get the line number on which the variable is declared.
53+
unsigned line = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_line), 0);
54+
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.
61+
StringRef name =
62+
dwarf::toString(die.find(dwarf::DW_AT_linkage_name),
63+
dwarf::toString(die.find(dwarf::DW_AT_name), ""));
64+
if (!name.empty())
65+
variableLoc.insert({name, {lt, file, line}});
66+
}
67+
}
68+
}
69+
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())
77+
return None;
78+
79+
// Take file name string from line table.
80+
std::string fileName;
81+
if (!it->second.lt->getFileNameByIndex(
82+
it->second.file, {},
83+
DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, fileName))
84+
return None;
85+
86+
return std::make_pair(fileName, it->second.line);
87+
}
88+
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) {
93+
DILineInfo info;
94+
for (const llvm::DWARFDebugLine::LineTable *lt : lineTables) {
95+
if (lt->getFileLineInfoForAddress(
96+
{offset, sectionIndex}, nullptr,
97+
DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, info))
98+
return info;
99+
}
100+
return None;
101+
}
102+
103+
} // namespace lld

lld/ELF/InputFiles.cpp

+4-73
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
#include "lld/Common/Memory.h"
1818
#include "llvm/ADT/STLExtras.h"
1919
#include "llvm/CodeGen/Analysis.h"
20-
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
2120
#include "llvm/IR/LLVMContext.h"
2221
#include "llvm/IR/Module.h"
2322
#include "llvm/LTO/LTO.h"
@@ -252,57 +251,8 @@ std::string InputFile::getSrcMsg(const Symbol &Sym, InputSectionBase &Sec,
252251
}
253252

254253
template <class ELFT> void ObjFile<ELFT>::initializeDwarf() {
255-
Dwarf = llvm::make_unique<DWARFContext>(make_unique<LLDDwarfObj<ELFT>>(this));
256-
for (std::unique_ptr<DWARFUnit> &CU : Dwarf->compile_units()) {
257-
auto Report = [](Error Err) {
258-
handleAllErrors(std::move(Err),
259-
[](ErrorInfoBase &Info) { warn(Info.message()); });
260-
};
261-
Expected<const DWARFDebugLine::LineTable *> ExpectedLT =
262-
Dwarf->getLineTableForUnit(CU.get(), Report);
263-
const DWARFDebugLine::LineTable *LT = nullptr;
264-
if (ExpectedLT)
265-
LT = *ExpectedLT;
266-
else
267-
Report(ExpectedLT.takeError());
268-
if (!LT)
269-
continue;
270-
LineTables.push_back(LT);
271-
272-
// Loop over variable records and insert them to VariableLoc.
273-
for (const auto &Entry : CU->dies()) {
274-
DWARFDie Die(CU.get(), &Entry);
275-
// Skip all tags that are not variables.
276-
if (Die.getTag() != dwarf::DW_TAG_variable)
277-
continue;
278-
279-
// Skip if a local variable because we don't need them for generating
280-
// error messages. In general, only non-local symbols can fail to be
281-
// linked.
282-
if (!dwarf::toUnsigned(Die.find(dwarf::DW_AT_external), 0))
283-
continue;
284-
285-
// Get the source filename index for the variable.
286-
unsigned File = dwarf::toUnsigned(Die.find(dwarf::DW_AT_decl_file), 0);
287-
if (!LT->hasFileAtIndex(File))
288-
continue;
289-
290-
// Get the line number on which the variable is declared.
291-
unsigned Line = dwarf::toUnsigned(Die.find(dwarf::DW_AT_decl_line), 0);
292-
293-
// Here we want to take the variable name to add it into VariableLoc.
294-
// Variable can have regular and linkage name associated. At first, we try
295-
// to get linkage name as it can be different, for example when we have
296-
// two variables in different namespaces of the same object. Use common
297-
// name otherwise, but handle the case when it also absent in case if the
298-
// input object file lacks some debug info.
299-
StringRef Name =
300-
dwarf::toString(Die.find(dwarf::DW_AT_linkage_name),
301-
dwarf::toString(Die.find(dwarf::DW_AT_name), ""));
302-
if (!Name.empty())
303-
VariableLoc.insert({Name, {LT, File, Line}});
304-
}
305-
}
254+
dwarf = make<DWARFCache>(std::make_unique<DWARFContext>(
255+
std::make_unique<LLDDwarfObj<ELFT>>(this)));
306256
}
307257

308258
// Returns the pair of file name and line number describing location of data
@@ -312,19 +262,7 @@ Optional<std::pair<std::string, unsigned>>
312262
ObjFile<ELFT>::getVariableLoc(StringRef Name) {
313263
llvm::call_once(InitDwarfLine, [this]() { initializeDwarf(); });
314264

315-
// Return if we have no debug information about data object.
316-
auto It = VariableLoc.find(Name);
317-
if (It == VariableLoc.end())
318-
return None;
319-
320-
// Take file name string from line table.
321-
std::string FileName;
322-
if (!It->second.LT->getFileNameByIndex(
323-
It->second.File, nullptr,
324-
DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FileName))
325-
return None;
326-
327-
return std::make_pair(FileName, It->second.Line);
265+
return dwarf->getVariableLoc(Name);
328266
}
329267

330268
// Returns source line information for a given offset
@@ -346,14 +284,7 @@ Optional<DILineInfo> ObjFile<ELFT>::getDILineInfo(InputSectionBase *S,
346284

347285
// Use fake address calcuated by adding section file offset and offset in
348286
// section. See comments for ObjectInfo class.
349-
DILineInfo Info;
350-
for (const llvm::DWARFDebugLine::LineTable *LT : LineTables) {
351-
if (LT->getFileLineInfoForAddress(
352-
{S->getOffsetInFile() + Offset, SectionIndex}, nullptr,
353-
DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, Info))
354-
return Info;
355-
}
356-
return None;
287+
return dwarf->getDILineInfo(S->getOffsetInFile() + Offset, SectionIndex);
357288
}
358289

359290
// Returns "<internal>", "foo.a(bar.o)" or "baz.o".

lld/ELF/InputFiles.h

+2-10
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010
#define LLD_ELF_INPUT_FILES_H
1111

1212
#include "Config.h"
13+
#include "lld/Common/DWARF.h"
1314
#include "lld/Common/ErrorHandler.h"
1415
#include "lld/Common/LLVM.h"
1516
#include "lld/Common/Reproduce.h"
1617
#include "llvm/ADT/CachedHashString.h"
1718
#include "llvm/ADT/DenseSet.h"
1819
#include "llvm/ADT/STLExtras.h"
19-
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
2020
#include "llvm/IR/Comdat.h"
2121
#include "llvm/Object/Archive.h"
2222
#include "llvm/Object/ELF.h"
@@ -26,7 +26,6 @@
2626

2727
namespace llvm {
2828
class TarWriter;
29-
struct DILineInfo;
3029
namespace lto {
3130
class InputFile;
3231
}
@@ -284,14 +283,7 @@ template <class ELFT> class ObjFile : public ELFFileBase {
284283
// reporting. Linker may find reasonable number of errors in a
285284
// single object file, so we cache debugging information in order to
286285
// parse it only once for each object file we link.
287-
std::unique_ptr<llvm::DWARFContext> Dwarf;
288-
std::vector<const llvm::DWARFDebugLine::LineTable *> LineTables;
289-
struct VarLoc {
290-
const llvm::DWARFDebugLine::LineTable *LT;
291-
unsigned File;
292-
unsigned Line;
293-
};
294-
llvm::DenseMap<StringRef, VarLoc> VariableLoc;
286+
DWARFCache *dwarf;
295287
llvm::once_flag InitDwarfLine;
296288
};
297289

lld/include/lld/Common/DWARF.h

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//===- DWARF.h --------------------------------------------------*- C++ -*-===//
2+
//
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
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLD_DWARF_H
10+
#define LLD_DWARF_H
11+
12+
#include "lld/Common/LLVM.h"
13+
#include "llvm/ADT/DenseMap.h"
14+
#include "llvm/ADT/StringRef.h"
15+
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
16+
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
17+
#include <memory>
18+
#include <string>
19+
20+
namespace llvm {
21+
struct DILineInfo;
22+
} // namespace llvm
23+
24+
namespace lld {
25+
26+
class DWARFCache {
27+
public:
28+
DWARFCache(std::unique_ptr<llvm::DWARFContext> dwarf);
29+
llvm::Optional<llvm::DILineInfo> getDILineInfo(uint64_t offset,
30+
uint64_t sectionIndex);
31+
llvm::Optional<std::pair<std::string, unsigned>>
32+
getVariableLoc(StringRef name);
33+
34+
private:
35+
std::unique_ptr<llvm::DWARFContext> dwarf;
36+
std::vector<const llvm::DWARFDebugLine::LineTable *> lineTables;
37+
struct VarLoc {
38+
const llvm::DWARFDebugLine::LineTable *lt;
39+
unsigned file;
40+
unsigned line;
41+
};
42+
llvm::DenseMap<StringRef, VarLoc> variableLoc;
43+
};
44+
45+
} // namespace lld
46+
47+
#endif

0 commit comments

Comments
 (0)