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:
parent
b019d460d1
commit
374d2ef905
103
bfd/ChangeLog
103
bfd/ChangeLog
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
384
bfd/elfcode.h
384
bfd/elfcode.h
|
@ -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))
|
||||
{
|
||||
|
|
58
bfd/libelf.h
58
bfd/libelf.h
|
@ -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 *,
|
||||
|
|
Loading…
Reference in New Issue