public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Add support for COFF secidx relocations
@ 2022-04-04 11:44 Mark Harmstone
  0 siblings, 0 replies; 3+ messages in thread
From: Mark Harmstone @ 2022-04-04 11:44 UTC (permalink / raw)
  To: binutils, mark

Hi all,

Apologies in advance if I've done anything wrong here, this is my first
substantive patch to binutils.

I've been working on adding support for Microsoft's PDB debugging format
to gcc and binutils, and this turned out to be a blocker. This adds
support for the secidx relocation type in COFF files, which is a two-byte
index for the section in which a symbol ends up. It also adds support for
the .secidx pseudo-directive to generate this (the syntax of which is
cribbed from llvm-mc, which supports this already).

Thanks

Mark

---
 bfd/bfd-in2.h                   |  1 +
 bfd/coff-i386.c                 | 95 +++++++++++++++++++++++++++++++--
 bfd/coff-x86_64.c               | 95 +++++++++++++++++++++++++++++++--
 bfd/libbfd.h                    |  1 +
 bfd/reloc.c                     |  2 +
 gas/config/tc-i386.c            | 24 +++++++++
 gas/expr.c                      |  1 +
 gas/expr.h                      |  2 +
 gas/symbols.c                   |  8 +++
 gas/testsuite/gas/i386/i386.exp |  3 +-
 gas/testsuite/gas/i386/secidx.d | 40 ++++++++++++++
 gas/testsuite/gas/i386/secidx.s | 79 +++++++++++++++++++++++++++
 include/coff/i386.h             |  1 +
 include/coff/x86_64.h           |  1 +
 ld/testsuite/ld-pe/pe.exp       | 15 ++++++
 ld/testsuite/ld-pe/secidx.d     | 27 ++++++++++
 ld/testsuite/ld-pe/secidx1.s    | 77 ++++++++++++++++++++++++++
 ld/testsuite/ld-pe/secidx2.s    | 17 ++++++
 ld/testsuite/ld-pe/secidx_64.d  | 27 ++++++++++
 19 files changed, 505 insertions(+), 11 deletions(-)
 create mode 100644 gas/testsuite/gas/i386/secidx.d
 create mode 100644 gas/testsuite/gas/i386/secidx.s
 create mode 100644 ld/testsuite/ld-pe/secidx.d
 create mode 100644 ld/testsuite/ld-pe/secidx1.s
 create mode 100644 ld/testsuite/ld-pe/secidx2.s
 create mode 100644 ld/testsuite/ld-pe/secidx_64.d

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 8e815bab624..23fbaa520e8 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -2235,6 +2235,7 @@ the section containing the relocation.  It depends on the specific target.  */
 
 /* Section relative relocations.  Some targets need this for DWARF2.  */
   BFD_RELOC_32_SECREL,
+  BFD_RELOC_16_SECIDX,
 
 /* For ELF.  */
   BFD_RELOC_32_GOT_PCREL,
diff --git a/bfd/coff-i386.c b/bfd/coff-i386.c
index 0670c5906c2..0664fd344ff 100644
--- a/bfd/coff-i386.c
+++ b/bfd/coff-i386.c
@@ -191,7 +191,7 @@ static bool
 in_reloc_p (bfd *abfd ATTRIBUTE_UNUSED, reloc_howto_type *howto)
 {
   return ! howto->pc_relative && howto->type != R_IMAGEBASE
-	 && howto->type != R_SECREL32;
+	 && howto->type != R_SECREL32 && howto->type != R_SECTION;
 }
 #endif /* COFF_WITH_PE */
 
@@ -236,8 +236,21 @@ static reloc_howto_type howto_table[] =
 	 false),		/* pcrel_offset */
   EMPTY_HOWTO (010),
   EMPTY_HOWTO (011),
-  EMPTY_HOWTO (012),
 #ifdef COFF_WITH_PE
