aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1995-11-29 20:04:17 +0000
committerIan Lance Taylor <ian@airs.com>1995-11-29 20:04:17 +0000
commit3dbf33eeb425669fe2e4240e2038f77c6c2f241d (patch)
tree21c0bc4b2a637a508cdf3165be22de9eee3990f4 /bfd
parent44ef8897daee098e361b279406693bc6849c61e5 (diff)
downloadgdb-3dbf33eeb425669fe2e4240e2038f77c6c2f241d.zip
gdb-3dbf33eeb425669fe2e4240e2038f77c6c2f241d.tar.gz
gdb-3dbf33eeb425669fe2e4240e2038f77c6c2f241d.tar.bz2
* 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.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog5
-rw-r--r--bfd/elf.c122
2 files changed, 124 insertions, 3 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index d9c4856..c926043 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,10 @@
Wed Nov 29 12:42:36 1995 Ian Lance Taylor <ian@cygnus.com>
+ * 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 ba00bc8..677bb45 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;