aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf.c
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1994-05-19 18:23:40 +0000
committerIan Lance Taylor <ian@airs.com>1994-05-19 18:23:40 +0000
commit013dec1ad95ef067951314b9f1beb2fa53296a6f (patch)
treec8f1921f6e06b5fa1b345d1b9a045a382868b642 /bfd/elf.c
parent4be9e22a91cbf326eb2f84af987b09326ac11bde (diff)
downloadgdb-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.c125
1 files changed, 101 insertions, 24 deletions
diff --git a/bfd/elf.c b/bfd/elf.c
index bfb3898..a3ec151 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -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;
+}