2016-11-02 00:45:57 +08:00
|
|
|
# This shell script emits a C file. -*- C -*-
|
2021-01-01 06:58:58 +08:00
|
|
|
# Copyright (C) 2004-2021 Free Software Foundation, Inc.
|
2016-11-02 00:45:57 +08:00
|
|
|
#
|
|
|
|
# This file is part of the GNU Binutils.
|
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation; either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program; if not, write to the Free Software
|
|
|
|
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
|
|
|
# MA 02110-1301, USA.
|
|
|
|
|
|
|
|
fragment <<EOF
|
|
|
|
|
|
|
|
#include "ldmain.h"
|
|
|
|
#include "ldctor.h"
|
|
|
|
#include "elf/riscv.h"
|
|
|
|
#include "elfxx-riscv.h"
|
|
|
|
|
|
|
|
static void
|
|
|
|
riscv_elf_before_allocation (void)
|
|
|
|
{
|
|
|
|
gld${EMULATION_NAME}_before_allocation ();
|
|
|
|
|
|
|
|
if (link_info.discard == discard_sec_merge)
|
|
|
|
link_info.discard = discard_l;
|
|
|
|
|
2018-03-11 21:25:30 +08:00
|
|
|
if (!bfd_link_relocatable (&link_info))
|
|
|
|
{
|
|
|
|
/* We always need at least some relaxation to handle code alignment. */
|
|
|
|
if (RELAXATION_DISABLED_BY_USER)
|
|
|
|
TARGET_ENABLE_RELAXATION;
|
|
|
|
else
|
|
|
|
ENABLE_RELAXATION;
|
|
|
|
}
|
2016-11-02 00:45:57 +08:00
|
|
|
|
RISC-V: Relax PCREL to GPREL while doing other relaxations is dangerous.
I get the feedback recently that enable linker relaxations may fail to
build some program. Consider the following case,
.text
foo:
addi a0, a0, %pcrel_lo(.L2)
call foo
.L1: auipc a1, %pcrel_hi(data_g)
addi a1, a1, %pcrel_lo(.L1)
lui a2, %hi(data_g)
addi a2, a2, %lo(data_g)
lui a3, %tprel_hi(data_t)
add a3, a3, tp, %tprel_add(data_t)
addi a3, a3, %tprel_lo(data_t)
.L2: auipc a0, %pcrel_hi(data_g)
.data
.word 0x0
.global data_g
data_g: .word 0x1
.section .tbss
data_t: .word 0x0
The current ld reports `dangerous relocation error` when doing the
pcgp relaxation,
test.o: in function `foo':
(.text+0x0): dangerous relocation: %pcrel_lo missing matching %pcrel_hi
The .L2 auipc should not be removed since it is behind the corresponding
addi, so we record the information in the pcgp_relocs table to avoid
removing the auipc later. But current ld still remove it since we do not
update the pcgp_relocs table while doing other relaxations. I have two
solutions to fix the problem,
1. Update the pcgp_relocs table once we actually delete the code.
2. Add new relax pass to do the pcgp relaxations
At first I tried to do the first solution, and we need to update at
least three information - hi_sec_off of riscv_pcgp_lo_reloc, hi_sec_off
and hi_addr (symbol value) of riscv_pcgp_hi_reloc. Update the hi_sec_off
is simple, but it is more complicate to update the symbol value, since we
almost have to do parts the same works of _bfd_riscv_relax_call again in
the riscv_relax_delete_bytes to get the correct symbol value.
Compared with the first solution, the second one is more intuitive and
simple. We add a new relax pass to do the pcgp relaxations later, so
we will get all the information correctly in the _bfd_riscv_relax_call,
including the symbol value, without changing so much code. I do not see
any penalty by adding a new relax pass for now, so it should be fine
to delay the pcgp relaxations.
Besides, I have pass all riscv-gnu-toolchain regressions for this patch.
bfd/
* elfnn-riscv.c (_bfd_riscv_relax_section): Add a new relax pass
to do the pcgp relaxation later, after the lui and call relaxations,
but before the delete and alignment relaxations.
ld/
* emultempl/riscvelf.em (riscv_elf_before_allocation): Change
link_info.relax_pass from 3 to 4.
* testsuite/ld-riscv-elf/pcgp-relax.d: New testcase.
* testsuite/ld-riscv-elf/pcgp-relax.s: Likewise.
* testsuite/ld-riscv-elf/ld-riscv-elf.exp: Updated.
2020-11-18 11:39:52 +08:00
|
|
|
link_info.relax_pass = 4;
|
2016-11-02 00:45:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gld${EMULATION_NAME}_after_allocation (void)
|
|
|
|
{
|
|
|
|
int need_layout = 0;
|
|
|
|
|
|
|
|
/* Don't attempt to discard unused .eh_frame sections until the final link,
|
|
|
|
as we can't reliably tell if they're used until after relaxation. */
|
|
|
|
if (!bfd_link_relocatable (&link_info))
|
|
|
|
{
|
|
|
|
need_layout = bfd_elf_discard_info (link_info.output_bfd, &link_info);
|
|
|
|
if (need_layout < 0)
|
|
|
|
{
|
2017-10-11 12:18:45 +08:00
|
|
|
einfo (_("%X%P: .eh_frame/.stab edit: %E\n"));
|
2016-11-02 00:45:57 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
RISC-V: Improve multiple relax passes problem.
According to the commit abd20cb637008da9d32018b4b03973e119388a0a, an
intersting thing is that - the more relax passes, the more chances of
relaxations are reduced [1]. Originally, we set the boolean `again`
to TRUE once the code is actually deleted, and then we run the relaxations
repeatedly if `again` is still TRUE. But `again` only works for the
relax pass itself, and won't affect others. That is - we can not use
`again` to re-run the relax pass when we already enter into the following
passes (can not run the relax passes backwards). Besides, we must seperate
the PCREL relaxations into two relax passes for some reasons [2], it make
us lose some relax opportunities.
This patch try to fix the problem, and the basic idea was come from Jim
Wilson - we use a new boolean, restart_relax, to determine if we need to
run the whole relax passes again from 0 to 2. Once we have deleted the
code between relax pass 0 to 2, the restart_relax will be set to TRUE,
we should run the whole relaxations again to give them more chances to
shorten the code. We will only enter into the relax pass 3 when the
restart_relax is FALSE, since we can't relax anything else once we start
to handle the alignments.
I have passed the gcc/binutils regressions by riscv-gnu-toolchain, and
looks fine for now.
[1] https://sourceware.org/pipermail/binutils/2020-November/114223.html
[2] https://sourceware.org/pipermail/binutils/2020-November/114235.html
bfd/
* elfnn-riscv.c (riscv_elf_link_hash_table): New boolean restart_relax,
used to check if we need to run the whole relaxations from relax pass 0
to 2 again.
(riscv_elf_link_hash_table_create): Init restart_relax to FALSE.
(_bfd_riscv_relax_align): Remove obsolete sec_flg0 set.
(_bfd_riscv_relax_delete): Set again to TRUE if we do delete the code.
(bfd_elfNN_riscv_restart_relax_sections): New function. Called by
after_allocation to check if we need to run the whole relaxations again.
(_bfd_riscv_relax_section): We will only enter into the relax pass 3 when
the restart_relax is FALSE; At last set restart_relax to TRUE if again is
TRUE, too.
* elfxx-riscv.h (bfd_elf32_riscv_restart_relax_sections): Declaration.
(bfd_elf64_riscv_restart_relax_sections): Likewise.
ld/
* emultempl/riscvelf.em (after_allocation): Run ldelf_map_segments many
times if riscv_restart_relax_sections returns TRUE.
* testsuite/ld-riscv-elf/restart-relax.d: New testcase. Before applying
this patch, the call won't be relaxed to jal; But now we have more chances
to do relaxations.
* testsuite/ld-riscv-elf/restart-relax.s: Likewise.
* testsuite/ld-riscv-elf/ld-riscv-elf.exp: Updated.
2020-12-18 10:59:41 +08:00
|
|
|
do
|
|
|
|
{
|
|
|
|
ldelf_map_segments (need_layout);
|
|
|
|
}
|
|
|
|
while (bfd_elf${ELFSIZE}_riscv_restart_relax_sections (&link_info));
|
2016-11-02 00:45:57 +08:00
|
|
|
}
|
|
|
|
|
2018-03-07 04:01:04 +08:00
|
|
|
/* This is a convenient point to tell BFD about target specific flags.
|
|
|
|
After the output has been created, but before inputs are read. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
riscv_create_output_section_statements (void)
|
|
|
|
{
|
|
|
|
/* See PR 22920 for an example of why this is necessary. */
|
|
|
|
if (strstr (bfd_get_target (link_info.output_bfd), "riscv") == NULL)
|
|
|
|
{
|
|
|
|
/* The RISC-V backend needs special fields in the output hash structure.
|
|
|
|
These will only be created if the output format is a RISC-V format,
|
|
|
|
hence we do not support linking and changing output formats at the
|
|
|
|
same time. Use a link followed by objcopy to change output formats. */
|
|
|
|
einfo (_("%F%P: error: cannot change output format"
|
|
|
|
" whilst linking %s binaries\n"), "RISC-V");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-02 00:45:57 +08:00
|
|
|
EOF
|
|
|
|
|
|
|
|
LDEMUL_BEFORE_ALLOCATION=riscv_elf_before_allocation
|
|
|
|
LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
|
2018-03-07 04:01:04 +08:00
|
|
|
LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=riscv_create_output_section_statements
|