This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: Dynamic section symbols, ignored output sections
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