aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog8
-rw-r--r--bfd/elf.c149
2 files changed, 83 insertions, 74 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index e178d33..8d994a8 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,11 @@
+2008-05-01 Alan Modra <amodra@bigpond.net.au>
+
+ PR 2995, PR 6473
+ * elf.c (_bfd_elf_make_section_from_shdr): Always set lma from p_paddr.
+ (assign_file_positions_for_load_sections): Combine nested "if".
+ (copy_elf_program_header): Don't set p_paddr_valid or p_vaddr_offset
+ when all header p_paddr fields are zero.
+
2008-04-30 Edmar Wienskoski <edmar@freescale.com>
* cpu-powerpc.c (bfd_powerpc_archs): Add e500mc entry.
diff --git a/bfd/elf.c b/bfd/elf.c
index c4a88ee..2f1ec37 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -946,63 +946,51 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
Elf_Internal_Phdr *phdr;
unsigned int i;
- /* Look through the phdrs to see if we need to adjust the lma.
- If all the p_paddr fields are zero, we ignore them, since
- some ELF linkers produce such output. */
phdr = elf_tdata (abfd)->phdr;
for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
{
- if (phdr->p_paddr != 0)
- break;
- }
- if (i < elf_elfheader (abfd)->e_phnum)
- {
- phdr = elf_tdata (abfd)->phdr;
- for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
+ /* This section is part of this segment if its file
+ offset plus size lies within the segment's memory
+ span and, if the section is loaded, the extent of the
+ loaded data lies within the extent of the segment.
+
+ Note - we used to check the p_paddr field as well, and
+ refuse to set the LMA if it was 0. This is wrong
+ though, as a perfectly valid initialised segment can
+ have a p_paddr of zero. Some architectures, eg ARM,
+ place special significance on the address 0 and
+ executables need to be able to have a segment which
+ covers this address. */
+ if (phdr->p_type == PT_LOAD
+ && (bfd_vma) hdr->sh_offset >= phdr->p_offset
+ && (hdr->sh_offset + hdr->sh_size
+ <= phdr->p_offset + phdr->p_memsz)
+ && ((flags & SEC_LOAD) == 0
+ || (hdr->sh_offset + hdr->sh_size
+ <= phdr->p_offset + phdr->p_filesz)))
{
- /* This section is part of this segment if its file
- offset plus size lies within the segment's memory
- span and, if the section is loaded, the extent of the
- loaded data lies within the extent of the segment.
-
- Note - we used to check the p_paddr field as well, and
- refuse to set the LMA if it was 0. This is wrong
- though, as a perfectly valid initialised segment can
- have a p_paddr of zero. Some architectures, eg ARM,
- place special significance on the address 0 and
- executables need to be able to have a segment which
- covers this address. */
- if (phdr->p_type == PT_LOAD
- && (bfd_vma) hdr->sh_offset >= phdr->p_offset
- && (hdr->sh_offset + hdr->sh_size
- <= phdr->p_offset + phdr->p_memsz)
- && ((flags & SEC_LOAD) == 0
- || (hdr->sh_offset + hdr->sh_size
- <= phdr->p_offset + phdr->p_filesz)))
- {
- if ((flags & SEC_LOAD) == 0)
- newsect->lma = (phdr->p_paddr
- + hdr->sh_addr - phdr->p_vaddr);
- else
- /* We used to use the same adjustment for SEC_LOAD
- sections, but that doesn't work if the segment
- is packed with code from multiple VMAs.
- Instead we calculate the section LMA based on
- the segment LMA. It is assumed that the
- segment will contain sections with contiguous
- LMAs, even if the VMAs are not. */
- newsect->lma = (phdr->p_paddr
- + hdr->sh_offset - phdr->p_offset);
-
- /* With contiguous segments, we can't tell from file
- offsets whether a section with zero size should
- be placed at the end of one segment or the
- beginning of the next. Decide based on vaddr. */
- if (hdr->sh_addr >= phdr->p_vaddr
- && (hdr->sh_addr + hdr->sh_size
- <= phdr->p_vaddr + phdr->p_memsz))
- break;
- }
+ if ((flags & SEC_LOAD) == 0)
+ newsect->lma = (phdr->p_paddr
+ + hdr->sh_addr - phdr->p_vaddr);
+ else
+ /* We used to use the same adjustment for SEC_LOAD
+ sections, but that doesn't work if the segment
+ is packed with code from multiple VMAs.
+ Instead we calculate the section LMA based on
+ the segment LMA. It is assumed that the
+ segment will contain sections with contiguous
+ LMAs, even if the VMAs are not. */
+ newsect->lma = (phdr->p_paddr
+ + hdr->sh_offset - phdr->p_offset);
+
+ /* With contiguous segments, we can't tell from file
+ offsets whether a section with zero size should
+ be placed at the end of one segment or the
+ beginning of the next. Decide based on vaddr. */
+ if (hdr->sh_addr >= phdr->p_vaddr
+ && (hdr->sh_addr + hdr->sh_size
+ <= phdr->p_vaddr + phdr->p_memsz))
+ break;
}
}
}
@@ -4359,30 +4347,28 @@ assign_file_positions_for_load_sections (bfd *abfd,
this_hdr = &elf_section_data (sec)->this_hdr;
align = (bfd_size_type) 1 << bfd_get_section_alignment (abfd, sec);
- if (p->p_type == PT_LOAD
- || p->p_type == PT_TLS)
+ if ((p->p_type == PT_LOAD
+ || p->p_type == PT_TLS)
+ && (this_hdr->sh_type != SHT_NOBITS
+ || ((this_hdr->sh_flags & SHF_ALLOC) != 0
+ && ((this_hdr->sh_flags & SHF_TLS) == 0
+ || p->p_type == PT_TLS))))
{
bfd_signed_vma adjust = sec->lma - (p->p_paddr + p->p_memsz);
- if (this_hdr->sh_type != SHT_NOBITS
- || ((this_hdr->sh_flags & SHF_ALLOC) != 0
- && ((this_hdr->sh_flags & SHF_TLS) == 0
- || p->p_type == PT_TLS)))
+ if (adjust < 0)
{
- if (adjust < 0)
- {
- (*_bfd_error_handler)
- (_("%B: section %A lma 0x%lx overlaps previous sections"),
- abfd, sec, (unsigned long) sec->lma);
- adjust = 0;
- }
- p->p_memsz += adjust;
+ (*_bfd_error_handler)
+ (_("%B: section %A lma 0x%lx overlaps previous sections"),
+ abfd, sec, (unsigned long) sec->lma);
+ adjust = 0;
+ }
+ p->p_memsz += adjust;
- if (this_hdr->sh_type != SHT_NOBITS)
- {
- off += adjust;
- p->p_filesz += adjust;
- }
+ if (this_hdr->sh_type != SHT_NOBITS)
+ {
+ off += adjust;
+ p->p_filesz += adjust;
}
}
@@ -5709,16 +5695,29 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
unsigned int i;
unsigned int num_segments;
bfd_boolean phdr_included = FALSE;
+ bfd_boolean p_paddr_valid;
iehdr = elf_elfheader (ibfd);
map_first = NULL;
pointer_to_map = &map_first;
+ /* If all the segment p_paddr fields are zero, don't set
+ map->p_paddr_valid. */
+ p_paddr_valid = FALSE;
num_segments = elf_elfheader (ibfd)->e_phnum;
for (i = 0, segment = elf_tdata (ibfd)->phdr;
i < num_segments;
i++, segment++)
+ if (segment->p_paddr != 0)
+ {
+ p_paddr_valid = TRUE;
+ break;
+ }
+
+ for (i = 0, segment = elf_tdata (ibfd)->phdr;
+ i < num_segments;
+ i++, segment++)
{
asection *section;
unsigned int section_count;
@@ -5759,7 +5758,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
map->p_flags = segment->p_flags;
map->p_flags_valid = 1;
map->p_paddr = segment->p_paddr;
- map->p_paddr_valid = 1;
+ map->p_paddr_valid = p_paddr_valid;
map->p_align = segment->p_align;
map->p_align_valid = 1;
map->p_vaddr_offset = 0;
@@ -5793,7 +5792,9 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
phdr_included = TRUE;
}
- if (!map->includes_phdrs && !map->includes_filehdr)
+ if (!map->includes_phdrs
+ && !map->includes_filehdr
+ && map->p_paddr_valid)
/* There is some other padding before the first section. */
map->p_vaddr_offset = ((lowest_section ? lowest_section->lma : 0)
- segment->p_paddr);