public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH]: Fix [ Bug #1403 ] Branch adjustment to another section not correct when doing linker relaxation
@ 2002-10-12  7:04 Stephane Carrez
  0 siblings, 0 replies; only message in thread
From: Stephane Carrez @ 2002-10-12  7:04 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 1006 bytes --]

Hi!

This patch fixes HC11 linker relaxation bug:

[ Bug #1403 ] Branch adjustment to another section not correct when doing linker relaxation
	http://savannah.gnu.org/bugs/?func=detailbug&bug_id=1403&group_id=2424

In the following code:

	.sect .text
	jmp foo
	jmp bar

	.sect .text.foo_bar
foo:	rts
bar: 
rts

The first jmp is relaxed and reduces the section's size by 1.
When we process the second jmp for relax the symbol value of bar is
computed using the old output section offset (it does not yet take
into account the change of size of the current section).  It is necessary
to let the linker re-compute the section offsets before processing
correctly this reloc.  It will be treated during a next relaxation pass.

Committed this patch to fix the bug.

	Stephane

2002-10-12  Stephane Carrez  <stcarrez@nerim.fr>

	* elf32-m68hc11.c (m68hc11_elf_relax_section): Don't treat relocs
	with symbols in other sections if we relaxed something;  the sections
	output offsets must be re-computed before.

[-- Attachment #2: elf32-m68hc11.c.diffs --]
[-- Type: text/plain, Size: 4583 bytes --]

Index: elf32-m68hc11.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-m68hc11.c,v
retrieving revision 1.10
diff -u -p -r1.10 elf32-m68hc11.c
--- elf32-m68hc11.c	12 Oct 2002 13:35:25 -0000	1.10
+++ elf32-m68hc11.c	12 Oct 2002 13:53:10 -0000
@@ -693,6 +693,7 @@ m68hc11_elf_relax_section (abfd, sec, li
       bfd_vma symval;
       bfd_vma value;
       Elf_Internal_Sym *isym;
+      asection *sym_sec;
 
       /* If this isn't something that can be relaxed, then ignore
 	 this reloc.  */
@@ -791,8 +792,6 @@ m68hc11_elf_relax_section (abfd, sec, li
       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
 	{
 	  /* A local symbol.  */
-          asection *sym_sec;
-
 	  isym = isymbuf + ELF32_R_SYM (irel->r_info);
           sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
 	  symval = (isym->st_value
@@ -819,9 +818,11 @@ m68hc11_elf_relax_section (abfd, sec, li
 	      continue;
 	    }
 
+          isym = 0;
+          sym_sec = h->root.u.def.section;
 	  symval = (h->root.u.def.value
-		    + h->root.u.def.section->output_section->vma
-		    + h->root.u.def.section->output_offset);
+		    + sym_sec->output_section->vma
+		    + sym_sec->output_offset);
 	}
 
       if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_GROUP)
@@ -838,6 +839,32 @@ m68hc11_elf_relax_section (abfd, sec, li
           continue;
         }
 
+      /* When we relax some bytes, the size of our section changes.
+         This affects the layout of next input sections that go in our
+         output section.  When the symbol is part of another section that
+         will go in the same output section as the current one, it's
+         final address may now be incorrect (too far).  We must let the
+         linker re-compute all section offsets before processing this
+         reloc.  Code example:
+
+                                Initial             Final
+         .sect .text            section size = 6    section size = 4
+         jmp foo
+         jmp bar
+         .sect .text.foo_bar    output_offset = 6   output_offset = 4
+         foo: rts
+         bar: rts
+
+         If we process the reloc now, the jmp bar is replaced by a
+         relative branch to the initial bar address (output_offset 6).  */
+      if (*again && sym_sec != sec
+          && sym_sec->output_section == sec->output_section)
+        {
+          prev_insn_group = 0;
+          prev_insn_branch = 0;
+          continue;
+        }
+      
       value = symval;
       /* Try to turn a far branch to a near branch.  */
       if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
@@ -883,6 +910,7 @@ m68hc11_elf_relax_section (abfd, sec, li
                                               irel->r_offset - 1, 3);
             }
           prev_insn_branch = 0;
+          *again = true;
         }
 
       /* Try to turn a 16 bit address into a 8 bit page0 address.  */
@@ -904,6 +932,8 @@ m68hc11_elf_relax_section (abfd, sec, li
 
           if (prev_insn_group)
             {
+              unsigned long old_sec_size = sec->_cooked_size;
+              
               /* Note that we've changed the reldection contents, etc.  */
               elf_section_data (sec)->relocs = internal_relocs;
               free_relocs = NULL;
@@ -921,6 +951,8 @@ m68hc11_elf_relax_section (abfd, sec, li
               prev_insn_group = 0;
               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
                                            R_M68HC11_NONE);
+              if (sec->_cooked_size != old_sec_size)
+                *again = true;
               continue;
             }
           
@@ -956,8 +988,7 @@ m68hc11_elf_relax_section (abfd, sec, li
           irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
                                        R_M68HC11_8);
 
-          /* That will change things, so, we should relax again.
-             Note that this is not required, and it may be slow.  */
+          /* That will change things, so, we should relax again.  */
           *again = true;
         }
       else if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_16)
@@ -999,6 +1030,8 @@ m68hc11_elf_relax_section (abfd, sec, li
                                                R_M68HC11_NONE);
                   m68hc11_elf_relax_delete_bytes (abfd, sec,
                                                   irel->r_offset + 1, 1);
+                  /* That will change things, so, we should relax again.  */
+                  *again = true;
                 }
             }
         }

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2002-10-12 14:04 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-10-12  7:04 [PATCH]: Fix [ Bug #1403 ] Branch adjustment to another section not correct when doing linker relaxation Stephane Carrez

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