From b00f0d4238cb34a54073cc5ab7e2060d58f69e3f Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Fri, 24 Apr 2020 15:41:13 +0300 Subject: [PATCH] [mips] Support 64-bit relative relocations MIPS 64-bit ABI does not provide special PC-relative relocation like R_MIPS_PC32 in 32-bit case. But we can use a "chain of relocation" defined by N64 ABIs. In that case one relocation record might contain up to three relocations which applied sequentially. Width of a final relocation mask applied to the result of relocation depends on the last relocation in the chain. In case of 64-bit PC-relative relocation we need the following chain: `R_MIPS_PC32 | R_MIPS_64`. The first relocation calculates an offset, but does not truncate the result. The second relocation just apply calculated result as a 64-bit value. The 64-bit PC-relative relocation might be useful in generation of `.eh_frame` sections to escape passing `-Wl,-z,notext` flags to linker. Differential Revision: https://reviews.llvm.org/D80390 --- lld/test/ELF/mips-pc64.s | 24 ++++++++++++++++++++++ .../Mips/MCTargetDesc/MipsELFObjectWriter.cpp | 12 +++++------ llvm/test/MC/Mips/relocation-n64.s | 2 ++ llvm/test/MC/Mips/unsupported-relocation.s | 2 -- 4 files changed, 31 insertions(+), 9 deletions(-) create mode 100644 lld/test/ELF/mips-pc64.s diff --git a/lld/test/ELF/mips-pc64.s b/lld/test/ELF/mips-pc64.s new file mode 100644 index 0000000..6248c67 --- /dev/null +++ b/lld/test/ELF/mips-pc64.s @@ -0,0 +1,24 @@ +# REQUIRES: mips + +# Check handling of 64-bit pc-realtive relocation. + +# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t.o +# RUN: echo 'SECTIONS { \ +# RUN: .text 0x10000 : { *(.text) } \ +# RUN: .data 0x30000 : { *(.data) } \ +# RUN: }' > %t.script +# RUN: ld.lld -shared %t.o -T %t.script -o %t +# RUN: llvm-readelf -x .data %t | FileCheck %s + +# CHECK: Hex dump of section '.data': +# CHECK-NEXT: 0x00030000 ffffffff fffffff0 00000001 fffdffe8 + + .option pic2 + .text +foo: + nop + .data +v0: + .quad foo+0x1fff0-. +v1: + .quad foo+0x1fffffff0-. diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp index ee2e877..fc0154d 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -234,14 +234,15 @@ unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx, case Mips::fixup_Mips_32: case FK_Data_4: return IsPCRel ? ELF::R_MIPS_PC32 : ELF::R_MIPS_32; + case Mips::fixup_Mips_64: + case FK_Data_8: + return IsPCRel + ? setRTypes(ELF::R_MIPS_PC32, ELF::R_MIPS_64, ELF::R_MIPS_NONE) + : ELF::R_MIPS_64; } if (IsPCRel) { switch (Kind) { - case FK_Data_8: - Ctx.reportError(Fixup.getLoc(), - "MIPS does not support 64-bit PC-relative relocations"); - return ELF::R_MIPS_NONE; case Mips::fixup_Mips_Branch_PCRel: case Mips::fixup_Mips_PC16: return ELF::R_MIPS_PC16; @@ -277,9 +278,6 @@ unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx, } switch (Kind) { - case Mips::fixup_Mips_64: - case FK_Data_8: - return ELF::R_MIPS_64; case FK_DTPRel_4: return ELF::R_MIPS_TLS_DTPREL32; case FK_DTPRel_8: diff --git a/llvm/test/MC/Mips/relocation-n64.s b/llvm/test/MC/Mips/relocation-n64.s index 155ac20..297b1a6 100644 --- a/llvm/test/MC/Mips/relocation-n64.s +++ b/llvm/test/MC/Mips/relocation-n64.s @@ -70,4 +70,6 @@ .word 0 bar: .word 1 + .option pic2 + .quad foo+0x1fffffff0-. // RELOC: R_MIPS_PC32/R_MIPS_64/R_MIPS_NONE foo 0x1FFFFFFF0 // DATA-LABEL: Section { diff --git a/llvm/test/MC/Mips/unsupported-relocation.s b/llvm/test/MC/Mips/unsupported-relocation.s index 258b483..311c0c7 100644 --- a/llvm/test/MC/Mips/unsupported-relocation.s +++ b/llvm/test/MC/Mips/unsupported-relocation.s @@ -11,5 +11,3 @@ foo: # CHECK: :[[@LINE-1]]:17: error: MIPS does not support one byte relocations .byte x+1 # CHECK: :[[@LINE-1]]:17: error: MIPS does not support one byte relocations - .quad x-foo -# CHECK: :[[@LINE-1]]:17: error: MIPS does not support 64-bit PC-relative relocations -- 2.7.4