Add support for creating shared libraries under i386 ELF and SPARC

ELF.  Based on patches by Eric Youngdale <ericy@cais.cais.com>.
	* libelf.h (struct elf_link_hash_entry): Remove copy_offset field.
	Add got_offset and plt_offset fields.
	(ELF_LINK_HASH_REF_DYNAMIC_MULTIPLE): Don't define.
	(ELF_LINK_HASH_DEF_DYNAMIC_MULTIPLE): Don't define.
	(ELF_LINK_HASH_NEEDS_COPY): Define.
	(struct elf_backend_data): Add check_relocs field.
	(struct bfd_elf_section_data): Change relocs from PTR to
	Elf_Internal_Rela *.
	(struct elf_obj_tdata): Add local_got_offsets field.
	(elf_local_got_offsets): Define accessor macro.
	(bfd_elf32_link_create_dynamic_sections): Declare.
	(bfd_elf32_link_record_dynamic_symbol): Declare.
	(bfd_elf64_link_create_dynamic_sections): Declare.
	(bfd_elf64_link_record_dynamic_symbol): Declare.
	* elfcode.h (elf_slurp_reloc_table): Don't use the section data
	relocs field.
	(elf_link_record_dynamic_symbol): Make globally visible.  Use
	macro to rename to NAME(bfd_elf,link_record_dynamic_symbol).
	(elf_link_add_object_symbols): If creating a shared library, put
	make all local symbols dynamic.  Don't bother with the
	DYNAMIC_MULTIPLE flags.  Call the check_relocs backend function if
	it is defined.
	(elf_link_create_dynamic_sections): Make globally visible.  Use
	macro to rename to NAME(bfd_elf,link_create_dynamic_sections).  If
	creating a shared library, make sure that _DYNAMIC is added as a
	dynamic symbol.
	(elf_link_read_relocs): New function.
	(NAME(bfd_elf,record_link_assignment)): If creating a shared
	library, always create symbols, and always make them dynamic.
	(elf_bfd_final_link): Permit creation of shared libraries.
	(elf_link_input_bfd): Use elf_link_read_relocs to get the relocs.
	* elf.c (_bfd_elf_link_hash_newfunc): Don't initialize
	copy_offset.  Initialize got_offset and plt_offset.
	* elf32-target.h (elf_backend_check_relocs): Define as 0 if not
	defined.
	(elf32_bed): Initialize check_relocs field.
	* elf64-target.h (elf_backend_check_relocs): Define as 0 if not
	defined.
	(elf64_bed): Initialize check_relocs field.
	* elf32-i386.c (elf_howto_table): Change R_386_PLT32 and
	R_386_GOTPC to be pc_relative and pcrel_offset.
	(elf_i386_pic_plt0_entry): Define.
	(elf_i386_pic_plt_entry): Define.
	(elf_i386_create_dynamic_sections): Create a .got.plt section, and
	define _GLOBAL_OFFSET_TABLE_ at the start of it.  If creating a
	shared library, make sure that _GLOBAL_OFFSET_TABLE_ is added as a
	dynamic symbol.  Don't create .rel.bss if creating a shared
	library.
	(elf_i386_check_relocs): New function.
	(elf_i386_adjust_dynamic_symbol): Don't make a PLT entry if the
	symbol already has one.  When making a PLT entry, set plt_offset.
	Don't create a copy reloc when creating a shared library.  Don't
	set copy_offset, just set ELF_LINK_HASH_NEEDS_COPY.
	(elf_i386_allocate_dynamic_section): Remove.
	(elf_i386_size_dynamic_sections): Look through all the sections
	rather than assuming we know their names.  Remove any empty reloc
	or plt sections.  Only add a DT_DEBUG entry if not creating a
	shared library.  Only add a DT_PLTGOT entry if there is a PLT.
	Add a DT_TEXTREL entry if required.
	(elf_i386_relocate_section): Permit undefined symbols when
	creating a shared library.  Handle the special relocation types
	specially.
	(elf_i386_finish_dynamic_symbol): Create a PLT entry if plt_offset
	is set.  If creating a shared library, produce a PIC PLT entry.
	Only mark a PLT symbol as undefined if it was not defined by a
	regular object file.  Create a GOT entry if got_offset is set.
	Create a copy reloc if ELF_LINK_HASH_NEEDS_COPY is set.
	(elf_i386_finish_dynamic_sections): Change the handling of
	DT_RELSZ to simply subtract out the size of .rel.plt.  If creating
	a shared library, produce PIC PLT code.
	(elf_backend_check_relocs): Define.
	* elf32-sparc.c (elf_sparc_howto_table): Change R_SPARC_GOT10,
	R_SPARC_GOT22, and R_SPARC_PC10 to not warn about reloc overflow.
	(elf32_sparc_create_dynamic_sections): If creating a shared
	library, make sure that _GLOBAL_OFFSET_TABLE_ is added as a
        dynamic symbol, and set the type to STT_OBJECT.  Likewise for
        _PROCEDURE_LINKAGE_TABLE_.  Don't create .rel.bss if creating a
        shared library.
	(elf32_sparc_check_relocs): New function.
	(elf32_sparc_adjust_dynamic_symbol): Don't make a PLT entry if the
	symbol already has one.  When making a PLT entry, set plt_offset.
	Don't create a copy reloc when creating a shared library.  Don't
	set copy_offset, just set ELF_LINK_HASH_NEEDS_COPY.
	(elf32_sparc_allocate_dynamic_section): Remove.
	(elf32_sparc_size_dynamic_sections): Look through all the sections
	rather than assuming we know their names.  Only add a DT_DEBUG
	entry if not creating a shared library.  Add a DT_TEXTREL entry if
	required.
	(elf32_sparc_relocate_section): Permit undefined symbols when
	creating a shared library.  Handle the special relocation types
	specially.
	(elf32_sparc_finish_dynamic_symbol): Create a PLT entry if plt_offset
	is set.  Only mark a PLT symbol as undefined if it was not defined
	by a regular object file.  Create a GOT entry if got_offset is
	set.  Create a copy reloc if ELF_LINK_HASH_NEEDS_COPY is set.
	(elf32_sparc_finish_dynamic_sections): Store dynobj in a local
	variable.
	(elf_backend_check_relocs): Define.
