* write.c (adjust_reloc_syms): Check that symbol is not NULL
[deliverable/binutils-gdb.git] / gas / config / obj-coff.c
index 3b62c52fb0bb171a6635e95d3a648e7238410914..a5c04d2a1e8cff2f4bf807c9235900f6b45d0299 100644 (file)
 
    You should have received a copy of the GNU General Public License
    along with GAS; see the file COPYING.  If not, write to
-   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "as.h"
 #include "obstack.h"
 #include "subsegs.h"
 
+/* I think this is probably always correct.  */
+#ifndef KEEP_RELOC_INFO
+#define KEEP_RELOC_INFO
+#endif
+
+
+/* structure used to keep the filenames which
+   are too long around so that we can stick them
+   into the string table */
+struct filename_list 
+{
+  char *filename;
+  struct filename_list *next;
+};
+
+static struct filename_list *filename_list_head;
+static struct filename_list *filename_list_tail;
+
 const char *s_get_name PARAMS ((symbolS * s));
 static symbolS *def_symbol_in_progress;
 
@@ -754,6 +772,16 @@ obj_coff_line (ignore)
   SA_SET_SYM_LNNO (def_symbol_in_progress, coff_line_base);
 
   demand_empty_rest_of_line ();
+
+#ifndef NO_LISTING
+  if (strcmp (".bf", S_GET_NAME (def_symbol_in_progress)) == 0)
+    {
+      extern int listing;
+
+      if (listing)
+       listing_source_line ((unsigned int) coff_line_base);
+    }
+#endif
 }
 
 static void
@@ -1002,6 +1030,10 @@ coff_frob_symbol (symp, punt)
        S_SET_STORAGE_CLASS (symp, C_EXT);
       else if (SF_GET_LOCAL (symp))
        *punt = 1;
+
+      if (SF_GET_FUNCTION (symp))
+       symp->bsym->flags |= BSF_FUNCTION;
+
       /* more ... */
     }
 
@@ -1301,8 +1333,9 @@ symbol_dump ()
 #include "frags.h"
 /* This is needed because we include internal bfd things. */
 #include <time.h>
-#include "bfd/libbfd.h"
-#include "bfd/libcoff.h"
+
+#include "libbfd.h"
+#include "libcoff.h"
 
 /* The NOP_OPCODE is for the alignment fill value.  Fill with nop so
    that we can stick sections together without causing trouble.  */
@@ -1485,6 +1518,8 @@ size_section (abfd, idx)
          size += TC_COFF_SIZEMACHDEP (frag);
          break;
 #endif
+       case rs_space:
+         assert (frag->fr_symbol == 0);
        case rs_fill:
        case rs_org:
          size += frag->fr_fix;
