aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Storsjo <martin@martin.st>2019-10-21 08:01:52 +0000
committerMartin Storsjo <martin@martin.st>2019-10-21 08:01:52 +0000
commit3a192b4c7952e420f700884089bcd486ece23df5 (patch)
treedbb087294cfe8d403398d5ed734d2fca12ff7b5a
parent63c19e2f97d3b6a83803a14c27983211a32bad25 (diff)
[LLD] Move duplicated dwarf parsing code to the Common library. NFC.
Differential Revision: https://reviews.llvm.org/D69197 git-svn-id: https://llvm.org/svn/llvm-project/lld/trunk@375390 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--COFF/InputFiles.cpp73
-rw-r--r--COFF/InputFiles.h12
-rw-r--r--Common/CMakeLists.txt2
-rw-r--r--Common/DWARF.cpp103
-rw-r--r--ELF/InputFiles.cpp77
-rw-r--r--ELF/InputFiles.h12
-rw-r--r--include/lld/Common/DWARF.h47
7 files changed, 164 insertions, 162 deletions
diff --git a/COFF/InputFiles.cpp b/COFF/InputFiles.cpp
index 8770a870d..4097cda59 100644
--- a/COFF/InputFiles.cpp
+++ b/COFF/InputFiles.cpp
@@ -795,81 +795,16 @@ void ObjFile::initializeDependencies() {
Optional<std::pair<StringRef, uint32_t>>
ObjFile::getVariableLocation(StringRef var) {
if (!dwarf) {
- dwarf = DWARFContext::create(*getCOFFObj());
+ dwarf = make<DWARFCache>(DWARFContext::create(*getCOFFObj()));
if (!dwarf)
return None;
- initializeDwarf();
}
if (config->machine == I386)
var.consume_front("_");
- auto it = variableLoc.find(var);
- if (it == variableLoc.end())
+ Optional<std::pair<std::string, unsigned>> ret = dwarf->getVariableLoc(var);
+ if (!ret)
return None;
-
- // Take file name string from line table.
- std::string fileName;
- if (!it->second.lt->getFileNameByIndex(
- it->second.file, {},
- DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, fileName))
- return None;
-
- return std::make_pair(saver.save(fileName), it->second.line);
-}
-
-// Used only for DWARF debug info, which is not common (except in MinGW
-// environments). This initializes the dwarf, lineTables and variableLoc
-// members.
-void ObjFile::initializeDwarf() {
- for (std::unique_ptr<DWARFUnit> &cu : dwarf->compile_units()) {
- auto report = [](Error err) {
- handleAllErrors(std::move(err),
- [](ErrorInfoBase &info) { warn(info.message()); });
- };
- Expected<const DWARFDebugLine::LineTable *> expectedLT =
- dwarf->getLineTableForUnit(cu.get(), report);
- const DWARFDebugLine::LineTable *lt = nullptr;
- if (expectedLT)
- lt = *expectedLT;
- else
- report(expectedLT.takeError());
- if (!lt)
- continue;
- lineTables.push_back(lt);
-
- // Loop over variable records and insert them to variableLoc.
- for (const auto &entry : cu->dies()) {
- DWARFDie die(cu.get(), &entry);
- // Skip all tags that are not variables.
- if (die.getTag() != dwarf::DW_TAG_variable)
- continue;
-
- // Skip if a local variable because we don't need them for generating
- // error messages. In general, only non-local symbols can fail to be
- // linked.
- if (!dwarf::toUnsigned(die.find(dwarf::DW_AT_external), 0))
- continue;
-
- // Get the source filename index for the variable.
- unsigned file = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_file), 0);
- if (!lt->hasFileAtIndex(file))
- continue;
-
- // Get the line number on which the variable is declared.
- unsigned line = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_line), 0);
-
- // Here we want to take the variable name to add it into variableLoc.
- // Variable can have regular and linkage name associated. At first, we try
- // to get linkage name as it can be different, for example when we have
- // two variables in different namespaces of the same object. Use common
- // name otherwise, but handle the case when it also absent in case if the
- // input object file lacks some debug info.
- StringRef name =
- dwarf::toString(die.find(dwarf::DW_AT_linkage_name),
- dwarf::toString(die.find(dwarf::DW_AT_name), ""));
- if (!name.empty())
- variableLoc.insert({name, {lt, file, line}});
- }
- }
+ return std::make_pair(saver.save(ret->first), ret->second);
}
StringRef ltrim1(StringRef s, const char *chars) {
diff --git a/COFF/InputFiles.h b/COFF/InputFiles.h
index d3f4cd7bb..66249715e 100644
--- a/COFF/InputFiles.h
+++ b/COFF/InputFiles.h
@@ -10,13 +10,13 @@
#define LLD_COFF_INPUT_FILES_H
#include "Config.h"
+#include "lld/Common/DWARF.h"
#include "lld/Common/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/LTO/LTO.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/COFF.h"
@@ -216,7 +216,6 @@ private:
void initializeSymbols();
void initializeFlags();
void initializeDependencies();
- void initializeDwarf();
SectionChunk *
readSection(uint32_t sectionNumber,
@@ -291,14 +290,7 @@ private:
// symbols in the real symbol table) are filled with null pointers.
std::vector<Symbol *> symbols;
- std::unique_ptr<llvm::DWARFContext> dwarf;
- std::vector<const llvm::DWARFDebugLine::LineTable *> lineTables;
- struct VarLoc {
- const llvm::DWARFDebugLine::LineTable *lt;
- unsigned file;
- unsigned line;
- };
- llvm::DenseMap<StringRef, VarLoc> variableLoc;
+ DWARFCache *dwarf;
};
// This type represents import library members that contain DLL names
diff --git a/Common/CMakeLists.txt b/Common/CMakeLists.txt
index 70849cc7b..1a04a8074 100644
--- a/Common/CMakeLists.txt
+++ b/Common/CMakeLists.txt
@@ -29,6 +29,7 @@ set_property(SOURCE Version.cpp APPEND PROPERTY
add_lld_library(lldCommon
Args.cpp
+ DWARF.cpp
ErrorHandler.cpp
Filesystem.cpp
Memory.cpp
@@ -46,6 +47,7 @@ add_lld_library(lldCommon
LINK_COMPONENTS
Codegen
Core
+ DebugInfoDWARF
Demangle
MC
Option
diff --git a/Common/DWARF.cpp b/Common/DWARF.cpp
new file mode 100644
index 000000000..077adbcaf
--- /dev/null
+++ b/Common/DWARF.cpp
@@ -0,0 +1,103 @@
+//===- DWARF.cpp ----------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/Common/DWARF.h"
+#include "lld/Common/ErrorHandler.h"
+
+using namespace llvm;
+
+namespace lld {
+
+DWARFCache::DWARFCache(std::unique_ptr<llvm::DWARFContext> d)
+ : dwarf(std::move(d)) {
+ for (std::unique_ptr<DWARFUnit> &cu : dwarf->compile_units()) {
+ auto report = [](Error err) {
+ handleAllErrors(std::move(err),
+ [](ErrorInfoBase &info) { warn(info.message()); });
+ };
+ Expected<const DWARFDebugLine::LineTable *> expectedLT =
+ dwarf->getLineTableForUnit(cu.get(), report);
+ const DWARFDebugLine::LineTable *lt = nullptr;
+ if (expectedLT)
+ lt = *expectedLT;
+ else
+ report(expectedLT.takeError());
+ if (!lt)
+ continue;
+ lineTables.push_back(lt);
+
+ // Loop over variable records and insert them to variableLoc.
+ for (const auto &entry : cu->dies()) {
+ DWARFDie die(cu.get(), &entry);
+ // Skip all tags that are not variables.
+ if (die.getTag() != dwarf::DW_TAG_variable)
+ continue;
+
+ // Skip if a local variable because we don't need them for generating
+ // error messages. In general, only non-local symbols can fail to be
+ // linked.
+ if (!dwarf::toUnsigned(die.find(dwarf::DW_AT_external), 0))
+ continue;
+
+ // Get the source filename index for the variable.
+ unsigned file = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_file), 0);
+ if (!lt->hasFileAtIndex(file))
+ continue;
+
+ // Get the line number on which the variable is declared.
+ unsigned line = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_line), 0);
+
+ // Here we want to take the variable name to add it into variableLoc.
+ // Variable can have regular and linkage name associated. At first, we try
+ // to get linkage name as it can be different, for example when we have
+ // two variables in different namespaces of the same object. Use common
+ // name otherwise, but handle the case when it also absent in case if the
+ // input object file lacks some debug info.
+ StringRef name =
+ dwarf::toString(die.find(dwarf::DW_AT_linkage_name),
+ dwarf::toString(die.find(dwarf::DW_AT_name), ""));
+ if (!name.empty())
+ variableLoc.insert({name, {lt, file, line}});
+ }
+ }
+}
+
+// Returns the pair of file name and line number describing location of data
+// object (variable, array, etc) definition.
+Optional<std::pair<std::string, unsigned>>
+DWARFCache::getVariableLoc(StringRef name) {
+ // Return if we have no debug information about data object.
+ auto it = variableLoc.find(name);
+ if (it == variableLoc.end())
+ return None;
+
+ // Take file name string from line table.
+ std::string fileName;
+ if (!it->second.lt->getFileNameByIndex(
+ it->second.file, {},
+ DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, fileName))
+ return None;
+
+ return std::make_pair(fileName, it->second.line);
+}
+
+// Returns source line information for a given offset
+// using DWARF debug info.
+Optional<DILineInfo> DWARFCache::getDILineInfo(uint64_t offset,
+ uint64_t sectionIndex) {
+ DILineInfo info;
+ for (const llvm::DWARFDebugLine::LineTable *lt : lineTables) {
+ if (lt->getFileLineInfoForAddress(
+ {offset, sectionIndex}, nullptr,
+ DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, info))
+ return info;
+ }
+ return None;
+}
+
+} // namespace lld
diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp
index b0389ccf1..fdf935a30 100644
--- a/ELF/InputFiles.cpp
+++ b/ELF/InputFiles.cpp
@@ -17,7 +17,6 @@
#include "lld/Common/Memory.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/Analysis.h"
-#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/LTO/LTO.h"
@@ -265,57 +264,8 @@ std::string InputFile::getSrcMsg(const Symbol &sym, InputSectionBase &sec,
}
template <class ELFT> void ObjFile<ELFT>::initializeDwarf() {
- dwarf = std::make_unique<DWARFContext>(std::make_unique<LLDDwarfObj<ELFT>>(this));
- for (std::unique_ptr<DWARFUnit> &cu : dwarf->compile_units()) {
- auto report = [](Error err) {
- handleAllErrors(std::move(err),
- [](ErrorInfoBase &info) { warn(info.message()); });
- };
- Expected<const DWARFDebugLine::LineTable *> expectedLT =
- dwarf->getLineTableForUnit(cu.get(), report);
- const DWARFDebugLine::LineTable *lt = nullptr;
- if (expectedLT)
- lt = *expectedLT;
- else
- report(expectedLT.takeError());
- if (!lt)
- continue;
- lineTables.push_back(lt);
-
- // Loop over variable records and insert them to variableLoc.
- for (const auto &entry : cu->dies()) {
- DWARFDie die(cu.get(), &entry);
- // Skip all tags that are not variables.
- if (die.getTag() != dwarf::DW_TAG_variable)
- continue;
-
- // Skip if a local variable because we don't need them for generating
- // error messages. In general, only non-local symbols can fail to be
- // linked.
- if (!dwarf::toUnsigned(die.find(dwarf::DW_AT_external), 0))
- continue;
-
- // Get the source filename index for the variable.
- unsigned file = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_file), 0);
- if (!lt->hasFileAtIndex(file))
- continue;
-
- // Get the line number on which the variable is declared.
- unsigned line = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_line), 0);
-
- // Here we want to take the variable name to add it into variableLoc.
- // Variable can have regular and linkage name associated. At first, we try
- // to get linkage name as it can be different, for example when we have
- // two variables in different namespaces of the same object. Use common
- // name otherwise, but handle the case when it also absent in case if the
- // input object file lacks some debug info.
- StringRef name =
- dwarf::toString(die.find(dwarf::DW_AT_linkage_name),
- dwarf::toString(die.find(dwarf::DW_AT_name), ""));
- if (!name.empty())
- variableLoc.insert({name, {lt, file, line}});
- }
- }
+ dwarf = make<DWARFCache>(std::make_unique<DWARFContext>(
+ std::make_unique<LLDDwarfObj<ELFT>>(this)));
}
// Returns the pair of file name and line number describing location of data
@@ -325,19 +275,7 @@ Optional<std::pair<std::string, unsigned>>
ObjFile<ELFT>::getVariableLoc(StringRef name) {
llvm::call_once(initDwarfLine, [this]() { initializeDwarf(); });
- // Return if we have no debug information about data object.
- auto it = variableLoc.find(name);
- if (it == variableLoc.end())
- return None;
-
- // Take file name string from line table.
- std::string fileName;
- if (!it->second.lt->getFileNameByIndex(
- it->second.file, {},
- DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, fileName))
- return None;
-
- return std::make_pair(fileName, it->second.line);
+ return dwarf->getVariableLoc(name);
}
// Returns source line information for a given offset
@@ -359,14 +297,7 @@ Optional<DILineInfo> ObjFile<ELFT>::getDILineInfo(InputSectionBase *s,
// Use fake address calcuated by adding section file offset and offset in
// section. See comments for ObjectInfo class.
- DILineInfo info;
- for (const llvm::DWARFDebugLine::LineTable *lt : lineTables) {
- if (lt->getFileLineInfoForAddress(
- {s->getOffsetInFile() + offset, sectionIndex}, nullptr,
- DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, info))
- return info;
- }
- return None;
+ return dwarf->getDILineInfo(s->getOffsetInFile() + offset, sectionIndex);
}
ELFFileBase::ELFFileBase(Kind k, MemoryBufferRef mb) : InputFile(k, mb) {
diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h
index 1c78654d0..cde6bc617 100644
--- a/ELF/InputFiles.h
+++ b/ELF/InputFiles.h
@@ -10,13 +10,13 @@
#define LLD_ELF_INPUT_FILES_H
#include "Config.h"
+#include "lld/Common/DWARF.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/LLVM.h"
#include "lld/Common/Reproduce.h"
#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
#include "llvm/IR/Comdat.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ELF.h"
@@ -26,7 +26,6 @@
namespace llvm {
class TarWriter;
-struct DILineInfo;
namespace lto {
class InputFile;
}
@@ -282,14 +281,7 @@ private:
// reporting. Linker may find reasonable number of errors in a
// single object file, so we cache debugging information in order to
// parse it only once for each object file we link.
- std::unique_ptr<llvm::DWARFContext> dwarf;
- std::vector<const llvm::DWARFDebugLine::LineTable *> lineTables;
- struct VarLoc {
- const llvm::DWARFDebugLine::LineTable *lt;
- unsigned file;
- unsigned line;
- };
- llvm::DenseMap<StringRef, VarLoc> variableLoc;
+ DWARFCache *dwarf;
llvm::once_flag initDwarfLine;
};
diff --git a/include/lld/Common/DWARF.h b/include/lld/Common/DWARF.h
new file mode 100644
index 000000000..f0d3d2fbd
--- /dev/null
+++ b/include/lld/Common/DWARF.h
@@ -0,0 +1,47 @@
+//===- DWARF.h --------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_DWARF_H
+#define LLD_DWARF_H
+
+#include "lld/Common/LLVM.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
+#include <memory>
+#include <string>
+
+namespace llvm {
+struct DILineInfo;
+} // namespace llvm
+
+namespace lld {
+
+class DWARFCache {
+public:
+ DWARFCache(std::unique_ptr<llvm::DWARFContext> dwarf);
+ llvm::Optional<llvm::DILineInfo> getDILineInfo(uint64_t offset,
+ uint64_t sectionIndex);
+ llvm::Optional<std::pair<std::string, unsigned>>
+ getVariableLoc(StringRef name);
+
+private:
+ std::unique_ptr<llvm::DWARFContext> dwarf;
+ std::vector<const llvm::DWARFDebugLine::LineTable *> lineTables;
+ struct VarLoc {
+ const llvm::DWARFDebugLine::LineTable *lt;
+ unsigned file;
+ unsigned line;
+ };
+ llvm::DenseMap<StringRef, VarLoc> variableLoc;
+};
+
+} // namespace lld
+
+#endif