Add weak symbols as an extension to a.out.
authorIan Lance Taylor <ian@airs.com>
Sat, 11 Jun 1994 20:40:59 +0000 (20:40 +0000)
committerIan Lance Taylor <ian@airs.com>
Sat, 11 Jun 1994 20:40:59 +0000 (20:40 +0000)
* aoutx.h (sym_in_text_section): Don't define.
(sym_in_data_section, sym_in_bss_section): Likewise.
(sym_is_undefined, sym_is_global_defn): Likewise.
(sym_is_debugger_info, sym_is_fortrancommon): Likewise.
(sym_is_absolute, sym_is_indirect): Likewise.
(translate_from_native_sym_flags): Rewrite for clarity.  Rearrange
arguments and change caller.  Handle weak symbols.
(translate_to_native_sym_flags): Likewise.
(aout_link_check_ar_symbols): Don't ignore weak symbols.  Pull
object in from archive if a weak defintion is found for an
existing undefined symbol.
(aout_link_add_symbols): Put all cases in switch.  Set flags of an
undefined symbol to 0.  Handle weak symbols.
(aout_link_write_symbols): Handle weak symbols.
(aout_link_write_other_symbol): Likewise.
(aout_link_input_section_std): Likewise.
(aout_link_input_section_ext): Likewise.
* sunos.c (sunos_write_dynamic_symbol): Likewise.

bfd/ChangeLog
bfd/aoutx.h
bfd/sunos.c

index aad953e..7984467 100644 (file)
@@ -1,3 +1,25 @@
+Sat Jun 11 16:32:30 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       Add weak symbols as an extension to a.out.
+       * aoutx.h (sym_in_text_section): Don't define.
+       (sym_in_data_section, sym_in_bss_section): Likewise.
+       (sym_is_undefined, sym_is_global_defn): Likewise.
+       (sym_is_debugger_info, sym_is_fortrancommon): Likewise.
+       (sym_is_absolute, sym_is_indirect): Likewise.
+       (translate_from_native_sym_flags): Rewrite for clarity.  Rearrange
+       arguments and change caller.  Handle weak symbols.
+       (translate_to_native_sym_flags): Likewise.
+       (aout_link_check_ar_symbols): Don't ignore weak symbols.  Pull
+       object in from archive if a weak defintion is found for an
+       existing undefined symbol.
+       (aout_link_add_symbols): Put all cases in switch.  Set flags of an
+       undefined symbol to 0.  Handle weak symbols.
+       (aout_link_write_symbols): Handle weak symbols.
+       (aout_link_write_other_symbol): Likewise.
+       (aout_link_input_section_std): Likewise.
+       (aout_link_input_section_ext): Likewise.
+       * sunos.c (sunos_write_dynamic_symbol): Likewise.
+
 Fri Jun 10 13:25:13 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
 
        * aoutx.h (NAME(aout,canonicalize_reloc)): Handle .bss section.
index 5801c71..742f79d 100644 (file)
@@ -133,6 +133,10 @@ DESCRIPTION
 #include "aout/ar.h"
 
 static boolean aout_get_external_symbols PARAMS ((bfd *));
