From 3dbf33eeb425669fe2e4240e2038f77c6c2f241d Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 29 Nov 1995 20:04:17 +0000 Subject: [PATCH] * elf.c (assign_file_positions_for_segments): Don't adjust p_paddr if p_paddr_valid is set. (copy_private_bfd_data): New static function. (_bfd_elf_copy_private_section_data): Call copy_private_bfd_data. --- bfd/ChangeLog | 5 +++ bfd/elf.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 124 insertions(+), 3 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index d9c4856c47..c9260434c7 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,10 @@ Wed Nov 29 12:42:36 1995 Ian Lance Taylor + * elf.c (assign_file_positions_for_segments): Don't adjust p_paddr + if p_paddr_valid is set. + (copy_private_bfd_data): New static function. + (_bfd_elf_copy_private_section_data): Call copy_private_bfd_data. + * elf.c (assign_file_positions_for_segments): Fix case where extra program headers were allocated. diff --git a/bfd/elf.c b/bfd/elf.c index ba00bc8d0c..677bb45d40 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -45,6 +45,7 @@ static boolean assign_file_positions_for_segments PARAMS ((bfd *)); static boolean assign_file_positions_except_relocs PARAMS ((bfd *)); static boolean prep_headers PARAMS ((bfd *)); static boolean swap_out_syms PARAMS ((bfd *, struct bfd_strtab_hash **)); +static boolean copy_private_bfd_data PARAMS ((bfd *, bfd *)); /* Standard ELF hash function. Do not change this function; you will cause invalid hash tables to be generated. (Well, you would if this @@ -1874,6 +1875,7 @@ assign_file_positions_for_segments (abfd) { struct elf_segment_map *mi; Elf_Internal_Phdr *pi; + struct elf_segment_map *mi_phdr; Elf_Internal_Phdr *pi_phdr; /* This is the first PT_LOAD segment. If there is a @@ -1890,17 +1892,22 @@ assign_file_positions_for_segments (abfd) p->p_filesz = off; p->p_memsz = off; p->p_vaddr -= off; - p->p_paddr -= off; + if (! m->p_paddr_valid) + p->p_paddr -= off; } if (mi->p_type == PT_PHDR) - pi_phdr = pi; + { + mi_phdr = mi; + pi_phdr = pi; + } } /* Set up the PT_PHDR addresses. */ if (pi_phdr != NULL) { pi_phdr->p_vaddr = p->p_vaddr + bed->s->sizeof_ehdr; - pi_phdr->p_paddr = p->p_paddr + bed->s->sizeof_ehdr; + if (! mi_phdr->p_paddr_valid) + pi_phdr->p_paddr = p->p_paddr + bed->s->sizeof_ehdr; } found_load = true; @@ -2451,6 +2458,93 @@ _bfd_elf_symbol_from_bfd_symbol (abfd, asym_ptr_ptr) return idx; } +/* Copy private BFD data. This copies any program header information. */ + +static boolean +copy_private_bfd_data (ibfd, obfd) + bfd *ibfd; + bfd *obfd; +{ + struct elf_segment_map *mfirst; + struct elf_segment_map **pm; + Elf_Internal_Phdr *p; + unsigned int i, c; + + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour + || bfd_get_flavour (obfd) != bfd_target_elf_flavour) + return true; + + if (elf_tdata (ibfd)->phdr == NULL) + return true; + + mfirst = NULL; + pm = &mfirst; + + c = elf_elfheader (ibfd)->e_phnum; + for (i = 0, p = elf_tdata (ibfd)->phdr; i < c; i++, p++) + { + struct elf_segment_map *m; + unsigned int csecs; + + csecs = 0; + if (p->p_type != PT_PHDR) + { + asection *s; + + for (s = ibfd->sections; s != NULL; s = s->next) + if (s->vma >= p->p_vaddr + && s->vma + s->_raw_size <= p->p_vaddr + p->p_memsz + && s->output_section != NULL) + ++csecs; + } + + m = ((struct elf_segment_map *) + bfd_alloc (obfd, + (sizeof (struct elf_segment_map) + + (csecs - 1) * sizeof (asection *)))); + if (m == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + m->next = NULL; + m->p_type = p->p_type; + m->p_flags = p->p_flags; + m->p_flags_valid = 1; + m->p_paddr = p->p_paddr; + m->p_paddr_valid = 1; + + if (p->p_type != PT_PHDR) + { + asection *s; + unsigned int isec; + + isec = 0; + for (s = ibfd->sections; s != NULL; s = s->next) + { + if (s->vma >= p->p_vaddr + && s->vma + s->_raw_size <= p->p_vaddr + p->p_memsz + && s->output_section != NULL) + { + m->sections[isec] = s->output_section; + ++isec; + } + } + qsort (m->sections, (size_t) csecs, sizeof (asection *), + elf_sort_sections); + m->count = csecs; + } + + *pm = m; + pm = &m->next; + } + + elf_tdata (obfd)->segment_map = mfirst; + + return true; +} + /* Copy private section information. This copies over the entsize field, and sometimes the info field. */ @@ -2467,6 +2561,28 @@ _bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec) || obfd->xvec->flavour != bfd_target_elf_flavour) return true; + /* Copy over private BFD data if it has not already been copied. + This must be done here, rather than in the copy_private_bfd_data + entry point, because the latter is called after the section + contents have been set, which means that the program headers have + already been worked out. */ + if (elf_tdata (obfd)->segment_map == NULL + && elf_tdata (ibfd)->phdr != NULL) + { + asection *s; + + /* Only set up the segments when all the sections have been set + up. */ + for (s = ibfd->sections; s != NULL; s = s->next) + if (s->output_section == NULL) + break; + if (s == NULL) + { + if (! copy_private_bfd_data (ibfd, obfd)) + return false; + } + } + ihdr = &elf_section_data (isec)->this_hdr; ohdr = &elf_section_data (osec)->this_hdr;