From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pl1-f180.google.com (mail-pl1-f180.google.com [209.85.214.180]) by sourceware.org (Postfix) with ESMTPS id 75E3A3858D33 for ; Fri, 2 Feb 2024 06:39:34 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 75E3A3858D33 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=gcc.gnu.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 75E3A3858D33 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=209.85.214.180 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706855980; cv=none; b=rAXKw+TmFGryXivekVLei+K0S1+PbRxNVGrQkghgONTKU0sRNAJFe755BTT2rNt+LqBjRCISxnuu/6G/A84mYEb5HXduw2M4zHUCwenJBHcgQFvtLm5lHGEWxb4LOC5p6Bz6wM0CCRmP95YZ/qW+lmAhZtqL5O/ePJImWqd8KtM= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706855980; c=relaxed/simple; bh=7nLOPyVO6zrfbDBknxwQJ3p5EJYPOm6Zy+K03OvQW3U=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=eA5IeUb+f3xs+9hLiiKsThPsYC4/8oC08MDnipXSPWs/hOK+eTIfEcAeT8VHONJbEiqyZ3aoB71HooMQKwMyIPg/G2sX70Nh0FoZQISDvLh2dk6xhnseArO/eCZCTt8tnaD4uk0tvA1EKmgFF6ias64f6RC/LKpLt2i8QDOujSk= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pl1-f180.google.com with SMTP id d9443c01a7336-1d780a392fdso14891205ad.3 for ; Thu, 01 Feb 2024 22:39:34 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706855973; x=1707460773; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=lN0LNZS65N5a+97z+wjYRWIZIK9ZHhEaTfew85FJcbU=; b=ScAHpv8briutgrE6bWxTCRNG87fBvq/wIFWHWc8SbWrSLK1HqG9W/KmkpUMbrtP03l 2akYoRsc2bu90reb/Y1n089KL1mGTowW29nosjTI6yNeZu5mktOmISV338N+cymvmDrM kBhLM3NoAEUknaq6HG5Wbve9r7N+ubfW/bCkYfpFsmwdyTBnTnn6BBEttWKlWbDorB8U R5a+fWmE36kRweqzTAnm8k90az/WbshCeSTaeKIBnG+K2Olz7pZzfOb4WxJtUBHGsoCE 6eAaU60COvbWdfHMljxsRnL5eKBf6/VV3fEGVX+Ir0wHnMOsWeWrgMIsvYVP8R8BK271 cIxA== X-Gm-Message-State: AOJu0YwL3wKmDs6/87ktUXt5m2EgP9MyndqkmpPuOzWx4qF1GLqOYWlu RDcR9Q5u6TDlN/KMRyylFxeIhQYCHrhxcRJPbTDQhKvlYER/XFeC X-Google-Smtp-Source: AGHT+IGpHbJgElGBmO7HCswkrP8BEIa/KVFC/N/JnWdwvbi9X74hkcMTLTDwM5EGONVxhdiBotGPaw== X-Received: by 2002:a17:902:d34d:b0:1d9:7121:170e with SMTP id l13-20020a170902d34d00b001d97121170emr734654plk.35.1706855972960; Thu, 01 Feb 2024 22:39:32 -0800 (PST) X-Forwarded-Encrypted: i=0; AJvYcCXnJlij6AzPB7Xf3ppvTnU5aarGhVJ/Sx7l7MKPBuPaYNDMLG7Ts/snGkf0ABDznKPkwrbKAYNiT7U0kCIbA/8+SI3iWHz1W7VQJIB32cFmuJAEaCYG Received: from localhost.localdomain ([149.248.38.156]) by smtp.gmail.com with ESMTPSA id s13-20020a17090330cd00b001d961ebf31bsm872882plc.82.2024.02.01.22.39.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Feb 2024 22:39:32 -0800 (PST) From: YunQiang Su To: nickc@redhat.com Cc: binutils@sourceware.org, macro@orcam.me.uk, xry111@xry111.site Subject: [PATCH] MIPS: Support PCREL GOT access Date: Fri, 2 Feb 2024 14:39:19 +0800 Message-Id: <20240202063919.1414368-1-syq@gcc.gnu.org> X-Mailer: git-send-email 2.39.2 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-10.7 required=5.0 tests=BAYES_00,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,GIT_PATCH_0,HEADER_FROM_DIFFERENT_DOMAINS,KAM_DMARC_STATUS,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: 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. --- 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 +- 21 files changed, 1155 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 diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 581d8fe0b3e..bce2030f9c5 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -3654,6 +3654,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..dc4e56d1f55 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 */ + 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 */ + }; 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..03e17dfda64 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 */ + 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 */ + }; 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 69dd71419ff..c8a9ceb7524 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 @@ -5241,6 +5250,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. */ @@ -5888,6 +5912,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: @@ -5905,6 +5933,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 @@ -5952,6 +5982,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: @@ -6413,6 +6451,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 ebd4f24149b..53604a094f6 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1272,6 +1272,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 e74cbd75e96..85e4081ccd6 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..33adb67107b 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_HI16 = 70, + R_MIPS_GOTPC_LO16 = 71, + R_MIPS_GOTPC_CALL_HI16 = 72, + R_MIPS_GOTPC_CALL_LO16 = 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 43c12de2c8a..1ec2feac072 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[] = @@ -15541,6 +15579,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; @@ -15822,6 +15868,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: @@ -15965,6 +16019,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: @@ -18386,6 +18448,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..4079c8de661 --- /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 (NewABI, 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..b4caff9bbe9 --- /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 (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) -- 2.39.2