[PATCH 1/3] LoongArch: Emit relocations for .long 0x2eef - symbol
mengqinggang <[email protected]>
| Newsgroups | gmane.comp.gnu.binutils |
|---|---|
| Message-ID | <[email protected]> |
Emit relocations for expressions like .long 0x2eef - symbol.
Since fx_addsy is set to NULL in fixup_segment, we cannot generate
relocations in md_apply_fix.
Set fx_addsy to abs_section_sym in md_apply_fix.
---
gas/config/tc-loongarch.c | 139 ++++++++++++--------
gas/testsuite/gas/loongarch/bfd_reloc_8.s | 16 ---
gas/testsuite/gas/loongarch/loongarch.exp | 2 +-
gas/testsuite/gas/loongarch/reloc-abs.d | 23 ++++
gas/testsuite/gas/loongarch/reloc-abs.s | 12 ++
gas/testsuite/gas/loongarch/reloc-add-sub.d | 22 ++++
gas/testsuite/gas/loongarch/reloc-add-sub.s | 16 +++
7 files changed, 155 insertions(+), 75 deletions(-)
delete mode 100644 gas/testsuite/gas/loongarch/bfd_reloc_8.s
create mode 100644 gas/testsuite/gas/loongarch/reloc-abs.d
create mode 100644 gas/testsuite/gas/loongarch/reloc-abs.s
create mode 100644 gas/testsuite/gas/loongarch/reloc-add-sub.d
create mode 100644 gas/testsuite/gas/loongarch/reloc-add-sub.s
diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
index bd7d8dabb7a..218c7004b8d 100644
--- a/gas/config/tc-loongarch.c
+++ b/gas/config/tc-loongarch.c
@@ -1758,39 +1758,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
fix_reloc_insn (fixP, (bfd_vma)stack_top, buf);
break;
- /* LARCH only has R_LARCH_64/32, not has R_LARCH_24/16/8.
- For BFD_RELOC_64/32, if fx_addsy and fx_subsy not null, wer need
- generate BFD_RELOC_LARCH_ADD64/32 and BFD_RELOC_LARCH_SUB64/32 here.
- Then will parse howto table bfd_reloc_code_real_type to generate
- R_LARCH_ADD64/32 and R_LARCH_SUB64/32 reloc at tc_gen_reloc function.
- If only fx_addsy not null, skip here directly, then generate
- R_LARCH_64/32.
-
- For BFD_RELOC_24/16/8, if fx_addsy and fx_subsy not null, wer need
- generate BFD_RELOC_LARCH_ADD24/16/8 and BFD_RELOC_LARCH_SUB24/16/8 here.
- Then will parse howto table bfd_reloc_code_real_type to generate
- R_LARCH_ADD24/16/8 and R_LARCH_SUB24/16/8 reloc at tc_gen_reloc
- function. If only fx_addsy not null, we generate
- BFD_RELOC_LARCH_ADD24/16/8 only, then generate R_LARCH_24/16/8.
- To avoid R_LARCH_ADDxx add extra value, we write 0 first
- (use md_number_to_chars (buf, 0, fixP->fx_size)). */
case BFD_RELOC_64:
case BFD_RELOC_32:
- if (fixP->fx_pcrel)
- {
- switch (fixP->fx_r_type)
- {
- case BFD_RELOC_64:
- fixP->fx_r_type = BFD_RELOC_64_PCREL;
- break;
- case BFD_RELOC_32:
- fixP->fx_r_type = BFD_RELOC_32_PCREL;
- break;
- default:
- break;
- }
- }
-
/* If symbol in .eh_frame the address may be adjusted, and contents of
.eh_frame will be adjusted, so use pc-relative relocation for FDE
initial location.
@@ -1807,33 +1776,65 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
fixP->fx_subsy = NULL;
break;
}
-
- if (fixP->fx_addsy && fixP->fx_subsy)
+ else if (fixP->fx_pcrel && LARCH_opts.thin_add_sub)
{
- fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
- fixP->fx_next->fx_addsy = fixP->fx_subsy;
- fixP->fx_next->fx_subsy = NULL;
- fixP->fx_next->fx_offset = 0;
- fixP->fx_subsy = NULL;
-
switch (fixP->fx_r_type)
{
case BFD_RELOC_64:
- fixP->fx_r_type = BFD_RELOC_LARCH_ADD64;
- fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB64;
+ fixP->fx_r_type = BFD_RELOC_64_PCREL;
break;
case BFD_RELOC_32:
- fixP->fx_r_type = BFD_RELOC_LARCH_ADD32;
- fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB32;
+ fixP->fx_r_type = BFD_RELOC_32_PCREL;
break;
default:
break;
}
+ }
+ else
+ {
+ /* For .long 0x2eef - 1b, fx_addsy is set to NULL in fixup_segment.
+ If fx_addsy and fx_subsy both is NULL, no need to emit relocations.
+ If fx_sybsy is not NULL, fake up a local symbol in the absolute
+ section, just as fixup_segment dose for fx_pcrel relocations. */
+ if (fixP->fx_addsy == NULL
+ && fixP->fx_subsy != NULL)
+ fixP->fx_addsy = abs_section_sym;
+
+ /* For .4byte/.8byte symbol, fx_addsy is not NULL, fx_subsy is NULL.
+ Not need to enter this if branch, just emit R_LARCH_32/64 directly.
+ BFD_RELOC_32/64 -> R_LARCH_32/64. */
+ if (fixP->fx_addsy && fixP->fx_subsy)
+ {
+ fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
+ fixP->fx_next->fx_addsy = fixP->fx_subsy;
+ fixP->fx_next->fx_subsy = NULL;
+ fixP->fx_next->fx_offset = 0;
+ fixP->fx_subsy = NULL;
- md_number_to_chars (buf, 0, fixP->fx_size);
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_64:
+ fixP->fx_r_type = BFD_RELOC_LARCH_ADD64;
+ fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB64;
+ break;
+ case BFD_RELOC_32:
+ fixP->fx_r_type = BFD_RELOC_LARCH_ADD32;
+ fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB32;
+ break;
+ default:
+ break;
+ }
+
+ /* Because we use ADD/SUB relocations, clear the position
+ to avoid the linker adding an extra value. */
+ md_number_to_chars (buf, 0, fixP->fx_size);
+ }
}
- if (fixP->fx_addsy == NULL)
+ /* If all symbols are resolved, write the value without emitting
+ relocatiosn. */
+ if (fixP->fx_addsy == NULL
+ && fixP->fx_subsy == NULL)
{
fixP->fx_done = 1;
md_number_to_chars (buf, *valP, fixP->fx_size);
@@ -1843,39 +1844,61 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
case BFD_RELOC_24:
case BFD_RELOC_16:
case BFD_RELOC_8:
+ /* Similar with BFD_RELOC_64/32. */
+ if (fixP->fx_addsy == NULL
+ && fixP->fx_subsy != NULL)
+ fixP->fx_addsy = abs_section_sym;
+
+ /* For .byte/.2byte/.3byte(if supported) symbol, fx_addsy is not NULL,
+ fx_subsy is NULL. There are no corresponding R_LARCH_8/16/24, need
+ to enter this if branch to emit R_LARCH_ADD8/16/24.
+ BFD_RELOC_8/16/24 -> BFD_RELOC_LARCH_ADD8/16/24 -> R_LARCH_ADD8/16/24. */
if (fixP->fx_addsy)
{
- fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
- fixP->fx_next->fx_addsy = fixP->fx_subsy;
- fixP->fx_next->fx_subsy = NULL;
- fixP->fx_next->fx_offset = 0;
- fixP->fx_subsy = NULL;
-
switch (fixP->fx_r_type)
{
case BFD_RELOC_24:
fixP->fx_r_type = BFD_RELOC_LARCH_ADD24;
- fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB24;
break;
case BFD_RELOC_16:
fixP->fx_r_type = BFD_RELOC_LARCH_ADD16;
- fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB16;
break;
case BFD_RELOC_8:
fixP->fx_r_type = BFD_RELOC_LARCH_ADD8;
- fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB8;
break;
default:
break;
}
- md_number_to_chars (buf, 0, fixP->fx_size);
+ if (fixP->fx_subsy != NULL)
+ {
+ fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
+ fixP->fx_next->fx_addsy = fixP->fx_subsy;
+ fixP->fx_next->fx_subsy = NULL;
+ fixP->fx_next->fx_offset = 0;
+ fixP->fx_subsy = NULL;
- if (fixP->fx_next->fx_addsy == NULL)
- fixP->fx_next->fx_done = 1;
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_LARCH_ADD24:
+ fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB24;
+ break;
+ case BFD_RELOC_LARCH_ADD16:
+ fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB16;
+ break;
+ case BFD_RELOC_LARCH_ADD8:
+ fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB8;
+ break;
+ default:
+ break;
+ }
+ }
+
+ md_number_to_chars (buf, 0, fixP->fx_size);
}
- if (fixP->fx_addsy == NULL)
+ if (fixP->fx_addsy == NULL
+ && fixP->fx_subsy == NULL)
{
fixP->fx_done = 1;
md_number_to_chars (buf, *valP, fixP->fx_size);
diff --git a/gas/testsuite/gas/loongarch/bfd_reloc_8.s b/gas/testsuite/gas/loongarch/bfd_reloc_8.s
deleted file mode 100644
index 27388a5826f..00000000000
--- a/gas/testsuite/gas/loongarch/bfd_reloc_8.s
+++ /dev/null
@@ -1,16 +0,0 @@
-# from linux kernel entry.s
-# test line 10 ".byte \type", BFD_RELOC_8 -> BFD_RELOC_RLARCH_ADD8 -> R_LARCH_ADD8
-
-.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
-.Lunwind_hint_ip_\@:
- .pushsection .discard.unwind_hints
- .long .Lunwind_hint_ip_\@ - .
- .short \sp_offset
- .byte \sp_reg
- .byte \type
- .byte \end
- .balign 4
- .popsection
-.endm
-
-UNWIND_HINT type=ORC_TYPE_CALL sp_reg=2
diff --git a/gas/testsuite/gas/loongarch/loongarch.exp b/gas/testsuite/gas/loongarch/loongarch.exp
index f1dfb53d855..e5b9262a483 100644
--- a/gas/testsuite/gas/loongarch/loongarch.exp
+++ b/gas/testsuite/gas/loongarch/loongarch.exp
@@ -20,7 +20,7 @@
if [istarget loongarch*-*-*] {
run_dump_tests [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
- gas_test_old bfd_reloc_8.s "" "bfd_reloc_8"
+
if [file exist "tls_le_insn_format_check.s "] {
set format [run_host_cmd "as" "tls_le_insn_format_check.s"]
if { [ regexp ".*no match insn.*" $format] } {
diff --git a/gas/testsuite/gas/loongarch/reloc-abs.d b/gas/testsuite/gas/loongarch/reloc-abs.d
new file mode 100644
index 00000000000..f1a4fb3d1ab
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/reloc-abs.d
@@ -0,0 +1,23 @@
+#source: reloc-abs.s
+#as: -mrelax
+#objdump: -dr
+
+#...
+.*R_LARCH_ADD16 \*ABS\*\+0x2eef
+.*R_LARCH_SUB16 .L1\^B1
+.*R_LARCH_ADD32 \*ABS\*\+0x2eef
+.*R_LARCH_SUB32 .L1\^B1
+.*R_LARCH_ADD64 \*ABS\*\+0x12345678
+.*R_LARCH_SUB64 .L1\^B1
+.*R_LARCH_ADD16 \*ABS\*\+0x2eef
+.*R_LARCH_SUB16 .L1\^B1
+.*R_LARCH_ADD32 \*ABS\*\+0x2eef
+.*R_LARCH_SUB32 .L1\^B1
+.*R_LARCH_ADD8 \*ABS\*\+0x2e
+.*R_LARCH_SUB8 .L1\^B1
+.*R_LARCH_ADD16 \*ABS\*\+0x2eef
+.*R_LARCH_SUB16 .L1\^B1
+.*R_LARCH_ADD32 \*ABS\*\+0x2eef
+.*R_LARCH_SUB32 .L1\^B1
+.*R_LARCH_ADD64 \*ABS\*\+0x12345678
+.*R_LARCH_SUB64 .L1\^B1
diff --git a/gas/testsuite/gas/loongarch/reloc-abs.s b/gas/testsuite/gas/loongarch/reloc-abs.s
new file mode 100644
index 00000000000..526b71f0283
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/reloc-abs.s
@@ -0,0 +1,12 @@
+ .text
+1:
+ nop
+ .half 0x2eef - 1b
+ .word 0x2eef - 1b
+ .dword 0x12345678 - 1b
+ .short 0x2eef - 1b
+ .long 0x2eef - 1b
+ .byte 0x2e - 1b
+ .2byte 0x2eef - 1b
+ .4byte 0x2eef - 1b
+ .8byte 0x12345678 - 1b
diff --git a/gas/testsuite/gas/loongarch/reloc-add-sub.d b/gas/testsuite/gas/loongarch/reloc-add-sub.d
new file mode 100644
index 00000000000..8c599fc1711
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/reloc-add-sub.d
@@ -0,0 +1,22 @@
+#source: reloc-add-sub.s
+#as: -mrelax
+#objdump: -dr
+
+#...
+ 4: R_LARCH_ADD32 \*ABS\*\+0xa
+ 4: R_LARCH_SUB32 x
+ 8: R_LARCH_32 x-0xa
+ c: R_LARCH_ADD32 x
+ c: R_LARCH_SUB32 y
+ 10: R_LARCH_32 x
+ 14: 00000005 .word 0x00000005
+ 15: R_LARCH_ADD8 \*ABS\*\+0xa
+ 15: R_LARCH_SUB8 x
+ 16: R_LARCH_ADD8 x-0xa
+ 17: R_LARCH_ADD8 x
+ 17: R_LARCH_SUB8 y
+ 18: 00000000 .word 0x00000000
+ 18: R_LARCH_ADD8 x
+ 19: R_LARCH_ADD8 x
+ 1a: R_LARCH_ADD8 x
+ 1b: R_LARCH_ADD8 x
diff --git a/gas/testsuite/gas/loongarch/reloc-add-sub.s b/gas/testsuite/gas/loongarch/reloc-add-sub.s
new file mode 100644
index 00000000000..9d18bbe3093
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/reloc-add-sub.s
@@ -0,0 +1,16 @@
+ .text
+x:
+ .long 10 - 5 # no relocation
+ .long 10 - x # R_LARCH_ADD32/SUB32
+ .long x - 10 # R_LARCH_32
+ .long x - y # R_LARCH_ADD32/SUB32
+ .long x # R_LARCH_32
+
+ .byte 10 - 5 # no relocation
+ .byte 10 - x # R_LARCH_ADD8/SUB8
+ .byte x - 10 # R_LARCH_ADD8
+ .byte x - y # R_LARCH_ADD8/SUB8
+ .byte x # R_LARCH_ADD8
+ .byte x
+ .byte x
+ .byte x
--
2.34.1