* 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

@ -1,5 +1,31 @@
Thu Jan 11 11:23:30 1996 Ian Lance Taylor <ian@cygnus.com>
* 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.
* elf-bfd.h (struct bfd_elf_section_data): Add tdata field.
(struct elf_obj_tdata): Rename ppc_flags_init field to flags_init.
(elf_flags_init): Rename from elf_ppc_flags_init.

View File

@ -212,6 +212,12 @@ struct elf_backend_data
section. */
boolean collect;
/* This is true if the linker should ignore changes to the type of a
symbol. This is true for MIPS ELF because some Irix 5 objects
record undefined functions as STT_OBJECT although the definitions
are STT_FUNC. */
boolean type_change_ok;
/* A function to translate an ELF RELA relocation to a BFD arelent
structure. */
void (*elf_info_to_howto) PARAMS ((bfd *, arelent *,
@ -412,13 +418,14 @@ struct elf_backend_data
void (*elf_backend_final_write_processing)
PARAMS ((bfd *, boolean linker));
/* A function to create any special program headers required by the
backend. PHDRS are the program headers, and PHDR_COUNT is the
number of them. If PHDRS is NULL, this just counts headers
without creating them. This returns an updated value for
PHDR_COUNT. */
int (*elf_backend_create_program_headers)
PARAMS ((bfd *, Elf_Internal_Phdr *phdrs, int phdr_count));
/* This function is called by get_program_header_size. It should
return the number of additional program segments which this BFD
will need. It should return -1 on error. */
int (*elf_backend_additional_program_headers) PARAMS ((bfd *));
/* This function is called to modify an existing segment map in a
backend specific fashion. */
boolean (*elf_backend_modify_segment_map) PARAMS ((bfd *));
/* The swapping table to use when dealing with ECOFF information.
Used for the MIPS ELF .mdebug section. */

View File

@ -576,6 +576,7 @@ bfd_section_from_shdr (abfd, shindex)
case SHT_DYNAMIC: /* Dynamic linking information. */
case SHT_NOBITS: /* .bss section. */
case SHT_HASH: /* .hash section. */
case SHT_NOTE: /* .note section. */
return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
case SHT_SYMTAB: /* A symbol table */
@ -752,9 +753,6 @@ bfd_section_from_shdr (abfd, shindex)
}
break;
case SHT_NOTE:
break;
case SHT_SHLIB:
return true;
@ -1746,6 +1744,12 @@ assign_file_positions_for_segments (abfd)
return false;
}
if (bed->elf_backend_modify_segment_map)
{
if (! (*bed->elf_backend_modify_segment_map) (abfd))
return false;
}
count = 0;
for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
++count;
@ -1757,11 +1761,6 @@ assign_file_positions_for_segments (abfd)
if (count == 0)
return true;
/* Let the backend count up any program headers it might need. */
if (bed->elf_backend_create_program_headers)
count = ((*bed->elf_backend_create_program_headers)
(abfd, (Elf_Internal_Phdr *) NULL, count));
/* If we already counted the number of program segments, make sure
that we allocated enough space. This happens when SIZEOF_HEADERS
is used in a linker script. */
@ -1978,11 +1977,6 @@ assign_file_positions_for_segments (abfd)
}
}
/* Let the backend set up any program headers it might need. */
if (bed->elf_backend_create_program_headers)
count = ((*bed->elf_backend_create_program_headers)
(abfd, phdrs, count));
/* Clear out any program headers we allocated but did not use. */
for (; count < alloc; count++, p++)
{
@ -2057,9 +2051,15 @@ get_program_header_size (abfd)
}
/* Let the backend count up any program headers it might need. */
if (bed->elf_backend_create_program_headers)
segs = ((*bed->elf_backend_create_program_headers)
(abfd, (Elf_Internal_Phdr *) NULL, segs));
if (bed->elf_backend_additional_program_headers)
{
int a;
a = (*bed->elf_backend_additional_program_headers) (abfd);
if (a == -1)
abort ();
segs += a;
}
elf_tdata (abfd)->program_header_size = segs * bed->s->sizeof_phdr;
return elf_tdata (abfd)->program_header_size;

File diff suppressed because it is too large Load Diff

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

View File

@ -156,6 +156,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef elf_backend_collect
#define elf_backend_collect false
#endif
#ifndef elf_backend_type_change_ok
#define elf_backend_type_change_ok false
#endif
#ifndef elf_backend_sym_is_global
#define elf_backend_sym_is_global 0
@ -214,8 +217,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef elf_backend_final_write_processing
#define elf_backend_final_write_processing 0
#endif
#ifndef elf_backend_create_program_headers
#define elf_backend_create_program_headers 0
#ifndef elf_backend_additional_program_headers
#define elf_backend_additional_program_headers 0
#endif
#ifndef elf_backend_modify_segment_map
#define elf_backend_modify_segment_map 0
#endif
#ifndef elf_backend_ecoff_debug_swap
#define elf_backend_ecoff_debug_swap 0
@ -242,6 +248,7 @@ static CONST struct elf_backend_data elfNN_bed =
ELF_MACHINE_CODE, /* elf_machine_code */
ELF_MAXPAGESIZE, /* maxpagesize */
elf_backend_collect,
elf_backend_type_change_ok,
elf_info_to_howto,
elf_info_to_howto_rel,
elf_backend_sym_is_global,
@ -263,7 +270,8 @@ static CONST struct elf_backend_data elfNN_bed =
elf_backend_finish_dynamic_sections,
elf_backend_begin_write_processing,
elf_backend_final_write_processing,
elf_backend_create_program_headers,
elf_backend_additional_program_headers,
elf_backend_modify_segment_map,
elf_backend_ecoff_debug_swap,
ELF_MACHINE_ALT1,
ELF_MACHINE_ALT2,
@ -283,11 +291,11 @@ const bfd_target TARGET_BIG_SYM =
/* flavour: general indication about file */
bfd_target_elf_flavour,
/* byteorder_big_p: data is big endian */
true,
/* byteorder: data is big endian */
BFD_ENDIAN_BIG,
/* header_byteorder_big_p: header is also big endian */
true,
/* header_byteorder: header is also big endian */
BFD_ENDIAN_BIG,
/* object_flags: mask of all file flags */
(HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS |
@ -367,11 +375,11 @@ const bfd_target TARGET_LITTLE_SYM =
/* flavour: general indication about file */
bfd_target_elf_flavour,
/* byteorder_big_p: data is big endian */
false, /* Nope -- this one's little endian */
/* byteorder: data is little endian */
BFD_ENDIAN_LITTLE,
/* header_byteorder_big_p: header is also big endian */
false, /* Nope -- this one's little endian */
/* header_byteorder: header is also little endian */
BFD_ENDIAN_LITTLE,
/* object_flags: mask of all file flags */
(HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS |