Add -Wshadow to the gcc command line options used when compiling the binutils.
[deliverable/binutils-gdb.git] / gas / symbols.c
index c9298e044cb4b5a6f82ef3c4c2c3b66f0fa9c093..9202a9b315ab0dcf921a3af8040aa90ac476d997 100644 (file)
@@ -1,13 +1,13 @@
 /* symbols.c -symbol table-
    Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GAS is distributed in the hope that it will be useful,
@@ -59,7 +59,7 @@ symbolS abs_symbol;
 #define LOCAL_LABEL_CHAR       '\002'
 
 struct obstack notes;
-#ifdef USE_UNIQUE
+#ifdef TE_PE
 /* The name of an external symbol which is
    used to make weak PE symbol names unique.  */
 const char * an_external_name;
@@ -109,7 +109,7 @@ save_symbol_name (const char *name)
 
   name_length = strlen (name) + 1;     /* +1 for \0.  */
   obstack_grow (&notes, name, name_length);
-  ret = obstack_finish (&notes);
+  ret = (char *) obstack_finish (&notes);
 
 #ifdef tc_canonicalize_symbol_name
   ret = tc_canonicalize_symbol_name (ret);
@@ -144,8 +144,7 @@ symbol_create (const char *name, /* It is copied, the caller can destroy/modify.
 
   symbolP->bsym = bfd_make_empty_symbol (stdoutput);
   if (symbolP->bsym == NULL)
-    as_perror ("%s", "bfd_make_empty_symbol");
-  symbolP->bsym->udata.p = (PTR) symbolP;
+    as_fatal ("bfd_make_empty_symbol: %s", bfd_errmsg (bfd_get_error ()));
   S_SET_NAME (symbolP, preserved_copy_of_name);
 
   S_SET_SEGMENT (symbolP, segment);
@@ -189,7 +188,7 @@ static unsigned long local_symbol_conversion_count;
 /* Create a local symbol and insert it into the local hash table.  */
 
 static struct local_symbol *
-local_symbol_make (const char *name, segT section, valueT value, fragS *frag)
+local_symbol_make (const char *name, segT section, valueT val, fragS *frag)
 {
   char *name_copy;
   struct local_symbol *ret;
@@ -203,9 +202,9 @@ local_symbol_make (const char *name, segT section, valueT value, fragS *frag)
   ret->lsy_name = name_copy;
   ret->lsy_section = section;
   local_symbol_set_frag (ret, frag);
-  ret->lsy_value = value;
+  ret->lsy_value = val;
 
-  hash_jam (local_hash, name_copy, (PTR) ret);
+  hash_jam (local_hash, name_copy, (void *) ret);
 
   return ret;
 }
@@ -218,7 +217,7 @@ local_symbol_convert (struct local_symbol *locsym)
 {
   symbolS *ret;
 
-  assert (locsym->lsy_marker == NULL);
+  gas_assert (locsym->lsy_marker == NULL);
   if (local_symbol_converted_p (locsym))
     return local_symbol_get_real_symbol (locsym);
 
@@ -247,6 +246,17 @@ local_symbol_convert (struct local_symbol *locsym)
   return ret;
 }
 \f
+static void
+define_sym_at_dot (symbolS *symbolP)
+{
+  symbolP->sy_frag = frag_now;
+#ifdef OBJ_VMS
+  S_SET_OTHER (symbolP, const_flag);
+#endif
+  S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
+  S_SET_SEGMENT (symbolP, now_seg);
+}
+
 /* We have just seen "<name>:".
    Creates a struct symbol unless it already exists.
 
@@ -336,10 +346,7 @@ colon (/* Just seen "x:" - rattle symbols & frags.  */
               || S_IS_COMMON (symbolP)
               || S_IS_VOLATILE (symbolP))
        {
-         if (S_IS_VOLATILE (symbolP)
-             /* This could be avoided when the symbol wasn't used so far, but
-                the comment in struc-symbol.h says this flag isn't reliable.  */
-             && (1 || !symbol_used_p (symbolP)))
+         if (S_IS_VOLATILE (symbolP))
            {
              symbolP = symbol_clone (symbolP, 1);
              S_SET_VALUE (symbolP, 0);
@@ -347,12 +354,7 @@ colon (/* Just seen "x:" - rattle symbols & frags.  */
            }
          if (S_GET_VALUE (symbolP) == 0)
            {
-             symbolP->sy_frag = frag_now;
-#ifdef OBJ_VMS
-             S_SET_OTHER (symbolP, const_flag);
-#endif
-             S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
-             S_SET_SEGMENT (symbolP, now_seg);
+             define_sym_at_dot (symbolP);
 #ifdef N_UNDF
              know (N_UNDF == 0);
 #endif /* if we have one, it better be zero.  */
@@ -397,12 +399,7 @@ colon (/* Just seen "x:" - rattle symbols & frags.  */
                    {
                      /* It is a .comm/.lcomm being converted to initialized
                         data.  */
-                     symbolP->sy_frag = frag_now;
-#ifdef OBJ_VMS
-                     S_SET_OTHER (symbolP, const_flag);
-#endif
-                     S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
-                     S_SET_SEGMENT (symbolP, now_seg); /* Keep N_EXT bit.  */
+                     define_sym_at_dot (symbolP);
                    }
                }
              else
@@ -435,6 +432,7 @@ colon (/* Just seen "x:" - rattle symbols & frags.  */
            {
              as_bad (_("symbol `%s' is already defined"), sym_name);
              symbolP = symbol_clone (symbolP, 0);
+             define_sym_at_dot (symbolP);
            }
        }
 
@@ -493,14 +491,14 @@ symbol_table_insert (symbolS *symbolP)
   if (LOCAL_SYMBOL_CHECK (symbolP))
     {
       error_string = hash_jam (local_hash, S_GET_NAME (symbolP),
-                              (PTR) symbolP);
+                              (void *) symbolP);
       if (error_string != NULL)
        as_fatal (_("inserting \"%s\" into symbol table failed: %s"),
                  S_GET_NAME (symbolP), error_string);
       return;
     }
 
-  if ((error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (PTR) symbolP)))
+  if ((error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (void *) symbolP)))
     {
       as_fatal (_("inserting \"%s\" into symbol table failed: %s"),
                S_GET_NAME (symbolP), error_string);
@@ -567,18 +565,15 @@ symbol_clone (symbolS *orgsymP, int replace)
     orgsymP = local_symbol_convert ((struct local_symbol *) orgsymP);
   bsymorg = orgsymP->bsym;
 
-  know (S_IS_DEFINED (orgsymP));
-
-  newsymP = obstack_alloc (&notes, sizeof (*newsymP));
+  newsymP = (symbolS *) obstack_alloc (&notes, sizeof (*newsymP));
   *newsymP = *orgsymP;
   bsymnew = bfd_make_empty_symbol (bfd_asymbol_bfd (bsymorg));
   if (bsymnew == NULL)
-    as_perror ("%s", "bfd_make_empty_symbol");
+    as_fatal ("bfd_make_empty_symbol: %s", bfd_errmsg (bfd_get_error ()));
   newsymP->bsym = bsymnew;
   bsymnew->name = bsymorg->name;
   bsymnew->flags =  bsymorg->flags;
   bsymnew->section =  bsymorg->section;
-  bsymnew->udata.p = (PTR) newsymP;
   bfd_copy_private_symbol_data (bfd_asymbol_bfd (bsymorg), bsymorg,
                                bfd_asymbol_bfd (bsymnew), bsymnew);
 
@@ -603,11 +598,20 @@ symbol_clone (symbolS *orgsymP, int replace)
        symbol_lastP = newsymP;
       else if (orgsymP->sy_next)
        orgsymP->sy_next->sy_previous = newsymP;
-      orgsymP->sy_next = NULL;
+
+      /* Symbols that won't be output can't be external.  */
+      S_CLEAR_EXTERNAL (orgsymP);
+      orgsymP->sy_previous = orgsymP->sy_next = orgsymP;
       debug_verify_symchain (symbol_rootP, symbol_lastP);
 
       symbol_table_insert (newsymP);
     }
