[v4] MIPS: Support PCREL GOT access
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_binutils_build--master-arm |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_binutils_check--master-arm |
success
|
Testing passed
|
Commit Message
Current if we need to access a GOT entry, we use the
got_base + offset. Thus we have GOT and XGOT.
From MIPSr6, we have PCREL instructions like ALUIPC,
so we have no need to use got_base now.
For pre-R6, we can use BAL to get the the value of PC.
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 asm notes 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 defination.
* 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
Comments
On Sat, Mar 16, 2024 at 1:51 AM YunQiang Su <syq@gcc.gnu.org> wrote:
>
> Current if we need to access a GOT entry, we use the
> got_base + offset. Thus we have GOT and XGOT.
> From MIPSr6, we have PCREL instructions like ALUIPC,
> so we have no need to use got_base now.
> For pre-R6, we can use BAL to get the the value of PC.
Currently loading a GOT entry requires loading the GOT base address
first, then adding an offset.
Therefore, (elaborate the reason) we need both GOT and XGOT.
MIPSr6 introduced PC-relative instructions like ..., which allow us to
use a pair of .. and .. 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 asm notes 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).
GCC's mips port names assembler relocation operators
(gas/config/tc-mips.c names them `mips_percent_op`).
Other ports seem to prefer "modifiers" (assembler modifiers,
expression modifiers).
> 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 defination.
typo
> * 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 29602e054da..e8bb1195c27 100644
> --- a/bfd/bfd-in2.h
> +++ b/bfd/bfd-in2.h
> @@ -3658,6 +3658,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 63d7334dd52..7edcc30d331 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 489a461bb0b..8ebaa859475 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 7e672200006..f6a6560b4c2 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 89dd34e798b..c4d6787357e 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
> }
> +
> +/**/
> +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;
> @@ -8282,6 +8359,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
> @@ -8742,6 +8827,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:
> @@ -8751,6 +8840,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:
> @@ -8788,6 +8879,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:
> @@ -8958,6 +9051,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)
> @@ -8983,6 +9080,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 f15b5f27db8..c10ee485abf 100644
> --- a/bfd/libbfd.h
> +++ b/bfd/libbfd.h
> @@ -1273,6 +1273,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 686d5500e02..23e95fe0c45 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 50af78d1430..550f373efdc 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.2
>
Fangrui Song <i@maskray.me> 于2024年4月3日周三 12:11写道:
>
> On Sat, Mar 16, 2024 at 1:51 AM YunQiang Su <syq@gcc.gnu.org> wrote:
> >
> > Current if we need to access a GOT entry, we use the
> > got_base + offset. Thus we have GOT and XGOT.
> > From MIPSr6, we have PCREL instructions like ALUIPC,
> > so we have no need to use got_base now.
> > For pre-R6, we can use BAL to get the the value of PC.
>
> Currently loading a GOT entry requires loading the GOT base address
> first, then adding an offset.
> Therefore, (elaborate the reason) we need both GOT and XGOT.
> MIPSr6 introduced PC-relative instructions like ..., which allow us to
> use a pair of .. and .. to materialize the GOT entry address.
>
Thanks.
Currently loading a GOT entry requires loading the GOT base address
first, then adding an offset. Therefore, (elaborate the reason)
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 asm notes 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).
>
> GCC's mips port names assembler relocation operators
> (gas/config/tc-mips.c names them `mips_percent_op`).
> Other ports seem to prefer "modifiers" (assembler modifiers,
> expression modifiers).
>
These percent_op can be used for them
> > * bfd-in2.h: Add new MIPS GOTPC BFD_RELOC defination.
>
> typo
>
Thanks.
Ping again.
@@ -3658,6 +3658,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,
@@ -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[] =
@@ -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[] =
@@ -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[] =
@@ -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
}
+
+/**/
+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;
@@ -8282,6 +8359,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
@@ -8742,6 +8827,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:
@@ -8751,6 +8840,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:
@@ -8788,6 +8879,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:
@@ -8958,6 +9051,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)
@@ -8983,6 +9080,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:
@@ -1273,6 +1273,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",
@@ -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.
@@ -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,
@@ -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);
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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
@@ -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"
@@ -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)
new file mode 100644
@@ -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
new file mode 100644
@@ -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
+#...
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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
+ ...
+#...
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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
+#...
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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/ : { *(*) }
+}
@@ -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"]]
}
}