+  /* 16-bit word section relocation (012).  */
+  HOWTO (R_SECTION,		/* type */
+	 0,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 coff_i386_reloc,	/* special_function */
+	 "secidx",		/* name */
+	 true,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
   /* 32-bit longword section relative relocation (013).  */
   HOWTO (R_SECREL32,		/* type */
 	 0,			/* rightshift */
@@ -253,6 +266,7 @@ static reloc_howto_type howto_table[] =
 	 0xffffffff,		/* dst_mask */
 	 true),			/* pcrel_offset */
 #else
+  EMPTY_HOWTO (012),
   EMPTY_HOWTO (013),
 #endif
   EMPTY_HOWTO (014),
@@ -407,9 +421,9 @@ static reloc_howto_type howto_table[] =
 
 #else /* COFF_WITH_PE */
 
-/* The PE relocate section routine.  The only difference between this
-   and the regular routine is that we don't want to do anything for a
-   relocatable link.  */
+/* The PE relocate section routine.  We handle secidx relocations here,
+ * as well as making sure that we don't do anything for a relocatable
+ * link.  */
 
 static bool
 coff_pe_i386_relocate_section (bfd *output_bfd,
@@ -421,9 +435,78 @@ coff_pe_i386_relocate_section (bfd *output_bfd,
 			       struct internal_syment *syms,
 			       asection **sections)
 {
+  struct internal_reloc *rel;
+  struct internal_reloc *relend;
+
   if (bfd_link_relocatable (info))
     return true;
 
+  rel = relocs;
+  relend = rel + input_section->reloc_count;
+
+  for (; rel < relend; rel++)
+    {
+      long symndx;
+      struct coff_link_hash_entry *h;
+      asection *sec, *s;
+      uint16_t idx = 0, i = 1;
+
+      if (rel->r_type != R_SECTION)
+	continue;
+
+      /* Make sure that _bfd_coff_generic_relocate_section won't parse
+       * this reloc after us */
+      rel->r_type = 0;
+
+      symndx = rel->r_symndx;
+
+      if (symndx < 0
+	  || (unsigned long) symndx >= obj_raw_syment_count (input_bfd))
+	continue;
+
+      h = obj_coff_sym_hashes (input_bfd)[symndx];
+
+      if (h == NULL)
+	sec = sections[symndx];
+      else
+      {
+	if (h->root.type == bfd_link_hash_defined
+	    || h->root.type == bfd_link_hash_defweak)
+	  {
+	    /* Defined weak symbols are a GNU extension. */
+	    sec = h->root.u.def.section;
+	  }
+	else
+	  {
+	    sec = NULL;
+	  }
+      }
+
+      if (!sec)
+	continue;
+
+      if (bfd_is_abs_section (sec))
+	continue;
+
+      if (discarded_section (sec))
+	continue;
+
+      s = output_bfd->sections;
+      while (s)
+	{
+	  if (s == sec->output_section)
+	    {
+	      idx = i;
+	      break;
+	    }
+
+	  i++;
+	  s = s->next;
+	}
+
+      bfd_putl16(idx, contents + rel->r_vaddr - input_section->vma);
+    }
+
   return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
 					     input_section, contents,
 					     relocs, syms, sections);
@@ -573,6 +656,8 @@ coff_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 #ifdef COFF_WITH_PE
     case BFD_RELOC_32_SECREL:
       return howto_table + R_SECREL32;
+    case BFD_RELOC_16_SECIDX:
+      return howto_table + R_SECTION;
 #endif
     default:
       BFD_FAIL ();
diff --git a/bfd/coff-x86_64.c b/bfd/coff-x86_64.c
index c2da0f4d1ae..f038c892029 100644
--- a/bfd/coff-x86_64.c
+++ b/bfd/coff-x86_64.c
@@ -225,7 +225,7 @@ static bool
 in_reloc_p (bfd *abfd ATTRIBUTE_UNUSED, reloc_howto_type *howto)
 {
   return ! howto->pc_relative && howto->type != R_AMD64_IMAGEBASE
-	 && howto->type != R_AMD64_SECREL;
+	 && howto->type != R_AMD64_SECREL && howto->type != R_AMD64_SECTION;
 }
 #endif /* COFF_WITH_PE */
 
@@ -356,8 +356,21 @@ static reloc_howto_type howto_table[] =
 	 0xffffffff,		/* src_mask */
 	 0xffffffff,		/* dst_mask */
 	 PCRELOFFSET),		/* pcrel_offset */
-  EMPTY_HOWTO (10), /* R_AMD64_SECTION 10  */
 #if defined(COFF_WITH_PE)
+  /* 16-bit word section relocation (10).  */
+  HOWTO (R_AMD64_SECTION,	/* type */
+	 0,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "IMAGE_REL_AMD64_SECTION", /* name */
+	 true,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 true),
   /* 32-bit longword section relative relocation (11).  */
   HOWTO (R_AMD64_SECREL,	/* type */
 	 0,			/* rightshift */
@@ -373,6 +386,7 @@ static reloc_howto_type howto_table[] =
 	 0xffffffff,		/* dst_mask */
 	 true),			/* pcrel_offset */
 #else
+  EMPTY_HOWTO (10),
   EMPTY_HOWTO (11),
 #endif
   EMPTY_HOWTO (12),
@@ -545,9 +559,9 @@ static reloc_howto_type howto_table[] =
 
 #else /* COFF_WITH_PE */
 
-/* The PE relocate section routine.  The only difference between this
-   and the regular routine is that we don't want to do anything for a
-   relocatable link.  */
+/* The PE relocate section routine.  We handle secidx relocations here,
+ * as well as making sure that we don't do anything for a relocatable
+ * link.  */
 
 static bool
 coff_pe_amd64_relocate_section (bfd *output_bfd,
@@ -559,9 +573,78 @@ coff_pe_amd64_relocate_section (bfd *output_bfd,
 				struct internal_syment *syms,
 				asection **sections)
 {
+  struct internal_reloc *rel;
+  struct internal_reloc *relend;
+
   if (bfd_link_relocatable (info))
     return true;
 
+  rel = relocs;
+  relend = rel + input_section->reloc_count;
+
+  for (; rel < relend; rel++)
+    {
+      long symndx;
+      struct coff_link_hash_entry *h;
+      asection *sec, *s;
+      uint16_t idx = 0, i = 1;
+
+      if (rel->r_type != R_SECTION)
+	continue;
+
+      /* Make sure that _bfd_coff_generic_relocate_section won't parse
+       * this reloc after us */
+      rel->r_type = 0;
+
+      symndx = rel->r_symndx;
+
+      if (symndx < 0
+	  || (unsigned long) symndx >= obj_raw_syment_count (input_bfd))
+	continue;
+
+      h = obj_coff_sym_hashes (input_bfd)[symndx];
+
+      if (h == NULL)
+	sec = sections[symndx];
+      else
+      {
+	if (h->root.type == bfd_link_hash_defined
+	    || h->root.type == bfd_link_hash_defweak)
+	  {
+	    /* Defined weak symbols are a GNU extension. */
+	    sec = h->root.u.def.section;
+	  }
+	else
+	  {
+	    sec = NULL;
+	  }
+      }
+
+      if (!sec)
+	continue;
+
+      if (bfd_is_abs_section (sec))
+	continue;
+
+      if (discarded_section (sec))
+	continue;
+
+      s = output_bfd->sections;
+      while (s)
+	{
+	  if (s == sec->output_section)
+	    {
+	      idx = i;
+	      break;
+	    }
+
+	  i++;
+	  s = s->next;
+	}
+
+      bfd_putl16(idx, contents + rel->r_vaddr - input_section->vma);
+    }
+
   return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,input_section, contents,relocs, syms, sections);
 }
 
@@ -716,6 +799,8 @@ coff_amd64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_ty
 #if defined(COFF_WITH_PE)
     case BFD_RELOC_32_SECREL:
       return howto_table + R_AMD64_SECREL;
+    case BFD_RELOC_16_SECIDX:
+      return howto_table + R_AMD64_SECTION;
 #endif
     default:
       BFD_FAIL ();
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 6e62e556962..8c02e29eebd 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1040,6 +1040,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_12_PCREL",
   "BFD_RELOC_8_PCREL",
   "BFD_RELOC_32_SECREL",
+  "BFD_RELOC_16_SECIDX",
   "BFD_RELOC_32_GOT_PCREL",
   "BFD_RELOC_16_GOT_PCREL",
   "BFD_RELOC_8_GOT_PCREL",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 164060361a9..5098e0ab09f 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -1621,6 +1621,8 @@ the section containing the relocation.  It depends on the specific target.
 
 ENUM
   BFD_RELOC_32_SECREL
+ENUMX
+  BFD_RELOC_16_SECIDX
 ENUMDOC
   Section relative relocations.  Some targets need this for DWARF2.
 
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index e0632681477..30b72db83fa 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -152,6 +152,7 @@ static void set_check (int);
 static void set_cpu_arch (int);
 #ifdef TE_PE
 static void pe_directive_secrel (int);
+static void pe_directive_secidx (int);
 #endif
 static void signed_cons (int);
 static char *output_invalid (int c);
@@ -1389,6 +1390,7 @@ const pseudo_typeS md_pseudo_table[] =
 #endif
 #ifdef TE_PE
   {"secrel32", pe_directive_secrel, 0},
+  {"secidx", pe_directive_secidx, 0},
 #endif
   {0, 0, 0}
 };
@@ -10288,6 +10290,8 @@ x86_cons_fix_new (fragS *frag, unsigned int off, unsigned int len,
       exp->X_op = O_symbol;
       r = BFD_RELOC_32_SECREL;
     }
+  else if (exp->X_op == O_secidx)
+    r = BFD_RELOC_16_SECIDX;
 #endif
 
   fix_new_exp (frag, off, len, exp, 0, r);
@@ -10578,6 +10582,25 @@ pe_directive_secrel (int dummy ATTRIBUTE_UNUSED)
   input_line_pointer--;
   demand_empty_rest_of_line ();
 }
+
+static void
+pe_directive_secidx (int dummy ATTRIBUTE_UNUSED)
+{
+  expressionS exp;
+
+  do
+  {
+    expression (&exp);
+    if (exp.X_op == O_symbol)
+      exp.X_op = O_secidx;
+
+    emit_expr (&exp, 2);
+  }
+  while (*input_line_pointer++ == ',');
+
+  input_line_pointer--;
+  demand_empty_rest_of_line ();
+}
 #endif
 
 /* Handle Vector operations.  */
@@ -14371,6 +14394,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
     case BFD_RELOC_VTABLE_INHERIT:
 #ifdef TE_PE
     case BFD_RELOC_32_SECREL:
+    case BFD_RELOC_16_SECIDX:
 #endif
       code = fixp->fx_r_type;
       break;