+  else
+    {
+      /* Symbols that won't be output can't be external.  */
+      S_CLEAR_EXTERNAL (newsymP);
+      newsymP->sy_previous = newsymP->sy_next = newsymP;
+    }
 
   return newsymP;
 }
@@ -877,12 +881,75 @@ verify_symbol_chain (symbolS *rootP, symbolS *lastP)
 
   for (; symbol_next (symbolP) != NULL; symbolP = symbol_next (symbolP))
     {
-      assert (symbolP->bsym != NULL);
-      assert (symbolP->sy_next->sy_previous == symbolP);
+      gas_assert (symbolP->bsym != NULL);
+      gas_assert (symbolP->sy_next->sy_previous == symbolP);
     }
 
-  assert (lastP == symbolP);
+  gas_assert (lastP == symbolP);
+}
+
+#ifdef OBJ_COMPLEX_RELC
+
+static int
+use_complex_relocs_for (symbolS * symp)
+{
+  switch (symp->sy_value.X_op)
+    {
+    case O_constant:
+      return 0;
+
+    case O_symbol:
+    case O_symbol_rva:
+    case O_uminus:
+    case O_bit_not:
+    case O_logical_not:
+      if (  (S_IS_COMMON (symp->sy_value.X_add_symbol)
+          || S_IS_LOCAL (symp->sy_value.X_add_symbol))
+         &&
+             (S_IS_DEFINED (symp->sy_value.X_add_symbol)
+          && S_GET_SEGMENT (symp->sy_value.X_add_symbol) != expr_section))
+       return 0;
+      break;
+
+    case O_multiply:
+    case O_divide:
+    case O_modulus:
+    case O_left_shift:
+    case O_right_shift:
+    case O_bit_inclusive_or:
+    case O_bit_or_not:
+    case O_bit_exclusive_or:
+    case O_bit_and:
+    case O_add:
+    case O_subtract:
+    case O_eq:
+    case O_ne:
+    case O_lt:
+    case O_le:
+    case O_ge:
+    case O_gt:
+    case O_logical_and:
+    case O_logical_or:
+
+      if (  (S_IS_COMMON (symp->sy_value.X_add_symbol)
+          || S_IS_LOCAL (symp->sy_value.X_add_symbol))
+         && 
+           (S_IS_COMMON (symp->sy_value.X_op_symbol)
+          || S_IS_LOCAL (symp->sy_value.X_op_symbol))
+
+         && S_IS_DEFINED (symp->sy_value.X_add_symbol)
+         && S_IS_DEFINED (symp->sy_value.X_op_symbol)
+         && S_GET_SEGMENT (symp->sy_value.X_add_symbol) != expr_section
+         && S_GET_SEGMENT (symp->sy_value.X_op_symbol) != expr_section)
+       return 0;
+      break;
+      
+    default:
+      break;
+    }
+  return 1;
 }
