diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/elf-bfd.h | 2 | ||||
-rw-r--r-- | bfd/elf.c | 44 | ||||
-rw-r--r-- | bfd/elflink.c | 6 |
3 files changed, 34 insertions, 18 deletions
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index b89d3dd..96cf119 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -2540,7 +2540,7 @@ extern long _bfd_elf_link_lookup_local_dynindx extern bool _bfd_elf_compute_section_file_positions (bfd *, struct bfd_link_info *); extern file_ptr _bfd_elf_assign_file_position_for_section - (Elf_Internal_Shdr *, file_ptr, bool); + (Elf_Internal_Shdr *, file_ptr, bool, unsigned char); extern bool _bfd_elf_modify_headers (bfd *, struct bfd_link_info *); @@ -4572,10 +4572,23 @@ align_file_position (file_ptr off, int align) file_ptr _bfd_elf_assign_file_position_for_section (Elf_Internal_Shdr *i_shdrp, file_ptr offset, - bool align) + bool align, + unsigned char log_file_align) { - if (align && i_shdrp->sh_addralign > 1) - offset = BFD_ALIGN (offset, i_shdrp->sh_addralign & -i_shdrp->sh_addralign); + if (i_shdrp->sh_addralign > 1) + { + file_ptr salign = i_shdrp->sh_addralign & -i_shdrp->sh_addralign; + + if (align) + offset = BFD_ALIGN (offset, salign); + else if (log_file_align) + { + /* Heuristic: Cap alignment at log_file_align. */ + file_ptr falign = 1u << log_file_align; + + offset = BFD_ALIGN (offset, salign < falign ? salign : falign); + } + } i_shdrp->sh_offset = offset; if (i_shdrp->bfd_section != NULL) i_shdrp->bfd_section->filepos = offset; @@ -4663,18 +4676,18 @@ _bfd_elf_compute_section_file_positions (bfd *abfd, off = elf_next_file_pos (abfd); hdr = & elf_symtab_hdr (abfd); - off = _bfd_elf_assign_file_position_for_section (hdr, off, true); + off = _bfd_elf_assign_file_position_for_section (hdr, off, true, 0); if (elf_symtab_shndx_list (abfd) != NULL) { hdr = & elf_symtab_shndx_list (abfd)->hdr; if (hdr->sh_size != 0) - off = _bfd_elf_assign_file_position_for_section (hdr, off, true); + off = _bfd_elf_assign_file_position_for_section (hdr, off, true, 0); /* FIXME: What about other symtab_shndx sections in the list ? */ } hdr = &elf_tdata (abfd)->strtab_hdr; - off = _bfd_elf_assign_file_position_for_section (hdr, off, true); + off = _bfd_elf_assign_file_position_for_section (hdr, off, true, 0); elf_next_file_pos (abfd) = off; @@ -6548,8 +6561,8 @@ assign_file_positions_for_non_load_sections (bfd *abfd, else align = hdr->sh_addralign & -hdr->sh_addralign; off += vma_page_aligned_bias (hdr->sh_addr, off, align); - off = _bfd_elf_assign_file_position_for_section (hdr, off, - false); + off = _bfd_elf_assign_file_position_for_section (hdr, off, false, + bed->s->log_file_align); } else if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA) && hdr->bfd_section == NULL) @@ -6566,7 +6579,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, || hdr == i_shdrpp[elf_shstrtab_sec (abfd)]) hdr->sh_offset = -1; else - off = _bfd_elf_assign_file_position_for_section (hdr, off, true); + off = _bfd_elf_assign_file_position_for_section (hdr, off, true, 0); } elf_next_file_pos (abfd) = off; @@ -6803,7 +6816,8 @@ assign_file_positions_except_relocs (bfd *abfd, hdr->sh_offset = -1; } else - off = _bfd_elf_assign_file_position_for_section (hdr, off, true); + off = _bfd_elf_assign_file_position_for_section (hdr, off, false, + 0); } elf_next_file_pos (abfd) = off; @@ -7018,7 +7032,7 @@ _bfd_elf_assign_file_positions_for_non_load (bfd *abfd) Elf_Internal_Shdr **shdrpp, **end_shdrpp; Elf_Internal_Shdr *shdrp; Elf_Internal_Ehdr *i_ehdrp; - const struct elf_backend_data *bed; + const struct elf_backend_data *bed = get_elf_backend_data (abfd); /* Skip non-load sections without section header. */ if ((abfd->flags & BFD_NO_SECTION_HEADER) != 0) @@ -7086,7 +7100,10 @@ _bfd_elf_assign_file_positions_for_non_load (bfd *abfd) sec->contents = NULL; } - off = _bfd_elf_assign_file_position_for_section (shdrp, off, true); + off = _bfd_elf_assign_file_position_for_section (shdrp, off, + (abfd->flags & (EXEC_P | DYNAMIC)) + || bfd_get_format (abfd) == bfd_core, + bed->s->log_file_align); } } @@ -7095,11 +7112,10 @@ _bfd_elf_assign_file_positions_for_non_load (bfd *abfd) _bfd_elf_strtab_finalize (elf_shstrtab (abfd)); shdrp = &elf_tdata (abfd)->shstrtab_hdr; shdrp->sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd)); - off = _bfd_elf_assign_file_position_for_section (shdrp, off, true); + off = _bfd_elf_assign_file_position_for_section (shdrp, off, true, 0); /* Place the section headers. */ i_ehdrp = elf_elfheader (abfd); - bed = get_elf_backend_data (abfd); off = align_file_position (off, 1 << bed->s->log_file_align); i_ehdrp->e_shoff = off; off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize; diff --git a/bfd/elflink.c b/bfd/elflink.c index a498dbb..19a9aec 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -12926,7 +12926,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) { file_ptr off = elf_next_file_pos (abfd); - _bfd_elf_assign_file_position_for_section (symtab_hdr, off, true); + _bfd_elf_assign_file_position_for_section (symtab_hdr, off, true, 0); /* Note that at this point elf_next_file_pos (abfd) is incorrect. We do not yet know the size of the .symtab section. @@ -13370,7 +13370,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) symtab_shndx_hdr->sh_size = amt; off = _bfd_elf_assign_file_position_for_section (symtab_shndx_hdr, - off, true); + off, true, 0); if (bfd_seek (abfd, symtab_shndx_hdr->sh_offset, SEEK_SET) != 0 || (bfd_write (flinfo.symshndxbuf, amt, abfd) != amt)) @@ -13394,7 +13394,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) symstrtab_hdr->sh_addralign = 1; off = _bfd_elf_assign_file_position_for_section (symstrtab_hdr, - off, true); + off, true, 0); elf_next_file_pos (abfd) = off; if (bfd_seek (abfd, symstrtab_hdr->sh_offset, SEEK_SET) != 0 |