aboutsummaryrefslogtreecommitdiff
path: root/bfd/linker.c
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1995-02-06 20:01:08 +0000
committerIan Lance Taylor <ian@airs.com>1995-02-06 20:01:08 +0000
commit6c97aedf2686633d3e837802ce51ebe630f64056 (patch)
treebb409db186375bad6ede2a558c8a29d9dd1cb950 /bfd/linker.c
parentebc4ca90f97420f225f48141c631405357b58c16 (diff)
downloadgdb-6c97aedf2686633d3e837802ce51ebe630f64056.zip
gdb-6c97aedf2686633d3e837802ce51ebe630f64056.tar.gz
gdb-6c97aedf2686633d3e837802ce51ebe630f64056.tar.bz2
Distinguish a weak defined symbol from a regular defined symbol.
* linker.c (enum link_action): Add DEFW. (link_action): Add bfd_link_hash_defweak column. (_bfd_generic_link_add_one_symbol): Add DEFW case. Handle bfd_link_hash_defweak in a few other cases. * Many files (bfd_link_hash_undefweak): Renamed from bfd_link_hash_weak. * aoutx.h (aout_link_write_symbols): Handle bfd_link_hash_defweak. (aout_link_write_other_symbol): Likewise. (aout_link_input_section_std): Likewise. (aout_link_input_section_ext): Likewise. * bout.c (get_value): Likewise. * coff-a29k.c (coff_a29k_relocate_section): Likewise. * coff-alpha.c (alpha_convert_external_reloc): Likewise. (alpha_relocate_section): Likewise. * coff-mips.c (mips_relocate_section): Likewise. (mips_relax_section): Likewise. (bfd_mips_ecoff_create_embedded_relocs): Likewise. * cofflink.c (coff_write_global_sym): Likewise. (_bfd_coff_generic_relocate_section): Likewise. * ecoff.c (ecoff_link_add_externals): Likewise. (ecoff_link_write_external): LIkewise. * elf32-hppa.c (elf32_hppa_relocate_section): Likewise. (elf32_hppa_size_stubs): Likewise. * elf32-i386.c (elf_i386_adjust_dynamic_symbol): Likewise. (elf_i386_relocate_section): Likewise. (elf_i386_finish_dynamic_symbol): Likewise. * elf32-mips.c (mips_elf_output_extsym): Likewise. (mips_elf_relocate_section): Likewise. * elf32-sparc.c (elf32_sparc_adjust_dynamic_symbol): Likewise. (elf32_sparc_relocate_section): Likewise. * elfcode.h (elf_link_add_object_symbols): Likewise. (elf_adjust_dynamic_symbol): Likewise. (elf_bfd_final_link): Likewise. (elf_link_output_extsym): Likewise. * i386linux.c (linux_add_one_symbol): Likewise. (linux_tally_symbols): Likewise. (linux_finish_dynamic_link): Likewise. * linker.c (_bfd_generic_link_output_symbols): Likewise. (set_symbol_from_hash): Likewise. * reloc16.c (bfd_coff_reloc16_get_value): Likewise. (bfd_perform_slip): Likewise. * sunos.c (sunos_add_one_symbol): Likewise. (sunos_scan_std_relocs): Likewise. (sunos_scan_ext_relocs): Likewise. (sunos_scan_dynamic_symbol): Likewise. (sunos_write_dynamic_symbol): Likewise.
Diffstat (limited to 'bfd/linker.c')
-rw-r--r--bfd/linker.c168
1 files changed, 97 insertions, 71 deletions
diff --git a/bfd/linker.c b/bfd/linker.c
index 37ab1c8..1c4b8fe 100644
--- a/bfd/linker.c
+++ b/bfd/linker.c
@@ -1,5 +1,5 @@
/* linker.c -- BFD linker routines
- Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
Written by Steve Chamberlain and Ian Lance Taylor, Cygnus Support
This file is part of BFD, the Binary File Descriptor library.
@@ -380,10 +380,7 @@ SUBSUBSECTION
written out when considering the symbols of each input file,
but it is still necessary to traverse the hash table since the
linker script may have defined some symbols that are not in
- any of the input files. The <<written>> field in the
- <<bfd_link_hash_entry>> structure may be used to determine
- which entries in the hash table have not already been written
- out.
+ any of the input files.
The <<strip>> field of the <<bfd_link_info>> structure
controls which symbols are written out. The possible values
@@ -1065,9 +1062,9 @@ generic_link_check_archive_element (abfd, info, pneeded, collect)
/* We are only interested if we know something about this
symbol, and it is undefined or common. An undefined weak
- symbol (type bfd_link_hash_weak) is not considered to be a
- reference when pulling files out of an archive. See the SVR4
- ABI, p. 4-27. */
+ symbol (type bfd_link_hash_undefweak) is not considered to be
+ a reference when pulling files out of an archive. See the
+ SVR4 ABI, p. 4-27. */
h = bfd_link_hash_lookup (info->hash, bfd_asymbol_name (p), false,
false, true);
if (h == (struct bfd_link_hash_entry *) NULL
@@ -1287,6 +1284,7 @@ enum link_action
UND, /* Mark symbol undefined. */
WEAK, /* Mark symbol weak undefined. */
DEF, /* Mark symbol defined. */
+ DEFW, /* Mark symbol weak defined. */
COM, /* Mark symbol common. */
REF, /* Mark defined symbol referenced. */
CREF, /* Possibly warn about common reference to defined symbol. */
@@ -1309,17 +1307,17 @@ enum link_action
/* The state table itself. The first index is a link_row and the
second index is a bfd_link_hash_type. */
-static const enum link_action link_action[8][7] =
+static const enum link_action link_action[8][8] =
{
- /* current\prev new undef weak def com indr warn */
- /* UNDEF_ROW */ {UND, NOACT, NOACT, REF, NOACT, REFC, WARNC },
- /* UNDEFW_ROW */ {WEAK, WEAK, NOACT, REF, NOACT, REFC, WARNC },
- /* DEF_ROW */ {DEF, DEF, DEF, MDEF, CDEF, MDEF, CYCLE },
- /* DEFW_ROW */ {DEF, DEF, DEF, NOACT, NOACT, NOACT, CYCLE },
- /* COMMON_ROW */ {COM, COM, COM, CREF, BIG, CREF, WARNC },
- /* INDR_ROW */ {IND, IND, IND, MDEF, CIND, MIND, CYCLE },
- /* WARN_ROW */ {MWARN, WARN, WARN, CWARN, WARN, CWARN, CYCLE },
- /* SET_ROW */ {SET, SET, SET, SET, SET, CYCLE, CYCLE }
+ /* current\prev new undef undefw def defw com indr warn */
+ /* UNDEF_ROW */ {UND, NOACT, NOACT, REF, REF, NOACT, REFC, WARNC },
+ /* UNDEFW_ROW */ {WEAK, WEAK, NOACT, REF, REF, NOACT, REFC, WARNC },
+ /* DEF_ROW */ {DEF, DEF, DEF, MDEF, DEF, CDEF, MDEF, CYCLE },
+ /* DEFW_ROW */ {DEFW, DEFW, DEFW, NOACT, NOACT, NOACT, NOACT, CYCLE },
+ /* COMMON_ROW */ {COM, COM, COM, CREF, CREF, BIG, CREF, WARNC },
+ /* INDR_ROW */ {IND, IND, IND, MDEF, IND, CIND, MIND, CYCLE },
+ /* WARN_ROW */ {MWARN, WARN, WARN, CWARN, CWARN, WARN, CWARN, CYCLE },
+ /* SET_ROW */ {SET, SET, SET, SET, SET, SET, CYCLE, CYCLE }
};
/* Most of the entries in the LINK_ACTION table are straightforward,
@@ -1453,7 +1451,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
case WEAK:
/* Make a new weak undefined symbol. */
- h->type = bfd_link_hash_weak;
+ h->type = bfd_link_hash_undefweak;
h->u.undef.abfd = abfd;
break;
@@ -1468,50 +1466,69 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
return false;
/* Fall through. */
case DEF:
- /* Define a symbol. */
- h->type = bfd_link_hash_defined;
- h->u.def.section = section;
- h->u.def.value = value;
-
- /* If we have been asked to, we act like collect2 and
- identify all functions that might be global constructors
- and destructors and pass them up in a callback. We only
- do this for certain object file types, since many object
- file types can handle this automatically. */
- if (collect && name[0] == '_')
- {
- const char *s;
+ case DEFW:
+ {
+ enum bfd_link_order_type oldtype;
- /* A constructor or destructor name starts like this:
- _+GLOBAL_[_.$][ID][_.$]
- where the first [_.$] and the second are the same
- character (we accept any character there, in case a
- new object file format comes along with even worse
- naming restrictions). */
+ /* Define a symbol. */
+ oldtype = h->type;
+ if (action == DEFW)
+ h->type = bfd_link_hash_defweak;
+ else
+ h->type = bfd_link_hash_defined;
+ h->u.def.section = section;
+ h->u.def.value = value;
+
+ /* If we have been asked to, we act like collect2 and
+ identify all functions that might be global
+ constructors and destructors and pass them up in a
+ callback. We only do this for certain object file
+ types, since many object file types can handle this
+ automatically. */
+ if (collect && name[0] == '_')
+ {
+ const char *s;
+
+ /* A constructor or destructor name starts like this:
+ _+GLOBAL_[_.$][ID][_.$] where the first [_.$] and
+ the second are the same character (we accept any
+ character there, in case a new object file format
+ comes along with even worse naming restrictions). */
#define CONS_PREFIX "GLOBAL_"
#define CONS_PREFIX_LEN (sizeof CONS_PREFIX - 1)
- s = name + 1;
- while (*s == '_')
- ++s;
- if (s[0] == 'G'
- && strncmp (s, CONS_PREFIX, CONS_PREFIX_LEN - 1) == 0)
- {
- char c;
-
- c = s[CONS_PREFIX_LEN + 1];
- if ((c == 'I' || c == 'D')
- && s[CONS_PREFIX_LEN] == s[CONS_PREFIX_LEN + 2])
- {
- if (! ((*info->callbacks->constructor)
- (info,
- c == 'I' ? true : false,
- name, abfd, section, value)))
- return false;
- }
- }
- }
+ s = name + 1;
+ while (*s == '_')
+ ++s;
+ if (s[0] == 'G'
+ && strncmp (s, CONS_PREFIX, CONS_PREFIX_LEN - 1) == 0)
+ {
+ char c;
+
+ c = s[CONS_PREFIX_LEN + 1];
+ if ((c == 'I' || c == 'D')
+ && s[CONS_PREFIX_LEN] == s[CONS_PREFIX_LEN + 2])
+ {
+ /* If this is a definition of a symbol which
+ was previously weakly defined, we are in
+ trouble. We have already added a
+ constructor entry for the weak defined
+ symbol, and now we are trying to add one
+ for the new symbol. Fortunately, this case
+ should never arise in practice. */
+ if (oldtype == bfd_link_hash_defweak)
+ abort ();
+
+ if (! ((*info->callbacks->constructor)
+ (info,
+ c == 'I' ? true : false,
+ name, abfd, section, value)))
+ return false;
+ }
+ }
+ }
+ }
break;
@@ -1602,7 +1619,8 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
was already defined. FIXME: It would nice if we could
report the BFD which defined an indirect symbol, but we
don't have anywhere to store the information. */
- if (h->type == bfd_link_hash_defined)
+ if (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_defweak)
obfd = h->u.def.section->owner;
else
obfd = NULL;
@@ -1631,10 +1649,6 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
msec = h->u.def.section;
mval = h->u.def.value;
break;
- case bfd_link_hash_common:
- msec = bfd_com_section_ptr;
- mval = h->u.c.size;
- break;
case bfd_link_hash_indirect:
msec = bfd_ind_section_ptr;
mval = 0;
@@ -1738,10 +1752,10 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
case CWARN:
/* Warn if this symbol has been referenced already,
- otherwise either add a warning or cycle. A symbol has
- been referenced if the next field is not NULL, or it is
- the tail of the undefined symbol list. The REF case
- above helps to ensure this. */
+ otherwise add a warning. A symbol has been referenced if
+ the next field is not NULL, or it is the tail of the
+ undefined symbol list. The REF case above helps to
+ ensure this. */
if (h->next != NULL || info->hash->undefs_tail == h)
{
if (! (*info->callbacks->warning) (info, string))
@@ -2037,12 +2051,19 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
case bfd_link_hash_new:
abort ();
case bfd_link_hash_undefined:
- case bfd_link_hash_weak:
+ break;
+ case bfd_link_hash_undefweak:
+ sym->flags |= BSF_WEAK;
break;
case bfd_link_hash_defined:
+ sym->flags |= BSF_GLOBAL;
+ sym->value = h->root.u.def.value;
+ sym->section = h->root.u.def.section;
+ break;
+ case bfd_link_hash_defweak:
+ sym->flags |= BSF_WEAK;
sym->value = h->root.u.def.value;
sym->section = h->root.u.def.section;
- sym->flags |= BSF_GLOBAL;
break;
case bfd_link_hash_common:
sym->value = h->root.u.c.size;
@@ -2160,7 +2181,7 @@ set_symbol_from_hash (sym, h)
sym->section = bfd_und_section_ptr;
sym->value = 0;
break;
- case bfd_link_hash_weak:
+ case bfd_link_hash_undefweak:
sym->section = bfd_und_section_ptr;
sym->value = 0;
sym->flags |= BSF_WEAK;
@@ -2169,6 +2190,11 @@ set_symbol_from_hash (sym, h)
sym->section = h->u.def.section;
sym->value = h->u.def.value;
break;
+ case bfd_link_hash_defweak:
+ sym->flags |= BSF_WEAK;
+ sym->section = h->u.def.section;
+ sym->value = h->u.def.value;
+ break;
case bfd_link_hash_common:
sym->value = h->u.c.size;
if (sym->section == NULL)
@@ -2263,7 +2289,7 @@ _bfd_generic_reloc_link_order (abfd, info, sec, link_order)
r->address = link_order->offset;
r->howto = bfd_reloc_type_lookup (abfd, link_order->u.reloc.p->reloc);
- if (r->howto == (const reloc_howto_type *) NULL)
+ if (r->howto == 0)
{
bfd_set_error (bfd_error_bad_value);
return false;