This commit is contained in:
Ian Lance Taylor 1994-07-26 17:18:37 +00:00
parent b019d460d1
commit 374d2ef905
5 changed files with 412 additions and 141 deletions

View File

@ -1,3 +1,106 @@
Tue Jul 26 11:04:00 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
Add support for creating shared libraries under i386 ELF and SPARC
ELF. Based on patches by Eric Youngdale <ericy@cais.cais.com>.
* libelf.h (struct elf_link_hash_entry): Remove copy_offset field.
Add got_offset and plt_offset fields.
(ELF_LINK_HASH_REF_DYNAMIC_MULTIPLE): Don't define.
(ELF_LINK_HASH_DEF_DYNAMIC_MULTIPLE): Don't define.
(ELF_LINK_HASH_NEEDS_COPY): Define.
(struct elf_backend_data): Add check_relocs field.
(struct bfd_elf_section_data): Change relocs from PTR to
Elf_Internal_Rela *.
(struct elf_obj_tdata): Add local_got_offsets field.
(elf_local_got_offsets): Define accessor macro.
(bfd_elf32_link_create_dynamic_sections): Declare.
(bfd_elf32_link_record_dynamic_symbol): Declare.
(bfd_elf64_link_create_dynamic_sections): Declare.
(bfd_elf64_link_record_dynamic_symbol): Declare.
* elfcode.h (elf_slurp_reloc_table): Don't use the section data
relocs field.
(elf_link_record_dynamic_symbol): Make globally visible. Use
macro to rename to NAME(bfd_elf,link_record_dynamic_symbol).
(elf_link_add_object_symbols): If creating a shared library, put
make all local symbols dynamic. Don't bother with the
DYNAMIC_MULTIPLE flags. Call the check_relocs backend function if
it is defined.
(elf_link_create_dynamic_sections): Make globally visible. Use
macro to rename to NAME(bfd_elf,link_create_dynamic_sections). If
creating a shared library, make sure that _DYNAMIC is added as a
dynamic symbol.
(elf_link_read_relocs): New function.
(NAME(bfd_elf,record_link_assignment)): If creating a shared
library, always create symbols, and always make them dynamic.
(elf_bfd_final_link): Permit creation of shared libraries.
(elf_link_input_bfd): Use elf_link_read_relocs to get the relocs.
* elf.c (_bfd_elf_link_hash_newfunc): Don't initialize
copy_offset. Initialize got_offset and plt_offset.
* elf32-target.h (elf_backend_check_relocs): Define as 0 if not
defined.
(elf32_bed): Initialize check_relocs field.
* elf64-target.h (elf_backend_check_relocs): Define as 0 if not
defined.
(elf64_bed): Initialize check_relocs field.
* elf32-i386.c (elf_howto_table): Change R_386_PLT32 and
R_386_GOTPC to be pc_relative and pcrel_offset.
(elf_i386_pic_plt0_entry): Define.
(elf_i386_pic_plt_entry): Define.
(elf_i386_create_dynamic_sections): Create a .got.plt section, and
define _GLOBAL_OFFSET_TABLE_ at the start of it. If creating a
shared library, make sure that _GLOBAL_OFFSET_TABLE_ is added as a
dynamic symbol. Don't create .rel.bss if creating a shared
library.
(elf_i386_check_relocs): New function.
(elf_i386_adjust_dynamic_symbol): Don't make a PLT entry if the
symbol already has one. When making a PLT entry, set plt_offset.
Don't create a copy reloc when creating a shared library. Don't
set copy_offset, just set ELF_LINK_HASH_NEEDS_COPY.
(elf_i386_allocate_dynamic_section): Remove.
(elf_i386_size_dynamic_sections): Look through all the sections
rather than assuming we know their names. Remove any empty reloc
or plt sections. Only add a DT_DEBUG entry if not creating a
shared library. Only add a DT_PLTGOT entry if there is a PLT.
Add a DT_TEXTREL entry if required.
(elf_i386_relocate_section): Permit undefined symbols when
creating a shared library. Handle the special relocation types
specially.
(elf_i386_finish_dynamic_symbol): Create a PLT entry if plt_offset
is set. If creating a shared library, produce a PIC PLT entry.
Only mark a PLT symbol as undefined if it was not defined by a
regular object file. Create a GOT entry if got_offset is set.
Create a copy reloc if ELF_LINK_HASH_NEEDS_COPY is set.
(elf_i386_finish_dynamic_sections): Change the handling of
DT_RELSZ to simply subtract out the size of .rel.plt. If creating
a shared library, produce PIC PLT code.
(elf_backend_check_relocs): Define.
* elf32-sparc.c (elf_sparc_howto_table): Change R_SPARC_GOT10,
R_SPARC_GOT22, and R_SPARC_PC10 to not warn about reloc overflow.
(elf32_sparc_create_dynamic_sections): If creating a shared
library, make sure that _GLOBAL_OFFSET_TABLE_ is added as a
dynamic symbol, and set the type to STT_OBJECT. Likewise for
_PROCEDURE_LINKAGE_TABLE_. Don't create .rel.bss if creating a
shared library.
(elf32_sparc_check_relocs): New function.
(elf32_sparc_adjust_dynamic_symbol): Don't make a PLT entry if the
symbol already has one. When making a PLT entry, set plt_offset.
Don't create a copy reloc when creating a shared library. Don't
set copy_offset, just set ELF_LINK_HASH_NEEDS_COPY.
(elf32_sparc_allocate_dynamic_section): Remove.
(elf32_sparc_size_dynamic_sections): Look through all the sections
rather than assuming we know their names. Only add a DT_DEBUG
entry if not creating a shared library. Add a DT_TEXTREL entry if
required.
(elf32_sparc_relocate_section): Permit undefined symbols when
creating a shared library. Handle the special relocation types
specially.
(elf32_sparc_finish_dynamic_symbol): Create a PLT entry if plt_offset
is set. Only mark a PLT symbol as undefined if it was not defined
by a regular object file. Create a GOT entry if got_offset is
set. Create a copy reloc if ELF_LINK_HASH_NEEDS_COPY is set.
(elf32_sparc_finish_dynamic_sections): Store dynobj in a local
variable.
(elf_backend_check_relocs): Define.
Mon Jul 25 12:21:07 1994 Stan Shebs (shebs@andros.cygnus.com)
* configure.in (pc532mach_vec): Change to pc532machaout_vec.

