public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* reloc_count problem in the linker
@ 2003-03-18 14:28 Jakub Jelinek
  2003-03-19  9:28 ` [PATCH] " Jakub Jelinek
  2003-03-19  9:36 ` Alan Modra
  0 siblings, 2 replies; 3+ messages in thread
From: Jakub Jelinek @ 2003-03-18 14:28 UTC (permalink / raw)
  To: binutils

Hi!

I'm seeing linker segfault on sparc64 (and I suppose
mips64 can have the same problems) when linking tst-ildouble test.
The problem seems to be that in bfd, there are 2 different reloc reading
APIs, _bfd_elfNN_link_read_relocs which stores the relocations in
elf_section_data (sec)->relocs array and their count into sec->reloc_count
and bfd_canonicalize_reloc which stores the relocations in sec->relocation
and their count into sec->reloc_count.
The problem is on arches where the two counts might not be equal (this
happens when one external relocation consists of more than one internal
relocations). elf_section_data (sec)->relocs correspond 1:1 with
the external relocs but the canonicalized relocs don't, e.g. sparc64
R_SPARC_OLO10 relocation is canonicalized to R_SPARC_LO10 + R_SPARC_13.
Linker mostly uses the first variant while other tools (objdump,
strip, etc.) mostly use the canonicalized relocs, but when linker emits
a warning, warning_find_reloc calls bfd_canonicalize_reloc
and if elf_section_data (sec)->relocs is already non-NULL,
bfd_canonicalize_reloc changes reloc_count so it no longer matches size
of ->relocs array (and thus linker reads past the end of the array).

What do you think would be best fix for this?
From brief looking at where bfd_canonizalize_reloc is used in the linker
it seems to me like it really doesn't require canonicalized reloc, so maybe
there could be another bfd routine which would get relocs in the same
form as bfd_canonizalize_reloc, but wouldn't actually guarantee their
canonizalization. Alternatively, there could be a routine which would return
just one arelent for abfd, sec, symbol_name tripplet (that's what both
ldmain.c and ldcref.c need apparently).

	Jakub

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

* [PATCH] reloc_count problem in the linker
  2003-03-18 14:28 reloc_count problem in the linker Jakub Jelinek
@ 2003-03-19  9:28 ` Jakub Jelinek
  2003-03-19  9:36 ` Alan Modra
  1 sibling, 0 replies; 3+ messages in thread
From: Jakub Jelinek @ 2003-03-19  9:28 UTC (permalink / raw)
  To: binutils

On Tue, Mar 18, 2003 at 03:28:15PM +0100, Jakub Jelinek wrote:
> I'm seeing linker segfault on sparc64 (and I suppose
> mips64 can have the same problems) when linking tst-ildouble test.
> The problem seems to be that in bfd, there are 2 different reloc reading
> APIs, _bfd_elfNN_link_read_relocs which stores the relocations in
> elf_section_data (sec)->relocs array and their count into sec->reloc_count
> and bfd_canonicalize_reloc which stores the relocations in sec->relocation
> and their count into sec->reloc_count.

Fixed thusly:

2003-03-19  Jakub Jelinek  <jakub@redhat.com>

	* elf64-sparc.c (struct sparc64_elf_section_data): Add reloc_count
	field.
	(canon_reloc_count): Define.
	(sparc64_elf_slurp_one_reloc_table, sparc64_elf_slurp_reloc_table,
	sparc64_elf_canonicalize_dynamic_reloc): Use it instead of
	reloc_count.
	(sparc64_elf_canonicalize_reloc): New routine.
	(bfd_elf64_canonicalize_reloc): Define.

--- bfd/elf64-sparc.c.jj	2003-02-22 15:46:41.000000000 -0500
+++ bfd/elf64-sparc.c	2003-03-18 19:20:50.000000000 -0500
@@ -96,6 +96,8 @@ static bfd_boolean sparc64_elf_slurp_one
   PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, asymbol **, bfd_boolean));
 static bfd_boolean sparc64_elf_slurp_reloc_table
   PARAMS ((bfd *, asection *, asymbol **, bfd_boolean));
+static long sparc64_elf_canonicalize_reloc
+  PARAMS ((bfd *, asection *, arelent **, asymbol **));
 static long sparc64_elf_canonicalize_dynamic_reloc
   PARAMS ((bfd *, arelent **, asymbol **));
 static void sparc64_elf_write_relocs PARAMS ((bfd *, asection *, PTR));
@@ -311,6 +313,17 @@ sparc64_elf_info_to_howto (abfd, cache_p
   cache_ptr->howto = &sparc64_elf_howto_table[ELF64_R_TYPE_ID (dst->r_info)];
 }
 \f
+struct sparc64_elf_section_data
+{
+  struct bfd_elf_section_data elf;
+  unsigned int do_relax, reloc_count;
+};
+
+#define sec_do_relax(sec) \
+  ((struct sparc64_elf_section_data *) elf_section_data (sec))->do_relax
+#define canon_reloc_count(sec) \
+  ((struct sparc64_elf_section_data *) elf_section_data (sec))->reloc_count
+
 /* Due to the way how we handle R_SPARC_OLO10, each entry in a SHT_RELA
    section can represent up to two relocs, we must tell the user to allocate
    more space.  */
@@ -361,7 +374,7 @@ sparc64_elf_slurp_one_reloc_table (abfd,
 
   native_relocs = (bfd_byte *) allocated;
 
-  relents = asect->relocation + asect->reloc_count;
+  relents = asect->relocation + canon_reloc_count (asect);
 
   entsize = rel_hdr->sh_entsize;
   BFD_ASSERT (entsize == sizeof (Elf64_External_Rela));
@@ -416,7 +429,7 @@ sparc64_elf_slurp_one_reloc_table (abfd,
 	relent->howto = &sparc64_elf_howto_table[ELF64_R_TYPE_ID (rela.r_info)];
     }
 
-  asect->reloc_count += relent - relents;
+  canon_reloc_count (asect) += relent - relents;
 
   if (allocated != NULL)
     free (allocated);
@@ -478,8 +491,9 @@ sparc64_elf_slurp_reloc_table (abfd, ase
   if (asect->relocation == NULL)
     return FALSE;
 
-  /* The sparc64_elf_slurp_one_reloc_table routine increments reloc_count.  */
-  asect->reloc_count = 0;
+  /* The sparc64_elf_slurp_one_reloc_table routine increments
+     canon_reloc_count.  */
+  canon_reloc_count (asect) = 0;
 
   if (!sparc64_elf_slurp_one_reloc_table (abfd, asect, rel_hdr, symbols,
 					  dynamic))
@@ -493,6 +507,32 @@ sparc64_elf_slurp_reloc_table (abfd, ase
   return TRUE;
 }
 
+/* Canonicalize the relocs.  */
+
+static long
+sparc64_elf_canonicalize_reloc (abfd, section, relptr, symbols)
+     bfd *abfd;
+     sec_ptr section;
+     arelent **relptr;
+     asymbol **symbols;
+{
+  arelent *tblptr;
+  unsigned int i;
+  struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+  if (! bed->s->slurp_reloc_table (abfd, section, symbols, FALSE))
+    return -1;
+
+  tblptr = section->relocation;
+  for (i = 0; i < canon_reloc_count (section); i++)
+    *relptr++ = tblptr++;
+
+  *relptr = NULL;
+
+  return canon_reloc_count (section);
+}
+
+
 /* Canonicalize the dynamic relocation entries.  Note that we return
    the dynamic relocations as a single block, although they are
    actually associated with particular sections; the interface, which
@@ -528,7 +568,7 @@ sparc64_elf_canonicalize_dynamic_reloc (
 
 	  if (! sparc64_elf_slurp_reloc_table (abfd, s, syms, TRUE))
 	    return -1;
-	  count = s->reloc_count;
+	  count = canon_reloc_count (s);
 	  p = s->relocation;
 	  for (i = 0; i < count; i++)
 	    *storage++ = p++;
@@ -1918,15 +1958,6 @@ sparc64_elf_size_dynamic_sections (outpu
   return TRUE;
 }
 \f
-struct sparc64_elf_section_data
-{
-  struct bfd_elf_section_data elf;
-  unsigned int do_relax;
-};
-
-#define sec_do_relax(sec) \
-  ((struct sparc64_elf_section_data *) elf_section_data (sec))->do_relax
-
 static bfd_boolean
 sparc64_elf_new_section_hook (abfd, sec)
      bfd *abfd;
@@ -3177,6 +3208,8 @@ const struct elf_size_info sparc64_elf_s
   sparc64_elf_get_reloc_upper_bound
 #define bfd_elf64_get_dynamic_reloc_upper_bound \
   sparc64_elf_get_dynamic_reloc_upper_bound
+#define bfd_elf64_canonicalize_reloc \
+  sparc64_elf_canonicalize_reloc
 #define bfd_elf64_canonicalize_dynamic_reloc \
   sparc64_elf_canonicalize_dynamic_reloc
 #define bfd_elf64_bfd_reloc_type_lookup \


	Jakub

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

* Re: reloc_count problem in the linker
  2003-03-18 14:28 reloc_count problem in the linker Jakub Jelinek
  2003-03-19  9:28 ` [PATCH] " Jakub Jelinek
@ 2003-03-19  9:36 ` Alan Modra
  1 sibling, 0 replies; 3+ messages in thread
From: Alan Modra @ 2003-03-19  9:36 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: binutils

On Tue, Mar 18, 2003 at 03:28:15PM +0100, Jakub Jelinek wrote:
> APIs, _bfd_elfNN_link_read_relocs which stores the relocations in
> elf_section_data (sec)->relocs array and their count into sec->reloc_count
> and bfd_canonicalize_reloc which stores the relocations in sec->relocation
> and their count into sec->reloc_count.

Stop using sec->reloc_count for ELF relocs, perhaps.  We already
have elf_section_data(sec)->rel_count and
elf_section_data(sec)->rel_count2

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

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

end of thread, other threads:[~2003-03-19  9:36 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-03-18 14:28 reloc_count problem in the linker Jakub Jelinek
2003-03-19  9:28 ` [PATCH] " Jakub Jelinek
2003-03-19  9:36 ` Alan Modra

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