[binutils-gdb] Add support for COFF secidx relocations

Nick Clifton nickc@sourceware.org
Thu Apr 7 13:48:31 GMT 2022


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=145667f8d991932165a70d7c1551620be44e4b4f

commit 145667f8d991932165a70d7c1551620be44e4b4f
Author: Mark Harmstone <mark@harmstone.com>
Date:   Thu Apr 7 14:47:17 2022 +0100

    Add support for COFF secidx relocations
    
    bfd     * coff-i386.c (in_reloc_p): Add R_SECTION.
            (howto_table): Add R_SECTION.
            (coff_pe_i386_relocation_section): Add support for R_SECTION.
            (coff_i386_reloc_type_lookup): Add support for
            BFD_RELOC_16_SECCIDX.
            * coff-x86_64.c (in_reloc_p): Add R_SECTION.
            (howto_table): Add R_SECTION.
            (coff_pe_amd64_relocation_section): Add support for R_SECTION.
            (coff_amd64_reloc_type_lookup): Add support for
            BFD_RELOC_16_SECCIDX.
            * reloc.c: Add BFD_RELOC_16_SECIDX.
            * bfd-in2.h: Regenerate.
            * libbfd.h: Regenerate.
    
    gas     * config/tc-i386.c (pe_directive_secidx): New function.
            (md_pseudo_table): Add support for secidx.
            (x86_cons_fix_new): Likewise.
            (tc_gen_reloc): Likewise.
            * expr.c (op_rank): Add O_secidx.
            * expr.h (operatorT): Likewise.
            * symbols.c (resolve_symbol_value): Add support for O_secidx.
            * testsuite/gas/i386/secidx.s: New test source file.
            * testsuite/gas/i386/secidx.d: New test driver file.
            * testsuite/gas/i386/i386.exp: Run new test.
    
    include * coff/i386.h: Define R_SECTION.
            * coff/x86_64.h: Likewise.
    
    ld      * testsuite/ld-pe/secidx1.s: New test source file.
            * testsuite/ld-pe/secidx2.s: New test source file.
            * testsuite/ld-pe/secidx.d: New test driver file.
            * testsuite/ld-pe/secidx_64.d: New test driver file.
            * testsuite/ld-pe/pe.exp: Add new tests.

Diff:
---
 bfd/ChangeLog                   | 16 +++++++
 bfd/bfd-in2.h                   |  1 +
 bfd/coff-i386.c                 | 99 ++++++++++++++++++++++++++++++++++++++---
 bfd/coff-x86_64.c               | 99 ++++++++++++++++++++++++++++++++++++++---
 bfd/libbfd.h                    |  1 +
 bfd/reloc.c                     |  2 +
 gas/ChangeLog                   | 13 ++++++
 gas/config/tc-i386.c            | 31 ++++++++++++-
 gas/expr.c                      |  1 +
 gas/expr.h                      | 40 ++++++++---------
 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/ChangeLog               |  5 +++
 include/coff/i386.h             |  1 +
 include/coff/x86_64.h           |  1 +
 ld/ChangeLog                    |  8 ++++
 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 +++++++++++
 23 files changed, 576 insertions(+), 35 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 98f0bab4211..5b532580041 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,19 @@
+2022-04-07  Mark Harmstone  <mark@harmstone.com>
+
+	* coff-i386.c (in_reloc_p): Add R_SECTION.
+	(howto_table): Add R_SECTION.
+	(coff_pe_i386_relocation_section): Add support for R_SECTION.
+	(coff_i386_reloc_type_lookup): Add support for
+	BFD_RELOC_16_SECCIDX.
+	* coff-x86_64.c (in_reloc_p): Add R_SECTION.
+	(howto_table): Add R_SECTION.
+	(coff_pe_amd64_relocation_section): Add support for R_SECTION.
+	(coff_amd64_reloc_type_lookup): Add support for
+	BFD_RELOC_16_SECCIDX.
+	* reloc.c: Add BFD_RELOC_16_SECIDX.
+	* bfd-in2.h: Regenerate.
+	* libbfd.h: Regenerate.
+
 2022-04-01  John Baldwin  <jhb@FreeBSD.org>
 
 	* elf-bfd.h (elfcore_write_x86_segbases): New.
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 404dae2eba5..eb3b79e0bfe 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -2229,6 +2229,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..32a499384b7 100644
--- a/bfd/coff-i386.c
+++ b/bfd/coff-i386.c
@@ -190,8 +190,10 @@ coff_i386_reloc (bfd *abfd,
 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;
+  return ! howto->pc_relative
+    && howto->type != R_IMAGEBASE
+    && howto->type != R_SECREL32
+    && howto->type != R_SECTION;
 }
 #endif /* COFF_WITH_PE */
 
@@ -236,8 +238,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 +268,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 +423,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 +437,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 +658,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..e8e16d3ce4b 100644
--- a/bfd/coff-x86_64.c
+++ b/bfd/coff-x86_64.c
@@ -224,8 +224,10 @@ coff_amd64_reloc (bfd *abfd,
 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;
+  return ! howto->pc_relative
+    && howto->type != R_AMD64_IMAGEBASE
+    && howto->type != R_AMD64_SECREL
+    && howto->type != R_AMD64_SECTION;
 }
 #endif /* COFF_WITH_PE */
 
@@ -356,8 +358,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 +388,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 +561,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 +575,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 +801,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/ChangeLog b/gas/ChangeLog
index 54abdfb5784..63fcc53bf70 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,16 @@
+2022-04-07  Mark Harmstone  <mark@harmstone.com>
+
+	* config/tc-i386.c (pe_directive_secidx): New function.
+	(md_pseudo_table): Add support for secidx.
+	(x86_cons_fix_new): Likewise.
+	(tc_gen_reloc): Likewise.
+	* expr.c (op_rank): Add O_secidx.
+	* expr.h (operatorT): Likewise.
+	* symbols.c (resolve_symbol_value): Add support for O_secidx.
+	* testsuite/gas/i386/secidx.s: New test source file.
+	* testsuite/gas/i386/secidx.d: New test driver file.
+	* testsuite/gas/i386/i386.exp: Run new test.
+
 2022-04-07  Andreas Krebbel  <krebbel@linux.ibm.com>
 
 	* config/tc-s390.c (s390_parse_cpu): Add z16 as alternate CPU
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 76177924d39..c2678ea10cc 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);
@@ -1385,6 +1386,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}
 };
@@ -10267,6 +10269,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);
@@ -10306,13 +10310,16 @@ lex_got (enum bfd_reloc_code_real *rel,
      we don't yet know the operand size (this will be set by insn
      matching).  Hence we record the word32 relocation here,
      and adjust the reloc according to the real size in reloc().  */
