[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.