Skip to content

Commit 44deaf7

Browse files
committed
[DWARF][RISCV] Add support for RISC-V relocations needed for debug info
When code relaxation is enabled many RISC-V fixups are not resolved but instead relocations are emitted. This happens even for DWARF debug sections. Therefore, to properly support the parsing of DWARF debug info we need to be able to resolve RISC-V relocations. This patch adds: * Support for RISC-V relocations in RelocationResolver * DWARF support for two relocations per object file offset * DWARF changes to support relocations in more DIE fields The two relocations per offset change is needed because some RISC-V relocations (used for label differences) come in pairs. Relocations can also be emitted for DWARF fields where relocations were not yet evaluated. Adding relocation support for some of these fields is essencial. On the other hand, LLVM currently emits RISC-V relocations for fixups that could be safely evaluated, since they can never be affected by code relaxations. This patch also adds relocation support for the fields affected by those extraneous relocations (the DWARF unit entry Length, and the DWARF debug line entry TotalLength and PrologueLength), for testing purposes. Differential Revision: https://reviews.llvm.org/D62062 Patch by Luís Marques. llvm-svn: 366402
1 parent 1d5cbb7 commit 44deaf7

File tree

10 files changed

+194
-13
lines changed

10 files changed

+194
-13
lines changed

lld/ELF/DWARF.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ LLDDwarfObj<ELFT>::findAux(const InputSectionBase &sec, uint64_t pos,
110110
DataRefImpl d;
111111
d.p = getAddend<ELFT>(rel);
112112
return RelocAddrEntry{secIndex, RelocationRef(d, nullptr),
113-
LLDRelocationResolver<RelTy>::resolve, val};
113+
val, Optional<object::RelocationRef>(),
114+
0, LLDRelocationResolver<RelTy>::resolve};
114115
}
115116

116117
template <class ELFT>

