* 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.
This commit is contained in:
Ian Lance Taylor 1995-11-29 20:04:17 +00:00
parent 44ef8897da
commit 3dbf33eeb4
2 changed files with 124 additions and 3 deletions

View file

@ -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.

122
bfd/elf.c
View file

@ -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;