diff --git a/gas/expr.c b/gas/expr.c
index 1e97a83f27b..a0b3c338673 100644
--- a/gas/expr.c
+++ b/gas/expr.c
@@ -1524,6 +1524,7 @@ static operator_rankT op_rank[O_max] = {
   0,	/* O_constant */
   0,	/* O_symbol */
   0,	/* O_symbol_rva */
+  0,	/* O_secidx */
   0,	/* O_register */
   0,	/* O_big */
   9,	/* O_uminus */
diff --git a/gas/expr.h b/gas/expr.h
index 3471e7cd572..6cc2cd41e82 100644
--- a/gas/expr.h
+++ b/gas/expr.h
@@ -50,6 +50,8 @@ typedef enum {
   O_symbol,
   /* X_add_symbol + X_add_number - the base address of the image.  */
   O_symbol_rva,
+  /* The section index of X_add_symbol.  */
+  O_secidx,
   /* A register (X_add_number is register number).  */
   O_register,
   /* A big value.  If X_add_number is negative or 0, the value is in
diff --git a/gas/symbols.c b/gas/symbols.c
index 8598792176a..8fdf03034c5 100644
--- a/gas/symbols.c
+++ b/gas/symbols.c
@@ -1366,6 +1366,7 @@ resolve_symbol_value (symbolS *symp)
 
 	case O_symbol:
 	case O_symbol_rva:
+	case O_secidx:
 	  left = resolve_symbol_value (add_symbol);
 	  seg_left = S_GET_SEGMENT (add_symbol);
 	  if (finalize_syms)
@@ -1446,6 +1447,13 @@ resolve_symbol_value (symbolS *symp)
 	      final_val += symp->frag->fr_address + left;
 	      resolved = symbol_resolved_p (add_symbol);
 	      symp->flags.resolving = 0;
+
+	      if (op == O_secidx && seg_left != undefined_section)
+		{
+		  final_val = 0;
+		  break;
+		}
+
 	      goto exit_dont_set_value;
 	    }
 	  else
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index 813a5ba50da..0385362e489 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -702,11 +702,12 @@ if [gas_32_check] then {
 	}
     }
 
-    # This is a PE specific test.
+    # These are PE specific tests.
     if { [istarget "*-*-cygwin*"] || [istarget "*-*-pe"]
 	 || [istarget "*-*-mingw*"]
     } then {
 	run_dump_test "secrel"
+	run_dump_test "secidx"
     }
 
     # Miscellaneous tests.
diff --git a/gas/testsuite/gas/i386/secidx.d b/gas/testsuite/gas/i386/secidx.d
new file mode 100644
index 00000000000..baf299fb7bd
--- /dev/null
+++ b/gas/testsuite/gas/i386/secidx.d
@@ -0,0 +1,40 @@
+#objdump: -rs
+#name: i386 secidx reloc
+
+.*: +file format pe-i386
+
+RELOCATION RECORDS FOR \[\.data\]:
+OFFSET[ 	]+TYPE[ 	]+VALUE 
+0+24 secidx            \.text
+0+27 secidx            \.text
+0+2a secidx            \.text
+0+2d secidx            \.text
+0+3c secidx            \.data
+0+3f secidx            \.data
+0+42 secidx            \.data
+0+45 secidx            \.data
+0+54 secidx            \.rdata
+0+57 secidx            \.rdata
+0+5a secidx            \.rdata
+0+5d secidx            \.rdata
+0+6c secidx            ext24
+0+6f secidx            ext2d
+0+72 secidx            ext36
+0+75 secidx            ext3f
+
+Contents of section \.text:
+ 0000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c  >>>><<<<>>>>><<<
+ 0010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c  >>>>>><<>>>>>>><
+Contents of section \.data:
+ 0000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c  >>>><<<<>>>>><<<
+ 0010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c  >>>>>><<>>>>>>><
+ 0020 3e3e3e3e 00001100 00110000 11000011  >>>>............
+ 0030 3c3c3c3c 3c3c3c3c 3e3e3e3e 00001100  <<<<<<<<>>>>....
+ 0040 00110000 11000011 3c3c3c3c 3c3c3c3c  ........<<<<<<<<
+ 0050 3e3e3e3e 00001100 00110000 11000011  >>>>............
+ 0060 3c3c3c3c 3c3c3c3c 3e3e3e3e 00001100  <<<<<<<<>>>>....
+ 0070 00110000 11000011 3c3c3c3c 3c3c3c3c  ........<<<<<<<<
+Contents of section \.rdata:
+ 0000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c  >>>><<<<>>>>><<<
+ 0010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c  >>>>>><<>>>>>>><
+ 0020 3e3e3e3e 00000000 00000000 00000000  >>>>............
diff --git a/gas/testsuite/gas/i386/secidx.s b/gas/testsuite/gas/i386/secidx.s
new file mode 100644
index 00000000000..7ac1d2c7036
--- /dev/null
+++ b/gas/testsuite/gas/i386/secidx.s
@@ -0,0 +1,79 @@
+.text
+
+	.ascii ">>>>"
+pre04:	.ascii "<<<<"
+	.ascii ">>>>>"
+pre0d:	.ascii "<<<"
+	.ascii ">>>>>>"
+pre16:	.ascii "<<"
+	.ascii ">>>>>>>"
+pre1f:	.ascii "<"
+
+.data
+
+	.ascii ">>>>"
+sam04:	.ascii "<<<<"
+	.ascii ">>>>>"
+sam0d:	.ascii "<<<"
+	.ascii ">>>>>>"
+sam16:	.ascii "<<"
+	.ascii ">>>>>>>"
+sam1f:	.ascii "<"
+
+	.ascii ">>>>"
+	.secidx pre04
+	.byte 0x11
+	.secidx pre0d
+	.byte 0x11
+	.secidx pre16
+	.byte 0x11
+	.secidx pre1f
+	.byte 0x11
+	.ascii "<<<<<<<<"
+
+	.ascii ">>>>"
+	.secidx sam04
+	.byte 0x11
+	.secidx sam0d
+	.byte 0x11
+	.secidx sam16
+	.byte 0x11
+	.secidx sam1f
+	.byte 0x11
+	.ascii "<<<<<<<<"
+
+	.ascii ">>>>"
+	.secidx nex04
+	.byte 0x11
+	.secidx nex0d
+	.byte 0x11
+	.secidx nex16
+	.byte 0x11
+	.secidx nex1f
+	.byte 0x11
+	.ascii "<<<<<<<<"
+
+	.ascii ">>>>"
+	.secidx ext24
+	.byte 0x11
+	.secidx ext2d
+	.byte 0x11
+	.secidx ext36
+	.byte 0x11
+	.secidx ext3f
+	.byte 0x11
+	.ascii "<<<<<<<<"
+
+.section .rdata
+
+	.ascii ">>>>"
+nex04:	.ascii "<<<<"
+	.ascii ">>>>>"
+nex0d:	.ascii "<<<"
+	.ascii ">>>>>>"
+nex16:	.ascii "<<"
+	.ascii ">>>>>>>"
+nex1f:	.ascii "<"
+	.ascii ">>>>"
+
+	.p2align 4,0
diff --git a/include/coff/i386.h b/include/coff/i386.h
index ac6b15955f8..d2f13286cdf 100644
--- a/include/coff/i386.h
+++ b/include/coff/i386.h
@@ -95,6 +95,7 @@ struct external_reloc
 
 #define R_DIR32		 6
 #define R_IMAGEBASE	 7
+#define R_SECTION	10
 #define R_SECREL32	11
 #define R_RELBYTE	15
 #define R_RELWORD	16
diff --git a/include/coff/x86_64.h b/include/coff/x86_64.h
index cddbda1b487..ef9f9bc5c67 100644
--- a/include/coff/x86_64.h
+++ b/include/coff/x86_64.h
@@ -97,6 +97,7 @@ struct external_reloc
 
 #define R_DIR32		 6
 #define R_IMAGEBASE	 7
+#define R_SECTION	10
 #define R_SECREL32	11
 #define R_RELBYTE	15
 #define R_RELWORD	16
diff --git a/ld/testsuite/ld-pe/pe.exp b/ld/testsuite/ld-pe/pe.exp
index f47c7eb2370..413b316f152 100644
--- a/ld/testsuite/ld-pe/pe.exp
+++ b/ld/testsuite/ld-pe/pe.exp
@@ -35,6 +35,8 @@ if {[istarget i*86-*-cygwin*]
       set pe_tests {
 	{".secrel32" "--disable-reloc-section" "" "" {secrel1.s secrel2.s}
 	 {{objdump -s secrel_64.d}} "secrel.x"}
+	{".secidx" "--disable-reloc-section" "" "" {secidx1.s secidx2.s}
+	 {{objdump -s secidx_64.d}} "secidx.x"}
 	{"Empty export table" "" "" "" "exports.s"
 	 {{objdump -p exports64.d}} "exports.dll"}
 	{"TLS directory entry" "" "" "" "tlssec.s"
@@ -44,6 +46,17 @@ if {[istarget i*86-*-cygwin*]
       set pe_tests {
 	{".secrel32" "--disable-auto-import --disable-reloc-section" "" "" {secrel1.s secrel2.s}
 	 {{objdump -s secrel.d}} "secrel.x"}
+	{".secidx" "--disable-auto-import --disable-reloc-section" "" "" {secidx1.s secidx2.s}
+	 {{objdump -s secidx.d}} "secidx.x"}
+	{"Empty export table" "" "" "" "exports.s"
+	 {{objdump -p exports.d}} "exports.dll"}
+	{"TLS directory entry" "" "" "" "tlssec.s"
+	 {{objdump -p tlssec32.d}} "tlssec.dll"}
+      }
+    } elseif {[istarget arm-wince-pe] } {
+      set pe_tests {
+	{".secrel32" "--disable-reloc-section" "" "" {secrel1.s secrel2.s}
+	 {{objdump -s secrel.d}} "secrel.x"}
 	{"Empty export table" "" "" "" "exports.s"
 	 {{objdump -p exports.d}} "exports.dll"}
 	{"TLS directory entry" "" "" "" "tlssec.s"
@@ -53,6 +66,8 @@ if {[istarget i*86-*-cygwin*]
       set pe_tests {
 	{".secrel32" "--disable-reloc-section" "" "" {secrel1.s secrel2.s}
 	 {{objdump -s secrel.d}} "secrel.x"}
+	{".secidx" "--disable-reloc-section" "" "" {secidx1.s secidx2.s}
+	 {{objdump -s secidx.d}} "secidx.x"}
 	{"Empty export table" "" "" "" "exports.s"
 	 {{objdump -p exports.d}} "exports.dll"}
 	{"TLS directory entry" "" "" "" "tlssec.s"
diff --git a/ld/testsuite/ld-pe/secidx.d b/ld/testsuite/ld-pe/secidx.d
new file mode 100644
index 00000000000..20ace36d1ed
--- /dev/null
+++ b/ld/testsuite/ld-pe/secidx.d
@@ -0,0 +1,27 @@
+
+tmpdir/secidx\.x: +file format pei-.*
+
+Contents of section .text:
+ .*1000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c  >>>><<<<>>>>><<<
+ .*1010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c  >>>>>><<>>>>>>><
+ .*1020 3c3c3c3c 3e3e3e3e 3e909090 ffffffff  <<<<>>>>>.......
+ .*1030 00000000 ffffffff 00000000           ............    
+Contents of section .data:
+ .*2000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c  >>>><<<<>>>>><<<
+ .*2010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c  >>>>>><<>>>>>>><
+ .*2020 3e3e3e3e 01001101 00110100 11010011  >>>>............
+ .*2030 3c3c3c3c 3c3c3c3c 3e3e3e3e 02001102  <<<<<<<<>>>>....
+ .*2040 00110200 11020011 3c3c3c3c 3c3c3c3c  ........<<<<<<<<
+ .*2050 3e3e3e3e 03001103 00110300 11030011  >>>>............
+ .*2060 3c3c3c3c 3c3c3c3c 3e3e3e3e 01001102  <<<<<<<<>>>>....
+ .*2070 00110300 113c3c3c 3c3c3c3c 3c000000  .....<<<<<<<<...
+ .*2080 3c3c3c3e 3e3e3e3e 3e000000           <<<>>>>>>...    
+Contents of section .rdata:
+ .*3000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c  >>>><<<<>>>>><<<
+ .*3010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c  >>>>>><<>>>>>>><
+ .*3020 3e3e3e3e 00000000 00000000 00000000  >>>>............
+ .*3030 3c3c3c3e 3e3e3e3e 3e000000           <<<>>>>>>...    
+Contents of section .idata:
+ .*4000 00000000 00000000 00000000 00000000  ................
+ .*4010 00000000                             ....            
+#...
diff --git a/ld/testsuite/ld-pe/secidx1.s b/ld/testsuite/ld-pe/secidx1.s
new file mode 100644
index 00000000000..b562caf26a4
--- /dev/null
+++ b/ld/testsuite/ld-pe/secidx1.s
@@ -0,0 +1,77 @@
+.text
+
+	.ascii ">>>>"
+pre04:	.ascii "<<<<"
+	.ascii ">>>>>"
+pre0d:	.ascii "<<<"
+	.ascii ">>>>>>"
+pre16:	.ascii "<<"
+	.ascii ">>>>>>>"
+pre1f:	.ascii "<"
+
+.data
+
+	.ascii ">>>>"
+sam04:	.ascii "<<<<"
+	.ascii ">>>>>"
+sam0d:	.ascii "<<<"
+	.ascii ">>>>>>"
+sam16:	.ascii "<<"
+	.ascii ">>>>>>>"
+sam1f:	.ascii "<"
+
+	.ascii ">>>>"
+	.secidx pre04
+	.byte 0x11
+	.secidx pre0d
+	.byte 0x11
+	.secidx pre16
+	.byte 0x11
+	.secidx pre1f
+	.byte 0x11
+	.ascii "<<<<<<<<"
+
+	.ascii ">>>>"
+	.secidx sam04
+	.byte 0x11
+	.secidx sam0d
+	.byte 0x11
+	.secidx sam16
+	.byte 0x11
+	.secidx sam1f
+	.byte 0x11
+	.ascii "<<<<<<<<"
+
+	.ascii ">>>>"
+	.secidx nex04
+	.byte 0x11
+	.secidx nex0d
+	.byte 0x11
+	.secidx nex16
+	.byte 0x11
+	.secidx nex1f
+	.byte 0x11
+	.ascii "<<<<<<<<"
+
+	.ascii ">>>>"
+	.secidx ext1
+	.byte 0x11
+	.secidx ext2
+	.byte 0x11
+	.secidx ext3
+	.byte 0x11
+	.ascii "<<<<<<<<"
+
+.section .rdata
+
+	.ascii ">>>>"
+nex04:	.ascii "<<<<"
+	.ascii ">>>>>"
+nex0d:	.ascii "<<<"
+	.ascii ">>>>>>"
+nex16:	.ascii "<<"
+	.ascii ">>>>>>>"
+nex1f:	.ascii "<"
+	.ascii ">>>>"
+
+	.p2align 4,0
diff --git a/ld/testsuite/ld-pe/secidx2.s b/ld/testsuite/ld-pe/secidx2.s
new file mode 100644
index 00000000000..0895bd9282a
--- /dev/null
+++ b/ld/testsuite/ld-pe/secidx2.s
@@ -0,0 +1,17 @@
+.text
+
+.global ext1
+ext1:	.ascii "<<<<"
+	.ascii ">>>>>"
+
+.data
+
+.global ext2
+ext2:	.ascii "<<<"
+	.ascii ">>>>>>"
+
+.section .rdata
+
+.global ext3
+ext3:	.ascii "<<<"
+	.ascii ">>>>>>"
diff --git a/ld/testsuite/ld-pe/secidx_64.d b/ld/testsuite/ld-pe/secidx_64.d
new file mode 100644
index 00000000000..ddf4aec74f9
--- /dev/null
+++ b/ld/testsuite/ld-pe/secidx_64.d
@@ -0,0 +1,27 @@
+
+tmpdir/secidx\.x: +file format pei-.*
+
+Contents of section \.text:
+ .*1000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c  >>>><<<<>>>>><<<
+ .*1010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c  >>>>>><<>>>>>>><
+ .*1020 3c3c3c3c 3e3e3e3e 3e909090 90909090  <<<<>>>>>.......
+ .*1030 ffffffff ffffffff 00000000 00000000  ................
+ .*1040 ffffffff ffffffff 00000000 00000000  ................
+Contents of section \.data:
+ .*2000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c  >>>><<<<>>>>><<<
+ .*2010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c  >>>>>><<>>>>>>><
+ .*2020 3e3e3e3e 01001101 00110100 11010011  >>>>............
+ .*2030 3c3c3c3c 3c3c3c3c 3e3e3e3e 02001102  <<<<<<<<>>>>....
+ .*2040 00110200 11020011 3c3c3c3c 3c3c3c3c  ........<<<<<<<<
+ .*2050 3e3e3e3e 03001103 00110300 11030011  >>>>............
+ .*2060 3c3c3c3c 3c3c3c3c 3e3e3e3e 01001102  <<<<<<<<>>>>....
+ .*2070 00110300 113c3c3c 3c3c3c3c 3c000000  .....<<<<<<<<...
+ .*2080 3c3c3c3e 3e3e3e3e 3e000000 00000000  <<<>>>>>>.......
+Contents of section \.rdata:
+ .*3000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c  >>>><<<<>>>>><<<
+ .*3010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c  >>>>>><<>>>>>>><
+ .*3020 3e3e3e3e 00000000 00000000 00000000  >>>>............
+ .*3030 3c3c3c3e 3e3e3e3e 3e000000 00000000  <<<>>>>>>.......
+Contents of section \.idata:
+ .*4000 00000000 00000000 00000000 00000000  ................
+ .*4010 00000000                             ....            
-- 
2.34.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] Add support for COFF secidx relocations
  2022-04-03 22:07 Mark Harmstone
@ 2022-04-07 13:49 ` Nick Clifton
  0 siblings, 0 replies; 3+ messages in thread
From: Nick Clifton @ 2022-04-07 13:49 UTC (permalink / raw)
  To: Mark Harmstone, binutils

Hi Mark,

> Apologies in advance if I've done anything wrong here, this is my first
> substantive patch to binutils.

Well I am impressed - the patch worked flawlessly and the only thing I had
to change was a couple of very minor code formatting issues.

> I've been working on adding support for Microsoft's PDB debugging format
> to gcc and binutils, and this turned out to be a blocker. This adds
> support for the secidx relocation type in COFF files, which is a two-byte
> index for the section in which a symbol ends up. It also adds support for
> the .secidx pseudo-directive to generate this (the syntax of which is
> cribbed from llvm-mc, which supports this already).

Patch approved and applied.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH] Add support for COFF secidx relocations
@ 2022-04-03 22:07 Mark Harmstone
  2022-04-07 13:49 ` Nick Clifton
  0 siblings, 1 reply; 3+ messages in thread
From: Mark Harmstone @ 2022-04-03 22:07 UTC (permalink / raw)
  To: binutils, mark

Hi all,

Apologies in advance if I've done anything wrong here, this is my first
substantive patch to binutils.

I've been working on adding support for Microsoft's PDB debugging format
to gcc and binutils, and this turned out to be a blocker. This adds
support for the secidx relocation type in COFF files, which is a two-byte
index for the section in which a symbol ends up. It also adds support for
the .secidx pseudo-directive to generate this (the syntax of which is
cribbed from llvm-mc, which supports this already).

Thanks

Mark

---
 bfd/bfd-in2.h                   |  1 +
 bfd/coff-i386.c                 | 95 +++++++++++++++++++++++++++++++--
 bfd/coff-x86_64.c               | 95 +++++++++++++++++++++++++++++++--
 bfd/libbfd.h                    |  1 +
 bfd/reloc.c                     |  2 +
 gas/config/tc-i386.c            | 24 +++++++++
 gas/expr.c                      |  1 +
 gas/expr.h                      |  2 +
 gas/symbols.c                   |  8 +++
 gas/testsuite/gas/i386/i386.exp |  3 +-
 gas/testsuite/gas/i386/secidx.d | 40 ++++++++++++++
 gas/testsuite/gas/i386/secidx.s | 79 +++++++++++++++++++++++++++
 include/coff/i386.h             |  1 +
 include/coff/x86_64.h           |  1 +
 ld/testsuite/ld-pe/pe.exp       | 15 ++++++
 ld/testsuite/ld-pe/secidx.d     | 27 ++++++++++
 ld/testsuite/ld-pe/secidx1.s    | 77 ++++++++++++++++++++++++++
 ld/testsuite/ld-pe/secidx2.s    | 17 ++++++
 ld/testsuite/ld-pe/secidx_64.d  | 27 ++++++++++
 19 files changed, 505 insertions(+), 11 deletions(-)
 create mode 100644 gas/testsuite/gas/i386/secidx.d
 create mode 100644 gas/testsuite/gas/i386/secidx.s
 create mode 100644 ld/testsuite/ld-pe/secidx.d
 create mode 100644 ld/testsuite/ld-pe/secidx1.s
 create mode 100644 ld/testsuite/ld-pe/secidx2.s
 create mode 100644 ld/testsuite/ld-pe/secidx_64.d

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 8e815bab624..23fbaa520e8 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -2235,6 +2235,7 @@ the section containing the relocation.  It depends on the specific target.  */
 
 /* Section relative relocations.  Some targets need this for DWARF2.  */
   BFD_RELOC_32_SECREL,
+  BFD_RELOC_16_SECIDX,
 
 /* For ELF.  */
   BFD_RELOC_32_GOT_PCREL,
diff --git a/bfd/coff-i386.c b/bfd/coff-i386.c
index 0670c5906c2..0664fd344ff 100644
--- a/bfd/coff-i386.c
+++ b/bfd/coff-i386.c
@@ -191,7 +191,7 @@ static bool
 in_reloc_p (bfd *abfd ATTRIBUTE_UNUSED, reloc_howto_type *howto)
 {
   return ! howto->pc_relative && howto->type != R_IMAGEBASE
-	 && howto->type != R_SECREL32;
+	 && howto->type != R_SECREL32 && howto->type != R_SECTION;
 }
 #endif /* COFF_WITH_PE */
 
@@ -236,8 +236,21 @@ static reloc_howto_type howto_table[] =
 	 false),		/* pcrel_offset */
   EMPTY_HOWTO (010),
   EMPTY_HOWTO (011),
-  EMPTY_HOWTO (012),
 #ifdef COFF_WITH_PE
+  /* 16-bit word section relocation (012).  */
+  HOWTO (R_SECTION,		/* type */
+	 0,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 coff_i386_reloc,	/* special_function */
+	 "secidx",		/* name */
+	 true,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
   /* 32-bit longword section relative relocation (013).  */
   HOWTO (R_SECREL32,		/* type */
 	 0,			/* rightshift */
@@ -253,6 +266,7 @@ static reloc_howto_type howto_table[] =
 	 0xffffffff,		/* dst_mask */
 	 true),			/* pcrel_offset */
 #else
+  EMPTY_HOWTO (012),
   EMPTY_HOWTO (013),
 #endif
   EMPTY_HOWTO (014),
@@ -407,9 +421,9 @@ static reloc_howto_type howto_table[] =
 
 #else /* COFF_WITH_PE */
 
-/* The PE relocate section routine.  The only difference between this
-   and the regular routine is that we don't want to do anything for a
-   relocatable link.  */
+/* The PE relocate section routine.  We handle secidx relocations here,
+ * as well as making sure that we don't do anything for a relocatable
+ * link.  */
 
 static bool
 coff_pe_i386_relocate_section (bfd *output_bfd,
@@ -421,9 +435,78 @@ coff_pe_i386_relocate_section (bfd *output_bfd,
 			       struct internal_syment *syms,
 			       asection **sections)
 {
+  struct internal_reloc *rel;
+  struct internal_reloc *relend;
+
   if (bfd_link_relocatable (info))
     return true;
 
+  rel = relocs;
+  relend = rel + input_section->reloc_count;
+
+  for (; rel < relend; rel++)
+    {
+      long symndx;
+      struct coff_link_hash_entry *h;
+      asection *sec, *s;
+      uint16_t idx = 0, i = 1;
+
+      if (rel->r_type != R_SECTION)
+	continue;
+
+      /* Make sure that _bfd_coff_generic_relocate_section won't parse
+       * this reloc after us */
+      rel->r_type = 0;
+
+      symndx = rel->r_symndx;
+
+      if (symndx < 0
+	  || (unsigned long) symndx >= obj_raw_syment_count (input_bfd))
+	continue;
+
+      h = obj_coff_sym_hashes (input_bfd)[symndx];
+
+      if (h == NULL)
+	sec = sections[symndx];
+      else
+      {
+	if (h->root.type == bfd_link_hash_defined
+	    || h->root.type == bfd_link_hash_defweak)
+	  {
+	    /* Defined weak symbols are a GNU extension. */
+	    sec = h->root.u.def.section;
+	  }
+	else
+	  {
+	    sec = NULL;
+	  }
+      }
+
+      if (!sec)
+	continue;
+
+      if (bfd_is_abs_section (sec))
+	continue;
+
+      if (discarded_section (sec))
+	continue;
+
+      s = output_bfd->sections;
+      while (s)
+	{
+	  if (s == sec->output_section)
+	    {
+	      idx = i;
+	      break;
+	    }
+
+	  i++;
+	  s = s->next;
+	}
+
+      bfd_putl16(idx, contents + rel->r_vaddr - input_section->vma);
+    }
+
   return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
 					     input_section, contents,
 					     relocs, syms, sections);
@@ -573,6 +656,8 @@ coff_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 #ifdef COFF_WITH_PE
     case BFD_RELOC_32_SECREL:
       return howto_table + R_SECREL32;
+    case BFD_RELOC_16_SECIDX:
+      return howto_table + R_SECTION;
 #endif
     default:
       BFD_FAIL ();
diff --git a/bfd/coff-x86_64.c b/bfd/coff-x86_64.c
index c2da0f4d1ae..f038c892029 100644
--- a/bfd/coff-x86_64.c
+++ b/bfd/coff-x86_64.c
@@ -225,7 +225,7 @@ static bool
 in_reloc_p (bfd *abfd ATTRIBUTE_UNUSED, reloc_howto_type *howto)
 {
   return ! howto->pc_relative && howto->type != R_AMD64_IMAGEBASE
-	 && howto->type != R_AMD64_SECREL;
+	 && howto->type != R_AMD64_SECREL && howto->type != R_AMD64_SECTION;
 }
 #endif /* COFF_WITH_PE */
 
@@ -356,8 +356,21 @@ static reloc_howto_type howto_table[] =
 	 0xffffffff,		/* src_mask */
 	 0xffffffff,		/* dst_mask */
 	 PCRELOFFSET),		/* pcrel_offset */
-  EMPTY_HOWTO (10), /* R_AMD64_SECTION 10  */
 #if defined(COFF_WITH_PE)
+  /* 16-bit word section relocation (10).  */
+  HOWTO (R_AMD64_SECTION,	/* type */
+	 0,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "IMAGE_REL_AMD64_SECTION", /* name */
+	 true,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 true),
   /* 32-bit longword section relative relocation (11).  */
   HOWTO (R_AMD64_SECREL,	/* type */
 	 0,			/* rightshift */
@@ -373,6 +386,7 @@ static reloc_howto_type howto_table[] =
 	 0xffffffff,		/* dst_mask */
 	 true),			/* pcrel_offset */
 #else
+  EMPTY_HOWTO (10),
   EMPTY_HOWTO (11),
 #endif
   EMPTY_HOWTO (12),
@@ -545,9 +559,9 @@ static reloc_howto_type howto_table[] =
 
 #else /* COFF_WITH_PE */
 
-/* The PE relocate section routine.  The only difference between this
-   and the regular routine is that we don't want to do anything for a
-   relocatable link.  */
+/* The PE relocate section routine.  We handle secidx relocations here,
+ * as well as making sure that we don't do anything for a relocatable
+ * link.  */
 
 static bool
 coff_pe_amd64_relocate_section (bfd *output_bfd,
@@ -559,9 +573,78 @@ coff_pe_amd64_relocate_section (bfd *output_bfd,
 				struct internal_syment *syms,
 				asection **sections)
 {
+  struct internal_reloc *rel;
+  struct internal_reloc *relend;
+
   if (bfd_link_relocatable (info))
     return true;
 
+  rel = relocs;
+  relend = rel + input_section->reloc_count;
+
+  for (; rel < relend; rel++)
+    {
+      long symndx;
+      struct coff_link_hash_entry *h;
+      asection *sec, *s;
+      uint16_t idx = 0, i = 1;
+
+      if (rel->r_type != R_SECTION)
+	continue;
+
+      /* Make sure that _bfd_coff_generic_relocate_section won't parse
+       * this reloc after us */
+      rel->r_type = 0;
+
+      symndx = rel->r_symndx;
+
+      if (symndx < 0
+	  || (unsigned long) symndx >= obj_raw_syment_count (input_bfd))
+	continue;
+
+      h = obj_coff_sym_hashes (input_bfd)[symndx];
+
+      if (h == NULL)
+	sec = sections[symndx];
+      else
+      {
+	if (h->root.type == bfd_link_hash_defined
+	    || h->root.type == bfd_link_hash_defweak)
+	  {
+	    /* Defined weak symbols are a GNU extension. */
+	    sec = h->root.u.def.section;
+	  }
+	else
+	  {
+	    sec = NULL;
+	  }
+      }
+
+      if (!sec)
+	continue;
+
+      if (bfd_is_abs_section (sec))
+	continue;
+
+      if (discarded_section (sec))
+	continue;
+
+      s = output_bfd->sections;
+      while (s)
+	{
+	  if (s == sec->output_section)
+	    {
+	      idx = i;
+	      break;
+	    }
+
+	  i++;
+	  s = s->next;
+	}
+
+      bfd_putl16(idx, contents + rel->r_vaddr - input_section->vma);
+    }
+
   return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,input_section, contents,relocs, syms, sections);
 }
 
@@ -716,6 +799,8 @@ coff_amd64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_ty
 #if defined(COFF_WITH_PE)
     case BFD_RELOC_32_SECREL:
       return howto_table + R_AMD64_SECREL;
+    case BFD_RELOC_16_SECIDX:
+      return howto_table + R_AMD64_SECTION;
 #endif
     default:
       BFD_FAIL ();
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 6e62e556962..8c02e29eebd 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1040,6 +1040,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_12_PCREL",
   "BFD_RELOC_8_PCREL",
   "BFD_RELOC_32_SECREL",
+  "BFD_RELOC_16_SECIDX",
   "BFD_RELOC_32_GOT_PCREL",
   "BFD_RELOC_16_GOT_PCREL",
   "BFD_RELOC_8_GOT_PCREL",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 164060361a9..5098e0ab09f 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -1621,6 +1621,8 @@ the section containing the relocation.  It depends on the specific target.
 
 ENUM
   BFD_RELOC_32_SECREL
+ENUMX
+  BFD_RELOC_16_SECIDX
 ENUMDOC
   Section relative relocations.  Some targets need this for DWARF2.
 
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index e0632681477..30b72db83fa 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -152,6 +152,7 @@ static void set_check (int);
 static void set_cpu_arch (int);
 #ifdef TE_PE
 static void pe_directive_secrel (int);
+static void pe_directive_secidx (int);
 #endif
 static void signed_cons (int);
 static char *output_invalid (int c);
@@ -1389,6 +1390,7 @@ const pseudo_typeS md_pseudo_table[] =
 #endif
 #ifdef TE_PE
   {"secrel32", pe_directive_secrel, 0},
+  {"secidx", pe_directive_secidx, 0},
 #endif
   {0, 0, 0}
 };
@@ -10288,6 +10290,8 @@ x86_cons_fix_new (fragS *frag, unsigned int off, unsigned int len,
       exp->X_op = O_symbol;
       r = BFD_RELOC_32_SECREL;
     }
+  else if (exp->X_op == O_secidx)
+    r = BFD_RELOC_16_SECIDX;
 #endif
 
   fix_new_exp (frag, off, len, exp, 0, r);
@@ -10578,6 +10582,25 @@ pe_directive_secrel (int dummy ATTRIBUTE_UNUSED)
   input_line_pointer--;
   demand_empty_rest_of_line ();
 }
