These changes clean things up a bit, and improve Solaris cross
[deliverable/binutils-gdb.git] / gas / config / obj-coffbfd.c
index 3936ebf725310f2ef7551b0d4c30c0cd482daaa4..2af4978d85916a3a2695aae4ef883ea57ba55fbc 100644 (file)
@@ -43,6 +43,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "../bfd/libbfd.h"
 
 
+#define MIN(a,b) ((a) < (b)? (a) : (b))
 /* This vector is used to turn an internal segment into a section #
    suitable for insertion into a coff symbol table 
  */
@@ -96,6 +97,10 @@ void EXFUN(bfd_as_write_hook,(struct internal_filehdr *,
 static void EXFUN(fixup_segment,(fixS *        fixP,
                  segT  this_segment_type));
 
+
+static void EXFUN(fixup_mdeps,(fragS *));
+
+
 static void EXFUN(fill_section,(bfd *abfd ,
                                struct internal_filehdr *f, unsigned
                                long *));
@@ -134,7 +139,7 @@ static void EXFUN( obj_coff_size,(void));
 static void EXFUN( obj_coff_tag,(void));
 static void EXFUN( obj_coff_type,(void));
 static void EXFUN( obj_coff_val,(void));
-static void EXFUN( obj_coff_section,(void));
+void EXFUN( obj_coff_section,(void));
 static void EXFUN( tag_init,(void));
 static void EXFUN( tag_insert,(char *name, symbolS *symbolP));
 
@@ -154,6 +159,8 @@ const pseudo_typeS obj_pseudo_table[] = {
        { "type",       obj_coff_type,          0       },
        { "val",        obj_coff_val,           0       },
         { "section",    obj_coff_section,       0       },
+        { "use",        obj_coff_section,       0       },
+        { "sect",    obj_coff_section,       0       },
         { "text",       obj_coff_text,          0       },
         { "data",       obj_coff_data,          0       },
        /* we don't yet handle this. */
@@ -250,27 +257,38 @@ symbolS* x)
 
 /* calculate the size of the frag chain and fill in the section header
    to contain all of it, also fill in the addr of the sections */
-static unsigned int  DEFUN(size_section,(abfd, idx),
-                 bfd *abfd AND
-                 unsigned int idx)
+static unsigned int  
+DEFUN(size_section,(abfd, idx),
+      bfd *abfd AND
+      unsigned int idx)
 {
 
   unsigned int size = 0;
   fragS *frag = segment_info[idx].frchainP->frch_root;
   while (frag) {
+    size = frag->fr_address;
+#if 0    
       if (frag->fr_address != size) {  
          printf("Out of step\n");
          size = frag->fr_address;
        }
-      size += frag->fr_fix;
+
       switch (frag->fr_type) {
+#ifdef TC_COFF_SIZEMACHDEP
+       case rs_machine_dependent:
+       size +=  TC_COFF_SIZEMACHDEP(frag);
+       break;
+#endif
        case rs_fill:
        case rs_org:
+      size += frag->fr_fix;
          size  +=    frag->fr_offset * frag->fr_var;
          break;
        case rs_align:
+      size += frag->fr_fix;
          size  +=   relax_align(size, frag->fr_offset);
        }
+#endif
       frag = frag->fr_next;
     }
   segment_info[idx].scnhdr.s_size = size;
@@ -315,7 +333,7 @@ void DEFUN(do_relocs_for,(abfd, file_cursor),
 {
   unsigned int nrelocs;
   unsigned int idx;
-  
+  unsigned int addr = 0;
   for (idx = SEG_E0; idx < SEG_E9; idx++) 
   {
     if (segment_info[idx].scnhdr.s_name[0]) 
@@ -325,7 +343,7 @@ void DEFUN(do_relocs_for,(abfd, file_cursor),
       struct external_reloc *external_reloc_vec;
       unsigned int external_reloc_size;
       unsigned int count = 0;
-      unsigned int base  = segment_info[idx].scnhdr.s_paddr;
+      unsigned int base  = addr;
       fixS *   fix_ptr = segment_info[idx].fix_root;
       nrelocs = count_entries_in_chain(idx);
       
@@ -418,6 +436,15 @@ void DEFUN(do_relocs_for,(abfd, file_cursor),
       *file_cursor += external_reloc_size;
       free( external_reloc_vec);
     }
+#ifndef ZERO_BASED_SEGMENTS
+    /* Supposedly setting segment addresses non-zero causes problems
+       for some platforms, although it shouldn't.  If you define
+       ZERO_BASED_SEGMENTS, all the segments will be based at 0.
+       Please don't make this the default, since some systems (e.g.,
+       SVR3.2) require the segments to be non-zero based.  Ian Taylor
+       <ian@cygnus.com>.  */
+    addr += segment_info[idx].scnhdr.s_size;
+#endif
   }
 }
 
@@ -431,89 +458,91 @@ static void DEFUN(fill_section,(abfd, filehdr, file_cursor),
                  unsigned long *file_cursor)
 {
 
-    unsigned int i;
-    unsigned int paddr = 0;
+  unsigned int i;
   
-    for (i = SEG_E0; i < SEG_UNKNOWN; i++) 
-    {  
-       unsigned int offset = 0;
+  for (i = SEG_E0; i < SEG_UNKNOWN; i++) 
+  {  
+    unsigned int offset = 0;
 
-       struct internal_scnhdr *s = &( segment_info[i].scnhdr);
+    struct internal_scnhdr *s = &( segment_info[i].scnhdr);
          
-       if (s->s_name[0]) 
-       {
-         fragS *frag = segment_info[i].frchainP->frch_root;
-         char *buffer =  malloc(s->s_size);
-         if (s->s_size != 0) 
+    if (s->s_name[0]) 
+    {
+      fragS *frag = segment_info[i].frchainP->frch_root;
+      char *buffer =  malloc(s->s_size);
+      if (s->s_size != 0) 
+       s->s_scnptr = *file_cursor;
+      else 
+       s->s_scnptr = 0;
+
+      s->s_flags = STYP_REG;
+      if (strcmp(s->s_name,".text")==0)
+       s->s_flags |= STYP_TEXT;
+      else if (strcmp(s->s_name,".data")==0)
+       s->s_flags |= STYP_DATA;
+      else if (strcmp(s->s_name,".bss")==0)
+       s->s_flags |= STYP_BSS | STYP_NOLOAD;
+      else if (strcmp(s->s_name,".lit")==0)
+       s->s_flags = STYP_LIT | STYP_TEXT;
+
+
+      while (frag) {
+       unsigned int fill_size;
+       switch (frag->fr_type) {
+        case rs_machine_dependent:
+         if(frag->fr_fix) 
          {
-           s->s_scnptr = *file_cursor;
-         s->s_paddr =  paddr;
-         s->s_vaddr =  paddr;
-
+           memcpy(buffer + frag->fr_address,
+                  frag->fr_literal,
+                  frag->fr_fix);
+           offset += frag->fr_fix;
          }
-         else 
-         {
-           s->s_scnptr = 0;
-         s->s_paddr =  0;
-         s->s_vaddr =  0;
 
+         break;
+        case rs_fill:
+        case rs_align:
+        case rs_org:
+         if(frag->fr_fix) 
+         {
+           memcpy(buffer + frag->fr_address,
+                  frag->fr_literal,
+                  frag->fr_fix);
+           offset += frag->fr_fix;
          }
-           
-
-         s->s_flags = STYP_REG;
-         if (strcmp(s->s_name,".text")==0)
-          s->s_flags |= STYP_TEXT;
-         else if (strcmp(s->s_name,".data")==0)
-          s->s_flags |= STYP_DATA;
-         else if (strcmp(s->s_name,".bss")==0)
-          s->s_flags |= STYP_BSS | STYP_NOLOAD;
-
-         while (frag) {
-             unsigned int fill_size;
-             switch (frag->fr_type) {
-
-               case rs_fill:
-               case rs_align:
-               case rs_org:
-                 if(frag->fr_fix) 
-                 {
-                   memcpy(buffer + frag->fr_address,
-                          frag->fr_literal,
-                          frag->fr_fix);
-                   offset += frag->fr_fix;
-                 }
 
-                 fill_size = frag->fr_var;
-                 if (fill_size)        
-                 {
-                   unsigned int count ;
-                   unsigned int off = frag->fr_fix;
-                   for (count = frag->fr_offset; count;  count--) 
-                   {
-                     memcpy(buffer +  frag->fr_address  + off,
-                            frag->fr_literal + frag->fr_fix,
-                            fill_size);
-                     off += fill_size;
-                     offset += fill_size;
+         fill_size = frag->fr_var;
+         if (fill_size)        
+         {
+           unsigned int count ;
+           unsigned int off = frag->fr_fix;
+           for (count = frag->fr_offset; count;  count--) 
+           {
+             memcpy(buffer +  frag->fr_address  + off,
+                    frag->fr_literal + frag->fr_fix,
+                    fill_size);
+             off += fill_size;
+             offset += fill_size;
                      
-                   }
-
-                 }
-                 break;
-               default:        
-                 abort();
-               }
-             frag = frag->fr_next;
            }
+
+         }
+         break;
+        case rs_broken_word:
+         break;
+        default:       
+         abort();
+       }
+       frag = frag->fr_next;
+      }
          
 
-         bfd_write(buffer, s->s_size,1,abfd);
-         free(buffer);
+      bfd_write(buffer, s->s_size,1,abfd);
+      free(buffer);
          
-         *file_cursor += s->s_size;
-         paddr += s->s_size;
-       }      
-    }
+      *file_cursor += s->s_size;
+
+    }      
+  }
 
 }
 
@@ -828,7 +857,8 @@ DEFUN_VOID(obj_coff_endef)
          case C_FCN:
            S_SET_SEGMENT(def_symbol_in_progress, SEG_E0);
 
-           if (def_symbol_in_progress->sy_symbol.ost_entry._n._n_nptr[1][1] == 'b') { /* .bf */
+           if (def_symbol_in_progress->sy_symbol.ost_entry._n._n_nptr[1][1] == 'b'
+               && def_symbol_in_progress->sy_symbol.ost_entry._n._n_nptr[1][2] == 'f') { /* .bf */
                    if (function_lineoff < 0) {
                            fprintf(stderr, "`.bf' symbol without preceding function\n");
                        }       /* missing function symbol */
@@ -1611,7 +1641,8 @@ static void DEFUN_VOID(remove_subsegs)
     }
 }
 
-
+int machine;
+int coff_flags;
 extern void DEFUN_VOID(write_object_file)
 {
     int i;
@@ -1621,7 +1652,7 @@ extern void DEFUN_VOID(write_object_file)
     struct internal_aouthdr aouthdr;
     unsigned long file_cursor;  
     bfd *abfd;
-      unsigned int addr = 0;  
+    unsigned int addr;
     abfd = bfd_openw(out_file_name, TARGET_FORMAT);
 
 
@@ -1630,7 +1661,7 @@ extern void DEFUN_VOID(write_object_file)
            exit(42);
        }
     bfd_set_format(abfd, bfd_object);
-    bfd_set_arch_mach(abfd, BFD_ARCH, 0);
+    bfd_set_arch_mach(abfd, BFD_ARCH, machine);
 
 
 
@@ -1660,40 +1691,45 @@ extern void DEFUN_VOID(write_object_file)
     {
        relax_segment(segment_info[i].frchainP->frch_root, i);
     }
-  
-
-
-
 
       filehdr.f_nscns = 0;
   
-      /* Find out how big the sections are */
+      /* Find out how big the sections are, and set the addresses.  */
+      addr = 0;
       for (i = SEG_E0; i < SEG_UNKNOWN; i++) 
       {
+       segment_info[i].scnhdr.s_paddr = addr;
+       segment_info[i].scnhdr.s_vaddr = addr;
 
        if (segment_info[i].scnhdr.s_name[0]) 
        {
          filehdr.f_nscns++;
        }
          
+#ifndef ZERO_BASED_SEGMENTS
+       /* See the comment at the previous ZERO_BASED_SEGMENTS check.  */
        if (i == SEG_E2) 
        {
-         /* THis is a special case, we leave the size alone, which will have */
-         /* been made up from all and any lcomms seen */
+         /* This is a special case, we leave the size alone, which
+            will have been made up from all and any lcomms seen.  */
+         addr += segment_info[i].scnhdr.s_size;
        }
-       else {
-           addr += size_section(abfd, i);
-         }
+       else 
+       {
+         addr += size_section(abfd, i);
+       }
+#endif
       }
 
 
 
     /* Turn the gas native symbol table shape into a coff symbol table */
     crawl_symbols(&filehdr, abfd);
-#ifndef TC_H8300
+#if !defined(TC_H8300) && !defined(TC_Z8K)
     for (i = SEG_E0; i < SEG_UNKNOWN; i++) 
     {
-       fixup_segment(segment_info[i].fix_root, i);
+      fixup_mdeps(segment_info[i].frchainP->frch_root);
+      fixup_segment(segment_info[i].fix_root, i);
     }
 #endif
 
@@ -1711,9 +1747,11 @@ extern void DEFUN_VOID(write_object_file)
 
     fill_section(abfd,&filehdr, &file_cursor);
 
+
+
     filehdr.f_magic = COFF_MAGIC;
     filehdr.f_timdat = time(0);
-    filehdr.f_flags = COFF_FLAGS ;
+    filehdr.f_flags = COFF_FLAGS | coff_flags;
     
     if (!had_lineno) 
     {
@@ -1744,7 +1782,9 @@ extern void DEFUN_VOID(write_object_file)
   }
     coff_header_append(abfd, &filehdr, &aouthdr);
 
-    bfd_close_all_done(abfd);
+    if (bfd_close_all_done(abfd) == false)
+      as_fatal ("Can't close %s: %s", out_file_name,
+               bfd_errmsg (bfd_error));
 }
 
 
@@ -1769,7 +1809,7 @@ static void DEFUN(change_to_section,(name, len, exp),
   subseg_new(i, exp);  
 }
 
-static void 
+void 
 DEFUN_VOID(obj_coff_section)
 {
     /* Strip out the section name */
@@ -1855,7 +1895,7 @@ DEFUN(c_line_new,(symbol, paddr, line_number, frag),
   
   if (line_number == 0) 
   {
-last_line_symbol = symbol;
+    last_line_symbol = symbol;
     new_line->line.l_addr.l_symndx = (long)symbol;
   }
   else 
@@ -1875,7 +1915,7 @@ last_line_symbol = symbol;
   {
     s->lineno_list_tail->next = new_line;
   }
-   s->lineno_list_tail = new_line;
+  s->lineno_list_tail = new_line;
   return LINESZ * s->scnhdr.s_nlnno ++;
 }
 
@@ -1992,44 +2032,80 @@ symbolS *symbol_rootP)
 
 static void DEFUN_VOID(obj_coff_lcomm)
 {
-    char *name;
-    char c;
-    int temp;
-    char *p;
-    symbolS *symbolP;
-    name = input_line_pointer;
+  char *name;
+  char c;
+  int temp;
+  char *p;
+  unsigned long vma;
 
+  symbolS *symbolP;
+  name = input_line_pointer;
 
 
-    c = get_symbol_end();
-    p = input_line_pointer;
-    *p = c;
-    SKIP_WHITESPACE();
-    if (*input_line_pointer != ',') {
-           as_bad("Expected comma after name");
-           ignore_rest_of_line();
-           return;
-       }
-    if (*input_line_pointer == '\n') {
-           as_bad("Missing size expression");
-           return;
-       }
-    input_line_pointer++;
-    if ((temp = get_absolute_expression ()) < 0) {
-           as_warn("lcomm length (%d.) <0! Ignored.", temp);
-           ignore_rest_of_line();
-           return;
-       }
-    *p = 0;
-    symbolP = symbol_find_or_make(name);
-    S_SET_VALUE(symbolP, segment_info[SEG_E2].scnhdr.s_size);
-    S_SET_SEGMENT(symbolP, SEG_E2);
-    segment_info[SEG_E2].scnhdr.s_size += temp;
-    S_SET_STORAGE_CLASS(symbolP, C_STAT);
-    demand_empty_rest_of_line();
+  c = get_symbol_end();
+  p = input_line_pointer;
+  *p = c;
+  SKIP_WHITESPACE();
+  if (*input_line_pointer != ',') {
+    as_bad("Expected comma after name");
+    ignore_rest_of_line();
+    return;
+  }
+  if (*input_line_pointer == '\n') {
+    as_bad("Missing size expression");
+    return;
+  }
+  input_line_pointer++;
+  if ((temp = get_absolute_expression ()) < 0) {
+    as_warn("lcomm length (%d.) <0! Ignored.", temp);
+    ignore_rest_of_line();
+    return;
+  }
+  *p = 0;
+
+  {
+    /* Allocate zero static local data in the .data section now
+       instead of the bss section as a symbol with a value */
+   char *x;
+   segT  oldseg = now_seg;
+   int oldsubseg  = now_subseg;
+     
+   subseg_new(SEG_DATA, 10);
+   colon(name);
+   frag_align(2,0);
+   record_alignment(SEG_DATA, 4);
+   x =  frag_var (rs_fill, 1, 1, (relax_substateT)0, (symbolS *)0,
+                 temp, (char *)0);
+   * x= 0;
+
+   subseg_new(oldseg, oldsubseg);
+ }
+  demand_empty_rest_of_line();
 }
 
+static void DEFUN(fixup_mdeps,(frags),
+                 fragS *frags)
+{
+  while (frags) 
+  {
+    switch (frags->fr_type) 
+    {
+     case rs_align:
+     case rs_org:
+      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(0, frags);
+      break;
+     default:
+      ;
+    }
+    frags = frags->fr_next;
+  }
 
+}
 #if 1
 static void DEFUN(fixup_segment,(fixP, this_segment_type),
 register fixS *        fixP AND
@@ -2084,6 +2160,7 @@ segT              this_segment_type)
                            }   /* not absolute */
                                
                        add_number -= S_GET_VALUE(sub_symbolP);
+                       fixP->fx_subsy = 0;
                                
                        /* if sub_symbol is in the same segment that add_symbol
                           and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE */
@@ -2171,9 +2248,14 @@ segT             this_segment_type)
                                    continue;
                                } /* COBR */
 #endif                         /* TC_I960 */
-               
-
-
+#ifdef TC_I386
+                           /* 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>.  */
+                           add_number += S_GET_VALUE(add_symbolP);
+#endif
                            break;
                                        
 
@@ -2190,12 +2272,23 @@ segT            this_segment_type)
                
        if (!fixP->fx_bit_fixP) {
                if ((size==1 &&
-                    (add_number& ~0xFF)   && (add_number&~0xFF!=(-1&~0xFF))) ||
+                    (add_number& ~0xFF)   && ((add_number&~0xFF)!=(-1&~0xFF))) ||
                    (size==2 &&
-                    (add_number& ~0xFFFF) && (add_number&~0xFFFF!=(-1&~0xFFFF)))) {
+                    (add_number& ~0xFFFF) && ((add_number&~0xFFFF)!=(-1&~0xFFFF)))) {
                        as_bad("Value of %d too large for field of %d bytes at 0x%x",
                               add_number, size, fragP->fr_address + where);
                    }           /* generic error checking */
+#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.  */
+               if (! flagseen['J']
+                   && size == 2
+                   && add_number > 0x7fff)
+                 as_bad ("Signed .word overflow; switch may be too large; %d at 0x%x",
+                         add_number, 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 -*/
This page took 0.029705 seconds and 4 git commands to generate.