These changes clean things up a bit, and improve Solaris cross
[deliverable/binutils-gdb.git] / gas / config / obj-coffbfd.c
index 1d5b50bd325170ca811015a0522fcc149a993d5e..2af4978d85916a3a2695aae4ef883ea57ba55fbc 100644 (file)
@@ -97,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 *));
@@ -135,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));
 
@@ -253,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;
@@ -421,7 +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
   }
 }
 
@@ -436,7 +459,6 @@ static void DEFUN(fill_section,(abfd, filehdr, file_cursor),
 {
 
   unsigned int i;
-  unsigned int paddr = 0;
   
   for (i = SEG_E0; i < SEG_UNKNOWN; i++) 
   {  
@@ -449,20 +471,9 @@ static void DEFUN(fill_section,(abfd, filehdr, file_cursor),
       fragS *frag = segment_info[i].frchainP->frch_root;
       char *buffer =  malloc(s->s_size);
       if (s->s_size != 0) 
-      {
        s->s_scnptr = *file_cursor;
-       s->s_paddr =  paddr;
-       s->s_vaddr =  paddr;
-
-      }
       else 
-      {
        s->s_scnptr = 0;
-       s->s_paddr =  0;
-       s->s_vaddr =  0;
-
-      }
-           
 
       s->s_flags = STYP_REG;
       if (strcmp(s->s_name,".text")==0)
@@ -478,7 +489,16 @@ static void DEFUN(fill_section,(abfd, filehdr, file_cursor),
       while (frag) {
        unsigned int fill_size;
        switch (frag->fr_type) {
+        case rs_machine_dependent:
+         if(frag->fr_fix) 
+         {
+           memcpy(buffer + frag->fr_address,
+                  frag->fr_literal,
+                  frag->fr_fix);
+           offset += frag->fr_fix;
+         }
 
+         break;
         case rs_fill:
         case rs_align:
         case rs_org:
@@ -507,6 +527,8 @@ static void DEFUN(fill_section,(abfd, filehdr, file_cursor),
 
          }
          break;
+        case rs_broken_word:
+         break;
         default:       
          abort();
        }
@@ -518,7 +540,7 @@ static void DEFUN(fill_section,(abfd, filehdr, file_cursor),
       free(buffer);
          
       *file_cursor += s->s_size;
-      paddr += s->s_size;
+
     }      
   }
 
@@ -1619,7 +1641,8 @@ static void DEFUN_VOID(remove_subsegs)
     }
 }
 
-
+int machine;
+int coff_flags;
 extern void DEFUN_VOID(write_object_file)
 {
     int i;
@@ -1629,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);
 
 
@@ -1638,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);
 
 
 
@@ -1668,41 +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);
        }
+#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
 
@@ -1724,7 +1751,7 @@ extern void DEFUN_VOID(write_object_file)
 
     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) 
     {
@@ -1755,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));
 }
 
 
@@ -1780,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 */
@@ -2003,48 +2032,80 @@ symbolS *symbol_rootP)
 
 static void DEFUN_VOID(obj_coff_lcomm)
 {
-    char *name;
-    char c;
-    int temp;
-    char *p;
-    unsigned long vma;
+  char *name;
+  char c;
+  int temp;
+  char *p;
+  unsigned long vma;
 
-    symbolS *symbolP;
-    name = input_line_pointer;
+  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;
 
-    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);
-    vma = segment_info[SEG_E2].scnhdr.s_size;
-    vma += relax_align(vma, MIN(8, temp));
-    S_SET_VALUE(symbolP,vma);
-    S_SET_SEGMENT(symbolP, SEG_E2);
-    segment_info[SEG_E2].scnhdr.s_size = vma + temp;
-    S_SET_STORAGE_CLASS(symbolP, C_STAT);
-    demand_empty_rest_of_line();
+  {
+    /* 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
@@ -2099,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 */
@@ -2186,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;
                                        
 
@@ -2205,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.028281 seconds and 4 git commands to generate.