+static boolean translate_from_native_sym_flags
+  PARAMS ((bfd *, aout_symbol_type *));
+static boolean translate_to_native_sym_flags
+  PARAMS ((bfd *, asymbol *, struct external_nlist *));
 
 /*
 SUBSECTION
@@ -1063,44 +1067,6 @@ NAME(aout,set_section_contents) (abfd, section, location, offset, count)
   return true;
 }
 \f
-/* Classify stabs symbols */
-
-#define sym_in_text_section(sym) \
-  (((sym)->type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_TEXT)
-
-#define sym_in_data_section(sym) \
-  (((sym)->type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_DATA)
-
-#define sym_in_bss_section(sym) \
-  (((sym)->type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_BSS)
-
-/* Symbol is undefined if type is N_UNDF|N_EXT and if it has
-  zero in the "value" field.  Nonzeroes there are fortrancommon
-  symbols.  */
-#define sym_is_undefined(sym) \
-  ((sym)->type == (N_UNDF | N_EXT) && (sym)->symbol.value == 0)
-
-/* Symbol is a global definition if N_EXT is on and if it has
-  a nonzero type field.  */
-#define sym_is_global_defn(sym) \
-  (((sym)->type & N_EXT) && (sym)->type & N_TYPE)
-
-/* Symbol is debugger info if any bits outside N_TYPE or N_EXT
-  are on.  */
-#define sym_is_debugger_info(sym) \
-  (((sym)->type & ~(N_EXT | N_TYPE)) || (sym)->type == N_FN)
-
-#define sym_is_fortrancommon(sym)       \
-  (((sym)->type == (N_EXT)) && (sym)->symbol.value != 0)
-
-/* Symbol is absolute if it has N_ABS set */
-#define sym_is_absolute(sym) \
-  (((sym)->type  & N_TYPE)== N_ABS)
-
-
-#define sym_is_indirect(sym) \
-  (((sym)->type & N_ABS)== N_ABS)
-
 /* Read the external symbols from an a.out file.  */
 
 static boolean
@@ -1178,298 +1144,340 @@ aout_get_external_symbols (abfd)
   return true;
 }
 
-/* Only in their own functions for ease of debugging; when sym flags have
-  stabilised these should be inlined into their (single) caller */
+/* Translate an a.out symbol into a BFD symbol.  The desc, other, type
+   and symbol->value fields of CACHE_PTR will be set from the a.out
+   nlist structure.  This function is responsible for setting
+   symbol->flags and symbol->section, and adjusting symbol->value.  */
 
 static boolean
-translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd)
-     struct external_nlist *sym_pointer;
-     aout_symbol_type * cache_ptr;
-     bfd * abfd;
+translate_from_native_sym_flags (abfd, cache_ptr)
+     bfd *abfd;
+     aout_symbol_type *cache_ptr;
 {
-  cache_ptr->symbol.section = 0;
-  switch (cache_ptr->type & N_TYPE)
+  flagword visible;
+
+  if ((cache_ptr->type & N_STAB) != 0
+      || cache_ptr->type == N_FN)
+    {
+      asection *sec;
+
+      /* This is a debugging symbol.  */
+
+      cache_ptr->symbol.flags = BSF_DEBUGGING;
+
+      /* Work out the symbol section.  */
+      switch (cache_ptr->type & N_TYPE)
+       {
+       case N_TEXT:
+       case N_FN:
+         sec = obj_textsec (abfd);
+         break;
+       case N_DATA:
+         sec = obj_datasec (abfd);
+         break;
+       case N_BSS:
+         sec = obj_bsssec (abfd);
+         break;
+       default:
+       case N_ABS:
+         sec = &bfd_abs_section;
+         break;
+       }
+
+      cache_ptr->symbol.section = sec;
+      cache_ptr->symbol.value -= sec->vma;
+
+      return true;
+    }
+
+  /* Get the default visibility.  This does not apply to all types, so
+     we just hold it in a local variable to use if wanted.  */
+  if ((cache_ptr->type & N_EXT) == 0)
+    visible = BSF_LOCAL;
+  else
+    visible = BSF_GLOBAL;
+
+  switch (cache_ptr->type)
     {
+    default:
+    case N_ABS: case N_ABS | N_EXT:
+      cache_ptr->symbol.section = &bfd_abs_section;
+      cache_ptr->symbol.flags = visible;
+      break;
+
+    case N_UNDF | N_EXT:
+      if (cache_ptr->symbol.value != 0)
+       {
+         /* This is a common symbol.  */
+         cache_ptr->symbol.flags = BSF_GLOBAL;
+         cache_ptr->symbol.section = &bfd_com_section;
+       }
+      else
+       {
+         cache_ptr->symbol.flags = 0;
+         cache_ptr->symbol.section = &bfd_und_section;
+       }
+      break;
+
+    case N_TEXT: case N_TEXT | N_EXT:
+      cache_ptr->symbol.section = obj_textsec (abfd);
+      cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
+      cache_ptr->symbol.flags = visible;
+      break;
+
+    case N_DATA: case N_DATA | N_EXT:
+      cache_ptr->symbol.section = obj_datasec (abfd);
+      cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
+      cache_ptr->symbol.flags = visible;
+      break;
+
+    case N_BSS: case N_BSS | N_EXT:
+      cache_ptr->symbol.section = obj_bsssec (abfd);
+      cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
+      cache_ptr->symbol.flags = visible;
+      break;
+
     case N_SETA: case N_SETA | N_EXT:
     case N_SETT: case N_SETT | N_EXT:
     case N_SETD: case N_SETD | N_EXT:
     case N_SETB: case N_SETB | N_EXT:
       {
-       char *copy = bfd_alloc (abfd, strlen (cache_ptr->symbol.name) + 1);
        asection *section;
+       arelent_chain *reloc;
        asection *into_section;
-       arelent_chain *reloc = (arelent_chain *) bfd_alloc (abfd, sizeof (arelent_chain));
 
-       if (!copy || !reloc)
+       /* This is a set symbol.  The name of the symbol is the name
+          of the set (e.g., __CTOR_LIST__).  The value of the symbol
+          is the value to add to the set.  We create a section with
+          the same name as the symbol, and add a reloc to insert the
+          appropriate value into the section.
+
+          This action is actually obsolete; it used to make the
+          linker do the right thing, but the linker no longer uses
+          this function.  */
+
+       section = bfd_get_section_by_name (abfd, cache_ptr->symbol.name);
+       if (section == NULL)
+         {
+           char *copy;
+
+           copy = bfd_alloc (abfd, strlen (cache_ptr->symbol.name) + 1);
+           if (copy == NULL)
+             {
+               bfd_set_error (bfd_error_no_memory);
+               return false;
+             }
+
+           strcpy (copy, cache_ptr->symbol.name);
+           section = bfd_make_section (abfd, copy);
+           if (section == NULL)
+             return false;
+         }
+
+       reloc = (arelent_chain *) bfd_alloc (abfd, sizeof (arelent_chain));
+       if (reloc == NULL)
          {
            bfd_set_error (bfd_error_no_memory);
            return false;
          }
 
-       strcpy (copy, cache_ptr->symbol.name);
-
-       /* Make sure that this bfd has a section with the right contructor
-          name */
-       section = bfd_get_section_by_name (abfd, copy);
-       if (!section)
-         section = bfd_make_section (abfd, copy);
-
-       /* Build a relocation entry for the constructor */
-       switch ((cache_ptr->type & N_TYPE))
+       /* Build a relocation entry for the constructor.  */
+       switch (cache_ptr->type & N_TYPE)
          {
-         case N_SETA: case N_SETA | N_EXT:
+         case N_SETA:
            into_section = &bfd_abs_section;
            cache_ptr->type = N_ABS;
            break;
-         case N_SETT: case N_SETT | N_EXT:
-           into_section = (asection *) obj_textsec (abfd);
+         case N_SETT:
+           into_section = obj_textsec (abfd);
            cache_ptr->type = N_TEXT;
            break;
-         case N_SETD: case N_SETD | N_EXT:
-           into_section = (asection *) obj_datasec (abfd);
+         case N_SETD:
+           into_section = obj_datasec (abfd);
            cache_ptr->type = N_DATA;
            break;
-         case N_SETB: case N_SETB | N_EXT:
-           into_section = (asection *) obj_bsssec (abfd);
+         case N_SETB:
+           into_section = obj_bsssec (abfd);
            cache_ptr->type = N_BSS;
            break;
-         default:
-           bfd_set_error (bfd_error_bad_value);
-           return false;
          }
 
-       /* Build a relocation pointing into the constuctor section
-          pointing at the symbol in the set vector specified */
-
+       /* Build a relocation pointing into the constructor section
+          pointing at the symbol in the set vector specified.  */
        reloc->relent.addend = cache_ptr->symbol.value;
-       cache_ptr->symbol.section = into_section->symbol->section;
+       cache_ptr->symbol.section = into_section;
        reloc->relent.sym_ptr_ptr = into_section->symbol_ptr_ptr;
 
-
-       /* We modify the symbol to belong to a section depending upon the
-          name of the symbol - probably __CTOR__ or __DTOR__ but we don't
-          really care, and add to the size of the section to contain a
-          pointer to the symbol. Build a reloc entry to relocate to this
-          symbol attached to this section.  */
-
+       /* We modify the symbol to belong to a section depending upon
+          the name of the symbol, and add to the size of the section
+          to contain a pointer to the symbol. Build a reloc entry to
+          relocate to this symbol attached to this section.  */
        section->flags = SEC_CONSTRUCTOR | SEC_RELOC;
 
-
        section->reloc_count++;
        section->alignment_power = 2;
 
        reloc->next = section->constructor_chain;
        section->constructor_chain = reloc;
        reloc->relent.address = section->_raw_size;
-       section->_raw_size += sizeof (int *);
+       section->_raw_size += BYTES_IN_WORD;
+
+       if (obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE)
+         reloc->relent.howto = howto_table_ext + CTOR_TABLE_RELOC_IDX;
+       else
+         reloc->relent.howto = howto_table_std + CTOR_TABLE_RELOC_IDX;
 
-       reloc->relent.howto
-         = (obj_reloc_entry_size(abfd) == RELOC_EXT_SIZE
-            ? howto_table_ext : howto_table_std)
-           + CTOR_TABLE_RELOC_IDX;
        cache_ptr->symbol.flags |= BSF_CONSTRUCTOR;
       }
       break;
-    default:
-      if (cache_ptr->type == N_WARNING)
-       {
-         /* This symbol is the text of a warning message, the next symbol
-            is the symbol to associate the warning with */
-         cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_WARNING;
-
-         /* @@ Stuffing pointers into integers is a no-no.
-            We can usually get away with it if the integer is
-            large enough though.  */
-         if (sizeof (cache_ptr + 1) > sizeof (bfd_vma))
-           abort ();
-         cache_ptr->symbol.value = (bfd_vma) ((cache_ptr + 1));
-
-          /* We don't use a warning symbol's section, but we need
-            it to be nonzero for the sanity check below, so
-            pick one arbitrarily.  */
-         cache_ptr->symbol.section = &bfd_abs_section;
 
-         break;
-       }
-      if ((cache_ptr->type | N_EXT) == (N_INDR | N_EXT))
-       {
-         /* Two symbols in a row for an INDR message. The first symbol
-            contains the name we will match, the second symbol contains
-            the name the first name is translated into. It is supplied to
-            us undefined. This is good, since we want to pull in any files
-            which define it */
-         cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_INDIRECT;
-
-         /* @@ Stuffing pointers into integers is a no-no.
-            We can usually get away with it if the integer is
-            large enough though.  */
-         if (sizeof (cache_ptr + 1) > sizeof (bfd_vma))
-           abort ();
-
-         cache_ptr->symbol.value = (bfd_vma) ((cache_ptr + 1));
-         cache_ptr->symbol.section = &bfd_ind_section;
-       }
+    case N_WARNING:
+      /* This symbol is the text of a warning message.  The next
+        symbol is the symbol to associate the warning with.  If a
+        reference is made to that symbol, a warning is issued.  */
+      cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_WARNING;
 
-      else if (sym_is_debugger_info (cache_ptr))
-       {
-         cache_ptr->symbol.flags = BSF_DEBUGGING;
-         /* Work out the section correct for this symbol */
-         switch (cache_ptr->type & N_TYPE)
-           {
-           case N_TEXT:
-           case N_FN:
-             cache_ptr->symbol.section = obj_textsec (abfd);
-             cache_ptr->symbol.value -= obj_textsec (abfd)->vma;
-             break;
-           case N_DATA:
-             cache_ptr->symbol.value -= obj_datasec (abfd)->vma;
-             cache_ptr->symbol.section = obj_datasec (abfd);
-             break;
-           case N_BSS:
-             cache_ptr->symbol.section = obj_bsssec (abfd);
-             cache_ptr->symbol.value -= obj_bsssec (abfd)->vma;
-             break;
-           default:
-           case N_ABS:
-             cache_ptr->symbol.section = &bfd_abs_section;
-             break;
-           }
-       }
-      else
-       {
+      /* @@ Stuffing pointers into integers is a no-no.  We can
+        usually get away with it if the integer is large enough
+        though.  */
+      if (sizeof (cache_ptr + 1) > sizeof (bfd_vma))
+       abort ();
+      cache_ptr->symbol.value = (bfd_vma) (cache_ptr + 1);
 
-         if (sym_is_fortrancommon (cache_ptr))
-           {
-             cache_ptr->symbol.flags = 0;
-             cache_ptr->symbol.section = &bfd_com_section;
-           }
-         else
-           {
+      cache_ptr->symbol.section = &bfd_abs_section;
 
+      break;
 
-           }
+    case N_INDR: case N_INDR | N_EXT:
+      /* An indirect symbol.  This consists of two symbols in a row.
+        The first symbol is the name of the indirection.  The second
+        symbol is the name of the target.  A reference to the first
+        symbol becomes a reference to the second.  */
+      cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_INDIRECT | visible;
 
-         /* In a.out, the value of a symbol is always relative to the
-          * start of the file, if this is a data symbol we'll subtract
-          * the size of the text section to get the section relative
-          * value. If this is a bss symbol (which would be strange)
-          * we'll subtract the size of the previous two sections
-          * to find the section relative address.
-          */
+      /* @@ Stuffing pointers into integers is a no-no.  We can
+        usually get away with it if the integer is large enough
+        though.  */
+      if (sizeof (cache_ptr + 1) > sizeof (bfd_vma))
+       abort ();
+      cache_ptr->symbol.value = (bfd_vma) (cache_ptr + 1);
 
-         if (sym_in_text_section (cache_ptr))
-           {
-             cache_ptr->symbol.value -= obj_textsec (abfd)->vma;
-             cache_ptr->symbol.section = obj_textsec (abfd);
-           }
-         else if (sym_in_data_section (cache_ptr))
-           {
-             cache_ptr->symbol.value -= obj_datasec (abfd)->vma;
-             cache_ptr->symbol.section = obj_datasec (abfd);
-           }
-         else if (sym_in_bss_section (cache_ptr))
-           {
-             cache_ptr->symbol.section = obj_bsssec (abfd);
-             cache_ptr->symbol.value -= obj_bsssec (abfd)->vma;
-           }
-         else if (sym_is_undefined (cache_ptr))
-           {
-             cache_ptr->symbol.flags = 0;
-             cache_ptr->symbol.section = &bfd_und_section;
-           }
-         else if (sym_is_absolute (cache_ptr))
-           {
-             cache_ptr->symbol.section = &bfd_abs_section;
-           }
+      cache_ptr->symbol.section = &bfd_ind_section;
 
-         if (sym_is_global_defn (cache_ptr))
-           {
-             cache_ptr->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
-           }
-         else if (! sym_is_undefined (cache_ptr))
-           {
-             cache_ptr->symbol.flags = BSF_LOCAL;
-           }
-       }
+      break;
+
+    case N_WEAKU:
+      cache_ptr->symbol.section = &bfd_und_section;
+      cache_ptr->symbol.flags = BSF_WEAK;
+      break;
+
+    case N_WEAKA:
+      cache_ptr->symbol.section = &bfd_abs_section;
+      cache_ptr->symbol.flags = BSF_WEAK;
+      break;
+
+    case N_WEAKT:
+      cache_ptr->symbol.section = obj_textsec (abfd);
+      cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
+      cache_ptr->symbol.flags = BSF_WEAK;
+      break;
+
+    case N_WEAKD:
+      cache_ptr->symbol.section = obj_datasec (abfd);
+      cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
+      cache_ptr->symbol.flags = BSF_WEAK;
+      break;
+
+    case N_WEAKB:
+      cache_ptr->symbol.section = obj_bsssec (abfd);
+      cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
+      cache_ptr->symbol.flags = BSF_WEAK;
+      break;
     }
-  if (cache_ptr->symbol.section == 0)
-    abort ();
+
   return true;
 }
 
+/* Set the fields of SYM_POINTER according to CACHE_PTR.  */
 
 static boolean
-translate_to_native_sym_flags (sym_pointer, cache_ptr, abfd)
-     struct external_nlist *sym_pointer;
-     asymbol *cache_ptr;
+translate_to_native_sym_flags (abfd, cache_ptr, sym_pointer)
      bfd *abfd;
+     asymbol *cache_ptr;
+     struct external_nlist *sym_pointer;
 {
   bfd_vma value = cache_ptr->value;
 
-  /* mask out any existing type bits in case copying from one section
-     to another */
+  /* Mask out any existing type bits in case copying from one section
+     to another */
   sym_pointer->e_type[0] &= ~N_TYPE;
 
-  /* We attempt to order these tests by decreasing frequency of success,
-     according to tcov when linking the linker.  */
-  if (bfd_get_output_section(cache_ptr) == &bfd_abs_section) {
+  if (bfd_get_section (cache_ptr) == &bfd_abs_section)
     sym_pointer->e_type[0] |= N_ABS;
-  }
-  else if (bfd_get_output_section(cache_ptr) == obj_textsec (abfd)) {
+  else if (bfd_get_section (cache_ptr) == obj_textsec (abfd))
     sym_pointer->e_type[0] |= N_TEXT;
-  }
-  else if (bfd_get_output_section(cache_ptr) == obj_datasec (abfd)) {
+  else if (bfd_get_section (cache_ptr) == obj_datasec (abfd))
     sym_pointer->e_type[0] |= N_DATA;
-  }
-  else if (bfd_get_output_section(cache_ptr) == obj_bsssec (abfd)) {
+  else if (bfd_get_section (cache_ptr) == obj_bsssec (abfd))
     sym_pointer->e_type[0] |= N_BSS;
-  }
-  else if (bfd_get_output_section(cache_ptr) == &bfd_und_section) {
-    sym_pointer->e_type[0] = (N_UNDF | N_EXT);
-  }
-  else if (bfd_get_output_section(cache_ptr) == &bfd_ind_section) {
+  else if (bfd_get_section (cache_ptr) == &bfd_und_section)
+    sym_pointer->e_type[0] = N_UNDF | N_EXT;
+  else if (bfd_get_section (cache_ptr) == &bfd_ind_section)
     sym_pointer->e_type[0] = N_INDR;
-  }
-  else if (bfd_get_output_section(cache_ptr) == NULL) {
-    /* Protect the bfd_is_com_section call.
-       This case occurs, e.g., for the *DEBUG* section of a COFF file.  */
-    bfd_set_error (bfd_error_nonrepresentable_section);
-    return false;
-  }
-  else if (bfd_is_com_section (bfd_get_output_section (cache_ptr))) {
-    sym_pointer->e_type[0] = (N_UNDF | N_EXT);
-  }
-  else {
-    bfd_set_error (bfd_error_nonrepresentable_section);
-    return false;
-  }
+  else if (bfd_get_section (cache_ptr) == NULL)
+    {
+      /* Protect the bfd_is_com_section call.  This case occurs, e.g.,
+        for the *DEBUG* section of a COFF file.  */
+      bfd_set_error (bfd_error_nonrepresentable_section);
+      return false;
+    }
+  else if (bfd_is_com_section (bfd_get_section (cache_ptr)))
+    sym_pointer->e_type[0] = N_UNDF | N_EXT;
+  else
+    {
+      bfd_set_error (bfd_error_nonrepresentable_section);
+      return false;
+    }
 
   /* Turn the symbol from section relative to absolute again */
+  value += cache_ptr->section->vma;
 
-  value +=  cache_ptr->section->output_section->vma  + cache_ptr->section->output_offset ;
-
-
-  if (cache_ptr->flags & (BSF_WARNING)) {
+  if ((cache_ptr->flags & BSF_WARNING) != 0)
     sym_pointer->e_type[0] = N_WARNING;
-  }
 
-  if (cache_ptr->flags & BSF_DEBUGGING) {
-    sym_pointer->e_type[0] = ((aout_symbol_type *)cache_ptr)->type;
-  }
-  else if (cache_ptr->flags & (BSF_GLOBAL | BSF_EXPORT)) {
+  if ((cache_ptr->flags & BSF_DEBUGGING) != 0)
+    sym_pointer->e_type[0] = ((aout_symbol_type *) cache_ptr)->type;
+  else if ((cache_ptr->flags & BSF_GLOBAL) != 0)
     sym_pointer->e_type[0] |= N_EXT;
-  }
-  if (cache_ptr->flags & BSF_CONSTRUCTOR) {
-    int type = ((aout_symbol_type *)cache_ptr)->type;
-    switch (type)
-      {
-      case N_ABS:      type = N_SETA; break;
-      case N_TEXT:     type = N_SETT; break;
-      case N_DATA:     type = N_SETD; break;
-      case N_BSS:      type = N_SETB; break;
-      }
-    sym_pointer->e_type[0] = type;
-  }
+
+  if ((cache_ptr->flags & BSF_CONSTRUCTOR) != 0)
+    {
+      int type = ((aout_symbol_type *) cache_ptr)->type;
+      switch (type)
+       {
+       case N_ABS:     type = N_SETA; break;
+       case N_TEXT:    type = N_SETT; break;
+       case N_DATA:    type = N_SETD; break;
+       case N_BSS:     type = N_SETB; break;
+       }
+      sym_pointer->e_type[0] = type;
+    }
+
+  if ((cache_ptr->flags & BSF_WEAK) != 0)
+    {
+      int type;
+
+      switch (sym_pointer->e_type[0] & N_TYPE)
+       {
+       default:
+       case N_ABS:     type = N_WEAKA; break;
+       case N_TEXT:    type = N_WEAKT; break;
+       case N_DATA:    type = N_WEAKD; break;
+       case N_BSS:     type = N_WEAKB; break;
+       case N_UNDF:    type = N_WEAKU; break;
+       }
+      sym_pointer->e_type[0] = type;
+    }
 
   PUT_WORD(abfd, value, sym_pointer->e_value);
 
@@ -1478,7 +1486,6 @@ translate_to_native_sym_flags (sym_pointer, cache_ptr, abfd)
 \f
 /* Native-level interface to symbols. */
 
-
 asymbol *
 NAME(aout,make_empty_symbol) (abfd)
      bfd *abfd;
@@ -1535,7 +1542,7 @@ NAME(aout,translate_symbol_table) (abfd, in, ext, count, str, strsize, dynamic)
       in->type = bfd_h_get_8 (abfd,  ext->e_type);
       in->symbol.udata = 0;
 
-      if (!translate_from_native_sym_flags (ext, in, abfd))
+      if (! translate_from_native_sym_flags (abfd, in))
        return false;
 
       if (dynamic)
@@ -2045,7 +2052,7 @@ NAME(aout,write_syms) (abfd)
          bfd_h_put_8(abfd, 0, nsp.e_type);
        }
 
-      if (! translate_to_native_sym_flags (&nsp, g, abfd))
+      if (! translate_to_native_sym_flags (abfd, g, &nsp))
        return false;
 
       if (bfd_write((PTR)&nsp,1,EXTERNAL_NLIST_SIZE, abfd)
@@ -3030,8 +3037,14 @@ aout_link_check_ar_symbols (abfd, info, pneeded)
       const char *name;
       struct bfd_link_hash_entry *h;
 
-      /* Ignore symbols that are not externally visible.  */
-      if ((type & N_EXT) == 0)
+      /* Ignore symbols that are not externally visible.  This is an
+        optimization only, as we check the type more thoroughly
+        below.  */
+      if ((type & N_EXT) == 0
+         && type != N_WEAKA
+         && type != N_WEAKT
+         && type != N_WEAKD
+         && type != N_WEAKB)
        {
          if (type == N_WARNING
              || type == N_INDR)
@@ -3123,6 +3136,23 @@ aout_link_check_ar_symbols (abfd, info, pneeded)
                }
            }
        }
