* linker.c (fix_syms): Choose best of previous and next
section based on section flags and vma.
This commit is contained in:
parent
75ee0d67f2
commit
720194edb0
|
@ -1,3 +1,8 @@
|
||||||
|
2006-10-23 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
|
* linker.c (fix_syms): Choose best of previous and next
|
||||||
|
section based on section flags and vma.
|
||||||
|
|
||||||
2006-10-21 Kaz Kojima <kkojima@rr.iij4u.or.jp>
|
2006-10-21 Kaz Kojima <kkojima@rr.iij4u.or.jp>
|
||||||
|
|
||||||
* elf32-sh64.c (sh64_elf_merge_symbol_attribute): Do merging
|
* elf32-sh64.c (sh64_elf_merge_symbol_attribute): Do merging
|
||||||
|
|
61
bfd/linker.c
61
bfd/linker.c
|
@ -3092,25 +3092,62 @@ fix_syms (struct bfd_link_hash_entry *h, void *data)
|
||||||
&& (s->output_section->flags & SEC_EXCLUDE) != 0
|
&& (s->output_section->flags & SEC_EXCLUDE) != 0
|
||||||
&& bfd_section_removed_from_list (obfd, s->output_section))
|
&& bfd_section_removed_from_list (obfd, s->output_section))
|
||||||
{
|
{
|
||||||
asection *op;
|
asection *op, *op1;
|
||||||
for (op = s->output_section->prev; op != NULL; op = op->prev)
|
|
||||||
|
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
|
if ((op->flags & SEC_EXCLUDE) == 0
|
||||||
&& !bfd_section_removed_from_list (obfd, op))
|
&& !bfd_section_removed_from_list (obfd, op))
|
||||||
break;
|
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)
|
if (op == NULL)
|
||||||
op = bfd_abs_section_ptr;
|
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.value -= op->vma;
|
||||||
h->u.def.section = op;
|
h->u.def.section = op;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue