BFD: Fix the bug of R_LARCH_AGLIN caused by discard section

To represent the first and third expression of .align, R_LARCH_ALIGN need to
associate with a symbol. We define a local symbol for R_LARCH_AGLIN.
But if the section of the local symbol is discarded, it may result in
a undefined symbol error.

Instead, we use the section name symbols, and this does not need to
add extra symbols.

During partial linking (ld -r), if the symbol associated with a relocation is
STT_SECTION type, the addend of relocation needs to add the section output
offset. We prevent it for R_LARCH_ALIGN.

The elf_backend_data.rela_normal only can set all relocations of a target to
rela_normal. Add a new function is_rela_normal to elf_backend_data, it can
set part of relocations to rela_normal.
This commit is contained in:
mengqinggang 2024-01-24 14:34:26 +08:00 committed by liuzhensong
parent c7a5bea4c6
commit daeda14191
9 changed files with 66 additions and 8 deletions

View file

@ -1721,6 +1721,10 @@ struct elf_backend_data
backend relocate_section routine for relocatable linking. */
unsigned rela_normal : 1;
/* Whether a relocation is rela_normal. Compared with rela_normal,
is_rela_normal can set part of relocations to rela_normal. */
bool (*is_rela_normal) (Elf_Internal_Rela *);
/* Set if DT_REL/DT_RELA/DT_RELSZ/DT_RELASZ should not include PLT
relocations. */
unsigned dtrel_excludes_plt : 1;

View file

@ -11692,7 +11692,10 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
{
rel_hash = PTR_ADD (esdo->rela.hashes, esdo->rela.count);
rela_hash_list = rel_hash;
rela_normal = bed->rela_normal;
if (bed->is_rela_normal != NULL)
rela_normal = bed->is_rela_normal (irela);
else
rela_normal = bed->rela_normal;
}
irela->r_offset = _bfd_elf_section_offset (output_bfd,

View file

@ -5454,6 +5454,21 @@ elf_loongarch64_hash_symbol (struct elf_link_hash_entry *h)
return _bfd_elf_hash_symbol (h);
}
/* If a relocation is rela_normal and the symbol associated with the
relocation is STT_SECTION type, the addend of the relocation would add
sec->output_offset when partial linking (ld -r).
See elf_backend_data.rela_normal and elf_link_input_bfd().
The addend of R_LARCH_ALIGN is used to represent the first and third
expression of .align, it should be a constant when linking. */
static bool
loongarch_elf_is_rela_normal (Elf_Internal_Rela *rel)
{
if (R_LARCH_ALIGN == ELFNN_R_TYPE (rel->r_info))
return false;
return true;
}
#define TARGET_LITTLE_SYM loongarch_elfNN_vec
#define TARGET_LITTLE_NAME "elfNN-loongarch"
#define ELF_ARCH bfd_arch_loongarch
@ -5489,6 +5504,7 @@ elf_loongarch64_hash_symbol (struct elf_link_hash_entry *h)
#define elf_backend_grok_psinfo loongarch_elf_grok_psinfo
#define elf_backend_hash_symbol elf_loongarch64_hash_symbol
#define bfd_elfNN_bfd_relax_section loongarch_elf_relax_section
#define elf_backend_is_rela_normal loongarch_elf_is_rela_normal
#define elf_backend_dtrel_excludes_plt 1

View file

@ -709,6 +709,10 @@
#define elf_backend_rela_normal 0
#endif
#ifndef elf_backend_is_rela_normal
#define elf_backend_is_rela_normal NULL
#endif
#ifndef elf_backend_dtrel_excludes_plt
#define elf_backend_dtrel_excludes_plt 0
#endif
@ -955,6 +959,7 @@ static const struct elf_backend_data elfNN_bed =
elf_backend_default_use_rela_p,
elf_backend_rela_plts_and_copies_p,
elf_backend_rela_normal,
elf_backend_is_rela_normal,
elf_backend_dtrel_excludes_plt,
elf_backend_sign_extend_vma,
elf_backend_want_got_plt,

View file

@ -1791,10 +1791,7 @@ loongarch_frag_align_code (int n, int max)
if (fragP->fr_subtype != 0 && offset > fragP->fr_subtype). */
if (max > 0 && (bfd_vma) max < worst_case_bytes)
{
s = symbol_find (".Lla-relax-align");
if (s == NULL)
s = (symbolS *)local_symbol_make (".Lla-relax-align", now_seg,
&zero_address_frag, 0);
s = symbol_find (now_seg->name);
ex.X_add_symbol = s;
ex.X_op = O_symbol;
ex.X_add_number = (max << 8) | n;

View file

@ -7,7 +7,7 @@
Disassembly of section .text:
[ ]*0000000000000000 <.Lla-relax-align>:
[ ]*0000000000000000 <.text>:
[ ]+0:[ ]+4c000020[ ]+ret
[ ]+4:[ ]+03400000[ ]+nop
[ ]+4: R_LARCH_ALIGN[ ]+\*ABS\*\+0xc
@ -20,12 +20,12 @@ Disassembly of section .text:
[ ]+1c:[ ]+03400000[ ]+nop
[ ]+20:[ ]+4c000020[ ]+ret
[ ]+24:[ ]+03400000[ ]+nop
[ ]+24: R_LARCH_ALIGN[ ]+.Lla-relax-align\+0x104
[ ]+24: R_LARCH_ALIGN[ ]+.text\+0x104
[ ]+28:[ ]+03400000[ ]+nop
[ ]+2c:[ ]+03400000[ ]+nop
[ ]+30:[ ]+4c000020[ ]+ret
[ ]+34:[ ]+03400000[ ]+nop
[ ]+34: R_LARCH_ALIGN[ ]+.Lla-relax-align\+0xb04
[ ]+34: R_LARCH_ALIGN[ ]+.text\+0xb04
[ ]+38:[ ]+03400000[ ]+nop
[ ]+3c:[ ]+03400000[ ]+nop
[ ]+40:[ ]+4c000020[ ]+ret

View file

@ -0,0 +1,4 @@
SECTIONS
{
/DISCARD/ : { *(.another.*) }
}

View file

@ -0,0 +1,17 @@
# Use the section name symbol for R_LARCH_ALIGN to avoid discard section problem
.section ".another.text", "ax"
.cfi_startproc
break 0
.cfi_def_cfa_offset 16
.p2align 5
break 1
.cfi_endproc
.text
.cfi_startproc
break 0
.cfi_def_cfa_offset 16
.p2align 5
break 1
.cfi_endproc

View file

@ -295,6 +295,18 @@ if [istarget loongarch64-*-*] {
"relax-align" \
] \
]
run_ld_link_tests \
[list \
[list \
"loongarch relax align discard" \
"-e 0x0 -T relax-align-discard.lds -r" "" \
"" \
{relax-align-discard.s} \
{} \
"relax-align-discard" \
] \
]
}
set objdump_flags "-s -j .data"