From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19415 invoked by alias); 23 Oct 2006 02:35:09 -0000 Received: (qmail 19396 invoked by uid 22791); 23 Oct 2006 02:35:07 -0000 X-Spam-Check-By: sourceware.org Received: from omta04sl.mx.bigpond.com (HELO omta04sl.mx.bigpond.com) (144.140.93.156) by sourceware.org (qpsmtpd/0.31) with ESMTP; Mon, 23 Oct 2006 02:34:54 +0000 Received: from bubble.grove.modra.org ([60.226.236.165]) by omta04sl.mx.bigpond.com with ESMTP id <20061023023450.NSBG11279.omta04sl.mx.bigpond.com@bubble.grove.modra.org>; Mon, 23 Oct 2006 02:34:50 +0000 Received: by bubble.grove.modra.org (Postfix, from userid 500) id E9BC62A3828; Mon, 23 Oct 2006 12:05:46 +0930 (CST) Date: Mon, 23 Oct 2006 14:13:00 -0000 From: Alan Modra To: Jakub Jelinek Cc: binutils@sources.redhat.com Subject: Re: Dynamic section symbols, ignored output sections Message-ID: <20061023023546.GC2713@bubble.grove.modra.org> Mail-Followup-To: Jakub Jelinek , binutils@sources.redhat.com References: <20060926232851.GB1534@bubble.grove.modra.org> <200609281742.31472.paul@codesourcery.com> <20060928165251.GA20383@lucon.org> <20061010163423.GJ4556@sunsite.mff.cuni.cz> <20061010231922.GK4556@sunsite.mff.cuni.cz> <20061011035305.GA19554@bubble.grove.modra.org> <20061011071125.GL4556@sunsite.mff.cuni.cz> <20061012034341.GA20843@bubble.grove.modra.org> <20061017132427.GE20843@bubble.grove.modra.org> <20061021194154.GL5868@sunsite.mff.cuni.cz> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20061021194154.GL5868@sunsite.mff.cuni.cz> User-Agent: Mutt/1.5.9i X-IsSubscribed: yes Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org X-SW-Source: 2006-10/txt/msg00252.txt.bz2 On Sat, Oct 21, 2006 at 09:41:54PM +0200, Jakub Jelinek wrote: > On Tue, Oct 17, 2006 at 10:54:27PM +0930, Alan Modra wrote: > > This patch does all of the above, plus adjusts the ld testsuite for > > the changes. > > Thanks a lot for this, seems to work fine here. > > Only a minor nit, IMHO using the preceeding section isn't always > the best choice. Yes, I was lazy. > E.g. .init_array etc. sections usually start the > RW segment (unless there is .tdata or .tbss) and those are often zero sized, > yet contain __init_array_{start,end} etc. symbols. With current CVS > binutils those symbols are attached to the preceeding section, which > is typically in the RX segment many KBs/MBs away, while there is > usually a section right after the removed .init_array which is kept. > The following patch prefers to use the next section if symbol's value > is not within the preceeding section (or equal to its end) and if > there is a following section that starts at vma equal to symbol value. > Is this ok for trunk or do you prefer to always choose the preceeding > section? Hmm. I prefer something different. :-) What we really want is to choose a section in the same segment as the removed section would have been if it was kept. Also, I think it a good idea to avoid changing a symbol from a TLS section to non-TLS and vice versa. We can make a reasonable guess about section to segment mapping from the section flags. * linker.c (fix_syms): Choose best of previous and next section based on section flags and vma. Index: bfd/linker.c =================================================================== RCS file: /cvs/src/src/bfd/linker.c,v retrieving revision 1.55 diff -u -p -r1.55 linker.c --- bfd/linker.c 17 Oct 2006 13:41:47 -0000 1.55 +++ bfd/linker.c 23 Oct 2006 02:32:09 -0000 @@ -3092,25 +3092,62 @@ fix_syms (struct bfd_link_hash_entry *h, && (s->output_section->flags & SEC_EXCLUDE) != 0 && bfd_section_removed_from_list (obfd, s->output_section)) { - asection *op; - for (op = s->output_section->prev; op != NULL; op = op->prev) + asection *op, *op1; + + h->u.def.value += s->output_offset + s->output_section->vma; + + /* Find preceding kept section. */ + for (op1 = s->output_section->prev; op1 != NULL; op1 = op1->prev) + if ((op1->flags & SEC_EXCLUDE) == 0 + && !bfd_section_removed_from_list (obfd, op1)) + break; + + /* Find following kept section. Start at prev->next because + other sections may have been added after S was removed. */ + if (s->output_section->prev != NULL) + op = s->output_section->prev->next; + else + op = s->output_section->owner->sections; + for (; op != NULL; op = op->next) if ((op->flags & SEC_EXCLUDE) == 0 && !bfd_section_removed_from_list (obfd, op)) break; - if (op == NULL) + + /* Choose better of two sections, based on flags. The idea + is to choose a section that will be in the same segment + as S would have been if it was kept. */ + if (op1 == NULL) { - if (s->output_section->prev != NULL) - op = s->output_section->prev->next; - else - op = s->output_section->owner->sections; - for (; op != NULL; op = op->next) - if ((op->flags & SEC_EXCLUDE) == 0 - && !bfd_section_removed_from_list (obfd, op)) - break; if (op == NULL) op = bfd_abs_section_ptr; } - h->u.def.value += s->output_offset + s->output_section->vma; + else if (op == NULL) + op = op1; + else if (((op1->flags ^ op->flags) + & (SEC_ALLOC | SEC_THREAD_LOCAL)) != 0) + { + if (((op->flags ^ s->flags) + & (SEC_ALLOC | SEC_THREAD_LOCAL)) != 0) + op = op1; + } + else if (((op1->flags ^ op->flags) & SEC_READONLY) != 0) + { + if (((op->flags ^ s->flags) & SEC_READONLY) != 0) + op = op1; + } + else if (((op1->flags ^ op->flags) & SEC_CODE) != 0) + { + if (((op->flags ^ s->flags) & SEC_CODE) != 0) + op = op1; + } + else + { + /* Flags we care about are the same. Prefer the following + section if that will result in a positive valued sym. */ + if (h->u.def.value < op->vma) + op = op1; + } + h->u.def.value -= op->vma; h->u.def.section = op; } -- Alan Modra IBM OzLabs - Linux Technology Centre