From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-oi1-f169.google.com (mail-oi1-f169.google.com [209.85.167.169]) by sourceware.org (Postfix) with ESMTPS id D3593385840D for ; Wed, 31 Jan 2024 08:32:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D3593385840D 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 D3593385840D Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=209.85.167.169 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706689987; cv=none; b=TAV26avsCcFWlXJ8rDQXY8ydj7t+8nU8soxLFrj5pfbtoUN6SPbKlu/xRCFSl3pe32ncgNnkO35Pc9obyq1Hdi1xiStjMj4C1EQFKHZxQP+1jkP6y44knNcUC7Z3AOGIeIMe4fRz4PUWEq94Lf7thds2UD92layEbdNk9HPeeVc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706689987; c=relaxed/simple; bh=8on5FnsyAwRq60Tu38Dz/+CtmhzazGrZAtOzKHxb0Og=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=SKRucR09no7SRaLqNZpuUCKoqiZpg+NJNce9LNDTTyKfUyjT/YKsgnTdW20zNrlTNYXQIdr1BRfvkQ9t0F1SNOAgfjD7loIAOQTn0NpYBG31lGojXS8zUKUGnmcMSlAQ7qcCEKv8y5h65m6cJJD7HpwoT9jWJ+pZuzEA4xu4KJU= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-oi1-f169.google.com with SMTP id 5614622812f47-3bbb4806f67so3584131b6e.3 for ; Wed, 31 Jan 2024 00:32:57 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706689977; x=1707294777; 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=hMyGN3qvmXoSokfzbBYHRkBEQKOf7BlW85v9ELKO85M=; b=huXTF1SlIAX/AaHzbtq+qZom9JQ63ar9vXWxr6FOOgRquCbUtuY7wL/rossyXd3IcO ICoLjPC/WVMKLyZzR/n+h8kLqRbxlucSNWXTss8ndteIzP/J6ilZB0gDHhPGLUDPEb+i 6ck/v/cZqEoq/rw+8fM/4TqBW6VDTi7dDCxIohtrylhdrlTDgpvLwnByb1af2RVojaQg UHsUCpqts+VIUtsSf3WDaswOWrxhjblZ8+Kvq/fs3kTwbUMBTJmBuSZqJnZ8lczgvKoS uAGyJXS50TS3cQI7qFPp9n+36HMNhYTG4fWyE1KcRYvhkf/13iTAusSokLaC97ZCROek 6eUw== X-Gm-Message-State: AOJu0Yzy8cwVdsZSPaoDUaYFGyuu/zf9OjZxgz2te4iAZorBP2u8rQ/T RYlWoHFX8w5d7IdoF+qVkqYqShbdFbrnsm8p1D8NJLUYDhWuRZYi4IBxmywrA9U= X-Google-Smtp-Source: AGHT+IHRH2o90h1Z1Vx6ljIiD+xnFWVbmBa5IxD54m/p8dmmdFT+M1eSaTf+e/FaSaIEJ0L7mkBBLg== X-Received: by 2002:a05:6808:e8d:b0:3bc:3d7a:48c1 with SMTP id k13-20020a0568080e8d00b003bc3d7a48c1mr1042813oil.54.1706689976976; Wed, 31 Jan 2024 00:32:56 -0800 (PST) Received: from localhost.localdomain ([149.248.38.156]) by smtp.gmail.com with ESMTPSA id z23-20020a62d117000000b006dddad7674asm9626429pfg.136.2024.01.31.00.32.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 31 Jan 2024 00:32:56 -0800 (PST) From: YunQiang Su To: nickc@redhat.com Cc: binutils@sourceware.org, macro@orcam.me.uk Subject: [PATCH] MIPS: support PCREL GOT access Date: Wed, 31 Jan 2024 16:32:44 +0800 Message-Id: <20240131083244.718579-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.8 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_H2,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. In this patch, we add 4 new relocs: R_MIPS_GOTPC_HI16, R_MIPS_GOTPC_LO16, R_MIPS_GOTPC_CALL_HI16, R_MIPS_GOTPC_CALL_LO16, and the asm notes for them: %gotpc_hi(sym), %gotpc_lo(sym) %gotpc_call_hi(sym), %gotpc_call_lo(sym). And we add 3 new BFD_RELOCS for function calling: BFD_RELOC_LO16_GOTOFF_CALL, BFD_RELOC_HI16_GOTOFF_CALL, BFD_RELOC_HI16_S_GOTOFF_CALL. We use BFD_RELOC_ values like: BFD_RELOC_HI16_S_GOTOFF -> R_MIPS_GOTPC_HI16 BFD_RELOC_LO16_GOTOFF -> R_MIPS_GOTPC_LO16 BFD_RELOC_HI16_S_GOTOFF_CALL -> R_MIPS_GOTPC_CALL_HI16 BFD_RELOC_LO16_GOTOFF_CALL -> R_MIPS_GOTPC_CALL_LO16. Note: the relocation is different for r6 and pre-r6. For r6, we use aluipc, which will unset the lower 16bit of result. The ASM examples is like this: R6: aluipc $2,%gotpc_hi(sym) lw $2,%gotpc_lo(sym)($2) Pre-R6: bal . + 8 lui $2,%gotpc_hi(sym) addiu $2,$2,$ra lw $2,%gotpc_lo(sym)($2) --- bfd/bfd-in2.h | 3 ++ bfd/elf32-mips.c | 62 ++++++++++++++++++++++++++++++++++- bfd/elf64-mips.c | 62 ++++++++++++++++++++++++++++++++++- bfd/elfn32-mips.c | 62 ++++++++++++++++++++++++++++++++++- bfd/elfxx-mips.c | 78 ++++++++++++++++++++++++++++++++++++++++++-- bfd/libbfd.h | 3 ++ bfd/reloc.c | 6 ++++ elfcpp/mips.h | 2 ++ gas/config/tc-mips.c | 29 +++++++++++++++- include/elf/mips.h | 6 +++- 10 files changed, 305 insertions(+), 8 deletions(-) diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 581d8fe0b3e..a7d24d216f4 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -3313,6 +3313,9 @@ enum bfd_reloc_code_real BFD_RELOC_HI16_PLTOFF, BFD_RELOC_HI16_S_PLTOFF, BFD_RELOC_8_PLTOFF, + BFD_RELOC_LO16_GOTOFF_CALL, + BFD_RELOC_HI16_GOTOFF_CALL, + BFD_RELOC_HI16_S_GOTOFF_CALL, /* Size relocations. */ BFD_RELOC_SIZE32, diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index 63d7334dd52..e2187d442a4 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -809,6 +809,62 @@ 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 */ }; /* The reloc used for BFD_RELOC_CTOR when doing a 64 bit link. This @@ -2030,7 +2086,11 @@ 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_HI16_S_GOTOFF_CALL, R_MIPS_GOTPC_CALL_HI16 }, + { BFD_RELOC_LO16_GOTOFF_CALL, R_MIPS_GOTPC_CALL_LO16 } }; static const struct elf_reloc_map mips16_reloc_map[] = diff --git a/bfd/elf64-mips.c b/bfd/elf64-mips.c index 489a461bb0b..5ab49b22ce5 100644 --- a/bfd/elf64-mips.c +++ b/bfd/elf64-mips.c @@ -889,6 +889,62 @@ 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 */ + }; /* The relocation table used for SHT_RELA sections. */ @@ -3743,7 +3799,11 @@ 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_HI16_S_GOTOFF_CALL, R_MIPS_GOTPC_CALL_HI16 }, + { BFD_RELOC_LO16_GOTOFF_CALL, R_MIPS_GOTPC_CALL_LO16 } }; static const struct elf_reloc_map mips16_reloc_map[] = diff --git a/bfd/elfn32-mips.c b/bfd/elfn32-mips.c index 7e672200006..79d5cb2c840 100644 --- a/bfd/elfn32-mips.c +++ b/bfd/elfn32-mips.c @@ -868,6 +868,62 @@ 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 */ + }; /* The relocation table used for SHT_RELA sections. */ @@ -3577,7 +3633,11 @@ 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_HI16_S_GOTOFF_CALL, R_MIPS_GOTPC_CALL_HI16 }, + { BFD_RELOC_LO16_GOTOFF_CALL, R_MIPS_GOTPC_CALL_LO16 } }; static const struct elf_reloc_map mips16_reloc_map[] = diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 69dd71419ff..0f3279d7b63 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -2267,19 +2267,25 @@ 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_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_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_MICROMIPS_CALL_LO16; } static inline bool @@ -5241,6 +5247,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 +5909,8 @@ 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_MICROMIPS_CALL16: case R_MICROMIPS_GOT16: case R_MICROMIPS_GOT_PAGE: @@ -5905,6 +5928,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 +5977,10 @@ 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_MICROMIPS_CALL16: case R_MICROMIPS_GOT16: case R_MICROMIPS_GOT_DISP: @@ -6413,6 +6442,37 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, value &= howto->dst_mask; break; + /* Pre-R6, we use + bal . + 8 + lui $2,%gotpc_hi(sym) + addu $2,$2,$ra + lw $2,%gotpc_lo(sym) + In this case, the LO should +=4, and HI should -=4. + + For R6+, we use + aluipc $2,%gotpc_hi(sym) + lw $2,%gotpc_lo(sym)($2) + 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: + if (MIPSR6_P (abfd)) + value = mips_elf_16bit_align (addend + gp - p + g, p, true); + else + 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); + if (MIPSR6_P (abfd)) + value = mips_elf_16bit_align (addend + gp - p + g, p, false); + else + value = addend + gp - p + g + 4; + value &= howto->dst_mask; + break; + case R_MIPS_PCHI16: value = mips_elf_high (symbol + addend - p); value &= howto->dst_mask; @@ -8282,6 +8342,10 @@ 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_PCHI16) lo16_type = R_MIPS_PCLO16; else @@ -8742,6 +8806,8 @@ _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_MIPS16_CALL16: case R_MICROMIPS_CALL16: case R_MICROMIPS_CALL_HI16: @@ -8751,6 +8817,7 @@ _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_GOT_PAGE: case R_MIPS_GOT_DISP: case R_MIPS16_GOT16: @@ -8788,6 +8855,7 @@ _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_GOT_OFST: case R_MIPS_TLS_GOTTPREL: case R_MIPS_TLS_GD: @@ -8958,6 +9026,8 @@ _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_MICROMIPS_CALL_HI16: case R_MICROMIPS_CALL_LO16: if (h != NULL) @@ -8983,6 +9053,8 @@ _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_MICROMIPS_GOT16: case R_MICROMIPS_GOT_HI16: case R_MICROMIPS_GOT_LO16: diff --git a/bfd/libbfd.h b/bfd/libbfd.h index ebd4f24149b..57bcaab2ab4 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1084,6 +1084,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_HI16_PLTOFF", "BFD_RELOC_HI16_S_PLTOFF", "BFD_RELOC_8_PLTOFF", + "BFD_RELOC_LO16_GOTOFF_CALL", + "BFD_RELOC_HI16_GOTOFF_CALL", + "BFD_RELOC_HI16_S_GOTOFF_CALL", "BFD_RELOC_SIZE32", "BFD_RELOC_SIZE64", "BFD_RELOC_68K_GLOB_DAT", diff --git a/bfd/reloc.c b/bfd/reloc.c index e74cbd75e96..6e8f8712b6b 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -1470,6 +1470,12 @@ ENUMX BFD_RELOC_HI16_S_PLTOFF ENUMX BFD_RELOC_8_PLTOFF +ENUMX + BFD_RELOC_LO16_GOTOFF_CALL +ENUMX + BFD_RELOC_HI16_GOTOFF_CALL +ENUMX + BFD_RELOC_HI16_S_GOTOFF_CALL ENUMDOC For ELF. diff --git a/elfcpp/mips.h b/elfcpp/mips.h index e8a8e2458e9..d3c2023f3c5 100644 --- a/elfcpp/mips.h +++ b/elfcpp/mips.h @@ -104,6 +104,8 @@ enum R_MIPS_PC19_S2 = 63, R_MIPS_PCHI16 = 64, R_MIPS_PCLO16 = 65, + R_MIPS_GOTPC_HI16 = 66, + R_MIPS_GOTPC_LO16 = 67, // 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..59a037cb4a3 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -4370,7 +4370,11 @@ limited_pcrel_reloc_p (bfd_reloc_code_real_type reloc) return true; case BFD_RELOC_32_PCREL: + case BFD_RELOC_HI16_S_GOTOFF: + case BFD_RELOC_LO16_GOTOFF: case BFD_RELOC_HI16_S_PCREL: + case BFD_RELOC_LO16_GOTOFF_CALL: + case BFD_RELOC_HI16_S_GOTOFF_CALL: case BFD_RELOC_LO16_PCREL: return HAVE_64BIT_ADDRESSES; @@ -7432,6 +7436,7 @@ 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_MICROMIPS_HI16_S: case BFD_RELOC_MIPS16_HI16_S: *result = ((operand + 0x8000) >> 16) & 0xffff; @@ -7445,6 +7450,8 @@ 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_LO16_GOTOFF_CALL: case BFD_RELOC_MICROMIPS_LO16: case BFD_RELOC_MIPS16_LO16: *result = operand & 0xffff; @@ -14583,7 +14590,11 @@ 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_HI16_S_GOTOFF_CALL}, + {"%gotpc_call_lo", BFD_RELOC_LO16_GOTOFF_CALL} }; static const struct percent_op_match mips16_percent_op[] = @@ -15541,7 +15552,11 @@ 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_HI16_S_PCREL + || fixp->fx_r_type == BFD_RELOC_LO16_GOTOFF_CALL + || fixp->fx_r_type == BFD_RELOC_HI16_S_GOTOFF_CALL || fixp->fx_r_type == BFD_RELOC_LO16_PCREL)) return 1; @@ -15822,6 +15837,10 @@ 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_HI16_S_GOTOFF_CALL: + case BFD_RELOC_LO16_GOTOFF_CALL: break; case BFD_RELOC_32: @@ -15965,6 +15984,10 @@ 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_HI16_S_GOTOFF_CALL: + case BFD_RELOC_LO16_GOTOFF_CALL: case BFD_RELOC_HI16_S_PCREL: case BFD_RELOC_LO16_PCREL: case BFD_RELOC_MIPS16_GPREL: @@ -18386,7 +18409,11 @@ 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_HI16_S_PCREL + || fixp->fx_r_type == BFD_RELOC_LO16_GOTOFF_CALL + || fixp->fx_r_type == BFD_RELOC_HI16_S_GOTOFF_CALL || fixp->fx_r_type == BFD_RELOC_LO16_PCREL); /* At this point, fx_addnumber is "symbol offset - pcrel address". diff --git a/include/elf/mips.h b/include/elf/mips.h index 686d5500e02..d9a9047b09c 100644 --- a/include/elf/mips.h +++ b/include/elf/mips.h @@ -98,7 +98,11 @@ 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) + FAKE_RELOC (R_MIPS_max, 70) /* These relocs are used for the mips16. */ FAKE_RELOC (R_MIPS16_min, 100) RELOC_NUMBER (R_MIPS16_26, 100) -- 2.39.2