@@ -1570,18 +1605,18 @@ do_relocs_for (abfd, h, file_cursor)
                 internal fix list.  */
              while (fix_ptr)
                {
-                 symbolS *symbol_ptr;
                  struct internal_reloc intr;
 
                  /* Only output some of the relocations */
                  if (TC_COUNT_RELOC (fix_ptr))
                    {
 #ifdef TC_RELOC_MANGLE
-                     TC_RELOC_MANGLE (fix_ptr, &intr, base);
+                     TC_RELOC_MANGLE (&segment_info[idx], fix_ptr, &intr,
+                                      base);
 
 #else
                      symbolS *dot;
-                     symbol_ptr = fix_ptr->fx_addsy;
+                     symbolS *symbol_ptr = fix_ptr->fx_addsy;
 
                      intr.r_type = TC_COFF_FIX2RTYPE (fix_ptr);
                      intr.r_vaddr =
@@ -1675,9 +1710,10 @@ fill_section (abfd, h, file_cursor)
   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
     {
       unsigned int offset = 0;
-
       struct internal_scnhdr *s = &(segment_info[i].scnhdr);
 
+      PROGRESS (1);
+
       if (s->s_name[0])
        {
          fragS *frag = segment_info[i].frchainP->frch_root;
@@ -1737,6 +1773,8 @@ fill_section (abfd, h, file_cursor)
                    }
 
                  break;
+               case rs_space:
+                 assert (frag->fr_symbol == 0);
                case rs_fill:
                case rs_align:
                case rs_org:
@@ -1826,6 +1864,8 @@ coff_header_append (abfd, h)
          bfd_coff_swap_scnhdr_out (abfd,
                                    &(segment_info[i].scnhdr),
                                    buffer);
+         if (size == 0)
+           as_bad ("bfd_coff_swap_scnhdr_out failed");
          bfd_write (buffer, size, 1, abfd);
        }
     }
@@ -2242,7 +2282,7 @@ obj_coff_line (ignore)
 #ifndef NO_LISTING
       {
        extern int listing;
-       if (listing && 0)
+       if (listing)
          {
            listing_source_line ((unsigned int) line_base);
          }
@@ -2416,6 +2456,10 @@ obj_read_begin_hook ()
 /* This function runs through the symbol table and puts all the
    externals onto another chain */
 
+/* The chain of globals.  */
+symbolS *symbol_globalP;
+symbolS *symbol_global_lastP;
+
 /* The chain of externals */
 symbolS *symbol_externP;
 symbolS *symbol_extern_lastP;
@@ -2431,10 +2475,21 @@ yank_symbols ()
   unsigned int symbol_number = 0;
   unsigned int last_file_symno = 0;
 
+  struct filename_list *filename_list_scan = filename_list_head;
+
   for (symbolP = symbol_rootP;
        symbolP;
        symbolP = symbolP ? symbol_next (symbolP) : symbol_rootP)
     {
+      if (symbolP->sy_mri_common)
+       {
+         if (S_GET_STORAGE_CLASS (symbolP) == C_EXT)
+           as_bad ("%s: global symbols not supported in common sections",
+                   S_GET_NAME (symbolP));
+         symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
+         continue;
+       }
+
       if (!SF_GET_DEBUG (symbolP))
        {
          /* Debug symbols do not need all this rubbish */
@@ -2556,6 +2611,14 @@ yank_symbols ()
        }
       else if (S_GET_STORAGE_CLASS (symbolP) == C_FILE)
        {
+         /* If the filename was too long to fit in the
+            auxent, put it in the string table */
+         if (SA_GET_FILE_FNAME_ZEROS (symbolP) == 0)
+           {
+             SA_SET_FILE_FNAME_OFFSET (symbolP, string_byte_count);
+             string_byte_count += strlen (filename_list_scan->filename) + 1;
+             filename_list_scan = filename_list_scan->next;
+           }
          if (S_GET_VALUE (symbolP))
            {
              S_SET_VALUE (symbolP, last_file_symno);
@@ -2595,6 +2658,23 @@ yank_symbols ()
          symbol_append (symbolP, symbol_extern_lastP, &symbol_externP, &symbol_extern_lastP);
          symbolP = hold;
        }
+      else if (! S_IS_DEBUG (symbolP)
+              && ! SF_GET_STATICS (symbolP)
+              && ! SF_GET_FUNCTION (symbolP)
+              && S_GET_STORAGE_CLASS (symbolP) == C_EXT)
+       {
+         symbolS *hold = symbol_previous (symbolP);
+
+         /* The O'Reilly COFF book says that defined global symbols
+             come at the end of the symbol table, just before
+             undefined global symbols.  */
+
+         symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
+         symbol_clear_list_pointers (symbolP);
+         symbol_append (symbolP, symbol_global_lastP, &symbol_globalP,
+                        &symbol_global_lastP);
+         symbolP = hold;
+       }
       else
        {
          if (SF_GET_STRING (symbolP))
@@ -2617,16 +2697,19 @@ yank_symbols ()
 
 
 static unsigned int
-glue_symbols ()
+glue_symbols (head, tail)
+     symbolS **head;
+     symbolS **tail;
 {
   unsigned int symbol_number = 0;
   symbolS *symbolP;
-  for (symbolP = symbol_externP; symbol_externP;)
+
+  for (symbolP = *head; *head != NULL;)
     {
-      symbolS *tmp = symbol_externP;
+      symbolS *tmp = *head;
 
       /* append */
-      symbol_remove (tmp, &symbol_externP, &symbol_extern_lastP);
+      symbol_remove (tmp, head, tail);
       symbol_append (tmp, symbol_lastP, &symbol_rootP, &symbol_lastP);
 
       /* and process */
@@ -2643,8 +2726,8 @@ glue_symbols ()
       tmp->sy_number = symbol_number;
       symbol_number += 1 + S_GET_NUMBER_AUXILIARY (tmp);
     }                          /* append the entire extern chain */
-  return symbol_number;
 
+  return symbol_number;
 }
 
 static unsigned int
@@ -2723,9 +2806,16 @@ crawl_symbols (h, abfd)
   /* Take all the externals out and put them into another chain */
   H_SET_SYMBOL_TABLE_SIZE (h, yank_symbols ());
   /* Take the externals and glue them onto the end.*/
-  H_SET_SYMBOL_TABLE_SIZE (h, H_GET_SYMBOL_COUNT (h) + glue_symbols ());
+  H_SET_SYMBOL_TABLE_SIZE (h,
+                          (H_GET_SYMBOL_COUNT (h)
+                           + glue_symbols (&symbol_globalP,
+                                           &symbol_global_lastP)
+                           + glue_symbols (&symbol_externP,
+                                           &symbol_extern_lastP)));
 
   H_SET_SYMBOL_TABLE_SIZE (h, tie_tags ());
+  know (symbol_globalP == NULL);
+  know (symbol_global_lastP == NULL);
   know (symbol_externP == NULL);
   know (symbol_extern_lastP == NULL);
 }
@@ -2739,6 +2829,7 @@ w_strings (where)
      char *where;
 {
   symbolS *symbolP;
+  struct filename_list *filename_list_scan = filename_list_head;
 
   /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
   md_number_to_chars (where, (valueT) string_byte_count, 4);
@@ -2752,10 +2843,16 @@ w_strings (where)
       if (SF_GET_STRING (symbolP))
        {
          size = strlen (S_GET_NAME (symbolP)) + 1;
-
          memcpy (where, S_GET_NAME (symbolP), size);
          where += size;
-
+       }
+      if (S_GET_STORAGE_CLASS (symbolP) == C_FILE
+         && SA_GET_FILE_FNAME_ZEROS (symbolP) == 0)
+       {
+         size = strlen (filename_list_scan->filename) + 1;
+         memcpy (where, filename_list_scan->filename, size);
+         filename_list_scan = filename_list_scan ->next;
+         where += size;
        }
     }
 }
@@ -2939,13 +3036,15 @@ write_object_file ()
 
   H_SET_STRING_SIZE (&headers, string_byte_count);
 
-#if !defined(TC_H8300) && !defined(TC_Z8K)
+#ifdef tc_frob_file
+  tc_frob_file ();
+#endif
+
   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
     {
       fixup_mdeps (segment_info[i].frchainP->frch_root, &headers, i);
       fixup_segment (&segment_info[i], i);
     }
-#endif
 
   /* Look for ".stab" segments and fill in their initial symbols
      correctly. */
@@ -2973,7 +3072,7 @@ write_object_file ()
 
   H_SET_FILE_MAGIC_NUMBER (&headers, COFF_MAGIC);
 #ifndef OBJ_COFF_OMIT_TIMESTAMP
-  H_SET_TIME_STAMP (&headers, (long)time((long*)0));
+  H_SET_TIME_STAMP (&headers, (long)time((time_t *)0));
 #else
   H_SET_TIME_STAMP (&headers, 0);
 #endif
@@ -2981,6 +3080,10 @@ write_object_file ()
   TC_COFF_SET_MACHINE (&headers);
 #endif
 
+#ifndef COFF_FLAGS
+#define COFF_FLAGS 0
+#endif
+
 #ifdef KEEP_RELOC_INFO
   H_SET_FLAGS (&headers, ((H_GET_LINENO_SIZE(&headers) ? 0 : F_LNNO) |
                          COFF_FLAGS | coff_flags));
@@ -3258,7 +3361,31 @@ c_dot_file_symbol (filename)
 
   S_SET_STORAGE_CLASS (symbolP, C_FILE);
   S_SET_NUMBER_AUXILIARY (symbolP, 1);
-  SA_SET_FILE_FNAME (symbolP, filename);
+
+  if (strlen (filename) > FILNMLEN)
+    {
+      /* Filename is too long to fit into an auxent,
+        we stick it into the string table instead.  We keep
+        a linked list of the filenames we find so we can emit
+        them later.*/
+      struct filename_list *f = xmalloc (sizeof (struct filename_list));
+
+      f->filename = filename;
+      f->next = 0;
+
+      SA_SET_FILE_FNAME_ZEROS (symbolP, 0);
+      SA_SET_FILE_FNAME_OFFSET (symbolP, 0);
+
+      if (filename_list_tail) 
+       filename_list_tail->next = f;
+      else
+       filename_list_head = f;
+      filename_list_tail = f;      
+    }
+  else 
+    {
+      SA_SET_FILE_FNAME (symbolP, filename);
+    }
 #ifndef NO_LISTING
   {
     extern int listing;
@@ -3443,12 +3570,15 @@ fixup_mdeps (frags, h, this_segment)
        {
        case rs_align:
        case rs_org:
+#ifdef HANDLE_ALIGN
+         HANDLE_ALIGN (frags);
+#endif
          frags->fr_type = rs_fill;
          frags->fr_offset =
            (frags->fr_next->fr_address - frags->fr_address - frags->fr_fix);
          break;
        case rs_machine_dependent:
-         md_convert_frag (h, frags);
+         md_convert_frag (h, this_segment, frags);
          frag_wane (frags);
          break;
        default:
@@ -3459,6 +3589,11 @@ fixup_mdeps (frags, h, this_segment)
 }
 
 #if 1
+
+#ifndef TC_FORCE_RELOCATION
+#define TC_FORCE_RELOCATION(fix) 0
+#endif
+
 static void
 fixup_segment (segP, this_segment_type)
      segment_info_type * segP;
@@ -3467,7 +3602,7 @@ fixup_segment (segP, this_segment_type)
   register fixS * fixP;
   register symbolS *add_symbolP;
   register symbolS *sub_symbolP;
-  register long add_number;
+  long add_number;
   register int size;
   register char *place;
   register long where;
@@ -3475,6 +3610,8 @@ fixup_segment (segP, this_segment_type)
   register fragS *fragP;
   register segT add_symbol_segment = absolute_section;
 
+  if (linkrelax)
+    return;
 
   for (fixP = segP->fix_root; fixP; fixP = fixP->fx_next)
     {
@@ -3504,6 +3641,15 @@ fixup_segment (segP, this_segment_type)
       add_number = fixP->fx_offset;
       pcrel = fixP->fx_pcrel;
 
+      if (add_symbolP != NULL
+         && add_symbolP->sy_mri_common)
+       {
+         know (add_symbolP->sy_value.X_op == O_symbol);
+         add_number += S_GET_VALUE (add_symbolP);
+         fixP->fx_offset = add_number;
+         add_symbolP = fixP->fx_addsy = add_symbolP->sy_value.X_add_symbol;
+       }
+
       if (add_symbolP)
        {
          add_symbol_segment = S_GET_SEGMENT (add_symbolP);
@@ -3545,11 +3691,18 @@ fixup_segment (segP, this_segment_type)
 #endif /* TC_I960 */
              add_number += S_GET_VALUE (add_symbolP) -
                S_GET_VALUE (sub_symbolP);
-
              add_symbolP = NULL;
-             fixP->fx_addsy = NULL;
-             fixP->fx_subsy = NULL;
-             fixP->fx_done = 1;
+
+             if (!TC_FORCE_RELOCATION (fixP))
+               {
+                 fixP->fx_addsy = NULL;
+                 fixP->fx_subsy = NULL;
+                 fixP->fx_done = 1;
+#ifdef TC_M68K /* is this right? */
+                 pcrel = 0;
+                 fixP->fx_pcrel = 0;
+#endif
+               }
            }
          else
            {
@@ -3613,8 +3766,11 @@ fixup_segment (segP, this_segment_type)
              add_number -= segP->scnhdr.s_vaddr;
 #endif
              pcrel = 0;        /* Lie. Don't want further pcrel processing. */
-             fixP->fx_addsy = NULL;
-             fixP->fx_done = 1;
+             if (!TC_FORCE_RELOCATION (fixP))
+               {
+                 fixP->fx_addsy = NULL;
+                 fixP->fx_done = 1;
+               }
            }
          else
            {
@@ -3625,13 +3781,18 @@ fixup_segment (segP, this_segment_type)
                  reloc_callj (fixP);   /* See comment about reloc_callj() above*/
 #endif /* TC_I960 */
                  add_number += S_GET_VALUE (add_symbolP);
-                 fixP->fx_addsy = NULL;
-                 fixP->fx_done = 1;
                  add_symbolP = NULL;
+
+                 if (!TC_FORCE_RELOCATION (fixP))
+                   {
+                     fixP->fx_addsy = NULL;
+                     fixP->fx_done = 1;
+                   }
                  break;
                default:
 
-#ifdef TC_A29K
+
+#if defined(TC_A29K) || (defined(TE_PE) && defined(TC_I386))
                  /* This really should be handled in the linker, but
                     backward compatibility forbids.  */
                  add_number += S_GET_VALUE (add_symbolP);
@@ -3657,12 +3818,11 @@ fixup_segment (segP, this_segment_type)
                      continue;
                    }           /* COBR */
 #endif /* TC_I960 */
-#if defined (TC_I386) || defined (TE_LYNX)
-                 /* 386 COFF uses a peculiar format in
-                    which the value of a common symbol is
-                    stored in the .text segment (I've
-                    checked this on SVR3.2 and SCO 3.2.2)
-                    Ian Taylor <ian@cygnus.com>.  */
+#if (defined (TC_I386) || defined (TE_LYNX)) && !defined(TE_PE)
+                 /* 386 COFF uses a peculiar format in which the
+                    value of a common symbol is stored in the .text
+                    segment (I've checked this on SVR3.2 and SCO
+                    3.2.2) Ian Taylor <ian@cygnus.com>.  */
                  if (S_IS_COMMON (add_symbolP))
                    add_number += S_GET_VALUE (add_symbolP);
 #endif
@@ -3675,7 +3835,7 @@ fixup_segment (segP, this_segment_type)
 
       if (pcrel)
        {
-#ifndef TC_M88K
+#if !defined(TC_M88K) && !(defined(TE_PE) && defined(TC_I386))
          /* This adjustment is not correct on the m88k, for which the
             linker does all the computation.  */
          add_number -= md_pcrel_from (fixP);
@@ -3710,10 +3870,10 @@ fixup_segment (segP, this_segment_type)
            }
 #endif
 #ifdef WARN_SIGNED_OVERFLOW_WORD
-         /* Warn if a .word value is too large when treated as
-            a signed number.  We already know it is not too
-            negative.  This is to catch over-large switches
-            generated by gcc on the 68k.  */
+         /* Warn if a .word value is too large when treated as a
+            signed number.  We already know it is not too negative.
+            This is to catch over-large switches generated by gcc on
+            the 68k.  */
          if (!flag_signed_overflow_ok
              && size == 2
              && add_number > 0x7fff)
@@ -3723,9 +3883,13 @@ fixup_segment (segP, this_segment_type)
                          (unsigned long) (fragP->fr_address + where));
 #endif
        }                       /* not a bit fix */
-      /* once this fix has been applied, we don't have to output anything
-          nothing more need be done -*/
+      /* Once this fix has been applied, we don't have to output
+        anything nothing more need be done.  */
+#ifdef MD_APPLY_FIX3
+      md_apply_fix3 (fixP, &add_number, this_segment_type);
+#else
       md_apply_fix (fixP, add_number);
+#endif
     }                          /* For each fixS in this segment. */
 }                              /* fixup_segment() */
 
This page took 0.13738 seconds and 4 git commands to generate.