forked from OSchip/llvm-project
[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
This commit is contained in:
parent
09b95b9dc9
commit
d7733f8422
|
@ -375,6 +375,23 @@ public:
|
|||
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);
|
||||
|
||||
|
|
|
@ -49,12 +49,7 @@ public:
|
|||
/// 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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 "
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
@ -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@...)")
|
||||
; 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@...)", 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@...)"}
|
||||
!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)
|
|
@ -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 different 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@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@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)
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue