diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/elf-bfd.h | 4 | ||||
-rw-r--r-- | bfd/elf.c | 57 | ||||
-rw-r--r-- | bfd/elflink.c | 33 |
3 files changed, 82 insertions, 12 deletions
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 01e0da1..f31244f 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -3146,6 +3146,10 @@ extern bool _bfd_elf_mmap_section_contents (bfd *abfd, asection *section, bfd_byte **buf); extern void _bfd_elf_munmap_section_contents (asection *, void *); +extern bool _bfd_elf_link_mmap_section_contents + (bfd *abfd, asection *section, bfd_byte **buf); +extern void _bfd_elf_link_munmap_section_contents + (asection *); /* Large common section. */ extern asection _bfd_elf_large_com_section; @@ -14366,10 +14366,12 @@ _bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec) return result; } -/* Mmap in section contents. */ +/* Mmap in section contents. If FINAL_LINK is false, set *BUF to NULL + before calling bfd_get_full_section_contents. */ -bool -_bfd_elf_mmap_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **buf) +static bool +elf_mmap_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **buf, + bool final_link) { #ifdef USE_MMAP const struct elf_backend_data *bed = get_elf_backend_data (abfd); @@ -14393,16 +14395,41 @@ _bfd_elf_mmap_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **buf) if (sec->mmapped_p) abort (); sec->mmapped_p = 1; + + /* Never use the preallocated buffer if mmapp is used. */ + *buf = NULL; } } #endif - *buf = NULL; + /* NB: When this is called from elf_link_input_bfd, FINAL_LINK is + true. If FINAL_LINK is false, *BUF is set to the preallocated + buffer if USE_MMAP is undefined and *BUF is set to NULL if + USE_MMAP is defined. */ + if (!final_link) + *buf = NULL; bool ret = bfd_get_full_section_contents (abfd, sec, buf); if (ret && sec->mmapped_p) *buf = sec->contents; return ret; } +/* Mmap in section contents. */ + +bool +_bfd_elf_mmap_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **buf) +{ + return elf_mmap_section_contents (abfd, sec, buf, false); +} + +/* Mmap in the full section contents for the final link. */ + +bool +_bfd_elf_link_mmap_section_contents (bfd *abfd, sec_ptr sec, + bfd_byte **buf) +{ + return elf_mmap_section_contents (abfd, sec, buf, true); +} + /* Munmap section contents. */ void @@ -14442,3 +14469,25 @@ _bfd_elf_munmap_section_contents (asection *sec ATTRIBUTE_UNUSED, free (contents); } + +/* Munmap the full section contents for the final link. */ + +void +_bfd_elf_link_munmap_section_contents (asection *sec ATTRIBUTE_UNUSED) +{ +#ifdef USE_MMAP + if (sec->mmapped_p && elf_section_data (sec)->contents_addr != NULL) + { + /* When _bfd_elf_link_mmap_section_contents returns CONTENTS as + malloced, CONTENTS_ADDR is set to NULL. */ + /* NB: CONTENTS_ADDR and CONTENTS_SIZE must be valid. */ + if (munmap (elf_section_data (sec)->contents_addr, + elf_section_data (sec)->contents_size) != 0) + abort (); + sec->mmapped_p = 0; + sec->contents = NULL; + elf_section_data (sec)->contents_addr = NULL; + elf_section_data (sec)->contents_size = 0; + } +#endif +} diff --git a/bfd/elflink.c b/bfd/elflink.c index a7b50bf..2a05299 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -11486,7 +11486,8 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) else { contents = flinfo->contents; - if (! bfd_get_full_section_contents (input_bfd, o, &contents)) + if (! _bfd_elf_link_mmap_section_contents (input_bfd, o, + &contents)) return false; } @@ -12047,6 +12048,9 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) } break; } + + /* Munmap the section contents for each input section. */ + _bfd_elf_link_munmap_section_contents (o); } return true; @@ -12485,13 +12489,17 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *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 also figure out some maximum sizes. */ - max_contents_size = 0; #ifdef USE_MMAP /* Mmap is used only if section size >= the minimum mmap section - size. max_external_reloc_size covers all relocation sections - smaller than the minimum mmap section size. */ + size. The initial max_contents_size value covers all sections + smaller than the minimum mmap section size. It may be increased + for compressed or linker created sections or sections whose + rawsize != size. max_external_reloc_size covers all relocation + sections smaller than the minimum mmap section size. */ + max_contents_size = _bfd_minimum_mmap_size; max_external_reloc_size = _bfd_minimum_mmap_size; #else + max_contents_size = 0; max_external_reloc_size = 0; #endif max_internal_reloc_count = 0; @@ -12527,10 +12535,19 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (sec->flags & SEC_MERGE) merged = true; - if (sec->rawsize > max_contents_size) - max_contents_size = sec->rawsize; - if (sec->size > max_contents_size) - max_contents_size = sec->size; +#ifdef USE_MMAP + /* Mmap is used only on non-compressed, non-linker created + sections whose rawsize == size. */ + if (sec->compress_status != COMPRESS_SECTION_NONE + || (sec->flags & SEC_LINKER_CREATED) != 0 + || sec->rawsize != sec->size) +#endif + { + if (sec->rawsize > max_contents_size) + max_contents_size = sec->rawsize; + if (sec->size > max_contents_size) + max_contents_size = sec->size; + } if (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour && (sec->owner->flags & DYNAMIC) == 0) |