diff --git a/bfd/linker.c b/bfd/linker.c index fccca0d..73f90f8 100644 --- a/bfd/linker.c +++ b/bfd/linker.c @@ -3132,10 +3132,12 @@ _bfd_generic_section_already_linked (bfd *abfd ATTRIBUTE_UNUSED, } /* 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. */ + the absolute section if USE_ABS_SECTION is TRUE and ADDR is out of + bounds of the neighbours. */ -asection * -_bfd_nearby_section (bfd *obfd, asection *s, bfd_vma addr) +static asection * +bfd_nearby_section (bfd *obfd, asection *s, bfd_vma addr, + bfd_boolean use_abs_section) { asection *next, *prev, *best; @@ -3198,14 +3200,24 @@ _bfd_nearby_section (bfd *obfd, asection *s, bfd_vma addr) best = prev; } - /* Refuse to choose a section for which we are out of bounds. */ - /* ??? This may make most of the above moot. */ - if (addr < best->vma || addr > best->vma + best->size) + /* Refuse to choose a section for which we are out of bounds if + asked. */ + if (use_abs_section + && (addr < best->vma || addr > best->vma + best->size)) best = bfd_abs_section_ptr; return best; } +/* 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) +{ + return bfd_nearby_section (obfd, s, addr, TRUE); +} + /* Convert symbols in excluded output sections to use a kept section. */ static bfd_boolean @@ -3225,7 +3237,11 @@ 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); + /* Don't use the absolute section if symbol is defined in + output. See PR ld/14052. */ + op = bfd_nearby_section (obfd, s->output_section, + h->u.def.value, + h->u.def.section->owner != obfd); h->u.def.value -= op->vma; h->u.def.section = op; }