-  static const struct {
+  static const struct
+  {
     const char *str;
     int len;
     const enum bfd_reloc_code_real rel[2];
     const i386_operand_type types64;
     bool need_GOT_symbol;
-  } gotrel[] = {
+  }
+    gotrel[] =
+  {
 #ifndef TE_PE
 #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
     { STRING_COMMA_LEN ("SIZE"),      { BFD_RELOC_SIZE32,
@@ -10557,6 +10564,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.  */
@@ -14359,6 +14385,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 2341343bf00..6ad8bee2733 100644
--- a/gas/expr.c
+++ b/gas/expr.c
@@ -1522,6 +1522,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..dff40857427 100644
--- a/gas/expr.h
+++ b/gas/expr.h
@@ -18,28 +18,27 @@
    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
    02110-1301, USA.  */
 
-/*
- * By popular demand, we define a struct to represent an expression.
- * This will no doubt mutate as expressions become baroque.
- *
- * Currently, we support expressions like "foo OP bar + 42".  In other
- * words we permit a (possibly undefined) symbol, a (possibly
- * undefined) symbol and the operation used to combine the symbols,
- * and an (absolute) augend.  RMS says this is so we can have 1-pass
- * assembly for any compiler emissions, and a 'case' statement might
- * emit 'undefined1 - undefined2'.
- *
- * The type of an expression used to be stored as a segment.  That got
- * confusing because it overloaded the concept of a segment.  I added
- * an operator field, instead.
- */
+/* By popular demand, we define a struct to represent an expression.
+   This will no doubt mutate as expressions become baroque.
+
+   Currently, we support expressions like "foo OP bar + 42".  In other
+   words we permit a (possibly undefined) symbol, a (possibly
+   undefined) symbol and the operation used to combine the symbols,
+   and an (absolute) augend.  RMS says this is so we can have 1-pass
+   assembly for any compiler emissions, and a 'case' statement might
+   emit 'undefined1 - undefined2'.
+
+   The type of an expression used to be stored as a segment.  That got
+   confusing because it overloaded the concept of a segment.  I added
+   an operator field, instead.  */
 
 /* This is the type of an expression.  The operator types are also
    used while parsing an expression.
 
    NOTE: This enumeration must match the op_rank array in expr.c.  */
 
-typedef enum {
+typedef enum
+{
   /* An illegal expression.  */
   O_illegal,
   /* A nonexistent expression.  */
@@ -50,6 +49,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
@@ -112,7 +113,8 @@ typedef enum {
   O_max
 } operatorT;
 
-typedef struct expressionS {
+typedef struct expressionS
+{
   /* The main symbol.  */
   symbolS *X_add_symbol;
   /* The second symbol, if needed.  */
@@ -182,12 +184,10 @@ extern unsigned int get_single_number (void);
 extern symbolS *make_expr_symbol (expressionS * expressionP);
 extern int expr_symbol_where (symbolS *, const char **, unsigned int *);
 extern void current_location (expressionS *);
-
 extern symbolS *expr_build_uconstant (offsetT);
 extern symbolS *expr_build_dot (void);
 extern uint32_t generic_bignum_to_int32 (void);
 extern uint64_t generic_bignum_to_int64 (void);
-
-int resolve_expression (expressionS *);
+extern int resolve_expression (expressionS *);
 
 extern bool literal_prefix_dollar_hex;
diff --git a/gas/symbols.c b/gas/symbols.c
index b35c6d25aca..fb480be6f21 100644
--- a/gas/symbols.c
+++ b/gas/symbols.c
@@ -1364,6 +1364,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)
@@ -1444,6 +1445,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 96356d3eb11..2c84ccc62b4 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -703,11 +703,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/ChangeLog b/include/ChangeLog
index 502fc47c148..c40136eb520 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,8 @@
+2022-04-07  Mark Harmstone  <mark@harmstone.com>
+
+	* coff/i386.h: Define R_SECTION.
+	* coff/x86_64.h: Likewise.
+
 2022-04-01  John Baldwin  <jhb@FreeBSD.org>
 
 	* elf/common.h (NT_FREEBSD_X86_SEGBASES): Define.
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/ChangeLog b/ld/ChangeLog
index 7fb9f5d20b1..1538f42516c 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,11 @@
+2022-04-07  Mark Harmstone  <mark@harmstone.com>
+
+	* testsuite/ld-pe/secidx1.s: New test source file.
+	* testsuite/ld-pe/secidx2.s: New test source file.
+	* testsuite/ld-pe/secidx.d: New test driver file.
+	* testsuite/ld-pe/secidx_64.d: New test driver file.
+	* testsuite/ld-pe/pe.exp: Add new tests.
+
 2022-03-01  Nick Clifton  <nickc@redhat.com>
 
 	PR 21964
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                             ....


More information about the Binutils-cvs mailing list