+
+static void
+pe_directive_secidx (int dummy ATTRIBUTE_UNUSED)
+{
+  expressionS exp;
+
+  do
+  {
+    expression (&exp);
+    if (exp.X_op == O_symbol)
+      exp.X_op = O_secidx;
+
+    emit_expr (&exp, 2);
+  }
+  while (*input_line_pointer++ == ',');
+
+  input_line_pointer--;
+  demand_empty_rest_of_line ();
+}
 #endif
 
 /* Handle Vector operations.  */
@@ -14371,6 +14394,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
     case BFD_RELOC_VTABLE_INHERIT:
 #ifdef TE_PE
     case BFD_RELOC_32_SECREL:
+    case BFD_RELOC_16_SECIDX:
 #endif
       code = fixp->fx_r_type;
       break;
diff --git a/gas/expr.c b/gas/expr.c
index 1e97a83f27b..a0b3c338673 100644
--- a/gas/expr.c
+++ b/gas/expr.c
@@ -1524,6 +1524,7 @@ static operator_rankT op_rank[O_max] = {
   0,	/* O_constant */
   0,	/* O_symbol */
   0,	/* O_symbol_rva */
+  0,	/* O_secidx */
   0,	/* O_register */
   0,	/* O_big */
   9,	/* O_uminus */
diff --git a/gas/expr.h b/gas/expr.h
index 3471e7cd572..6cc2cd41e82 100644
--- a/gas/expr.h
+++ b/gas/expr.h
@@ -50,6 +50,8 @@ typedef enum {
   O_symbol,
   /* X_add_symbol + X_add_number - the base address of the image.  */
   O_symbol_rva,
+  /* The section index of X_add_symbol.  */
+  O_secidx,
   /* A register (X_add_number is register number).  */
   O_register,
   /* A big value.  If X_add_number is negative or 0, the value is in
diff --git a/gas/symbols.c b/gas/symbols.c
index 8598792176a..8fdf03034c5 100644
--- a/gas/symbols.c
+++ b/gas/symbols.c
@@ -1366,6 +1366,7 @@ resolve_symbol_value (symbolS *symp)
 
 	case O_symbol:
 	case O_symbol_rva:
+	case O_secidx:
 	  left = resolve_symbol_value (add_symbol);
 	  seg_left = S_GET_SEGMENT (add_symbol);
 	  if (finalize_syms)
@@ -1446,6 +1447,13 @@ resolve_symbol_value (symbolS *symp)
 	      final_val += symp->frag->fr_address + left;
 	      resolved = symbol_resolved_p (add_symbol);
 	      symp->flags.resolving = 0;
+
+	      if (op == O_secidx && seg_left != undefined_section)
+		{
+		  final_val = 0;
+		  break;
+		}
+
 	      goto exit_dont_set_value;
 	    }
 	  else
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index 813a5ba50da..0385362e489 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -702,11 +702,12 @@ if [gas_32_check] then {
 	}
     }
 
-    # This is a PE specific test.
+    # These are PE specific tests.
     if { [istarget "*-*-cygwin*"] || [istarget "*-*-pe"]
 	 || [istarget "*-*-mingw*"]
     } then {
 	run_dump_test "secrel"
+	run_dump_test "secidx"
     }
 
     # Miscellaneous tests.
diff --git a/gas/testsuite/gas/i386/secidx.d b/gas/testsuite/gas/i386/secidx.d
new file mode 100644
index 00000000000..baf299fb7bd
--- /dev/null
+++ b/gas/testsuite/gas/i386/secidx.d
@@ -0,0 +1,40 @@
+#objdump: -rs
+#name: i386 secidx reloc
+
+.*: +file format pe-i386
+
+RELOCATION RECORDS FOR \[\.data\]:
+OFFSET[ 	]+TYPE[ 	]+VALUE 
+0+24 secidx            \.text
+0+27 secidx            \.text
+0+2a secidx            \.text
+0+2d secidx            \.text
+0+3c secidx            \.data
+0+3f secidx            \.data
+0+42 secidx            \.data
+0+45 secidx            \.data
+0+54 secidx            \.rdata
+0+57 secidx            \.rdata
+0+5a secidx            \.rdata
+0+5d secidx            \.rdata
+0+6c secidx            ext24
+0+6f secidx            ext2d
+0+72 secidx            ext36
+0+75 secidx            ext3f
+
+Contents of section \.text:
+ 0000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c  >>>><<<<>>>>><<<
+ 0010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c  >>>>>><<>>>>>>><
+Contents of section \.data:
+ 0000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c  >>>><<<<>>>>><<<
+ 0010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c  >>>>>><<>>>>>>><
+ 0020 3e3e3e3e 00001100 00110000 11000011  >>>>............
+ 0030 3c3c3c3c 3c3c3c3c 3e3e3e3e 00001100  <<<<<<<<>>>>....
+ 0040 00110000 11000011 3c3c3c3c 3c3c3c3c  ........<<<<<<<<
+ 0050 3e3e3e3e 00001100 00110000 11000011  >>>>............
+ 0060 3c3c3c3c 3c3c3c3c 3e3e3e3e 00001100  <<<<<<<<>>>>....
+ 0070 00110000 11000011 3c3c3c3c 3c3c3c3c  ........<<<<<<<<
+Contents of section \.rdata:
+ 0000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c  >>>><<<<>>>>><<<
+ 0010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c  >>>>>><<>>>>>>><
+ 0020 3e3e3e3e 00000000 00000000 00000000  >>>>............
diff --git a/gas/testsuite/gas/i386/secidx.s b/gas/testsuite/gas/i386/secidx.s
new file mode 100644
index 00000000000..7ac1d2c7036
--- /dev/null
+++ b/gas/testsuite/gas/i386/secidx.s
@@ -0,0 +1,79 @@
+.text
+
+	.ascii ">>>>"
+pre04:	.ascii "<<<<"
+	.ascii ">>>>>"
+pre0d:	.ascii "<<<"
+	.ascii ">>>>>>"
+pre16:	.ascii "<<"
+	.ascii ">>>>>>>"
+pre1f:	.ascii "<"
+
+.data
+
+	.ascii ">>>>"
+sam04:	.ascii "<<<<"
+	.ascii ">>>>>"
+sam0d:	.ascii "<<<"
+	.ascii ">>>>>>"
+sam16:	.ascii "<<"
+	.ascii ">>>>>>>"
+sam1f:	.ascii "<"
+
+	.ascii ">>>>"
+	.secidx pre04
+	.byte 0x11
+	.secidx pre0d
+	.byte 0x11
+	.secidx pre16
+	.byte 0x11
+	.secidx pre1f
+	.byte 0x11
+	.ascii "<<<<<<<<"
+
+	.ascii ">>>>"
+	.secidx sam04
+	.byte 0x11
+	.secidx sam0d
+	.byte 0x11
+	.secidx sam16
+	.byte 0x11
+	.secidx sam1f
+	.byte 0x11
+	.ascii "<<<<<<<<"
+
+	.ascii ">>>>"
+	.secidx nex04
+	.byte 0x11
+	.secidx nex0d
+	.byte 0x11
+	.secidx nex16
+	.byte 0x11
+	.secidx nex1f
+	.byte 0x11
+	.ascii "<<<<<<<<"
+
+	.ascii ">>>>"
+	.secidx ext24
+	.byte 0x11
+	.secidx ext2d
+	.byte 0x11
+	.secidx ext36
+	.byte 0x11
+	.secidx ext3f
+	.byte 0x11
+	.ascii "<<<<<<<<"
+
+.section .rdata
+
+	.ascii ">>>>"
+nex04:	.ascii "<<<<"
+	.ascii ">>>>>"
+nex0d:	.ascii "<<<"
+	.ascii ">>>>>>"
+nex16:	.ascii "<<"
+	.ascii ">>>>>>>"
+nex1f:	.ascii "<"
+	.ascii ">>>>"
+
+	.p2align 4,0
diff --git a/include/coff/i386.h b/include/coff/i386.h
index ac6b15955f8..d2f13286cdf 100644
--- a/include/coff/i386.h
+++ b/include/coff/i386.h
@@ -95,6 +95,7 @@ struct external_reloc
 
 #define R_DIR32		 6
 #define R_IMAGEBASE	 7
+#define R_SECTION	10
 #define R_SECREL32	11
 #define R_RELBYTE	15
 #define R_RELWORD	16
diff --git a/include/coff/x86_64.h b/include/coff/x86_64.h
index cddbda1b487..ef9f9bc5c67 100644
--- a/include/coff/x86_64.h
+++ b/include/coff/x86_64.h
@@ -97,6 +97,7 @@ struct external_reloc
 
 #define R_DIR32		 6
 #define R_IMAGEBASE	 7
+#define R_SECTION	10
 #define R_SECREL32	11
 #define R_RELBYTE	15
 #define R_RELWORD	16
diff --git a/ld/testsuite/ld-pe/pe.exp b/ld/testsuite/ld-pe/pe.exp
index f47c7eb2370..413b316f152 100644
--- a/ld/testsuite/ld-pe/pe.exp
+++ b/ld/testsuite/ld-pe/pe.exp
@@ -35,6 +35,8 @@ if {[istarget i*86-*-cygwin*]
       set pe_tests {
 	{".secrel32" "--disable-reloc-section" "" "" {secrel1.s secrel2.s}
 	 {{objdump -s secrel_64.d}} "secrel.x"}
+	{".secidx" "--disable-reloc-section" "" "" {secidx1.s secidx2.s}
+	 {{objdump -s secidx_64.d}} "secidx.x"}
 	{"Empty export table" "" "" "" "exports.s"
 	 {{objdump -p exports64.d}} "exports.dll"}
 	{"TLS directory entry" "" "" "" "tlssec.s"
@@ -44,6 +46,17 @@ if {[istarget i*86-*-cygwin*]
       set pe_tests {
 	{".secrel32" "--disable-auto-import --disable-reloc-section" "" "" {secrel1.s secrel2.s}
 	 {{objdump -s secrel.d}} "secrel.x"}
+	{".secidx" "--disable-auto-import --disable-reloc-section" "" "" {secidx1.s secidx2.s}
+	 {{objdump -s secidx.d}} "secidx.x"}
+	{"Empty export table" "" "" "" "exports.s"
+	 {{objdump -p exports.d}} "exports.dll"}
+	{"TLS directory entry" "" "" "" "tlssec.s"
+	 {{objdump -p tlssec32.d}} "tlssec.dll"}
+      }
+    } elseif {[istarget arm-wince-pe] } {
+      set pe_tests {
+	{".secrel32" "--disable-reloc-section" "" "" {secrel1.s secrel2.s}
+	 {{objdump -s secrel.d}} "secrel.x"}
 	{"Empty export table" "" "" "" "exports.s"
 	 {{objdump -p exports.d}} "exports.dll"}
 	{"TLS directory entry" "" "" "" "tlssec.s"
@@ -53,6 +66,8 @@ if {[istarget i*86-*-cygwin*]
       set pe_tests {
 	{".secrel32" "--disable-reloc-section" "" "" {secrel1.s secrel2.s}
 	 {{objdump -s secrel.d}} "secrel.x"}
+	{".secidx" "--disable-reloc-section" "" "" {secidx1.s secidx2.s}
+	 {{objdump -s secidx.d}} "secidx.x"}
 	{"Empty export table" "" "" "" "exports.s"
 	 {{objdump -p exports.d}} "exports.dll"}
 	{"TLS directory entry" "" "" "" "tlssec.s"
diff --git a/ld/testsuite/ld-pe/secidx.d b/ld/testsuite/ld-pe/secidx.d
new file mode 100644
index 00000000000..20ace36d1ed
--- /dev/null
+++ b/ld/testsuite/ld-pe/secidx.d
@@ -0,0 +1,27 @@
+
+tmpdir/secidx\.x: +file format pei-.*
+
+Contents of section .text:
+ .*1000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c  >>>><<<<>>>>><<<
+ .*1010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c  >>>>>><<>>>>>>><
+ .*1020 3c3c3c3c 3e3e3e3e 3e909090 ffffffff  <<<<>>>>>.......
+ .*1030 00000000 ffffffff 00000000           ............    
+Contents of section .data:
+ .*2000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c  >>>><<<<>>>>><<<
+ .*2010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c  >>>>>><<>>>>>>><
+ .*2020 3e3e3e3e 01001101 00110100 11010011  >>>>............
+ .*2030 3c3c3c3c 3c3c3c3c 3e3e3e3e 02001102  <<<<<<<<>>>>....
+ .*2040 00110200 11020011 3c3c3c3c 3c3c3c3c  ........<<<<<<<<
+ .*2050 3e3e3e3e 03001103 00110300 11030011  >>>>............
+ .*2060 3c3c3c3c 3c3c3c3c 3e3e3e3e 01001102  <<<<<<<<>>>>....
+ .*2070 00110300 113c3c3c 3c3c3c3c 3c000000  .....<<<<<<<<...
+ .*2080 3c3c3c3e 3e3e3e3e 3e000000           <<<>>>>>>...    
+Contents of section .rdata:
+ .*3000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c  >>>><<<<>>>>><<<
+ .*3010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c  >>>>>><<>>>>>>><
+ .*3020 3e3e3e3e 00000000 00000000 00000000  >>>>............
+ .*3030 3c3c3c3e 3e3e3e3e 3e000000           <<<>>>>>>...    
+Contents of section .idata:
+ .*4000 00000000 00000000 00000000 00000000  ................
+ .*4010 00000000                             ....            
+#...
diff --git a/ld/testsuite/ld-pe/secidx1.s b/ld/testsuite/ld-pe/secidx1.s
new file mode 100644
index 00000000000..b562caf26a4
--- /dev/null
+++ b/ld/testsuite/ld-pe/secidx1.s
@@ -0,0 +1,77 @@
+.text
+
+	.ascii ">>>>"
+pre04:	.ascii "<<<<"
+	.ascii ">>>>>"
+pre0d:	.ascii "<<<"
+	.ascii ">>>>>>"
+pre16:	.ascii "<<"
+	.ascii ">>>>>>>"
+pre1f:	.ascii "<"
+
+.data
+
+	.ascii ">>>>"
+sam04:	.ascii "<<<<"
+	.ascii ">>>>>"
+sam0d:	.ascii "<<<"
+	.ascii ">>>>>>"
+sam16:	.ascii "<<"
+	.ascii ">>>>>>>"
+sam1f:	.ascii "<"
+
+	.ascii ">>>>"
+	.secidx pre04
+	.byte 0x11
+	.secidx pre0d
+	.byte 0x11
+	.secidx pre16
+	.byte 0x11
+	.secidx pre1f
+	.byte 0x11
+	.ascii "<<<<<<<<"
+
+	.ascii ">>>>"
+	.secidx sam04
+	.byte 0x11
+	.secidx sam0d
+	.byte 0x11
+	.secidx sam16
+	.byte 0x11
+	.secidx sam1f
+	.byte 0x11
+	.ascii "<<<<<<<<"
+
+	.ascii ">>>>"
+	.secidx nex04
+	.byte 0x11
+	.secidx nex0d
+	.byte 0x11
+	.secidx nex16
+	.byte 0x11
+	.secidx nex1f
+	.byte 0x11
+	.ascii "<<<<<<<<"
+
+	.ascii ">>>>"
+	.secidx ext1
+	.byte 0x11
+	.secidx ext2
+	.byte 0x11
+	.secidx ext3
+	.byte 0x11
+	.ascii "<<<<<<<<"
+
+.section .rdata
+
+	.ascii ">>>>"
+nex04:	.ascii "<<<<"
+	.ascii ">>>>>"
+nex0d:	.ascii "<<<"
+	.ascii ">>>>>>"
+nex16:	.ascii "<<"
+	.ascii ">>>>>>>"
+nex1f:	.ascii "<"
+	.ascii ">>>>"
+
+	.p2align 4,0
diff --git a/ld/testsuite/ld-pe/secidx2.s b/ld/testsuite/ld-pe/secidx2.s
new file mode 100644
index 00000000000..0895bd9282a
--- /dev/null
+++ b/ld/testsuite/ld-pe/secidx2.s
@@ -0,0 +1,17 @@
+.text
+
+.global ext1
+ext1:	.ascii "<<<<"
+	.ascii ">>>>>"
+
+.data
+
+.global ext2
+ext2:	.ascii "<<<"
+	.ascii ">>>>>>"
+
+.section .rdata
+
+.global ext3
+ext3:	.ascii "<<<"
+	.ascii ">>>>>>"
diff --git a/ld/testsuite/ld-pe/secidx_64.d b/ld/testsuite/ld-pe/secidx_64.d
new file mode 100644
index 00000000000..ddf4aec74f9
--- /dev/null
+++ b/ld/testsuite/ld-pe/secidx_64.d
@@ -0,0 +1,27 @@
+
+tmpdir/secidx\.x: +file format pei-.*
+
+Contents of section \.text:
+ .*1000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c  >>>><<<<>>>>><<<
+ .*1010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c  >>>>>><<>>>>>>><
+ .*1020 3c3c3c3c 3e3e3e3e 3e909090 90909090  <<<<>>>>>.......
+ .*1030 ffffffff ffffffff 00000000 00000000  ................
+ .*1040 ffffffff ffffffff 00000000 00000000  ................
+Contents of section \.data:
+ .*2000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c  >>>><<<<>>>>><<<
+ .*2010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c  >>>>>><<>>>>>>><
+ .*2020 3e3e3e3e 01001101 00110100 11010011  >>>>............
+ .*2030 3c3c3c3c 3c3c3c3c 3e3e3e3e 02001102  <<<<<<<<>>>>....
+ .*2040 00110200 11020011 3c3c3c3c 3c3c3c3c  ........<<<<<<<<
+ .*2050 3e3e3e3e 03001103 00110300 11030011  >>>>............
+ .*2060 3c3c3c3c 3c3c3c3c 3e3e3e3e 01001102  <<<<<<<<>>>>....
+ .*2070 00110300 113c3c3c 3c3c3c3c 3c000000  .....<<<<<<<<...
+ .*2080 3c3c3c3e 3e3e3e3e 3e000000 00000000  <<<>>>>>>.......
+Contents of section \.rdata:
+ .*3000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c  >>>><<<<>>>>><<<
+ .*3010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c  >>>>>><<>>>>>>><
+ .*3020 3e3e3e3e 00000000 00000000 00000000  >>>>............
+ .*3030 3c3c3c3e 3e3e3e3e 3e000000 00000000  <<<>>>>>>.......
+Contents of section \.idata:
+ .*4000 00000000 00000000 00000000 00000000  ................
+ .*4010 00000000                             ....            
-- 
2.34.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-04-07 13:49 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-04 11:44 [PATCH] Add support for COFF secidx relocations Mark Harmstone
  -- strict thread matches above, loose matches on Subject: below --
2022-04-03 22:07 Mark Harmstone
2022-04-07 13:49 ` Nick Clifton

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).