Index: ELF/GdbIndex.h =================================================================== --- ELF/GdbIndex.h +++ ELF/GdbIndex.h @@ -12,15 +12,33 @@ #include "InputFiles.h" #include "llvm/Object/ELF.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" namespace lld { namespace elf { template class InputSection; -template -std::vector> -readCuList(InputSection *Sec); +template struct AddressEntry { + InputSectionBase *Section; // Section. + uint64_t LowAddress; // The low address. + uint64_t HighAddress; // The high address. + uint32_t CuIndex; // The CU index. +}; + +template class GdbIndexBuilder { + typedef typename ELFT::uint uintX_t; + + InputSection *DebugInfoSec; + + std::unique_ptr Dwarf; + +public: + GdbIndexBuilder(InputSection *DebugInfoSec); + + std::vector> readCuList(); + std::vector> readAddressArea(size_t CurrentCU); +}; } // namespace elf } // namespace lld Index: ELF/GdbIndex.cpp =================================================================== --- ELF/GdbIndex.cpp +++ ELF/GdbIndex.cpp @@ -57,35 +57,32 @@ // hashtable in according to .gdb_index format specification. // 6) Constant pool is populated at the same time as symbol table. // -// Current version of implementation has 1, 2, 3 steps. So it writes .gdb_index -// header and list of compilation units. Since we so not plan to support types -// CU list area, it is also empty and so far is "implemented". +// Current version implements steps 1-4. So it writes .gdb_index +// header, list of compilation units and address area. Since we so not plan to +// support types CU list area, it is also empty and so far is "implemented". // Other data areas are not yet implemented. //===----------------------------------------------------------------------===// #include "GdbIndex.h" -#include "llvm/DebugInfo/DWARF/DWARFContext.h" - using namespace llvm; using namespace llvm::object; +using namespace lld::elf; template -std::vector> -lld::elf::readCuList(InputSection *DebugInfoSec) { - typedef typename ELFT::uint uintX_t; - - std::unique_ptr Dwarf; +GdbIndexBuilder::GdbIndexBuilder(InputSection *DebugInfoSec) + : DebugInfoSec(DebugInfoSec) { if (Expected> Obj = object::ObjectFile::createObjectFile(DebugInfoSec->getFile()->MB)) Dwarf.reset(new DWARFContextInMemory(*Obj.get())); - - if (!Dwarf) { + else error(getFilename(DebugInfoSec->getFile()) + ": error creating DWARF context"); - return {}; - } +} +template +std::vector> +GdbIndexBuilder::readCuList() { std::vector> Ret; for (std::unique_ptr &CU : Dwarf->compile_units()) Ret.push_back( @@ -93,11 +90,28 @@ return Ret; } -template std::vector> -lld::elf::readCuList(InputSection *); -template std::vector> -lld::elf::readCuList(InputSection *); -template std::vector> -lld::elf::readCuList(InputSection *); -template std::vector> -lld::elf::readCuList(InputSection *); +template +std::vector> +GdbIndexBuilder::readAddressArea(size_t CurrentCU) { + std::vector> Ret; + for (const auto &CU : Dwarf->compile_units()) { + DWARFAddressRangesVector ReadAddressed; + CU->collectAddressRanges(ReadAddressed); + + ArrayRef *> Sections = + DebugInfoSec->getFile()->getSections(); + for (auto &R : ReadAddressed) + Ret.push_back({Sections[R.SecNdx], R.LowPC, R.HighPC, CurrentCU}); + ++CurrentCU; + } + return Ret; +} + +namespace lld { +namespace elf { +template class GdbIndexBuilder; +template class GdbIndexBuilder; +template class GdbIndexBuilder; +template class GdbIndexBuilder; +} +} Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -150,11 +150,14 @@ // Pairs of [CU Offset, CU length]. std::vector> CompilationUnits; + std::vector> AddressArea; + private: void parseDebugSections(); void readDwarf(InputSection *I); uint32_t CuTypesOffset; + uint32_t SymTabOffset; }; template class GotSection final : public OutputSectionBase { Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -71,8 +71,16 @@ template void GdbIndexSection::readDwarf(InputSection *I) { - std::vector> CuList = readCuList(I); + GdbIndexBuilder Builder(I); + if (HasError) + return; + + size_t CuId = CompilationUnits.size(); + std::vector> CuList = Builder.readCuList(); CompilationUnits.insert(CompilationUnits.end(), CuList.begin(), CuList.end()); + + std::vector> AddrArea = Builder.readAddressArea(CuId); + AddressArea.insert(AddressArea.end(), AddrArea.begin(), AddrArea.end()); } template void GdbIndexSection::finalize() { @@ -81,16 +89,18 @@ // GdbIndex header consist from version fields // and 5 more fields with different kinds of offsets. CuTypesOffset = CuListOffset + CompilationUnits.size() * CompilationUnitSize; - this->Header.sh_size = CuTypesOffset; + SymTabOffset = CuTypesOffset + AddressArea.size() * AddressEntrySize; + + this->Header.sh_size = SymTabOffset; } template void GdbIndexSection::writeTo(uint8_t *Buf) { - write32le(Buf, 7); // Write Version - write32le(Buf + 4, CuListOffset); // CU list offset - write32le(Buf + 8, CuTypesOffset); // Types CU list offset - write32le(Buf + 12, CuTypesOffset); // Address area offset - write32le(Buf + 16, CuTypesOffset); // Symbol table offset - write32le(Buf + 20, CuTypesOffset); // Constant pool offset + write32le(Buf, 7); // Write version. + write32le(Buf + 4, CuListOffset); // CU list offset. + write32le(Buf + 8, CuTypesOffset); // Types CU list offset. + write32le(Buf + 12, CuTypesOffset); // Address area offset. + write32le(Buf + 16, SymTabOffset); // Symbol table offset. + write32le(Buf + 20, SymTabOffset); // Constant pool offset. Buf += 24; // Write the CU list. @@ -99,6 +109,15 @@ write64le(Buf + 8, CU.second); Buf += 16; } + + // Write the address area. + for (AddressEntry &E : AddressArea) { + uintX_t BaseAddr = E.Section->OutSec->getVA() + E.Section->getOffset(0); + write64le(Buf, BaseAddr + E.LowAddress); + write64le(Buf + 8, BaseAddr + E.HighAddress); + write32le(Buf + 16, E.CuIndex); + Buf += 20; + } } template Index: test/ELF/gdb-index.s =================================================================== --- test/ELF/gdb-index.s +++ test/ELF/gdb-index.s @@ -31,8 +31,10 @@ # CHECK: .gnu_index contents: # CHECK-NEXT: Version = 7 # CHECK: CU list offset = 0x18, has 2 entries: -# CHECK-NEXT: 0: Offset = 0x0, Length = 0x34 -# CHECK-NEXT: 1: Offset = 0x34, Length = 0x34 -# CHECK: Address area offset = 0x38, has 0 entries: -# CHECK: Symbol table offset = 0x38, size = 0, filled slots: -# CHECK: Constant pool offset = 0x38, has 0 CU vectors: +# CHECK-NEXT: 0: Offset = 0x0, Length = 0x34 +# CHECK-NEXT: 1: Offset = 0x34, Length = 0x34 +# CHECK: Address area offset = 0x38, has 2 entries: +# CHECK-NEXT: Low address = 0x11000, High address = 0x1100b, CU index = 0 +# CHECK-NEXT: Low address = 0x1100b, High address = 0x11016, CU index = 1 +# CHECK: Symbol table offset = 0x60, size = 0, filled slots: +# CHECK: Constant pool offset = 0x60, has 0 CU vectors: