From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22322 invoked by alias); 12 Oct 2002 14:04:20 -0000 Mailing-List: contact binutils-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sources.redhat.com Received: (qmail 22313 invoked from network); 12 Oct 2002 14:04:19 -0000 Received: from unknown (HELO mallaury.noc.nerim.net) (62.4.17.82) by sources.redhat.com with SMTP; 12 Oct 2002 14:04:19 -0000 Received: from nerim.fr (stcarrez.net1.nerim.net [62.212.108.40]) by mallaury.noc.nerim.net (Postfix) with ESMTP id 141216312E; Sat, 12 Oct 2002 16:04:16 +0200 (CEST) Message-ID: <3DA847FA.1090805@nerim.fr> Date: Sat, 12 Oct 2002 07:04:00 -0000 From: Stephane Carrez User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.4.1) Gecko/20020508 Netscape6/6.2.3 X-Accept-Language: en-us MIME-Version: 1.0 To: binutils@sources.redhat.com Subject: [PATCH]: Fix [ Bug #1403 ] Branch adjustment to another section not correct when doing linker relaxation Content-Type: multipart/mixed; boundary="------------040400010606030507070308" X-SW-Source: 2002-10/txt/msg00271.txt.bz2 This is a multi-part message in MIME format. --------------040400010606030507070308 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1006 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 * 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. --------------040400010606030507070308 Content-Type: text/plain; name="elf32-m68hc11.c.diffs" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="elf32-m68hc11.c.diffs" Content-length: 4583 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; } } } --------------040400010606030507070308--