[llvm] d7733f8 - [DebugInfo] Expand ability to load 2-byte addresses in dwarf sections
David Blaikie via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 21 17:31:18 PDT 2021
Author: Jack Anderson
Date: 2021-10-21T17:31:00-07:00
New Revision: d7733f84228bde1079117e82b36fac94e9b323ed
URL: https://github.com/llvm/llvm-project/commit/d7733f84228bde1079117e82b36fac94e9b323ed
DIFF: https://github.com/llvm/llvm-project/commit/d7733f84228bde1079117e82b36fac94e9b323ed.diff
LOG: [DebugInfo] Expand ability to load 2-byte addresses in dwarf sections
Some dwarf loaders in LLVM are hard-coded to only accept 4-byte and 8-byte address sizes. This patch generalizes acceptance into `DWARFContext::isAddressSizeSupported` and provides a common way to generate rejection errors.
The MSP430 target has been given new tests to cover dwarf loading cases that previously failed due to 2-byte addresses.
Reviewed By: dblaikie
Differential Revision: https://reviews.llvm.org/D111953
Added:
llvm/test/DebugInfo/MSP430/cu-ranges.ll
llvm/test/DebugInfo/MSP430/dwarf-basics-v5.ll
llvm/test/DebugInfo/MSP430/ranges_always.ll
Modified:
llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp
llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp
llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp
llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp
llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
llvm/test/tools/llvm-dwarfdump/X86/debug_addr_invalid_addr_size.s
llvm/test/tools/llvm-dwarfdump/X86/debug_rnglists_invalid.s
llvm/unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
index 991605a664e7..353fbefc6b98 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
@@ -375,6 +375,23 @@ class DWARFContext : public DIContext {
static bool isAddressSizeSupported(unsigned AddressSize) {
return llvm::is_contained(getSupportedAddressSizes(), AddressSize);
}
+ template <typename... Ts>
+ static Error checkAddressSizeSupported(unsigned AddressSize,
+ std::error_code EC, char const *Fmt,
+ const Ts &...Vals) {
+ if (isAddressSizeSupported(AddressSize))
+ return Error::success();
+ std::string Buffer;
+ raw_string_ostream Stream(Buffer);
+ Stream << format(Fmt, Vals...)
+ << " has unsupported address size: " << AddressSize
+ << " (supported are ";
+ ListSeparator LS;
+ for (unsigned Size : DWARFContext::getSupportedAddressSizes())
+ Stream << LS << Size;
+ Stream << ')';
+ return make_error<StringError>(Stream.str(), EC);
+ }
std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath);
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
index 2f72c642a2d5..0d9f37c5610b 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
@@ -49,12 +49,7 @@ class DWARFDebugRangeList {
/// 2. An address, which defines the appropriate base address for
/// use in interpreting the beginning and ending address offsets of
/// subsequent entries of the location list.
- bool isBaseAddressSelectionEntry(uint8_t AddressSize) const {
- assert(AddressSize == 4 || AddressSize == 8);
- if (AddressSize == 4)
- return StartAddress == -1U;
- return StartAddress == -1ULL;
- }
+ bool isBaseAddressSelectionEntry(uint8_t AddressSize) const;
};
private:
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp
index dcf2aefeb39f..5b1c62e6a259 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp
@@ -8,7 +8,7 @@
#include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h"
#include "llvm/BinaryFormat/Dwarf.h"
-#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
using namespace llvm;
@@ -18,12 +18,10 @@ Error DWARFDebugAddrTable::extractAddresses(const DWARFDataExtractor &Data,
assert(EndOffset >= *OffsetPtr);
uint64_t DataSize = EndOffset - *OffsetPtr;
assert(Data.isValidOffsetForDataOfSize(*OffsetPtr, DataSize));
- if (AddrSize != 4 && AddrSize != 8)
- return createStringError(errc::not_supported,
- "address table at offset 0x%" PRIx64
- " has unsupported address size %" PRIu8
- " (4 and 8 are supported)",
- Offset, AddrSize);
+ if (Error SizeErr = DWARFContext::checkAddressSizeSupported(
+ AddrSize, errc::not_supported, "address table at offset 0x%" PRIx64,
+ Offset))
+ return SizeErr;
if (DataSize % AddrSize != 0) {
invalidateLength();
return createStringError(errc::invalid_argument,
@@ -148,8 +146,20 @@ void DWARFDebugAddrTable::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
}
if (Addrs.size() > 0) {
- const char *AddrFmt =
- (AddrSize == 4) ? "0x%8.8" PRIx64 "\n" : "0x%16.16" PRIx64 "\n";
+ const char *AddrFmt;
+ switch (AddrSize) {
+ case 2:
+ AddrFmt = "0x%4.4" PRIx64 "\n";
+ break;
+ case 4:
+ AddrFmt = "0x%8.8" PRIx64 "\n";
+ break;
+ case 8:
+ AddrFmt = "0x%16.16" PRIx64 "\n";
+ break;
+ default:
+ llvm_unreachable("unsupported address size");
+ }
OS << "Addrs: [\n";
for (uint64_t Addr : Addrs)
OS << format(AddrFmt, Addr);
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp
index 598e3ecee30e..c60c9d9d7227 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp
@@ -8,6 +8,7 @@
#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Format.h"
@@ -87,12 +88,10 @@ Error DWARFDebugArangeSet::extract(DWARFDataExtractor data,
"the length of address range table at offset "
"0x%" PRIx64 " exceeds section size",
Offset);
- if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8)
- return createStringError(errc::invalid_argument,
- "address range table at offset 0x%" PRIx64
- " has unsupported address size: %d "
- "(4 and 8 supported)",
- Offset, HeaderData.AddrSize);
+ if (Error SizeErr = DWARFContext::checkAddressSizeSupported(
+ HeaderData.AddrSize, errc::invalid_argument,
+ "address range table at offset 0x%" PRIx64, Offset))
+ return SizeErr;
if (HeaderData.SegSize != 0)
return createStringError(errc::not_supported,
"non-zero segment selector size in address range "
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp
index dc7da5d9348f..cad3dcab8a7e 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp
@@ -16,6 +16,12 @@
using namespace llvm;
+bool DWARFDebugRangeList::RangeListEntry::isBaseAddressSelectionEntry(
+ uint8_t AddressSize) const {
+ assert(DWARFContext::isAddressSizeSupported(AddressSize));
+ return StartAddress == dwarf::computeTombstoneAddress(AddressSize);
+}
+
void DWARFDebugRangeList::clear() {
Offset = -1ULL;
AddressSize = 0;
@@ -30,9 +36,10 @@ Error DWARFDebugRangeList::extract(const DWARFDataExtractor &data,
"invalid range list offset 0x%" PRIx64, *offset_ptr);
AddressSize = data.getAddressSize();
- if (AddressSize != 4 && AddressSize != 8)
- return createStringError(errc::invalid_argument,
- "invalid address size: %" PRIu8, AddressSize);
+ if (Error SizeErr = DWARFContext::checkAddressSizeSupported(
+ AddressSize, errc::invalid_argument,
+ "range list at offset 0x%" PRIx64, *offset_ptr))
+ return SizeErr;
Offset = *offset_ptr;
while (true) {
RangeListEntry Entry;
@@ -58,12 +65,22 @@ Error DWARFDebugRangeList::extract(const DWARFDataExtractor &data,
}
void DWARFDebugRangeList::dump(raw_ostream &OS) const {
- for (const RangeListEntry &RLE : Entries) {
- const char *format_str =
- (AddressSize == 4 ? "%08" PRIx64 " %08" PRIx64 " %08" PRIx64 "\n"
- : "%08" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n");
- OS << format(format_str, Offset, RLE.StartAddress, RLE.EndAddress);
+ const char *AddrFmt;
+ switch (AddressSize) {
+ case 2:
+ AddrFmt = "%08" PRIx64 " %04" PRIx64 " %04" PRIx64 "\n";
+ break;
+ case 4:
+ AddrFmt = "%08" PRIx64 " %08" PRIx64 " %08" PRIx64 "\n";
+ break;
+ case 8:
+ AddrFmt = "%08" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n";
+ break;
+ default:
+ llvm_unreachable("unsupported address size");
}
+ for (const RangeListEntry &RLE : Entries)
+ OS << format(AddrFmt, Offset, RLE.StartAddress, RLE.EndAddress);
OS << format("%08" PRIx64 " <End of list>\n", Offset);
}
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp
index c876af1e9b51..b73dda3ff9ce 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp
@@ -8,6 +8,7 @@
#include "llvm/DebugInfo/DWARF/DWARFListTable.h"
#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Format.h"
@@ -54,11 +55,10 @@ Error DWARFListTableHeader::extract(DWARFDataExtractor Data,
"unrecognised %s table version %" PRIu16
" in table at offset 0x%" PRIx64,
SectionName.data(), HeaderData.Version, HeaderOffset);
- if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8)
- return createStringError(errc::not_supported,
- "%s table at offset 0x%" PRIx64
- " has unsupported address size %" PRIu8,
- SectionName.data(), HeaderOffset, HeaderData.AddrSize);
+ if (Error SizeErr = DWARFContext::checkAddressSizeSupported(
+ HeaderData.AddrSize, errc::not_supported,
+ "%s table at offset 0x%" PRIx64, SectionName.data(), HeaderOffset))
+ return SizeErr;
if (HeaderData.SegSize != 0)
return createStringError(errc::not_supported,
"%s table at offset 0x%" PRIx64
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
index d3904248efce..82c34f537036 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -315,15 +315,10 @@ bool DWARFUnitHeader::extract(DWARFContext &Context,
return false;
}
- if (!DWARFContext::isAddressSizeSupported(getAddressByteSize())) {
- SmallVector<std::string, 3> Sizes;
- for (auto Size : DWARFContext::getSupportedAddressSizes())
- Sizes.push_back(std::to_string(Size));
- Context.getWarningHandler()(createStringError(
- errc::invalid_argument,
- "DWARF unit at offset 0x%8.8" PRIx64 " "
- "has unsupported address size %" PRIu8 ", supported are %s",
- Offset, getAddressByteSize(), llvm::join(Sizes, ", ").c_str()));
+ if (Error SizeErr = DWARFContext::checkAddressSizeSupported(
+ getAddressByteSize(), errc::invalid_argument,
+ "DWARF unit at offset 0x%8.8" PRIx64, Offset)) {
+ Context.getWarningHandler()(std::move(SizeErr));
return false;
}
diff --git a/llvm/test/DebugInfo/MSP430/cu-ranges.ll b/llvm/test/DebugInfo/MSP430/cu-ranges.ll
new file mode 100644
index 000000000000..9648d39256b6
--- /dev/null
+++ b/llvm/test/DebugInfo/MSP430/cu-ranges.ll
@@ -0,0 +1,72 @@
+; RUN: llc -O0 -mtriple=msp430 -filetype=obj %s -o %t
+; RUN: llvm-dwarfdump -v %t | FileCheck %s
+
+; Ported from generic test to cover 2-byte address size case
+
+; Check that we emit ranges for this which has a non-traditional section and a normal section.
+
+; CHECK: DW_TAG_compile_unit
+; CHECK: DW_AT_ranges
+; CHECK: DW_TAG_subprogram
+; CHECK: DW_AT_low_pc
+; CHECK: DW_AT_high_pc
+; CHECK: DW_TAG_subprogram
+; CHECK: DW_AT_low_pc
+; CHECK: DW_AT_high_pc
+
+; CHECK: .debug_ranges contents:
+; CHECK-NEXT: 00000000 0000 0030
+; CHECK-NEXT: 00000000 0000 0030
+; CHECK-NEXT: 00000000 <End of list>
+
+; Function Attrs: nounwind uwtable
+define i32 @foo(i32 %a) #0 section "__TEXT,__foo" !dbg !4 {
+entry:
+ %a.addr = alloca i32, align 4
+ store i32 %a, i32* %a.addr, align 4
+ call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !13, metadata !DIExpression()), !dbg !14
+ %0 = load i32, i32* %a.addr, align 4, !dbg !15
+ %add = add nsw i32 %0, 5, !dbg !15
+ ret i32 %add, !dbg !15
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+; Function Attrs: nounwind uwtable
+define i32 @bar(i32 %a) #0 !dbg !9 {
+entry:
+ %a.addr = alloca i32, align 4
+ store i32 %a, i32* %a.addr, align 4
+ call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !16, metadata !DIExpression()), !dbg !17
+ %0 = load i32, i32* %a.addr, align 4, !dbg !18
+ %add = add nsw i32 %0, 5, !dbg !18
+ ret i32 %add, !dbg !18
+}
+
+attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "frame-pointer"="all" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!10, !11}
+!llvm.ident = !{!12}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.5.0 (trunk 204164) (llvm/trunk 204183)", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2)
+!1 = !DIFile(filename: "foo.c", directory: "/usr/local/google/home/echristo")
+!2 = !{}
+!4 = distinct !DISubprogram(name: "foo", line: 1, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 1, file: !1, scope: !5, type: !6, retainedNodes: !2)
+!5 = !DIFile(filename: "foo.c", directory: "/usr/local/google/home/echristo")
+!6 = !DISubroutineType(types: !7)
+!7 = !{!8, !8}
+!8 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!9 = distinct !DISubprogram(name: "bar", line: 5, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 5, file: !1, scope: !5, type: !6, retainedNodes: !2)
+!10 = !{i32 2, !"Dwarf Version", i32 4}
+!11 = !{i32 1, !"Debug Info Version", i32 3}
+!12 = !{!"clang version 3.5.0 (trunk 204164) (llvm/trunk 204183)"}
+!13 = !DILocalVariable(name: "a", line: 1, arg: 1, scope: !4, file: !5, type: !8)
+!14 = !DILocation(line: 1, scope: !4)
+!15 = !DILocation(line: 2, scope: !4)
+!16 = !DILocalVariable(name: "a", line: 5, arg: 1, scope: !9, file: !5, type: !8)
+!17 = !DILocation(line: 5, scope: !9)
+!18 = !DILocation(line: 6, scope: !9)
+
diff --git a/llvm/test/DebugInfo/MSP430/dwarf-basics-v5.ll b/llvm/test/DebugInfo/MSP430/dwarf-basics-v5.ll
new file mode 100644
index 000000000000..98922f1b7d08
--- /dev/null
+++ b/llvm/test/DebugInfo/MSP430/dwarf-basics-v5.ll
@@ -0,0 +1,154 @@
+; RUN: llc -generate-arange-section -minimize-addr-in-v5=Ranges --filetype=obj -o %t < %s
+; RUN: llvm-dwarfdump --debug-info -debug-aranges -debug-addr %t | FileCheck %s
+; RUN: llvm-dwarfdump --verify %t
+
+; This file was based on output of
+;
+; clang -target msp430 -S -emit-llvm -gdwarf-5 -Os dwarf-basics-v5.c
+;
+; for the following dwarf-basics-v5.c
+;
+; struct X {
+; void *a;
+; };
+;
+; int f(long y, struct X *p)
+; {
+; return 42;
+; }
+;
+
+; CHECK: file format elf32-msp430
+
+; CHECK: .debug_info contents:
+; CHECK: Compile Unit: length = 0x{{.*}}, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = 0x0000, addr_size = 0x02 (next unit at 0x{{.*}})
+
+; CHECK: DW_TAG_compile_unit
+; CHECK: DW_AT_producer ("clang version 14.0.0 (git at ...)")
+; CHECK: DW_AT_language (DW_LANG_C99)
+; CHECK: DW_AT_name ("dwarf-basics-v5.c")
+; CHECK: DW_AT_str_offsets_base (0x00000008)
+; CHECK: DW_AT_stmt_list (0x{{.*}})
+; CHECK: DW_AT_comp_dir ("/tmp")
+; CHECK: DW_AT_low_pc (0x{{.*}})
+; CHECK: DW_AT_high_pc (0x{{.*}})
+; CHECK: DW_AT_addr_base (0x00000008)
+; CHECK: DW_AT_loclists_base (0x0000000c)
+
+; CHECK: DW_TAG_subprogram
+; CHECK: DW_AT_low_pc (0x{{.*}})
+; CHECK: DW_AT_high_pc (0x{{.*}})
+; CHECK: DW_AT_frame_base (DW_OP_reg1 SPB)
+; CHECK: DW_AT_call_all_calls (true)
+; CHECK: DW_AT_name ("f")
+; CHECK: DW_AT_decl_file ("/tmp{{[/\\]}}dwarf-basics-v5.c")
+; CHECK: DW_AT_decl_line (5)
+; CHECK: DW_AT_prototyped (true)
+; CHECK: DW_AT_type (0x{{.*}} "int")
+; CHECK: DW_AT_external (true)
+
+; CHECK: DW_TAG_formal_parameter
+; CHECK: DW_AT_location (indexed (0x0) loclist = 0x{{.*}}:
+; CHECK: [0x0000, 0x0004): DW_OP_reg12 R12B)
+; CHECK: DW_AT_name ("y")
+; CHECK: DW_AT_decl_file ("/tmp{{[/\\]}}dwarf-basics-v5.c")
+; CHECK: DW_AT_decl_line (5)
+; CHECK: DW_AT_type (0x{{.*}} "long")
+
+; CHECK: DW_TAG_formal_parameter
+; CHECK: DW_AT_location (DW_OP_reg14 R14B)
+; CHECK: DW_AT_name ("p")
+; CHECK: DW_AT_decl_file ("/tmp{{[/\\]}}dwarf-basics-v5.c")
+; CHECK: DW_AT_decl_line (5)
+; CHECK: DW_AT_type (0x{{.*}} "X *")
+
+; CHECK: NULL
+
+; CHECK: DW_TAG_base_type
+; CHECK: DW_AT_name ("int")
+; CHECK: DW_AT_encoding (DW_ATE_signed)
+; CHECK: DW_AT_byte_size (0x02)
+
+; CHECK: DW_TAG_base_type
+; CHECK: DW_AT_name ("long")
+; CHECK: DW_AT_encoding (DW_ATE_signed)
+; CHECK: DW_AT_byte_size (0x04)
+
+; CHECK: DW_TAG_pointer_type
+; CHECK: DW_AT_type (0x{{.*}} "X")
+
+; CHECK: DW_TAG_structure_type
+; CHECK: DW_AT_name ("X")
+; CHECK: DW_AT_byte_size (0x02)
+; CHECK: DW_AT_decl_file ("/tmp{{[/\\]}}dwarf-basics-v5.c")
+; CHECK: DW_AT_decl_line (1)
+
+; CHECK: DW_TAG_member
+; CHECK: DW_AT_name ("a")
+; CHECK: DW_AT_type (0x{{.*}} "void *")
+; CHECK: DW_AT_decl_file ("/tmp{{[/\\]}}dwarf-basics-v5.c")
+; CHECK: DW_AT_decl_line (2)
+; CHECK: DW_AT_data_member_location (0x00)
+
+; CHECK: NULL
+
+; CHECK: DW_TAG_pointer_type
+
+; CHECK: NULL
+
+; CHECK: .debug_aranges contents:
+; CHECK-NEXT: Address Range Header: length = 0x{{.*}}, format = DWARF32, version = 0x0002, cu_offset = 0x00000000, addr_size = 0x02, seg_size = 0x00
+; CHECK-NEXT: [0x0000, 0x0006)
+
+; CHECK: .debug_addr contents:
+; CHECK-NEXT: Address table header: length = 0x{{.*}}, format = DWARF32, version = 0x0005, addr_size = 0x02, seg_size = 0x00
+; CHECK-NEXT: Addrs: [
+; CHECK-NEXT: 0x0000
+; CHECK-NEXT: ]
+
+; ModuleID = 'dwarf-basics-v5.c'
+source_filename = "dwarf-basics-v5.c"
+target datalayout = "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16"
+target triple = "msp430"
+
+%struct.X = type { i8* }
+
+; Function Attrs: mustprogress nofree norecurse nosync nounwind optsize readnone willreturn
+define dso_local i16 @f(i32 noundef %y, %struct.X* nocapture noundef readnone %p) local_unnamed_addr #0 !dbg !6 {
+entry:
+ call void @llvm.dbg.value(metadata i32 %y, metadata !17, metadata !DIExpression()), !dbg !19
+ call void @llvm.dbg.value(metadata %struct.X* %p, metadata !18, metadata !DIExpression()), !dbg !19
+ ret i16 42, !dbg !20
+}
+
+; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
+declare void @llvm.dbg.value(metadata, metadata, metadata) #1
+
+attributes #0 = { mustprogress nofree norecurse nosync nounwind optsize readnone willreturn "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #1 = { nofree nosync nounwind readnone speculatable willreturn }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4}
+!llvm.ident = !{!5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 14.0.0 (git at ...)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "dwarf-basics-v5.c", directory: "/tmp", checksumkind: CSK_MD5, checksum: "ead340d457001e2ce340630cfa3a9cb8")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 2}
+!5 = !{!"clang version 14.0.0 (git at ...)"}
+!6 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 5, type: !7, scopeLine: 6, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !16)
+!7 = !DISubroutineType(types: !8)
+!8 = !{!9, !10, !11}
+!9 = !DIBasicType(name: "int", size: 16, encoding: DW_ATE_signed)
+!10 = !DIBasicType(name: "long", size: 32, encoding: DW_ATE_signed)
+!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 16)
+!12 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "X", file: !1, line: 1, size: 16, elements: !13)
+!13 = !{!14}
+!14 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !12, file: !1, line: 2, baseType: !15, size: 16)
+!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 16)
+!16 = !{!17, !18}
+!17 = !DILocalVariable(name: "y", arg: 1, scope: !6, file: !1, line: 5, type: !10)
+!18 = !DILocalVariable(name: "p", arg: 2, scope: !6, file: !1, line: 5, type: !11)
+!19 = !DILocation(line: 0, scope: !6)
+!20 = !DILocation(line: 7, column: 3, scope: !6)
diff --git a/llvm/test/DebugInfo/MSP430/ranges_always.ll b/llvm/test/DebugInfo/MSP430/ranges_always.ll
new file mode 100644
index 000000000000..f8fe03d21087
--- /dev/null
+++ b/llvm/test/DebugInfo/MSP430/ranges_always.ll
@@ -0,0 +1,241 @@
+; RUN: llc -O0 %s -mtriple=msp430 -filetype=obj -o - -minimize-addr-in-v5=Ranges \
+; RUN: | llvm-dwarfdump -debug-info -debug-addr -debug-rnglists -v - \
+; RUN: | FileCheck --check-prefix=CHECK --check-prefix=RNG \
+; RUN: --implicit-check-not=DW_TAG --implicit-check-not=NULL --implicit-check-not=_pc %s
+
+; RUN: llc -O0 %s -mtriple=msp430 -filetype=obj -o - -minimize-addr-in-v5=Expressions \
+; RUN: | llvm-dwarfdump -debug-info -debug-addr -debug-rnglists -v - \
+; RUN: | FileCheck --check-prefix=CHECK --check-prefix=EXPRORFORM --check-prefix=EXPR\
+; RUN: --implicit-check-not=DW_TAG --implicit-check-not=NULL --implicit-check-not=_pc %s
+
+; RUN: llc -O0 %s -mtriple=msp430 -filetype=obj -o - -minimize-addr-in-v5=Form \
+; RUN: | llvm-dwarfdump -debug-info -debug-addr -debug-rnglists -v - \
+; RUN: | FileCheck --check-prefix=CHECK --check-prefix=EXPRORFORM --check-prefix=FORM \
+; RUN: --implicit-check-not=DW_TAG --implicit-check-not=NULL --implicit-check-not=_pc %s
+
+; Ported from X86 test to cover 2-byte address size case
+
+; Generated from the following source. f4 is used to put a hole in the CU
+; ranges while keeping f2 and f4 in the same section (as opposed to
+; -ffunction-sections, which would produce CU ranges, but each function would
+; be in a
diff erent section, so unable to share addresses). The call to f1 at
+; the start of f3 ensures the range for the inlined subroutine doesn't share
+; the starting address with f3 (so it can be improved by using a rnglist to
+; allow it to share an address it wouldn't already be sharing).
+
+; Without f6 being in another section, technically we could use a non-zero CU
+; low_pc that could act as a base address for all the addresses in the CU & avoid
+; the need for these forced rnglists - we don't do that currently, but f6 ensures
+; that this test will remain meaningful even if that improvement is made in the
+; future. (implementing that would require detecting that all the addresses in
+; the CU ranges are in the same section, then picking the lowest such address as
+; the base address to make all other addresses relative to)
+
+; IR from the following, compiled with:
+; $ clang -g -c -gdwarf-5 -O1
+; __attribute__((optnone)) void f1() { }
+; __attribute__((always_inline)) inline void f2() {
+; f1();
+; }
+; void f3() {
+; f1();
+; f2();
+; }
+; __attribute__((nodebug)) void f4() {
+; }
+; void f5() {
+; }
+; __attribute__((section(".other"))) void f6() {
+; }
+
+; CHECK-LABEL: .debug_info contents:
+; CHECK: DW_TAG_compile_unit
+; CHECK: DW_AT_low_pc
+; CHECK-SAME: (0x0000)
+; RNG: DW_AT_ranges
+; RNG-SAME: (indexed (0x3) rangelist = [[CU_RANGE:.*]]
+; EXPRORFORM: DW_AT_ranges
+; EXPRORFORM-SAME: (indexed (0x0) rangelist = [[CU_RANGE:.*]]
+; CHECK: DW_TAG_subprogram
+; CHECK: DW_AT_low_pc
+; CHECK-SAME: (indexed (00000000) address = 0x0000 ".text")
+; CHECK: DW_AT_high_pc
+; CHECK-SAME: (0x00000002)
+; CHECK: DW_AT_name
+; CHECK-SAME: "f1"
+; CHECK: DW_TAG_subprogram
+; CHECK: DW_AT_name
+; CHECK-SAME: "f2"
+; CHECK: DW_TAG_subprogram
+; EXPR: DW_AT_low_pc
+; EXPR-SAME: (DW_OP_addrx 0x0, DW_OP_const4u 0x2, DW_OP_plus)
+; FORM: DW_AT_low_pc
+; FORM-SAME: [DW_FORM_LLVM_addrx_offset] (indexed (00000000) + 0x2 address = 0x0002 ".text")
+; EXPRORFORM: DW_AT_high_pc
+; EXPRORFORM-SAME: (0x0000000a)
+; RNG: DW_AT_ranges
+; RNG-SAME: (indexed (0x0) rangelist = [[F3_RANGE:.*]]
+; CHECK: DW_AT_name
+; CHECK-SAME: "f3"
+; CHECK: DW_TAG_inlined_subroutine
+; EXPR: DW_AT_low_pc
+; EXPR-SAME: [DW_FORM_exprloc] (DW_OP_addrx 0x0, DW_OP_const4u 0x6, DW_OP_plus)
+; FORM: DW_AT_low_pc
+; FORM-SAME: [DW_FORM_LLVM_addrx_offset] (indexed (00000000) + 0x6 address = 0x0006 ".text")
+; EXPRORFORM: DW_AT_high_pc
+; EXPRORFORM-SAME: (0x00000004)
+; RNG: DW_AT_ranges
+; RNG-SAME: (indexed (0x1) rangelist = [[INL_RANGE:.*]]
+; CHECK: DW_TAG_call_site
+; RNG: DW_AT_call_return_pc
+; RNG-SAME: (indexed (00000001) address = 0x0006 ".text")
+; EXPR: DW_AT_call_return_pc
+; EXPR-SAME: [DW_FORM_exprloc] (DW_OP_addrx 0x0, DW_OP_const4u 0x6, DW_OP_plus)
+; FORM: DW_AT_call_return_pc
+; FORM-SAME: [DW_FORM_LLVM_addrx_offset] (indexed (00000000) + 0x6 address = 0x0006 ".text")
+; CHECK: DW_TAG_call_site
+; RNG: DW_AT_call_return_pc
+; RNG-SAME: (indexed (00000002) address = 0x000a ".text")
+; EXPR: DW_AT_call_return_pc
+; EXPR-SAME: [DW_FORM_exprloc] (DW_OP_addrx 0x0, DW_OP_const4u 0xa, DW_OP_plus)
+; FORM: DW_AT_call_return_pc
+; FORM-SAME: [DW_FORM_LLVM_addrx_offset] (indexed (00000000) + 0xa address = 0x000a ".text")
+; CHECK: NULL
+; CHECK: DW_TAG_subprogram
+; EXPR: DW_AT_low_pc
+; EXPR-SAME: [DW_FORM_exprloc] (DW_OP_addrx 0x0, DW_OP_const4u 0xe, DW_OP_plus)
+; FORM: DW_AT_low_pc
+; FORM-SAME: [DW_FORM_LLVM_addrx_offset] (indexed (00000000) + 0xe address = 0x000e ".text")
+; EXPRORFORM: DW_AT_high_pc
+; EXPRORFORM-SAME: (0x00000002)
+; RNG: DW_AT_ranges
+; RNG-SAME: (indexed (0x2) rangelist = [[F5_RANGE:.*]]
+; CHECK: DW_AT_name
+; CHECK-SAME: "f5"
+; CHECK: DW_TAG_subprogram
+; CHECK: DW_AT_low_pc [DW_FORM_addrx] (indexed (
+; RNG-SAME: 00000003
+; EXPRORFORM-SAME: 00000001
+; CHECK: ) address = 0x0000 ".other")
+; CHECK: DW_AT_high_pc
+; CHECK-SAME: (0x00000006)
+; CHECK: DW_AT_name
+; CHECK-SAME: "f6"
+; CHECK: DW_TAG_inlined_subroutine
+; RNG: DW_AT_low_pc
+; RNG-SAME: (indexed (00000003) address = 0x0000 ".other")
+; EXPRORFORM: DW_AT_low_pc
+; EXPRORFORM-SAME: (indexed (00000001) address = 0x0000 ".other")
+; CHECK: DW_AT_high_pc
+; CHECK-SAME: (0x00000004)
+; CHECK: DW_TAG_call_site
+; CHECK: DW_AT_call_return_pc
+; CHECK: NULL
+; CHECK: NULL
+
+; CHECK-LABEL: .debug_addr contents:
+; CHECK: 0x00000000: Address table
+; CHECK-NEXT: Addrs: [
+; CHECK-NEXT: 0x0000
+; RNG-NEXT: 0x0006
+; RNG-NEXT: 0x000a
+; CHECK-NEXT: 0x0000
+; RNG-NEXT: 0x0004
+; CHECK-NEXT: ]
+
+; CHECK-LABEL: .debug_rnglists contents:
+; RNG: 0x00000000: range list header: {{.*}}, offset_entry_count = 0x00000004
+; EXPRORFORM: 0x00000000: range list header: {{.*}}, offset_entry_count = 0x00000001
+; CHECK: ranges:
+; RNG-NEXT: [[F3_RANGE]]: [DW_RLE_base_addressx]:
+; RNG-SAME: 0x0000
+; RNG-NEXT: [DW_RLE_offset_pair ]
+; RNG-NEXT: [DW_RLE_end_of_list ]
+
+; RNG-NEXT: [[INL_RANGE]]: [DW_RLE_base_addressx]:
+; RNG-SAME: 0x0000
+; RNG-NEXT: [DW_RLE_offset_pair ]
+; RNG-NEXT: [DW_RLE_end_of_list ]
+
+; RNG-NEXT: [[F5_RANGE]]: [DW_RLE_base_addressx]:
+; RNG-SAME: 0x0000
+; RNG-NEXT: [DW_RLE_offset_pair ]
+; RNG-NEXT: [DW_RLE_end_of_list ]
+
+; CHECK-NEXT: [[CU_RANGE]]: [DW_RLE_base_addressx]:
+; CHECK-SAME: 0x0000
+; CHECK-NEXT: [DW_RLE_offset_pair ]
+; CHECK-NEXT: [DW_RLE_offset_pair ]
+; RNG-NEXT: [DW_RLE_startx_length]:
+; RNG-SAME: 0x0003
+; EXPRORFORM-NEXT: [DW_RLE_startx_length]:
+; EXPRORFORM-SAME: 0x0001
+; CHECK-NEXT: [DW_RLE_end_of_list ]
+
+; Function Attrs: mustprogress noinline nounwind optnone uwtable
+define dso_local void @_Z2f1v() local_unnamed_addr #0 !dbg !7 {
+entry:
+ ret void, !dbg !12
+}
+
+; Function Attrs: mustprogress nounwind uwtable
+define dso_local void @_Z2f3v() local_unnamed_addr #1 !dbg !13 {
+entry:
+ call void @_Z2f1v(), !dbg !14
+ call void @_Z2f1v() #3, !dbg !15
+ ret void, !dbg !18
+}
+
+; Function Attrs: mustprogress nofree norecurse nosync nounwind readnone uwtable willreturn
+define dso_local void @_Z2f4v() local_unnamed_addr #2 {
+entry:
+ ret void
+}
+
+; Function Attrs: mustprogress nofree norecurse nosync nounwind readnone uwtable willreturn
+define dso_local void @_Z2f5v() local_unnamed_addr #2 !dbg !19 {
+entry:
+ ret void, !dbg !20
+}
+
+; Function Attrs: mustprogress nounwind uwtable
+define dso_local void @_Z2f6v() local_unnamed_addr #1 section ".other" !dbg !21 {
+entry:
+ call void @_Z2f1v() #3, !dbg !22
+ ret void, !dbg !24
+}
+
+attributes #0 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #1 = { mustprogress nounwind uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #2 = { mustprogress nofree norecurse nosync nounwind readnone uwtable willreturn "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #3 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 14.0.0 (git at github.com:llvm/llvm-project.git e2c3dc6fc76e767f08249f6d2c36e41660a4e331)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "/usr/local/google/home/blaikie/dev/scratch/test.cpp", directory: "/usr/local/google/home/blaikie/dev/llvm/src", checksumkind: CSK_MD5, checksum: "e70db21a276125757057e729999c09c7")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 7, !"uwtable", i32 1}
+!6 = !{!"clang version 14.0.0 (git at github.com:llvm/llvm-project.git e2c3dc6fc76e767f08249f6d2c36e41660a4e331)"}
+!7 = distinct !DISubprogram(name: "f1", linkageName: "_Z2f1v", scope: !8, file: !8, line: 1, type: !9, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
+!8 = !DIFile(filename: "scratch/test.cpp", directory: "/usr/local/google/home/blaikie/dev", checksumkind: CSK_MD5, checksum: "e70db21a276125757057e729999c09c7")
+!9 = !DISubroutineType(types: !10)
+!10 = !{null}
+!11 = !{}
+!12 = !DILocation(line: 1, column: 38, scope: !7)
+!13 = distinct !DISubprogram(name: "f3", linkageName: "_Z2f3v", scope: !8, file: !8, line: 5, type: !9, scopeLine: 5, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
+!14 = !DILocation(line: 6, column: 3, scope: !13)
+!15 = !DILocation(line: 3, column: 3, scope: !16, inlinedAt: !17)
+!16 = distinct !DISubprogram(name: "f2", linkageName: "_Z2f2v", scope: !8, file: !8, line: 2, type: !9, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
+!17 = distinct !DILocation(line: 7, column: 3, scope: !13)
+!18 = !DILocation(line: 8, column: 1, scope: !13)
+!19 = distinct !DISubprogram(name: "f5", linkageName: "_Z2f5v", scope: !8, file: !8, line: 11, type: !9, scopeLine: 11, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
+!20 = !DILocation(line: 12, column: 1, scope: !19)
+!21 = distinct !DISubprogram(name: "f6", linkageName: "_Z2f6v", scope: !8, file: !8, line: 13, type: !9, scopeLine: 13, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
+!22 = !DILocation(line: 3, column: 3, scope: !16, inlinedAt: !23)
+!23 = distinct !DILocation(line: 14, column: 3, scope: !21)
+!24 = !DILocation(line: 15, column: 1, scope: !21)
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_invalid_addr_size.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_invalid_addr_size.s
index 2638471f4426..873cc9e7a81d 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_invalid_addr_size.s
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_invalid_addr_size.s
@@ -4,7 +4,7 @@
# CHECK: .debug_addr contents:
# CHECK-NOT: {{.}}
-# ERR: unsupported address size 3 (4 and 8 are supported)
+# ERR: unsupported address size: 3 (supported are 2, 4, 8)
# ERR-NOT: {{.}}
# invalid addr size
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_rnglists_invalid.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_rnglists_invalid.s
index 0abef7f8159a..e02a8a5efcf0 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/debug_rnglists_invalid.s
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_rnglists_invalid.s
@@ -27,7 +27,7 @@
# CHECK-NOT: error:
# CHECK: error: .debug_rnglists table at offset 0x22 has too small length (0xb) to contain a complete header
# CHECK-NEXT: error: unrecognised .debug_rnglists table version 4 in table at offset 0x2d
-# CHECK-NEXT: error: .debug_rnglists table at offset 0x39 has unsupported address size 2
+# CHECK-NEXT: error: .debug_rnglists table at offset 0x39 has unsupported address size: 3
# CHECK-NEXT: error: .debug_rnglists table at offset 0x45 has unsupported segment selector size 4
# CHECK-NEXT: error: .debug_rnglists table at offset 0x51 has more offset entries (12345678) than there is space for
# CHECK-NEXT: error: read past end of table when reading DW_RLE_start_end encoding at offset 0x69
@@ -71,7 +71,7 @@
# Table 4 (unsupported address size)
.long 8 # Table length
.short 5 # Version
-.byte 2 # Address size
+.byte 3 # Address size
.byte 0 # Segment selector size
.long 0 # Offset entry count
diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp
index bdd4ca5b0199..1a7161b4a435 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp
@@ -75,14 +75,14 @@ TEST(DWARFDebugArangeSet, UnsupportedAddressSize) {
"\x0c\x00\x00\x00" // Length
"\x02\x00" // Version
"\x00\x00\x00\x00" // Debug Info Offset
- "\x02" // Address Size (not supported)
+ "\x03" // Address Size (not supported)
"\x00" // Segment Selector Size
// No padding
"\x00\x00\x00\x00"; // Termination tuple
ExpectExtractError(
DebugArangesSecRaw,
- "address range table at offset 0x0 has unsupported address size: 2 "
- "(4 and 8 supported)");
+ "address range table at offset 0x0 has unsupported address size: 3 "
+ "(supported are 2, 4, 8)");
}
TEST(DWARFDebugArangeSet, UnsupportedSegmentSelectorSize) {
More information about the llvm-commits
mailing list