/* ELF linking support for BFD.
- Copyright 1995 Free Software Foundation, Inc.
+ Copyright 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
register asection *s;
struct elf_link_hash_entry *h;
struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ int ptralign;
/* This function may be called more than once. */
if (bfd_get_section_by_name (abfd, ".got") != NULL)
return true;
+ switch (bed->s->arch_size)
+ {
+ case 32: ptralign = 2; break;
+ case 64: ptralign = 3; break;
+ default: abort();
+ }
+
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
| SEC_LINKER_CREATED);
s = bfd_make_section (abfd, ".got");
if (s == NULL
|| !bfd_set_section_flags (abfd, s, flags)
- || !bfd_set_section_alignment (abfd, s, 2))
+ || !bfd_set_section_alignment (abfd, s, ptralign))
return false;
if (bed->want_got_plt)
s = bfd_make_section (abfd, ".got.plt");
if (s == NULL
|| !bfd_set_section_flags (abfd, s, flags)
- || !bfd_set_section_alignment (abfd, s, 2))
+ || !bfd_set_section_alignment (abfd, s, ptralign))
return false;
}
a global offset table. */
h = NULL;
if (!(_bfd_generic_link_add_one_symbol
- (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s, (bfd_vma) 0,
- (const char *) NULL, false, get_elf_backend_data (abfd)->collect,
- (struct bfd_link_hash_entry **) &h)))
+ (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s,
+ bed->got_symbol_offset, (const char *) NULL, false,
+ bed->collect, (struct bfd_link_hash_entry **) &h)))
return false;
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
h->type = STT_OBJECT;
elf_hash_table (info)->hgot = h;
- /* The first three global offset table entries are reserved. */
- s->_raw_size += 3 * 4;
+ /* The first bit of the global offset table is the header. */
+ s->_raw_size += bed->got_header_size + bed->got_symbol_offset;
return true;
}
bfd *abfd;
struct bfd_link_info *info;
{
- flagword flags;
+ flagword flags, pltflags;
register asection *s;
struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ int ptralign = 0;
+
+ switch (bed->s->arch_size)
+ {
+ case 32: ptralign = 2; break;
+ case 64: ptralign = 3; break;
+ default: abort();
+ }
/* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
.rel[a].bss sections. */
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
| SEC_LINKER_CREATED);
+ pltflags = flags;
+ pltflags |= SEC_CODE;
+ if (bed->plt_not_loaded)
+ pltflags &= ~ (SEC_LOAD | SEC_HAS_CONTENTS);
+ if (bed->plt_readonly)
+ pltflags |= SEC_READONLY;
+
s = bfd_make_section (abfd, ".plt");
if (s == NULL
- || ! bfd_set_section_flags (abfd, s,
- (flags | SEC_CODE
- | (bed->plt_readonly ? SEC_READONLY : 0)))
- || ! bfd_set_section_alignment (abfd, s, 2))
+ || ! bfd_set_section_flags (abfd, s, pltflags)
+ || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
return false;
if (bed->want_plt_sym)
return false;
}
- s = bfd_make_section (abfd, bed->use_rela_p ? ".rela.plt" : ".rel.plt");
+ s = bfd_make_section (abfd,
+ bed->default_use_rela_p ? ".rela.plt" : ".rel.plt");
if (s == NULL
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
- || ! bfd_set_section_alignment (abfd, s, 2))
+ || ! bfd_set_section_alignment (abfd, s, ptralign))
return false;
if (! _bfd_elf_create_got_section (abfd, info))
copy relocs. */
if (! info->shared)
{
- s = bfd_make_section (abfd, bed->use_rela_p ? ".rela.bss" : ".rel.bss");
+ s = bfd_make_section (abfd,
+ (bed->default_use_rela_p
+ ? ".rela.bss" : ".rel.bss"));
if (s == NULL
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
- || ! bfd_set_section_alignment (abfd, s, 2))
+ || ! bfd_set_section_alignment (abfd, s, ptralign))
return false;
}
if (h->dynindx == -1)
{
struct bfd_strtab_hash *dynstr;
+ char *p, *alc;
+ const char *name;
+ boolean copy;
+ bfd_size_type indx;
h->dynindx = elf_hash_table (info)->dynsymcount;
++elf_hash_table (info)->dynsymcount;
return false;
}
- h->dynstr_index = ((unsigned long)
- _bfd_stringtab_add (dynstr, h->root.root.string,
- true, false));
- if (h->dynstr_index == (unsigned long) -1)
+ /* We don't put any version information in the dynamic string
+ table. */
+ name = h->root.root.string;
+ p = strchr (name, ELF_VER_CHR);
+ if (p == NULL)
+ {
+ alc = NULL;
+ copy = false;
+ }
+ else
+ {
+ alc = bfd_malloc (p - name + 1);
+ if (alc == NULL)
+ return false;
+ strncpy (alc, name, p - name);
+ alc[p - name] = '\0';
+ name = alc;
+ copy = true;
+ }
+
+ indx = _bfd_stringtab_add (dynstr, name, true, copy);
+
+ if (alc != NULL)
+ free (alc);
+
+ if (indx == (bfd_size_type) -1)
return false;
+ h->dynstr_index = indx;
}
return true;
}
+
+/* Return the dynindex of a local dynamic symbol. */
+
+long
+_bfd_elf_link_lookup_local_dynindx (info, input_bfd, input_indx)
+ struct bfd_link_info *info;
+ bfd *input_bfd;
+ long input_indx;
+{
+ struct elf_link_local_dynamic_entry *e;
+
+ for (e = elf_hash_table (info)->dynlocal; e ; e = e->next)
+ if (e->input_bfd == input_bfd && e->input_indx == input_indx)
+ return e->dynindx;
+ return -1;
+}
+
+/* This function is used to renumber the dynamic symbols, if some of
+ them are removed because they are marked as local. This is called
+ via elf_link_hash_traverse. */
+
+static boolean elf_link_renumber_hash_table_dynsyms
+ PARAMS ((struct elf_link_hash_entry *, PTR));
+
+static boolean
+elf_link_renumber_hash_table_dynsyms (h, data)
+ struct elf_link_hash_entry *h;
+ PTR data;
+{
+ size_t *count = (size_t *) data;
+
+ if (h->dynindx != -1)
+ h->dynindx = ++(*count);
+
+ return true;
+}
+
+/* Assign dynsym indicies. In a shared library we generate a section
+ symbol for each output section, which come first. Next come all of
+ the back-end allocated local dynamic syms, followed by the rest of
+ the global symbols. */
+
+unsigned long
+_bfd_elf_link_renumber_dynsyms (output_bfd, info)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+{
+ unsigned long dynsymcount = 0;
+
+ if (info->shared)
+ {
+ asection *p;
+ for (p = output_bfd->sections; p ; p = p->next)
+ elf_section_data (p)->dynindx = ++dynsymcount;
+ }
+
+ if (elf_hash_table (info)->dynlocal)
+ {
+ struct elf_link_local_dynamic_entry *p;
+ for (p = elf_hash_table (info)->dynlocal; p ; p = p->next)
+ p->dynindx = ++dynsymcount;
+ }
+
+ elf_link_hash_traverse (elf_hash_table (info),
+ elf_link_renumber_hash_table_dynsyms,
+ &dynsymcount);
+
+ /* There is an unused NULL entry at the head of the table which
+ we must account for in our count. Unless there weren't any
+ symbols, which means we'll have no table at all. */
+ if (dynsymcount != 0)
+ ++dynsymcount;
+
+ return elf_hash_table (info)->dynsymcount = dynsymcount;
+}
\f
-/* Create a special linker section, or return a pointer to a linker section already created */
+/* Create a special linker section, or return a pointer to a linker
+ section already created */
elf_linker_section_t *
_bfd_elf_create_linker_section (abfd, info, which, defaults)
s->_raw_size += lsect->hole_size;
if (lsect->hole_offset > lsect->max_hole_offset)
{
- (*_bfd_error_handler) ("%s: Section %s is already to large to put hole of %ld bytes in",
+ (*_bfd_error_handler) (_("%s: Section %s is already to large to put hole of %ld bytes in"),
bfd_get_filename (abfd),
lsect->name,
(long)lsect->hole_size);
}
}
+#if 0
+ /* This does not make sense. The sections which may exist in the
+ object file have nothing to do with the sections we want to
+ create. */
+
/* Find the related sections if they have been created */
if (lsect->bss_name && !lsect->bss_section)
lsect->bss_section = bfd_get_section_by_name (dynobj, lsect->bss_name);
if (lsect->rel_name && !lsect->rel_section)
lsect->rel_section = bfd_get_section_by_name (dynobj, lsect->rel_name);
+#endif
return lsect;
}