diff options
Diffstat (limited to 'bfd/elf32-ppc.c')
-rw-r--r-- | bfd/elf32-ppc.c | 95 |
1 files changed, 32 insertions, 63 deletions
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index c9f22bb..e7a310c 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -2159,123 +2159,92 @@ ppc_elf_begin_write_processing (bfd *abfd, struct bfd_link_info *link_info) { bfd *ibfd; asection *asec; - char *buffer; - unsigned num_input_sections; - bfd_size_type output_section_size; + char *buffer = NULL; + bfd_size_type largest_input_size = 0; unsigned i; unsigned num_entries; - unsigned long offset; unsigned long length; const char *error_message = NULL; if (link_info == NULL) return; - /* Scan the input bfds, looking for apuinfo sections. */ - num_input_sections = 0; - output_section_size = 0; - - for (ibfd = link_info->input_bfds; ibfd; ibfd = ibfd->link_next) - { - asec = bfd_get_section_by_name (ibfd, APUINFO_SECTION_NAME); - if (asec) - { - ++ num_input_sections; - output_section_size += asec->size; - } - } - - /* We need at least one input sections - in order to make merging worthwhile. */ - if (num_input_sections < 1) - return; - - /* Just make sure that the output section exists as well. */ - asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME); - if (asec == NULL) - return; - - /* Allocate a buffer for the contents of the input sections. */ - buffer = bfd_malloc (output_section_size); - if (buffer == NULL) - return; - - offset = 0; apuinfo_list_init (); /* Read in the input sections contents. */ for (ibfd = link_info->input_bfds; ibfd; ibfd = ibfd->link_next) { unsigned long datum; - char *ptr; asec = bfd_get_section_by_name (ibfd, APUINFO_SECTION_NAME); if (asec == NULL) continue; + error_message = _("corrupt %s section in %B"); length = asec->size; - if (length < 24) + if (length < 20) + goto fail; + + if (largest_input_size < asec->size) { - error_message = _("corrupt or empty %s section in %B"); - goto fail; + if (buffer) + free (buffer); + largest_input_size = asec->size; + buffer = bfd_malloc (largest_input_size); + if (!buffer) + return; } - + if (bfd_seek (ibfd, asec->filepos, SEEK_SET) != 0 - || (bfd_bread (buffer + offset, length, ibfd) != length)) + || (bfd_bread (buffer, length, ibfd) != length)) { error_message = _("unable to read in %s section from %B"); goto fail; } - /* Process the contents of the section. */ - ptr = buffer + offset; - error_message = _("corrupt %s section in %B"); - /* Verify the contents of the header. Note - we have to extract the values this way in order to allow for a host whose endian-ness is different from the target. */ - datum = bfd_get_32 (ibfd, ptr); + datum = bfd_get_32 (ibfd, buffer); if (datum != sizeof APUINFO_LABEL) goto fail; - datum = bfd_get_32 (ibfd, ptr + 8); + datum = bfd_get_32 (ibfd, buffer + 8); if (datum != 0x2) goto fail; - if (strcmp (ptr + 12, APUINFO_LABEL) != 0) + if (strcmp (buffer + 12, APUINFO_LABEL) != 0) goto fail; /* Get the number of bytes used for apuinfo entries. */ - datum = bfd_get_32 (ibfd, ptr + 4); + datum = bfd_get_32 (ibfd, buffer + 4); if (datum + 20 != length) goto fail; - /* Make sure that we do not run off the end of the section. */ - if (offset + length > output_section_size) - goto fail; - /* Scan the apuinfo section, building a list of apuinfo numbers. */ for (i = 0; i < datum; i += 4) - apuinfo_list_add (bfd_get_32 (ibfd, ptr + 20 + i)); - - /* Update the offset. */ - offset += length; + apuinfo_list_add (bfd_get_32 (ibfd, buffer + 20 + i)); } error_message = NULL; /* Compute the size of the output section. */ num_entries = apuinfo_list_length (); - output_section_size = 20 + num_entries * 4; - - asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME); - if (! bfd_set_section_size (abfd, asec, output_section_size)) - ibfd = abfd, - error_message = _("warning: unable to set size of %s section in %B"); + if (num_entries) + { + /* Set the output section size, if it exists. */ + asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME); + if (asec && ! bfd_set_section_size (abfd, asec, 20 + num_entries * 4)) + { + ibfd = abfd; + error_message = _("warning: unable to set size of %s section in %B"); + } + } fail: - free (buffer); + if (buffer) + free (buffer); if (error_message) (*_bfd_error_handler) (error_message, ibfd, APUINFO_SECTION_NAME); |