summaryrefslogtreecommitdiff
path: root/ELF/SyntheticSections.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ELF/SyntheticSections.cpp')
-rw-r--r--ELF/SyntheticSections.cpp174
1 files changed, 98 insertions, 76 deletions
diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp
index 223fc9a0fd078..5cd6c5f2b914d 100644
--- a/ELF/SyntheticSections.cpp
+++ b/ELF/SyntheticSections.cpp
@@ -27,9 +27,9 @@
#include "Threads.h"
#include "Writer.h"
#include "lld/Config/Version.h"
+#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
#include "llvm/Object/ELFObjectFile.h"
-#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/RandomNumberGenerator.h"
@@ -1691,49 +1691,44 @@ static uint32_t hash(StringRef Str) {
return R;
}
-static std::vector<std::pair<uint64_t, uint64_t>>
-readCuList(DWARFContext &Dwarf, InputSection *Sec) {
- std::vector<std::pair<uint64_t, uint64_t>> Ret;
+static std::vector<CompilationUnitEntry> readCuList(DWARFContext &Dwarf,
+ InputSection *Sec) {
+ std::vector<CompilationUnitEntry> Ret;
for (std::unique_ptr<DWARFCompileUnit> &CU : Dwarf.compile_units())
Ret.push_back({Sec->OutSecOff + CU->getOffset(), CU->getLength() + 4});
return Ret;
}
-static InputSection *findSection(ArrayRef<InputSectionBase *> Arr,
- uint64_t Offset) {
- for (InputSectionBase *S : Arr)
- if (auto *IS = dyn_cast_or_null<InputSection>(S))
- if (IS != &InputSection::Discarded && IS->Live &&
- Offset >= IS->getOffsetInFile() &&
- Offset < IS->getOffsetInFile() + IS->getSize())
- return IS;
- return nullptr;
-}
-
-static std::vector<AddressEntry>
-readAddressArea(DWARFContext &Dwarf, InputSection *Sec, size_t CurrentCU) {
+static std::vector<AddressEntry> readAddressArea(DWARFContext &Dwarf,
+ InputSection *Sec) {
std::vector<AddressEntry> Ret;
+ uint32_t CurrentCu = 0;
for (std::unique_ptr<DWARFCompileUnit> &CU : Dwarf.compile_units()) {
DWARFAddressRangesVector Ranges;
CU->collectAddressRanges(Ranges);
ArrayRef<InputSectionBase *> Sections = Sec->File->getSections();
- for (DWARFAddressRange &R : Ranges)
- if (InputSection *S = findSection(Sections, R.LowPC))
- Ret.push_back({S, R.LowPC - S->getOffsetInFile(),
- R.HighPC - S->getOffsetInFile(), CurrentCU});
- ++CurrentCU;
+ for (DWARFAddressRange &R : Ranges) {
+ InputSectionBase *S = Sections[R.SectionIndex];
+ if (!S || S == &InputSection::Discarded || !S->Live)
+ continue;
+ // Range list with zero size has no effect.
+ if (R.LowPC == R.HighPC)
+ continue;
+ Ret.push_back({cast<InputSection>(S), R.LowPC, R.HighPC, CurrentCu});
+ }
+ ++CurrentCu;
}
return Ret;
}
-static std::vector<std::pair<StringRef, uint8_t>>
-readPubNamesAndTypes(DWARFContext &Dwarf, bool IsLE) {
+static std::vector<NameTypeEntry> readPubNamesAndTypes(DWARFContext &Dwarf,
+ bool IsLE) {
StringRef Data[] = {Dwarf.getGnuPubNamesSection(),
Dwarf.getGnuPubTypesSection()};
- std::vector<std::pair<StringRef, uint8_t>> Ret;
+ std::vector<NameTypeEntry> Ret;
for (StringRef D : Data) {
DWARFDebugPubTable PubTable(D, IsLE, true);
for (const DWARFDebugPubTable::Set &Set : PubTable.getData())
@@ -1743,52 +1738,77 @@ readPubNamesAndTypes(DWARFContext &Dwarf, bool IsLE) {
return Ret;
}
-class ObjInfoTy : public llvm::LoadedObjectInfo {
- uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const override {
- auto &S = static_cast<const object::ELFSectionRef &>(Sec);
- if (S.getFlags() & ELF::SHF_ALLOC)
- return S.getOffset();
- return 0;
- }
+static std::vector<InputSection *> getDebugInfoSections() {
+ std::vector<InputSection *> Ret;
+ for (InputSectionBase *S : InputSections)
+ if (InputSection *IS = dyn_cast<InputSection>(S))
+ if (IS->getParent() && IS->Name == ".debug_info")
+ Ret.push_back(IS);
+ return Ret;
+}
- std::unique_ptr<llvm::LoadedObjectInfo> clone() const override { return {}; }
-};
+void GdbIndexSection::buildIndex() {
+ std::vector<InputSection *> V = getDebugInfoSections();
+ if (V.empty())
+ return;
+
+ for (InputSection *Sec : V)
+ Chunks.push_back(readDwarf(Sec));
+
+ uint32_t CuId = 0;
+ for (GdbIndexChunk &D : Chunks) {
+ for (AddressEntry &E : D.AddressArea)
+ E.CuIndex += CuId;
+
+ // Populate constant pool area.
+ for (NameTypeEntry &NameType : D.NamesAndTypes) {
+ uint32_t Hash = hash(NameType.Name);
+ size_t Offset = StringPool.add(NameType.Name);
+
+ bool IsNew;
+ GdbSymbol *Sym;
+ std::tie(IsNew, Sym) = SymbolTable.add(Hash, Offset);
+ if (IsNew) {
+ Sym->CuVectorIndex = CuVectors.size();
+ CuVectors.resize(CuVectors.size() + 1);
+ }
-void GdbIndexSection::readDwarf(InputSection *Sec) {
+ CuVectors[Sym->CuVectorIndex].insert(CuId | (NameType.Type << 24));
+ }
+
+ CuId += D.CompilationUnits.size();
+ }
+}
+
+GdbIndexChunk GdbIndexSection::readDwarf(InputSection *Sec) {
Expected<std::unique_ptr<object::ObjectFile>> Obj =
object::ObjectFile::createObjectFile(Sec->File->MB);
if (!Obj) {
error(toString(Sec->File) + ": error creating DWARF context");
- return;
+ return {};
}
- ObjInfoTy ObjInfo;
- DWARFContextInMemory Dwarf(*Obj.get(), &ObjInfo);
-
- size_t CuId = CompilationUnits.size();
- for (std::pair<uint64_t, uint64_t> &P : readCuList(Dwarf, Sec))
- CompilationUnits.push_back(P);
-
- for (AddressEntry &Ent : readAddressArea(Dwarf, Sec, CuId))
- AddressArea.push_back(Ent);
-
- std::vector<std::pair<StringRef, uint8_t>> NamesAndTypes =
- readPubNamesAndTypes(Dwarf, Config->IsLE);
+ DWARFContextInMemory Dwarf(*Obj.get());
- for (std::pair<StringRef, uint8_t> &Pair : NamesAndTypes) {
- uint32_t Hash = hash(Pair.first);
- size_t Offset = StringPool.add(Pair.first);
+ GdbIndexChunk Ret;
+ Ret.CompilationUnits = readCuList(Dwarf, Sec);
+ Ret.AddressArea = readAddressArea(Dwarf, Sec);
+ Ret.NamesAndTypes = readPubNamesAndTypes(Dwarf, Config->IsLE);
+ return Ret;
+}
- bool IsNew;
- GdbSymbol *Sym;
- std::tie(IsNew, Sym) = SymbolTable.add(Hash, Offset);
- if (IsNew) {
- Sym->CuVectorIndex = CuVectors.size();
- CuVectors.resize(CuVectors.size() + 1);
- }
+static size_t getCuSize(std::vector<GdbIndexChunk> &C) {
+ size_t Ret = 0;
+ for (GdbIndexChunk &D : C)
+ Ret += D.CompilationUnits.size();
+ return Ret;
+}
- CuVectors[Sym->CuVectorIndex].insert((Pair.second << 24) | (uint32_t)CuId);
- }
+static size_t getAddressAreaSize(std::vector<GdbIndexChunk> &C) {
+ size_t Ret = 0;
+ for (GdbIndexChunk &D : C)
+ Ret += D.AddressArea.size();
+ return Ret;
}
void GdbIndexSection::finalizeContents() {
@@ -1796,17 +1816,14 @@ void GdbIndexSection::finalizeContents() {
return;
Finalized = true;
- for (InputSectionBase *S : InputSections)
- if (InputSection *IS = dyn_cast<InputSection>(S))
- if (IS->getParent() && IS->Name == ".debug_info")
- readDwarf(IS);
+ buildIndex();
SymbolTable.finalizeContents();
// GdbIndex header consist from version fields
// and 5 more fields with different kinds of offsets.
- CuTypesOffset = CuListOffset + CompilationUnits.size() * CompilationUnitSize;
- SymTabOffset = CuTypesOffset + AddressArea.size() * AddressEntrySize;
+ CuTypesOffset = CuListOffset + getCuSize(Chunks) * CompilationUnitSize;
+ SymTabOffset = CuTypesOffset + getAddressAreaSize(Chunks) * AddressEntrySize;
ConstantPoolOffset =
SymTabOffset + SymbolTable.getCapacity() * SymTabEntrySize;
@@ -1835,19 +1852,24 @@ void GdbIndexSection::writeTo(uint8_t *Buf) {
Buf += 24;
// Write the CU list.
- for (std::pair<uint64_t, uint64_t> CU : CompilationUnits) {
- write64le(Buf, CU.first);
- write64le(Buf + 8, CU.second);
- Buf += 16;
+ for (GdbIndexChunk &D : Chunks) {
+ for (CompilationUnitEntry &Cu : D.CompilationUnits) {
+ write64le(Buf, Cu.CuOffset);
+ write64le(Buf + 8, Cu.CuLength);
+ Buf += 16;
+ }
}
// Write the address area.
- for (AddressEntry &E : AddressArea) {
- uint64_t BaseAddr = E.Section->getParent()->Addr + E.Section->getOffset(0);
- write64le(Buf, BaseAddr + E.LowAddress);
- write64le(Buf + 8, BaseAddr + E.HighAddress);
- write32le(Buf + 16, E.CuIndex);
- Buf += 20;
+ for (GdbIndexChunk &D : Chunks) {
+ for (AddressEntry &E : D.AddressArea) {
+ uint64_t BaseAddr =
+ E.Section->getParent()->Addr + E.Section->getOffset(0);
+ write64le(Buf, BaseAddr + E.LowAddress);
+ write64le(Buf + 8, BaseAddr + E.HighAddress);
+ write32le(Buf + 16, E.CuIndex);
+ Buf += 20;
+ }
}
// Write the symbol table.