+#endif
 
 static void
 report_op_error (symbolS *symp, symbolS *left, symbolS *right)
@@ -928,13 +995,11 @@ report_op_error (symbolS *symp, symbolS *left, symbolS *right)
          && seg_right != undefined_section)
        {
          if (right)
-           as_bad_where (file, line,
-                         _("invalid sections for operation on `%s' and `%s' setting `%s'"),
-                         S_GET_NAME (left), S_GET_NAME (right), S_GET_NAME (symp));
+           as_bad (_("invalid sections for operation on `%s' and `%s' setting `%s'"),
+                   S_GET_NAME (left), S_GET_NAME (right), S_GET_NAME (symp));
          else
-           as_bad_where (file, line,
-                         _("invalid section for operation on `%s' setting `%s'"),
-                         S_GET_NAME (left), S_GET_NAME (symp));
+           as_bad (_("invalid section for operation on `%s' setting `%s'"),
+                   S_GET_NAME (left), S_GET_NAME (symp));
        }
     }
 }
@@ -988,6 +1053,53 @@ resolve_symbol_value (symbolS *symp)
       final_val = 0;
       resolved = 1;
     }
+#ifdef OBJ_COMPLEX_RELC
+  else if (final_seg == expr_section
+          && use_complex_relocs_for (symp))
+    {
+      symbolS * relc_symbol = NULL;
+      char * relc_symbol_name = NULL;
+
+      relc_symbol_name = symbol_relc_make_expr (& symp->sy_value);
+
+      /* For debugging, print out conversion input & output.  */
+#ifdef DEBUG_SYMS
+      print_expr (& symp->sy_value);
+      if (relc_symbol_name)
+       fprintf (stderr, "-> relc symbol: %s\n", relc_symbol_name);
+#endif
+
+      if (relc_symbol_name != NULL)
+       relc_symbol = symbol_new (relc_symbol_name, undefined_section,
+                                 0, & zero_address_frag);
+
+      if (relc_symbol == NULL)
+       {
+         as_bad (_("cannot convert expression symbol %s to complex relocation"),
+                 S_GET_NAME (symp));
+         resolved = 0;
+       }
+      else
+       {
+         symbol_table_insert (relc_symbol);
+
+         /* S_CLEAR_EXTERNAL (relc_symbol); */
+         if (symp->bsym->flags & BSF_SRELC)
+           relc_symbol->bsym->flags |= BSF_SRELC;
+         else
+           relc_symbol->bsym->flags |= BSF_RELC;         
+         /* symp->bsym->flags |= BSF_RELC; */
+         copy_symbol_attributes (symp, relc_symbol);
+         symp->sy_value.X_op = O_symbol;
+         symp->sy_value.X_add_symbol = relc_symbol;
+         symp->sy_value.X_add_number = 0;
+         resolved = 1;
+       }
+
+      final_seg = undefined_section;
+      goto exit_dont_set_value;
+    }
+#endif
   else
     {
       symbolS *add_symbol, *op_symbol;
@@ -1018,6 +1130,9 @@ resolve_symbol_value (symbolS *symp)
          final_val += symp->sy_frag->fr_address / OCTETS_PER_BYTE;
          if (final_seg == expr_section)
            final_seg = absolute_section;
+         /* Fall through.  */
+
+       case O_register:
          resolved = 1;
          break;
 
@@ -1031,13 +1146,13 @@ resolve_symbol_value (symbolS *symp)
        do_symbol:
          if (S_IS_WEAKREFR (symp))
            {
-             assert (final_val == 0);
+             gas_assert (final_val == 0);
              if (S_IS_WEAKREFR (add_symbol))
                {
-                 assert (add_symbol->sy_value.X_op == O_symbol
+                 gas_assert (add_symbol->sy_value.X_op == O_symbol
                          && add_symbol->sy_value.X_add_number == 0);
                  add_symbol = add_symbol->sy_value.X_add_symbol;
-                 assert (! S_IS_WEAKREFR (add_symbol));
+                 gas_assert (! S_IS_WEAKREFR (add_symbol));
                  symp->sy_value.X_add_symbol = add_symbol;
                }
            }
@@ -1085,8 +1200,9 @@ resolve_symbol_value (symbolS *symp)
              symp->sy_resolving = 0;
              goto exit_dont_set_value;
            }
-         else if (finalize_syms && final_seg == expr_section
-                  && seg_left != expr_section)
+         else if (finalize_syms
+                  && ((final_seg == expr_section && seg_left != expr_section)
+                      || symbol_shadow_p (symp)))
            {
              /* If the symbol is an expression symbol, do similarly
                 as for undefined and common syms above.  Handles
@@ -1294,7 +1410,6 @@ resolve_symbol_value (symbolS *symp)
                      && symbol_resolved_p (op_symbol));
          break;
 
-       case O_register:
        case O_big:
        case O_illegal:
          /* Give an error (below) if not in expr_section.  We don't
@@ -1332,15 +1447,15 @@ exit_dont_set_value:
   return final_val;
 }
 
-static void resolve_local_symbol (const char *, PTR);
+static void resolve_local_symbol (const char *, void *);
 
 /* A static function passed to hash_traverse.  */
 
 static void
-resolve_local_symbol (const char *key ATTRIBUTE_UNUSED, PTR value)
+resolve_local_symbol (const char *key ATTRIBUTE_UNUSED, void *value)
 {
   if (value != NULL)
-    resolve_symbol_value (value);
+    resolve_symbol_value ((symbolS *) value);
 }
 
 /* Resolve all local symbols.  */
@@ -1369,21 +1484,21 @@ snapshot_symbol (symbolS **symbolPP, valueT *valueP, segT *segP, fragS **fragPP)
     }
   else
     {
-      expressionS expr = symbolP->sy_value;
+      expressionS exp = symbolP->sy_value;
 
-      if (!symbolP->sy_resolved && expr.X_op != O_illegal)
+      if (!symbolP->sy_resolved && exp.X_op != O_illegal)
        {
          int resolved;
 
          if (symbolP->sy_resolving)
            return 0;
          symbolP->sy_resolving = 1;
-         resolved = resolve_expression (&expr);
+         resolved = resolve_expression (&exp);
          symbolP->sy_resolving = 0;
          if (!resolved)
            return 0;
 
-         switch (expr.X_op)
+         switch (exp.X_op)
            {
            case O_constant:
            case O_register:
@@ -1392,7 +1507,7 @@ snapshot_symbol (symbolS **symbolPP, valueT *valueP, segT *segP, fragS **fragPP)
              /* Fall thru.  */
            case O_symbol:
            case O_symbol_rva:
-             symbolP = expr.X_add_symbol;
+             symbolP = exp.X_add_symbol;
              break;
            default:
              return 0;
@@ -1400,12 +1515,12 @@ snapshot_symbol (symbolS **symbolPP, valueT *valueP, segT *segP, fragS **fragPP)
        }
 
       *symbolPP = symbolP;
-      *valueP = expr.X_add_number;
+      *valueP = exp.X_add_number;
       *segP = symbolP->bsym->section;
       *fragPP = symbolP->sy_frag;
 
       if (*segP == expr_section)
-       switch (expr.X_op)
+       switch (exp.X_op)
          {
          case O_constant: *segP = absolute_section; break;
          case O_register: *segP = reg_section; break;
@@ -1487,7 +1602,7 @@ define_dollar_label (long label)
     {
       dollar_labels = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
       dollar_label_instances = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
-      dollar_label_defines = xmalloc (DOLLAR_LABEL_BUMP_BY);
+      dollar_label_defines = (char *) xmalloc (DOLLAR_LABEL_BUMP_BY);
       dollar_label_max = DOLLAR_LABEL_BUMP_BY;
       dollar_label_count = 0;
     }
@@ -1498,7 +1613,7 @@ define_dollar_label (long label)
                                         dollar_label_max * sizeof (long));
       dollar_label_instances = (long *) xrealloc ((char *) dollar_label_instances,
                                          dollar_label_max * sizeof (long));
-      dollar_label_defines = xrealloc (dollar_label_defines, dollar_label_max);
+      dollar_label_defines = (char *) xrealloc (dollar_label_defines, dollar_label_max);
     }                          /* if we needed to grow  */
 
   dollar_labels[dollar_label_count] = label;
@@ -1747,17 +1862,17 @@ decode_local_label_name (char *s)
   int instance_number;
   char *type;
   const char *message_format;
-  int index = 0;
+  int lindex = 0;
 
 #ifdef LOCAL_LABEL_PREFIX
-  if (s[index] == LOCAL_LABEL_PREFIX)
-    ++index;
+  if (s[lindex] == LOCAL_LABEL_PREFIX)
+    ++lindex;
 #endif
 
-  if (s[index] != 'L')
+  if (s[lindex] != 'L')
     return s;
 
-  for (label_number = 0, p = s + index + 1; ISDIGIT (*p); ++p)
+  for (label_number = 0, p = s + lindex + 1; ISDIGIT (*p); ++p)
     label_number = (10 * label_number) + *p - '0';
 
   if (*p == DOLLAR_LABEL_CHAR)
@@ -1771,7 +1886,7 @@ decode_local_label_name (char *s)
     instance_number = (10 * instance_number) + *p - '0';
 
   message_format = _("\"%d\" (instance number %d of a %s label)");
-  symbol_decode = obstack_alloc (&notes, strlen (message_format) + 30);
+  symbol_decode = (char *) obstack_alloc (&notes, strlen (message_format) + 30);
   sprintf (symbol_decode, message_format, label_number, instance_number, type);
 
   return symbol_decode;
@@ -1832,12 +1947,17 @@ copy_symbol_attributes (symbolS *dest, symbolS *src)
 
   /* In an expression, transfer the settings of these flags.
      The user can override later, of course.  */
-#define COPIED_SYMFLAGS        (BSF_FUNCTION | BSF_OBJECT)
+#define COPIED_SYMFLAGS        (BSF_FUNCTION | BSF_OBJECT \
+                        | BSF_GNU_INDIRECT_FUNCTION)
   dest->bsym->flags |= src->bsym->flags & COPIED_SYMFLAGS;
 
 #ifdef OBJ_COPY_SYMBOL_ATTRIBUTES
   OBJ_COPY_SYMBOL_ATTRIBUTES (dest, src);
 #endif
+
+#ifdef TC_COPY_SYMBOL_ATTRIBUTES
+  TC_COPY_SYMBOL_ATTRIBUTES (dest, src);
+#endif
 }
 
 int
