Skip to content

Commit 908b780

Browse files
committed
[LLD] Move duplicated dwarf parsing code to the Common library. NFC.
Differential Revision: https://reviews.llvm.org/D69197 llvm-svn: 375390
1 parent 5e5af53 commit 908b780

File tree

7 files changed

+164
-162
lines changed

7 files changed

+164
-162
lines changed

lld/COFF/InputFiles.cpp

+4-69
Original file line numberDiff line numberDiff line change
@@ -795,81 +795,16 @@ void ObjFile::initializeDependencies() {
795795
Optional<std::pair<StringRef, uint32_t>>
796796
ObjFile::getVariableLocation(StringRef var) {
797797
if (!dwarf) {
798-
dwarf = DWARFContext::create(*getCOFFObj());
798+
dwarf = make<DWARFCache>(DWARFContext::create(*getCOFFObj()));
799799
if (!dwarf)
800800
return None;
801-
initializeDwarf();
802801
}
803802
if (config->machine == I386)
804803
var.consume_front("_");
805-
auto it = variableLoc.find(var);
806-
if (it == variableLoc.end())
804+
Optional<std::pair<std::string, unsigned>> ret = dwarf->getVariableLoc(var);
805+
if (!ret)
807806
return None;
808-
809-
// Take file name string from line table.
810-
std::string fileName;
811-
if (!it->second.lt->getFileNameByIndex(
812-
it->second.file, {},
813-
DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, fileName))
814-
return None;
815-
816-
return std::make_pair(saver.save(fileName), it->second.line);
817-
}
818-
819-
// Used only for DWARF debug info, which is not common (except in MinGW
820-
// environments). This initializes the dwarf, lineTables and variableLoc
821-
// members.
822-
void ObjFile::initializeDwarf() {
823-
for (std::unique_ptr<DWARFUnit> &cu : dwarf->compile_units()) {
824-
auto report = [](Error err) {
825-
handleAllErrors(std::move(err),
826-
[](ErrorInfoBase &info) { warn(info.message()); });
827-
};
828-
Expected<const DWARFDebugLine::LineTable *> expectedLT =
829-
dwarf->getLineTableForUnit(cu.get(), report);
830-
const DWARFDebugLine::LineTable *lt = nullptr;
831-
if (expectedLT)
832-
lt = *expectedLT;
833-
else
834-
report(expectedLT.takeError());
835-
if (!lt)
836-
continue;
837-
lineTables.push_back(lt);
838-
839-
// Loop over variable records and insert them to variableLoc.
840-
for (const auto &entry : cu->dies()) {
841-
DWARFDie die(cu.get(), &entry);
842-
// Skip all tags that are not variables.
843-
if (die.getTag() != dwarf::DW_TAG_variable)
844-
continue;
845-
846-
// Skip if a local variable because we don't need them for generating
847-
// error messages. In general, only non-local symbols can fail to be
848-
// linked.
849-
if (!dwarf::toUnsigned(die.find(dwarf::DW_AT_external), 0))
850-
continue;
851-
852-
// Get the source filename index for the variable.
853-
unsigned file = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_file), 0);
854-
if (!lt->hasFileAtIndex(file))
855-
continue;
856-
857-
// Get the line number on which the variable is declared.
858-
unsigned line = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_line), 0);
859-
860-
// Here we want to take the variable name to add it into variableLoc.
861-
// Variable can have regular and linkage name associated. At first, we try
862-
// to get linkage name as it can be different, for example when we have
863-
// two variables in different namespaces of the same object. Use common
864-
// name otherwise, but handle the case when it also absent in case if the
865-
// input object file lacks some debug info.
866-
StringRef name =
867-
dwarf::toString(die.find(dwarf::DW_AT_linkage_name),
868-
dwarf::toString(die.find(dwarf::DW_AT_name), ""));
869-
if (!name.empty())
870-
variableLoc.insert({name, {lt, file, line}});
871-
}
872-
}
807+
return std::make_pair(saver.save(ret->first), ret->second);
873808
}
874809

