From 627b32bcf9eadc335b8c07f7cf8ea7155ef15fbd Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 2 May 2007 13:44:37 +0000 Subject: [PATCH] include/elf/ * internal.h (ELF_IS_SECTION_IN_SEGMENT): Check both file offset and vma for appropriate sections. bfd/ * elf.c (assign_file_positions_for_load_sections): Set sh_offset here. Set sh_type to SHT_NOBITS if we won't be allocating file space. Don't bump p_memsz for non-alloc sections. Adjust section-in-segment check. (assign_file_positions_for_non_load_sections): Don't set sh_offset here for sections that have already been handled above. --- bfd/ChangeLog | 9 +++++++++ bfd/elf.c | 28 +++++++++++++++++++--------- include/elf/ChangeLog | 5 +++++ include/elf/internal.h | 36 ++++++++++++++++++------------------ 4 files changed, 51 insertions(+), 27 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 73257527c20..1c00088371e 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +2007-05-02 Alan Modra + + * elf.c (assign_file_positions_for_load_sections): Set sh_offset + here. Set sh_type to SHT_NOBITS if we won't be allocating + file space. Don't bump p_memsz for non-alloc sections. Adjust + section-in-segment check. + (assign_file_positions_for_non_load_sections): Don't set sh_offset + here for sections that have already been handled above. + 2007-04-30 Alan Modra * elf32-spu.c (struct spu_link_hash_table): Add stack_analysis diff --git a/bfd/elf.c b/bfd/elf.c index 3501f3dc6d8..1314bba7449 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -4511,6 +4511,7 @@ assign_file_positions_for_load_sections (bfd *abfd, asection *sec; flagword flags; bfd_size_type align; + Elf_Internal_Shdr *this_hdr; sec = *secpp; flags = sec->flags; @@ -4543,13 +4544,14 @@ assign_file_positions_for_load_sections (bfd *abfd, } } + this_hdr = &elf_section_data (sec)->this_hdr; if (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core) { /* The section at i == 0 is the one that actually contains everything. */ if (i == 0) { - sec->filepos = off; + this_hdr->sh_offset = sec->filepos = off; off += sec->size; p->p_filesz = sec->size; p->p_memsz = 0; @@ -4568,7 +4570,7 @@ assign_file_positions_for_load_sections (bfd *abfd, { if (p->p_type == PT_LOAD) { - sec->filepos = off + voff; + this_hdr->sh_offset = sec->filepos = off + voff; /* FIXME: The SEC_HAS_CONTENTS test here dates back to 1997, and the exact reason for it isn't clear. One plausible explanation is that it is to work around @@ -4586,12 +4588,22 @@ assign_file_positions_for_load_sections (bfd *abfd, if ((flags & SEC_LOAD) != 0 || (flags & SEC_HAS_CONTENTS) != 0) off += sec->size; + else + /* If we aren't making room for this section, then + it must be SHT_NOBITS regardless of what we've + set via struct bfd_elf_special_section. */ + this_hdr->sh_type = SHT_NOBITS; } if ((flags & SEC_LOAD) != 0) { p->p_filesz += sec->size; - p->p_memsz += sec->size; + /* SEC_LOAD without SEC_ALLOC is a weird combination + used by note sections to signify that a PT_NOTE + segment should be created. These take file space + but are not actually loaded into memory. */ + if ((flags & SEC_ALLOC) != 0) + p->p_memsz += sec->size; } /* .tbss is special. It doesn't contribute to p_memsz of @@ -4629,11 +4641,9 @@ assign_file_positions_for_load_sections (bfd *abfd, } } - /* Check if all sections are in the segment. Skip PT_GNU_RELRO - and PT_NOTE segments since they will be processed by - assign_file_positions_for_non_load_sections later. */ - if (p->p_type != PT_GNU_RELRO - && p->p_type != PT_NOTE) + /* Check that all sections are in the segment. */ + if (p->p_type == PT_LOAD + || (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core)) for (i = 0, secpp = m->sections; i < m->count; i++, secpp++) { Elf_Internal_Shdr *this_hdr; @@ -4689,7 +4699,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, && (hdr->bfd_section->filepos != 0 || (hdr->sh_type == SHT_NOBITS && hdr->contents == NULL))) - hdr->sh_offset = hdr->bfd_section->filepos; + BFD_ASSERT (hdr->sh_offset == hdr->bfd_section->filepos); else if ((hdr->sh_flags & SHF_ALLOC) != 0) { if (hdr->sh_size != 0) diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog index 89deb482b30..c214009738c 100644 --- a/include/elf/ChangeLog +++ b/include/elf/ChangeLog @@ -1,3 +1,8 @@ +2007-05-02 Alan Modra + + * internal.h (ELF_IS_SECTION_IN_SEGMENT): Check both file offset + and vma for appropriate sections. + 2007-04-26 Jan Beulich * common.h (DT_ENCODING): Correct value (back to spec mandated diff --git a/include/elf/internal.h b/include/elf/internal.h index f2161ff9d8e..152171136c1 100644 --- a/include/elf/internal.h +++ b/include/elf/internal.h @@ -1,6 +1,6 @@ /* ELF support for BFD. Copyright 1991, 1992, 1993, 1994, 1995, 1997, 1998, 2000, 2001, 2002, - 2003, 2006 Free Software Foundation, Inc. + 2003, 2006, 2007 Free Software Foundation, Inc. Written by Fred Fish @ Cygnus Support, from information published in "UNIX System V Release 4, Programmers Guide: ANSI C and @@ -268,23 +268,23 @@ struct elf_segment_map /* Decide if the given sec_hdr is in the given segment. PT_TLS segment contains only SHF_TLS sections. Only PT_LOAD and PT_TLS segments can contain SHF_TLS sections. */ -#define ELF_IS_SECTION_IN_SEGMENT(sec_hdr, segment) \ - (((((sec_hdr->sh_flags & SHF_TLS) != 0) \ - && (segment->p_type == PT_TLS \ - || segment->p_type == PT_LOAD)) \ - || ((sec_hdr->sh_flags & SHF_TLS) == 0 \ - && segment->p_type != PT_TLS)) \ - /* Compare allocated sec_hdrs by VMA, unallocated sec_hdrs \ - by file offset. */ \ - && (sec_hdr->sh_flags & SHF_ALLOC \ - ? (sec_hdr->sh_addr >= segment->p_vaddr \ - && (sec_hdr->sh_addr \ - + ELF_SECTION_SIZE(sec_hdr, segment) \ - <= segment->p_vaddr + segment->p_memsz)) \ - : ((bfd_vma) sec_hdr->sh_offset >= segment->p_offset \ - && (sec_hdr->sh_offset \ - + ELF_SECTION_SIZE(sec_hdr, segment) \ - <= segment->p_offset + segment->p_filesz)))) +#define ELF_IS_SECTION_IN_SEGMENT(sec_hdr, segment) \ + (((((sec_hdr->sh_flags & SHF_TLS) != 0) \ + && (segment->p_type == PT_TLS \ + || segment->p_type == PT_LOAD)) \ + || ((sec_hdr->sh_flags & SHF_TLS) == 0 \ + && segment->p_type != PT_TLS)) \ + /* Any section besides one of type SHT_NOBITS must have a file \ + offset within the segment. */ \ + && (sec_hdr->sh_type == SHT_NOBITS \ + || ((bfd_vma) sec_hdr->sh_offset >= segment->p_offset \ + && (sec_hdr->sh_offset + ELF_SECTION_SIZE(sec_hdr, segment) \ + <= segment->p_offset + segment->p_filesz))) \ + /* SHF_ALLOC sections must have VMAs within the segment. */ \ + && ((sec_hdr->sh_flags & SHF_ALLOC) == 0 \ + || (sec_hdr->sh_addr >= segment->p_vaddr \ + && (sec_hdr->sh_addr + ELF_SECTION_SIZE(sec_hdr, segment) \ + <= segment->p_vaddr + segment->p_memsz)))) /* Decide if the given sec_hdr is in the given segment in file. */ #define ELF_IS_SECTION_IN_SEGMENT_FILE(sec_hdr, segment) \ -- 2.30.2