@@ -1932,6 +2052,7 @@ S_FORCE_RELOC (symbolS *s, int strict)
 
   return ((strict
           && ((s->bsym->flags & BSF_WEAK) != 0
+              || (s->bsym->flags & BSF_GNU_INDIRECT_FUNCTION) != 0
               || (EXTERN_FORCE_RELOC
                   && (s->bsym->flags & BSF_GLOBAL) != 0)))
          || s->bsym->section == undefined_section
@@ -2071,10 +2192,18 @@ S_SET_EXTERNAL (symbolS *s)
                     _("section symbols are already global"));
       return;
     }
+#ifndef TC_GLOBAL_REGISTER_SYMBOL_OK
+  if (S_GET_SEGMENT (s) == reg_section)
+    {
+      as_bad ("can't make register symbol `%s' global",
+             S_GET_NAME (s));
+      return;
+    }
+#endif
   s->bsym->flags |= BSF_GLOBAL;
   s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK);
 
-#ifdef USE_UNIQUE
+#ifdef TE_PE
   if (! an_external_name && S_GET_NAME(s)[0] != '.')
     an_external_name = S_GET_NAME (s);
 #endif
@@ -2256,6 +2385,20 @@ symbol_set_value_expression (symbolS *s, const expressionS *exp)
   S_CLEAR_WEAKREFR (s);
 }
 
