forked from OSchip/llvm-project
[BOLT][DWARF] Fix gdb index section
Since we now re-write .debug_info the DWARF CU Offsets can change. Just like for .debug_aranges the GDB Index will need to be updated. Reviewed By: Amir, maksfb Differential Revision: https://reviews.llvm.org/D118273
This commit is contained in:
parent
1f26aa42ce
commit
612f0f4568
|
@ -107,6 +107,13 @@ struct DebugLineTableRowRef {
|
||||||
/// Common buffer vector used for debug info handling.
|
/// Common buffer vector used for debug info handling.
|
||||||
using DebugBufferVector = SmallVector<char, 16>;
|
using DebugBufferVector = SmallVector<char, 16>;
|
||||||
|
|
||||||
|
/// Map of old CU offset to new offset and length.
|
||||||
|
struct CUInfo {
|
||||||
|
uint32_t Offset;
|
||||||
|
uint32_t Length;
|
||||||
|
};
|
||||||
|
using CUOffsetMap = std::map<uint32_t, CUInfo>;
|
||||||
|
|
||||||
/// Serializes the .debug_ranges DWARF section.
|
/// Serializes the .debug_ranges DWARF section.
|
||||||
class DebugRangesSectionWriter {
|
class DebugRangesSectionWriter {
|
||||||
public:
|
public:
|
||||||
|
@ -155,9 +162,8 @@ public:
|
||||||
/// Writes .debug_aranges with the added ranges to the MCObjectWriter.
|
/// Writes .debug_aranges with the added ranges to the MCObjectWriter.
|
||||||
/// Takes in \p RangesStream to write into, and \p CUMap which maps CU
|
/// Takes in \p RangesStream to write into, and \p CUMap which maps CU
|
||||||
/// original offsets to new ones.
|
/// original offsets to new ones.
|
||||||
void
|
void writeARangesSection(raw_svector_ostream &RangesStream,
|
||||||
writeARangesSection(raw_svector_ostream &RangesStream,
|
const CUOffsetMap &CUMap) const;
|
||||||
const std::unordered_map<uint32_t, uint32_t> CUMap) const;
|
|
||||||
|
|
||||||
/// Resets the writer to a clear state.
|
/// Resets the writer to a clear state.
|
||||||
void reset() { CUAddressRanges.clear(); }
|
void reset() { CUAddressRanges.clear(); }
|
||||||
|
@ -647,8 +653,8 @@ public:
|
||||||
void setDWPOffset(uint64_t DWPOffset) { DWPUnitOffset = DWPOffset; }
|
void setDWPOffset(uint64_t DWPOffset) { DWPUnitOffset = DWPOffset; }
|
||||||
|
|
||||||
/// When this function is invoked all of the DebugInfo Patches must be done.
|
/// When this function is invoked all of the DebugInfo Patches must be done.
|
||||||
/// Returns a map of old CU offsets to new ones.
|
/// Returns a map of old CU offsets to new offsets and new sizes.
|
||||||
std::unordered_map<uint32_t, uint32_t> computeNewOffsets();
|
CUOffsetMap computeNewOffsets(DWARFContext &DWCtx, bool IsDWOContext);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct PatchDeleter {
|
struct PatchDeleter {
|
||||||
|
@ -685,7 +691,7 @@ private:
|
||||||
using UniquePatchPtrType = std::unique_ptr<Patch, PatchDeleter>;
|
using UniquePatchPtrType = std::unique_ptr<Patch, PatchDeleter>;
|
||||||
|
|
||||||
uint64_t DWPUnitOffset{0};
|
uint64_t DWPUnitOffset{0};
|
||||||
uint32_t ChangeInSize{0};
|
int32_t ChangeInSize{0};
|
||||||
std::vector<UniquePatchPtrType> DebugPatches;
|
std::vector<UniquePatchPtrType> DebugPatches;
|
||||||
/// Mutex used for parallel processing of debug info.
|
/// Mutex used for parallel processing of debug info.
|
||||||
std::mutex WriterMutex;
|
std::mutex WriterMutex;
|
||||||
|
|
|
@ -93,14 +93,14 @@ class DWARFRewriter {
|
||||||
makeFinalLocListsSection(SimpleBinaryPatcher &DebugInfoPatcher);
|
makeFinalLocListsSection(SimpleBinaryPatcher &DebugInfoPatcher);
|
||||||
|
|
||||||
/// Finalize debug sections in the main binary.
|
/// Finalize debug sections in the main binary.
|
||||||
void finalizeDebugSections(DebugInfoBinaryPatcher &DebugInfoPatcher);
|
CUOffsetMap finalizeDebugSections(DebugInfoBinaryPatcher &DebugInfoPatcher);
|
||||||
|
|
||||||
/// Patches the binary for DWARF address ranges (e.g. in functions and lexical
|
/// Patches the binary for DWARF address ranges (e.g. in functions and lexical
|
||||||
/// blocks) to be updated.
|
/// blocks) to be updated.
|
||||||
void updateDebugAddressRanges();
|
void updateDebugAddressRanges();
|
||||||
|
|
||||||
/// Rewrite .gdb_index section if present.
|
/// Rewrite .gdb_index section if present.
|
||||||
void updateGdbIndexSection();
|
void updateGdbIndexSection(CUOffsetMap &CUMap);
|
||||||
|
|
||||||
/// Output .dwo files.
|
/// Output .dwo files.
|
||||||
void writeDWOFiles(std::unordered_map<uint64_t, std::string> &DWOIdToName);
|
void writeDWOFiles(std::unordered_map<uint64_t, std::string> &DWOIdToName);
|
||||||
|
|
|
@ -121,8 +121,7 @@ void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset,
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugARangesSectionWriter::writeARangesSection(
|
void DebugARangesSectionWriter::writeARangesSection(
|
||||||
raw_svector_ostream &RangesStream,
|
raw_svector_ostream &RangesStream, const CUOffsetMap &CUMap) const {
|
||||||
const std::unordered_map<uint32_t, uint32_t> CUMap) const {
|
|
||||||
// For reference on the format of the .debug_aranges section, see the DWARF4
|
// For reference on the format of the .debug_aranges section, see the DWARF4
|
||||||
// specification, section 6.1.4 Lookup by Address
|
// specification, section 6.1.4 Lookup by Address
|
||||||
// http://www.dwarfstd.org/doc/DWARF4.pdf
|
// http://www.dwarfstd.org/doc/DWARF4.pdf
|
||||||
|
@ -148,9 +147,9 @@ void DebugARangesSectionWriter::writeARangesSection(
|
||||||
|
|
||||||
assert(CUMap.count(Offset) && "Original CU offset is not found in CU Map");
|
assert(CUMap.count(Offset) && "Original CU offset is not found in CU Map");
|
||||||
// Header field #3: debug info offset of the correspondent compile unit.
|
// Header field #3: debug info offset of the correspondent compile unit.
|
||||||
support::endian::write(RangesStream,
|
support::endian::write(
|
||||||
static_cast<uint32_t>(CUMap.find(Offset)->second),
|
RangesStream, static_cast<uint32_t>(CUMap.find(Offset)->second.Offset),
|
||||||
support::little);
|
support::little);
|
||||||
|
|
||||||
// Header field #4: address size.
|
// Header field #4: address size.
|
||||||
// 8 since we only write ELF64 binaries for now.
|
// 8 since we only write ELF64 binaries for now.
|
||||||
|
@ -473,23 +472,32 @@ std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) {
|
||||||
return BinaryContentsStr;
|
return BinaryContentsStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<uint32_t, uint32_t>
|
CUOffsetMap DebugInfoBinaryPatcher::computeNewOffsets(DWARFContext &DWCtx,
|
||||||
DebugInfoBinaryPatcher::computeNewOffsets() {
|
bool IsDWOContext) {
|
||||||
std::unordered_map<uint32_t, uint32_t> CUMap;
|
CUOffsetMap CUMap;
|
||||||
std::sort(DebugPatches.begin(), DebugPatches.end(),
|
std::sort(DebugPatches.begin(), DebugPatches.end(),
|
||||||
[](const UniquePatchPtrType &V1, const UniquePatchPtrType &V2) {
|
[](const UniquePatchPtrType &V1, const UniquePatchPtrType &V2) {
|
||||||
return V1.get()->Offset < V2.get()->Offset;
|
return V1.get()->Offset < V2.get()->Offset;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
DWARFUnitVector::compile_unit_range CompileUnits =
|
||||||
|
IsDWOContext ? DWCtx.dwo_compile_units() : DWCtx.compile_units();
|
||||||
|
|
||||||
|
for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits)
|
||||||
|
CUMap[CU->getOffset()] = {static_cast<uint32_t>(CU->getOffset()),
|
||||||
|
static_cast<uint32_t>(CU->getLength())};
|
||||||
|
|
||||||
// Calculating changes in .debug_info size from Patches to build a map of old
|
// Calculating changes in .debug_info size from Patches to build a map of old
|
||||||
// to updated reference destination offsets.
|
// to updated reference destination offsets.
|
||||||
|
uint32_t PreviousOffset = 0;
|
||||||
|
int32_t PreviousChangeInSize = 0;
|
||||||
for (UniquePatchPtrType &PatchBase : DebugPatches) {
|
for (UniquePatchPtrType &PatchBase : DebugPatches) {
|
||||||
Patch *P = PatchBase.get();
|
Patch *P = PatchBase.get();
|
||||||
switch (P->Kind) {
|
switch (P->Kind) {
|
||||||
default:
|
default:
|
||||||
continue;
|
continue;
|
||||||
case DebugPatchKind::PatchValue64to32: {
|
case DebugPatchKind::PatchValue64to32: {
|
||||||
ChangeInSize -= 4;
|
PreviousChangeInSize -= 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DebugPatchKind::PatchValueVariable: {
|
case DebugPatchKind::PatchValueVariable: {
|
||||||
|
@ -498,13 +506,14 @@ DebugInfoBinaryPatcher::computeNewOffsets() {
|
||||||
std::string Temp;
|
std::string Temp;
|
||||||
raw_string_ostream OS(Temp);
|
raw_string_ostream OS(Temp);
|
||||||
encodeULEB128(DPV->Value, OS);
|
encodeULEB128(DPV->Value, OS);
|
||||||
ChangeInSize += Temp.size() - DPV->OldValueSize;
|
PreviousChangeInSize += Temp.size() - DPV->OldValueSize;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DebugPatchKind::DestinationReferenceLabel: {
|
case DebugPatchKind::DestinationReferenceLabel: {
|
||||||
DestinationReferenceLabel *DRL =
|
DestinationReferenceLabel *DRL =
|
||||||
reinterpret_cast<DestinationReferenceLabel *>(P);
|
reinterpret_cast<DestinationReferenceLabel *>(P);
|
||||||
OldToNewOffset[DRL->Offset] = DRL->Offset + ChangeInSize;
|
OldToNewOffset[DRL->Offset] =
|
||||||
|
DRL->Offset + ChangeInSize + PreviousChangeInSize;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DebugPatchKind::ReferencePatchValue: {
|
case DebugPatchKind::ReferencePatchValue: {
|
||||||
|
@ -512,7 +521,7 @@ DebugInfoBinaryPatcher::computeNewOffsets() {
|
||||||
// to reduce algorithmic complexity.
|
// to reduce algorithmic complexity.
|
||||||
DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P);
|
DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P);
|
||||||
if (RDP->PatchInfo.IndirectRelative) {
|
if (RDP->PatchInfo.IndirectRelative) {
|
||||||
ChangeInSize += 4 - RDP->PatchInfo.OldValueSize;
|
PreviousChangeInSize += 4 - RDP->PatchInfo.OldValueSize;
|
||||||
assert(RDP->PatchInfo.OldValueSize <= 4 &&
|
assert(RDP->PatchInfo.OldValueSize <= 4 &&
|
||||||
"Variable encoding reference greater than 4 bytes.");
|
"Variable encoding reference greater than 4 bytes.");
|
||||||
}
|
}
|
||||||
|
@ -522,11 +531,16 @@ DebugInfoBinaryPatcher::computeNewOffsets() {
|
||||||
DWARFUnitOffsetBaseLabel *BaseLabel =
|
DWARFUnitOffsetBaseLabel *BaseLabel =
|
||||||
reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P);
|
reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P);
|
||||||
uint32_t CUOffset = BaseLabel->Offset;
|
uint32_t CUOffset = BaseLabel->Offset;
|
||||||
|
ChangeInSize += PreviousChangeInSize;
|
||||||
uint32_t CUOffsetUpdate = CUOffset + ChangeInSize;
|
uint32_t CUOffsetUpdate = CUOffset + ChangeInSize;
|
||||||
CUMap[CUOffset] = CUOffsetUpdate;
|
CUMap[CUOffset].Offset = CUOffsetUpdate;
|
||||||
|
CUMap[PreviousOffset].Length += PreviousChangeInSize;
|
||||||
|
PreviousChangeInSize = 0;
|
||||||
|
PreviousOffset = CUOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CUMap[PreviousOffset].Length += PreviousChangeInSize;
|
||||||
return CUMap;
|
return CUMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -323,14 +323,14 @@ void DWARFRewriter::updateDebugInfo() {
|
||||||
DebugInfoPatcher->clearDestinationLabels();
|
DebugInfoPatcher->clearDestinationLabels();
|
||||||
flushPendingRanges(*DebugInfoPatcher);
|
flushPendingRanges(*DebugInfoPatcher);
|
||||||
|
|
||||||
finalizeDebugSections(*DebugInfoPatcher);
|
CUOffsetMap OffsetMap = finalizeDebugSections(*DebugInfoPatcher);
|
||||||
|
|
||||||
if (opts::WriteDWP)
|
if (opts::WriteDWP)
|
||||||
writeDWP(DWOIdToName);
|
writeDWP(DWOIdToName);
|
||||||
else
|
else
|
||||||
writeDWOFiles(DWOIdToName);
|
writeDWOFiles(DWOIdToName);
|
||||||
|
|
||||||
updateGdbIndexSection();
|
updateGdbIndexSection(OffsetMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DWARFRewriter::updateUnitDebugInfo(
|
void DWARFRewriter::updateUnitDebugInfo(
|
||||||
|
@ -820,8 +820,8 @@ void DWARFRewriter::updateLineTableOffsets(const MCAsmLayout &Layout) {
|
||||||
TypeInfoSection->setIsFinalized();
|
TypeInfoSection->setIsFinalized();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DWARFRewriter::finalizeDebugSections(
|
CUOffsetMap
|
||||||
DebugInfoBinaryPatcher &DebugInfoPatcher) {
|
DWARFRewriter::finalizeDebugSections(DebugInfoBinaryPatcher &DebugInfoPatcher) {
|
||||||
if (StrWriter->isInitialized()) {
|
if (StrWriter->isInitialized()) {
|
||||||
RewriteInstance::addToDebugSectionsToOverwrite(".debug_str");
|
RewriteInstance::addToDebugSectionsToOverwrite(".debug_str");
|
||||||
std::unique_ptr<DebugStrBufferVector> DebugStrSectionContents =
|
std::unique_ptr<DebugStrBufferVector> DebugStrSectionContents =
|
||||||
|
@ -898,8 +898,8 @@ void DWARFRewriter::finalizeDebugSections(
|
||||||
}
|
}
|
||||||
|
|
||||||
// No more creating new DebugInfoPatches.
|
// No more creating new DebugInfoPatches.
|
||||||
std::unordered_map<uint32_t, uint32_t> CUMap =
|
CUOffsetMap CUMap =
|
||||||
DebugInfoPatcher.computeNewOffsets();
|
DebugInfoPatcher.computeNewOffsets(*BC.DwCtx.get(), false);
|
||||||
|
|
||||||
// Skip .debug_aranges if we are re-generating .gdb_index.
|
// Skip .debug_aranges if we are re-generating .gdb_index.
|
||||||
if (opts::KeepARanges || !BC.getGdbIndexSection()) {
|
if (opts::KeepARanges || !BC.getGdbIndexSection()) {
|
||||||
|
@ -916,6 +916,7 @@ void DWARFRewriter::finalizeDebugSections(
|
||||||
copyByteArray(ARangesContents),
|
copyByteArray(ARangesContents),
|
||||||
ARangesContents.size());
|
ARangesContents.size());
|
||||||
}
|
}
|
||||||
|
return CUMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates all the data structures necessary for creating MCStreamer.
|
// Creates all the data structures necessary for creating MCStreamer.
|
||||||
|
@ -958,15 +959,14 @@ StringRef getSectionName(const SectionRef &Section) {
|
||||||
|
|
||||||
// Exctracts an appropriate slice if input is DWP.
|
// Exctracts an appropriate slice if input is DWP.
|
||||||
// Applies patches or overwrites the section.
|
// Applies patches or overwrites the section.
|
||||||
Optional<StringRef>
|
Optional<StringRef> updateDebugData(
|
||||||
updateDebugData(std::string &Storage, const SectionRef &Section,
|
DWARFContext &DWCtx, std::string &Storage, const SectionRef &Section,
|
||||||
const StringMap<KnownSectionsEntry> &KnownSections,
|
const StringMap<KnownSectionsEntry> &KnownSections, MCStreamer &Streamer,
|
||||||
MCStreamer &Streamer, DWARFRewriter &Writer,
|
DWARFRewriter &Writer, const DWARFUnitIndex::Entry *DWOEntry,
|
||||||
const DWARFUnitIndex::Entry *DWOEntry, uint64_t DWOId,
|
uint64_t DWOId, std::unique_ptr<DebugBufferVector> &OutputBuffer) {
|
||||||
std::unique_ptr<DebugBufferVector> &OutputBuffer) {
|
|
||||||
auto applyPatch = [&](DebugInfoBinaryPatcher *Patcher,
|
auto applyPatch = [&](DebugInfoBinaryPatcher *Patcher,
|
||||||
StringRef Data) -> StringRef {
|
StringRef Data) -> StringRef {
|
||||||
Patcher->computeNewOffsets();
|
Patcher->computeNewOffsets(DWCtx, true);
|
||||||
Storage = Patcher->patchBinary(Data);
|
Storage = Patcher->patchBinary(Data);
|
||||||
return StringRef(Storage.c_str(), Storage.size());
|
return StringRef(Storage.c_str(), Storage.size());
|
||||||
};
|
};
|
||||||
|
@ -1127,9 +1127,9 @@ void DWARFRewriter::writeDWP(
|
||||||
for (const SectionRef &Section : DWOFile->sections()) {
|
for (const SectionRef &Section : DWOFile->sections()) {
|
||||||
std::string Storage = "";
|
std::string Storage = "";
|
||||||
std::unique_ptr<DebugBufferVector> OutputData;
|
std::unique_ptr<DebugBufferVector> OutputData;
|
||||||
Optional<StringRef> TOutData =
|
Optional<StringRef> TOutData = updateDebugData(
|
||||||
updateDebugData(Storage, Section, KnownSections, *Streamer, *this,
|
(*DWOCU)->getContext(), Storage, Section, KnownSections, *Streamer,
|
||||||
DWOEntry, *DWOId, OutputData);
|
*this, DWOEntry, *DWOId, OutputData);
|
||||||
if (!TOutData)
|
if (!TOutData)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -1227,9 +1227,9 @@ void DWARFRewriter::writeDWOFiles(
|
||||||
for (const SectionRef &Section : File->sections()) {
|
for (const SectionRef &Section : File->sections()) {
|
||||||
std::string Storage = "";
|
std::string Storage = "";
|
||||||
std::unique_ptr<DebugBufferVector> OutputData;
|
std::unique_ptr<DebugBufferVector> OutputData;
|
||||||
if (Optional<StringRef> OutData =
|
if (Optional<StringRef> OutData = updateDebugData(
|
||||||
updateDebugData(Storage, Section, KnownSections, *Streamer, *this,
|
(*DWOCU)->getContext(), Storage, Section, KnownSections,
|
||||||
DWOEntry, *DWOId, OutputData))
|
*Streamer, *this, DWOEntry, *DWOId, OutputData))
|
||||||
Streamer->emitBytes(*OutData);
|
Streamer->emitBytes(*OutData);
|
||||||
}
|
}
|
||||||
Streamer->Finish();
|
Streamer->Finish();
|
||||||
|
@ -1237,7 +1237,7 @@ void DWARFRewriter::writeDWOFiles(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DWARFRewriter::updateGdbIndexSection() {
|
void DWARFRewriter::updateGdbIndexSection(CUOffsetMap &CUMap) {
|
||||||
if (!BC.getGdbIndexSection())
|
if (!BC.getGdbIndexSection())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1314,10 +1314,23 @@ void DWARFRewriter::updateGdbIndexSection() {
|
||||||
write32le(Buffer + 20, ConstantPoolOffset + Delta);
|
write32le(Buffer + 20, ConstantPoolOffset + Delta);
|
||||||
Buffer += 24;
|
Buffer += 24;
|
||||||
|
|
||||||
// Copy over CU list and types CU list.
|
// Writing out CU List <Offset, Size>
|
||||||
memcpy(Buffer, GdbIndexContents.data() + 24,
|
for (auto &CUInfo : CUMap) {
|
||||||
AddressTableOffset - CUListOffset);
|
write64le(Buffer, CUInfo.second.Offset);
|
||||||
Buffer += AddressTableOffset - CUListOffset;
|
// Length encoded in CU doesn't contain first 4 bytes that encode length.
|
||||||
|
write64le(Buffer + 8, CUInfo.second.Length + 4);
|
||||||
|
Buffer += 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy over types CU list
|
||||||
|
// Spec says " triplet, the first value is the CU offset, the second value is
|
||||||
|
// the type offset in the CU, and the third value is the type signature"
|
||||||
|
// Looking at what is being generated by gdb-add-index. The first entry is TU
|
||||||
|
// offset, second entry is offset from it, and third entry is the type
|
||||||
|
// signature.
|
||||||
|
memcpy(Buffer, GdbIndexContents.data() + CUTypesOffset,
|
||||||
|
AddressTableOffset - CUTypesOffset);
|
||||||
|
Buffer += AddressTableOffset - CUTypesOffset;
|
||||||
|
|
||||||
// Generate new address table.
|
// Generate new address table.
|
||||||
for (const std::pair<const uint64_t, DebugAddressRangesVector> &CURangesPair :
|
for (const std::pair<const uint64_t, DebugAddressRangesVector> &CURangesPair :
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
.file "test.cpp"
|
||||||
|
.text
|
||||||
|
.Ltext0:
|
||||||
|
.globl main
|
||||||
|
.type main, @function
|
||||||
|
main:
|
||||||
|
.LFB0:
|
||||||
|
.file 1 "test.cpp"
|
||||||
|
.loc 1 1 12
|
||||||
|
.cfi_startproc
|
||||||
|
pushq %rbp
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_offset 6, -16
|
||||||
|
movq %rsp, %rbp
|
||||||
|
.cfi_def_cfa_register 6
|
||||||
|
.loc 1 1 21
|
||||||
|
movl $0, %eax
|
||||||
|
.loc 1 1 24
|
||||||
|
popq %rbp
|
||||||
|
.cfi_def_cfa 7, 8
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
.LFE0:
|
||||||
|
.size main, .-main
|
||||||
|
.Letext0:
|
||||||
|
.section .debug_info,"",@progbits
|
||||||
|
.Ldebug_info0:
|
||||||
|
.long 0x4f
|
||||||
|
.value 0x4
|
||||||
|
.long .Ldebug_abbrev0
|
||||||
|
.byte 0x8
|
||||||
|
.uleb128 0x1
|
||||||
|
.long .LASF0
|
||||||
|
.byte 0x4
|
||||||
|
.long .LASF1
|
||||||
|
.long .LASF2
|
||||||
|
.quad .Ltext0
|
||||||
|
.quad .Letext0-.Ltext0
|
||||||
|
.long .Ldebug_line0
|
||||||
|
.uleb128 0x2
|
||||||
|
.long .LASF3
|
||||||
|
.byte 0x1
|
||||||
|
.byte 0x1
|
||||||
|
.byte 0x5
|
||||||
|
.long 0x4b
|
||||||
|
.quad .LFB0
|
||||||
|
.quad .LFE0-.LFB0
|
||||||
|
.uleb128 0x1
|
||||||
|
.byte 0x9c
|
||||||
|
.uleb128 0x3
|
||||||
|
.byte 0x4
|
||||||
|
.byte 0x5
|
||||||
|
.string "int"
|
||||||
|
.byte 0
|
||||||
|
.section .debug_abbrev,"",@progbits
|
||||||
|
.Ldebug_abbrev0:
|
||||||
|
.uleb128 0x1
|
||||||
|
.uleb128 0x11
|
||||||
|
.byte 0x1
|
||||||
|
.uleb128 0x25
|
||||||
|
.uleb128 0xe
|
||||||
|
.uleb128 0x13
|
||||||
|
.uleb128 0xb
|
||||||
|
.uleb128 0x3
|
||||||
|
.uleb128 0xe
|
||||||
|
.uleb128 0x1b
|
||||||
|
.uleb128 0xe
|
||||||
|
.uleb128 0x11
|
||||||
|
.uleb128 0x1
|
||||||
|
.uleb128 0x12
|
||||||
|
.uleb128 0x7
|
||||||
|
.uleb128 0x10
|
||||||
|
.uleb128 0x17
|
||||||
|
.byte 0
|
||||||
|
.byte 0
|
||||||
|
.uleb128 0x2
|
||||||
|
.uleb128 0x2e
|
||||||
|
.byte 0
|
||||||
|
.uleb128 0x3f
|
||||||
|
.uleb128 0x19
|
||||||
|
.uleb128 0x3
|
||||||
|
.uleb128 0xe
|
||||||
|
.uleb128 0x3a
|
||||||
|
.uleb128 0xb
|
||||||
|
.uleb128 0x3b
|
||||||
|
.uleb128 0xb
|
||||||
|
.uleb128 0x39
|
||||||
|
.uleb128 0xb
|
||||||
|
.uleb128 0x49
|
||||||
|
.uleb128 0x13
|
||||||
|
.uleb128 0x11
|
||||||
|
.uleb128 0x1
|
||||||
|
.uleb128 0x12
|
||||||
|
.uleb128 0x7
|
||||||
|
.uleb128 0x40
|
||||||
|
.uleb128 0x18
|
||||||
|
.uleb128 0x2117
|
||||||
|
.uleb128 0x19
|
||||||
|
.byte 0
|
||||||
|
.byte 0
|
||||||
|
.uleb128 0x3
|
||||||
|
.uleb128 0x24
|
||||||
|
.byte 0
|
||||||
|
.uleb128 0xb
|
||||||
|
.uleb128 0xb
|
||||||
|
.uleb128 0x3e
|
||||||
|
.uleb128 0xb
|
||||||
|
.uleb128 0x3
|
||||||
|
.uleb128 0x8
|
||||||
|
.byte 0
|
||||||
|
.byte 0
|
||||||
|
.byte 0
|
||||||
|
.section .debug_aranges,"",@progbits
|
||||||
|
.long 0x2c
|
||||||
|
.value 0x2
|
||||||
|
.long .Ldebug_info0
|
||||||
|
.byte 0x8
|
||||||
|
.byte 0
|
||||||
|
.value 0
|
||||||
|
.value 0
|
||||||
|
.quad .Ltext0
|
||||||
|
.quad .Letext0-.Ltext0
|
||||||
|
.quad 0
|
||||||
|
.quad 0
|
||||||
|
.section .debug_line,"",@progbits
|
||||||
|
.Ldebug_line0:
|
||||||
|
.section .debug_str,"MS",@progbits,1
|
||||||
|
.LASF1:
|
||||||
|
.string "test.cpp"
|
||||||
|
.LASF0:
|
||||||
|
.string "GNU C++14 8.5.0 20210514 (Red Hat 8.5.0-3) -mtune=generic -march=x86-64 -g2"
|
||||||
|
.LASF2:
|
||||||
|
.string ""
|
||||||
|
.LASF3:
|
||||||
|
.string "main"
|
||||||
|
.ident "GCC: (GNU) 8.5.0 20210514 (Red Hat 8.5.0-3)"
|
||||||
|
.section .note.GNU-stack,"",@progbits
|
|
@ -0,0 +1,142 @@
|
||||||
|
.file "test2.cpp"
|
||||||
|
.text
|
||||||
|
.Ltext0:
|
||||||
|
.globl _Z5main2v
|
||||||
|
.type _Z5main2v, @function
|
||||||
|
_Z5main2v:
|
||||||
|
.LFB0:
|
||||||
|
.file 1 "test2.cpp"
|
||||||
|
.loc 1 1 13
|
||||||
|
.cfi_startproc
|
||||||
|
pushq %rbp
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_offset 6, -16
|
||||||
|
movq %rsp, %rbp
|
||||||
|
.cfi_def_cfa_register 6
|
||||||
|
.loc 1 1 22
|
||||||
|
movl $0, %eax
|
||||||
|
.loc 1 1 25
|
||||||
|
popq %rbp
|
||||||
|
.cfi_def_cfa 7, 8
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
.LFE0:
|
||||||
|
.size _Z5main2v, .-_Z5main2v
|
||||||
|
.Letext0:
|
||||||
|
.section .debug_info,"",@progbits
|
||||||
|
.Ldebug_info0:
|
||||||
|
.long 0x53
|
||||||
|
.value 0x4
|
||||||
|
.long .Ldebug_abbrev0
|
||||||
|
.byte 0x8
|
||||||
|
.uleb128 0x1
|
||||||
|
.long .LASF0
|
||||||
|
.byte 0x4
|
||||||
|
.long .LASF1
|
||||||
|
.long .LASF2
|
||||||
|
.quad .Ltext0
|
||||||
|
.quad .Letext0-.Ltext0
|
||||||
|
.long .Ldebug_line0
|
||||||
|
.uleb128 0x2
|
||||||
|
.long .LASF3
|
||||||
|
.byte 0x1
|
||||||
|
.byte 0x1
|
||||||
|
.byte 0x5
|
||||||
|
.long .LASF4
|
||||||
|
.long 0x4f
|
||||||
|
.quad .LFB0
|
||||||
|
.quad .LFE0-.LFB0
|
||||||
|
.uleb128 0x1
|
||||||
|
.byte 0x9c
|
||||||
|
.uleb128 0x3
|
||||||
|
.byte 0x4
|
||||||
|
.byte 0x5
|
||||||
|
.string "int"
|
||||||
|
.byte 0
|
||||||
|
.section .debug_abbrev,"",@progbits
|
||||||
|
.Ldebug_abbrev0:
|
||||||
|
.uleb128 0x1
|
||||||
|
.uleb128 0x11
|
||||||
|
.byte 0x1
|
||||||
|
.uleb128 0x25
|
||||||
|
.uleb128 0xe
|
||||||
|
.uleb128 0x13
|
||||||
|
.uleb128 0xb
|
||||||
|
.uleb128 0x3
|
||||||
|
.uleb128 0xe
|
||||||
|
.uleb128 0x1b
|
||||||
|
.uleb128 0xe
|
||||||
|
.uleb128 0x11
|
||||||
|
.uleb128 0x1
|
||||||
|
.uleb128 0x12
|
||||||
|
.uleb128 0x7
|
||||||
|
.uleb128 0x10
|
||||||
|
.uleb128 0x17
|
||||||
|
.byte 0
|
||||||
|
.byte 0
|
||||||
|
.uleb128 0x2
|
||||||
|
.uleb128 0x2e
|
||||||
|
.byte 0
|
||||||
|
.uleb128 0x3f
|
||||||
|
.uleb128 0x19
|
||||||
|
.uleb128 0x3
|
||||||
|
.uleb128 0xe
|
||||||
|
.uleb128 0x3a
|
||||||
|
.uleb128 0xb
|
||||||
|
.uleb128 0x3b
|
||||||
|
.uleb128 0xb
|
||||||
|
.uleb128 0x39
|
||||||
|
.uleb128 0xb
|
||||||
|
.uleb128 0x6e
|
||||||
|
.uleb128 0xe
|
||||||
|
.uleb128 0x49
|
||||||
|
.uleb128 0x13
|
||||||
|
.uleb128 0x11
|
||||||
|
.uleb128 0x1
|
||||||
|
.uleb128 0x12
|
||||||
|
.uleb128 0x7
|
||||||
|
.uleb128 0x40
|
||||||
|
.uleb128 0x18
|
||||||
|
.uleb128 0x2117
|
||||||
|
.uleb128 0x19
|
||||||
|
.byte 0
|
||||||
|
.byte 0
|
||||||
|
.uleb128 0x3
|
||||||
|
.uleb128 0x24
|
||||||
|
.byte 0
|
||||||
|
.uleb128 0xb
|
||||||
|
.uleb128 0xb
|
||||||
|
.uleb128 0x3e
|
||||||
|
.uleb128 0xb
|
||||||
|
.uleb128 0x3
|
||||||
|
.uleb128 0x8
|
||||||
|
.byte 0
|
||||||
|
.byte 0
|
||||||
|
.byte 0
|
||||||
|
.section .debug_aranges,"",@progbits
|
||||||
|
.long 0x2c
|
||||||
|
.value 0x2
|
||||||
|
.long .Ldebug_info0
|
||||||
|
.byte 0x8
|
||||||
|
.byte 0
|
||||||
|
.value 0
|
||||||
|
.value 0
|
||||||
|
.quad .Ltext0
|
||||||
|
.quad .Letext0-.Ltext0
|
||||||
|
.quad 0
|
||||||
|
.quad 0
|
||||||
|
.section .debug_line,"",@progbits
|
||||||
|
.Ldebug_line0:
|
||||||
|
.section .debug_str,"MS",@progbits,1
|
||||||
|
.LASF3:
|
||||||
|
.string "main2"
|
||||||
|
.LASF2:
|
||||||
|
.string ""
|
||||||
|
.LASF0:
|
||||||
|
.string "GNU C++14 8.5.0 20210514 (Red Hat 8.5.0-3) -mtune=generic -march=x86-64 -g2"
|
||||||
|
.LASF4:
|
||||||
|
.string "_Z5main2v"
|
||||||
|
.LASF1:
|
||||||
|
.string "test2.cpp"
|
||||||
|
.ident "GCC: (GNU) 8.5.0 20210514 (Red Hat 8.5.0-3)"
|
||||||
|
.section .note.GNU-stack,"",@progbits
|
|
@ -0,0 +1,32 @@
|
||||||
|
RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %p/Inputs/dwarfdump-gdbindex.s -o %t.o
|
||||||
|
RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %p/Inputs/dwarfdump-gdbindex2.s -o %t2.o
|
||||||
|
RUN: ld.lld --gdb-index %t.o %t2.o -o %tfile.exe
|
||||||
|
RUN: llvm-bolt %tfile.exe -o %tfile.exe.bolt -update-debug-sections
|
||||||
|
RUN: llvm-dwarfdump -gdb-index %tfile.exe.bolt | FileCheck %s
|
||||||
|
|
||||||
|
; test.cpp:
|
||||||
|
; int main() { return 0; }
|
||||||
|
; test2.cpp:
|
||||||
|
; int main2() { return 0; }
|
||||||
|
; Compiled with:
|
||||||
|
; gcc -gsplit-dwarf -c test.cpp test2.cpp
|
||||||
|
; gold --gdb-index test.o test2.o -o dwarfdump-gdbindex-v7.elf-x86-64
|
||||||
|
; gcc version 5.3.1 20160413, GNU gold (GNU Binutils for Ubuntu 2.26) 1.11
|
||||||
|
; Info about gdb-index: https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html
|
||||||
|
|
||||||
|
; CHECK-LABEL: .gdb_index contents:
|
||||||
|
; CHECK: Version = 7
|
||||||
|
|
||||||
|
; CHECK: CU list offset = 0x18, has 2 entries:
|
||||||
|
; CHECK-NEXT: 0: Offset = 0x0, Length = 0x4f
|
||||||
|
; CHECK-NEXT: 1: Offset = 0x4f, Length = 0x53
|
||||||
|
|
||||||
|
; CHECK: Types CU list offset = 0x38, has 0 entries:
|
||||||
|
|
||||||
|
; CHECK: Address area offset = 0x38, has 2 entries:
|
||||||
|
; CHECK-NEXT: Low/High address = [0x20117c, 0x201187) (Size: 0xb), CU id = 0
|
||||||
|
; CHECK-NEXT: Low/High address = [0x201188, 0x201193) (Size: 0xb), CU id = 1
|
||||||
|
|
||||||
|
; CHECK: Symbol table offset = 0x60, size = 1024, filled slots:
|
||||||
|
|
||||||
|
; CHECK: Constant pool offset = 0x2060, has 0 CU vectors:
|
Loading…
Reference in New Issue