[llvm] 16a0313 - [DWARF] Add support for 64-bit DWARF in .debug_names.
Igor Kudrin via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 31 01:14:10 PST 2020
Author: Igor Kudrin
Date: 2020-01-31T16:12:35+07:00
New Revision: 16a0313ee328f093682d5924eef6313cd4a8fcbe
URL: https://github.com/llvm/llvm-project/commit/16a0313ee328f093682d5924eef6313cd4a8fcbe
DIFF: https://github.com/llvm/llvm-project/commit/16a0313ee328f093682d5924eef6313cd4a8fcbe.diff
LOG: [DWARF] Add support for 64-bit DWARF in .debug_names.
Differential Revision: https://reviews.llvm.org/D72900
Added:
llvm/unittests/DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp
Modified:
llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
llvm/test/DebugInfo/X86/dwarfdump-debug-names.s
llvm/unittests/DebugInfo/DWARF/CMakeLists.txt
Removed:
################################################################################
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
index f1e02aae5564..961a8d82fe9e 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
@@ -229,7 +229,8 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
/// 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 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
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;
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
index a5f257fe9cce..bfcd0960faec 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
@@ -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};
}
diff --git a/llvm/test/DebugInfo/X86/dwarfdump-debug-names.s b/llvm/test/DebugInfo/X86/dwarfdump-debug-names.s
index ccfb6fc538f7..cc3de5dcc967 100644
--- a/llvm/test/DebugInfo/X86/dwarfdump-debug-names.s
+++ b/llvm/test/DebugInfo/X86/dwarfdump-debug-names.s
@@ -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: }
diff --git a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt
index 611621dbd379..68d7840b6e6d 100644
--- a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt
+++ b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt
@@ -11,6 +11,7 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(DebugInfoDWARFTests
DwarfGenerator.cpp
DwarfUtils.cpp
+ DWARFAcceleratorTableTest.cpp
DWARFDebugArangeSetTest.cpp
DWARFDebugInfoTest.cpp
DWARFDebugLineTest.cpp
diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp
new file mode 100644
index 000000000000..17a4b7474bfb
--- /dev/null
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp
@@ -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
More information about the llvm-commits
mailing list