View File

@ -121,6 +121,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef elf_backend_create_dynamic_sections
#define elf_backend_create_dynamic_sections 0
#endif
#ifndef elf_backend_check_relocs
#define elf_backend_check_relocs 0
#endif
#ifndef elf_backend_adjust_dynamic_symbol
#define elf_backend_adjust_dynamic_symbol 0
#endif
@ -171,6 +174,7 @@ static CONST struct elf_backend_data elf32_bed =
elf_backend_add_symbol_hook,
elf_backend_link_output_symbol_hook,
elf_backend_create_dynamic_sections,
elf_backend_check_relocs,
elf_backend_adjust_dynamic_symbol,
elf_backend_size_dynamic_sections,
elf_backend_relocate_section,

View File

@ -124,6 +124,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef elf_backend_create_dynamic_sections
#define elf_backend_create_dynamic_sections 0
#endif
#ifndef elf_backend_check_relocs
#define elf_backend_check_relocs 0
#endif
#ifndef elf_backend_adjust_dynamic_symbol
#define elf_backend_adjust_dynamic_symbol 0
#endif
@ -174,6 +177,7 @@ static CONST struct elf_backend_data elf64_bed =
elf_backend_add_symbol_hook,
elf_backend_link_output_symbol_hook,
elf_backend_create_dynamic_sections,
elf_backend_check_relocs,
elf_backend_adjust_dynamic_symbol,
elf_backend_size_dynamic_sections,
elf_backend_relocate_section,

View File

@ -116,6 +116,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define elf_find_section NAME(bfd_elf,find_section)
#define elf_bfd_link_add_symbols NAME(bfd_elf,bfd_link_add_symbols)
#define elf_add_dynamic_entry NAME(bfd_elf,add_dynamic_entry)
#define elf_link_create_dynamic_sections \
NAME(bfd_elf,link_create_dynamic_sections)
#define elf_link_record_dynamic_symbol \
NAME(bfd_elf,link_record_dynamic_symbol)
#define elf_bfd_final_link NAME(bfd_elf,bfd_final_link)
#if ARCH_SIZE == 64
@ -2931,24 +2935,20 @@ elf_slurp_reloc_table (abfd, asect, symbols)
&& (asect->reloc_count
== d->rel_hdr.sh_size / d->rel_hdr.sh_entsize));
native_relocs = (bfd_byte *) elf_section_data (asect)->relocs;
if (native_relocs == NULL)
allocated = (PTR) malloc (d->rel_hdr.sh_size);
if (allocated == NULL)
{
allocated = (PTR) malloc (d->rel_hdr.sh_size);
if (allocated == NULL)
{
bfd_set_error (bfd_error_no_memory);
goto error_return;
}
if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0
|| (bfd_read (allocated, 1, d->rel_hdr.sh_size, abfd)
!= d->rel_hdr.sh_size))
goto error_return;
native_relocs = (bfd_byte *) allocated;
bfd_set_error (bfd_error_no_memory);
goto error_return;
}
if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0
|| (bfd_read (allocated, 1, d->rel_hdr.sh_size, abfd)
!= d->rel_hdr.sh_size))
goto error_return;
native_relocs = (bfd_byte *) allocated;
relents = ((arelent *)
bfd_alloc (abfd, asect->reloc_count * sizeof (arelent)));
if (relents == NULL)
@ -3750,10 +3750,8 @@ static boolean elf_link_add_object_symbols
PARAMS ((bfd *, struct bfd_link_info *));
static boolean elf_link_add_archive_symbols
PARAMS ((bfd *, struct bfd_link_info *));
static INLINE boolean elf_link_record_dynamic_symbol
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
static boolean elf_link_create_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
static Elf_Internal_Rela *elf_link_read_relocs
PARAMS ((bfd *, asection *, PTR, Elf_Internal_Rela *, boolean));
static boolean elf_adjust_dynamic_symbol
PARAMS ((struct elf_link_hash_entry *, PTR));
@ -3947,7 +3945,7 @@ elf_link_add_archive_symbols (abfd, info)
read the input files, since we need to have a list of all of them
before we can determine the final sizes of the output sections. */
static INLINE boolean
INLINE boolean
elf_link_record_dynamic_symbol (info, h)
struct bfd_link_info *info;
struct elf_link_hash_entry *h;
@ -3977,6 +3975,8 @@ elf_link_add_object_symbols (abfd, info)
const Elf_Internal_Sym *,
const char **, flagword *,
asection **, bfd_vma *));
boolean (*check_relocs) PARAMS ((bfd *, struct bfd_link_info *,
asection *, const Elf_Internal_Rela *));
boolean collect;
Elf_Internal_Shdr *hdr;
size_t symcount;
@ -4055,9 +4055,9 @@ elf_link_add_object_symbols (abfd, info)
dynamic = true;
/* You can't use -r against a dynamic object. There's no hope
of using a dynamic object which does not exactly match the
format of the output file. */
/* You can't use -r against a dynamic object. Also, there's no
hope of using a dynamic object which does not exactly match
the format of the output file. */
if (info->relocateable
|| info->hash->creator != abfd->xvec)
{
@ -4143,7 +4143,6 @@ elf_link_add_object_symbols (abfd, info)
strindex = bfd_add_to_strtab (abfd,
elf_hash_table (info)->dynstr,
name);
if (strindex == (unsigned long) -1)
goto error_return;
if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex))
@ -4334,6 +4333,7 @@ elf_link_add_object_symbols (abfd, info)
weaks = *sym_hash;
}
/* Get the alignment of a common symbol. */
if (sym.st_shndx == SHN_COMMON
&& h->root.type == bfd_link_hash_common)
h->root.u.c.alignment_power = bfd_log2 (sym.st_value);
@ -4344,7 +4344,7 @@ elf_link_add_object_symbols (abfd, info)
boolean dynsym;
int new_flag;
/* Remember the symbol size, type and alignment. */
/* Remember the symbol size and type. */
if (sym.st_size != 0)
{
/* FIXME: We should probably somehow give a warning if
@ -4372,8 +4372,9 @@ elf_link_add_object_symbols (abfd, info)
new_flag = ELF_LINK_HASH_REF_REGULAR;
else
new_flag = ELF_LINK_HASH_DEF_REGULAR;
if ((old_flags & (ELF_LINK_HASH_DEF_DYNAMIC
| ELF_LINK_HASH_REF_DYNAMIC)) != 0)
if (info->shared
|| (old_flags & (ELF_LINK_HASH_DEF_DYNAMIC
| ELF_LINK_HASH_REF_DYNAMIC)) != 0)
dynsym = true;
}
else
@ -4382,20 +4383,10 @@ elf_link_add_object_symbols (abfd, info)
new_flag = ELF_LINK_HASH_REF_DYNAMIC;
else
new_flag = ELF_LINK_HASH_DEF_DYNAMIC;
if ((old_flags & new_flag) != 0)
{
if (! definition)
new_flag = ELF_LINK_HASH_REF_DYNAMIC_MULTIPLE;
else
new_flag = ELF_LINK_HASH_DEF_DYNAMIC_MULTIPLE;
dynsym = true;
}
else
{
if ((old_flags & (ELF_LINK_HASH_DEF_REGULAR
| ELF_LINK_HASH_REF_REGULAR)) != 0)
dynsym = true;
}
if ((old_flags & new_flag) != 0
|| (old_flags & (ELF_LINK_HASH_DEF_REGULAR
| ELF_LINK_HASH_REF_REGULAR)) != 0)
dynsym = true;
}
h->elf_link_hash_flags |= new_flag;
@ -4466,7 +4457,65 @@ elf_link_add_object_symbols (abfd, info)
}
if (buf != NULL)
free (buf);
{
free (buf);
buf = NULL;
}
/* If this object is the same format as the output object, and it is
not a shared library, then let the backend look through the
relocs.
This is required to build global offset table entries and to
arrange for dynamic relocs. It is not required for the
particular common case of linking non PIC code, even when linking
against shared libraries, but unfortunately there is no way of
knowing whether an object file has been compiled PIC or not.
Looking through the relocs is not particularly time consuming.
The problem is that we must either (1) keep the relocs in memory,
which causes the linker to require additional runtime memory or
(2) read the relocs twice from the input file, which wastes time.
This would be a good case for using mmap.
I have no idea how to handle linking PIC code into a file of a
different format. It probably can't be done. */
check_relocs = get_elf_backend_data (abfd)->check_relocs;
if (! dynamic
&& abfd->xvec == info->hash->creator
&& check_relocs != NULL)
{
asection *o;
for (o = abfd->sections; o != NULL; o = o->next)
{
Elf_Internal_Rela *internal_relocs;
boolean ok;
if ((o->flags & SEC_RELOC) == 0
|| o->reloc_count == 0)
continue;
/* I believe we can ignore the relocs for any section which
does not form part of the final process image, such as a
debugging section. */
if ((o->flags & SEC_ALLOC) == 0)
continue;
internal_relocs = elf_link_read_relocs (abfd, o, (PTR) NULL,
(Elf_Internal_Rela *) NULL,
info->keep_memory);
if (internal_relocs == NULL)
goto error_return;
ok = (*check_relocs) (abfd, info, o, internal_relocs);
if (! info->keep_memory)
free (internal_relocs);
if (! ok)
goto error_return;
}
}
return true;
@ -4485,7 +4534,7 @@ elf_link_add_object_symbols (abfd, info)
are assigned to the output sections. We work out the actual
contents and size of these sections later. */
static boolean
boolean
elf_link_create_dynamic_sections (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
@ -4509,6 +4558,25 @@ elf_link_create_dynamic_sections (abfd, info)
return false;
}
s = bfd_make_section (abfd, ".dynsym");
if (s == NULL
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
|| ! bfd_set_section_alignment (abfd, s, LOG_FILE_ALIGN))
return false;
/* The first .dynsym symbol is a dummy. */
elf_hash_table (info)->dynsymcount = 1;
s = bfd_make_section (abfd, ".dynstr");
if (s == NULL
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY))
return false;
/* Create a strtab to hold the dynamic symbol names. */
elf_hash_table (info)->dynstr = bfd_new_strtab (abfd);
if (elf_hash_table (info)->dynstr == NULL)
return false;
s = bfd_make_section (abfd, ".dynamic");
if (s == NULL
|| ! bfd_set_section_flags (abfd, s, flags)
@ -4530,24 +4598,9 @@ elf_link_create_dynamic_sections (abfd, info)
(struct bfd_link_hash_entry **) &h)))
return false;
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
s = bfd_make_section (abfd, ".dynsym");
if (s == NULL
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
|| ! bfd_set_section_alignment (abfd, s, LOG_FILE_ALIGN))
return false;
/* The first .dynsym symbol is a dummy. */
elf_hash_table (info)->dynsymcount = 1;
s = bfd_make_section (abfd, ".dynstr");
if (s == NULL
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY))
return false;
/* Create a strtab to hold the dynamic symbol names. */
elf_hash_table (info)->dynstr = bfd_new_strtab (abfd);
if (elf_hash_table (info)->dynstr == NULL)
if (info->shared
&& ! elf_link_record_dynamic_symbol (info, h))
return false;
s = bfd_make_section (abfd, ".hash");
@ -4604,6 +4657,122 @@ elf_add_dynamic_entry (info, tag, val)
return true;
}
/* Read and swap the relocs for a section. They may have been cached.
If the EXTERNAL_RELOCS and INTERNAL_RELOCS arguments are not NULL,
they are used as buffers to read into. They are known to be large
enough. If the INTERNAL_RELOCS relocs argument is NULL, the return
value is allocated using either malloc or bfd_alloc, according to
the KEEP_MEMORY argument. */
static Elf_Internal_Rela *
elf_link_read_relocs (abfd, o, external_relocs, internal_relocs, keep_memory)
bfd *abfd;
asection *o;
PTR external_relocs;
Elf_Internal_Rela *internal_relocs;
boolean keep_memory;
{
Elf_Internal_Shdr *rel_hdr;
PTR alloc1 = NULL;
Elf_Internal_Rela *alloc2 = NULL;
if (elf_section_data (o)->relocs != NULL)
return elf_section_data (o)->relocs;
if (o->reloc_count == 0)
return NULL;
rel_hdr = &elf_section_data (o)->rel_hdr;
if (internal_relocs == NULL)
{
size_t size;
size = o->reloc_count * sizeof (Elf_Internal_Rela);
if (keep_memory)
internal_relocs = (Elf_Internal_Rela *) bfd_alloc (abfd, size);
else
internal_relocs = alloc2 = (Elf_Internal_Rela *) malloc (size);
if (internal_relocs == NULL)
{
bfd_set_error (bfd_error_no_memory);
goto error_return;
}
}
if (external_relocs == NULL)
{
alloc1 = (PTR) malloc (rel_hdr->sh_size);
if (alloc1 == NULL)
{
bfd_set_error (bfd_error_no_memory);
goto error_return;
}
external_relocs = alloc1;
}
if ((bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0)
|| (bfd_read (external_relocs, 1, rel_hdr->sh_size, abfd)
!= rel_hdr->sh_size))
goto error_return;
/* Swap in the relocs. For convenience, we always produce an
Elf_Internal_Rela array; if the relocs are Rel, we set the addend
to 0. */
if (rel_hdr->sh_entsize == sizeof (Elf_External_Rel))
{
Elf_External_Rel *erel;
Elf_External_Rel *erelend;
Elf_Internal_Rela *irela;
erel = (Elf_External_Rel *) external_relocs;
erelend = erel + o->reloc_count;
irela = internal_relocs;
for (; erel < erelend; erel++, irela++)
{
Elf_Internal_Rel irel;
elf_swap_reloc_in (abfd, erel, &irel);
irela->r_offset = irel.r_offset;
irela->r_info = irel.r_info;
irela->r_addend = 0;
}
}
else
{
Elf_External_Rela *erela;
Elf_External_Rela *erelaend;
Elf_Internal_Rela *irela;
BFD_ASSERT (rel_hdr->sh_entsize == sizeof (Elf_External_Rela));
erela = (Elf_External_Rela *) external_relocs;
erelaend = erela + o->reloc_count;
irela = internal_relocs;
for (; erela < erelaend; erela++, irela++)
elf_swap_reloca_in (abfd, erela, irela);
}
/* Cache the results for next time, if we can. */
if (keep_memory)
elf_section_data (o)->relocs = internal_relocs;
if (alloc1 != NULL)
free (alloc1);
/* Don't free alloc2, since if it was allocated we are passing it
back (under the name of internal_relocs). */
return internal_relocs;
error_return:
if (alloc1 != NULL)
free (alloc1);
if (alloc2 != NULL)
free (alloc2);
return NULL;
}
/* Record an assignment to a symbol made by a linker script. We need
this in case some dynamic object refers to this symbol. */
@ -4617,17 +4786,20 @@ NAME(bfd_elf,record_link_assignment) (output_bfd, info, name)
struct elf_link_hash_entry *h;
/* This is called after we have examined all the input objects. If
the symbol does not exist, it merely means that no object refers
to it, and we can just ignore it at this point. */
we are generating a shared library, we always output these
symbols. Otherwise, if the symbol does not exist, it merely
means that no object refers to it, and we can just ignore it at
this point. */
h = elf_link_hash_lookup (elf_hash_table (info), name,
false, false, false);
info->shared, info->shared, false);
if (h == NULL)
return true;
return ! info->shared;
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
if ((h->elf_link_hash_flags & (ELF_LINK_HASH_DEF_DYNAMIC
| ELF_LINK_HASH_REF_DYNAMIC)) != 0
if (((h->elf_link_hash_flags & (ELF_LINK_HASH_DEF_DYNAMIC
| ELF_LINK_HASH_REF_DYNAMIC)) != 0
|| info->shared)
&& h->dynindx == -1)
{
if (! elf_link_record_dynamic_symbol (info, h))
@ -4969,12 +5141,7 @@ elf_bfd_final_link (abfd, info)
struct elf_backend_data *bed = get_elf_backend_data (abfd);
if (info->shared)
{
fprintf (stderr,
"Generating ELF shared libraries is not yet supported\n");
bfd_set_error (bfd_error_invalid_operation);
return false;
}
abfd->flags |= DYNAMIC;
dynobj = elf_hash_table (info)->dynobj;
@ -5936,8 +6103,6 @@ elf_link_input_bfd (finfo, input_bfd)
/* Relocate the contents of each section. */
for (o = input_bfd->sections; o != NULL; o = o->next)
{
Elf_Internal_Shdr *input_rel_hdr;
if ((o->flags & SEC_HAS_CONTENTS) == 0)
continue;
@ -5956,59 +6121,16 @@ elf_link_input_bfd (finfo, input_bfd)
if ((o->flags & SEC_RELOC) != 0)
{
PTR external_relocs;
Elf_Internal_Rela *internal_relocs;
/* Get the external relocs. They may have been cached. */
external_relocs = elf_section_data (o)->relocs;
if (external_relocs == NULL)
{
input_rel_hdr = &elf_section_data (o)->rel_hdr;
if ((bfd_seek (input_bfd, input_rel_hdr->sh_offset, SEEK_SET)
!= 0)
|| (bfd_read (finfo->external_relocs, 1,
input_rel_hdr->sh_size, input_bfd)
!= input_rel_hdr->sh_size))
return false;
external_relocs = finfo->external_relocs;
}
/* Swap in the relocs. For convenience, we always produce
an Elf_Internal_Rela array; if the relocs are Rel, we set
the addend to 0. */
if (input_rel_hdr->sh_entsize == sizeof (Elf_External_Rel))
{
Elf_External_Rel *erel;
Elf_External_Rel *erelend;
Elf_Internal_Rela *irela;
erel = (Elf_External_Rel *) external_relocs;
erelend = erel + o->reloc_count;
irela = finfo->internal_relocs;
for (; erel < erelend; erel++, irela++)
{
Elf_Internal_Rel irel;
elf_swap_reloc_in (input_bfd, erel, &irel);
irela->r_offset = irel.r_offset;
irela->r_info = irel.r_info;
irela->r_addend = 0;
}
}
else
{
Elf_External_Rela *erela;
Elf_External_Rela *erelaend;
Elf_Internal_Rela *irela;
BFD_ASSERT (input_rel_hdr->sh_entsize
== sizeof (Elf_External_Rela));
erela = (Elf_External_Rela *) external_relocs;
erelaend = erela + o->reloc_count;
irela = finfo->internal_relocs;
for (; erela < erelaend; erela++, irela++)
elf_swap_reloca_in (input_bfd, erela, irela);
}
/* Get the swapped relocs. */
internal_relocs = elf_link_read_relocs (input_bfd, o,
finfo->external_relocs,
finfo->internal_relocs,
false);
if (internal_relocs == NULL
&& o->reloc_count > 0)
return false;
/* Relocate the section by invoking a back end routine.
@ -6033,7 +6155,7 @@ elf_link_input_bfd (finfo, input_bfd)
if (! (*relocate_section) (output_bfd, finfo->info,
input_bfd, o,
finfo->contents,
finfo->internal_relocs,
internal_relocs,
finfo->internal_syms,
finfo->sections,
finfo->symstrtab->tab))
@ -6044,11 +6166,12 @@ elf_link_input_bfd (finfo, input_bfd)
Elf_Internal_Rela *irela;
Elf_Internal_Rela *irelaend;
struct elf_link_hash_entry **rel_hash;
Elf_Internal_Shdr *input_rel_hdr;
Elf_Internal_Shdr *output_rel_hdr;
/* Adjust the reloc addresses and symbol indices. */
irela = finfo->internal_relocs;
irela = internal_relocs;
irelaend = irela + o->reloc_count;
rel_hash = (elf_section_data (o->output_section)->rel_hashes
+ o->output_section->reloc_count);
@ -6164,10 +6287,11 @@ elf_link_input_bfd (finfo, input_bfd)
}
/* Swap out the relocs. */
input_rel_hdr = &elf_section_data (o)->rel_hdr;
output_rel_hdr = &elf_section_data (o->output_section)->rel_hdr;
BFD_ASSERT (output_rel_hdr->sh_entsize
== input_rel_hdr->sh_entsize);
irela = finfo->internal_relocs;
irela = internal_relocs;
irelaend = irela + o->reloc_count;
if (input_rel_hdr->sh_entsize == sizeof (Elf_External_Rel))
{

View File

@ -89,9 +89,18 @@ struct elf_link_hash_entry
one. Otherwise it is NULL. */
struct elf_link_hash_entry *weakdef;
/* If we need to generate a COPY reloc, the processor specific
backend uses this to hold the offset into the reloc section. */
bfd_vma copy_offset;
/* If this symbol requires an entry in the global offset table, the
processor specific backend uses this field to hold the offset
into the .got section. If this field is -1, then the symbol does
not require a global offset table entry. */
bfd_vma got_offset;
/* If this symbol requires an entry in the procedure linkage table,
the processor specific backend uses these two fields to hold the
offset into the procedure linkage section and the offset into the
.got section. If plt_offset is -1, then the symbol does not
require an entry in the procedure linkage table. */
bfd_vma plt_offset;
/* Symbol type (STT_NOTYPE, STT_OBJECT, etc.). */
char type;
@ -106,14 +115,12 @@ struct elf_link_hash_entry
#define ELF_LINK_HASH_REF_DYNAMIC 04
/* Symbol is defined by a shared object. */
#define ELF_LINK_HASH_DEF_DYNAMIC 010
/* Symbol is referenced by two or more shared objects. */
#define ELF_LINK_HASH_REF_DYNAMIC_MULTIPLE 020
/* Symbol is defined by two or more shared objects. */
#define ELF_LINK_HASH_DEF_DYNAMIC_MULTIPLE 040
/* Dynamic symbol has been adjustd. */
#define ELF_LINK_HASH_DYNAMIC_ADJUSTED 0100
#define ELF_LINK_HASH_DYNAMIC_ADJUSTED 020
/* Symbol is defined as weak. */
#define ELF_LINK_HASH_DEFINED_WEAK 0200
#define ELF_LINK_HASH_DEFINED_WEAK 040
/* Symbol needs a copy reloc. */
#define ELF_LINK_HASH_NEEDS_COPY 0100
};
/* ELF linker hash table. */
@ -277,6 +284,20 @@ struct elf_backend_data
boolean (*elf_backend_create_dynamic_sections)
PARAMS ((bfd *abfd, struct bfd_link_info *info));
/* The CHECK_RELOCS function is called by the add_symbols phase of
the ELF backend linker. It is called once for each section with
relocs of an object file, just after the symbols for the object
file have been added to the global linker hash table. The
function must look through the relocs and do any special handling
required. This generally means allocating space in the global
offset table, and perhaps allocating space for a reloc. The
relocs are always passed as Rela structures; if the section
actually uses Rel structures, the r_addend field will always be
zero. */
boolean (*check_relocs)
PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *o,
const Elf_Internal_Rela *relocs));
/* The ADJUST_DYNAMIC_SYMBOL function is called by the ELF backend
linker for every symbol which is defined by a dynamic object and
referenced by a regular object. This is called after all the
@ -396,8 +417,10 @@ struct bfd_elf_section_data {
/* Used by the backend linker to store the symbol hash table entries
associated with relocs against global symbols. */
struct elf_link_hash_entry **rel_hashes;
/* A pointer to the unswapped external relocs; this may be NULL. */
PTR relocs;
/* A pointer to the swapped relocs. If the section uses REL relocs,
rather than RELA, all the r_addend fields will be zero. This
pointer may be NULL. It is used by the backend linker. */
Elf_Internal_Rela *relocs;
};
#define elf_section_data(sec) ((struct bfd_elf_section_data*)sec->used_by_bfd)
@ -443,6 +466,10 @@ struct elf_obj_tdata
minus the sh_info field of the symbol table header. */
struct elf_link_hash_entry **sym_hashes;
/* A mapping from local symbols to offsets into the global offset
table, used when linking. This is indexed by the symbol index. */
bfd_vma *local_got_offsets;
/* The linker ELF emulation code needs to let the backend ELF linker
know what filename should be used for a dynamic object if the
dynamic object is found using a search. This field is used to
@ -473,6 +500,7 @@ struct elf_obj_tdata
#define elf_gp(bfd) (elf_tdata(bfd) -> gp)
#define elf_gp_size(bfd) (elf_tdata(bfd) -> gp_size)
#define elf_sym_hashes(bfd) (elf_tdata(bfd) -> sym_hashes)
#define elf_local_got_offsets(bfd) (elf_tdata(bfd) -> local_got_offsets)
#define elf_dt_needed_name(bfd) (elf_tdata(bfd) -> dt_needed_name)
#define elf_bad_symtab(bfd) (elf_tdata(bfd) -> bad_symtab)
@ -565,6 +593,10 @@ extern void bfd_elf32_swap_dyn_out
PARAMS ((bfd *, const Elf_Internal_Dyn *, Elf32_External_Dyn *));
extern boolean bfd_elf32_add_dynamic_entry
PARAMS ((struct bfd_link_info *, bfd_vma, bfd_vma));
extern boolean bfd_elf32_link_create_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
extern boolean bfd_elf32_link_record_dynamic_symbol
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
/* If the target doesn't have reloc handling written yet: */
extern void bfd_elf32_no_info_to_howto PARAMS ((bfd *, arelent *,
@ -626,6 +658,10 @@ extern void bfd_elf64_swap_dyn_out
PARAMS ((bfd *, const Elf_Internal_Dyn *, Elf64_External_Dyn *));
extern boolean bfd_elf64_add_dynamic_entry
PARAMS ((struct bfd_link_info *, bfd_vma, bfd_vma));
extern boolean bfd_elf64_link_create_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
extern boolean bfd_elf64_link_record_dynamic_symbol
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
/* If the target doesn't have reloc handling written yet: */
extern void bfd_elf64_no_info_to_howto PARAMS ((bfd *, arelent *,