875810
StringRef ltrim1(StringRef s, const char *chars) {

lld/COFF/InputFiles.h

+2-10
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
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"
1617
#include "llvm/ADT/DenseSet.h"
1718
#include "llvm/BinaryFormat/Magic.h"
1819
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
19-
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
2020
#include "llvm/LTO/LTO.h"
2121
#include "llvm/Object/Archive.h"
2222
#include "llvm/Object/COFF.h"
@@ -216,7 +216,6 @@ class ObjFile : public InputFile {
216216
void initializeSymbols();
217217
void initializeFlags();
218218
void initializeDependencies();
219-
void initializeDwarf();
220219

221220
SectionChunk *
222221
readSection(uint32_t sectionNumber,
@@ -291,14 +290,7 @@ class ObjFile : public InputFile {
291290
// symbols in the real symbol table) are filled with null pointers.
292291
std::vector<Symbol *> symbols;
293292

294-
std::unique_ptr<llvm::DWARFContext> dwarf;
295-
std::vector<const llvm::DWARFDebugLine::LineTable *> lineTables;
296-
struct VarLoc {
297-
const llvm::DWARFDebugLine::LineTable *lt;
298-
unsigned file;
299-
unsigned line;
300-
};
301-
llvm::DenseMap<StringRef, VarLoc> variableLoc;
293+
DWARFCache *dwarf;
302294
};
303295

304296
// 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"
@@ -265,57 +264,8 @@ std::string InputFile::getSrcMsg(const Symbol &sym, InputSectionBase &sec,
265264
}
266265

267266
template <class ELFT> void ObjFile<ELFT>::initializeDwarf() {
268-
dwarf = std::make_unique<DWARFContext>(std::make_unique<LLDDwarfObj<ELFT>>(this));
269-
for (std::unique_ptr<DWARFUnit> &cu : dwarf->compile_units()) {
270-
auto report = [](Error err) {
271-
handleAllErrors(std::move(err),
272-
[](ErrorInfoBase &info) { warn(info.message()); });
273-
};
274-
Expected<const DWARFDebugLine::LineTable *> expectedLT =
275-
dwarf->getLineTableForUnit(cu.get(), report);
276-
const DWARFDebugLine::LineTable *lt = nullptr;
277-
if (expectedLT)
278-
lt = *expectedLT;
279-
else
280-
report(expectedLT.takeError());
281-
if (!lt)
282-
continue;
283-
lineTables.push_back(lt);
284-
285-
// Loop over variable records and insert them to variableLoc.
286-
for (const auto &entry : cu->dies()) {
287-
DWARFDie die(cu.get(), &entry);
288-
// Skip all tags that are not variables.
289-
if (die.getTag() != dwarf::DW_TAG_variable)
290-
continue;
291-
292-
// Skip if a local variable because we don't need them for generating
293-
// error messages. In general, only non-local symbols can fail to be
294-
// linked.
295-
if (!dwarf::toUnsigned(die.find(dwarf::DW_AT_external), 0))
296-
continue;
297-
298-
// Get the source filename index for the variable.
299-
unsigned file = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_file), 0);
300-
if (!lt->hasFileAtIndex(file))
301-
continue;
302-
303-
// Get the line number on which the variable is declared.
304-
unsigned line = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_line), 0);
305-
306-
// Here we want to take the variable name to add it into variableLoc.
307-
// Variable can have regular and linkage name associated. At first, we try
308-
// to get linkage name as it can be different, for example when we have
309-
// two variables in different namespaces of the same object. Use common
310-
// name otherwise, but handle the case when it also absent in case if the
311-
// input object file lacks some debug info.
312-
StringRef name =
313-
dwarf::toString(die.find(dwarf::DW_AT_linkage_name),
314-
dwarf::toString(die.find(dwarf::DW_AT_name), ""));
315-
if (!name.empty())
316-
variableLoc.insert({name, {lt, file, line}});
317-
}
318-
}
267+
dwarf = make<DWARFCache>(std::make_unique<DWARFContext>(
268+
std::make_unique<LLDDwarfObj<ELFT>>(this)));
319269
}
320270

321271
// Returns the pair of file name and line number describing location of data
@@ -325,19 +275,7 @@ Optional<std::pair<std::string, unsigned>>
325275
ObjFile<ELFT>::getVariableLoc(StringRef name) {
326276
llvm::call_once(initDwarfLine, [this]() { initializeDwarf(); });
327277

328-
// Return if we have no debug information about data object.
329-
auto it = variableLoc.find(name);
330-
if (it == variableLoc.end())
331-
return None;
332-
333-
// Take file name string from line table.
334-
std::string fileName;
335-
if (!it->second.lt->getFileNameByIndex(
336-
it->second.file, {},
337-
DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, fileName))
338-
return None;
339-
340-
return std::make_pair(fileName, it->second.line);
278+
return dwarf->getVariableLoc(name);
341279
}
342280

343281
// Returns source line information for a given offset
@@ -359,14 +297,7 @@ Optional<DILineInfo> ObjFile<ELFT>::getDILineInfo(InputSectionBase *s,
359297

360298
// Use fake address calcuated by adding section file offset and offset in
361299
// section. See comments for ObjectInfo class.
362-
DILineInfo info;
363-
for (const llvm::DWARFDebugLine::LineTable *lt : lineTables) {
364-
if (lt->getFileLineInfoForAddress(
365-
{s->getOffsetInFile() + offset, sectionIndex}, nullptr,
366-
DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, info))
367-
return info;
368-
}
369-
return None;
300+
return dwarf->getDILineInfo(s->getOffsetInFile() + offset, sectionIndex);
370301
}
371302

372303
ELFFileBase::ELFFileBase(Kind k, MemoryBufferRef mb) : InputFile(k, mb) {

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
}
@@ -282,14 +281,7 @@ template <class ELFT> class ObjFile : public ELFFileBase {
282281
// reporting. Linker may find reasonable number of errors in a
283282
// single object file, so we cache debugging information in order to
284283
// parse it only once for each object file we link.
285-
std::unique_ptr<llvm::DWARFContext> dwarf;
286-
std::vector<const llvm::DWARFDebugLine::LineTable *> lineTables;
287-
struct VarLoc {
288-
const llvm::DWARFDebugLine::LineTable *lt;
289-
unsigned file;
290-
unsigned line;
291-
};
292-
llvm::DenseMap<StringRef, VarLoc> variableLoc;
284+
DWARFCache *dwarf;
293285
llvm::once_flag initDwarfLine;
294286
};
295287

0 commit comments

Comments
 (0)