Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -2414,18 +2414,28 @@ template static std::vector -readPubNamesAndTypes(DWARFContext &Dwarf, uint32_t Idx) { - auto &Obj = static_cast &>(Dwarf.getDWARFObj()); +readPubNamesAndTypes(const LLDDwarfObj &Obj, + const std::vector &CUs) { const DWARFSection &PubNames = Obj.getGnuPubNamesSection(); const DWARFSection &PubTypes = Obj.getGnuPubTypesSection(); std::vector Ret; for (const DWARFSection *Pub : {&PubNames, &PubTypes}) { DWARFDebugPubTable Table(Obj, *Pub, Config->IsLE, true); - for (const DWARFDebugPubTable::Set &Set : Table.getData()) + uint32_t I = 0; + for (const DWARFDebugPubTable::Set &Set : Table.getData()) { + // The value written into the constant pool is Kind << 24 | CuIndex. As we + // don't know how many compilation units precede this object to compute + // CuIndex, We compute (Kind << 24 | CuIndexInThisObject) instead, and add + // the number of preceding compilation units later. + // + // We assume both CUs[*].CuOff and Set.Offset are increasing. + while (I < CUs.size() && CUs[I].CuOffset < Set.Offset) + ++I; for (const DWARFDebugPubTable::Entry &Ent : Set.Entries) Ret.push_back({{Ent.Name, computeGdbHash(Ent.Name)}, - (Ent.Descriptor.toBits() << 24) | Idx}); + (Ent.Descriptor.toBits() << 24) | I}); + } } return Ret; } @@ -2433,10 +2443,18 @@ // Create a list of symbols from a given list of symbol names and types // by uniquifying them by name. static std::vector -createSymbols(ArrayRef> NameTypes) { +createSymbols(ArrayRef> NameTypes, + const std::vector &Chunks) { typedef GdbIndexSection::GdbSymbol GdbSymbol; typedef GdbIndexSection::NameTypeEntry NameTypeEntry; + uint32_t CuIdx = 0; + std::vector CuIdxs(Chunks.size()); + for (uint32_t I = 0, E = Chunks.size(); I != E; ++I) { + CuIdxs[I] = CuIdx; + CuIdx += Chunks[I].CompilationUnits.size(); + } + // The number of symbols we will handle in this function is of the order // of millions for very large executables, so we use multi-threading to // speed it up. @@ -2453,21 +2471,24 @@ // Instantiate GdbSymbols while uniqufying them by name. std::vector> Symbols(NumShards); parallelForEachN(0, Concurrency, [&](size_t ThreadId) { + uint32_t I = 0; for (ArrayRef Entries : NameTypes) { for (const NameTypeEntry &Ent : Entries) { size_t ShardId = Ent.Name.hash() >> Shift; if ((ShardId & (Concurrency - 1)) != ThreadId) continue; + uint32_t V = Ent.Type + CuIdxs[I]; size_t &Idx = Map[ShardId][Ent.Name]; if (Idx) { - Symbols[ShardId][Idx - 1].CuVector.push_back(Ent.Type); + Symbols[ShardId][Idx - 1].CuVector.push_back(V); continue; } Idx = Symbols[ShardId].size() + 1; - Symbols[ShardId].push_back({Ent.Name, {Ent.Type}, 0, 0}); + Symbols[ShardId].push_back({Ent.Name, {V}, 0, 0}); } + ++I; } }); @@ -2519,12 +2540,14 @@ Chunks[I].Sec = Sections[I]; Chunks[I].CompilationUnits = readCuList(Dwarf); Chunks[I].AddressAreas = readAddressAreas(Dwarf, Sections[I]); - NameTypes[I] = readPubNamesAndTypes(Dwarf, I); + NameTypes[I] = readPubNamesAndTypes( + static_cast &>(Dwarf.getDWARFObj()), + Chunks[I].CompilationUnits); }); auto *Ret = make(); Ret->Chunks = std::move(Chunks); - Ret->Symbols = createSymbols(NameTypes); + Ret->Symbols = createSymbols(NameTypes, Ret->Chunks); Ret->initOutputSize(); return Ret; } Index: test/ELF/gdb-index-multiple-cu.s =================================================================== --- /dev/null +++ test/ELF/gdb-index-multiple-cu.s @@ -0,0 +1,64 @@ +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: ld.lld --gdb-index %t.o -o %t +# RUN: llvm-dwarfdump -gdb-index %t | FileCheck %s + +# Kind << 24 | CuIndex = 48 << 24 | 1 = 0x30000001 +# CHECK: Constant pool +# CHECK-NEXT: 0(0x0): 0x30000001 + +.globl _start +_start: + ret + +.section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .ascii "\264B" # DW_AT_GNU_pubnames + .byte 12 # DW_FORM_flag + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 8 # DW_FORM_string + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 + +.section .debug_info,"",@progbits +.Lcu_begin0: + .long .Lcu_end0 - .Lcu_begin0 - 4 + .short 4 # DWARF version number + .long 0 # Offset Into Abbrev. Section + .byte 4 # Address Size + .byte 1 # Abbrev [1] DW_TAG_compile_unit + .byte 0 # DW_AT_GNU_pubnames + .byte 0 +.Lcu_end0: +.Lcu_begin1: + .long .Lcu_end1 - .Lcu_begin1 - 4 + .short 4 # DWARF version number + .long 0 # Offset Into Abbrev. Section + .byte 4 # Address Size +.Ldie: + .byte 1 # Abbrev [1] DW_TAG_compile_unit + .byte 1 # DW_AT_GNU_pubnames + .byte 2 # Abbrev [2] DW_TAG_subprogram + .asciz "_start" # DW_AT_name + .byte 0 +.Lcu_end1: + +# .debug_gnu_pubnames has just one set, associated with .Lcu_begin1 (CuIndex: 1) +.section .debug_gnu_pubnames,"",@progbits + .long .LpubNames_end1-.LpubNames_begin1 +.LpubNames_begin1: + .short 2 # Version + .long .Lcu_begin1 # CU Offset + .long .Lcu_end1 - .Lcu_begin1 + .long .Ldie - .Lcu_begin0 + .byte 48 # Kind: FUNCTION, EXTERNAL + .asciz "_start" # External Name + .long 0 +.LpubNames_end1: