1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

[DWARF] Add support for 64-bit DWARF in .debug_names.

Differential Revision: https://reviews.llvm.org/D72900
This commit is contained in:
Igor Kudrin 2020-01-15 10:20:58 +07:00
parent c93b68ebf4
commit 2e7956d059
5 changed files with 181 additions and 21 deletions

View File

@ -229,7 +229,8 @@ public:
/// DWARF v5 Name Index header.
struct Header {
uint32_t UnitLength;
uint64_t UnitLength;
dwarf::DwarfFormat Format;
uint16_t Version;
uint32_t CompUnitCount;
uint32_t LocalTypeUnitCount;
@ -456,7 +457,10 @@ public:
Error extract();
uint64_t getUnitOffset() const { return Base; }
uint64_t getNextUnitOffset() const { return Base + 4 + Hdr.UnitLength; }
uint64_t getNextUnitOffset() const {
return Base + dwarf::getUnitLengthFieldByteSize(Hdr.Format) +
Hdr.UnitLength;
}
void dump(ScopedPrinter &W) const;
friend class DWARFDebugNames;

View File

@ -377,6 +377,19 @@ void DWARFDebugNames::Header::dump(ScopedPrinter &W) const {
Error DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS,
uint64_t *Offset) {
uint64_t StartingOffset = *Offset;
// Check that we can read the unit length field.
if (!AS.isValidOffsetForDataOfSize(StartingOffset, 4))
return createStringError(errc::illegal_byte_sequence,
"Section too small: cannot read header.");
UnitLength = AS.getU32(Offset);
if (UnitLength >= dwarf::DW_LENGTH_lo_reserved &&
UnitLength != dwarf::DW_LENGTH_DWARF64)
return createStringError(errc::illegal_byte_sequence,
"Unsupported reserved unit length value");
Format = (UnitLength == dwarf::DW_LENGTH_DWARF64) ? dwarf::DWARF64
: dwarf::DWARF32;
// These fields are the same for 32-bit and 64-bit DWARF formats.
constexpr unsigned CommonHeaderSize = 2 + // Version
2 + // Padding
@ -387,14 +400,14 @@ Error DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS,
4 + // Name count
4 + // Abbreviations table size
4; // Augmentation string size
static const unsigned DWARF32HeaderFixedPartSize =
dwarf::getUnitLengthFieldByteSize(dwarf::DWARF32) + CommonHeaderSize;
// Check that we can read the fixed-size part.
if (!AS.isValidOffsetForDataOfSize(*Offset, DWARF32HeaderFixedPartSize))
if (!AS.isValidOffsetForDataOfSize(
StartingOffset,
CommonHeaderSize + dwarf::getUnitLengthFieldByteSize(Format)))
return createStringError(errc::illegal_byte_sequence,
"Section too small: cannot read header.");
UnitLength = AS.getU32(Offset);
if (Format == dwarf::DWARF64)
UnitLength = AS.getU64(Offset);
Version = AS.getU16(Offset);
// Skip padding
*Offset += 2;
@ -498,9 +511,10 @@ Error DWARFDebugNames::NameIndex::extract() {
if (Error E = Hdr.extract(AS, &Offset))
return E;
const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
CUsBase = Offset;
Offset += Hdr.CompUnitCount * 4;
Offset += Hdr.LocalTypeUnitCount * 4;
Offset += Hdr.CompUnitCount * SectionOffsetSize;
Offset += Hdr.LocalTypeUnitCount * SectionOffsetSize;
Offset += Hdr.ForeignTypeUnitCount * 8;
BucketsBase = Offset;
Offset += Hdr.BucketCount * 4;
@ -508,9 +522,9 @@ Error DWARFDebugNames::NameIndex::extract() {
if (Hdr.BucketCount > 0)
Offset += Hdr.NameCount * 4;
StringOffsetsBase = Offset;
Offset += Hdr.NameCount * 4;
Offset += Hdr.NameCount * SectionOffsetSize;
EntryOffsetsBase = Offset;
Offset += Hdr.NameCount * 4;
Offset += Hdr.NameCount * SectionOffsetSize;
if (!AS.isValidOffsetForDataOfSize(Offset, Hdr.AbbrevTableSize))
return createStringError(errc::illegal_byte_sequence,
@ -591,20 +605,24 @@ std::error_code DWARFDebugNames::SentinelError::convertToErrorCode() const {
uint64_t DWARFDebugNames::NameIndex::getCUOffset(uint32_t CU) const {
assert(CU < Hdr.CompUnitCount);
uint64_t Offset = CUsBase + 4 * CU;
return Section.AccelSection.getRelocatedValue(4, &Offset);
const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
uint64_t Offset = CUsBase + SectionOffsetSize * CU;
return Section.AccelSection.getRelocatedValue(SectionOffsetSize, &Offset);
}
uint64_t DWARFDebugNames::NameIndex::getLocalTUOffset(uint32_t TU) const {
assert(TU < Hdr.LocalTypeUnitCount);
uint64_t Offset = CUsBase + 4 * (Hdr.CompUnitCount + TU);
return Section.AccelSection.getRelocatedValue(4, &Offset);
const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
uint64_t Offset = CUsBase + SectionOffsetSize * (Hdr.CompUnitCount + TU);
return Section.AccelSection.getRelocatedValue(SectionOffsetSize, &Offset);
}
uint64_t DWARFDebugNames::NameIndex::getForeignTUSignature(uint32_t TU) const {
assert(TU < Hdr.ForeignTypeUnitCount);
const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
uint64_t Offset =
CUsBase + 4 * (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) + 8 * TU;
CUsBase +
SectionOffsetSize * (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) + 8 * TU;
return Section.AccelSection.getU64(&Offset);
}
@ -625,7 +643,7 @@ DWARFDebugNames::NameIndex::getEntry(uint64_t *Offset) const {
Entry E(*this, *AbbrevIt);
dwarf::FormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32};
dwarf::FormParams FormParams = {Hdr.Version, 0, Hdr.Format};
for (auto &Value : E.Values) {
if (!Value.extractValue(AS, Offset, FormParams))
return createStringError(errc::io_error,
@ -637,12 +655,16 @@ DWARFDebugNames::NameIndex::getEntry(uint64_t *Offset) const {
DWARFDebugNames::NameTableEntry
DWARFDebugNames::NameIndex::getNameTableEntry(uint32_t Index) const {
assert(0 < Index && Index <= Hdr.NameCount);
uint64_t StringOffsetOffset = StringOffsetsBase + 4 * (Index - 1);
uint64_t EntryOffsetOffset = EntryOffsetsBase + 4 * (Index - 1);
const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
uint64_t StringOffsetOffset =
StringOffsetsBase + SectionOffsetSize * (Index - 1);
uint64_t EntryOffsetOffset =
EntryOffsetsBase + SectionOffsetSize * (Index - 1);
const DWARFDataExtractor &AS = Section.AccelSection;
uint64_t StringOffset = AS.getRelocatedValue(4, &StringOffsetOffset);
uint64_t EntryOffset = AS.getU32(&EntryOffsetOffset);
uint64_t StringOffset =
AS.getRelocatedValue(SectionOffsetSize, &StringOffsetOffset);
uint64_t EntryOffset = AS.getUnsigned(&EntryOffsetOffset, SectionOffsetSize);
EntryOffset += EntriesBase;
return {Section.StringSection, Index, StringOffset, EntryOffset};
}

View File

@ -93,6 +93,46 @@
.long 0 # End of list: bar
.p2align 2
.Lnames_end1:
.long 0xffffffff # DWARF64 mark
.quad .Lnames_end2-.Lnames_start2 # Length
.Lnames_start2:
.short 5 # Version
.space 2 # Padding
.long 1 # CU count
.long 1 # Local TU count
.long 1 # Foreign TU count
.long 1 # Bucket count
.long 1 # Name count
.long .Lnames_abbrev_end2-.Lnames_abbrev_start2 # Abbreviations table size
.long 0 # Augmentation string size
.quad 0xcc00cccccccc # CU0 offset
.quad 0xaa00aaaaaaaa # Local TU0 offset
.quad 0xffffff00ffffffff # Foreign TU2 signature
.long 1 # Bucket 0
.long 0xb887389 # Hash in Bucket 0
.quad .Linfo_string0 # String in Bucket 0: foo
.quad .Lnames3-.Lnames_entries2 # Offset in Bucket 0
.Lnames_abbrev_start2:
.byte 0x01 # Abbrev code
.byte 0x24 # DW_TAG_base_type
.byte 0x02 # DW_IDX_type_unit
.byte 0x06 # DW_FORM_data4
.byte 0x05 # DW_IDX_type_hash
.byte 0x07 # DW_FORM_data8
.byte 0x00 # End of abbrev
.byte 0x00 # End of abbrev
.byte 0x00 # End of abbrev list
.Lnames_abbrev_end2:
.Lnames_entries2:
.Lnames3:
.byte 0x01 # Abbrev code
.long 1 # DW_IDX_type_unit
.quad 0xff03ffffffff # DW_IDX_type_hash
.byte 0x00 # End of list: foo
.p2align 2
.Lnames_end2:
# CHECK: .debug_names contents:
# CHECK-NEXT: Name Index @ 0x0 {
# CHECK-NEXT: Header {
@ -172,3 +212,44 @@
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: }
# CHECK-NEXT: Name Index @ 0xac {
# CHECK-NEXT: Header {
# CHECK-NEXT: Length: 0x68
# CHECK-NEXT: Version: 5
# CHECK-NEXT: CU count: 1
# CHECK-NEXT: Local TU count: 1
# CHECK-NEXT: Foreign TU count: 1
# CHECK-NEXT: Bucket count: 1
# CHECK-NEXT: Name count: 1
# CHECK-NEXT: Abbreviations table size: 0x9
# CHECK-NEXT: Augmentation: ''
# CHECK-NEXT: }
# CHECK-NEXT: Compilation Unit offsets [
# CHECK-NEXT: CU[0]: 0xcc00cccccccc
# CHECK-NEXT: ]
# CHECK-NEXT: Local Type Unit offsets [
# CHECK-NEXT: LocalTU[0]: 0xaa00aaaaaaaa
# CHECK-NEXT: ]
# CHECK-NEXT: Foreign Type Unit signatures [
# CHECK-NEXT: ForeignTU[0]: 0xffffff00ffffffff
# CHECK-NEXT: ]
# CHECK-NEXT: Abbreviations [
# CHECK-NEXT: Abbreviation 0x1 {
# CHECK-NEXT: Tag: DW_TAG_base_type
# CHECK-NEXT: DW_IDX_type_unit: DW_FORM_data4
# CHECK-NEXT: DW_IDX_type_hash: DW_FORM_data8
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: Bucket 0 [
# CHECK-NEXT: Name 1 {
# CHECK-NEXT: Hash: 0xB887389
# CHECK-NEXT: String: 0x00000000 "foo"
# CHECK-NEXT: Entry @ 0x111 {
# CHECK-NEXT: Abbrev: 0x1
# CHECK-NEXT: Tag: DW_TAG_base_type
# CHECK-NEXT: DW_IDX_type_unit: 0x00000001
# CHECK-NEXT: DW_IDX_type_hash: 0x0000ff03ffffffff
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: }

View File

@ -11,6 +11,7 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(DebugInfoDWARFTests
DwarfGenerator.cpp
DwarfUtils.cpp
DWARFAcceleratorTableTest.cpp
DWARFDebugArangeSetTest.cpp
DWARFDebugInfoTest.cpp
DWARFDebugLineTest.cpp

View File

@ -0,0 +1,52 @@
//===- DWARFAcceleratorTableTest.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 "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
void ExpectDebugNamesExtractError(StringRef NamesSecData, StringRef StrSecData,
const char *ErrorMessage) {
DWARFSection NamesDWARFSection;
NamesDWARFSection.Data = NamesSecData;
StringMap<std::unique_ptr<MemoryBuffer>> Sections;
auto Context = DWARFContext::create(Sections, /* AddrSize = */ 4,
/* isLittleEndian = */ true);
DWARFDataExtractor NamesExtractor(Context->getDWARFObj(), NamesDWARFSection,
/* isLittleEndian = */ true,
/* AddrSize = */ 4);
DataExtractor StrExtractor(StrSecData,
/* isLittleEndian = */ true,
/* AddrSize = */ 4);
DWARFDebugNames Table(NamesExtractor, StrExtractor);
Error E = Table.extract();
ASSERT_TRUE(E.operator bool());
EXPECT_STREQ(ErrorMessage, toString(std::move(E)).c_str());
}
TEST(DWARFDebugNames, ReservedUnitLength) {
static const char NamesSecData[64] =
"\xf0\xff\xff\xff"; // Reserved unit length value
ExpectDebugNamesExtractError(StringRef(NamesSecData, sizeof(NamesSecData)),
StringRef(),
"Unsupported reserved unit length value");
}
TEST(DWARFDebugNames, TooSmallForDWARF64) {
// DWARF64 header takes at least 44 bytes.
static const char NamesSecData[43] = "\xff\xff\xff\xff"; // DWARF64 mark
ExpectDebugNamesExtractError(
StringRef(NamesSecData, sizeof(NamesSecData)), StringRef(),
"Section too small: cannot read header.");
}
} // end anonymous namespace