* [PATCH v1] LoongArch: Add support for the third expression of .align for R_LARCH_ALIGN
@ 2023-12-14 1:53 mengqinggang
0 siblings, 0 replies; only message in thread
From: mengqinggang @ 2023-12-14 1:53 UTC (permalink / raw)
To: binutils
Cc: xuchenghua, chenglulu, liuzhensong, cailulu, xry111, i.swmail,
maskray, luweining, wanglei, hejinyang, mengqinggang
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 | 45 ++++++++++++++-----
gas/config/tc-loongarch.c | 13 ++++--
gas/config/tc-loongarch.h | 4 +-
gas/testsuite/gas/loongarch/relax_align.d | 47 ++++++++++++--------
gas/testsuite/gas/loongarch/relax_align.s | 4 +-
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 +-
8 files changed, 86 insertions(+), 39 deletions(-)
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index 024c5d4cd96..4e6ef4f61c7 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -3852,11 +3852,21 @@ loongarch_relax_align (bfd *abfd, asection *sec,
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 alignment = 1, pos, max = 0, addend;
- symval -= rel->r_addend;
+ int index = ELFNN_R_SYM (rel->r_info);
+ if (index > 0)
+ {
+ alignment = 1 << (rel->r_addend & 0xff);
+ max = rel->r_addend >> 8;
+ }
+ else
+ while (alignment <= rel->r_addend)
+ alignment *= 2;
+
+ addend = alignment - 4;
+
+ symval -= addend;
bfd_vma aligned_addr = ((symval - 1) & ~(alignment - 1)) + alignment;
bfd_vma nop_bytes = aligned_addr - symval;
@@ -3864,22 +3874,25 @@ loongarch_relax_align (bfd *abfd, asection *sec,
sec->sec_flg0 = true;
/* Make sure there are enough NOPs to actually achieve the alignment. */
- if (rel->r_addend < nop_bytes)
+ if (addend < 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) nop_bytes, (int64_t) alignment, (int64_t) addend);
bfd_set_error (bfd_error_bad_value);
return false;
}
- /* Delete the reloc. */
rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
+ if (max > 0 && 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 (nop_bytes == addend)
return true;
/* Write as many LOONGARCH NOPs as we need. */
@@ -3888,7 +3901,7 @@ loongarch_relax_align (bfd *abfd, asection *sec,
/* Delete the excess NOPs. */
return loongarch_relax_delete_bytes (abfd, sec, rel->r_offset + nop_bytes,
- rel->r_addend - nop_bytes, link_info);
+ addend - nop_bytes, link_info);
}
static bool
@@ -3939,6 +3952,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 +3964,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;
@@ -4005,12 +4019,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. */
+ 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/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
index 59232832cf7..99c0ac47418 100644
--- a/gas/config/tc-loongarch.c
+++ b/gas/config/tc-loongarch.c
@@ -1648,12 +1648,14 @@ 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;
/* If we are moving to a smaller alignment than the instruction size, then no
@@ -1667,8 +1669,13 @@ 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 = colon (".Lla-relax-align");
+ 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 4afa38422d6..194ee107c0a 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 1810eb4cae7..d870e983bb6 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,31 @@
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\*
+.* <.Lla-relax-align-0x14>:
+[ ]+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.*
+0000000000000014 <.Lla-relax-align>:
+[ ]+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 3880d783e79..c0177c88fc1 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-loongarch-elf/relax-align.dd b/ld/testsuite/ld-loongarch-elf/relax-align.dd
index 5fce2255dda..37fdab18fab 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 9617c02d8e5..66dfea8f2c9 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 24d79ed5c20..77323d8d7a3 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.36.0
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2023-12-14 1:54 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-14 1:53 [PATCH v1] LoongArch: Add support for the third expression of .align for R_LARCH_ALIGN mengqinggang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).