X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Fmerge.c;h=3cddeff51ee5a1a19bdd5275afac3cf02f618e57;hb=2425a30e406a0523020b7e70abb864a06a45bb97;hp=7aa088ff94734a50eb070351849507b567498f38;hpb=3409e291c1c178630a26ca916cd178c0c07e2fd9;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/merge.c b/bfd/merge.c index 7aa088ff94..3cddeff51e 100644 --- a/bfd/merge.c +++ b/bfd/merge.c @@ -1,6 +1,5 @@ /* SEC_MERGE support. - Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 - Free Software Foundation, Inc. + Copyright (C) 2001-2017 Free Software Foundation, Inc. Written by Jakub Jelinek . This file is part of BFD, the Binary File Descriptor library. @@ -26,6 +25,7 @@ #include "sysdep.h" #include "bfd.h" +#include "elf-bfd.h" #include "libbfd.h" #include "hashtab.h" #include "libiberty.h" @@ -284,7 +284,8 @@ sec_merge_add (struct sec_merge_hash *tab, const char *str, } static bfd_boolean -sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry) +sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry, + unsigned char *contents, file_ptr offset) { struct sec_merge_sec_info *secinfo = entry->secinfo; asection *sec = secinfo->sec; @@ -307,7 +308,12 @@ sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry) len = -off & (entry->alignment - 1); if (len != 0) { - if (bfd_bwrite (pad, len, abfd) != len) + if (contents) + { + memcpy (contents + offset, pad, len); + offset += len; + } + else if (bfd_bwrite (pad, len, abfd) != len) goto err; off += len; } @@ -315,7 +321,12 @@ sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry) str = entry->root.string; len = entry->len; - if (bfd_bwrite (str, len, abfd) != len) + if (contents) + { + memcpy (contents + offset, str, len); + offset += len; + } + else if (bfd_bwrite (str, len, abfd) != len) goto err; off += len; @@ -323,9 +334,13 @@ sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry) /* Trailing alignment needed? */ off = sec->size - off; - if (off != 0 - && bfd_bwrite (pad, off, abfd) != off) - goto err; + if (off != 0) + { + if (contents) + memcpy (contents + offset, pad, off); + else if (bfd_bwrite (pad, off, abfd) != off) + goto err; + } if (pad != NULL) free (pad); @@ -348,6 +363,7 @@ _bfd_add_merge_section (bfd *abfd, void **psinfo, asection *sec, struct sec_merge_sec_info *secinfo; unsigned int align; bfd_size_type amt; + bfd_byte *contents; if ((abfd->flags & DYNAMIC) != 0 || (sec->flags & SEC_MERGE) == 0) @@ -432,8 +448,8 @@ _bfd_add_merge_section (bfd *abfd, void **psinfo, asection *sec, sec->rawsize = sec->size; if (sec->flags & SEC_STRINGS) memset (secinfo->contents + sec->size, 0, sec->entsize); - if (! bfd_get_section_contents (sec->owner, sec, secinfo->contents, - 0, sec->size)) + contents = secinfo->contents; + if (! bfd_get_full_section_contents (sec->owner, sec, &contents)) goto error_return; return TRUE; @@ -785,6 +801,8 @@ _bfd_write_merged_section (bfd *output_bfd, asection *sec, void *psecinfo) { struct sec_merge_sec_info *secinfo; file_ptr pos; + unsigned char *contents; + Elf_Internal_Shdr *hdr; secinfo = (struct sec_merge_sec_info *) psecinfo; @@ -795,11 +813,26 @@ _bfd_write_merged_section (bfd *output_bfd, asection *sec, void *psecinfo) return TRUE; /* FIXME: octets_per_byte. */ - pos = sec->output_section->filepos + sec->output_offset; - if (bfd_seek (output_bfd, pos, SEEK_SET) != 0) - return FALSE; + hdr = &elf_section_data (sec->output_section)->this_hdr; + if (hdr->sh_offset == (file_ptr) -1) + { + /* We must compress this section. Write output to the + buffer. */ + contents = hdr->contents; + if ((sec->output_section->flags & SEC_ELF_COMPRESS) == 0 + || contents == NULL) + abort (); + } + else + { + contents = NULL; + pos = sec->output_section->filepos + sec->output_offset; + if (bfd_seek (output_bfd, pos, SEEK_SET) != 0) + return FALSE; + } - if (! sec_merge_emit (output_bfd, secinfo->first_str)) + if (! sec_merge_emit (output_bfd, secinfo->first_str, contents, + sec->output_offset)) return FALSE; return TRUE; @@ -826,11 +859,10 @@ _bfd_merged_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED, asection **psec, if (offset >= sec->rawsize) { if (offset > sec->rawsize) - { - (*_bfd_error_handler) - (_("%s: access beyond end of merged section (%ld)"), - bfd_get_filename (sec->owner), (long) offset); - } + _bfd_error_handler + /* xgettext:c-format */ + (_("%s: access beyond end of merged section (%ld)"), + bfd_get_filename (sec->owner), (long) offset); return secinfo->first_str ? sec->size : 0; } @@ -884,3 +916,17 @@ _bfd_merged_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED, asection **psec, *psec = entry->secinfo->sec; return entry->u.index + (secinfo->contents + offset - p); } + +/* Tidy up when done. */ + +void +_bfd_merge_sections_free (void *xsinfo) +{ + struct sec_merge_info *sinfo; + + for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next) + { + bfd_hash_table_free (&sinfo->htab->table); + free (sinfo->htab); + } +}