mirror of
https://github.com/bminor/binutils-gdb.git
synced 2026-02-05 00:01:30 +00:00
PR 33726, symbols in excluded sections
This improves "nearby" section choice when memory regions are active, preferring a section in the same region as the excluded section over other sections. PR 33726 include/ * bfdlink.h (struct bfd_link_callbacks): Add nearby_section. (_bfd_nearby_section): Delete. (bfd_fix_excluded_sec_syms): Rename and remove bfd param from _bfd_fix_excluded_sec_syms. bfd/ * linker.c (_bfd_nearby_section): Delete. (fix_syms): Use linker callback. * elflink.c (elf_link_input_bfd): Likewise. (_bfd_elf_final_link): Update. ld/ * ldemul.c (finish_default): Update. * ldlang.c (lang_output_section_get): Delete. (ldlang_nearby_section): New function. * ldlang.h (ldlang_nearby_section): Declare. (lang_output_section_get): New static inline. * ldmain.c (link_callbacks): Add ldlang_nearby_section.
This commit is contained in:
@@ -12113,8 +12113,8 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
|
||||
if (r_symndx == STN_UNDEF)
|
||||
{
|
||||
irela->r_addend += osec->vma;
|
||||
osec = _bfd_nearby_section (output_bfd, osec,
|
||||
osec->vma);
|
||||
osec = flinfo->info->callbacks->nearby_section
|
||||
(output_bfd, osec, osec->vma);
|
||||
irela->r_addend -= osec->vma;
|
||||
r_symndx = osec->target_index;
|
||||
}
|
||||
@@ -12755,7 +12755,7 @@ _bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
|
||||
}
|
||||
}
|
||||
if (sections_removed)
|
||||
_bfd_fix_excluded_sec_syms (abfd, info);
|
||||
bfd_fix_excluded_sec_syms (info);
|
||||
|
||||
/* Count up the number of relocations we will output for each output
|
||||
section, so that we know the sizes of the reloc sections. We
|
||||
|
||||
80
bfd/linker.c
80
bfd/linker.c
@@ -3093,82 +3093,13 @@ _bfd_generic_section_already_linked (bfd *abfd ATTRIBUTE_UNUSED,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Choose a neighbouring section to S in OBFD that will be output, or
|
||||
the absolute section if ADDR is out of bounds of the neighbours. */
|
||||
|
||||
asection *
|
||||
_bfd_nearby_section (bfd *obfd, asection *s, bfd_vma addr)
|
||||
{
|
||||
asection *next, *prev, *best;
|
||||
|
||||
/* Find preceding kept section. */
|
||||
for (prev = s->prev; prev != NULL; prev = prev->prev)
|
||||
if ((prev->flags & SEC_EXCLUDE) == 0
|
||||
&& !bfd_section_removed_from_list (obfd, prev))
|
||||
break;
|
||||
|
||||
/* Find following kept section. Start at prev->next because
|
||||
other sections may have been added after S was removed. */
|
||||
if (s->prev != NULL)
|
||||
next = s->prev->next;
|
||||
else
|
||||
next = s->owner->sections;
|
||||
for (; next != NULL; next = next->next)
|
||||
if ((next->flags & SEC_EXCLUDE) == 0
|
||||
&& !bfd_section_removed_from_list (obfd, next))
|
||||
break;
|
||||
|
||||
/* 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. */
|
||||
best = next;
|
||||
if (prev == NULL)
|
||||
{
|
||||
if (next == NULL)
|
||||
best = bfd_abs_section_ptr;
|
||||
}
|
||||
else if (next == NULL)
|
||||
best = prev;
|
||||
else if (((prev->flags ^ next->flags)
|
||||
& (SEC_ALLOC | SEC_THREAD_LOCAL | SEC_LOAD)) != 0)
|
||||
{
|
||||
if (((next->flags ^ s->flags)
|
||||
& (SEC_ALLOC | SEC_THREAD_LOCAL)) != 0
|
||||
/* We prefer to choose a loaded section. Section S
|
||||
doesn't have SEC_LOAD set (it being excluded, that
|
||||
part of the flag processing didn't happen) so we
|
||||
can't compare that flag to those of NEXT and PREV. */
|
||||
|| ((prev->flags & SEC_LOAD) != 0
|
||||
&& (next->flags & SEC_LOAD) == 0))
|
||||
best = prev;
|
||||
}
|
||||
else if (((prev->flags ^ next->flags) & SEC_READONLY) != 0)
|
||||
{
|
||||
if (((next->flags ^ s->flags) & SEC_READONLY) != 0)
|
||||
best = prev;
|
||||
}
|
||||
else if (((prev->flags ^ next->flags) & SEC_CODE) != 0)
|
||||
{
|
||||
if (((next->flags ^ s->flags) & SEC_CODE) != 0)
|
||||
best = prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Flags we care about are the same. Prefer the following
|
||||
section if that will result in a positive valued sym. */
|
||||
if (addr < next->vma)
|
||||
best = prev;
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
/* Convert symbols in excluded output sections to use a kept section. */
|
||||
|
||||
static bool
|
||||
fix_syms (struct bfd_link_hash_entry *h, void *data)
|
||||
{
|
||||
bfd *obfd = (bfd *) data;
|
||||
struct bfd_link_info *info = data;
|
||||
bfd *obfd = info->output_bfd;
|
||||
|
||||
if (h->type == bfd_link_hash_defined
|
||||
|| h->type == bfd_link_hash_defweak)
|
||||
@@ -3182,7 +3113,8 @@ fix_syms (struct bfd_link_hash_entry *h, void *data)
|
||||
asection *op;
|
||||
|
||||
h->u.def.value += s->output_offset + s->output_section->vma;
|
||||
op = _bfd_nearby_section (obfd, s->output_section, h->u.def.value);
|
||||
op = info->callbacks->nearby_section (obfd, s->output_section,
|
||||
h->u.def.value);
|
||||
h->u.def.value -= op->vma;
|
||||
h->u.def.section = op;
|
||||
}
|
||||
@@ -3192,9 +3124,9 @@ fix_syms (struct bfd_link_hash_entry *h, void *data)
|
||||
}
|
||||
|
||||
void
|
||||
_bfd_fix_excluded_sec_syms (bfd *obfd, struct bfd_link_info *info)
|
||||
bfd_fix_excluded_sec_syms (struct bfd_link_info *info)
|
||||
{
|
||||
bfd_link_hash_traverse (info->hash, fix_syms, obfd);
|
||||
bfd_link_hash_traverse (info->hash, fix_syms, info);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user