llvm.org GIT mirror llvm / bfd9349
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@366402 91177308-0d34-0410-b5e6-96231b3b80d8 Alex Bradbury a month ago
9 changed file(s) with 192 addition(s) and 12 deletion(s). Raw diff Collapse all Expand all
1919 struct RelocAddrEntry {
2020 uint64_t SectionIndex;
2121 object::RelocationRef Reloc;
22 uint64_t SymbolValue;
23 Optional Reloc2;
24 uint64_t SymbolValue2;
2225 object::RelocationResolver Resolver;
23 uint64_t SymbolValue;
2426 };
2527
2628 /// In place of applying the relocations to the data we've read from disk we use
16501650 //
16511651 // TODO Don't store Resolver in every RelocAddrEntry.
16521652 if (Supports && Supports(Reloc.getType())) {
1653 Map->try_emplace(Reloc.getOffset(),
1654 RelocAddrEntry{SymInfoOrErr->SectionIndex, Reloc,
1655 Resolver, SymInfoOrErr->Address});
1653 auto I = Map->try_emplace(
1654 Reloc.getOffset(),
1655 RelocAddrEntry{SymInfoOrErr->SectionIndex, Reloc,
1656 SymInfoOrErr->Address,
1657 Optional(), 0, Resolver});
1658 // If we didn't successfully insert that's because we already had a
1659 // relocation for that offset. Store it as a second relocation in the
1660 // same RelocAddrEntry instead.
1661 if (!I.second) {
1662 RelocAddrEntry &entry = I.first->getSecond();
1663 if (entry.Reloc2) {
1664 ErrorPolicy EP = HandleError(createError(
1665 "At most two relocations per offset are supported"));
1666 if (EP == ErrorPolicy::Halt)
1667 return;
1668 }
1669 entry.Reloc2 = Reloc;
1670 entry.SymbolValue2 = SymInfoOrErr->Address;
1671 }
16561672 } else {
16571673 SmallString<32> Type;
16581674 Reloc.getTypeName(Type);
2323 return A;
2424 if (SecNdx)
2525 *SecNdx = E->SectionIndex;
26 return E->Resolver(E->Reloc, E->SymbolValue, A);
26 uint64_t R = E->Resolver(E->Reloc, E->SymbolValue, A);
27 if (E->Reloc2)
28 R = E->Resolver(*E->Reloc2, E->SymbolValue2, R);
29 return R;
2730 }
2831
2932 Optional
299299 const uint64_t PrologueOffset = *OffsetPtr;
300300
301301 clear();
302 TotalLength = DebugLineData.getU32(OffsetPtr);
302 TotalLength = DebugLineData.getRelocatedValue(4, OffsetPtr);
303303 if (TotalLength == UINT32_MAX) {
304304 FormParams.Format = dwarf::DWARF64;
305305 TotalLength = DebugLineData.getU64(OffsetPtr);
324324 SegSelectorSize = DebugLineData.getU8(OffsetPtr);
325325 }
326326
327 PrologueLength = DebugLineData.getUnsigned(OffsetPtr, sizeofPrologueLength());
327 PrologueLength =
328 DebugLineData.getRelocatedValue(sizeofPrologueLength(), OffsetPtr);
328329 const uint64_t EndPrologueOffset = PrologueLength + *OffsetPtr;
329330 MinInstLength = DebugLineData.getU8(OffsetPtr);
330331 if (getVersion() >= 4)
753754 // requires the use of DW_LNS_advance_pc. Such assemblers, however,
754755 // can use DW_LNS_fixed_advance_pc instead, sacrificing compression.
755756 {
756 uint16_t PCOffset = DebugLineData.getU16(OffsetPtr);
757 uint16_t PCOffset = DebugLineData.getRelocatedValue(2, OffsetPtr);
757758 State.Row.Address.Address += PCOffset;
758759 if (OS)
759760 *OS
298298 case DW_FORM_data8:
299299 case DW_FORM_ref8:
300300 case DW_FORM_ref_sup8:
301 Value.uval = Data.getU64(OffsetPtr);
301 Value.uval = Data.getRelocatedValue(8, OffsetPtr);
302302 break;
303303 case DW_FORM_data16:
304304 // Treat this like a 16-byte block.
2424 "%s table length at offset 0x%" PRIx32,
2525 SectionName.data(), *OffsetPtr);
2626 // TODO: Add support for DWARF64.
27 HeaderData.Length = Data.getU32(OffsetPtr);
27 HeaderData.Length = Data.getRelocatedValue(4, OffsetPtr);
2828 if (HeaderData.Length == 0xffffffffu)
2929 return createStringError(errc::not_supported,
3030 "DWARF64 is not supported in %s at offset 0x%" PRIx32,
7272 SectionName.data(), HeaderOffset, HeaderData.OffsetEntryCount);
7373 Data.setAddressSize(HeaderData.AddrSize);
7474 for (uint32_t I = 0; I < HeaderData.OffsetEntryCount; ++I)
75 Offsets.push_back(Data.getU32(OffsetPtr));
75 Offsets.push_back(Data.getRelocatedValue(4, OffsetPtr));
7676 return Error::success();
7777 }
7878
240240 IndexEntry = Entry;
241241 if (!IndexEntry && Index)
242242 IndexEntry = Index->getFromOffset(*offset_ptr);
243 Length = debug_info.getU32(offset_ptr);
243 Length = debug_info.getRelocatedValue(4, offset_ptr);
244244 FormParams.Format = DWARF32;
245245 unsigned SizeOfLength = 4;
246246 if (Length == 0xffffffff) {
327327 if (R.getType() == ELF::R_HEX_32)
328328 return S + getELFAddend(R);
329329 llvm_unreachable("Invalid relocation type");
330 }
331
332 static bool supportsRISCV(uint64_t Type) {
333 switch (Type) {
334 case ELF::R_RISCV_NONE:
335 case ELF::R_RISCV_32:
336 case ELF::R_RISCV_64:
337 case ELF::R_RISCV_ADD8:
338 case ELF::R_RISCV_SUB8:
339 case ELF::R_RISCV_ADD16:
340 case ELF::R_RISCV_SUB16:
341 case ELF::R_RISCV_ADD32:
342 case ELF::R_RISCV_SUB32:
343 case ELF::R_RISCV_ADD64:
344 case ELF::R_RISCV_SUB64:
345 return true;
346 default:
347 return false;
348 }
349 }
350
351 static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) {
352 int64_t RA = getELFAddend(R);
353 switch (R.getType()) {
354 case ELF::R_RISCV_NONE:
355 return A;
356 case ELF::R_RISCV_32:
357 return (S + RA) & 0xFFFFFFFF;
358 case ELF::R_RISCV_64:
359 return S + RA;
360 case ELF::R_RISCV_ADD8:
361 return (A + (S + RA)) & 0xFF;
362 case ELF::R_RISCV_SUB8:
363 return (A - (S + RA)) & 0xFF;
364 case ELF::R_RISCV_ADD16:
365 return (A + (S + RA)) & 0xFFFF;
366 case ELF::R_RISCV_SUB16:
367 return (A - (S + RA)) & 0xFFFF;
368 case ELF::R_RISCV_ADD32:
369 return (A + (S + RA)) & 0xFFFFFFFF;
370 case ELF::R_RISCV_SUB32:
371 return (A - (S + RA)) & 0xFFFFFFFF;
372 case ELF::R_RISCV_ADD64:
373 return (A + (S + RA));
374 case ELF::R_RISCV_SUB64:
375 return (A - (S + RA));
376 default:
377 llvm_unreachable("Invalid relocation type");
378 }
330379 }
331380
332381 static bool supportsCOFFX86(uint64_t Type) {
448497 return {supportsSparc64, resolveSparc64};
449498 case Triple::amdgcn:
450499 return {supportsAmdgpu, resolveAmdgpu};
500 case Triple::riscv64:
501 return {supportsRISCV, resolveRISCV};
451502 default:
452503 return {nullptr, nullptr};
453504 }
476527 return {supportsSparc32, resolveSparc32};
477528 case Triple::hexagon:
478529 return {supportsHexagon, resolveHexagon};
530 case Triple::riscv32:
531 return {supportsRISCV, resolveRISCV};
479532 default:
480533 return {nullptr, nullptr};
481534 }
0 ; RUN: llc -filetype=obj -mtriple=riscv32 -mattr=+relax %s -o %t.o
1 ; RUN: llvm-readobj -r %t.o | FileCheck -check-prefix=READOBJ-RELOCS %s
2 ; RUN: llvm-objdump --source %t.o | FileCheck -check-prefix=OBJDUMP-SOURCE %s
3 ; RUN: llvm-dwarfdump --debug-info --debug-line %t.o | \
4 ; RUN: FileCheck -check-prefix=DWARF-DUMP %s
5
6 ; Check that we actually have relocations, otherwise this is kind of pointless.
7 ; READOBJ-RELOCS: Section (8) .rela.debug_info {
8 ; READOBJ-RELOCS-NEXT: 0x0 R_RISCV_ADD32 - 0x0
9 ; READOBJ-RELOCS-NEXT: 0x0 R_RISCV_SUB32 - 0x0
10 ; READOBJ-RELOCS: Section (11) .rela.debug_addr {
11 ; READOBJ-RELOCS-NEXT: 0x0 R_RISCV_ADD32 - 0x0
12 ; READOBJ-RELOCS-NEXT: 0x0 R_RISCV_SUB32 - 0x0
13 ; READOBJ-RELOCS: Section (17) .rela.debug_line {
14 ; READOBJ-RELOCS-NEXT: 0x0 R_RISCV_ADD32 - 0xFFFFFFFC
15 ; READOBJ-RELOCS-NEXT: 0x0 R_RISCV_SUB32 .Lline_table_start0 0x0
16
17 ; Check that we can print the source, even with relocations.
18 ; OBJDUMP-SOURCE: Disassembly of section .text:
19 ; OBJDUMP-SOURCE-EMPTY:
20 ; OBJDUMP-SOURCE-NEXT: 00000000 main:
21 ; OBJDUMP-SOURCE: ; {
22 ; OBJDUMP-SOURCE: ; return 0;
23
24 ; Check that we correctly dump the DWARF info, even with relocations.
25 ; DWARF-DUMP: DW_AT_name ("dwarf-riscv-relocs.c")
26 ; DWARF-DUMP: DW_AT_comp_dir (".")
27 ; DWARF-DUMP: DW_AT_name ("main")
28 ; DWARF-DUMP: DW_AT_decl_file ("./dwarf-riscv-relocs.c")
29 ; DWARF-DUMP: DW_AT_decl_line (1)
30 ; DWARF-DUMP: DW_AT_type (0x00000032 "int")
31 ; DWARF-DUMP: DW_AT_name ("int")
32 ; DWARF-DUMP: DW_AT_encoding (DW_ATE_signed)
33 ; DWARF-DUMP: DW_AT_byte_size (0x04)
34
35 ; DWARF-DUMP: .debug_line contents:
36 ; DWARF-DUMP-NEXT: debug_line[0x00000000]
37 ; DWARF-DUMP-NEXT: Line table prologue:
38 ; DWARF-DUMP-NEXT: total_length: 0x0000005f
39 ; DWARF-DUMP-NEXT: version: 5
40 ; DWARF-DUMP-NEXT: address_size: 4
41 ; DWARF-DUMP-NEXT: seg_select_size: 0
42 ; DWARF-DUMP-NEXT: prologue_length: 0x0000003e
43 ; DWARF-DUMP-NEXT: min_inst_length: 1
44 ; DWARF-DUMP-NEXT: max_ops_per_inst: 1
45 ; DWARF-DUMP-NEXT: default_is_stmt: 1
46 ; DWARF-DUMP-NEXT: line_base: -5
47 ; DWARF-DUMP-NEXT: line_range: 14
48 ; DWARF-DUMP-NEXT: opcode_base: 13
49 ; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_copy] = 0
50 ; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_advance_pc] = 1
51 ; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_advance_line] = 1
52 ; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_set_file] = 1
53 ; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_set_column] = 1
54 ; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_negate_stmt] = 0
55 ; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_set_basic_block] = 0
56 ; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_const_add_pc] = 0
57 ; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_fixed_advance_pc] = 1
58 ; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_set_prologue_end] = 0
59 ; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0
60 ; DWARF-DUMP-NEXT: standard_opcode_lengths[DW_LNS_set_isa] = 1
61 ; DWARF-DUMP-NEXT: include_directories[ 0] = "."
62 ; DWARF-DUMP-NEXT: file_names[ 0]:
63 ; DWARF-DUMP-NEXT: name: "dwarf-riscv-relocs.c"
64 ; DWARF-DUMP-NEXT: dir_index: 0
65 ; DWARF-DUMP-NEXT: md5_checksum: 05ab89f5481bc9f2d037e7886641e919
66 ; DWARF-DUMP-NEXT: source: "int main()\n{\n return 0;\n}\n"
67 ; DWARF-DUMP-EMPTY:
68 ; DWARF-DUMP-NEXT: Address Line Column File ISA Discriminator Flags
69 ; DWARF-DUMP-NEXT: ------------------ ------ ------ ------ --- ------------- -------------
70 ; DWARF-DUMP-NEXT: 0x0000000000000000 2 0 0 0 0 is_stmt
71 ; DWARF-DUMP-NEXT: 0x0000000000000014 3 5 0 0 0 is_stmt prologue_end
72 ; DWARF-DUMP-NEXT: 0x0000000000000028 3 5 0 0 0 is_stmt end_sequence
73
74 ; ModuleID = 'dwarf-riscv-relocs.c'
75 source_filename = "dwarf-riscv-relocs.c"
76 target datalayout = "e-m:e-p:32:32-i64:64-n32-S128"
77 target triple = "riscv32"
78
79 ; Function Attrs: noinline nounwind optnone
80 define dso_local i32 @main() #0 !dbg !7 {
81 entry:
82 %retval = alloca i32, align 4
83 store i32 0, i32* %retval, align 4
84 ret i32 0, !dbg !11
85 }
86
87 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" }
88
89 !llvm.dbg.cu = !{!0}
90 !llvm.module.flags = !{!3, !4, !5}
91 !llvm.ident = !{!6}
92
93 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
94 !1 = !DIFile(filename: "dwarf-riscv-relocs.c", directory: ".", checksumkind: CSK_MD5, checksum: "05ab89f5481bc9f2d037e7886641e919", source: "int main()\0A{\0A return 0;\0A}\0A")
95 !2 = !{}
96 !3 = !{i32 2, !"Dwarf Version", i32 5}
97 !4 = !{i32 2, !"Debug Info Version", i32 3}
98 !5 = !{i32 1, !"wchar_size", i32 4}
99 !6 = !{!"clang"}
100 !7 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 1, type: !8, scopeLine: 2, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
101 !8 = !DISubroutineType(types: !9)
102 !9 = !{!10}
103 !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
104 !11 = !DILocation(line: 3, column: 5, scope: !7)