diff options
author | Ian Lance Taylor <ian@airs.com> | 1994-05-19 18:23:40 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1994-05-19 18:23:40 +0000 |
commit | 013dec1ad95ef067951314b9f1beb2fa53296a6f (patch) | |
tree | c8f1921f6e06b5fa1b345d1b9a045a382868b642 /bfd/elf.c | |
parent | 4be9e22a91cbf326eb2f84af987b09326ac11bde (diff) | |
download | gdb-013dec1ad95ef067951314b9f1beb2fa53296a6f.zip gdb-013dec1ad95ef067951314b9f1beb2fa53296a6f.tar.gz gdb-013dec1ad95ef067951314b9f1beb2fa53296a6f.tar.bz2 |
Add support for ELF shared libraries. Loosely based on work by
Eric Youngdale <ericy@cais.com>.
* libelf.h (struct elf_backend_data): Add new fields for dynamic
linking: elf_backend_create_dynamic_sections,
elf_backend_adjust_dynamic_symbol,
elf_backend_size_dynamic_sections,
elf_backend_finish_dynamic_symbol,
elf_backend_finish_dynamic_sections.
(struct elf_link_hash_entry): Change type of align field to
bfd_size_type. Add fields dynindx, dynstr_index, weakdef,
elf_link_hash_flags.
(struct elf_link_hash_table): Add fields dynobj, dynsymcount,
dynstr, bucketcount.
(bfd_elf32_swap_reloc_in, bfd_elf32_swap_reloc_out): Declare.
(bfd_elf32_swap_reloca_in, bfd_elf32_swap_reloca_out): Declare.
(bfd_elf32_swap_dyn_in, bfd_elf32_swap_dyn_out): Declare.
(bfd_elf32_add_dynamic_entry): Declare.
(bfd_elf64_swap_reloc_in, bfd_elf64_swap_reloc_out): Declare.
(bfd_elf64_swap_reloca_in, bfd_elf64_swap_reloca_out): Declare.
(bfd_elf64_swap_dyn_in, bfd_elf64_swap_dyn_out): Declare.
(bfd_elf64_add_dynamic_entry): Declare.
* elfcode.h (Elf_External_Dyn): Define.
(elf_swap_reloc_in): Define as macro using NAME. Make externally
visible.
(elf_swap_reloc_out): Likewise.
(elf_swap_reloca_in, elf_swap_reloca_out): Likewise.
(elf_swap_dyn_in, elf_swap_dyn_out): Define as macro using NAME
and as new externally visible function.
(elf_fake_sections): Set section type of dynamic sections based on
section names.
(elf_write_phdrs): Remove.
(assign_file_position_for_section): Add new align argument.
Change all callers.
(get_program_header_size): New static function.
(struct seg_info): Remove.
(map_program_segments): Completely rewrite.
(assign_file_positions_except_relocs): Completely rewrite.
(assign_file_positions_for_relocs): Don't set a file position for
sections which already have one. Don't bother to align the file
position here.
(section_from_elf_index): Handle SHT_HASH and SHT_DYNAMIC
section types.
(elf_section_from_bfd_section): Likewise.
(elf_slurp_symbol_table): If section_from_elf_index fails, just
use bfd_abs_section rather than returning an error.
(elf_sizeof_headers): Make useful.
(elf_link_record_dynamic_symbol): New static function.
(elf_link_add_object_symbols): Handle dynamic objects.
(elf_link_create_dynamic_sections): New static function.
(elf_add_dynamic_entry): Define as macro using NAME and as new
externally visible function.
(NAME(bfd_elf,record_link_assignment)): New function.
(elf_buckets): New static variable.
(NAME(bfd_elf,size_dynamic_sections)): New function.
(struct elf_final_link_info): Add dynsym_sec and hash_sec fields.
(elf_bfd_final_link): Handle dynamic linking. Create a section
symbol for all ELF sections, not all BFD sections. Store section
symbol index in target_index field, not index field. Traverse
over global symbols even if stripping.
(elf_link_output_extsym): Output dynamic symbols. Mark symbols
defined by dynamic objects as undefined.
(elf_link_input_bfd): Ignore dynamic objects. Use target_index
field for section relocs, and make sure it is set.
(elf_reloc_link_order): Use target_index field for section relocs,
and make sure it is set.
* elf.c (elf_link_hash_newfunc): Initialize dynindx, dynstr_index,
weakdef and elf_link_hash_flags fields.
(_bfd_elf_link_hash_table_create): Initialize dynobj, dynsymcount,
dynstr and bucketcount fields.
* elf32-target.h: Initialize new dynamic linking fields.
* elf64-target.h: Likewise.
* elf32-i386.c: New functions for dynamic linking support.
* elf32-sparc.c: Likewise.
* bfd-in.h (bfd_elf32_record_link_assignment): Declare.
(bfd_elf64_record_link_assignment): Declare.
(bfd_elf32_size_dynamic_sections): Declare.
(bfd_elf64_size_dynamic_sections): Declare.
* bfd-in2.h: Rebuilt.
Diffstat (limited to 'bfd/elf.c')
-rw-r--r-- | bfd/elf.c | 125 |
1 files changed, 101 insertions, 24 deletions
@@ -33,6 +33,7 @@ SECTION #include "bfd.h" #include "sysdep.h" +#include "bfdlink.h" #include "libbfd.h" #define ARCH_SIZE 0 #include "libelf.h" @@ -41,8 +42,8 @@ SECTION cause invalid hash tables to be generated. (Well, you would if this were being used yet.) */ unsigned long -DEFUN (bfd_elf_hash, (name), - CONST unsigned char *name) +bfd_elf_hash (name) + CONST unsigned char *name; { unsigned long h = 0; unsigned long g; @@ -65,33 +66,32 @@ DEFUN (bfd_elf_hash, (name), buffer. */ static char * -DEFUN (elf_read, (abfd, offset, size), - bfd * abfd AND - long offset AND - int size) +elf_read (abfd, offset, size) + bfd * abfd; + long offset; + int size; { char *buf; if ((buf = bfd_alloc (abfd, size)) == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return NULL; } if (bfd_seek (abfd, offset, SEEK_SET) == -1) - { - bfd_error = system_call_error; - return NULL; - } + return NULL; if (bfd_read ((PTR) buf, size, 1, abfd) != size) { - bfd_error = system_call_error; + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_file_truncated); return NULL; } return buf; } boolean -DEFUN (elf_mkobject, (abfd), bfd * abfd) +elf_mkobject (abfd) + bfd * abfd; { /* this just does initialization */ /* coff_mkobject zalloc's space for tdata.coff_obj_data ... */ @@ -99,7 +99,7 @@ DEFUN (elf_mkobject, (abfd), bfd * abfd) bfd_zalloc (abfd, sizeof (struct elf_obj_tdata)); if (elf_tdata (abfd) == 0) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } /* since everything is done at close time, do we need any @@ -109,9 +109,9 @@ DEFUN (elf_mkobject, (abfd), bfd * abfd) } char * -DEFUN (elf_get_str_section, (abfd, shindex), - bfd * abfd AND - unsigned int shindex) +elf_get_str_section (abfd, shindex) + bfd * abfd; + unsigned int shindex; { Elf_Internal_Shdr **i_shdrp; char *shstrtab = NULL; @@ -135,10 +135,10 @@ DEFUN (elf_get_str_section, (abfd, shindex), } char * -DEFUN (elf_string_from_elf_section, (abfd, shindex, strindex), - bfd * abfd AND - unsigned int shindex AND - unsigned int strindex) +elf_string_from_elf_section (abfd, shindex, strindex) + bfd * abfd; + unsigned int shindex; + unsigned int strindex; { Elf_Internal_Shdr *hdr; @@ -170,9 +170,9 @@ DESCRIPTION */ struct elf_internal_shdr * -DEFUN (bfd_elf_find_section, (abfd, name), - bfd * abfd AND - char *name) +bfd_elf_find_section (abfd, name) + bfd * abfd; + char *name; { Elf_Internal_Shdr **i_shdrp; char *shstrtab; @@ -210,6 +210,7 @@ const char *const bfd_elf_section_type_names[] = { function. It just short circuits the reloc if producing relocateable output against an external symbol. */ +/*ARGSUSED*/ bfd_reloc_status_type bfd_elf_generic_reloc (abfd, reloc_entry, @@ -237,3 +238,79 @@ bfd_elf_generic_reloc (abfd, return bfd_reloc_continue; } + +/* Generic ELF link code. */ + +static struct bfd_hash_entry *elf_link_hash_newfunc + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); + +/* Create an entry in an ELF linker hash table. */ + +static struct bfd_hash_entry * +elf_link_hash_newfunc (entry, table, string) + struct bfd_hash_entry *entry; + struct bfd_hash_table *table; + const char *string; +{ + struct elf_link_hash_entry *ret = (struct elf_link_hash_entry *) entry; + + /* Allocate the structure if it has not already been allocated by a + subclass. */ + if (ret == (struct elf_link_hash_entry *) NULL) + ret = ((struct elf_link_hash_entry *) + bfd_hash_allocate (table, sizeof (struct elf_link_hash_entry))); + if (ret == (struct elf_link_hash_entry *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return (struct bfd_hash_entry *) ret; + } + + /* Call the allocation method of the superclass. */ + ret = ((struct elf_link_hash_entry *) + _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, + table, string)); + if (ret != (struct elf_link_hash_entry *) NULL) + { + /* Set local fields. */ + ret->indx = -1; + ret->size = 0; + ret->align = 0; + ret->dynindx = -1; + ret->dynstr_index = 0; + ret->weakdef = NULL; + ret->type = STT_NOTYPE; + ret->elf_link_hash_flags = 0; + } + + return (struct bfd_hash_entry *) ret; +} + +/* Create an ELF linker hash table. */ + +struct bfd_link_hash_table * +_bfd_elf_link_hash_table_create (abfd) + bfd *abfd; +{ + struct elf_link_hash_table *ret; + + ret = ((struct elf_link_hash_table *) + bfd_alloc (abfd, sizeof (struct elf_link_hash_table))); + if (ret == (struct elf_link_hash_table *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + if (! _bfd_link_hash_table_init (&ret->root, abfd, + elf_link_hash_newfunc)) + { + bfd_release (abfd, ret); + return NULL; + } + + ret->dynobj = NULL; + ret->dynsymcount = 0; + ret->dynstr = NULL; + ret->bucketcount = 0; + + return &ret->root; +} |