public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Alan Modra <amodra@gmail.com>
To: binutils@sourceware.org
Cc: "Maciej W. Rozycki" <macro@orcam.me.uk>,
	Chenghua Xu <paul.hua.gm@gmail.com>
Subject: coff-mips refhi list
Date: Sat, 20 May 2023 21:14:46 +0930	[thread overview]
Message-ID: <ZGiyriwnKNKJqiJV@squeak.grove.modra.org> (raw)
In-Reply-To: <ZGix1HLiOB2Vwvhp@squeak.grove.modra.org>

Like "Move mips_hi16_list to mips_elf_section_data" but for coff.
Also makes mips_refhi_reloc and mips_reflo_reloc a little more elegant
in that they now make use of the generic reloc machinery in order to
apply the relocations.

OK?

	* libecoff.h (struct mips_hi): Delete
	(struct mips_h16): New.
	(struct ecoff_tdata): Delete mips_refhi_list.
	(struct ecoff_section_tdata): Put existing gp into a union.
	Add mips_hi16_list.
	* coff-alpha.c (alpha_relocate_section): Adjust section data access.
	* coff-mips.c (mips_refhi_reloc): Delete dead code.  Stash hi reloc
	on ecoff_section_tdata.
	(mips_reflo_reloc): Use new hi16 list.  Apply hi reloc using
	bfd_perform_relocation.
	* ecoff.c (free_mips_hi16_list): New function.
	(_bfd_ecoff_close_and_cleanup): Clear new hi16 list attached to
	sections rather than bfd tdata.

diff --git a/bfd/coff-alpha.c b/bfd/coff-alpha.c
index 45b3f760f55..79bae7a24d4 100644
--- a/bfd/coff-alpha.c
+++ b/bfd/coff-alpha.c
@@ -1422,11 +1422,11 @@ alpha_relocate_section (bfd *output_bfd,
 	  lita_sec->used_by_bfd = lita_sec_data;
 	}
 
-      if (lita_sec_data->gp != 0)
+      if (lita_sec_data->u.gp != 0)
 	{
 	  /* If we already assigned a gp to this section, we better
 	     stick with that value.  */
-	  gp = lita_sec_data->gp;
+	  gp = lita_sec_data->u.gp;
 	}
       else
 	{
@@ -1459,7 +1459,7 @@ alpha_relocate_section (bfd *output_bfd,
 
 	    }
 
-	  lita_sec_data->gp = gp;
+	  lita_sec_data->u.gp = gp;
 	}
 
       _bfd_set_gp_value (output_bfd, gp);
diff --git a/bfd/coff-mips.c b/bfd/coff-mips.c
index fdc0771979d..11b6a064248 100644
--- a/bfd/coff-mips.c
+++ b/bfd/coff-mips.c
@@ -427,17 +427,11 @@ static bfd_reloc_status_type
 mips_refhi_reloc (bfd *abfd,
 		  arelent *reloc_entry,
 		  asymbol *symbol,
-		  void * data,
+		  void *data ATTRIBUTE_UNUSED,
 		  asection *input_section,
 		  bfd *output_bfd,
 		  char **error_message ATTRIBUTE_UNUSED)
 {
-  bfd_reloc_status_type ret;
-  bfd_vma relocation;
-  struct mips_hi *n;
-
-  /* If we're relocating, and this an external symbol, we don't want
-     to change anything.  */
   if (output_bfd != (bfd *) NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
       && reloc_entry->addend == 0)
@@ -446,36 +440,33 @@ mips_refhi_reloc (bfd *abfd,
       return bfd_reloc_ok;
     }
 
-  ret = bfd_reloc_ok;
-  if (bfd_is_und_section (symbol->section)
-      && output_bfd == (bfd *) NULL)
-    ret = bfd_reloc_undefined;
-
-  if (bfd_is_com_section (symbol->section))
-    relocation = 0;
-  else
-    relocation = symbol->value;
-
-  relocation += symbol->section->output_section->vma;
-  relocation += symbol->section->output_offset;
-  relocation += reloc_entry->addend;
-
-  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
-    return bfd_reloc_outofrange;
+  /* Is this the call via bfd_perform_relocation in mips_reflo_reloc?
+     If so, continue and apply the reloc.  */
+  struct ecoff_section_tdata *sdata = input_section->used_by_bfd;
+  if (sdata != NULL
+      && sdata->u.mips_hi16_list != NULL
+      && reloc_entry == &sdata->u.mips_hi16_list->rel)
+    return bfd_reloc_continue;
 
+  if (sdata == NULL)
+    {
+      sdata = bfd_zalloc (abfd, sizeof (*sdata));
+      input_section->used_by_bfd = sdata;
+      if (sdata == NULL)
+	return bfd_reloc_outofrange;
+    }
   /* Save the information, and let REFLO do the actual relocation.  */
-  n = (struct mips_hi *) bfd_malloc ((bfd_size_type) sizeof *n);
+  struct mips_hi16 *n = bfd_malloc (sizeof (*n));
   if (n == NULL)
     return bfd_reloc_outofrange;
-  n->addr = (bfd_byte *) data + reloc_entry->address;
-  n->addend = relocation;
-  n->next = ecoff_data (abfd)->mips_refhi_list;
-  ecoff_data (abfd)->mips_refhi_list = n;
+  n->rel = *reloc_entry;
+  n->next = sdata->u.mips_hi16_list;
+  sdata->u.mips_hi16_list = n;
 
   if (output_bfd != (bfd *) NULL)
     reloc_entry->address += input_section->output_offset;
 
-  return ret;
+  return bfd_reloc_ok;
 }
 
 /* Do a REFLO relocation.  This is a straightforward 16 bit inplace
@@ -491,54 +482,36 @@ mips_reflo_reloc (bfd *abfd,
 		  bfd *output_bfd,
 		  char **error_message)
 {
-  if (ecoff_data (abfd)->mips_refhi_list != NULL)
+  bfd_size_type octets = (reloc_entry->address
+			  * OCTETS_PER_BYTE (abfd, input_section));
+
+  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+				  input_section, octets))
+    return bfd_reloc_outofrange;
+
+  struct ecoff_section_tdata* sdata = input_section->used_by_bfd;
+  if (sdata != NULL && sdata->u.mips_hi16_list != NULL)
     {
-      struct mips_hi *l;
+      struct mips_hi16 *hi;
+      bfd_byte *loc = (bfd_byte *) data + octets;
+      /* Adjustment for the high part addend.  See longer explanation
+	 in elfxx-mips.c _bfd_mips_elf_lo16_reloc.  */
+      bfd_vma vallo = (bfd_get_32 (abfd, loc) & 0x8000) ^ 0x8000;
 
-      l = ecoff_data (abfd)->mips_refhi_list;
-      while (l != NULL)
+      while ((hi = sdata->u.mips_hi16_list) != NULL)
 	{
-	  unsigned long insn;
-	  unsigned long val;
-	  unsigned long vallo;
-	  struct mips_hi *next;
-	  bfd_size_type octets = (reloc_entry->address
-				  * OCTETS_PER_BYTE (abfd, input_section));
-	  bfd_byte *loc = (bfd_byte *) data + octets;
-
-	  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
-					  input_section, octets))
-	    return bfd_reloc_outofrange;
-
-	  /* Do the REFHI relocation.  Note that we actually don't
-	     need to know anything about the REFLO itself, except
-	     where to find the low 16 bits of the addend needed by the
-	     REFHI.  */
-	  insn = bfd_get_32 (abfd, l->addr);
-	  vallo = bfd_get_32 (abfd, loc) & 0xffff;
-	  val = ((insn & 0xffff) << 16) + vallo;
-	  val += l->addend;
-
-	  /* The low order 16 bits are always treated as a signed
-	     value.  Therefore, a negative value in the low order bits
-	     requires an adjustment in the high order bits.  We need
-	     to make this adjustment in two ways: once for the bits we
-	     took from the data, and once for the bits we are putting
-	     back in to the data.  */
-	  if ((vallo & 0x8000) != 0)
-	    val -= 0x10000;
-	  if ((val & 0x8000) != 0)
-	    val += 0x10000;
-
-	  insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff);
-	  bfd_put_32 (abfd, (bfd_vma) insn, l->addr);
-
-	  next = l->next;
-	  free (l);
-	  l = next;
-	}
+	  bfd_reloc_status_type ret;
 
-      ecoff_data (abfd)->mips_refhi_list = NULL;
+	  /* Apply the REFHI relocation.  */
+	  hi->rel.addend += vallo;
+	  ret = bfd_perform_relocation (abfd, &hi->rel, data, input_section,
+					output_bfd, error_message);
+	  if (ret != bfd_reloc_ok)
+	    return ret;
+
+	  sdata->u.mips_hi16_list = hi->next;
+	  free (hi);
+	}
     }
 
   /* Now do the REFLO reloc in the usual way.  */
diff --git a/bfd/ecoff.c b/bfd/ecoff.c
index 676b8d84017..8e3b4585555 100644
--- a/bfd/ecoff.c
+++ b/bfd/ecoff.c
@@ -109,18 +109,40 @@ _bfd_ecoff_mkobject_hook (bfd *abfd, void * filehdr, void * aouthdr)
   return (void *) ecoff;
 }
 
+/* Free the mips_hi16_list attached to S.  Return true if there were
+   unmatched hi16 relocs.  */
+
+static bool
+free_mips_hi16_list (asection *s)
+{
+  struct ecoff_section_tdata* sdata = s->used_by_bfd;
+  if (sdata != NULL)
+    {
+      struct mips_hi16 *hi;
+      struct mips_hi16 **hip = &sdata->u.mips_hi16_list;
+      bool ret = *hip != NULL;
+
+      while ((hi = *hip) != NULL)
+	{
+	  *hip = hi->next;
+	  free (hi);
+	}
+      return ret;
+    }
+  return false;
+}
+
 bool
 _bfd_ecoff_close_and_cleanup (bfd *abfd)
 {
-  struct ecoff_tdata *tdata = ecoff_data (abfd);
-
-  if (tdata != NULL && bfd_get_format (abfd) == bfd_object)
-    while (tdata->mips_refhi_list != NULL)
-      {
-	struct mips_hi *ref = tdata->mips_refhi_list;
-	tdata->mips_refhi_list = ref->next;
-	free (ref);
-      }
+  if (bfd_get_format (abfd) == bfd_object
+      && ecoff_backend (abfd)->arch == bfd_arch_mips)
+    {
+      for (asection *s = abfd->sections; s; s = s->next)
+	if (free_mips_hi16_list (s))
+	  _bfd_error_handler
+	    (_("%pB(%pA): unmatched hi16 reloc"), abfd, s);
+    }
   return _bfd_generic_close_and_cleanup (abfd);
 }
 
diff --git a/bfd/libecoff.h b/bfd/libecoff.h
index 12664b890c4..96649c39e3d 100644
--- a/bfd/libecoff.h
+++ b/bfd/libecoff.h
@@ -80,11 +80,10 @@ struct ecoff_backend_data
   members of the embedded bfd_coff_backend_data struct.  */
 #define ECOFF_NO_LONG_SECTION_NAMES (false), _bfd_ecoff_no_long_sections
 
-struct mips_hi
+struct mips_hi16
 {
-  struct mips_hi *next;
-  bfd_byte *addr;
-  bfd_vma addend;
+  struct mips_hi16 *next;
+  arelent rel;
 };
 
 /* This is the target specific information kept for ECOFF files.  */
@@ -154,9 +153,6 @@ typedef struct ecoff_tdata
      particular ECOFF file.  This is not valid until
      ecoff_compute_section_file_positions is called.  */
   bool rdata_in_text;
-
-  /* Used by coff-mips.c to track REFHI relocs for pairing with REFLO.  */
-  struct mips_hi *mips_refhi_list;
 } ecoff_data_type;
 
 /* Each canonical asymbol really looks like this.  */
@@ -195,13 +191,18 @@ typedef struct ecoff_symbol_struct
 
 struct ecoff_section_tdata
 {
-  /* When producing an executable (i.e., final, non-relocatable link)
-     on the Alpha, we may need to use multiple global pointer values
-     to span the entire .lita section.  In essence, we allow each
-     input .lita section to have its own gp value.  To support this,
-     we need to keep track of the gp values that we picked for each
-     input .lita section . */
-  bfd_vma gp;
+  union
+  {
+    /* When producing an executable (i.e., final, non-relocatable link)
+       on the Alpha, we may need to use multiple global pointer values
+       to span the entire .lita section.  In essence, we allow each
+       input .lita section to have its own gp value.  To support this,
+       we need to keep track of the gp values that we picked for each
+       input .lita section . */
+    bfd_vma gp;
+    /* Used by coff-mips.c to track hi16 relocs.  */
+    struct mips_hi16 *mips_hi16_list;
+  } u;
 };
 
 /* An accessor macro for the ecoff_section_tdata structure.  */

-- 
Alan Modra
Australia Development Lab, IBM

  reply	other threads:[~2023-05-20 11:44 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-06 12:33 Protect mips_hi16_list from fuzzed debug info Alan Modra
2023-02-07 14:11 ` Maciej W. Rozycki
2023-02-08  0:32   ` Alan Modra
2023-02-08 23:28     ` Maciej W. Rozycki
2023-02-09  0:29       ` Alan Modra
2023-02-09  1:26         ` Maciej W. Rozycki
2023-02-09 10:14           ` Alan Modra
2023-02-10 18:13             ` Maciej W. Rozycki
2023-05-20 11:41             ` Alan Modra
2023-05-20 11:44               ` Alan Modra [this message]
2023-05-23 21:19               ` Maciej W. Rozycki
2023-12-19  9:35 mips hi16/lo16 reloc handling Alan Modra
2023-12-19  9:35 ` coff-mips refhi list Alan Modra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ZGiyriwnKNKJqiJV@squeak.grove.modra.org \
    --to=amodra@gmail.com \
    --cc=binutils@sourceware.org \
    --cc=macro@orcam.me.uk \
    --cc=paul.hua.gm@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).