diff options
Diffstat (limited to 'bfd/elf64-ppc.c')
-rw-r--r-- | bfd/elf64-ppc.c | 39 |
1 files changed, 27 insertions, 12 deletions
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 3f219fa..45d0879 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -8015,7 +8015,13 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) } bfd_put_32 (htab->stub_bfd, B_DOT | (off & 0x3fffffc), loc); - BFD_ASSERT (off + (1 << 25) < (bfd_vma) (1 << 26)); + if (off + (1 << 25) >= (bfd_vma) (1 << 26)) + { + (*_bfd_error_handler) (_("long branch stub `%s' offset overflow"), + stub_entry->root.string); + htab->stub_error = TRUE; + return FALSE; + } if (info->emitrelocations) { @@ -8087,7 +8093,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) if (br_entry == NULL) { (*_bfd_error_handler) (_("can't find branch stub `%s'"), - stub_entry->root.string + 9); + stub_entry->root.string); htab->stub_error = TRUE; return FALSE; } @@ -8331,7 +8337,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) if (br_entry == NULL) { (*_bfd_error_handler) (_("can't build branch stub `%s'"), - stub_entry->root.string + 9); + stub_entry->root.string); htab->stub_error = TRUE; return FALSE; } @@ -8752,7 +8758,10 @@ group_sections (struct ppc_link_hash_table *htab, curr = tail; total = tail->size; - big_sec = total >= stub_group_size; + big_sec = total > stub_group_size; + if (big_sec) + (*_bfd_error_handler) (_("%B section %A exceeds stub group size"), + tail->owner, tail); curr_toc = htab->stub_group[tail->id].toc_off; while ((prev = PREV_SEC (curr)) != NULL @@ -8854,10 +8863,8 @@ ppc64_elf_size_stubs (bfd *output_bfd, bfd *input_bfd; unsigned int bfd_indx; asection *stub_sec; - bfd_boolean stub_changed; htab->stub_iteration += 1; - stub_changed = FALSE; for (input_bfd = info->input_bfds, bfd_indx = 0; input_bfd != NULL; @@ -9106,8 +9113,6 @@ ppc64_elf_size_stubs (bfd *output_bfd, if (stub_entry->h != NULL) htab->stub_globals += 1; - - stub_changed = TRUE; } /* We're done with the internal relocs, free them. */ @@ -9125,16 +9130,14 @@ ppc64_elf_size_stubs (bfd *output_bfd, } } - if (!stub_changed) - break; - - /* OK, we've added some stubs. Find out the new size of the + /* We may have added some stubs. Find out the new size of the stub sections. */ for (stub_sec = htab->stub_bfd->sections; stub_sec != NULL; stub_sec = stub_sec->next) if ((stub_sec->flags & SEC_LINKER_CREATED) == 0) { + stub_sec->rawsize = stub_sec->size; stub_sec->size = 0; stub_sec->reloc_count = 0; } @@ -9145,6 +9148,18 @@ ppc64_elf_size_stubs (bfd *output_bfd, bfd_hash_traverse (&htab->stub_hash_table, ppc_size_one_stub, info); + for (stub_sec = htab->stub_bfd->sections; + stub_sec != NULL; + stub_sec = stub_sec->next) + if ((stub_sec->flags & SEC_LINKER_CREATED) == 0 + && stub_sec->rawsize != stub_sec->size) + break; + + /* Exit from this loop when no stubs have been added, and no stubs + have changed size. */ + if (stub_sec == NULL) + break; + /* Ask the linker to do its stuff. */ (*htab->layout_sections_again) (); } |