aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1994-07-26 17:18:37 +0000
committerIan Lance Taylor <ian@airs.com>1994-07-26 17:18:37 +0000
commit374d2ef9053ed629c495b9f9f07b7e4f70578f81 (patch)
treeae10177842c1a8edaacf8b4282365ed3fbab3eb5 /bfd
parentb019d460d18d477bd951cbc98f6372290775f50f (diff)
downloadgdb-374d2ef9053ed629c495b9f9f07b7e4f70578f81.zip
gdb-374d2ef9053ed629c495b9f9f07b7e4f70578f81.tar.gz
gdb-374d2ef9053ed629c495b9f9f07b7e4f70578f81.tar.bz2
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.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog103
-rw-r--r--bfd/elf32-target.h4
-rw-r--r--bfd/elf64-target.h4
-rw-r--r--bfd/elfcode.h384
-rw-r--r--bfd/libelf.h58
5 files changed, 412 insertions, 141 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index d008556..0d2dd49 100644
--- a/bfd/ChangeLog
+++ b/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.
diff --git a/bfd/elf32-target.h b/bfd/elf32-target.h
index 67dabec..c1091f2 100644
--- a/bfd/elf32-target.h
+++ b/bfd/elf32-target.h
@@ -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,
diff --git a/bfd/elf64-target.h b/bfd/elf64-target.h
index a85b5d0..006d60c 100644
--- a/bfd/elf64-target.h
+++ b/bfd/elf64-target.h
@@ -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,
diff --git a/bfd/elfcode.h b/bfd/elfcode.h
index fd02038..49f24c4 100644
--- a/bfd/elfcode.h
+++ b/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,23 +2935,19 @@ 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;
- }
+ 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;
+ 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;
- }
+ native_relocs = (bfd_byte *) allocated;
relents = ((arelent *)
bfd_alloc (abfd, asect->reloc_count * sizeof (arelent)));
@@ -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;
-
- /* 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);
- }
+ Elf_Internal_Rela *internal_relocs;
+
+ /* 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))
{
diff --git a/bfd/libelf.h b/bfd/libelf.h
index f14ac95..d43f135 100644
--- a/bfd/libelf.h
+++ b/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 *,