From 5c44b38ef660ed5eb5e28fe2c522d15494b42def Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Sat, 3 May 2008 05:18:02 +0000 Subject: [PATCH] PR 2995, PR 6473 * elf.c (rewrite_elf_program_header): Rather than clearing p_paddr_valid at end, don't set it in the first place. Delete comment no longer relevant. When not p_paddr_valid, don't set paddr from vaddr, and don't set p_vaddr_offset. --- bfd/ChangeLog | 8 ++++++++ bfd/elf.c | 40 ++++++++++++++++++++++------------------ 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 5539be2..f4a679f 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2008-05-03 Alan Modra + + PR 2995, PR 6473 + * elf.c (rewrite_elf_program_header): Rather than clearing + p_paddr_valid at end, don't set it in the first place. Delete + comment no longer relevant. When not p_paddr_valid, don't set + paddr from vaddr, and don't set p_vaddr_offset. + 2008-05-01 Cary Coutant * elf.c (bfd_elf_get_str_section): Fix memory leak caused by diff --git a/bfd/elf.c b/bfd/elf.c index 1a32d42..20f4cb3 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -5056,6 +5056,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) unsigned int i; unsigned int num_segments; bfd_boolean phdr_included = FALSE; + bfd_boolean p_paddr_valid; bfd_vma maxpagesize; struct elf_segment_map *phdr_adjust_seg = NULL; unsigned int phdr_adjust_num = 0; @@ -5184,6 +5185,20 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) for (section = ibfd->sections; section != NULL; section = section->next) section->segment_mark = FALSE; + /* The Solaris linker creates program headers in which all the + p_paddr fields are zero. When we try to objcopy or strip such a + file, we get confused. Check for this case, and if we find it + don't set the p_paddr_valid fields. */ + p_paddr_valid = FALSE; + for (i = 0, segment = elf_tdata (ibfd)->phdr; + i < num_segments; + i++, segment++) + if (segment->p_paddr != 0) + { + p_paddr_valid = TRUE; + break; + } + /* Scan through the segments specified in the program header of the input BFD. For this first scan we look for overlaps in the loadable segments. These can be created by weird @@ -5319,7 +5334,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) if (!first_section || first_section->output_section != NULL) { map->p_paddr = segment->p_paddr; - map->p_paddr_valid = 1; + map->p_paddr_valid = p_paddr_valid; } /* Determine if this segment contains the ELF file header @@ -5386,8 +5401,6 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) pointers that we are interested in. As these sections get assigned to a segment, they are removed from this array. */ - /* Gcc 2.96 miscompiles this code on mips. Don't do casting here - to work around this long long bug. */ sections = bfd_malloc2 (section_count, sizeof (asection *)); if (sections == NULL) return FALSE; @@ -5422,7 +5435,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) We try to catch that case here, and set it to the correct value. Note - some backends require that p_paddr be left as zero. */ - if (segment->p_paddr == 0 + if (!p_paddr_valid && segment->p_vaddr != 0 && !bed->want_p_paddr_set_to_zero && isec == 0 @@ -5480,9 +5493,11 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) *pointer_to_map = map; pointer_to_map = &map->next; - if (!bed->want_p_paddr_set_to_zero + if (p_paddr_valid + && !bed->want_p_paddr_set_to_zero && matching_lma != map->p_paddr - && !map->includes_filehdr && !map->includes_phdrs) + && !map->includes_filehdr + && !map->includes_phdrs) /* There is some padding before the first section in the segment. So, we must account for that in the output segment's vma. */ @@ -5634,7 +5649,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) map->p_flags = segment->p_flags; map->p_flags_valid = 1; map->p_paddr = suggested_lma; - map->p_paddr_valid = 1; + map->p_paddr_valid = p_paddr_valid; map->includes_filehdr = 0; map->includes_phdrs = 0; } @@ -5644,17 +5659,6 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) free (sections); } - /* The Solaris linker creates program headers in which all the - p_paddr fields are zero. When we try to objcopy or strip such a - file, we get confused. Check for this case, and if we find it - reset the p_paddr_valid fields. */ - for (map = map_first; map != NULL; map = map->next) - if (map->p_paddr != 0) - break; - if (map == NULL) - for (map = map_first; map != NULL; map = map->next) - map->p_paddr_valid = 0; - elf_tdata (obfd)->segment_map = map_first; /* If we had to estimate the number of program headers that were -- 2.7.4