+/* Return whether 2 symbols are the same.  */
+
+int
+symbol_same_p (symbolS *s1, symbolS *s2)
+{
+  if (s1->bsym == NULL
+      && local_symbol_converted_p ((struct local_symbol *) s1))
+    s1 = local_symbol_get_real_symbol ((struct local_symbol *) s1);
+  if (s2->bsym == NULL
+      && local_symbol_converted_p ((struct local_symbol *) s2))
+    s2 = local_symbol_get_real_symbol ((struct local_symbol *) s2);
+  return s1 == s2;
+}
+
 /* Return a pointer to the X_add_number component of a symbol.  */
 
 offsetT *
@@ -2496,6 +2639,17 @@ symbol_constant_p (symbolS *s)
   return s->sy_value.X_op == O_constant;
 }
 
+/* Return whether a symbol was cloned and thus removed from the global
+   symbol list.  */
+
+int
+symbol_shadow_p (symbolS *s)
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    return 0;
+  return s->sy_next == s;
+}
+
 /* Return the BFD symbol for a symbol.  */
 
 asymbol *
@@ -2604,14 +2758,20 @@ print_symbol_value_1 (FILE *file, symbolS *sym)
   const char *name = S_GET_NAME (sym);
   if (!name || !name[0])
     name = "(unnamed)";