+
+      if (type == N_WEAKA
+         || type == N_WEAKT
+         || type == N_WEAKD
+         || type == N_WEAKB)
+       {
+         /* This symbol is weak but defined.  We must pull it in if
+            the current link symbol is undefined, but we don't want
+            it if the current link symbol is common.  */
+         if (h->type == bfd_link_hash_undefined)
+           {
+             if (! (*info->callbacks->add_archive_element) (info, abfd, name))
+               return false;
+             *pneeded = true;
+             return true;
+           }
+       }
     }
 
   /* We do not need this object file.  */
@@ -3200,29 +3230,6 @@ aout_link_add_symbols (abfd, info)
       if ((type & N_STAB) != 0)
        continue;
 
-      /* Ignore symbols that are not external.  */
-      if ((type & N_EXT) == 0
-         && type != N_WARNING
-         && type != N_SETA
-         && type != N_SETT
-         && type != N_SETD
-         && type != N_SETB)
-       {
-         /* If this is an N_INDR symbol we must skip the next entry,
-            which is the symbol to indirect to (actually, an N_INDR
-            symbol without N_EXT set is pretty useless).  */
-         if (type == N_INDR)
-           {
-             ++p;
-             ++sym_hash;
-           }
-         continue;
-       }
-
-      /* Ignore N_FN symbols (these appear to have N_EXT set).  */
-      if (type == N_FN)
-       continue;
-
       name = strings + GET_WORD (abfd, p->e_strx);
       value = GET_WORD (abfd, p->e_value);
       flags = BSF_GLOBAL;
