/* BFD backend for SunOS binaries.
- Copyright (C) 1990, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright 1990, 1991, 1992, 1994, 1995, 1996, 1997, 1998, 2000, 2001,
+ 2002
+ Free Software Foundation, Inc.
Written by Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define TARGETNAME "a.out-sunos-big"
-#define MY(OP) CAT(sunos_big_,OP)
+
+/* Do not "beautify" the CONCAT* macro args. Traditional C will not
+ remove whitespace added here, and thus will fail to concatenate
+ the tokens. */
+#define MY(OP) CONCAT2 (sunos_big_,OP)
#include "bfd.h"
#include "bfdlink.h"
#define MY_check_dynamic_reloc sunos_check_dynamic_reloc
#define MY_finish_dynamic_link sunos_finish_dynamic_link
+/* ??? Where should this go? */
+#define MACHTYPE_OK(mtype) \
+ (((mtype) == M_SPARC && bfd_lookup_arch (bfd_arch_sparc, 0) != NULL) \
+ || ((mtype) == M_SPARCLET \
+ && bfd_lookup_arch (bfd_arch_sparc, bfd_mach_sparc_sparclet) != NULL) \
+ || ((mtype) == M_SPARCLITE_LE \
+ && bfd_lookup_arch (bfd_arch_sparc, bfd_mach_sparc_sparclet) != NULL) \
+ || (((mtype) == M_UNKNOWN || (mtype) == M_68010 || (mtype) == M_68020) \
+ && bfd_lookup_arch (bfd_arch_m68k, 0) != NULL))
+
/* Include the usual a.out support. */
#include "aoutf1.h"
+/* The SunOS 4.1.4 /usr/include/locale.h defines valid as a macro. */
+#undef valid
+
/* SunOS shared library support. We store a pointer to this structure
in obj_aout_dynamic_info (abfd). */
struct external_sun4_dynamic dyninfo;
unsigned long dynver;
struct external_sun4_dynamic_link linkinfo;
+ bfd_size_type amt;
if (obj_aout_dynamic_info (abfd) != (PTR) NULL)
return true;
return false;
}
- info = ((struct sunos_dynamic_info *)
- bfd_zalloc (abfd, sizeof (struct sunos_dynamic_info)));
+ amt = sizeof (struct sunos_dynamic_info);
+ info = (struct sunos_dynamic_info *) bfd_zalloc (abfd, amt);
if (!info)
return false;
info->valid = false;
if ((abfd->flags & DYNAMIC) == 0)
return true;
if (! bfd_get_section_contents (abfd, obj_datasec (abfd), (PTR) &dyninfo,
- (file_ptr) 0, sizeof dyninfo))
+ (file_ptr) 0,
+ (bfd_size_type) sizeof dyninfo))
return true;
dynver = GET_WORD (abfd, dyninfo.ld_version);
/* This executable appears to be dynamically linked in a way that we
can understand. */
- if (! bfd_get_section_contents (abfd, dynsec, (PTR) &linkinfo, dynoff,
+ if (! bfd_get_section_contents (abfd, dynsec, (PTR) &linkinfo,
+ (file_ptr) dynoff,
(bfd_size_type) sizeof linkinfo))
return true;
bfd *abfd;
{
struct sunos_dynamic_info *info;
+ bfd_size_type amt;
/* Get the general dynamic information. */
if (obj_aout_dynamic_info (abfd) == NULL)
/* Get the dynamic nlist structures. */
if (info->dynsym == (struct external_nlist *) NULL)
{
- info->dynsym = ((struct external_nlist *)
- bfd_alloc (abfd,
- (info->dynsym_count
- * EXTERNAL_NLIST_SIZE)));
+ amt = (bfd_size_type) info->dynsym_count * EXTERNAL_NLIST_SIZE;
+ info->dynsym = (struct external_nlist *) bfd_alloc (abfd, amt);
if (info->dynsym == NULL && info->dynsym_count != 0)
return false;
- if (bfd_seek (abfd, info->dyninfo.ld_stab, SEEK_SET) != 0
- || (bfd_read ((PTR) info->dynsym, info->dynsym_count,
- EXTERNAL_NLIST_SIZE, abfd)
- != info->dynsym_count * EXTERNAL_NLIST_SIZE))
+ if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_stab, SEEK_SET) != 0
+ || bfd_bread ((PTR) info->dynsym, amt, abfd) != amt)
{
if (info->dynsym != NULL)
{
/* Get the dynamic strings. */
if (info->dynstr == (char *) NULL)
{
- info->dynstr = (char *) bfd_alloc (abfd, info->dyninfo.ld_symb_size);
+ amt = info->dyninfo.ld_symb_size;
+ info->dynstr = (char *) bfd_alloc (abfd, amt);
if (info->dynstr == NULL && info->dyninfo.ld_symb_size != 0)
return false;
- if (bfd_seek (abfd, info->dyninfo.ld_symbols, SEEK_SET) != 0
- || (bfd_read ((PTR) info->dynstr, 1, info->dyninfo.ld_symb_size,
- abfd)
- != info->dyninfo.ld_symb_size))
+ if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_symbols, SEEK_SET) != 0
+ || bfd_bread ((PTR) info->dynstr, amt, abfd) != amt)
{
if (info->dynstr != NULL)
{
table = (bfd_byte *) bfd_malloc (table_size);
if (table == NULL && table_size != 0)
abort ();
- if (bfd_seek (abfd, info->dyninfo.ld_hash, SEEK_SET) != 0
- || bfd_read ((PTR) table, 1, table_size, abfd) != table_size)
+ if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_hash, SEEK_SET) != 0
+ || bfd_bread ((PTR) table, table_size, abfd) != table_size)
abort ();
for (i = 0; i < info->dynsym_count; i++)
{
structures. */
if (info->canonical_dynsym == (aout_symbol_type *) NULL)
{
- info->canonical_dynsym = ((aout_symbol_type *)
- bfd_alloc (abfd,
- (info->dynsym_count
- * sizeof (aout_symbol_type))));
+ bfd_size_type size;
+ bfd_size_type strsize = info->dyninfo.ld_symb_size;
+
+ size = (bfd_size_type) info->dynsym_count * sizeof (aout_symbol_type);
+ info->canonical_dynsym = (aout_symbol_type *) bfd_alloc (abfd, size);
if (info->canonical_dynsym == NULL && info->dynsym_count != 0)
return -1;
if (! aout_32_translate_symbol_table (abfd, info->canonical_dynsym,
- info->dynsym, info->dynsym_count,
- info->dynstr,
- info->dyninfo.ld_symb_size,
- true))
+ info->dynsym,
+ (bfd_size_type) info->dynsym_count,
+ info->dynstr, strsize, true))
{
if (info->canonical_dynsym != NULL)
{
{
struct sunos_dynamic_info *info;
unsigned long i;
+ bfd_size_type size;
/* Get the general dynamic information. */
if (obj_aout_dynamic_info (abfd) == (PTR) NULL)
/* Get the dynamic reloc information. */
if (info->dynrel == NULL)
{
- info->dynrel = (PTR) bfd_alloc (abfd,
- (info->dynrel_count
- * obj_reloc_entry_size (abfd)));
- if (info->dynrel == NULL && info->dynrel_count != 0)
+ size = (bfd_size_type) info->dynrel_count * obj_reloc_entry_size (abfd);
+ info->dynrel = (PTR) bfd_alloc (abfd, size);
+ if (info->dynrel == NULL && size != 0)
return -1;
- if (bfd_seek (abfd, info->dyninfo.ld_rel, SEEK_SET) != 0
- || (bfd_read ((PTR) info->dynrel, info->dynrel_count,
- obj_reloc_entry_size (abfd), abfd)
- != info->dynrel_count * obj_reloc_entry_size (abfd)))
+ if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_rel, SEEK_SET) != 0
+ || bfd_bread ((PTR) info->dynrel, size, abfd) != size)
{
if (info->dynrel != NULL)
{
{
arelent *to;
- info->canonical_dynrel = ((arelent *)
- bfd_alloc (abfd,
- (info->dynrel_count
- * sizeof (arelent))));
+ size = (bfd_size_type) info->dynrel_count * sizeof (arelent);
+ info->canonical_dynrel = (arelent *) bfd_alloc (abfd, size);
if (info->canonical_dynrel == NULL && info->dynrel_count != 0)
return -1;
-
+
to = info->canonical_dynrel;
if (obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE)
pend = p + info->dynrel_count;
for (; p < pend; p++, to++)
NAME(aout,swap_ext_reloc_in) (abfd, p, to, syms,
- info->dynsym_count);
+ (bfd_size_type) info->dynsym_count);
}
else
{
pend = p + info->dynrel_count;
for (; p < pend; p++, to++)
NAME(aout,swap_std_reloc_in) (abfd, p, to, syms,
- info->dynsym_count);
+ (bfd_size_type) info->dynsym_count);
}
}
};
/* save %sp, -96, %sp */
-#define SPARC_PLT_ENTRY_WORD0 0x9de3bfa0
+#define SPARC_PLT_ENTRY_WORD0 ((bfd_vma) 0x9de3bfa0)
/* call; address filled in later. */
-#define SPARC_PLT_ENTRY_WORD1 0x40000000
+#define SPARC_PLT_ENTRY_WORD1 ((bfd_vma) 0x40000000)
/* sethi; reloc index filled in later. */
-#define SPARC_PLT_ENTRY_WORD2 0x01000000
+#define SPARC_PLT_ENTRY_WORD2 ((bfd_vma) 0x01000000)
/* This sequence is used when for the jump table entry to a defined
symbol in a complete executable. It is used when linking PIC
compiled code which is not being put into a shared library. */
/* sethi <address to be filled in later>, %g1 */
-#define SPARC_PLT_PIC_WORD0 0x03000000
+#define SPARC_PLT_PIC_WORD0 ((bfd_vma) 0x03000000)
/* jmp %g1 + <address to be filled in later> */
-#define SPARC_PLT_PIC_WORD1 0x81c06000
+#define SPARC_PLT_PIC_WORD1 ((bfd_vma) 0x81c06000)
/* nop */
-#define SPARC_PLT_PIC_WORD2 0x01000000
+#define SPARC_PLT_PIC_WORD2 ((bfd_vma) 0x01000000)
/* An m68k procedure linkage table entry is 8 bytes. The first entry
in the table is a jump which is filled in the by the runtime
};
/* bsrl */
-#define M68K_PLT_ENTRY_WORD0 (0x61ff)
+#define M68K_PLT_ENTRY_WORD0 ((bfd_vma) 0x61ff)
/* Remaining words filled in later. */
/* An entry in the SunOS linker hash table. */
/* Symbol is defined by a regular object. */
#define SUNOS_DEF_REGULAR 02
/* Symbol is referenced by a dynamic object. */
-#define SUNOS_REF_DYNAMIC 010
+#define SUNOS_REF_DYNAMIC 04
/* Symbol is defined by a dynamic object. */
-#define SUNOS_DEF_DYNAMIC 020
+#define SUNOS_DEF_DYNAMIC 010
+ /* Symbol is a constructor symbol in a regular object. */
+#define SUNOS_CONSTRUCTOR 020
};
/* The SunOS linker hash table. */
/* Whether we need the dynamic sections. */
boolean dynamic_sections_needed;
+ /* Whether we need the .got table. */
+ boolean got_needed;
+
/* The number of dynamic symbols. */
size_t dynsymcount;
/* The list of dynamic objects needed by dynamic objects included in
the link. */
struct bfd_link_needed_list *needed;
+
+ /* The offset of __GLOBAL_OFFSET_TABLE_ into the .got section. */
+ bfd_vma got_base;
};
/* Routine to create an entry in an SunOS link hash table. */
bfd *abfd;
{
struct sunos_link_hash_table *ret;
+ bfd_size_type amt = sizeof (struct sunos_link_hash_table);
- ret = ((struct sunos_link_hash_table *)
- bfd_alloc (abfd, sizeof (struct sunos_link_hash_table)));
+ ret = (struct sunos_link_hash_table *) bfd_malloc (amt);
if (ret == (struct sunos_link_hash_table *) NULL)
return (struct bfd_link_hash_table *) NULL;
if (! NAME(aout,link_hash_table_init) (&ret->root, abfd,
sunos_link_hash_newfunc))
{
- bfd_release (abfd, ret);
+ free (ret);
return (struct bfd_link_hash_table *) NULL;
}
ret->dynobj = NULL;
ret->dynamic_sections_created = false;
ret->dynamic_sections_needed = false;
+ ret->got_needed = false;
ret->dynsymcount = 0;
ret->bucketcount = 0;
ret->needed = NULL;
+ ret->got_base = 0;
return &ret->root.root;
}
sunos_hash_table (info)->dynobj = abfd;
- flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED);
/* The .dynamic section holds the basic dynamic information: the
sun4_dynamic structure, the dynamic debugger information, and
sunos_hash_table (info)->dynamic_sections_created = true;
}
- if (needed && ! sunos_hash_table (info)->dynamic_sections_needed)
+ if ((needed && ! sunos_hash_table (info)->dynamic_sections_needed)
+ || info->shared)
{
bfd *dynobj;
dynobj = sunos_hash_table (info)->dynobj;
s = bfd_get_section_by_name (dynobj, ".got");
- s->_raw_size = BYTES_IN_WORD;
+ if (s->_raw_size == 0)
+ s->_raw_size = BYTES_IN_WORD;
sunos_hash_table (info)->dynamic_sections_needed = true;
+ sunos_hash_table (info)->got_needed = true;
}
return true;
}
/* Add dynamic symbols during a link. This is called by the a.out
- backend linker when it encounters an object with the DYNAMIC flag
- set. */
+ backend linker for each object it encounters. */
static boolean
sunos_add_dynamic_symbols (abfd, info, symsp, sym_countp, stringsp)
bfd_size_type *sym_countp;
char **stringsp;
{
- asection *s;
bfd *dynobj;
struct sunos_dynamic_info *dinfo;
unsigned long need;
+ asection **ps;
+
+ /* Make sure we have all the required sections. */
+ if (info->hash->creator == abfd->xvec)
+ {
+ if (! sunos_create_dynamic_sections (abfd, info,
+ (((abfd->flags & DYNAMIC) != 0
+ && ! info->relocateable)
+ ? true
+ : false)))
+ return false;
+ }
+
+ /* There is nothing else to do for a normal object. */
+ if ((abfd->flags & DYNAMIC) == 0)
+ return true;
+
+ dynobj = sunos_hash_table (info)->dynobj;
/* We do not want to include the sections in a dynamic object in the
output file. We hack by simply clobbering the list of sections
in the BFD. This could be handled more cleanly by, say, a new
section flag; the existing SEC_NEVER_LOAD flag is not the one we
want, because that one still implies that the section takes up
- space in the output file. */
- abfd->sections = NULL;
+ space in the output file. If this is the first object we have
+ seen, we must preserve the dynamic sections we just created. */
+ for (ps = &abfd->sections; *ps != NULL; )
+ {
+ if (abfd != dynobj || ((*ps)->flags & SEC_LINKER_CREATED) == 0)
+ bfd_section_list_remove (abfd, ps);
+ else
+ ps = &(*ps)->next;
+ }
/* The native linker seems to just ignore dynamic objects when -r is
used. */
return false;
}
- /* Make sure we have all the required information. */
- if (! sunos_create_dynamic_sections (abfd, info, true))
- return false;
-
/* Make sure we have a .need and a .rules sections. These are only
needed if there really is a dynamic object in the link, so they
are not added by sunos_create_dynamic_sections. */
- dynobj = sunos_hash_table (info)->dynobj;
if (bfd_get_section_by_name (dynobj, ".need") == NULL)
{
/* The .need section holds the list of names of shared objets
which must be included at runtime. The address of this
section is put in the ld_need field. */
- s = bfd_make_section (dynobj, ".need");
+ asection *s = bfd_make_section (dynobj, ".need");
if (s == NULL
|| ! bfd_set_section_flags (dynobj, s,
(SEC_ALLOC
/* The .rules section holds the path to search for shared
objects. The address of this section is put in the ld_rules
field. */
- s = bfd_make_section (dynobj, ".rules");
+ asection *s = bfd_make_section (dynobj, ".rules");
if (s == NULL
|| ! bfd_set_section_flags (dynobj, s,
(SEC_ALLOC
unsigned long name, flags;
unsigned short major_vno, minor_vno;
struct bfd_link_needed_list *needed, **pp;
+ char *namebuf, *p;
+ bfd_size_type alc;
bfd_byte b;
+ char *namecopy;
- if (bfd_seek (abfd, need, SEEK_SET) != 0
- || bfd_read (buf, 1, 16, abfd) != 16)
+ if (bfd_seek (abfd, (file_ptr) need, SEEK_SET) != 0
+ || bfd_bread (buf, (bfd_size_type) 16, abfd) != 16)
return false;
/* For the format of an ld_need entry, see aout/sun4.h. We
name = bfd_get_32 (abfd, buf);
flags = bfd_get_32 (abfd, buf + 4);
- major_vno = bfd_get_16 (abfd, buf + 8);
- minor_vno = bfd_get_16 (abfd, buf + 10);
+ major_vno = (unsigned short) bfd_get_16 (abfd, buf + 8);
+ minor_vno = (unsigned short) bfd_get_16 (abfd, buf + 10);
need = bfd_get_32 (abfd, buf + 12);
- needed = (struct bfd_link_needed_list *) bfd_alloc (abfd, sizeof (struct bfd_link_needed_list));
+ alc = sizeof (struct bfd_link_needed_list);
+ needed = (struct bfd_link_needed_list *) bfd_alloc (abfd, alc);
if (needed == NULL)
return false;
needed->by = abfd;
/* We return the name as [-l]name[.maj][.min]. */
+ alc = 30;
+ namebuf = (char *) bfd_malloc (alc + 1);
+ if (namebuf == NULL)
+ return false;
+ p = namebuf;
if ((flags & 0x80000000) != 0)
- bfd_alloc_grow (abfd, "-l", 2);
- if (bfd_seek (abfd, name, SEEK_SET) != 0)
- return false;
+ {
+ *p++ = '-';
+ *p++ = 'l';
+ }
+ if (bfd_seek (abfd, (file_ptr) name, SEEK_SET) != 0)
+ {
+ free (namebuf);
+ return false;
+ }
+
do
{
- if (bfd_read (&b, 1, 1, abfd) != 1)
- return false;
- bfd_alloc_grow (abfd, &b, 1);
+ if (bfd_bread (&b, (bfd_size_type) 1, abfd) != 1)
+ {
+ free (namebuf);
+ return false;
+ }
+
+ if ((bfd_size_type) (p - namebuf) >= alc)
+ {
+ char *n;
+
+ alc *= 2;
+ n = (char *) bfd_realloc (namebuf, alc + 1);
+ if (n == NULL)
+ {
+ free (namebuf);
+ return false;
+ }
+ p = n + (p - namebuf);
+ namebuf = n;
+ }
+
+ *p++ = b;
}
while (b != '\0');
- if (major_vno != 0)
+
+ if (major_vno == 0)
+ *p = '\0';
+ else
{
- char verbuf[30];
+ char majbuf[30];
+ char minbuf[30];
- sprintf (verbuf, ".%d", major_vno);
- bfd_alloc_grow (abfd, verbuf, strlen (verbuf));
- if (minor_vno != 0)
+ sprintf (majbuf, ".%d", major_vno);
+ if (minor_vno == 0)
+ minbuf[0] = '\0';
+ else
+ sprintf (minbuf, ".%d", minor_vno);
+
+ if ((p - namebuf) + strlen (majbuf) + strlen (minbuf) >= alc)
{
- sprintf (verbuf, ".%d", minor_vno);
- bfd_alloc_grow (abfd, verbuf, strlen (verbuf));
+ char *n;
+
+ alc = (p - namebuf) + strlen (majbuf) + strlen (minbuf);
+ n = (char *) bfd_realloc (namebuf, alc + 1);
+ if (n == NULL)
+ {
+ free (namebuf);
+ return false;
+ }
+ p = n + (p - namebuf);
+ namebuf = n;
}
+
+ strcpy (p, majbuf);
+ strcat (p, minbuf);
}
- needed->name = bfd_alloc_finish (abfd);
- if (needed->name == NULL)
- return false;
+
+ namecopy = bfd_alloc (abfd, (bfd_size_type) strlen (namebuf) + 1);
+ if (namecopy == NULL)
+ {
+ free (namebuf);
+ return false;
+ }
+ strcpy (namecopy, namebuf);
+ free (namebuf);
+ needed->name = namecopy;
needed->next = NULL;
struct sunos_link_hash_entry *h;
int new_flag;
- if (! sunos_hash_table (info)->dynamic_sections_created)
- {
- /* We must create the dynamic sections while reading the input
- files, even though at this point we don't know if any of the
- sections will be needed. This will ensure that the dynamic
- sections are mapped to the right output section. It does no
- harm to create these sections if they are not needed. */
- if (! sunos_create_dynamic_sections (abfd, info, false))
- return false;
- }
-
- h = sunos_link_hash_lookup (sunos_hash_table (info), name, true, copy,
- false);
+ if ((flags & (BSF_INDIRECT | BSF_WARNING | BSF_CONSTRUCTOR)) != 0
+ || ! bfd_is_und_section (section))
+ h = sunos_link_hash_lookup (sunos_hash_table (info), name, true, copy,
+ false);
+ else
+ h = ((struct sunos_link_hash_entry *)
+ bfd_wrapped_link_hash_lookup (abfd, info, name, true, copy, false));
if (h == NULL)
return false;
/* The existing definition is from a dynamic object. We
want to override it with the definition we just found.
Clobber the existing definition. */
- h->root.root.type = bfd_link_hash_new;
+ h->root.root.type = bfd_link_hash_undefined;
+ h->root.root.u.undef.abfd = h->root.root.u.def.section->owner;
}
else if (h->root.root.type == bfd_link_hash_common
&& (h->root.root.u.c.p->section->owner->flags & DYNAMIC) != 0)
}
}
+ if ((abfd->flags & DYNAMIC) != 0
+ && abfd->xvec == info->hash->creator
+ && (h->flags & SUNOS_CONSTRUCTOR) != 0)
+ {
+ /* The existing symbol is a constructor symbol, and this symbol
+ is from a dynamic object. A constructor symbol is actually a
+ definition, although the type will be bfd_link_hash_undefined
+ at this point. We want to ignore the definition from the
+ dynamic object. */
+ section = bfd_und_section_ptr;
+ }
+ else if ((flags & BSF_CONSTRUCTOR) != 0
+ && (abfd->flags & DYNAMIC) == 0
+ && h->root.root.type == bfd_link_hash_defined
+ && h->root.root.u.def.section->owner != NULL
+ && (h->root.root.u.def.section->owner->flags & DYNAMIC) != 0)
+ {
+ /* The existing symbol is defined by a dynamic object, and this
+ is a constructor symbol. As above, we want to force the use
+ of the constructor symbol from the regular object. */
+ h->root.root.type = bfd_link_hash_new;
+ }
+
/* Do the usual procedure for adding a symbol. */
if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section,
value, string, copy, collect,
++sunos_hash_table (info)->dynsymcount;
h->dynindx = -2;
}
+
+ if ((flags & BSF_CONSTRUCTOR) != 0
+ && (abfd->flags & DYNAMIC) == 0)
+ h->flags |= SUNOS_CONSTRUCTOR;
}
return true;
/*ARGSUSED*/
struct bfd_link_needed_list *
bfd_sunos_get_needed_list (abfd, info)
- bfd *abfd;
+ bfd *abfd ATTRIBUTE_UNUSED;
struct bfd_link_info *info;
{
if (info->hash->creator != &MY(vec))
asection **srulesptr;
{
bfd *dynobj;
- size_t dynsymcount;
+ bfd_size_type dynsymcount;
struct sunos_link_hash_entry *h;
asection *s;
size_t bucketcount;
- size_t hashalloc;
+ bfd_size_type hashalloc;
size_t i;
bfd *sub;
*sneedptr = NULL;
*srulesptr = NULL;
+ if (info->relocateable)
+ return true;
+
if (output_bfd->xvec != &MY(vec))
return true;
/* If there were no dynamic objects in the link, and we don't need
to build a global offset table, there is nothing to do here. */
- if (! sunos_hash_table (info)->dynamic_sections_needed)
+ if (! sunos_hash_table (info)->dynamic_sections_needed
+ && ! sunos_hash_table (info)->got_needed)
return true;
/* If __GLOBAL_OFFSET_TABLE_ was mentioned, define it. */
}
h->root.root.type = bfd_link_hash_defined;
h->root.root.u.def.section = bfd_get_section_by_name (dynobj, ".got");
- h->root.root.u.def.value = 0;
+
+ /* If the .got section is more than 0x1000 bytes, we set
+ __GLOBAL_OFFSET_TABLE_ to be 0x1000 bytes into the section,
+ so that 13 bit relocations have a greater chance of working. */
+ s = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (s != NULL);
+ if (s->_raw_size >= 0x1000)
+ h->root.root.u.def.value = 0x1000;
+ else
+ h->root.root.u.def.value = 0;
+
+ sunos_hash_table (info)->got_base = h->root.root.u.def.value;
}
- /* The .dynamic section is always the same size. */
- s = bfd_get_section_by_name (dynobj, ".dynamic");
- BFD_ASSERT (s != NULL);
- s->_raw_size = (sizeof (struct external_sun4_dynamic)
- + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE
- + sizeof (struct external_sun4_dynamic_link));
-
- /* Set the size of the .dynsym and .hash sections. We counted the
- number of dynamic symbols as we read the input files. We will
- build the dynamic symbol table (.dynsym) and the hash table
- (.hash) when we build the final symbol table, because until then
- we do not know the correct value to give the symbols. We build
- the dynamic symbol string table (.dynstr) in a traversal of the
- symbol table using sunos_scan_dynamic_symbol. */
- s = bfd_get_section_by_name (dynobj, ".dynsym");
- BFD_ASSERT (s != NULL);
- s->_raw_size = dynsymcount * sizeof (struct external_nlist);
- s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
- if (s->contents == NULL && s->_raw_size != 0)
- return false;
-
- /* The number of buckets is just the number of symbols divided by
- four. To compute the final size of the hash table, we must
- actually compute the hash table. Normally we need exactly as
- many entries in the hash table as there are dynamic symbols, but
- if some of the buckets are not used we will need additional
- entries. In the worst case, every symbol will hash to the same
- bucket, and we will need BUCKETCOUNT - 1 extra entries. */
- if (dynsymcount >= 4)
- bucketcount = dynsymcount / 4;
- else if (dynsymcount > 0)
- bucketcount = dynsymcount;
- else
- bucketcount = 1;
- s = bfd_get_section_by_name (dynobj, ".hash");
- BFD_ASSERT (s != NULL);
- hashalloc = (dynsymcount + bucketcount - 1) * HASH_ENTRY_SIZE;
- s->contents = (bfd_byte *) bfd_alloc (dynobj, hashalloc);
- if (s->contents == NULL && dynsymcount > 0)
- return false;
- memset (s->contents, 0, hashalloc);
- for (i = 0; i < bucketcount; i++)
- PUT_WORD (output_bfd, (bfd_vma) -1, s->contents + i * HASH_ENTRY_SIZE);
- s->_raw_size = bucketcount * HASH_ENTRY_SIZE;
-
- sunos_hash_table (info)->bucketcount = bucketcount;
-
- /* Scan all the symbols, place them in the dynamic symbol table, and
- build the dynamic hash table. We reuse dynsymcount as a counter
- for the number of symbols we have added so far. */
- sunos_hash_table (info)->dynsymcount = 0;
- sunos_link_hash_traverse (sunos_hash_table (info),
- sunos_scan_dynamic_symbol,
- (PTR) info);
- BFD_ASSERT (sunos_hash_table (info)->dynsymcount == dynsymcount);
-
- /* The SunOS native linker seems to align the total size of the
- symbol strings to a multiple of 8. I don't know if this is
- important, but it can't hurt much. */
- s = bfd_get_section_by_name (dynobj, ".dynstr");
- BFD_ASSERT (s != NULL);
- if ((s->_raw_size & 7) != 0)
+ /* If there are any shared objects in the link, then we need to set
+ up the dynamic linking information. */
+ if (sunos_hash_table (info)->dynamic_sections_needed)
{
- bfd_size_type add;
- bfd_byte *contents;
+ *sdynptr = bfd_get_section_by_name (dynobj, ".dynamic");
- add = 8 - (s->_raw_size & 7);
- contents = (bfd_byte *) bfd_realloc (s->contents,
- (size_t) (s->_raw_size + add));
- if (contents == NULL)
+ /* The .dynamic section is always the same size. */
+ s = *sdynptr;
+ BFD_ASSERT (s != NULL);
+ s->_raw_size = (sizeof (struct external_sun4_dynamic)
+ + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE
+ + sizeof (struct external_sun4_dynamic_link));
+
+ /* Set the size of the .dynsym and .hash sections. We counted
+ the number of dynamic symbols as we read the input files. We
+ will build the dynamic symbol table (.dynsym) and the hash
+ table (.hash) when we build the final symbol table, because
+ until then we do not know the correct value to give the
+ symbols. We build the dynamic symbol string table (.dynstr)
+ in a traversal of the symbol table using
+ sunos_scan_dynamic_symbol. */
+ s = bfd_get_section_by_name (dynobj, ".dynsym");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size = dynsymcount * sizeof (struct external_nlist);
+ s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
+ if (s->contents == NULL && s->_raw_size != 0)
return false;
- memset (contents + s->_raw_size, 0, (size_t) add);
- s->contents = contents;
- s->_raw_size += add;
+
+ /* The number of buckets is just the number of symbols divided
+ by four. To compute the final size of the hash table, we
+ must actually compute the hash table. Normally we need
+ exactly as many entries in the hash table as there are
+ dynamic symbols, but if some of the buckets are not used we
+ will need additional entries. In the worst case, every
+ symbol will hash to the same bucket, and we will need
+ BUCKETCOUNT - 1 extra entries. */
+ if (dynsymcount >= 4)
+ bucketcount = dynsymcount / 4;
+ else if (dynsymcount > 0)
+ bucketcount = dynsymcount;
+ else
+ bucketcount = 1;
+ s = bfd_get_section_by_name (dynobj, ".hash");
+ BFD_ASSERT (s != NULL);
+ hashalloc = (dynsymcount + bucketcount - 1) * HASH_ENTRY_SIZE;
+ s->contents = (bfd_byte *) bfd_alloc (dynobj, hashalloc);
+ if (s->contents == NULL && dynsymcount > 0)
+ return false;
+ memset (s->contents, 0, (size_t) hashalloc);
+ for (i = 0; i < bucketcount; i++)
+ PUT_WORD (output_bfd, (bfd_vma) -1, s->contents + i * HASH_ENTRY_SIZE);
+ s->_raw_size = bucketcount * HASH_ENTRY_SIZE;
+
+ sunos_hash_table (info)->bucketcount = bucketcount;
+
+ /* Scan all the symbols, place them in the dynamic symbol table,
+ and build the dynamic hash table. We reuse dynsymcount as a
+ counter for the number of symbols we have added so far. */
+ sunos_hash_table (info)->dynsymcount = 0;
+ sunos_link_hash_traverse (sunos_hash_table (info),
+ sunos_scan_dynamic_symbol,
+ (PTR) info);
+ BFD_ASSERT (sunos_hash_table (info)->dynsymcount == dynsymcount);
+
+ /* The SunOS native linker seems to align the total size of the
+ symbol strings to a multiple of 8. I don't know if this is
+ important, but it can't hurt much. */
+ s = bfd_get_section_by_name (dynobj, ".dynstr");
+ BFD_ASSERT (s != NULL);
+ if ((s->_raw_size & 7) != 0)
+ {
+ bfd_size_type add;
+ bfd_byte *contents;
+
+ add = 8 - (s->_raw_size & 7);
+ contents = (bfd_byte *) bfd_realloc (s->contents,
+ s->_raw_size + add);
+ if (contents == NULL)
+ return false;
+ memset (contents + s->_raw_size, 0, (size_t) add);
+ s->contents = contents;
+ s->_raw_size += add;
+ }
}
/* Now that we have worked out the sizes of the procedure linkage
if (s->contents == NULL)
return false;
- *sdynptr = bfd_get_section_by_name (dynobj, ".dynamic");
*sneedptr = bfd_get_section_by_name (dynobj, ".need");
*srulesptr = bfd_get_section_by_name (dynobj, ".rules");
return true;
if (! info->keep_memory)
- relocs = free_relocs = bfd_malloc ((size_t) rel_size);
+ relocs = free_relocs = bfd_malloc (rel_size);
else
{
struct aout_section_data_struct *n;
+ bfd_size_type amt = sizeof (struct aout_section_data_struct);
- n = ((struct aout_section_data_struct *)
- bfd_alloc (abfd, sizeof (struct aout_section_data_struct)));
+ n = (struct aout_section_data_struct *) bfd_alloc (abfd, amt);
if (n == NULL)
relocs = NULL;
else
{
set_aout_section_data (sec, n);
- relocs = bfd_malloc ((size_t) rel_size);
+ relocs = bfd_malloc (rel_size);
aout_section_data (sec)->relocs = relocs;
}
}
return false;
if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0
- || bfd_read (relocs, 1, rel_size, abfd) != rel_size)
+ || bfd_bread (relocs, rel_size, abfd) != rel_size)
goto error_return;
if (obj_reloc_entry_size (abfd) == RELOC_STD_SIZE)
sunos_scan_std_relocs (info, abfd, sec, relocs, rel_size)
struct bfd_link_info *info;
bfd *abfd;
- asection *sec;
+ asection *sec ATTRIBUTE_UNUSED;
const struct reloc_std_external *relocs;
bfd_size_type rel_size;
{
if (dynobj == NULL)
{
- if (! sunos_create_dynamic_sections (abfd, info, true))
+ asection *sgot;
+
+ if (! sunos_create_dynamic_sections (abfd, info, false))
return false;
dynobj = sunos_hash_table (info)->dynobj;
splt = bfd_get_section_by_name (dynobj, ".plt");
srel = bfd_get_section_by_name (dynobj, ".dynrel");
BFD_ASSERT (splt != NULL && srel != NULL);
+
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (sgot != NULL);
+ if (sgot->_raw_size == 0)
+ sgot->_raw_size = BYTES_IN_WORD;
+ sunos_hash_table (info)->got_needed = true;
}
BFD_ASSERT ((h->flags & SUNOS_REF_REGULAR) != 0);
sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
struct bfd_link_info *info;
bfd *abfd;
- asection *sec;
+ asection *sec ATTRIBUTE_UNUSED;
const struct reloc_ext_external *relocs;
bfd_size_type rel_size;
{
asection *splt = NULL;
asection *sgot = NULL;
asection *srel = NULL;
+ bfd_size_type amt;
/* We only know how to handle SPARC plt entries. */
if (bfd_get_arch (abfd) != bfd_arch_sparc)
{
if (dynobj == NULL)
{
- if (! sunos_create_dynamic_sections (abfd, info, true))
+ if (! sunos_create_dynamic_sections (abfd, info, false))
return false;
dynobj = sunos_hash_table (info)->dynobj;
splt = bfd_get_section_by_name (dynobj, ".plt");
sgot = bfd_get_section_by_name (dynobj, ".got");
srel = bfd_get_section_by_name (dynobj, ".dynrel");
BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL);
+
+ /* Make sure we have an initial entry in the .got table. */
+ if (sgot->_raw_size == 0)
+ sgot->_raw_size = BYTES_IN_WORD;
+ sunos_hash_table (info)->got_needed = true;
}
if (r_extern)
if (adata (abfd).local_got_offsets == NULL)
{
+ amt = bfd_get_symcount (abfd);
+ amt *= sizeof (bfd_vma);
adata (abfd).local_got_offsets =
- (bfd_vma *) bfd_zalloc (abfd,
- (bfd_get_symcount (abfd)
- * sizeof (bfd_vma)));
+ (bfd_vma *) bfd_zalloc (abfd, amt);
if (adata (abfd).local_got_offsets == NULL)
return false;
}
|| (h->flags & SUNOS_DEF_REGULAR) != 0))
continue;
+ if (r_type == RELOC_JMP_TBL
+ && ! info->shared
+ && (h->flags & SUNOS_DEF_DYNAMIC) == 0
+ && (h->flags & SUNOS_DEF_REGULAR) == 0)
+ {
+ /* This symbol is apparently undefined. Don't do anything
+ here; just let the relocation routine report an undefined
+ symbol. */
+ continue;
+ }
+
if (strcmp (h->root.root.root.string, "__GLOBAL_OFFSET_TABLE_") == 0)
continue;
if (dynobj == NULL)
{
- if (! sunos_create_dynamic_sections (abfd, info, true))
+ if (! sunos_create_dynamic_sections (abfd, info, false))
return false;
dynobj = sunos_hash_table (info)->dynobj;
splt = bfd_get_section_by_name (dynobj, ".plt");
sgot = bfd_get_section_by_name (dynobj, ".got");
srel = bfd_get_section_by_name (dynobj, ".dynrel");
BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL);
+
+ /* Make sure we have an initial entry in the .got table. */
+ if (sgot->_raw_size == 0)
+ sgot->_raw_size = BYTES_IN_WORD;
+ sunos_hash_table (info)->got_needed = true;
}
BFD_ASSERT (r_type == RELOC_JMP_TBL
{
struct bfd_link_info *info = (struct bfd_link_info *) data;
+ if (h->root.root.type == bfd_link_hash_warning)
+ h = (struct sunos_link_hash_entry *) h->root.root.u.i.link;
+
/* Set the written flag for symbols we do not want to write out as
part of the regular symbol table. This is all symbols which are
not defined in a regular object file. For some reason symbols
s->contents = contents;
h->dynstr_index = s->_raw_size;
- strcpy (contents + s->_raw_size, h->root.root.root.string);
+ strcpy ((char *) contents + s->_raw_size, h->root.root.root.string);
s->_raw_size += len + 1;
/* Add it to the dynamic hash table. */
/*ARGSUSED*/
static boolean
sunos_link_dynamic_object (info, abfd)
- struct bfd_link_info *info;
- bfd *abfd;
+ struct bfd_link_info *info ATTRIBUTE_UNUSED;
+ bfd *abfd ATTRIBUTE_UNUSED;
{
return true;
}
asection *s;
struct external_nlist *outsym;
- if (h->dynindx < 0)
- return true;
-
- switch (h->root.root.type)
- {
- default:
- case bfd_link_hash_new:
- abort ();
- /* Avoid variable not initialized warnings. */
- return true;
- case bfd_link_hash_undefined:
- type = N_UNDF | N_EXT;
- val = 0;
- break;
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- {
- asection *sec;
- asection *output_section;
-
- sec = h->root.root.u.def.section;
- output_section = sec->output_section;
- BFD_ASSERT (bfd_is_abs_section (output_section)
- || output_section->owner == output_bfd);
- if (h->plt_offset != 0
- && (h->flags & SUNOS_DEF_REGULAR) == 0)
- {
- type = N_UNDF | N_EXT;
- val = 0;
- }
- else
- {
- if (output_section == obj_textsec (output_bfd))
- type = (h->root.root.type == bfd_link_hash_defined
- ? N_TEXT
- : N_WEAKT);
- else if (output_section == obj_datasec (output_bfd))
- type = (h->root.root.type == bfd_link_hash_defined
- ? N_DATA
- : N_WEAKD);
- else if (output_section == obj_bsssec (output_bfd))
- type = (h->root.root.type == bfd_link_hash_defined
- ? N_BSS
- : N_WEAKB);
- else
- type = (h->root.root.type == bfd_link_hash_defined
- ? N_ABS
- : N_WEAKA);
- type |= N_EXT;
- val = (h->root.root.u.def.value
- + output_section->vma
- + sec->output_offset);
- }
- }
- break;
- case bfd_link_hash_common:
- type = N_UNDF | N_EXT;
- val = h->root.root.u.c.size;
- break;
- case bfd_link_hash_undefweak:
- type = N_WEAKU;
- val = 0;
- break;
- case bfd_link_hash_indirect:
- case bfd_link_hash_warning:
- /* FIXME: Ignore these for now. The circumstances under which
- they should be written out are not clear to me. */
- return true;
- }
-
- s = bfd_get_section_by_name (sunos_hash_table (info)->dynobj, ".dynsym");
- BFD_ASSERT (s != NULL);
- outsym = ((struct external_nlist *)
- (s->contents + h->dynindx * EXTERNAL_NLIST_SIZE));
-
- bfd_h_put_8 (output_bfd, type, outsym->e_type);
- bfd_h_put_8 (output_bfd, 0, outsym->e_other);
-
- /* FIXME: The native linker doesn't use 0 for desc. It seems to use
- one less than the desc value in the shared library, although that
- seems unlikely. */
- bfd_h_put_16 (output_bfd, 0, outsym->e_desc);
-
- PUT_WORD (output_bfd, h->dynstr_index, outsym->e_strx);
- PUT_WORD (output_bfd, val, outsym->e_value);
-
/* If this symbol is in the procedure linkage table, fill in the
table entry. */
if (h->plt_offset != 0)
bfd *dynobj;
asection *splt;
bfd_byte *p;
- asection *s;
bfd_vma r_address;
dynobj = sunos_hash_table (info)->dynobj;
}
else
{
- bfd_vma val;
-
val = (h->root.root.u.def.section->output_section->vma
+ h->root.root.u.def.section->output_offset
+ h->root.root.u.def.value);
abort ();
bfd_put_16 (output_bfd, M68K_PLT_ENTRY_WORD0, p);
bfd_put_32 (output_bfd, (- (h->plt_offset + 2)), p + 2);
- bfd_put_16 (output_bfd, s->reloc_count, p + 6);
+ bfd_put_16 (output_bfd, (bfd_vma) s->reloc_count, p + 6);
r_address += 2;
break;
result of a JMP_TBL reloc from PIC compiled code. */
if (info->shared || (h->flags & SUNOS_DEF_REGULAR) == 0)
{
+ BFD_ASSERT (h->dynindx >= 0);
BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj)
< s->_raw_size);
p = s->contents + s->reloc_count * obj_reloc_entry_size (output_bfd);
PUT_WORD (output_bfd, r_address, srel->r_address);
if (bfd_header_big_endian (output_bfd))
{
- srel->r_index[0] = h->dynindx >> 16;
- srel->r_index[1] = h->dynindx >> 8;
- srel->r_index[2] = h->dynindx;
+ srel->r_index[0] = (bfd_byte) (h->dynindx >> 16);
+ srel->r_index[1] = (bfd_byte) (h->dynindx >> 8);
+ srel->r_index[2] = (bfd_byte) (h->dynindx);
srel->r_type[0] = (RELOC_STD_BITS_EXTERN_BIG
| RELOC_STD_BITS_JMPTABLE_BIG);
}
else
{
- srel->r_index[2] = h->dynindx >> 16;
- srel->r_index[1] = h->dynindx >> 8;
- srel->r_index[0] = h->dynindx;
+ srel->r_index[2] = (bfd_byte) (h->dynindx >> 16);
+ srel->r_index[1] = (bfd_byte) (h->dynindx >> 8);
+ srel->r_index[0] = (bfd_byte)h->dynindx;
srel->r_type[0] = (RELOC_STD_BITS_EXTERN_LITTLE
| RELOC_STD_BITS_JMPTABLE_LITTLE);
}
PUT_WORD (output_bfd, r_address, erel->r_address);
if (bfd_header_big_endian (output_bfd))
{
- erel->r_index[0] = h->dynindx >> 16;
- erel->r_index[1] = h->dynindx >> 8;
- erel->r_index[2] = h->dynindx;
+ erel->r_index[0] = (bfd_byte) (h->dynindx >> 16);
+ erel->r_index[1] = (bfd_byte) (h->dynindx >> 8);
+ erel->r_index[2] = (bfd_byte)h->dynindx;
erel->r_type[0] =
(RELOC_EXT_BITS_EXTERN_BIG
| (RELOC_JMP_SLOT << RELOC_EXT_BITS_TYPE_SH_BIG));
}
else
{
- erel->r_index[2] = h->dynindx >> 16;
- erel->r_index[1] = h->dynindx >> 8;
- erel->r_index[0] = h->dynindx;
+ erel->r_index[2] = (bfd_byte) (h->dynindx >> 16);
+ erel->r_index[1] = (bfd_byte) (h->dynindx >> 8);
+ erel->r_index[0] = (bfd_byte)h->dynindx;
erel->r_type[0] =
(RELOC_EXT_BITS_EXTERN_LITTLE
| (RELOC_JMP_SLOT << RELOC_EXT_BITS_TYPE_SH_LITTLE));
}
}
+ /* If this is not a dynamic symbol, we don't have to do anything
+ else. We only check this after handling the PLT entry, because
+ we can have a PLT entry for a nondynamic symbol when linking PIC
+ compiled code from a regular object. */
+ if (h->dynindx < 0)
+ return true;
+
+ switch (h->root.root.type)
+ {
+ default:
+ case bfd_link_hash_new:
+ abort ();
+ /* Avoid variable not initialized warnings. */
+ return true;
+ case bfd_link_hash_undefined:
+ type = N_UNDF | N_EXT;
+ val = 0;
+ break;
+ case bfd_link_hash_defined:
+ case bfd_link_hash_defweak:
+ {
+ asection *sec;
+ asection *output_section;
+
+ sec = h->root.root.u.def.section;
+ output_section = sec->output_section;
+ BFD_ASSERT (bfd_is_abs_section (output_section)
+ || output_section->owner == output_bfd);
+ if (h->plt_offset != 0
+ && (h->flags & SUNOS_DEF_REGULAR) == 0)
+ {
+ type = N_UNDF | N_EXT;
+ val = 0;
+ }
+ else
+ {
+ if (output_section == obj_textsec (output_bfd))
+ type = (h->root.root.type == bfd_link_hash_defined
+ ? N_TEXT
+ : N_WEAKT);
+ else if (output_section == obj_datasec (output_bfd))
+ type = (h->root.root.type == bfd_link_hash_defined
+ ? N_DATA
+ : N_WEAKD);
+ else if (output_section == obj_bsssec (output_bfd))
+ type = (h->root.root.type == bfd_link_hash_defined
+ ? N_BSS
+ : N_WEAKB);
+ else
+ type = (h->root.root.type == bfd_link_hash_defined
+ ? N_ABS
+ : N_WEAKA);
+ type |= N_EXT;
+ val = (h->root.root.u.def.value
+ + output_section->vma
+ + sec->output_offset);
+ }
+ }
+ break;
+ case bfd_link_hash_common:
+ type = N_UNDF | N_EXT;
+ val = h->root.root.u.c.size;
+ break;
+ case bfd_link_hash_undefweak:
+ type = N_WEAKU;
+ val = 0;
+ break;
+ case bfd_link_hash_indirect:
+ case bfd_link_hash_warning:
+ /* FIXME: Ignore these for now. The circumstances under which
+ they should be written out are not clear to me. */
+ return true;
+ }
+
+ s = bfd_get_section_by_name (sunos_hash_table (info)->dynobj, ".dynsym");
+ BFD_ASSERT (s != NULL);
+ outsym = ((struct external_nlist *)
+ (s->contents + h->dynindx * EXTERNAL_NLIST_SIZE));
+
+ H_PUT_8 (output_bfd, type, outsym->e_type);
+ H_PUT_8 (output_bfd, 0, outsym->e_other);
+
+ /* FIXME: The native linker doesn't use 0 for desc. It seems to use
+ one less than the desc value in the shared library, although that
+ seems unlikely. */
+ H_PUT_16 (output_bfd, 0, outsym->e_desc);
+
+ PUT_WORD (output_bfd, h->dynstr_index, outsym->e_strx);
+ PUT_WORD (output_bfd, val, outsym->e_value);
+
return true;
}
asection *input_section;
struct aout_link_hash_entry *harg;
PTR reloc;
- bfd_byte *contents;
+ bfd_byte *contents ATTRIBUTE_UNUSED;
boolean *skip;
bfd_vma *relocationp;
{
bfd *dynobj;
boolean baserel;
boolean jmptbl;
+ boolean pcrel;
asection *s;
bfd_byte *p;
long indx;
dynobj = sunos_hash_table (info)->dynobj;
- if (h != NULL && h->plt_offset != 0)
+ if (h != NULL
+ && h->plt_offset != 0
+ && (info->shared
+ || (h->flags & SUNOS_DEF_REGULAR) == 0))
{
asection *splt;
{
baserel = (0 != (srel->r_type[0] & RELOC_STD_BITS_BASEREL_BIG));
jmptbl = (0 != (srel->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG));
+ pcrel = (0 != (srel->r_type[0] & RELOC_STD_BITS_PCREL_BIG));
}
else
{
baserel = (0 != (srel->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE));
jmptbl = (0 != (srel->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE));
+ pcrel = (0 != (srel->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE));
}
}
else
|| r_type == RELOC_BASE13
|| r_type == RELOC_BASE22);
jmptbl = r_type == RELOC_JMP_TBL;
+ pcrel = (r_type == RELOC_DISP8
+ || r_type == RELOC_DISP16
+ || r_type == RELOC_DISP32
+ || r_type == RELOC_WDISP30
+ || r_type == RELOC_WDISP22);
+ /* We don't consider the PC10 and PC22 types to be PC relative,
+ because they are pcrel_offset. */
}
if (baserel)
srel->r_address);
if (bfd_header_big_endian (dynobj))
{
- srel->r_index[0] = indx >> 16;
- srel->r_index[1] = indx >> 8;
- srel->r_index[2] = indx;
+ srel->r_index[0] = (bfd_byte) (indx >> 16);
+ srel->r_index[1] = (bfd_byte) (indx >> 8);
+ srel->r_index[2] = (bfd_byte)indx;
if (h == NULL)
srel->r_type[0] = 2 << RELOC_STD_BITS_LENGTH_SH_BIG;
else
}
else
{
- srel->r_index[2] = indx >> 16;
- srel->r_index[1] = indx >> 8;
- srel->r_index[0] = indx;
+ srel->r_index[2] = (bfd_byte) (indx >> 16);
+ srel->r_index[1] = (bfd_byte) (indx >> 8);
+ srel->r_index[0] = (bfd_byte)indx;
if (h == NULL)
srel->r_type[0] = 2 << RELOC_STD_BITS_LENGTH_SH_LITTLE;
else
erel->r_address);
if (bfd_header_big_endian (dynobj))
{
- erel->r_index[0] = indx >> 16;
- erel->r_index[1] = indx >> 8;
- erel->r_index[2] = indx;
+ erel->r_index[0] = (bfd_byte) (indx >> 16);
+ erel->r_index[1] = (bfd_byte) (indx >> 8);
+ erel->r_index[2] = (bfd_byte)indx;
if (h == NULL)
erel->r_type[0] =
RELOC_32 << RELOC_EXT_BITS_TYPE_SH_BIG;
}
else
{
- erel->r_index[2] = indx >> 16;
- erel->r_index[1] = indx >> 8;
- erel->r_index[0] = indx;
+ erel->r_index[2] = (bfd_byte) (indx >> 16);
+ erel->r_index[1] = (bfd_byte) (indx >> 8);
+ erel->r_index[0] = (bfd_byte)indx;
if (h == NULL)
erel->r_type[0] =
RELOC_32 << RELOC_EXT_BITS_TYPE_SH_LITTLE;
*got_offsetp |= 1;
}
- *relocationp = sgot->vma + (*got_offsetp &~ 1);
+ *relocationp = (sgot->vma
+ + (*got_offsetp &~ (bfd_vma) 1)
+ - sunos_hash_table (info)->got_base);
/* There is nothing else to do for a base relative reloc. */
return true;
srel->r_address);
if (bfd_header_big_endian (dynobj))
{
- srel->r_index[0] = indx >> 16;
- srel->r_index[1] = indx >> 8;
- srel->r_index[2] = indx;
+ srel->r_index[0] = (bfd_byte) (indx >> 16);
+ srel->r_index[1] = (bfd_byte) (indx >> 8);
+ srel->r_index[2] = (bfd_byte)indx;
}
else
{
- srel->r_index[2] = indx >> 16;
- srel->r_index[1] = indx >> 8;
- srel->r_index[0] = indx;
+ srel->r_index[2] = (bfd_byte) (indx >> 16);
+ srel->r_index[1] = (bfd_byte) (indx >> 8);
+ srel->r_index[0] = (bfd_byte)indx;
}
+ /* FIXME: We may have to change the addend for a PC relative
+ reloc. */
}
else
{
erel->r_address);
if (bfd_header_big_endian (dynobj))
{
- erel->r_index[0] = indx >> 16;
- erel->r_index[1] = indx >> 8;
- erel->r_index[2] = indx;
+ erel->r_index[0] = (bfd_byte) (indx >> 16);
+ erel->r_index[1] = (bfd_byte) (indx >> 8);
+ erel->r_index[2] = (bfd_byte)indx;
}
else
{
- erel->r_index[2] = indx >> 16;
- erel->r_index[1] = indx >> 8;
- erel->r_index[0] = indx;
+ erel->r_index[2] = (bfd_byte) (indx >> 16);
+ erel->r_index[1] = (bfd_byte) (indx >> 8);
+ erel->r_index[0] = (bfd_byte)indx;
+ }
+ if (pcrel && h != NULL)
+ {
+ /* Adjust the addend for the change in address. */
+ PUT_WORD (dynobj,
+ (GET_WORD (dynobj, erel->r_addend)
+ - (input_section->output_section->vma
+ + input_section->output_offset
+ - input_section->vma)),
+ erel->r_addend);
}
}
asection *o;
asection *s;
asection *sdyn;
- struct external_sun4_dynamic esd;
- struct external_sun4_dynamic_link esdl;
- if (! sunos_hash_table (info)->dynamic_sections_needed)
+ if (! sunos_hash_table (info)->dynamic_sections_needed
+ && ! sunos_hash_table (info)->got_needed)
return true;
dynobj = sunos_hash_table (info)->dynobj;
dynamic information, unless this is a shared library. */
s = bfd_get_section_by_name (dynobj, ".got");
BFD_ASSERT (s != NULL);
- if (info->shared)
+ if (info->shared || sdyn->_raw_size == 0)
PUT_WORD (dynobj, 0, s->contents);
else
PUT_WORD (dynobj, sdyn->output_section->vma + sdyn->output_offset,
BFD_ASSERT (o->output_section != NULL
&& o->output_section->owner == abfd);
if (! bfd_set_section_contents (abfd, o->output_section,
- o->contents, o->output_offset,
+ o->contents,
+ (file_ptr) o->output_offset,
o->_raw_size))
return false;
}
}
- /* Finish up the dynamic link information. */
- PUT_WORD (dynobj, (bfd_vma) 3, esd.ld_version);
- PUT_WORD (dynobj,
- sdyn->output_section->vma + sdyn->output_offset + sizeof esd,
- esd.ldd);
- PUT_WORD (dynobj,
- (sdyn->output_section->vma
- + sdyn->output_offset
- + sizeof esd
- + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE),
- esd.ld);
-
- if (! bfd_set_section_contents (abfd, sdyn->output_section, &esd,
- sdyn->output_offset, sizeof esd))
- return false;
+ if (sdyn->_raw_size > 0)
+ {
+ struct external_sun4_dynamic esd;
+ struct external_sun4_dynamic_link esdl;
+ file_ptr pos;
+ /* Finish up the dynamic link information. */
+ PUT_WORD (dynobj, (bfd_vma) 3, esd.ld_version);
+ PUT_WORD (dynobj,
+ sdyn->output_section->vma + sdyn->output_offset + sizeof esd,
+ esd.ldd);
+ PUT_WORD (dynobj,
+ (sdyn->output_section->vma
+ + sdyn->output_offset
+ + sizeof esd
+ + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE),
+ esd.ld);
+
+ if (! bfd_set_section_contents (abfd, sdyn->output_section, &esd,
+ (file_ptr) sdyn->output_offset,
+ (bfd_size_type) sizeof esd))
+ return false;
- PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_loaded);
+ PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_loaded);
- s = bfd_get_section_by_name (dynobj, ".need");
- if (s == NULL || s->_raw_size == 0)
- PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_need);
- else
- PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
- esdl.ld_need);
+ s = bfd_get_section_by_name (dynobj, ".need");
+ if (s == NULL || s->_raw_size == 0)
+ PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_need);
+ else
+ PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
+ esdl.ld_need);
- s = bfd_get_section_by_name (dynobj, ".rules");
- if (s == NULL || s->_raw_size == 0)
- PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_rules);
- else
- PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
- esdl.ld_rules);
+ s = bfd_get_section_by_name (dynobj, ".rules");
+ if (s == NULL || s->_raw_size == 0)
+ PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_rules);
+ else
+ PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
+ esdl.ld_rules);
- s = bfd_get_section_by_name (dynobj, ".got");
- BFD_ASSERT (s != NULL);
- PUT_WORD (dynobj, s->output_section->vma + s->output_offset, esdl.ld_got);
+ s = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (s != NULL);
+ PUT_WORD (dynobj, s->output_section->vma + s->output_offset,
+ esdl.ld_got);
- s = bfd_get_section_by_name (dynobj, ".plt");
- BFD_ASSERT (s != NULL);
- PUT_WORD (dynobj, s->output_section->vma + s->output_offset, esdl.ld_plt);
- PUT_WORD (dynobj, s->_raw_size, esdl.ld_plt_sz);
+ s = bfd_get_section_by_name (dynobj, ".plt");
+ BFD_ASSERT (s != NULL);
+ PUT_WORD (dynobj, s->output_section->vma + s->output_offset,
+ esdl.ld_plt);
+ PUT_WORD (dynobj, s->_raw_size, esdl.ld_plt_sz);
- s = bfd_get_section_by_name (dynobj, ".dynrel");
- BFD_ASSERT (s != NULL);
- BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj) == s->_raw_size);
- PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
- esdl.ld_rel);
+ s = bfd_get_section_by_name (dynobj, ".dynrel");
+ BFD_ASSERT (s != NULL);
+ BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj)
+ == s->_raw_size);
+ PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
+ esdl.ld_rel);
- s = bfd_get_section_by_name (dynobj, ".hash");
- BFD_ASSERT (s != NULL);
- PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
- esdl.ld_hash);
+ s = bfd_get_section_by_name (dynobj, ".hash");
+ BFD_ASSERT (s != NULL);
+ PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
+ esdl.ld_hash);
- s = bfd_get_section_by_name (dynobj, ".dynsym");
- BFD_ASSERT (s != NULL);
- PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
- esdl.ld_stab);
+ s = bfd_get_section_by_name (dynobj, ".dynsym");
+ BFD_ASSERT (s != NULL);
+ PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
+ esdl.ld_stab);
- PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_stab_hash);
+ PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_stab_hash);
- PUT_WORD (dynobj, (bfd_vma) sunos_hash_table (info)->bucketcount,
- esdl.ld_buckets);
+ PUT_WORD (dynobj, (bfd_vma) sunos_hash_table (info)->bucketcount,
+ esdl.ld_buckets);
- s = bfd_get_section_by_name (dynobj, ".dynstr");
- BFD_ASSERT (s != NULL);
- PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
- esdl.ld_symbols);
- PUT_WORD (dynobj, s->_raw_size, esdl.ld_symb_size);
-
- /* The size of the text area is the size of the .text section
- rounded up to a page boundary. FIXME: Should the page size be
- conditional on something? */
- PUT_WORD (dynobj,
- BFD_ALIGN (obj_textsec (abfd)->_raw_size, 0x2000),
- esdl.ld_text);
-
- if (! bfd_set_section_contents (abfd, sdyn->output_section, &esdl,
- (sdyn->output_offset
- + sizeof esd
- + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE),
- sizeof esdl))
- return false;
+ s = bfd_get_section_by_name (dynobj, ".dynstr");
+ BFD_ASSERT (s != NULL);
+ PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
+ esdl.ld_symbols);
+ PUT_WORD (dynobj, s->_raw_size, esdl.ld_symb_size);
- abfd->flags |= DYNAMIC;
+ /* The size of the text area is the size of the .text section
+ rounded up to a page boundary. FIXME: Should the page size be
+ conditional on something? */
+ PUT_WORD (dynobj,
+ BFD_ALIGN (obj_textsec (abfd)->_raw_size, 0x2000),
+ esdl.ld_text);
+
+ pos = sdyn->output_offset;
+ pos += sizeof esd + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE;
+ if (! bfd_set_section_contents (abfd, sdyn->output_section, &esdl,
+ pos, (bfd_size_type) sizeof esdl))
+ return false;
+
+ abfd->flags |= DYNAMIC;
+ }
return true;
}