Fetch the repository succeeded.
This action will force synchronization from src-openEuler/binutils, which will overwrite any changes that you have made since you forked the repository, and can not be recovered!!!
Synchronous operation will process in the background and will refresh the page when finishing processing. Please be patient.
From 3df3fec5862a2d6adec7dc469e7c53596e0ca464 Mon Sep 17 00:00:00 2001
From: mengqinggang <mengqinggang@loongson.cn>
Date: Fri, 8 Dec 2023 15:15:50 +0800
Subject: [PATCH 023/123] LoongArch: Add support for the third expression of
.align for R_LARCH_ALIGN
If the symbol index is not zero, the addend is used to represent
the first and the third expressions of the .align.
The lowest 8 bits are used to represent the first expression.
Other bits are used to represent the third expression.
The addend of R_LARCH_ALIGN for ".align 5, ,4" is 0x405.
The addend of R_LARCH_ALIGN for ".balign 32, ,4" is 0x405.
---
bfd/elfnn-loongarch.c | 71 ++++++++++++-------
bfd/elfxx-loongarch.c | 10 ++-
gas/config/tc-loongarch.c | 20 ++++--
gas/config/tc-loongarch.h | 4 +-
gas/testsuite/gas/loongarch/relax_align.d | 46 +++++++-----
gas/testsuite/gas/loongarch/relax_align.s | 4 +-
ld/testsuite/ld-elf/anno-sym.d | 2 +
ld/testsuite/ld-loongarch-elf/anno-sym.d | 7 ++
ld/testsuite/ld-loongarch-elf/anno-sym.l | 4 ++
ld/testsuite/ld-loongarch-elf/anno-sym.s | 13 ++++
.../ld-loongarch-elf/ld-loongarch-elf.exp | 1 +
ld/testsuite/ld-loongarch-elf/relax-align.dd | 5 +-
ld/testsuite/ld-loongarch-elf/relax-align.s | 5 +-
ld/testsuite/ld-loongarch-elf/relax.exp | 2 +-
14 files changed, 134 insertions(+), 60 deletions(-)
create mode 100644 ld/testsuite/ld-loongarch-elf/anno-sym.d
create mode 100644 ld/testsuite/ld-loongarch-elf/anno-sym.l
create mode 100644 ld/testsuite/ld-loongarch-elf/anno-sym.s
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index 6fd6a04d..8e61d8d2 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -3851,44 +3851,53 @@ loongarch_relax_align (bfd *abfd, asection *sec,
Elf_Internal_Rela *rel,
bfd_vma symval)
{
- bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
- bfd_vma alignment = 1, pos;
- while (alignment <= rel->r_addend)
- alignment *= 2;
+ bfd_vma addend, max = 0, alignment = 1;
- symval -= rel->r_addend;
- bfd_vma aligned_addr = ((symval - 1) & ~(alignment - 1)) + alignment;
- bfd_vma nop_bytes = aligned_addr - symval;
+ int index = ELFNN_R_SYM (rel->r_info);
+ if (index > 0)
+ {
+ alignment = 1 << (rel->r_addend & 0xff);
+ max = rel->r_addend >> 8;
+ }
+ else
+ alignment = rel->r_addend + 4;
- /* Once we've handled an R_LARCH_ALIGN, we can't relax anything else. */
- sec->sec_flg0 = true;
+ addend = alignment - 4; /* The bytes of NOPs added by R_LARCH_ALIGN. */
+ symval -= addend; /* The address of first NOP added by R_LARCH_ALIGN. */
+ bfd_vma aligned_addr = ((symval - 1) & ~(alignment - 1)) + alignment;
+ bfd_vma need_nop_bytes = aligned_addr - symval; /* */
/* Make sure there are enough NOPs to actually achieve the alignment. */
- if (rel->r_addend < nop_bytes)
+ if (addend < need_nop_bytes)
{
_bfd_error_handler
(_("%pB(%pA+%#" PRIx64 "): %" PRId64 " bytes required for alignment "
"to %" PRId64 "-byte boundary, but only %" PRId64 " present"),
abfd, sym_sec, (uint64_t) rel->r_offset,
- (int64_t) nop_bytes, (int64_t) alignment, (int64_t) rel->r_addend);
+ (int64_t) need_nop_bytes, (int64_t) alignment, (int64_t) addend);
bfd_set_error (bfd_error_bad_value);
return false;
}
- /* Delete the reloc. */
+ /* Once we've handled an R_LARCH_ALIGN in a section,
+ we can't relax anything else in this section. */
+ sec->sec_flg0 = true;
rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
+ /* If skipping more bytes than the specified maximum,
+ then the alignment is not done at all and delete all NOPs. */
+ if (max > 0 && need_nop_bytes > max)
+ return loongarch_relax_delete_bytes (abfd, sec, rel->r_offset,
+ addend, link_info);
+
/* If the number of NOPs is already correct, there's nothing to do. */
- if (nop_bytes == rel->r_addend)
+ if (need_nop_bytes == addend)
return true;
- /* Write as many LOONGARCH NOPs as we need. */
- for (pos = 0; pos < (nop_bytes & -4); pos += 4)
- bfd_putl32 (LARCH_NOP, contents + rel->r_offset + pos);
-
/* Delete the excess NOPs. */
- return loongarch_relax_delete_bytes (abfd, sec, rel->r_offset + nop_bytes,
- rel->r_addend - nop_bytes, link_info);
+ return loongarch_relax_delete_bytes (abfd, sec,
+ rel->r_offset + need_nop_bytes,
+ addend - need_nop_bytes, link_info);
}
static bool
@@ -3897,8 +3906,8 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
bool *again)
{
struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
- Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (abfd);
struct bfd_elf_section_data *data = elf_section_data (sec);
+ Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (abfd);
Elf_Internal_Rela *relocs;
*again = false;
@@ -3931,7 +3940,7 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
0, NULL, NULL, NULL)))
return true;
- data->relocs = relocs;
+ data->relocs = relocs;
for (unsigned int i = 0; i < sec->reloc_count; i++)
{
@@ -3939,6 +3948,7 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
asection *sym_sec;
bfd_vma symval;
unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
+ unsigned long r_type = ELFNN_R_TYPE (rel->r_info);
bool local_got = false;
char symtype;
struct elf_link_hash_entry *h = NULL;
@@ -3950,7 +3960,7 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
continue;
- if (sym->st_shndx == SHN_UNDEF)
+ if (sym->st_shndx == SHN_UNDEF || R_LARCH_ALIGN == r_type)
{
sym_sec = sec;
symval = rel->r_offset;
@@ -3976,9 +3986,9 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
continue;
if ((h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- && h->root.u.def.section != NULL
- && h->root.u.def.section->output_section != NULL)
+ || h->root.type == bfd_link_hash_defweak)
+ && h->root.u.def.section != NULL
+ && h->root.u.def.section->output_section != NULL)
{
symval = h->root.u.def.value;
sym_sec = h->root.u.def.section;
@@ -4004,12 +4014,21 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
if (symtype != STT_SECTION)
symval += rel->r_addend;
}
+ /* For R_LARCH_ALIGN, symval is sec_addr (sym_sec) + rel->r_offset
+ + (alingmeng - 4).
+ If r_symndx is 0, alignmeng-4 is r_addend.
+ If r_symndx > 0, alignment-4 is 2^(r_addend & 0xff)-4. */
+ else if (R_LARCH_ALIGN == r_type)
+ if (r_symndx > 0)
+ symval += ((1 << (rel->r_addend & 0xff)) - 4);
+ else
+ symval += rel->r_addend;
else
symval += rel->r_addend;
symval += sec_addr (sym_sec);
- switch (ELFNN_R_TYPE (rel->r_info))
+ switch (r_type)
{
case R_LARCH_ALIGN:
if (1 == info->relax_pass)
diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c
index d93b7904..679b79f3 100644
--- a/bfd/elfxx-loongarch.c
+++ b/bfd/elfxx-loongarch.c
@@ -1395,9 +1395,13 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
NULL, /* adjust_reloc_bits. */
NULL), /* larch_reloc_type_name. */
- /* Indicates an alignment statement. The addend field encodes how many
- bytes of NOPs follow the statement. The desired alignment is the
- addend rounded up to the next power of two. */
+ /* Indicates an alignment statement. f the symbol index is 0,
+ the addend indicates the number of bytes occupied by nop instructions
+ at the relocation offset. The alignment boundary is specified by the
+ addend rounded up to the next power of two.
+ If the symbol index is not 0, the addend indicates the first and third
+ expressions of .align. The lowest 8 bits are used to represent the first
+ expression, other bits are used to represent the third expression. */
LOONGARCH_HOWTO (R_LARCH_ALIGN, /* type (102). */
0, /* rightshift. */
0, /* size. */
diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
index 367a0b6c..9b912daf 100644
--- a/gas/config/tc-loongarch.c
+++ b/gas/config/tc-loongarch.c
@@ -1652,14 +1652,16 @@ loongarch_make_nops (char *buf, bfd_vma bytes)
the correct alignment now because of other linker relaxations. */
bool
-loongarch_frag_align_code (int n)
+loongarch_frag_align_code (int n, int max)
{
- bfd_vma bytes = (bfd_vma) 1 << n;
- bfd_vma insn_alignment = 4;
- bfd_vma worst_case_bytes = bytes - insn_alignment;
char *nops;
+ symbolS *s;
expressionS ex;
+ bfd_vma insn_alignment = 4;
+ bfd_vma bytes = (bfd_vma) 1 << n;
+ bfd_vma worst_case_bytes = bytes - insn_alignment;
+
/* If we are moving to a smaller alignment than the instruction size, then no
alignment is required. */
if (bytes <= insn_alignment)
@@ -1671,8 +1673,14 @@ loongarch_frag_align_code (int n)
nops = frag_more (worst_case_bytes);
- ex.X_op = O_constant;
- ex.X_add_number = 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);
+
+ ex.X_add_symbol = s;
+ ex.X_op = O_symbol;
+ ex.X_add_number = (max << 8) | n;
loongarch_make_nops (nops, worst_case_bytes);
diff --git a/gas/config/tc-loongarch.h b/gas/config/tc-loongarch.h
index 4afa3842..194ee107 100644
--- a/gas/config/tc-loongarch.h
+++ b/gas/config/tc-loongarch.h
@@ -49,11 +49,11 @@ extern int loongarch_relax_frag (asection *, struct frag *, long);
#define md_undefined_symbol(name) (0)
#define md_operand(x)
-extern bool loongarch_frag_align_code (int);
+extern bool loongarch_frag_align_code (int, int);
#define md_do_align(N, FILL, LEN, MAX, LABEL) \
if ((N) != 0 && !(FILL) && !need_pass_2 && subseg_text_p (now_seg)) \
{ \
- if (loongarch_frag_align_code (N)) \
+ if (loongarch_frag_align_code (N, MAX)) \
goto LABEL; \
}
diff --git a/gas/testsuite/gas/loongarch/relax_align.d b/gas/testsuite/gas/loongarch/relax_align.d
index 1810eb4c..2cc6c86d 100644
--- a/gas/testsuite/gas/loongarch/relax_align.d
+++ b/gas/testsuite/gas/loongarch/relax_align.d
@@ -1,4 +1,4 @@
-#as:
+#as: --no-warn
#objdump: -dr
#skip: loongarch32-*-*
@@ -7,20 +7,30 @@
Disassembly of section .text:
-00000000.* <L1>:
-[ ]+0:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0,[ ]+0
-[ ]+0:[ ]+R_LARCH_PCALA_HI20[ ]+L1
-[ ]+0:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
-[ ]+4:[ ]+02c00084[ ]+addi\.d[ ]+\$a0,[ ]+\$a0,[ ]+0
-[ ]+4:[ ]+R_LARCH_PCALA_LO12[ ]+L1
-[ ]+4:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
-[ ]+8:[ ]+03400000[ ]+nop[ ]+
-[ ]+8:[ ]+R_LARCH_ALIGN[ ]+\*ABS\*\+0xc
-[ ]+c:[ ]+03400000[ ]+nop[ ]+
-[ ]+10:[ ]+03400000[ ]+nop[ ]+
-[ ]+14:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0,[ ]+0
-[ ]+14:[ ]+R_LARCH_PCALA_HI20[ ]+L1
-[ ]+14:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
-[ ]+18:[ ]+02c00084[ ]+addi\.d[ ]+\$a0,[ ]+\$a0,[ ]+0
-[ ]+18:[ ]+R_LARCH_PCALA_LO12[ ]+L1
-[ ]+18:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
+[ ]*0000000000000000 <.Lla-relax-align>:
+[ ]+0:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0, 0
+[ ]+0: R_LARCH_PCALA_HI20[ ]+L1
+[ ]+0: R_LARCH_RELAX[ ]+\*ABS\*
+[ ]+4:[ ]+02c00084[ ]+addi.d[ ]+\$a0, \$a0, 0
+[ ]+4: R_LARCH_PCALA_LO12[ ]+L1
+[ ]+4: R_LARCH_RELAX[ ]+\*ABS\*
+[ ]+8:[ ]+03400000[ ]+nop.*
+[ ]+8: R_LARCH_ALIGN[ ]+.Lla-relax-align\+0x4
+[ ]+c:[ ]+03400000[ ]+nop.*
+[ ]+10:[ ]+03400000[ ]+nop.*
+[ ]+14:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0, 0
+[ ]+14: R_LARCH_PCALA_HI20[ ]+L1
+[ ]+14: R_LARCH_RELAX[ ]+\*ABS\*
+[ ]+18:[ ]+02c00084[ ]+addi.d[ ]+\$a0, \$a0, 0
+[ ]+18: R_LARCH_PCALA_LO12[ ]+L1
+[ ]+18: R_LARCH_RELAX[ ]+\*ABS\*
+[ ]+1c:[ ]+03400000[ ]+nop.*
+[ ]+1c: R_LARCH_ALIGN[ ]+.Lla-relax-align\+0x404
+[ ]+20:[ ]+03400000[ ]+nop.*
+[ ]+24:[ ]+03400000[ ]+nop.*
+[ ]+28:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0, 0
+[ ]+28: R_LARCH_PCALA_HI20[ ]+L1
+[ ]+28: R_LARCH_RELAX[ ]+\*ABS\*
+[ ]+2c:[ ]+02c00084[ ]+addi.d[ ]+\$a0, \$a0, 0
+[ ]+2c: R_LARCH_PCALA_LO12[ ]+L1
+[ ]+2c: R_LARCH_RELAX[ ]+\*ABS\*
diff --git a/gas/testsuite/gas/loongarch/relax_align.s b/gas/testsuite/gas/loongarch/relax_align.s
index 3880d783..c0177c88 100644
--- a/gas/testsuite/gas/loongarch/relax_align.s
+++ b/gas/testsuite/gas/loongarch/relax_align.s
@@ -1,5 +1,7 @@
.text
-L1:
+.L1:
la.local $a0, L1
.align 4
la.local $a0, L1
+ .align 4, , 4
+ la.local $a0, L1
diff --git a/ld/testsuite/ld-elf/anno-sym.d b/ld/testsuite/ld-elf/anno-sym.d
index 9e53c4a9..f1ce21f9 100644
--- a/ld/testsuite/ld-elf/anno-sym.d
+++ b/ld/testsuite/ld-elf/anno-sym.d
@@ -3,3 +3,5 @@
#error_output: anno-sym.l
# The mips-irix6 target fails this test because it does not find any function symbols. Not sure why.
#skip: *-*-irix*
+# The .align generate a local symbol .Lla-relax-align.
+#skip: loongarch*-*-*
diff --git a/ld/testsuite/ld-loongarch-elf/anno-sym.d b/ld/testsuite/ld-loongarch-elf/anno-sym.d
new file mode 100644
index 00000000..a58f4a6c
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/anno-sym.d
@@ -0,0 +1,7 @@
+# Copied from ld-elf, add -mno-relax to prevent generate .Lla-relax-align symbol
+# Check that linking anno-sym.o produces an undefined reference message referring to '_start' and not 'annobin_hello.c'
+#as: -mno-relax
+#ld: -e _start
+#error_output: anno-sym.l
+# The mips-irix6 target fails this test because it does not find any function symbols. Not sure why.
+#skip: *-*-irix*
diff --git a/ld/testsuite/ld-loongarch-elf/anno-sym.l b/ld/testsuite/ld-loongarch-elf/anno-sym.l
new file mode 100644
index 00000000..ee9611ae
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/anno-sym.l
@@ -0,0 +1,4 @@
+#...
+.*: in function `(|_)start':
+.*: undefined reference to `foo'
+#pass
diff --git a/ld/testsuite/ld-loongarch-elf/anno-sym.s b/ld/testsuite/ld-loongarch-elf/anno-sym.s
new file mode 100644
index 00000000..92016a80
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/anno-sym.s
@@ -0,0 +1,13 @@
+ .text
+
+ .hidden .annobin_hello.c
+ .type .annobin_hello.c, STT_NOTYPE
+ .equiv .annobin_hello.c, .
+ .size .annobin_hello.c, 0
+
+ .global _start
+_start:
+ .nop
+ .align 4
+ .dc.a foo
+
diff --git a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
index 1fc70d0a..b43a518a 100644
--- a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
+++ b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
@@ -32,6 +32,7 @@ if [istarget "loongarch64-*-*"] {
run_dump_test "syscall"
run_dump_test "disas-jirl"
run_dump_test "local-ifunc-reloc"
+ run_dump_test "anno-sym"
}
if [istarget "loongarch32-*-*"] {
diff --git a/ld/testsuite/ld-loongarch-elf/relax-align.dd b/ld/testsuite/ld-loongarch-elf/relax-align.dd
index 5fce2255..37fdab18 100644
--- a/ld/testsuite/ld-loongarch-elf/relax-align.dd
+++ b/ld/testsuite/ld-loongarch-elf/relax-align.dd
@@ -1,7 +1,8 @@
#...
.*pcaddi.*
-.*pcaddi.*
.*nop.*
+.*pcaddi.*
.*nop.*
-.*0:.*pcaddi.*
+.*pcaddi.*
+.*pcaddi.*
#pass
diff --git a/ld/testsuite/ld-loongarch-elf/relax-align.s b/ld/testsuite/ld-loongarch-elf/relax-align.s
index 9617c02d..66dfea8f 100644
--- a/ld/testsuite/ld-loongarch-elf/relax-align.s
+++ b/ld/testsuite/ld-loongarch-elf/relax-align.s
@@ -4,6 +4,9 @@
.text
L1:
la.local $a0, L1
+ .align 3
la.local $a0, L1
- .align 4
+ .align 3, ,4
+ la.local $a0, L1
+ .align 3, ,2
la.local $a0, L1
diff --git a/ld/testsuite/ld-loongarch-elf/relax.exp b/ld/testsuite/ld-loongarch-elf/relax.exp
index 24d79ed5..77323d8d 100644
--- a/ld/testsuite/ld-loongarch-elf/relax.exp
+++ b/ld/testsuite/ld-loongarch-elf/relax.exp
@@ -121,7 +121,7 @@ if [istarget loongarch64-*-*] {
[list \
"loongarch relax-align" \
"-e 0x0 -z relro" "" \
- "" \
+ "--no-warn" \
{relax-align.s} \
[list \
[list objdump -d relax-align.dd] \
--
2.33.0
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。