* elf32-mips.c: Extensive changes for a start at dynamic linking

support, from Kazumoto Kojima <kkojima@info.kanagawa-u.ac.jp>.

	* elf-bfd.h (struct elf_backend_data): Add type_change_ok field.
	(struct elf_backend_data): Remove
	elf_backend_create_program_headers field.  Add
	elf_backend_additional_program_headers and
	elf_backend_modify_segment_map fields.
	* elfxx-target.h (elf_backend_type_change_ok): Define if not
	defined.
	(elf_backend_additional_program_headers): Likewise.
	(elf_backend_modify_segment_map): Likewise.
	(elf_backend_create_program_headers): Don't define.
	(elfNN_bed): Change to account for field changes.
	* elf.c (assign_file_positions_for_segments): Call new
	modify_segment_map backend function.  Don't call old
	create_program_headers backend function.
	(get_program_header_size): Call additional_program_headers rather
	than create_program_headers.
	* elflink.h (elf_link_add_object_symbols): Initialize
	type_change_ok from new backend field.
	(elf_link_output_extsym): Don't warn if _rld_new_interface is
	defined.
	(elf_reloc_link_order): Treat a reloc against a defined symbol as
	a reloc against the appropriate section.
This commit is contained in:
Ian Lance Taylor
1996-01-11 21:06:42 +00:00
parent f9407a89f4
commit 5b3b9ff61d
6 changed files with 3049 additions and 269 deletions

View File

@@ -629,7 +629,7 @@ elf_link_add_object_symbols (abfd, info)
definition = true;
size_change_ok = false;
type_change_ok = false;
type_change_ok = get_elf_backend_data (abfd)->type_change_ok;
if (info->hash->creator->flavour == bfd_target_elf_flavour)
{
/* We need to look up the symbol now in order to get some of
@@ -648,15 +648,16 @@ elf_link_add_object_symbols (abfd, info)
/* It's OK to change the type if it used to be a weak
definition. */
type_change_ok = (h->root.type == bfd_link_hash_defweak
|| h->root.type == bfd_link_hash_undefweak);
if (h->root.type == bfd_link_hash_defweak
|| h->root.type == bfd_link_hash_undefweak)
type_change_ok = true;
/* It's OK to change the size if it used to be a weak
definition, or if it used to be undefined, or if we will
be overriding an old definition.
*/
size_change_ok = (type_change_ok
|| h->root.type == bfd_link_hash_undefined);
be overriding an old definition. */
if (type_change_ok
|| h->root.type == bfd_link_hash_undefined)
size_change_ok = true;
/* If we are looking at a dynamic object, and this is a
definition, we need to see if it has already been defined
@@ -2401,12 +2402,15 @@ elf_link_output_extsym (h, data)
linker will complain that the symbol is undefined when the
program is run. We don't have to worry about symbols that are
referenced by regular files, because we will already have issued
warnings for them. */
warnings for them. FIXME: _rld_new_interface is apparently
supposed to be undefined on Irix 5.3. This should be handled in
a better way. */
if (! finfo->info->relocateable
&& ! finfo->info->shared
&& h->root.type == bfd_link_hash_undefined
&& (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0
&& (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
&& (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0
&& strcmp (h->root.root.string, "_rld_new_interface") != 0)
{
if (! ((*finfo->info->callbacks->undefined_symbol)
(finfo->info, h->root.root.string, h->root.u.undef.abfd,
@@ -2987,6 +2991,7 @@ elf_reloc_link_order (output_bfd, info, output_section, link_order)
reloc_howto_type *howto;
long indx;
bfd_vma offset;
bfd_vma addend;
struct elf_link_hash_entry **rel_hash_ptr;
Elf_Internal_Shdr *rel_hdr;
@@ -2997,50 +3002,7 @@ elf_reloc_link_order (output_bfd, info, output_section, link_order)
return false;
}
/* If this is an inplace reloc, we must write the addend into the
object file. */
if (howto->partial_inplace
&& link_order->u.reloc.p->addend != 0)
{
bfd_size_type size;
bfd_reloc_status_type rstat;
bfd_byte *buf;
boolean ok;
size = bfd_get_reloc_size (howto);
buf = (bfd_byte *) bfd_zmalloc (size);
if (buf == (bfd_byte *) NULL)
return false;
rstat = _bfd_relocate_contents (howto, output_bfd,
link_order->u.reloc.p->addend, buf);
switch (rstat)
{
case bfd_reloc_ok:
break;
default:
case bfd_reloc_outofrange:
abort ();
case bfd_reloc_overflow:
if (! ((*info->callbacks->reloc_overflow)
(info,
(link_order->type == bfd_section_reloc_link_order
? bfd_section_name (output_bfd,
link_order->u.reloc.p->u.section)
: link_order->u.reloc.p->u.name),
howto->name, link_order->u.reloc.p->addend,
(bfd *) NULL, (asection *) NULL, (bfd_vma) 0)))
{
free (buf);
return false;
}
break;
}
ok = bfd_set_section_contents (output_bfd, output_section, (PTR) buf,
(file_ptr) link_order->offset, size);
free (buf);
if (! ok)
return false;
}
addend = link_order->u.reloc.p->addend;
/* Figure out the symbol index. */
rel_hash_ptr = (elf_section_data (output_section)->rel_hashes
@@ -3055,10 +3017,26 @@ elf_reloc_link_order (output_bfd, info, output_section, link_order)
{
struct elf_link_hash_entry *h;
/* Treat a reloc against a defined symbol as though it were
actually against the section. */
h = elf_link_hash_lookup (elf_hash_table (info),
link_order->u.reloc.p->u.name,
false, false, true);
if (h != NULL)
if (h != NULL
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak))
{
asection *section;
section = h->root.u.def.section;
indx = section->output_section->target_index;
*rel_hash_ptr = NULL;
/* It seems that we ought to add the symbol value to the
addend here, but in practice it has already been added
because it was passed to constructor_callback. */
addend += section->output_section->vma + section->output_offset;
}
else if (h != NULL)
{
/* Setting the index to -2 tells elf_link_output_extsym that
this symbol is used by a reloc. */
@@ -3076,6 +3054,49 @@ elf_reloc_link_order (output_bfd, info, output_section, link_order)
}
}
/* If this is an inplace reloc, we must write the addend into the
object file. */
if (howto->partial_inplace && addend != 0)
{
bfd_size_type size;
bfd_reloc_status_type rstat;
bfd_byte *buf;
boolean ok;
size = bfd_get_reloc_size (howto);
buf = (bfd_byte *) bfd_zmalloc (size);
if (buf == (bfd_byte *) NULL)
return false;
rstat = _bfd_relocate_contents (howto, output_bfd, addend, buf);
switch (rstat)
{
case bfd_reloc_ok:
break;
default:
case bfd_reloc_outofrange:
abort ();
case bfd_reloc_overflow:
if (! ((*info->callbacks->reloc_overflow)
(info,
(link_order->type == bfd_section_reloc_link_order
? bfd_section_name (output_bfd,
link_order->u.reloc.p->u.section)
: link_order->u.reloc.p->u.name),
howto->name, addend, (bfd *) NULL, (asection *) NULL,
(bfd_vma) 0)))
{
free (buf);
return false;
}
break;
}
ok = bfd_set_section_contents (output_bfd, output_section, (PTR) buf,
(file_ptr) link_order->offset, size);
free (buf);
if (! ok)
return false;
}
/* The address of a reloc is relative to the section in a
relocateable file, and is a virtual address in an executable
file. */
@@ -3103,7 +3124,7 @@ elf_reloc_link_order (output_bfd, info, output_section, link_order)
irela.r_offset = offset;
irela.r_info = ELF_R_INFO (indx, howto->type);
irela.r_addend = link_order->u.reloc.p->addend;
irela.r_addend = addend;
erela = ((Elf_External_Rela *) rel_hdr->contents
+ output_section->reloc_count);
elf_swap_reloca_out (output_bfd, &irela, erela);