-  fprintf (file, "sym %lx %s", (unsigned long) sym, name);
+  fprintf (file, "sym ");
+  fprintf_vma (file, (bfd_vma) ((bfd_hostptr_t) sym));
+  fprintf (file, " %s", name);
 
   if (LOCAL_SYMBOL_CHECK (sym))
     {
       struct local_symbol *locsym = (struct local_symbol *) sym;
-      if (local_symbol_get_frag (locsym) != &zero_address_frag
+
+      if (local_symbol_get_frag (locsym) != & zero_address_frag
          && local_symbol_get_frag (locsym) != NULL)
-       fprintf (file, " frag %lx", (long) local_symbol_get_frag (locsym));
+       {
+         fprintf (file, " frag ");
+         fprintf_vma (file, (bfd_vma) ((bfd_hostptr_t) local_symbol_get_frag (locsym)));
+        }
       if (local_symbol_resolved_p (locsym))
        fprintf (file, " resolved");
       fprintf (file, " local");
@@ -2619,7 +2779,10 @@ print_symbol_value_1 (FILE *file, symbolS *sym)
   else
     {
       if (sym->sy_frag != &zero_address_frag)
-       fprintf (file, " frag %lx", (long) sym->sy_frag);
+       {
+         fprintf (file, " frag ");
+         fprintf_vma (file, (bfd_vma) ((bfd_hostptr_t) sym->sy_frag));
+       }
       if (sym->written)
        fprintf (file, " written");
       if (sym->sy_resolved)
@@ -2652,7 +2815,7 @@ print_symbol_value_1 (FILE *file, symbolS *sym)
 
       if (s != undefined_section
          && s != expr_section)
-       fprintf (file, " %lx", (long) S_GET_VALUE (sym));
+       fprintf (file, " %lx", (unsigned long) S_GET_VALUE (sym));
     }
   else if (indent_level < max_indent_level
           && S_GET_SEGMENT (sym) != undefined_section)
@@ -2661,7 +2824,7 @@ print_symbol_value_1 (FILE *file, symbolS *sym)
       fprintf (file, "\n%*s<", indent_level * 4, "");
       if (LOCAL_SYMBOL_CHECK (sym))
        fprintf (file, "constant %lx",
-                (long) ((struct local_symbol *) sym)->lsy_value);
+                (unsigned long) ((struct local_symbol *) sym)->lsy_value);
       else
        print_expr_1 (file, &sym->sy_value);
       fprintf (file, ">");
@@ -2693,7 +2856,9 @@ print_binary (FILE *file, const char *name, expressionS *exp)
 void
 print_expr_1 (FILE *file, expressionS *exp)
 {
-  fprintf (file, "expr %lx ", (long) exp);
+  fprintf (file, "expr ");
+  fprintf_vma (file, (bfd_vma) ((bfd_hostptr_t) exp));
+  fprintf (file, " ");
   switch (exp->X_op)
     {
     case O_illegal:
@@ -2703,7 +2868,7 @@ print_expr_1 (FILE *file, expressionS *exp)
       fprintf (file, "absent");
       break;
     case O_constant:
-      fprintf (file, "constant %lx", (long) exp->X_add_number);
+      fprintf (file, "constant %lx", (unsigned long) exp->X_add_number);
       break;
     case O_symbol:
       indent_level++;
@@ -2713,7 +2878,7 @@ print_expr_1 (FILE *file, expressionS *exp)
     maybe_print_addnum:
       if (exp->X_add_number)
        fprintf (file, "\n%*s%lx", indent_level * 4, "",
-                (long) exp->X_add_number);
+                (unsigned long) exp->X_add_number);
       indent_level--;
       break;
     case O_register:
@@ -2817,3 +2982,219 @@ symbol_print_statistics (FILE *file)
   fprintf (file, "%lu mini local symbols created, %lu converted\n",
           local_symbol_count, local_symbol_conversion_count);
 }
+
+#ifdef OBJ_COMPLEX_RELC
+
+/* Convert given symbol to a new complex-relocation symbol name.  This
+   may be a recursive function, since it might be called for non-leaf
+   nodes (plain symbols) in the expression tree.  The caller owns the
+   returning string, so should free it eventually.  Errors are
+   indicated via as_bad and a NULL return value.  The given symbol
+   is marked with sy_used_in_reloc.  */
+
+char *
+symbol_relc_make_sym (symbolS * sym)
+{
+  char * terminal = NULL;
+  const char * sname;
+  char typetag;
+  int sname_len;
+
+  gas_assert (sym != NULL);
+
+  /* Recurse to symbol_relc_make_expr if this symbol
+     is defined as an expression or a plain value.  */
+  if (   S_GET_SEGMENT (sym) == expr_section
+      || S_GET_SEGMENT (sym) == absolute_section)
+    return symbol_relc_make_expr (& sym->sy_value);
+
+  /* This may be a "fake symbol" L0\001, referring to ".".
+     Write out a special null symbol to refer to this position.  */
+  if (! strcmp (S_GET_NAME (sym), FAKE_LABEL_NAME))
+    return xstrdup (".");
+
+  /* We hope this is a plain leaf symbol.  Construct the encoding
+     as {S,s}II...:CCCCCCC....
+     where 'S'/'s' means section symbol / plain symbol
+     III is decimal for the symbol name length
+     CCC is the symbol name itself.  */
+  symbol_mark_used_in_reloc (sym);
+
+  sname = S_GET_NAME (sym);
+  sname_len = strlen (sname);
+  typetag = symbol_section_p (sym) ? 'S' : 's';
+
+  terminal = xmalloc (1 /* S or s */
+                     + 8 /* sname_len in decimal */
+                     + 1 /* _ spacer */
+                     + sname_len /* name itself */
+                     + 1 /* \0 */ );
+
+  sprintf (terminal, "%c%d:%s", typetag, sname_len, sname);
+  return terminal;
+}
+
+/* Convert given value to a new complex-relocation symbol name.  This
+   is a non-recursive function, since it is be called for leaf nodes
+   (plain values) in the expression tree.  The caller owns the
+   returning string, so should free() it eventually.  No errors.  */
+
+char *
+symbol_relc_make_value (offsetT val)
+{
+  char * terminal = xmalloc (28);  /* Enough for long long.  */
+
+  terminal[0] = '#';
+  bfd_sprintf_vma (stdoutput, terminal + 1, val);
+  return terminal;
+}
+
+/* Convert given expression to a new complex-relocation symbol name.
+   This is a recursive function, since it traverses the entire given
+   expression tree.  The caller owns the returning string, so should
+   free() it eventually.  Errors are indicated via as_bad() and a NULL
+   return value.  */
+
+char *
+symbol_relc_make_expr (expressionS * exp)
+{
+  char * opstr = NULL; /* Operator prefix string.  */
+  int    arity = 0;    /* Arity of this operator.  */
+  char * operands[3];  /* Up to three operands.  */
+  char * concat_string = NULL;
+
+  operands[0] = operands[1] = operands[2] = NULL;
+
+  gas_assert (exp != NULL);
+
+  /* Match known operators -> fill in opstr, arity, operands[] and fall
+     through to construct subexpression fragments; may instead return 
+     string directly for leaf nodes.  */
+
+  /* See expr.h for the meaning of all these enums.  Many operators 
+     have an unnatural arity (X_add_number implicitly added).  The
+     conversion logic expands them to explicit "+" subexpressions.   */
+
+  switch (exp->X_op)
+    {
+    default:
+      as_bad ("Unknown expression operator (enum %d)", exp->X_op);
+      break;
+
+      /* Leaf nodes.  */
+    case O_constant:
+      return symbol_relc_make_value (exp->X_add_number);
+
+    case O_symbol:
+      if (exp->X_add_number) 
+       { 
+         arity = 2; 
+         opstr = "+"; 
+         operands[0] = symbol_relc_make_sym (exp->X_add_symbol);
+         operands[1] = symbol_relc_make_value (exp->X_add_number);
+         break;
+       }
+      else
+       return symbol_relc_make_sym (exp->X_add_symbol);
+
+      /* Helper macros for nesting nodes.  */
+
+#define HANDLE_XADD_OPT1(str_)                                                 \
+      if (exp->X_add_number)                                           \
+        {                                                              \
+          arity = 2;                                                   \
+          opstr = "+:" str_;                                           \
+          operands[0] = symbol_relc_make_sym (exp->X_add_symbol);      \
+          operands[1] = symbol_relc_make_value (exp->X_add_number);    \
+          break;                                                       \
+        }                                                              \
+      else                                                             \
+        {                                                              \
+          arity = 1;                                                   \
+          opstr = str_;                                                        \
+          operands[0] = symbol_relc_make_sym (exp->X_add_symbol);      \
+        }                                                              \
+      break
+      
+#define HANDLE_XADD_OPT2(str_)                                                 \
+      if (exp->X_add_number)                                           \
+        {                                                              \
+          arity = 3;                                                   \
+          opstr = "+:" str_;                                           \
+          operands[0] = symbol_relc_make_sym (exp->X_add_symbol);      \
+          operands[1] = symbol_relc_make_sym (exp->X_op_symbol);       \
+          operands[2] = symbol_relc_make_value (exp->X_add_number);    \
+        }                                                              \
+      else                                                             \
+        {                                                              \
+          arity = 2;                                                   \
+          opstr = str_;                                                        \
+          operands[0] = symbol_relc_make_sym (exp->X_add_symbol);      \
+          operands[1] = symbol_relc_make_sym (exp->X_op_symbol);       \
+        }                                                              \
+      break
+
+      /* Nesting nodes.  */
+
+    case O_uminus:             HANDLE_XADD_OPT1 ("0-");
+    case O_bit_not:            HANDLE_XADD_OPT1 ("~");
+    case O_logical_not:        HANDLE_XADD_OPT1 ("!");
+    case O_multiply:           HANDLE_XADD_OPT2 ("*");
+    case O_divide:             HANDLE_XADD_OPT2 ("/");
+    case O_modulus:            HANDLE_XADD_OPT2 ("%");
+    case O_left_shift:         HANDLE_XADD_OPT2 ("<<");
+    case O_right_shift:        HANDLE_XADD_OPT2 (">>");
+    case O_bit_inclusive_or:   HANDLE_XADD_OPT2 ("|");
+    case O_bit_exclusive_or:   HANDLE_XADD_OPT2 ("^");
+    case O_bit_and:            HANDLE_XADD_OPT2 ("&");
+    case O_add:                HANDLE_XADD_OPT2 ("+");
+    case O_subtract:           HANDLE_XADD_OPT2 ("-");
+    case O_eq:                 HANDLE_XADD_OPT2 ("==");
+    case O_ne:                 HANDLE_XADD_OPT2 ("!=");
+    case O_lt:                 HANDLE_XADD_OPT2 ("<");
+    case O_le:                 HANDLE_XADD_OPT2 ("<=");
+    case O_ge:                 HANDLE_XADD_OPT2 (">=");
+    case O_gt:                 HANDLE_XADD_OPT2 (">");
+    case O_logical_and:        HANDLE_XADD_OPT2 ("&&");
+    case O_logical_or:         HANDLE_XADD_OPT2 ("||");
+    }
+
+  /* Validate & reject early.  */
+  if (arity >= 1 && ((operands[0] == NULL) || (strlen (operands[0]) == 0)))
+    opstr = NULL;
+  if (arity >= 2 && ((operands[1] == NULL) || (strlen (operands[1]) == 0)))
+    opstr = NULL;
+  if (arity >= 3 && ((operands[2] == NULL) || (strlen (operands[2]) == 0)))
+    opstr = NULL;
+
+  if (opstr == NULL)
+    concat_string = NULL;
+  else
+    {
+      /* Allocate new string; include inter-operand padding gaps etc.  */
+      concat_string = xmalloc (strlen (opstr) 
+                              + 1
+                              + (arity >= 1 ? (strlen (operands[0]) + 1 ) : 0)
+                              + (arity >= 2 ? (strlen (operands[1]) + 1 ) : 0)
+                              + (arity >= 3 ? (strlen (operands[2]) + 0 ) : 0)
+                              + 1);
+      gas_assert (concat_string != NULL);
+      
+      /* Format the thing.  */
+      sprintf (concat_string, 
+              (arity == 0 ? "%s" :
+               arity == 1 ? "%s:%s" :
+               arity == 2 ? "%s:%s:%s" :
+               /* arity == 3 */ "%s:%s:%s:%s"),
+              opstr, operands[0], operands[1], operands[2]);
+    }
+
+  /* Free operand strings (not opstr).  */
+  if (arity >= 1) xfree (operands[0]);
+  if (arity >= 2) xfree (operands[1]);
+  if (arity >= 3) xfree (operands[2]);
+
+  return concat_string;
+}
+
+#endif
This page took 0.033802 seconds and 4 git commands to generate.