@@ -3231,11 +3238,32 @@ aout_link_add_symbols (abfd, info)
        {
        default:
          abort ();
+
+       case N_UNDF:
+       case N_ABS:
+       case N_TEXT:
+       case N_DATA:
+       case N_BSS:
+       case N_FN_SEQ:
+       case N_COMM:
+       case N_SETV:
+       case N_FN:
+         /* Ignore symbols that are not externally visible.  */
+         continue;
+       case N_INDR:
+         /* Ignore local indirect symbol.  */
+         ++p;
+         ++sym_hash;
+         continue;
+
        case N_UNDF | N_EXT:
-         if (value != 0)
-           section = &bfd_com_section;
+         if (value == 0)
+           {
+             section = &bfd_und_section;
+             flags = 0;
+           }
          else
-           section = &bfd_und_section;
+           section = &bfd_com_section;
          break;
        case N_ABS | N_EXT:
          section = &bfd_abs_section;
@@ -3293,6 +3321,29 @@ aout_link_add_symbols (abfd, info)
          section = &bfd_und_section;
          flags |= BSF_WARNING;
          break;
+       case N_WEAKU:
+         section = &bfd_und_section;
+         flags = BSF_WEAK;
+         break;
+       case N_WEAKA:
+         section = &bfd_abs_section;
+         flags = BSF_WEAK;
+         break;
+       case N_WEAKT:
+         section = obj_textsec (abfd);
+         value -= bfd_get_section_vma (abfd, section);
+         flags = BSF_WEAK;
+         break;
+       case N_WEAKD:
+         section = obj_datasec (abfd);
+         value -= bfd_get_section_vma (abfd, section);
+         flags = BSF_WEAK;
+         break;
+       case N_WEAKB:
+         section = obj_bsssec (abfd);
+         value -= bfd_get_section_vma (abfd, section);
+         flags = BSF_WEAK;
+         break;
        }
 
       if (! ((*add_one_symbol)
@@ -3777,13 +3828,17 @@ aout_link_write_symbols (finfo, input_bfd, symbol_map)
            }
 
          /* Get the value of the symbol.  */
-         if ((type & N_TYPE) == N_TEXT)
+         if ((type & N_TYPE) == N_TEXT
+             || type == N_WEAKT)
            symsec = obj_textsec (input_bfd);
-         else if ((type & N_TYPE) == N_DATA)
+         else if ((type & N_TYPE) == N_DATA
+                  || type == N_WEAKD)
            symsec = obj_datasec (input_bfd);
-         else if ((type & N_TYPE) == N_BSS)
+         else if ((type & N_TYPE) == N_BSS
+                  || type == N_WEAKB)
            symsec = obj_bsssec (input_bfd);
-         else if ((type & N_TYPE) == N_ABS)
+         else if ((type & N_TYPE) == N_ABS
+                  || type == N_WEAKA)
            symsec = &bfd_abs_section;
          else if (((type & N_TYPE) == N_INDR
                    && (hresolve == (struct aout_link_hash_entry *) NULL
@@ -3856,6 +3911,11 @@ aout_link_write_symbols (finfo, input_bfd, symbol_map)
                }
              else if (hresolve->root.type == bfd_link_hash_common)
                val = hresolve->root.u.c.size;
+             else if (hresolve->root.type == bfd_link_hash_weak)
+               {
+                 val = 0;
+                 type = N_WEAKU;
+               }
              else
                val = 0;
 
@@ -4027,6 +4087,9 @@ aout_link_write_other_symbol (h, data)
       type = N_UNDF | N_EXT;
       val = h->root.u.c.size;
       break;
+    case bfd_link_hash_weak:
+      type = N_WEAKU;
+      val = 0;
     case bfd_link_hash_indirect:
     case bfd_link_hash_warning:
       /* FIXME: Ignore these for now.  The circumstances under which
@@ -4408,6 +4471,9 @@ aout_link_input_section_std (finfo, input_bfd, input_section, relocs,
                                + h->root.u.def.section->output_section->vma
                                + h->root.u.def.section->output_offset);
                }
+             else if (h != (struct aout_link_hash_entry *) NULL
+                      && h->root.type == bfd_link_hash_weak)
+               relocation = 0;
              else
                {
                  const char *name;
@@ -4702,6 +4768,9 @@ aout_link_input_section_ext (finfo, input_bfd, input_section, relocs,
                                + h->root.u.def.section->output_section->vma
                                + h->root.u.def.section->output_offset);
                }
+             else if (h != (struct aout_link_hash_entry *) NULL
+                      && h->root.type == bfd_link_hash_weak)
+               relocation = 0;
              else
                {
                  const char *name;
index 9740cdd..0ebc9ad 100644 (file)
@@ -1513,7 +1513,7 @@ sunos_scan_dynamic_symbol (h, data)
      which are referenced by a regular object and defined by a dynamic
      object do not seem to show up in the regular symbol table.  */
   if ((h->flags & SUNOS_DEF_REGULAR) == 0)
-    h->root.root.written = true;
+    h->root.written = true;
 
   /* If this symbol is defined by a dynamic object and referenced by a
      regular object, see whether we gave it a reasonable value while
@@ -1695,6 +1695,10 @@ sunos_write_dynamic_symbol (output_bfd, info, harg)
       type = N_UNDF | N_EXT;
       val = h->root.root.u.c.size;
       break;
+    case bfd_link_hash_weak:
+      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