[PATCH v6] MIPS: Support PCREL GOT access
YunQiang Su
syq@debian.org
Mon Jun 10 14:09:49 GMT 2024
From: YunQiang Su <syq@gcc.gnu.org>
Currently loading a GOT entry requires loading the GOT base address
first, then adding an offset. Due to the 16-bit limitation of ld/lw
instructions, GP-based access can have up to 16k/8k slots, which is not
enough for large applications. Therefore, we need both GOT and XGOT. MIPSr6
introduced PC-relative instructions like ALUIPC/AUIPC, which allow us
to use a pair of GOTPC_HI and GOTPC_LO to materialize the GOT entry address.
In this patch, we add 8 new relocs:
R_MIPS_GOTPC_HI16, R_MIPS_GOTPC_LO16,
R_MIPS_GOTPC_CALL_HI16, R_MIPS_GOTPC_CALL_LO16,
R_MIPS_GOTPC_AHI16, R_MIPS_GOTPC_ALO16,
R_MIPS_GOTPC_CALL_AHI16, R_MIPS_GOTPC_CALL_ALO16.
These percent_op can be used for them:
%gotpc_hi(sym), %gotpc_lo(sym),
%gotpc_call_hi(sym), %gotpc_call_lo(sym),
%gotpc_ahi(sym), %gotpc_alo(sym),
%gotpc_call_ahi(sym), %gotpc_call_alo(sym).
3 new BFD_RELOCS are added for ALUIPC style relocs:
BFD_RELOC_MIPS_ALO16_GOTOFF,
BFD_RELOC_MIPS_AHI16_GOTOFF,
BFD_RELOC_MIPS_AHI16_S_GOTOFF.
6 new BFD_RELOCS are added for function calling:
BFD_RELOC_MIPS_LO16_GOTOFF_CALL,
BFD_RELOC_MIPS_HI16_GOTOFF_CALL,
BFD_RELOC_MIPS_HI16_S_GOTOFF_CALL,
BFD_RELOC_MIPS_ALO16_GOTOFF_CALL,
BFD_RELOC_MIPS_AHI16_GOTOFF_CALL,
BFD_RELOC_MIPS_AHI16_S_GOTOFF_CALL,
The mapping between BFD_RELOC_ and R_MIPS_GOTPC are:
BFD_RELOC_HI16_S_GOTOFF -> R_MIPS_GOTPC_HI16
BFD_RELOC_LO16_GOTOFF -> R_MIPS_GOTPC_LO16
BFD_RELOC_MIPS_HI16_S_GOTOFF_CALL -> R_MIPS_GOTPC_CALL_HI16
BFD_RELOC_MIPS_LO16_GOTOFF_CALL -> R_MIPS_GOTPC_CALL_LO16.
BFD_RELOC_MIPS_AHI16_S_GOTOFF -> R_MIPS_GOTPC_AHI16
BFD_RELOC_MIPS_ALO16_GOTOFF -> R_MIPS_GOTPC_ALO16
BFD_RELOC_MIPS_MIPS_AHI16_S_GOTOFF_CALL -> R_MIPS_GOTPC_CALL_AHI16
BFD_RELOC_MIPS_MIPS_ALO16_GOTOFF_CALL -> R_MIPS_GOTPC_CALL_ALO16.
The difference of BAL and ALUIPC is that ALUIPC will unset the lower 16
bits of result.
For r6, both styles are supported, and of course ALUIPC style is
recommended. For pre-R6, only BAL style is supported.
Here are the ASM examples:
ALUIPC:
aluipc $2,%gotpc_ahi(sym)
lw $2,%gotpc_alo(sym)($2)
BAL:
bal . + 8 # Note: $31 is clobbered here.
lui $2,%gotpc_hi(sym)
addiu $2,$2,$31
lw $2,%gotpc_lo(sym)($2)
gas/ChangeLog:
* config/tc-mips.c: Add GOTPC relocs support.
* testsuite/gas/mips/mips.exp: Add GOTPC testcases.
* testsuite/gas/mips/gotpc-aluipc-32.s: Ditto.
* testsuite/gas/mips/gotpc-aluipc-64.s: Ditto.
* testsuite/gas/mips/gotpc-aluipc-n64.d: Ditto.
* testsuite/gas/mips/gotpc-aluipc-n32.d: Ditto.
* testsuite/gas/mips/gotpc-aluipc-o32.d: Ditto.
* testsuite/gas/mips/gotpc-bal-32.s: Ditto.
* testsuite/gas/mips/gotpc-bal-64.s: Ditto.
* testsuite/gas/mips/gotpc-bal-n64.d: Ditto.
* testsuite/gas/mips/gotpc-bal-n32.d: Ditto.
* testsuite/gas/mips/gotpc-bal-o32.d: Ditto.
bfd/ChangeLog:
* elfxx-mips.c: Add GOTPC relocs support.
* elf32-mips.c: Ditto.
* elf64-mips.c: Ditto.
* elfn32-mips.c: Ditto.
* bfd-in2.h: Add new MIPS GOTPC BFD_RELOC definitions.
* reclos.c: Ditto.
* libbfd.h: Ditto.
elfcpp/ChangeLog:
* mips.h: Add new MIPS GOTPC relocs.
include/ChangeLog:
* elf/mips.h (elf_mips_reloc_type): Add new MIPS GOTPC relocs.
ld/ChangeLog:
* testsuite/ld-mips-elf/mips-elf.exp: Add GOTPC testcases.
* testsuite/ld-mips-elf/gotpc-callee.s: Likewise.
* testsuite/ld-mips-elf/gotpc.ld: Likewise.
* testsuite/ld-mips-elf/gotpc-o32.s: Likewise.
* testsuite/ld-mips-elf/gotpc-o32.dd: Likewise.
* testsuite/ld-mips-elf/gotpc-o32.gd: Likewise.
* testsuite/ld-mips-elf/gotpc-n32.s: Likewise.
* testsuite/ld-mips-elf/gotpc-n32.dd: Likewise.
* testsuite/ld-mips-elf/gotpc-n32.gd: Likewise.
* testsuite/ld-mips-elf/gotpc-n64.s: Likewise.
* testsuite/ld-mips-elf/gotpc-n64.dd: Likewise.
* testsuite/ld-mips-elf/gotpc-n64.gd: Likewise.
---
bfd/bfd-in2.h | 12 ++
bfd/elf32-mips.c | 123 +++++++++++-
bfd/elf64-mips.c | 234 +++++++++++++++++++++-
bfd/elfn32-mips.c | 234 +++++++++++++++++++++-
bfd/elfxx-mips.c | 107 +++++++++-
bfd/libbfd.h | 9 +
bfd/reloc.c | 18 ++
elfcpp/mips.h | 8 +
gas/config/tc-mips.c | 72 ++++++-
gas/testsuite/gas/mips/gotpc-aluipc-32.s | 51 +++++
gas/testsuite/gas/mips/gotpc-aluipc-64.s | 50 +++++
gas/testsuite/gas/mips/gotpc-aluipc-n32.d | 17 ++
gas/testsuite/gas/mips/gotpc-aluipc-n64.d | 25 +++
gas/testsuite/gas/mips/gotpc-aluipc-o32.d | 17 ++
gas/testsuite/gas/mips/gotpc-bal-32.s | 55 +++++
gas/testsuite/gas/mips/gotpc-bal-64.s | 54 +++++
gas/testsuite/gas/mips/gotpc-bal-n32.d | 17 ++
gas/testsuite/gas/mips/gotpc-bal-n64.d | 25 +++
gas/testsuite/gas/mips/gotpc-bal-o32.d | 17 ++
gas/testsuite/gas/mips/mips.exp | 8 +
include/elf/mips.h | 10 +-
ld/testsuite/ld-mips-elf/gotpc-callee.s | 41 ++++
ld/testsuite/ld-mips-elf/gotpc-n32.dd | 73 +++++++
ld/testsuite/ld-mips-elf/gotpc-n32.gd | 15 ++
ld/testsuite/ld-mips-elf/gotpc-n32.s | 46 +++++
ld/testsuite/ld-mips-elf/gotpc-n64.dd | 75 +++++++
ld/testsuite/ld-mips-elf/gotpc-n64.gd | 15 ++
ld/testsuite/ld-mips-elf/gotpc-n64.s | 46 +++++
ld/testsuite/ld-mips-elf/gotpc-o32.dd | 71 +++++++
ld/testsuite/ld-mips-elf/gotpc-o32.gd | 15 ++
ld/testsuite/ld-mips-elf/gotpc-o32.s | 45 +++++
ld/testsuite/ld-mips-elf/gotpc.ld | 17 ++
ld/testsuite/ld-mips-elf/mips-elf.exp | 23 +++
33 files changed, 1637 insertions(+), 8 deletions(-)
create mode 100644 gas/testsuite/gas/mips/gotpc-aluipc-32.s
create mode 100644 gas/testsuite/gas/mips/gotpc-aluipc-64.s
create mode 100644 gas/testsuite/gas/mips/gotpc-aluipc-n32.d
create mode 100644 gas/testsuite/gas/mips/gotpc-aluipc-n64.d
create mode 100644 gas/testsuite/gas/mips/gotpc-aluipc-o32.d
create mode 100644 gas/testsuite/gas/mips/gotpc-bal-32.s
create mode 100644 gas/testsuite/gas/mips/gotpc-bal-64.s
create mode 100644 gas/testsuite/gas/mips/gotpc-bal-n32.d
create mode 100644 gas/testsuite/gas/mips/gotpc-bal-n64.d
create mode 100644 gas/testsuite/gas/mips/gotpc-bal-o32.d
create mode 100644 ld/testsuite/ld-mips-elf/gotpc-callee.s
create mode 100644 ld/testsuite/ld-mips-elf/gotpc-n32.dd
create mode 100644 ld/testsuite/ld-mips-elf/gotpc-n32.gd
create mode 100644 ld/testsuite/ld-mips-elf/gotpc-n32.s
create mode 100644 ld/testsuite/ld-mips-elf/gotpc-n64.dd
create mode 100644 ld/testsuite/ld-mips-elf/gotpc-n64.gd
create mode 100644 ld/testsuite/ld-mips-elf/gotpc-n64.s
create mode 100644 ld/testsuite/ld-mips-elf/gotpc-o32.dd
create mode 100644 ld/testsuite/ld-mips-elf/gotpc-o32.gd
create mode 100644 ld/testsuite/ld-mips-elf/gotpc-o32.s
create mode 100644 ld/testsuite/ld-mips-elf/gotpc.ld
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index e3b5a8b8522..8d116e60a6f 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -3675,6 +3675,18 @@ enum bfd_reloc_code_real
BFD_RELOC_MIPS_18_PCREL_S3,
BFD_RELOC_MIPS_19_PCREL_S2,
+ BFD_RELOC_MIPS_LO16_GOTOFF_CALL,
+ BFD_RELOC_MIPS_HI16_GOTOFF_CALL,
+ BFD_RELOC_MIPS_HI16_S_GOTOFF_CALL,
+
+ BFD_RELOC_MIPS_ALO16_GOTOFF,
+ BFD_RELOC_MIPS_AHI16_GOTOFF,
+ BFD_RELOC_MIPS_AHI16_S_GOTOFF,
+
+ BFD_RELOC_MIPS_ALO16_GOTOFF_CALL,
+ BFD_RELOC_MIPS_AHI16_GOTOFF_CALL,
+ BFD_RELOC_MIPS_AHI16_S_GOTOFF_CALL,
+
/* microMIPS versions of generic BFD relocs. */
BFD_RELOC_MICROMIPS_GPREL16,
BFD_RELOC_MICROMIPS_HI16,
diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c
index bec7a207aa8..801d396dad9 100644
--- a/bfd/elf32-mips.c
+++ b/bfd/elf32-mips.c
@@ -809,6 +809,119 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
0x0000ffff, /* src_mask */
0x0000ffff, /* dst_mask */
true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_HI16, /* type */
+ 16, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_HI16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_LO16, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_LO16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_CALL_HI16, /* type */
+ 16, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_CALL_HI16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_CALL_LO16, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_CALL_LO16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_AHI16, /* type */
+ 16, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_AHI16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_ALO16, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_ALO16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_CALL_AHI16, /* type */
+ 16, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_CALL_AHI16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_CALL_ALO16, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_CALL_ALO16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
};
/* The reloc used for BFD_RELOC_CTOR when doing a 64 bit link. This
@@ -2030,7 +2143,15 @@ static const struct elf_reloc_map mips_reloc_map[] =
{ BFD_RELOC_MIPS_18_PCREL_S3, R_MIPS_PC18_S3 },
{ BFD_RELOC_MIPS_19_PCREL_S2, R_MIPS_PC19_S2 },
{ BFD_RELOC_HI16_S_PCREL, R_MIPS_PCHI16 },
- { BFD_RELOC_LO16_PCREL, R_MIPS_PCLO16 }
+ { BFD_RELOC_LO16_PCREL, R_MIPS_PCLO16 },
+ { BFD_RELOC_HI16_S_GOTOFF, R_MIPS_GOTPC_HI16 },
+ { BFD_RELOC_LO16_GOTOFF, R_MIPS_GOTPC_LO16 },
+ { BFD_RELOC_MIPS_HI16_S_GOTOFF_CALL, R_MIPS_GOTPC_CALL_HI16 },
+ { BFD_RELOC_MIPS_LO16_GOTOFF_CALL, R_MIPS_GOTPC_CALL_LO16 },
+ { BFD_RELOC_MIPS_AHI16_S_GOTOFF, R_MIPS_GOTPC_AHI16 },
+ { BFD_RELOC_MIPS_ALO16_GOTOFF, R_MIPS_GOTPC_ALO16 },
+ { BFD_RELOC_MIPS_AHI16_S_GOTOFF_CALL, R_MIPS_GOTPC_CALL_AHI16 },
+ { BFD_RELOC_MIPS_ALO16_GOTOFF_CALL, R_MIPS_GOTPC_CALL_ALO16 }
};
static const struct elf_reloc_map mips16_reloc_map[] =
diff --git a/bfd/elf64-mips.c b/bfd/elf64-mips.c
index afd7b30f134..fdc754e0d37 100644
--- a/bfd/elf64-mips.c
+++ b/bfd/elf64-mips.c
@@ -889,6 +889,118 @@ static reloc_howto_type mips_elf64_howto_table_rel[] =
0x0000ffff, /* dst_mask */
true), /* pcrel_offset */
+ HOWTO (R_MIPS_GOTPC_HI16, /* type */
+ 16, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_HI16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_LO16, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_LO16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_CALL_HI16, /* type */
+ 16, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_CALL_HI16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_CALL_LO16, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_CALL_LO16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_AHI16, /* type */
+ 16, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_AHI16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_ALO16, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_ALO16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_CALL_AHI16, /* type */
+ 16, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_CALL_AHI16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_CALL_ALO16, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_CALL_ALO16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
};
/* The relocation table used for SHT_RELA sections. */
@@ -1670,6 +1782,118 @@ static reloc_howto_type mips_elf64_howto_table_rela[] =
0x0000ffff, /* dst_mask */
true), /* pcrel_offset */
+ HOWTO (R_MIPS_GOTPC_HI16, /* type */
+ 16, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_HI16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_LO16, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_LO16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_CALL_HI16, /* type */
+ 16, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_CALL_HI16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_CALL_LO16, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_CALL_LO16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_AHI16, /* type */
+ 16, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_AHI16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_ALO16, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_ALO16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_CALL_AHI16, /* type */
+ 16, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_CALL_AHI16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_CALL_ALO16, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_CALL_ALO16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
};
static reloc_howto_type mips16_elf64_howto_table_rel[] =
@@ -3743,7 +3967,15 @@ static const struct elf_reloc_map mips_reloc_map[] =
{ BFD_RELOC_MIPS_18_PCREL_S3, R_MIPS_PC18_S3 },
{ BFD_RELOC_MIPS_19_PCREL_S2, R_MIPS_PC19_S2 },
{ BFD_RELOC_HI16_S_PCREL, R_MIPS_PCHI16 },
- { BFD_RELOC_LO16_PCREL, R_MIPS_PCLO16 }
+ { BFD_RELOC_LO16_PCREL, R_MIPS_PCLO16 },
+ { BFD_RELOC_HI16_S_GOTOFF, R_MIPS_GOTPC_HI16 },
+ { BFD_RELOC_LO16_GOTOFF, R_MIPS_GOTPC_LO16 },
+ { BFD_RELOC_MIPS_HI16_S_GOTOFF_CALL, R_MIPS_GOTPC_CALL_HI16 },
+ { BFD_RELOC_MIPS_LO16_GOTOFF_CALL, R_MIPS_GOTPC_CALL_LO16 },
+ { BFD_RELOC_MIPS_AHI16_S_GOTOFF, R_MIPS_GOTPC_AHI16 },
+ { BFD_RELOC_MIPS_ALO16_GOTOFF, R_MIPS_GOTPC_ALO16 },
+ { BFD_RELOC_MIPS_AHI16_S_GOTOFF_CALL, R_MIPS_GOTPC_CALL_AHI16 },
+ { BFD_RELOC_MIPS_ALO16_GOTOFF_CALL, R_MIPS_GOTPC_CALL_ALO16 }
};
static const struct elf_reloc_map mips16_reloc_map[] =
diff --git a/bfd/elfn32-mips.c b/bfd/elfn32-mips.c
index e137204aff7..87cb2d2168a 100644
--- a/bfd/elfn32-mips.c
+++ b/bfd/elfn32-mips.c
@@ -868,6 +868,118 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
0x0000ffff, /* dst_mask */
true), /* pcrel_offset */
+ HOWTO (R_MIPS_GOTPC_HI16, /* type */
+ 16, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_HI16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_LO16, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_LO16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_CALL_HI16, /* type */
+ 16, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_CALL_HI16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_CALL_LO16, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_CALL_LO16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_AHI16, /* type */
+ 16, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_AHI16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_ALO16, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_ALO16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_CALL_AHI16, /* type */
+ 16, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_CALL_AHI16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_CALL_ALO16, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_CALL_ALO16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
};
/* The relocation table used for SHT_RELA sections. */
@@ -1650,6 +1762,118 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
0x0000ffff, /* dst_mask */
true), /* pcrel_offset */
+ HOWTO (R_MIPS_GOTPC_HI16, /* type */
+ 16, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_HI16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_LO16, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_LO16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_CALL_HI16, /* type */
+ 16, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_CALL_HI16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_CALL_LO16, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_CALL_LO16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_AHI16, /* type */
+ 16, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_AHI16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_ALO16, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_ALO16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_CALL_AHI16, /* type */
+ 16, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_CALL_AHI16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_MIPS_GOTPC_CALL_ALO16, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOTPC_CALL_ALO16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
};
static reloc_howto_type elf_mips16_howto_table_rel[] =
@@ -3577,7 +3801,15 @@ static const struct elf_reloc_map mips_reloc_map[] =
{ BFD_RELOC_MIPS_18_PCREL_S3, R_MIPS_PC18_S3 },
{ BFD_RELOC_MIPS_19_PCREL_S2, R_MIPS_PC19_S2 },
{ BFD_RELOC_HI16_S_PCREL, R_MIPS_PCHI16 },
- { BFD_RELOC_LO16_PCREL, R_MIPS_PCLO16 }
+ { BFD_RELOC_LO16_PCREL, R_MIPS_PCLO16 },
+ { BFD_RELOC_HI16_S_GOTOFF, R_MIPS_GOTPC_HI16 },
+ { BFD_RELOC_LO16_GOTOFF, R_MIPS_GOTPC_LO16 },
+ { BFD_RELOC_MIPS_HI16_S_GOTOFF_CALL, R_MIPS_GOTPC_CALL_HI16 },
+ { BFD_RELOC_MIPS_LO16_GOTOFF_CALL, R_MIPS_GOTPC_CALL_LO16 },
+ { BFD_RELOC_MIPS_AHI16_S_GOTOFF, R_MIPS_GOTPC_AHI16 },
+ { BFD_RELOC_MIPS_ALO16_GOTOFF, R_MIPS_GOTPC_ALO16 },
+ { BFD_RELOC_MIPS_AHI16_S_GOTOFF_CALL, R_MIPS_GOTPC_CALL_AHI16 },
+ { BFD_RELOC_MIPS_ALO16_GOTOFF_CALL, R_MIPS_GOTPC_CALL_ALO16 }
};
static const struct elf_reloc_map mips16_reloc_map[] =
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 59444b063a4..fe209037839 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -2267,19 +2267,28 @@ got_page_reloc_p (unsigned int r_type)
static inline bool
got_lo16_reloc_p (unsigned int r_type)
{
- return r_type == R_MIPS_GOT_LO16 || r_type == R_MICROMIPS_GOT_LO16;
+ return (r_type == R_MIPS_GOT_LO16
+ || r_type == R_MIPS_GOTPC_LO16
+ || r_type == R_MIPS_GOTPC_ALO16
+ || r_type == R_MICROMIPS_GOT_LO16);
}
static inline bool
call_hi16_reloc_p (unsigned int r_type)
{
- return r_type == R_MIPS_CALL_HI16 || r_type == R_MICROMIPS_CALL_HI16;
+ return (r_type == R_MIPS_CALL_HI16
+ || r_type == R_MIPS_GOTPC_CALL_HI16
+ || r_type == R_MIPS_GOTPC_CALL_AHI16
+ || r_type == R_MICROMIPS_CALL_HI16);
}
static inline bool
call_lo16_reloc_p (unsigned int r_type)
{
- return r_type == R_MIPS_CALL_LO16 || r_type == R_MICROMIPS_CALL_LO16;
+ return (r_type == R_MIPS_CALL_LO16
+ || r_type == R_MIPS_GOTPC_CALL_LO16
+ || r_type == R_MIPS_GOTPC_CALL_ALO16
+ || r_type == R_MICROMIPS_CALL_LO16);
}
static inline bool
@@ -5240,6 +5249,21 @@ mips_elf_highest (bfd_vma value ATTRIBUTE_UNUSED)
return MINUS_ONE;
#endif
}
+
+/* Calculate the aligned hi or lo for aluipc. */
+static bfd_vma
+mips_elf_16bit_align (bfd_vma value, bfd_vma p, bool hi)
+{
+ bfd_vma value_lo = (value & 0xffff) + (p & 0xffff);
+ bfd_vma value_hi = (value >> 16) & 0xffff;
+ value_hi += mips_elf_high (value_lo);
+ value_lo &= 0xffff;
+ if (hi)
+ return value_hi;
+ else
+ return value_lo;
+}
+
/* Create the .compact_rel section. */
@@ -5887,6 +5911,10 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
case R_MIPS_GOT_DISP:
case R_MIPS_GOT_LO16:
case R_MIPS_CALL_LO16:
+ case R_MIPS_GOTPC_LO16:
+ case R_MIPS_GOTPC_CALL_LO16:
+ case R_MIPS_GOTPC_ALO16:
+ case R_MIPS_GOTPC_CALL_ALO16:
case R_MICROMIPS_CALL16:
case R_MICROMIPS_GOT16:
case R_MICROMIPS_GOT_PAGE:
@@ -5904,6 +5932,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
/* Fall through. */
case R_MIPS_GOT_HI16:
case R_MIPS_CALL_HI16:
+ case R_MIPS_GOTPC_HI16:
+ case R_MIPS_GOTPC_CALL_HI16:
case R_MICROMIPS_GOT_HI16:
case R_MICROMIPS_CALL_HI16:
if (resolved_to_zero
@@ -5951,6 +5981,14 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
case R_MIPS_CALL_HI16:
case R_MIPS_GOT_LO16:
case R_MIPS_CALL_LO16:
+ case R_MIPS_GOTPC_HI16:
+ case R_MIPS_GOTPC_LO16:
+ case R_MIPS_GOTPC_CALL_HI16:
+ case R_MIPS_GOTPC_CALL_LO16:
+ case R_MIPS_GOTPC_AHI16:
+ case R_MIPS_GOTPC_ALO16:
+ case R_MIPS_GOTPC_CALL_AHI16:
+ case R_MIPS_GOTPC_CALL_ALO16:
case R_MICROMIPS_CALL16:
case R_MICROMIPS_GOT16:
case R_MICROMIPS_GOT_DISP:
@@ -6412,6 +6450,45 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
value &= howto->dst_mask;
break;
+ /* For r6 and pre-r6, we can use:
+ bal . + 8
+ lui $2,%gotpc_hi(sym) # or %gotpc_call_hi
+ addu $2,$2,$ra
+ lw $2,%gotpc_lo(sym) # or %gotpc_call_lo
+ In this case, the LO should +=4, and HI should -=4.
+
+ For R6+, we can use
+ aluipc $2,%gotpc_ahi(sym) # or %gotpc_call_ahi
+ lw $2,%gotpc_alo(sym)($2) or %gotpc_call_alo
+ In this case, the HI is OK, while LO should +4 and add the page_offet */
+ case R_MIPS_GOTPC_HI16:
+ case R_MIPS_GOTPC_CALL_HI16:
+ value = mips_elf_high (addend + gp - p + g - 4);
+ value &= howto->dst_mask;
+ break;
+
+ case R_MIPS_GOTPC_LO16:
+ case R_MIPS_GOTPC_CALL_LO16:
+ if (howto->partial_inplace)
+ addend = _bfd_mips_elf_sign_extend (addend, 16);
+ value = addend + gp - p + g + 4;
+ value &= howto->dst_mask;
+ break;
+
+ case R_MIPS_GOTPC_AHI16:
+ case R_MIPS_GOTPC_CALL_AHI16:
+ value = mips_elf_16bit_align (addend + gp - p + g, p, true);
+ value &= howto->dst_mask;
+ break;
+
+ case R_MIPS_GOTPC_ALO16:
+ case R_MIPS_GOTPC_CALL_ALO16:
+ if (howto->partial_inplace)
+ addend = _bfd_mips_elf_sign_extend (addend, 16);
+ value = mips_elf_16bit_align (addend + gp - p + g, p, false);
+ value &= howto->dst_mask;
+ break;
+
case R_MIPS_PCHI16:
value = mips_elf_high (symbol + addend - p);
value &= howto->dst_mask;
@@ -8294,6 +8371,14 @@ mips_elf_add_lo16_rel_addend (bfd *abfd,
lo16_type = R_MIPS16_LO16;
else if (micromips_reloc_p (r_type))
lo16_type = R_MICROMIPS_LO16;
+ else if (r_type == R_MIPS_GOTPC_HI16)
+ lo16_type = R_MIPS_GOTPC_LO16;
+ else if (r_type == R_MIPS_GOTPC_CALL_HI16)
+ lo16_type = R_MIPS_GOTPC_CALL_LO16;
+ else if (r_type == R_MIPS_GOTPC_AHI16)
+ lo16_type = R_MIPS_GOTPC_ALO16;
+ else if (r_type == R_MIPS_GOTPC_CALL_AHI16)
+ lo16_type = R_MIPS_GOTPC_CALL_ALO16;
else if (r_type == R_MIPS_PCHI16)
lo16_type = R_MIPS_PCLO16;
else
@@ -8754,6 +8839,10 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_MIPS_CALL16:
case R_MIPS_CALL_HI16:
case R_MIPS_CALL_LO16:
+ case R_MIPS_GOTPC_CALL_HI16:
+ case R_MIPS_GOTPC_CALL_LO16:
+ case R_MIPS_GOTPC_CALL_AHI16:
+ case R_MIPS_GOTPC_CALL_ALO16:
case R_MIPS16_CALL16:
case R_MICROMIPS_CALL16:
case R_MICROMIPS_CALL_HI16:
@@ -8763,6 +8852,8 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_MIPS_GOT16:
case R_MIPS_GOT_LO16:
+ case R_MIPS_GOTPC_LO16:
+ case R_MIPS_GOTPC_ALO16:
case R_MIPS_GOT_PAGE:
case R_MIPS_GOT_DISP:
case R_MIPS16_GOT16:
@@ -8800,6 +8891,8 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
/* Fall through. */
case R_MIPS_GOT_HI16:
+ case R_MIPS_GOTPC_HI16:
+ case R_MIPS_GOTPC_AHI16:
case R_MIPS_GOT_OFST:
case R_MIPS_TLS_GOTTPREL:
case R_MIPS_TLS_GD:
@@ -8970,6 +9063,10 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_MIPS_CALL_HI16:
case R_MIPS_CALL_LO16:
+ case R_MIPS_GOTPC_CALL_HI16:
+ case R_MIPS_GOTPC_CALL_LO16:
+ case R_MIPS_GOTPC_CALL_AHI16:
+ case R_MIPS_GOTPC_CALL_ALO16:
case R_MICROMIPS_CALL_HI16:
case R_MICROMIPS_CALL_LO16:
if (h != NULL)
@@ -8995,6 +9092,10 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_MIPS_GOT16:
case R_MIPS_GOT_HI16:
case R_MIPS_GOT_LO16:
+ case R_MIPS_GOTPC_HI16:
+ case R_MIPS_GOTPC_LO16:
+ case R_MIPS_GOTPC_AHI16:
+ case R_MIPS_GOTPC_ALO16:
case R_MICROMIPS_GOT16:
case R_MICROMIPS_GOT_HI16:
case R_MICROMIPS_GOT_LO16:
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 5e8ed9eeefe..a9f95830e6e 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1315,6 +1315,15 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_MIPS_26_PCREL_S2",
"BFD_RELOC_MIPS_18_PCREL_S3",
"BFD_RELOC_MIPS_19_PCREL_S2",
+ "BFD_RELOC_MIPS_LO16_GOTOFF_CALL",
+ "BFD_RELOC_MIPS_HI16_GOTOFF_CALL",
+ "BFD_RELOC_MIPS_HI16_S_GOTOFF_CALL",
+ "BFD_RELOC_MIPS_ALO16_GOTOFF",
+ "BFD_RELOC_MIPS_AHI16_GOTOFF",
+ "BFD_RELOC_MIPS_AHI16_S_GOTOFF",
+ "BFD_RELOC_MIPS_ALO16_GOTOFF_CALL",
+ "BFD_RELOC_MIPS_AHI16_GOTOFF_CALL",
+ "BFD_RELOC_MIPS_AHI16_S_GOTOFF_CALL",
"BFD_RELOC_MICROMIPS_GPREL16",
"BFD_RELOC_MICROMIPS_HI16",
"BFD_RELOC_MICROMIPS_HI16_S",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index a187afe9b56..b88763c850b 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -2040,6 +2040,24 @@ ENUMX
BFD_RELOC_MIPS_18_PCREL_S3
ENUMX
BFD_RELOC_MIPS_19_PCREL_S2
+ENUMX
+ BFD_RELOC_LO16_GOTOFF_CALL
+ENUMX
+ BFD_RELOC_HI16_GOTOFF_CALL
+ENUMX
+ BFD_RELOC_HI16_S_GOTOFF_CALL
+ENUMX
+ BFD_RELOC_ALO16_GOTOFF
+ENUMX
+ BFD_RELOC_AHI16_GOTOFF
+ENUMX
+ BFD_RELOC_AHI16_S_GOTOFF
+ENUMX
+ BFD_RELOC_ALO16_GOTOFF_CALL
+ENUMX
+ BFD_RELOC_AHI16_GOTOFF_CALL
+ENUMX
+ BFD_RELOC_AHI16_S_GOTOFF_CALL
ENUMDOC
MIPS PC-relative relocations.
diff --git a/elfcpp/mips.h b/elfcpp/mips.h
index e8a8e2458e9..79884bd651b 100644
--- a/elfcpp/mips.h
+++ b/elfcpp/mips.h
@@ -104,6 +104,14 @@ enum
R_MIPS_PC19_S2 = 63,
R_MIPS_PCHI16 = 64,
R_MIPS_PCLO16 = 65,
+ R_MIPS_GOTPC_HI16 = 66,
+ R_MIPS_GOTPC_LO16 = 67,
+ R_MIPS_GOTPC_CALL_HI16 = 68,
+ R_MIPS_GOTPC_CALL_LO16 = 69,
+ R_MIPS_GOTPC_AHI16 = 70,
+ R_MIPS_GOTPC_ALO16 = 71,
+ R_MIPS_GOTPC_CALL_AHI16 = 72,
+ R_MIPS_GOTPC_CALL_ALO16 = 73,
// These relocs are used for the mips16.
R_MIPS16_26 = 100,
R_MIPS16_GPREL = 101,
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 8f54cb8937a..7ee6c0259fa 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -4372,6 +4372,14 @@ limited_pcrel_reloc_p (bfd_reloc_code_real_type reloc)
case BFD_RELOC_32_PCREL:
case BFD_RELOC_HI16_S_PCREL:
case BFD_RELOC_LO16_PCREL:
+ case BFD_RELOC_HI16_S_GOTOFF:
+ case BFD_RELOC_LO16_GOTOFF:
+ case BFD_RELOC_MIPS_LO16_GOTOFF_CALL:
+ case BFD_RELOC_MIPS_HI16_S_GOTOFF_CALL:
+ case BFD_RELOC_MIPS_AHI16_S_GOTOFF:
+ case BFD_RELOC_MIPS_ALO16_GOTOFF:
+ case BFD_RELOC_MIPS_ALO16_GOTOFF_CALL:
+ case BFD_RELOC_MIPS_AHI16_S_GOTOFF_CALL:
return HAVE_64BIT_ADDRESSES;
default:
@@ -7432,6 +7440,8 @@ calculate_reloc (bfd_reloc_code_real_type reloc, offsetT operand,
case BFD_RELOC_HI16_S:
case BFD_RELOC_HI16_S_PCREL:
+ case BFD_RELOC_HI16_S_GOTOFF:
+ case BFD_RELOC_MIPS_AHI16_S_GOTOFF:
case BFD_RELOC_MICROMIPS_HI16_S:
case BFD_RELOC_MIPS16_HI16_S:
*result = ((operand + 0x8000) >> 16) & 0xffff;
@@ -7445,6 +7455,10 @@ calculate_reloc (bfd_reloc_code_real_type reloc, offsetT operand,
case BFD_RELOC_LO16:
case BFD_RELOC_LO16_PCREL:
+ case BFD_RELOC_LO16_GOTOFF:
+ case BFD_RELOC_MIPS_LO16_GOTOFF_CALL:
+ case BFD_RELOC_MIPS_ALO16_GOTOFF:
+ case BFD_RELOC_MIPS_ALO16_GOTOFF_CALL:
case BFD_RELOC_MICROMIPS_LO16:
case BFD_RELOC_MIPS16_LO16:
*result = operand & 0xffff;
@@ -7507,6 +7521,22 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
as_warn (_("wrong size instruction in a %u-bit branch delay slot"),
(prev_pinfo2 & INSN2_BRANCH_DELAY_16BIT) != 0 ? 16 : 32);
+ if (!ISA_IS_R6 (mips_opts.isa))
+ switch (*reloc_type)
+ {
+ default:
+ break;
+
+ case BFD_RELOC_MIPS_ALO16_GOTOFF:
+ case BFD_RELOC_MIPS_AHI16_GOTOFF:
+ case BFD_RELOC_MIPS_AHI16_S_GOTOFF:
+ case BFD_RELOC_MIPS_ALO16_GOTOFF_CALL:
+ case BFD_RELOC_MIPS_AHI16_GOTOFF_CALL:
+ case BFD_RELOC_MIPS_AHI16_S_GOTOFF_CALL:
+ as_fatal (_("ALUIPC style GOTPC cannot work with pre-R6."));
+ break;
+ }
+
if (address_expr == NULL)
ip->complete_p = 1;
else if (reloc_type[0] <= BFD_RELOC_UNUSED
@@ -14583,7 +14613,15 @@ static const struct percent_op_match mips_percent_op[] =
{"%gottprel", BFD_RELOC_MIPS_TLS_GOTTPREL},
{"%hi", BFD_RELOC_HI16_S},
{"%pcrel_hi", BFD_RELOC_HI16_S_PCREL},
- {"%pcrel_lo", BFD_RELOC_LO16_PCREL}
+ {"%pcrel_lo", BFD_RELOC_LO16_PCREL},
+ {"%gotpc_hi", BFD_RELOC_HI16_S_GOTOFF},
+ {"%gotpc_lo", BFD_RELOC_LO16_GOTOFF},
+ {"%gotpc_call_hi", BFD_RELOC_MIPS_HI16_S_GOTOFF_CALL},
+ {"%gotpc_call_lo", BFD_RELOC_MIPS_LO16_GOTOFF_CALL},
+ {"%gotpc_ahi", BFD_RELOC_MIPS_AHI16_S_GOTOFF},
+ {"%gotpc_alo", BFD_RELOC_MIPS_ALO16_GOTOFF},
+ {"%gotpc_call_ahi", BFD_RELOC_MIPS_AHI16_S_GOTOFF_CALL},
+ {"%gotpc_call_alo", BFD_RELOC_MIPS_ALO16_GOTOFF_CALL}
};
static const struct percent_op_match mips16_percent_op[] =
@@ -15543,6 +15581,14 @@ mips_force_relocation (fixS *fixp)
|| fixp->fx_r_type == BFD_RELOC_MIPS_26_PCREL_S2
|| fixp->fx_r_type == BFD_RELOC_MIPS_18_PCREL_S3
|| fixp->fx_r_type == BFD_RELOC_MIPS_19_PCREL_S2
+ || fixp->fx_r_type == BFD_RELOC_HI16_S_GOTOFF
+ || fixp->fx_r_type == BFD_RELOC_LO16_GOTOFF
+ || fixp->fx_r_type == BFD_RELOC_MIPS_LO16_GOTOFF_CALL
+ || fixp->fx_r_type == BFD_RELOC_MIPS_HI16_S_GOTOFF_CALL
+ || fixp->fx_r_type == BFD_RELOC_MIPS_AHI16_S_GOTOFF
+ || fixp->fx_r_type == BFD_RELOC_MIPS_ALO16_GOTOFF
+ || fixp->fx_r_type == BFD_RELOC_MIPS_ALO16_GOTOFF_CALL
+ || fixp->fx_r_type == BFD_RELOC_MIPS_AHI16_S_GOTOFF_CALL
|| fixp->fx_r_type == BFD_RELOC_HI16_S_PCREL
|| fixp->fx_r_type == BFD_RELOC_LO16_PCREL))
return 1;
@@ -15824,6 +15870,14 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
case BFD_RELOC_MIPS_19_PCREL_S2:
case BFD_RELOC_HI16_S_PCREL:
case BFD_RELOC_LO16_PCREL:
+ case BFD_RELOC_HI16_S_GOTOFF:
+ case BFD_RELOC_LO16_GOTOFF:
+ case BFD_RELOC_MIPS_HI16_S_GOTOFF_CALL:
+ case BFD_RELOC_MIPS_LO16_GOTOFF_CALL:
+ case BFD_RELOC_MIPS_AHI16_S_GOTOFF:
+ case BFD_RELOC_MIPS_ALO16_GOTOFF:
+ case BFD_RELOC_MIPS_AHI16_S_GOTOFF_CALL:
+ case BFD_RELOC_MIPS_ALO16_GOTOFF_CALL:
break;
case BFD_RELOC_32:
@@ -15967,6 +16021,14 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
case BFD_RELOC_MIPS_GOT_LO16:
case BFD_RELOC_MIPS_CALL_HI16:
case BFD_RELOC_MIPS_CALL_LO16:
+ case BFD_RELOC_HI16_S_GOTOFF:
+ case BFD_RELOC_LO16_GOTOFF:
+ case BFD_RELOC_MIPS_HI16_S_GOTOFF_CALL:
+ case BFD_RELOC_MIPS_LO16_GOTOFF_CALL:
+ case BFD_RELOC_MIPS_AHI16_S_GOTOFF:
+ case BFD_RELOC_MIPS_ALO16_GOTOFF:
+ case BFD_RELOC_MIPS_AHI16_S_GOTOFF_CALL:
+ case BFD_RELOC_MIPS_ALO16_GOTOFF_CALL:
case BFD_RELOC_HI16_S_PCREL:
case BFD_RELOC_LO16_PCREL:
case BFD_RELOC_MIPS16_GPREL:
@@ -18388,6 +18450,14 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
|| fixp->fx_r_type == BFD_RELOC_MIPS_26_PCREL_S2
|| fixp->fx_r_type == BFD_RELOC_MIPS_18_PCREL_S3
|| fixp->fx_r_type == BFD_RELOC_MIPS_19_PCREL_S2
+ || fixp->fx_r_type == BFD_RELOC_HI16_S_GOTOFF
+ || fixp->fx_r_type == BFD_RELOC_LO16_GOTOFF
+ || fixp->fx_r_type == BFD_RELOC_MIPS_LO16_GOTOFF_CALL
+ || fixp->fx_r_type == BFD_RELOC_MIPS_HI16_S_GOTOFF_CALL
+ || fixp->fx_r_type == BFD_RELOC_MIPS_AHI16_S_GOTOFF
+ || fixp->fx_r_type == BFD_RELOC_MIPS_ALO16_GOTOFF
+ || fixp->fx_r_type == BFD_RELOC_MIPS_ALO16_GOTOFF_CALL
+ || fixp->fx_r_type == BFD_RELOC_MIPS_AHI16_S_GOTOFF_CALL
|| fixp->fx_r_type == BFD_RELOC_HI16_S_PCREL
|| fixp->fx_r_type == BFD_RELOC_LO16_PCREL);
diff --git a/gas/testsuite/gas/mips/gotpc-aluipc-32.s b/gas/testsuite/gas/mips/gotpc-aluipc-32.s
new file mode 100644
index 00000000000..877193313a1
--- /dev/null
+++ b/gas/testsuite/gas/mips/gotpc-aluipc-32.s
@@ -0,0 +1,51 @@
+ .file 1 "nn.c"
+ .section .mdebug.abi32
+ .previous
+ .nan 2008
+ .module fp=xx
+ .module nooddspreg
+ .module arch=mips32r6
+ .abicalls
+ .text
+ .section .rodata.str1.4,"aMS",@progbits,1
+ .align 2
+$LC0:
+ .ascii "XXXX\000"
+ .section .text.startup,"ax",@progbits
+ .align 2
+ .globl main
+ .set nomips16
+ .ent main
+ .type main, @function
+main:
+ .frame $sp,32,$31 # vars= 0, regs= 1/0, args= 16, gp= 8
+ .mask 0x80000000,-4
+ .fmask 0x00000000,0
+ .set noreorder
+ .cpload $25
+ .set nomacro
+ addiu $sp,$sp,-32
+ sw $31,28($sp)
+
+ aluipc $4,%gotpc_ahi($LC0)
+ lw $4,%gotpc_alo($LC0)($4)
+
+ aluipc $25,%gotpc_call_ahi(puts)
+ lw $25,%gotpc_call_alo(puts)($25)
+
+ .cprestore 16
+ .reloc 1f,R_MIPS_JALR,puts
+1: jalr $25
+ nop
+
+ lw $31,28($sp)
+ move $2,$0
+ jr $31
+ addiu $sp,$sp,32
+
+ .set macro
+ .set reorder
+ .end main
+ .size main, .-main
+ .ident "GCC: (Debian 12.2.0-14) 12.2.0"
+ .section .note.GNU-stack,"",@progbits
diff --git a/gas/testsuite/gas/mips/gotpc-aluipc-64.s b/gas/testsuite/gas/mips/gotpc-aluipc-64.s
new file mode 100644
index 00000000000..234be37b6fe
--- /dev/null
+++ b/gas/testsuite/gas/mips/gotpc-aluipc-64.s
@@ -0,0 +1,50 @@
+ .file 1 "nn.c"
+ .section .mdebug.abi64
+ .previous
+ .abicalls
+ .text
+ .section .rodata.str1.8,"aMS",@progbits,1
+ .align 3
+.LC0:
+ .ascii "XXXX\000"
+ .section .text.startup,"ax",@progbits
+ .align 2
+ .align 3
+ .globl main
+ .set nomips16
+ .ent main
+ .type main, @function
+main:
+ .frame $sp,16,$31 # vars= 0, regs= 2/0, args= 0, gp= 0
+ .mask 0x90000000,-8
+ .fmask 0x00000000,0
+ .set noreorder
+ .set nomacro
+ daddiu $sp,$sp,-16
+ sd $28,0($sp)
+ lui $28,%hi(%neg(%gp_rel(main)))
+ daddu $28,$28,$25
+ sd $31,8($sp)
+ daddiu $28,$28,%lo(%neg(%gp_rel(main)))
+
+ aluipc $4,%gotpc_ahi(.LC0)
+ ld $4,%gotpc_alo(.LC0)($4)
+
+ aluipc $25,%gotpc_call_ahi(puts)
+ ld $25,%gotpc_call_alo(puts)($25)
+
+ .reloc 1f,R_MIPS_JALR,puts
+1: jalr $25
+ nop
+
+ ld $31,8($sp)
+ ld $28,0($sp)
+ move $2,$0
+ jr $31
+ daddiu $sp,$sp,16
+
+ .set macro
+ .set reorder
+ .end main
+ .size main, .-main
+ .section .note.GNU-stack,"",@progbits
diff --git a/gas/testsuite/gas/mips/gotpc-aluipc-n32.d b/gas/testsuite/gas/mips/gotpc-aluipc-n32.d
new file mode 100644
index 00000000000..41bc6d474d7
--- /dev/null
+++ b/gas/testsuite/gas/mips/gotpc-aluipc-n32.d
@@ -0,0 +1,17 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: R_MIPS_GOTPC support (NewABI, ALUIPC, N32)
+#source: gotpc-aluipc-64.s
+#as: -n32 -mips64r6
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text\.startup:
+#...
+.*R_MIPS_GOTPC_AHI16 \.rodata\.str1\.8
+#...
+.*R_MIPS_GOTPC_ALO16 \.rodata\.str1\.8
+#...
+.*R_MIPS_GOTPC_CALL_AHI16 puts
+#...
+.*R_MIPS_GOTPC_CALL_ALO16 puts
+#pass
diff --git a/gas/testsuite/gas/mips/gotpc-aluipc-n64.d b/gas/testsuite/gas/mips/gotpc-aluipc-n64.d
new file mode 100644
index 00000000000..0561040ef09
--- /dev/null
+++ b/gas/testsuite/gas/mips/gotpc-aluipc-n64.d
@@ -0,0 +1,25 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: R_MIPS_GOTPC support (NewABI, ALUIPC, N64)
+#source: gotpc-aluipc-64.s
+#as: -64 -mips64r6
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text\.startup:
+#...
+.*R_MIPS_GOTPC_AHI16 \.LC0
+.*R_MIPS_NONE.*
+.*R_MIPS_NONE.*
+#...
+.*R_MIPS_GOTPC_ALO16 \.LC0
+.*R_MIPS_NONE.*
+.*R_MIPS_NONE.*
+#...
+.*R_MIPS_GOTPC_CALL_AHI16 puts
+.*R_MIPS_NONE.*
+.*R_MIPS_NONE.*
+#...
+.*R_MIPS_GOTPC_CALL_ALO16 puts
+.*R_MIPS_NONE.*
+.*R_MIPS_NONE.*
+#pass
diff --git a/gas/testsuite/gas/mips/gotpc-aluipc-o32.d b/gas/testsuite/gas/mips/gotpc-aluipc-o32.d
new file mode 100644
index 00000000000..1832061a34e
--- /dev/null
+++ b/gas/testsuite/gas/mips/gotpc-aluipc-o32.d
@@ -0,0 +1,17 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: R_MIPS_GOTPC support (OldABI, ALUIPC, O32)
+#source: gotpc-aluipc-32.s
+#as: -32 -mips32r6
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text\.startup:
+#...
+.*R_MIPS_GOTPC_AHI16 \.rodata\.str1\.4
+#...
+.*R_MIPS_GOTPC_ALO16 \.rodata\.str1\.4
+#...
+.*R_MIPS_GOTPC_CALL_AHI16 puts
+#...
+.*R_MIPS_GOTPC_CALL_ALO16 puts
+#pass
diff --git a/gas/testsuite/gas/mips/gotpc-bal-32.s b/gas/testsuite/gas/mips/gotpc-bal-32.s
new file mode 100644
index 00000000000..841a13dbf87
--- /dev/null
+++ b/gas/testsuite/gas/mips/gotpc-bal-32.s
@@ -0,0 +1,55 @@
+ .file 1 "nn.c"
+ .section .mdebug.abi32
+ .previous
+ .nan 2008
+ .module fp=xx
+ .module nooddspreg
+ .module arch=mips32r6
+ .abicalls
+ .text
+ .section .rodata.str1.4,"aMS",@progbits,1
+ .align 2
+$LC0:
+ .ascii "XXXX\000"
+ .section .text.startup,"ax",@progbits
+ .align 2
+ .globl main
+ .set nomips16
+ .ent main
+ .type main, @function
+main:
+ .frame $sp,32,$31 # vars= 0, regs= 1/0, args= 16, gp= 8
+ .mask 0x80000000,-4
+ .fmask 0x00000000,0
+ .set noreorder
+ .cpload $25
+ .set nomacro
+ addiu $sp,$sp,-32
+ sw $31,28($sp)
+
+ bal . + 8
+ lui $4,%gotpc_hi($LC0)
+ addu $4,$4,$31
+ lw $4,%gotpc_lo($LC0)($4)
+
+ bal . + 8
+ lui $25,%gotpc_call_hi(puts)
+ addu $25,$25,$31
+ lw $25,%gotpc_call_lo(puts)($25)
+
+ .cprestore 16
+ .reloc 1f,R_MIPS_JALR,puts
+1: jalr $25
+ nop
+
+ lw $31,28($sp)
+ move $2,$0
+ jr $31
+ addiu $sp,$sp,32
+
+ .set macro
+ .set reorder
+ .end main
+ .size main, .-main
+ .ident "GCC: (Debian 12.2.0-14) 12.2.0"
+ .section .note.GNU-stack,"",@progbits
diff --git a/gas/testsuite/gas/mips/gotpc-bal-64.s b/gas/testsuite/gas/mips/gotpc-bal-64.s
new file mode 100644
index 00000000000..c97e6b87af9
--- /dev/null
+++ b/gas/testsuite/gas/mips/gotpc-bal-64.s
@@ -0,0 +1,54 @@
+ .file 1 "nn.c"
+ .section .mdebug.abi64
+ .previous
+ .abicalls
+ .text
+ .section .rodata.str1.8,"aMS",@progbits,1
+ .align 3
+.LC0:
+ .ascii "XXXX\000"
+ .section .text.startup,"ax",@progbits
+ .align 2
+ .align 3
+ .globl main
+ .set nomips16
+ .ent main
+ .type main, @function
+main:
+ .frame $sp,16,$31 # vars= 0, regs= 2/0, args= 0, gp= 0
+ .mask 0x90000000,-8
+ .fmask 0x00000000,0
+ .set noreorder
+ .set nomacro
+ daddiu $sp,$sp,-16
+ sd $28,0($sp)
+ lui $28,%hi(%neg(%gp_rel(main)))
+ daddu $28,$28,$25
+ sd $31,8($sp)
+ daddiu $28,$28,%lo(%neg(%gp_rel(main)))
+
+ bal . + 8
+ lui $4,%gotpc_hi(.LC0)
+ daddu $4,$4,$31
+ ld $4,%gotpc_lo(.LC0)($4)
+
+ bal . + 8
+ lui $25,%gotpc_call_hi(puts)
+ daddu $25,$25,$31
+ ld $25,%gotpc_call_lo(puts)($25)
+
+ .reloc 1f,R_MIPS_JALR,puts
+1: jalr $25
+ nop
+
+ ld $31,8($sp)
+ ld $28,0($sp)
+ move $2,$0
+ jr $31
+ daddiu $sp,$sp,16
+
+ .set macro
+ .set reorder
+ .end main
+ .size main, .-main
+ .section .note.GNU-stack,"",@progbits
diff --git a/gas/testsuite/gas/mips/gotpc-bal-n32.d b/gas/testsuite/gas/mips/gotpc-bal-n32.d
new file mode 100644
index 00000000000..ec412020dc7
--- /dev/null
+++ b/gas/testsuite/gas/mips/gotpc-bal-n32.d
@@ -0,0 +1,17 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: R_MIPS_GOTPC support (NewABI, BAL, N32)
+#source: gotpc-bal-64.s
+#as: -n32 -march=from-abi
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text\.startup:
+#...
+.*R_MIPS_GOTPC_HI16 \.rodata\.str1\.8
+#...
+.*R_MIPS_GOTPC_LO16 \.rodata\.str1\.8
+#...
+.*R_MIPS_GOTPC_CALL_HI16 puts
+#...
+.*R_MIPS_GOTPC_CALL_LO16 puts
+#pass
diff --git a/gas/testsuite/gas/mips/gotpc-bal-n64.d b/gas/testsuite/gas/mips/gotpc-bal-n64.d
new file mode 100644
index 00000000000..60b9f020f50
--- /dev/null
+++ b/gas/testsuite/gas/mips/gotpc-bal-n64.d
@@ -0,0 +1,25 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: R_MIPS_GOTPC support (NewABI, BAL, N64)
+#source: gotpc-bal-64.s
+#as: -64 -march=from-abi
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text\.startup:
+#...
+.*R_MIPS_GOTPC_HI16 \.rodata\.str1\.8
+.*R_MIPS_NONE.*
+.*R_MIPS_NONE.*
+#...
+.*R_MIPS_GOTPC_LO16 \.rodata\.str1\.8
+.*R_MIPS_NONE.*
+.*R_MIPS_NONE.*
+#...
+.*R_MIPS_GOTPC_CALL_HI16 puts
+.*R_MIPS_NONE.*
+.*R_MIPS_NONE.*
+#...
+.*R_MIPS_GOTPC_CALL_LO16 puts
+.*R_MIPS_NONE.*
+.*R_MIPS_NONE.*
+#pass
diff --git a/gas/testsuite/gas/mips/gotpc-bal-o32.d b/gas/testsuite/gas/mips/gotpc-bal-o32.d
new file mode 100644
index 00000000000..57cb891042a
--- /dev/null
+++ b/gas/testsuite/gas/mips/gotpc-bal-o32.d
@@ -0,0 +1,17 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: R_MIPS_GOTPC support (OldABI, BAL, O32)
+#source: gotpc-bal-32.s
+#as: -32 -march=from-abi
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text\.startup:
+#...
+.*R_MIPS_GOTPC_HI16 \.rodata\.str1\.4
+#...
+.*R_MIPS_GOTPC_LO16 \.rodata\.str1\.4
+#...
+.*R_MIPS_GOTPC_CALL_HI16 puts
+#...
+.*R_MIPS_GOTPC_CALL_LO16 puts
+#pass
diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp
index 2ddbf0c768d..619d04b3bd5 100644
--- a/gas/testsuite/gas/mips/mips.exp
+++ b/gas/testsuite/gas/mips/mips.exp
@@ -1210,7 +1210,15 @@ if { [istarget mips*-*-vxworks*] } {
run_dump_test "elf-rel-xgot-n32"
run_dump_test "elf-rel-got-n64"
run_dump_test "elf-rel-xgot-n64"
+
+ run_dump_test "gotpc-bal-n64"
+ run_dump_test "gotpc-bal-n32"
+ run_dump_test "gotpc-aluipc-n64"
+ run_dump_test "gotpc-aluipc-n32"
}
+ run_dump_test "gotpc-bal-o32"
+ run_dump_test "gotpc-aluipc-o32"
+
run_dump_test "elf-rel17"
if $has_newabi {
run_dump_test "elf-rel18"
diff --git a/include/elf/mips.h b/include/elf/mips.h
index fb3357666ec..2bb9a46dd70 100644
--- a/include/elf/mips.h
+++ b/include/elf/mips.h
@@ -98,7 +98,15 @@ START_RELOC_NUMBERS (elf_mips_reloc_type)
RELOC_NUMBER (R_MIPS_PC19_S2, 63)
RELOC_NUMBER (R_MIPS_PCHI16, 64)
RELOC_NUMBER (R_MIPS_PCLO16, 65)
- FAKE_RELOC (R_MIPS_max, 66)
+ RELOC_NUMBER (R_MIPS_GOTPC_HI16, 66)
+ RELOC_NUMBER (R_MIPS_GOTPC_LO16, 67)
+ RELOC_NUMBER (R_MIPS_GOTPC_CALL_HI16, 68)
+ RELOC_NUMBER (R_MIPS_GOTPC_CALL_LO16, 69)
+ RELOC_NUMBER (R_MIPS_GOTPC_AHI16, 70)
+ RELOC_NUMBER (R_MIPS_GOTPC_ALO16, 71)
+ RELOC_NUMBER (R_MIPS_GOTPC_CALL_AHI16, 72)
+ RELOC_NUMBER (R_MIPS_GOTPC_CALL_ALO16, 73)
+ FAKE_RELOC (R_MIPS_max, 74)
/* These relocs are used for the mips16. */
FAKE_RELOC (R_MIPS16_min, 100)
RELOC_NUMBER (R_MIPS16_26, 100)
diff --git a/ld/testsuite/ld-mips-elf/gotpc-callee.s b/ld/testsuite/ld-mips-elf/gotpc-callee.s
new file mode 100644
index 00000000000..4689b66f302
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/gotpc-callee.s
@@ -0,0 +1,41 @@
+ .text
+ .set nomips16
+ .set nomicromips
+ .globl c1
+ .ent c1
+ .type c1, @function
+c1:
+ .set noreorder
+ .set nomacro
+ jr $31
+ li $2,1
+ .set reorder
+ .set macro
+ .end c1
+ .size c1, .-c1
+
+ .globl c2
+ .ent c2
+ .type c2, @function
+c2:
+ .set noreorder
+ .set nomacro
+ jr $31
+ li $2,2
+ .set reorder
+ .set macro
+ .end c2
+ .size c2, .-c2
+
+ .data
+ .globl g1
+ .type g1, @object
+ .size g1, 4
+g1:
+ .word 0x12345678
+
+ .globl g2
+ .type g2, @object
+ .size g2, 4
+g2:
+ .word 0x09abcdef
diff --git a/ld/testsuite/ld-mips-elf/gotpc-n32.dd b/ld/testsuite/ld-mips-elf/gotpc-n32.dd
new file mode 100644
index 00000000000..2c94d04ee27
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/gotpc-n32.dd
@@ -0,0 +1,73 @@
+
+.*: +file format .*mips.*
+
+DYNAMIC SYMBOL TABLE:
+00000000 g DF .text 00000074 f1
+00000090 DF \*UND\* 00000000 c1
+00000004 g DO \*ABS\* 00000004 g2
+00000080 DF \*UND\* 00000000 c2
+00000000 g DO \*ABS\* 00000004 g1
+
+
+
+Disassembly of section .text:
+
+00000000 <f1>:
+ 0: 27bdfff0 addiu sp,sp,-16
+ 4: ffbf0008 sd ra,8\(sp\)
+ 8: ffb00000 sd s0,0\(sp\)
+ c: 24100000 li s0,0
+
+00000010 <L0\^A>:
+ 10: 04110001 bal 18 <L0\^A\+0x8>
+ 14: 3c190000 lui t9,0x0
+ 18: 033fc821 addu t9,t9,ra
+ 1c: 8f3900a0 lw t9,160\(t9\)
+ 20: 0320f809 jalr t9
+ 24: 00000000 nop
+ 28: 02028021 addu s0,s0,v0
+ 2c: ef3f0000 aluipc t9,0x0
+ 30: 8f3900c0 lw t9,192\(t9\)
+ 34: 0320f809 jalr t9
+ 38: 00000000 nop
+ 3c: 02028021 addu s0,s0,v0
+
+00000040 <L0\^A>:
+ 40: 04110001 bal 48 <L0\^A\+0x8>
+ 44: 3c020000 lui v0,0x0
+ 48: 005f1021 addu v0,v0,ra
+ 4c: 8c42007c lw v0,124\(v0\)
+ 50: 00501021 addu v0,v0,s0
+ 54: ec7f0000 aluipc v1,0x0
+ 58: 8c6300bc lw v1,188\(v1\)
+ 5c: 00431021 addu v0,v0,v1
+ 60: dfb00000 ld s0,0\(sp\)
+ 64: dfbf0008 ld ra,8\(sp\)
+ 68: 24420001 addiu v0,v0,1
+ 6c: 03e00009 jr ra
+ 70: 27bd0010 addiu sp,sp,16
+ ...
+
+Disassembly of section .MIPS.stubs:
+
+00000080 <_MIPS_STUBS_>:
+ 80: 8f998010 lw t9,-32752\(gp\)
+ 84: 03e07825 move t3,ra
+ 88: 0320f809 jalr t9
+ 8c: 24180004 li t8,4
+ 90: 8f998010 lw t9,-32752\(gp\)
+ 94: 03e07825 move t3,ra
+ 98: 0320f809 jalr t9
+ 9c: 24180002 li t8,2
+ ...
+
+Disassembly of section .got:
+
+000000b0 <.got>:
+ b0: 00000000 nop
+ b4: 80000000 lb zero,0\(zero\)
+ b8: 00000090 .word 0x90
+ bc: 00000004 sllv zero,zero,zero
+ c0: 00000080 sll zero,zero,0x2
+ c4: 00000000 nop
+#...
diff --git a/ld/testsuite/ld-mips-elf/gotpc-n32.gd b/ld/testsuite/ld-mips-elf/gotpc-n32.gd
new file mode 100644
index 00000000000..33c9b40ab77
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/gotpc-n32.gd
@@ -0,0 +1,15 @@
+
+Primary GOT:
+ Canonical gp value: 000080a0
+
+ Reserved entries:
+ Address Access Initial Purpose
+ 000000b0 -32752\(gp\) 00000000 Lazy resolver
+ 000000b4 -32748\(gp\) 80000000 Module pointer \(GNU extension\)
+
+ Global entries:
+ Address Access Initial Sym.Val. Type Ndx Name
+ 000000b8 -32744\(gp\) 00000090 00000090 FUNC UND c1
+ 000000bc -32740\(gp\) 00000004 00000004 OBJECT ABS g2
+ 000000c0 -32736\(gp\) 00000080 00000080 FUNC UND c2
+ 000000c4 -32732\(gp\) 00000000 00000000 OBJECT ABS g1
diff --git a/ld/testsuite/ld-mips-elf/gotpc-n32.s b/ld/testsuite/ld-mips-elf/gotpc-n32.s
new file mode 100644
index 00000000000..ce4f4af87f1
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/gotpc-n32.s
@@ -0,0 +1,46 @@
+ .text
+ .globl f1
+ .set nomips16
+ .set nomicromips
+ .ent f1
+ .type f1, @function
+f1:
+ .set noreorder
+ .set nomacro
+ addiu $sp,$sp,-16
+ sd $31,8($sp)
+ sd $16,0($sp)
+ li $16,0
+
+ bal . + 8
+ lui $25,%gotpc_call_hi(c1)
+ addu $25,$25,$31
+ lw $25,%gotpc_call_lo(c1)($25)
+ jalr $25
+ nop
+ addu $16,$16,$2
+ aluipc $25,%gotpc_call_ahi(c2)
+ lw $25,%gotpc_call_alo(c2)($25)
+ jalr $25
+ nop
+ addu $16,$16,$2
+
+ bal . + 8
+ lui $2,%gotpc_hi(g1)
+ addu $2,$2,$31
+ lw $2,%gotpc_lo(g1)($2)
+ addu $2,$2,$16
+ aluipc $3,%gotpc_ahi(g2)
+ lw $3,%gotpc_alo(g2)($3)
+ addu $2,$2,$3
+
+ ld $16,0($sp)
+ ld $31,8($sp)
+ addiu $2,$2,1
+ jr $31
+ addiu $sp,$sp,16
+
+ .set macro
+ .set reorder
+ .end f1
+ .size f1, .-f1
diff --git a/ld/testsuite/ld-mips-elf/gotpc-n64.dd b/ld/testsuite/ld-mips-elf/gotpc-n64.dd
new file mode 100644
index 00000000000..08e8e2b48a1
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/gotpc-n64.dd
@@ -0,0 +1,75 @@
+
+.*: +file format .*mips.*
+
+DYNAMIC SYMBOL TABLE:
+0000000000000000 g DF .text 0000000000000074 f1
+0000000000000090 DF \*UND\* 0000000000000000 c1
+0000000000000004 g DO \*ABS\* 0000000000000004 g2
+0000000000000080 DF \*UND\* 0000000000000000 c2
+0000000000000000 g DO \*ABS\* 0000000000000004 g1
+
+
+
+Disassembly of section .text:
+
+0000000000000000 <f1>:
+ 0: 67bdfff0 daddiu sp,sp,-16
+ 4: ffbf0008 sd ra,8\(sp\)
+ 8: ffb00000 sd s0,0\(sp\)
+ c: 24100000 li s0,0
+
+0000000000000010 <L0\^A>:
+ 10: 04110001 bal 18 <L0\^A\+0x8>
+ 14: 3c190000 lui t9,0x0
+ 18: 033fc82d daddu t9,t9,ra
+ 1c: df3900a8 ld t9,168\(t9\)
+ 20: 0320f809 jalr t9
+ 24: 00000000 nop
+ 28: 02028021 addu s0,s0,v0
+ 2c: ef3f0000 aluipc t9,0x0
+ 30: df3900d0 ld t9,208\(t9\)
+ 34: 0320f809 jalr t9
+ 38: 00000000 nop
+ 3c: 02028021 addu s0,s0,v0
+
+0000000000000040 <L0\^A>:
+ 40: 04110001 bal 48 <L0\^A\+0x8>
+ 44: 3c020000 lui v0,0x0
+ 48: 005f102d daddu v0,v0,ra
+ 4c: 8c420090 lw v0,144\(v0\)
+ 50: 00501021 addu v0,v0,s0
+ 54: ec7f0000 aluipc v1,0x0
+ 58: 8c6300c8 lw v1,200\(v1\)
+ 5c: 00431021 addu v0,v0,v1
+ 60: dfb00000 ld s0,0\(sp\)
+ 64: dfbf0008 ld ra,8\(sp\)
+ 68: 24420001 addiu v0,v0,1
+ 6c: 03e00009 jr ra
+ 70: 67bd0010 daddiu sp,sp,16
+ ...
+
+Disassembly of section .MIPS.stubs:
+
+0000000000000080 <_MIPS_STUBS_>:
+ 80: df998010 ld t9,-32752\(gp\)
+ 84: 03e07825 move t3,ra
+ 88: 0320f809 jalr t9
+ 8c: 64180004 daddiu t8,zero,4
+ 90: df998010 ld t9,-32752\(gp\)
+ 94: 03e07825 move t3,ra
+ 98: 0320f809 jalr t9
+ 9c: 64180002 daddiu t8,zero,2
+ ...
+
+Disassembly of section .got:
+
+00000000000000b0 <.got>:
+ ...
+ bc: 80000000 lb zero,0\(zero\)
+ c0: 00000090 .word 0x90
+ c4: 00000000 nop
+ c8: 00000004 sllv zero,zero,zero
+ cc: 00000000 nop
+ d0: 00000080 sll zero,zero,0x2
+ ...
+#...
diff --git a/ld/testsuite/ld-mips-elf/gotpc-n64.gd b/ld/testsuite/ld-mips-elf/gotpc-n64.gd
new file mode 100644
index 00000000000..c08cca49ba4
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/gotpc-n64.gd
@@ -0,0 +1,15 @@
+
+Primary GOT:
+ Canonical gp value: 00000000000080a0
+
+ Reserved entries:
+ Address Access Initial Purpose
+ 00000000000000b0 -32752\(gp\) 0000000000000000 Lazy resolver
+ 00000000000000b8 -32744\(gp\) 8000000000000000 Module pointer \(GNU extension\)
+
+ Global entries:
+ Address Access Initial Sym.Val. Type Ndx Name
+ 00000000000000c0 -32736\(gp\) 0000000000000090 0000000000000090 FUNC UND c1
+ 00000000000000c8 -32728\(gp\) 0000000000000004 0000000000000004 OBJECT ABS g2
+ 00000000000000d0 -32720\(gp\) 0000000000000080 0000000000000080 FUNC UND c2
+ 00000000000000d8 -32712\(gp\) 0000000000000000 0000000000000000 OBJECT ABS g1
diff --git a/ld/testsuite/ld-mips-elf/gotpc-n64.s b/ld/testsuite/ld-mips-elf/gotpc-n64.s
new file mode 100644
index 00000000000..47dbd40af2b
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/gotpc-n64.s
@@ -0,0 +1,46 @@
+ .text
+ .globl f1
+ .set nomips16
+ .set nomicromips
+ .ent f1
+ .type f1, @function
+f1:
+ .set noreorder
+ .set nomacro
+ daddiu $sp,$sp,-16
+ sd $31,8($sp)
+ sd $16,0($sp)
+ li $16,0
+
+ bal . + 8
+ lui $25,%gotpc_call_hi(c1)
+ daddu $25,$25,$31
+ ld $25,%gotpc_call_lo(c1)($25)
+ jalr $25
+ nop
+ addu $16,$16,$2
+ aluipc $25,%gotpc_call_ahi(c2)
+ ld $25,%gotpc_call_alo(c2)($25)
+ jalr $25
+ nop
+ addu $16,$16,$2
+
+ bal . + 8
+ lui $2,%gotpc_hi(g1)
+ daddu $2,$2,$31
+ lw $2,%gotpc_lo(g1)($2)
+ addu $2,$2,$16
+ aluipc $3,%gotpc_ahi(g2)
+ lw $3,%gotpc_alo(g2)($3)
+ addu $2,$2,$3
+
+ ld $16,0($sp)
+ ld $31,8($sp)
+ addiu $2,$2,1
+ jr $31
+ daddiu $sp,$sp,16
+
+ .set macro
+ .set reorder
+ .end f1
+ .size f1, .-f1
diff --git a/ld/testsuite/ld-mips-elf/gotpc-o32.dd b/ld/testsuite/ld-mips-elf/gotpc-o32.dd
new file mode 100644
index 00000000000..1c77b059ef6
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/gotpc-o32.dd
@@ -0,0 +1,71 @@
+
+.*: +file format .*mips.*
+
+DYNAMIC SYMBOL TABLE:
+00000000 g DF .text 00000070 f1
+00000080 DF \*UND\* 00000000 c1
+00000004 g DO \*ABS\* 00000004 g2
+00000070 DF \*UND\* 00000000 c2
+00000000 g DO \*ABS\* 00000004 g1
+
+
+
+Disassembly of section .text:
+
+00000000 <f1>:
+ 0: 27bdffe0 addiu sp,sp,-32
+ 4: afbf001c sw ra,28\(sp\)
+ 8: afb00018 sw s0,24\(sp\)
+ c: 24100000 li s0,0
+
+00000010 <L0\^A>:
+ 10: 04110001 bal 18 <L0\^A\+0x8>
+ 14: 3c190000 lui t9,0x0
+ 18: 033fc821 addu t9,t9,ra
+ 1c: 8f390090 lw t9,144\(t9\)
+ 20: 0320f809 jalr t9
+ 24: 00000000 nop
+ 28: 02028021 addu s0,s0,v0
+ 2c: ef3f0000 aluipc t9,0x0
+ 30: 8f3900b0 lw t9,176\(t9\)
+ 34: 0320f809 jalr t9
+ 38: 00000000 nop
+ 3c: 02028021 addu s0,s0,v0
+
+00000040 <L0\^A>:
+ 40: 04110001 bal 48 <L0\^A\+0x8>
+ 44: 3c020000 lui v0,0x0
+ 48: 005f1021 addu v0,v0,ra
+ 4c: 8c42006c lw v0,108\(v0\)
+ 50: 00501021 addu v0,v0,s0
+ 54: ec7f0000 aluipc v1,0x0
+ 58: 8c6300ac lw v1,172\(v1\)
+ 5c: 00431021 addu v0,v0,v1
+ 60: 8fb00018 lw s0,24\(sp\)
+ 64: 8fbf001c lw ra,28\(sp\)
+ 68: 03e00009 jr ra
+ 6c: 27bd0020 addiu sp,sp,32
+
+Disassembly of section .MIPS.stubs:
+
+00000070 <_MIPS_STUBS_>:
+ 70: 8f998010 lw t9,-32752\(gp\)
+ 74: 03e07825 move t7,ra
+ 78: 0320f809 jalr t9
+ 7c: 24180004 li t8,4
+ 80: 8f998010 lw t9,-32752\(gp\)
+ 84: 03e07825 move t7,ra
+ 88: 0320f809 jalr t9
+ 8c: 24180002 li t8,2
+ ...
+
+Disassembly of section .got:
+
+000000a0 <.got>:
+ a0: 00000000 nop
+ a4: 80000000 lb zero,0\(zero\)
+ a8: 00000080 sll zero,zero,0x2
+ ac: 00000004 sllv zero,zero,zero
+ b0: 00000070 tge zero,zero,0x1
+ b4: 00000000 nop
+#...
diff --git a/ld/testsuite/ld-mips-elf/gotpc-o32.gd b/ld/testsuite/ld-mips-elf/gotpc-o32.gd
new file mode 100644
index 00000000000..7a479237a22
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/gotpc-o32.gd
@@ -0,0 +1,15 @@
+
+Primary GOT:
+ Canonical gp value: 00008090
+
+ Reserved entries:
+ Address Access Initial Purpose
+ 000000a0 -32752\(gp\) 00000000 Lazy resolver
+ 000000a4 -32748\(gp\) 80000000 Module pointer \(GNU extension\)
+
+ Global entries:
+ Address Access Initial Sym.Val. Type Ndx Name
+ 000000a8 -32744\(gp\) 00000080 00000080 FUNC UND c1
+ 000000ac -32740\(gp\) 00000004 00000004 OBJECT ABS g2
+ 000000b0 -32736\(gp\) 00000070 00000070 FUNC UND c2
+ 000000b4 -32732\(gp\) 00000000 00000000 OBJECT ABS g1
diff --git a/ld/testsuite/ld-mips-elf/gotpc-o32.s b/ld/testsuite/ld-mips-elf/gotpc-o32.s
new file mode 100644
index 00000000000..3ac3b650aa1
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/gotpc-o32.s
@@ -0,0 +1,45 @@
+ .text
+ .globl f1
+ .set nomips16
+ .set nomicromips
+ .ent f1
+ .type f1, @function
+f1:
+ .set noreorder
+ .set nomacro
+ addiu $sp,$sp,-32
+ sw $31,28($sp)
+ sw $16,24($sp)
+ li $16,0
+
+ bal . + 8
+ lui $25,%gotpc_call_hi(c1)
+ addu $25,$25,$31
+ lw $25,%gotpc_call_lo(c1)($25)
+ jalr $25
+ nop
+ addu $16,$16,$2
+ aluipc $25,%gotpc_call_ahi(c2)
+ lw $25,%gotpc_call_alo(c2)($25)
+ jalr $25
+ nop
+ addu $16,$16,$2
+
+ bal . + 8
+ lui $2,%gotpc_hi(g1)
+ addu $2,$2,$31
+ lw $2,%gotpc_lo(g1)($2)
+ addu $2,$2,$16
+ aluipc $3,%gotpc_ahi(g2)
+ lw $3,%gotpc_alo(g2)($3)
+ addu $2,$2,$3
+
+ lw $16,24($sp)
+ lw $31,28($sp)
+ jr $31
+ addiu $sp,$sp,32
+
+ .set macro
+ .set reorder
+ .end f1
+ .size f1, .-f1
diff --git a/ld/testsuite/ld-mips-elf/gotpc.ld b/ld/testsuite/ld-mips-elf/gotpc.ld
new file mode 100644
index 00000000000..3dadc7e6d4d
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/gotpc.ld
@@ -0,0 +1,17 @@
+ENTRY (foo);
+SECTIONS
+{
+ .text : { *(.text) }
+ .MIPS.stubs : { *(.MIPS.stubs) }
+ HIDDEN (_gp = ALIGN(16) + 0x7ff0);
+ .got : { *(.got) }
+ .dynamic : { *(.dynamic) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .pdr : { *(.pdr) }
+ .shstrtab : { *(.shstrtab) }
+ .symtab : { *(.symtab) }
+ .strtab : { *(.strtab) }
+ /DISCARD/ : { *(*) }
+}
diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp
index 818238d0d58..995abc07997 100644
--- a/ld/testsuite/ld-mips-elf/mips-elf.exp
+++ b/ld/testsuite/ld-mips-elf/mips-elf.exp
@@ -719,6 +719,29 @@ if { $linux_gnu } {
"readelf --relocs gp-hidden${suff64}.rd" \
"readelf --syms gp-hidden.sd"] \
"gp-hidden-${abi}"]]
+
+ set gotpc_asflags [regsub -- {-march=[^[:blank:]]*} $abi_asflags($abi) {}]
+ run_ld_link_tests [list \
+ [list \
+ "MIPS R_MIPS_GOTPC support (Prepare, $abi)" \
+ "$abi_ldflags($abi) -shared -T gotpc.ld" \
+ "" \
+ "$gotpc_asflags -mips64r6 -KPIC" \
+ [list gotpc-callee.s] \
+ "" \
+ "libgotpc-callee-${abi}.so"]]
+ run_ld_link_tests [list \
+ [list \
+ "MIPS R_MIPS_GOTPC support ($abi)" \
+ "$abi_ldflags($abi) -shared -T gotpc.ld \
+ -Ltmpdir -lgotpc-callee-${abi}" \
+ "" \
+ "$gotpc_asflags -mips64r6 -KPIC" \
+ [list gotpc-${abi}.s] \
+ [list \
+ "objdump -DTC gotpc-${abi}.dd" \
+ "readelf -A gotpc-${abi}.gd"] \
+ "gotpc-${abi}.so"]]
}
}
--
2.39.3 (Apple Git-146)
More information about the Binutils
mailing list