llvm/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ namespace llvm {
2020
struct RelocAddrEntry {
2121
uint64_t SectionIndex;
2222
object::RelocationRef Reloc;
23-
object::RelocationResolver Resolver;
2423
uint64_t SymbolValue;
24+
Optional<object::RelocationRef> Reloc2;
25+
uint64_t SymbolValue2;
26+
object::RelocationResolver Resolver;
2527
};
2628

2729
/// In place of applying the relocations to the data we've read from disk we use

llvm/lib/DebugInfo/DWARF/DWARFContext.cpp

+19-3
Original file line numberDiff line numberDiff line change
@@ -1651,9 +1651,25 @@ class DWARFObjInMemory final : public DWARFObject {
16511651
//
16521652
// TODO Don't store Resolver in every RelocAddrEntry.
16531653
if (Supports && Supports(Reloc.getType())) {
1654-
Map->try_emplace(Reloc.getOffset(),
1655-
RelocAddrEntry{SymInfoOrErr->SectionIndex, Reloc,
1656-
Resolver, SymInfoOrErr->Address});
1654+
auto I = Map->try_emplace(
1655+
Reloc.getOffset(),
1656+
RelocAddrEntry{SymInfoOrErr->SectionIndex, Reloc,
1657+
SymInfoOrErr->Address,
1658+
Optional<object::RelocationRef>(), 0, Resolver});
1659+
// If we didn't successfully insert that's because we already had a
1660+
// relocation for that offset. Store it as a second relocation in the
1661+
// same RelocAddrEntry instead.
1662+
if (!I.second) {
1663+
RelocAddrEntry &entry = I.first->getSecond();
1664+
if (entry.Reloc2) {
1665+
ErrorPolicy EP = HandleError(createError(
1666+
"At most two relocations per offset are supported"));
1667+
if (EP == ErrorPolicy::Halt)
1668+
return;
1669+
}
1670+
entry.Reloc2 = Reloc;
1671+
entry.SymbolValue2 = SymInfoOrErr->Address;
1672+
}
16571673
} else {
16581674
SmallString<32> Type;
16591675
Reloc.getTypeName(Type);

llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off,
2424
return A;
2525
if (SecNdx)
2626
*SecNdx = E->SectionIndex;
27-
return E->Resolver(E->Reloc, E->SymbolValue, A);
27+
uint64_t R = E->Resolver(E->Reloc, E->SymbolValue, A);
28+
if (E->Reloc2)
29+
R = E->Resolver(*E->Reloc2, E->SymbolValue2, R);
30+
return R;
2831
}
2932

3033
Optional<uint64_t>

llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData,
300300
const uint64_t PrologueOffset = *OffsetPtr;
301301

302302
clear();
303-
TotalLength = DebugLineData.getU32(OffsetPtr);
303+
TotalLength = DebugLineData.getRelocatedValue(4, OffsetPtr);
304304
if (TotalLength == UINT32_MAX) {
305305
FormParams.Format = dwarf::DWARF64;
306306
TotalLength = DebugLineData.getU64(OffsetPtr);
@@ -325,7 +325,8 @@ Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData,
325325
SegSelectorSize = DebugLineData.getU8(OffsetPtr);
326326
}
327327

328-
PrologueLength = DebugLineData.getUnsigned(OffsetPtr, sizeofPrologueLength());
328+
PrologueLength =
329+
DebugLineData.getRelocatedValue(sizeofPrologueLength(), OffsetPtr);
329330
const uint64_t EndPrologueOffset = PrologueLength + *OffsetPtr;
330331
MinInstLength = DebugLineData.getU8(OffsetPtr);
331332
if (getVersion() >= 4)
@@ -754,7 +755,7 @@ Error DWARFDebugLine::LineTable::parse(
754755
// requires the use of DW_LNS_advance_pc. Such assemblers, however,
755756
// can use DW_LNS_fixed_advance_pc instead, sacrificing compression.
756757
{
757-
uint16_t PCOffset = DebugLineData.getU16(OffsetPtr);
758+
uint16_t PCOffset = DebugLineData.getRelocatedValue(2, OffsetPtr);
758759
State.Row.Address.Address += PCOffset;
759760
if (OS)
760761
*OS

llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data,
299299
case DW_FORM_data8:
300300
case DW_FORM_ref8:
301301
case DW_FORM_ref_sup8:
302-
Value.uval = Data.getU64(OffsetPtr);
302+
Value.uval = Data.getRelocatedValue(8, OffsetPtr);
303303
break;
304304
case DW_FORM_data16:
305305
// Treat this like a 16-byte block.

llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Error DWARFListTableHeader::extract(DWARFDataExtractor Data,
2525
"%s table length at offset 0x%" PRIx32,
2626
SectionName.data(), *OffsetPtr);
2727
// TODO: Add support for DWARF64.
28-
HeaderData.Length = Data.getU32(OffsetPtr);
28+
HeaderData.Length = Data.getRelocatedValue(4, OffsetPtr);
2929
if (HeaderData.Length == 0xffffffffu)
3030
return createStringError(errc::not_supported,
3131
"DWARF64 is not supported in %s at offset 0x%" PRIx32,
@@ -73,7 +73,7 @@ Error DWARFListTableHeader::extract(DWARFDataExtractor Data,
7373
SectionName.data(), HeaderOffset, HeaderData.OffsetEntryCount);
7474
Data.setAddressSize(HeaderData.AddrSize);
7575
for (uint32_t I = 0; I < HeaderData.OffsetEntryCount; ++I)
76-
Offsets.push_back(Data.getU32(OffsetPtr));
76+
Offsets.push_back(Data.getRelocatedValue(4, OffsetPtr));
7777
return Error::success();
7878
}
7979

llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ bool DWARFUnitHeader::extract(DWARFContext &Context,
241241
IndexEntry = Entry;
242242
if (!IndexEntry && Index)
243243
IndexEntry = Index->getFromOffset(*offset_ptr);
244-
Length = debug_info.getU32(offset_ptr);
244+
Length = debug_info.getRelocatedValue(4, offset_ptr);
245245
FormParams.Format = DWARF32;
246246
unsigned SizeOfLength = 4;
247247
if (Length == 0xffffffff) {

llvm/lib/Object/RelocationResolver.cpp

+53
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,55 @@ static uint64_t resolveHexagon(RelocationRef R, uint64_t S, uint64_t A) {
330330
llvm_unreachable("Invalid relocation type");
331331
}
332332

333+
static bool supportsRISCV(uint64_t Type) {
334+
switch (Type) {
335+
case ELF::R_RISCV_NONE:
336+
case ELF::R_RISCV_32:
337+
case ELF::R_RISCV_64:
338+
case ELF::R_RISCV_ADD8:
339+
case ELF::R_RISCV_SUB8:
340+
case ELF::R_RISCV_ADD16:
341+
case ELF::R_RISCV_SUB16:
342+
case ELF::R_RISCV_ADD32:
343+
case ELF::R_RISCV_SUB32:
344+
case ELF::R_RISCV_ADD64:
345+
case ELF::R_RISCV_SUB64:
346+
return true;
347+
default:
348+
return false;
349+
}
350+
}
351+
352+
static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) {
353+
int64_t RA = getELFAddend(R);
354+
switch (R.getType()) {
355+
case ELF::R_RISCV_NONE:
356+
return A;
357+
case ELF::R_RISCV_32:
358+
return (S + RA) & 0xFFFFFFFF;
359+
case ELF::R_RISCV_64:
360+
return S + RA;
361+
case ELF::R_RISCV_ADD8:
362+
return (A + (S + RA)) & 0xFF;
363+
case ELF::R_RISCV_SUB8:
364+
return (A - (S + RA)) & 0xFF;
365+
case ELF::R_RISCV_ADD16:
366+
return (A + (S + RA)) & 0xFFFF;
367+
case ELF::R_RISCV_SUB16:
368+
return (A - (S + RA)) & 0xFFFF;
369+
case ELF::R_RISCV_ADD32:
370+
return (A + (S + RA)) & 0xFFFFFFFF;
371+
case ELF::R_RISCV_SUB32:
372+
return (A - (S + RA)) & 0xFFFFFFFF;
373+
case ELF::R_RISCV_ADD64:
374+
return (A + (S + RA));
375+
case ELF::R_RISCV_SUB64:
376+
return (A - (S + RA));
377+
default:
378+
llvm_unreachable("Invalid relocation type");
379+
}
380+
}
381+
333382
static bool supportsCOFFX86(uint64_t Type) {
334383
switch (Type) {
335384
case COFF::IMAGE_REL_I386_SECREL:
@@ -449,6 +498,8 @@ getRelocationResolver(const ObjectFile &Obj) {
449498
return {supportsSparc64, resolveSparc64};
450499
case Triple::amdgcn:
451500
return {supportsAmdgpu, resolveAmdgpu};
501+
case Triple::riscv64:
502+
return {supportsRISCV, resolveRISCV};
452503
default:
453504
return {nullptr, nullptr};
454505
}
@@ -477,6 +528,8 @@ getRelocationResolver(const ObjectFile &Obj) {
477528
return {supportsSparc32, resolveSparc32};
478529
case Triple::hexagon:
479530
return {supportsHexagon, resolveHexagon};
531+
case Triple::riscv32:
532+
return {supportsRISCV, resolveRISCV};
480533
default:
481534
return {nullptr, nullptr};
482535
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
; RUN: llc -filetype=obj -mtriple=riscv32 -mattr=+relax %s -o %t.o
2+
; RUN: llvm-readobj -r %t.o | FileCheck -check-prefix=READOBJ-RELOCS %s
3+
; RUN: llvm-objdump --source %t.o | FileCheck -check-prefix=OBJDUMP-SOURCE %s
4+
; RUN: llvm-dwarfdump --debug-info --debug-line %t.o | \
5+
; RUN: FileCheck -check-prefix=DWARF-DUMP %s
6+
7+
; Check that we actually have relocations, otherwise this is kind of pointless.
8+
; READOBJ-RELOCS: Section (8) .rela.debug_info {
9+
; READOBJ-RELOCS-NEXT: 0x0 R_RISCV_ADD32 - 0x0
10+
; READOBJ-RELOCS-NEXT: 0x0 R_RISCV_SUB32 - 0x0
11+
; READOBJ-RELOCS: Section (11) .rela.debug_addr {
12+
; READOBJ-RELOCS-NEXT: 0x0 R_RISCV_ADD32 - 0x0
13+
; READOBJ-RELOCS-NEXT: 0x0 R_RISCV_SUB32 - 0x0
14+
; READOBJ-RELOCS: Section (17) .rela.debug_line {
15+
; READOBJ-RELOCS-NEXT: 0x0 R_RISCV_ADD32 - 0xFFFFFFFC
16+
; READOBJ-RELOCS-NEXT: 0x0 R_RISCV_SUB32 .Lline_table_start0 0x0
17+
18+
; Check that we can print the source, even with relocations.
19+
; OBJDUMP-SOURCE: Disassembly of section .text:
20+
; OBJDUMP-SOURCE-EMPTY:
21+
; OBJDUMP-SOURCE-NEXT: 00000000 main:
22+
; OBJDUMP-SOURCE: ; {
23+
; OBJDUMP-SOURCE: ; return 0;
24+
25+
; Check that we correctly dump the DWARF info, even with relocations.
26+
; DWARF-DUMP: DW_AT_name ("dwarf-riscv-relocs.c")
27+
; DWARF-DUMP: DW_AT_comp_dir (".")
28+
; DWARF-DUMP: DW_AT_name ("main")
29+
; DWARF-DUMP: DW_AT_decl_file ("./dwarf-riscv-relocs.c")
30+
; DWARF-DUMP: DW_AT_decl_line (1)
31+
; DWARF-DUMP: DW_AT_type (0x00000032 "int")
32+
; DWARF-DUMP: DW_AT_name ("int")
33+
; DWARF-DUMP: DW_AT_encoding (DW_ATE_signed)
34+
; DWARF-DUMP: DW_AT_byte_size (0x04)
35+
36+
; DWARF-DUMP: .debug_line contents:
37+
; DWARF-DUMP-NEXT: debug_line[0x00000000]
38+
; DWARF-DUMP-NEXT: Line table prologue:
39+
; DWARF-DUMP-NEXT: total_length: 0x0000005f
40+
; DWARF-DUMP-NEXT: version: 5
41+
; DWARF-DUMP-NEXT: address_size: 4
42+
; DWARF-DUMP-NEXT: seg_select_size: 0
43+
; DWARF-DUMP-NEXT: prologue_length: 0x0000003e
44+
; DWARF-DUMP-NEXT: min_inst_length: 1
45+
; DWARF-DUMP-NEXT: max_ops_per_inst: 1
46+
; DWARF-DUMP-NEXT: default_is_stmt: 1
47+
; DWARF-DUMP-NEXT: line_base: -5
48+
; DWARF-DUMP-NEXT: line_range: 14
49+
; DWARF-DUMP-NEXT: opcode_base: 13
50+
; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_copy] = 0
51+
; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_advance_pc] = 1
52+
; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_advance_line] = 1
53+
; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_set_file] = 1
54+
; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_set_column] = 1
55+
; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_negate_stmt] = 0
56+
; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_set_basic_block] = 0
57+
; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_const_add_pc] = 0
58+
; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_fixed_advance_pc] = 1
59+
; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_set_prologue_end] = 0
60+
; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0
61+
; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_set_isa] = 1
62+
; DWARF-DUMP-NEXT: include_directories[ 0] = "."
63+
; DWARF-DUMP-NEXT: file_names[ 0]:
64+
; DWARF-DUMP-NEXT: name: "dwarf-riscv-relocs.c"
65+
; DWARF-DUMP-NEXT: dir_index: 0
66+
; DWARF-DUMP-NEXT: md5_checksum: 05ab89f5481bc9f2d037e7886641e919
67+
; DWARF-DUMP-NEXT: source: "int main()\n{\n return 0;\n}\n"
68+
; DWARF-DUMP-EMPTY:
69+
; DWARF-DUMP-NEXT: Address Line Column File ISA Discriminator Flags
70+
; DWARF-DUMP-NEXT: ------------------ ------ ------ ------ --- ------------- -------------
71+
; DWARF-DUMP-NEXT: 0x0000000000000000 2 0 0 0 0 is_stmt
72+
; DWARF-DUMP-NEXT: 0x0000000000000014 3 5 0 0 0 is_stmt prologue_end
73+
; DWARF-DUMP-NEXT: 0x0000000000000028 3 5 0 0 0 is_stmt end_sequence
74+
75+
; ModuleID = 'dwarf-riscv-relocs.c'
76+
source_filename = "dwarf-riscv-relocs.c"
77+
target datalayout = "e-m:e-p:32:32-i64:64-n32-S128"
78+
target triple = "riscv32"
79+
80+
; Function Attrs: noinline nounwind optnone
81+
define dso_local i32 @main() #0 !dbg !7 {
82+
entry:
83+
%retval = alloca i32, align 4
84+
store i32 0, i32* %retval, align 4
85+
ret i32 0, !dbg !11
86+
}
87+
88+
attributes #0 = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+relax" "unsafe-fp-math"="false" "use-soft-float"="false" }
89+
90+
!llvm.dbg.cu = !{!0}
91+
!llvm.module.flags = !{!3, !4, !5}
92+
!llvm.ident = !{!6}
93+
94+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
95+
!1 = !DIFile(filename: "dwarf-riscv-relocs.c", directory: ".", checksumkind: CSK_MD5, checksum: "05ab89f5481bc9f2d037e7886641e919", source: "int main()\0A{\0A return 0;\0A}\0A")
96+
!2 = !{}
97+
!3 = !{i32 2, !"Dwarf Version", i32 5}
98+
!4 = !{i32 2, !"Debug Info Version", i32 3}
99+
!5 = !{i32 1, !"wchar_size", i32 4}
100+
!6 = !{!"clang"}
101+
!7 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 1, type: !8, scopeLine: 2, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
102+
!8 = !DISubroutineType(types: !9)
103+
!9 = !{!10}
104+
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
105+
!11 = !DILocation(line: 3, column: 5, scope: !7)

0 commit comments

Comments
 (0)