2003-08-03 Jason Eckhardt <jle@rice.edu>
[deliverable/binutils-gdb.git] / gas / write.c
index 4ee6a7d6a0fca39222d71794252f77fb200eeb23..1419ab564eb9ca2c3898d9863ee5819f75dcd5bd 100644 (file)
@@ -1,6 +1,6 @@
 /* write.c - emit .o file
    Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002
+   1998, 1999, 2000, 2001, 2002, 2003
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
@@ -34,7 +34,7 @@
 
 #ifndef TC_FORCE_RELOCATION
 #define TC_FORCE_RELOCATION(FIX)               \
-  (S_FORCE_RELOC ((FIX)->fx_addsy))
+  (generic_force_reloc (FIX))
 #endif
 
 #ifndef TC_FORCE_RELOCATION_ABS
 #endif
 
 #ifndef TC_FORCE_RELOCATION_SUB_ABS
-#define TC_FORCE_RELOCATION_SUB_ABS(FIX)       \
-  (S_FORCE_RELOC ((FIX)->fx_subsy))
+#define TC_FORCE_RELOCATION_SUB_ABS(FIX)       0
 #endif
 
 #ifndef TC_FORCE_RELOCATION_SUB_LOCAL
 #ifdef DIFF_EXPR_OK
-#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX)     \
-  (S_FORCE_RELOC ((FIX)->fx_subsy))
+#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX)     0
 #else
-#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX) 1
+#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX)     1
 #endif
 #endif
 
@@ -187,9 +185,6 @@ static void cvt_frag_to_fill PARAMS ((object_headers *, segT, fragS *));
 static void remove_subsegs PARAMS ((frchainS *, int, fragS **, fragS **));
 static void relax_and_size_all_segments PARAMS ((void));
 #endif
-#if defined (BFD_ASSEMBLER) && defined (OBJ_COFF) && defined (TE_GO32)
-static void set_segment_vma PARAMS ((bfd *, asection *, PTR));
-#endif
 
 /* Create a fixS in obstack 'notes'.  */
 
@@ -379,6 +374,19 @@ fix_new_exp (frag, where, size, exp, pcrel, r_type)
   return fix_new_internal (frag, where, size, add, sub, off, pcrel, r_type);
 }
 
+/* Generic function to determine whether a fixup requires a relocation.  */
+int
+generic_force_reloc (fix)
+     fixS *fix;
+{
+#ifdef BFD_ASSEMBLER
+  if (fix->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+      || fix->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+    return 1;
+#endif
+  return S_FORCE_RELOC (fix->fx_addsy, fix->fx_subsy == NULL);
+}
+
 /* Append a string onto another string, bumping the pointer along.  */
 void
 append (charPP, fromP, length)
@@ -696,11 +704,11 @@ size_seg (abfd, sec, xxx)
   else
     flags &= ~SEC_RELOC;
   x = bfd_set_section_flags (abfd, sec, flags);
-  assert (x == true);
+  assert (x);
 
   newsize = md_section_align (sec, size);
   x = bfd_set_section_size (abfd, sec, newsize);
-  assert (x == true);
+  assert (x);
 
   /* If the size had to be rounded up, add some padding in the last
      non-empty frag.  */
@@ -828,7 +836,7 @@ adjust_reloc_syms (abfd, sec, xxx)
 
        /* If the symbol is undefined, common, weak, or global (ELF
           shared libs), we can't replace it with the section symbol.  */
-       if (S_FORCE_RELOC (fixp->fx_addsy))
+       if (S_FORCE_RELOC (fixp->fx_addsy, 1))
          continue;
 
        /* Is there some other (target cpu dependent) reason we can't adjust
@@ -873,7 +881,8 @@ adjust_reloc_syms (abfd, sec, xxx)
 
        /* Never adjust a reloc against local symbol in a merge section
           with non-zero addend.  */
-       if ((symsec->flags & SEC_MERGE) != 0 && fixp->fx_offset != 0)
+       if ((symsec->flags & SEC_MERGE) != 0
+           && (fixp->fx_offset != 0 || fixp->fx_subsy != NULL))
          continue;
 
        /* Never adjust a reloc against TLS local symbol.  */
@@ -929,8 +938,7 @@ write_relocs (abfd, sec, xxx)
 
 #ifndef RELOC_EXPANSION_POSSIBLE
   /* Set up reloc information as well.  */
-  relocs = (arelent **) xmalloc (n * sizeof (arelent *));
-  memset ((char *) relocs, 0, n * sizeof (arelent *));
+  relocs = (arelent **) xcalloc (n, sizeof (arelent *));
 
   i = 0;
   for (fixp = seginfo->fix_root; fixp != (fixS *) NULL; fixp = fixp->fx_next)
@@ -1002,13 +1010,12 @@ write_relocs (abfd, sec, xxx)
 #else
   n = n * MAX_RELOC_EXPANSION;
   /* Set up reloc information as well.  */
-  relocs = (arelent **) xmalloc (n * sizeof (arelent *));
+  relocs = (arelent **) xcalloc (n, sizeof (arelent *));
 
   i = 0;
   for (fixp = seginfo->fix_root; fixp != (fixS *) NULL; fixp = fixp->fx_next)
     {
       arelent **reloc;
-      char *data;
       bfd_reloc_status_type s;
       symbolS *sym;
       int j;
@@ -1044,7 +1051,6 @@ write_relocs (abfd, sec, xxx)
          relocs[i++] = reloc[j];
          assert (i <= n);
        }
-      data = fixp->fx_frag->fr_literal + fixp->fx_where;
       if (fixp->fx_where + fixp->fx_size
          > fixp->fx_frag->fr_fix + fixp->fx_frag->fr_offset)
        as_bad_where (fixp->fx_file, fixp->fx_line,
@@ -1129,7 +1135,7 @@ write_contents (abfd, sec, xxx)
      PTR xxx ATTRIBUTE_UNUSED;
 {
   segment_info_type *seginfo = seg_info (sec);
-  unsigned long offset = 0;
+  addressT offset = 0;
   fragS *f;
 
   /* Write out the frags.  */
@@ -1142,9 +1148,9 @@ write_contents (abfd, sec, xxx)
        f = f->fr_next)
     {
       int x;
-      unsigned long fill_size;
+      addressT fill_size;
       char *fill_literal;
-      long count;
+      offsetT count;
 
       assert (f->fr_type == rs_fill);
       if (f->fr_fix)
@@ -1152,7 +1158,7 @@ write_contents (abfd, sec, xxx)
          x = bfd_set_section_contents (stdoutput, sec,
                                        f->fr_literal, (file_ptr) offset,
                                        (bfd_size_type) f->fr_fix);
-         if (x == false)
+         if (!x)
            {
              bfd_perror (stdoutput->filename);
              as_perror (_("FATAL: Can't write %s"), stdoutput->filename);
@@ -1176,7 +1182,7 @@ write_contents (abfd, sec, xxx)
                                                fill_literal,
                                                (file_ptr) offset,
                                                (bfd_size_type) fill_size);
-                 if (x == false)
+                 if (!x)
                    {
                      bfd_perror (stdoutput->filename);
                      as_perror (_("FATAL: Can't write %s"),
@@ -1210,7 +1216,7 @@ write_contents (abfd, sec, xxx)
                  x = bfd_set_section_contents
                    (stdoutput, sec, buf, (file_ptr) offset,
                     (bfd_size_type) n_per_buf * fill_size);
-                 if (x != true)
+                 if (!x)
                    as_fatal (_("cannot write to output file"));
                  offset += n_per_buf * fill_size;
                }
@@ -1304,7 +1310,7 @@ relax_and_size_all_segments ()
 #ifdef OBJ_BOUT
   /* See above comments on b.out data section address.  */
   {
-    long bss_vma;
+    addressT bss_vma;
     if (data_last_frag == 0)
       bss_vma = H_GET_TEXT_SIZE (&headers);
     else
@@ -1344,7 +1350,7 @@ set_symtab ()
   int nsyms;
   asymbol **asympp;
   symbolS *symp;
-  boolean result;
+  bfd_boolean result;
   extern PTR bfd_alloc PARAMS ((bfd *, bfd_size_type));
 
   /* Count symbols.  We can't rely on a count made by the loop in
@@ -1370,25 +1376,11 @@ set_symtab ()
   else
     asympp = 0;
   result = bfd_set_symtab (stdoutput, asympp, nsyms);
-  assert (result == true);
+  assert (result);
   symbol_table_frozen = 1;
 }
 #endif
 
-#if defined (BFD_ASSEMBLER) && defined (OBJ_COFF) && defined (TE_GO32)
-static void
-set_segment_vma (abfd, sec, xxx)
-     bfd *abfd;
-     asection *sec;
-     PTR xxx ATTRIBUTE_UNUSED;
-{
-  static bfd_vma addr = 0;
-
-  bfd_set_section_vma (abfd, sec, addr);
-  addr += bfd_section_size (abfd, sec);
-}
-#endif /* BFD_ASSEMBLER && OBJ_COFF && !TE_PE  */
-
 /* Finish the subsegments.  After every sub-segment, we fake an
    ".align ...".  This conforms to BSD4.2 brane-damage.  We then fake
    ".fill 0" because that is the kind of frag that requires least
@@ -1427,7 +1419,25 @@ subsegs_finish ()
          any alignment is meaningless, and, moreover, will look weird
          if we are generating a listing.  */
       if (!had_errors ())
-       alignment = SUB_SEGMENT_ALIGN (now_seg, frchainP);
+       {
+         alignment = SUB_SEGMENT_ALIGN (now_seg, frchainP);
+#ifdef BFD_ASSEMBLER
+         if ((bfd_get_section_flags (now_seg->owner, now_seg) & SEC_MERGE)
+             && now_seg->entsize)
+           {
+             unsigned int entsize = now_seg->entsize;
+             int entalign = 0;
+
+             while ((entsize & 1) == 0)
+               {
+                 ++entalign;
+                 entsize >>= 1;
+               }
+             if (entalign > alignment)
+               alignment = entalign;
+           }
+#endif
+       }
 
       if (subseg_text_p (now_seg))
        frag_align_code (alignment, 0);
@@ -1573,12 +1583,8 @@ write_object_file ()
   /* Relaxation has completed.  Freeze all syms.  */
   finalize_syms = 1;
 
-#if defined (BFD_ASSEMBLER) && defined (OBJ_COFF) && defined (TE_GO32)
-  /* Now that the segments have their final sizes, run through the
-     sections and set their vma and lma. !BFD gas sets them, and BFD gas
-     should too. Currently, only DJGPP uses this code, but other
-     COFF targets may need to execute this too.  */
-  bfd_map_over_sections (stdoutput, set_segment_vma, (char *) 0);
+#ifdef md_post_relax_hook
+  md_post_relax_hook;
 #endif
 
 #ifndef BFD_ASSEMBLER
@@ -1632,7 +1638,7 @@ write_object_file ()
 #ifdef OBJ_BOUT
            || fragP->fr_next == data_frag_root
 #endif
-           || ((fragP->fr_next->fr_address - fragP->fr_address)
+           || ((offsetT) (fragP->fr_next->fr_address - fragP->fr_address)
                == (fragP->fr_fix + fragP->fr_offset * fragP->fr_var))))
        abort ();
 #endif
@@ -2064,7 +2070,7 @@ relax_frag (segment, fragP, stretch)
   const relax_typeS *start_type;
   relax_substateT next_state;
   relax_substateT this_state;
-  long growth;
+  offsetT growth;
   offsetT aim;
   addressT target;
   addressT address;
@@ -2287,7 +2293,7 @@ relax_segment (segment_frag_root, segment)
 
   /* Do relax().  */
   {
-    long stretch;      /* May be any size, 0 or negative.  */
+    offsetT stretch;   /* May be any size, 0 or negative.  */
     /* Cumulative number of addresses we have relaxed this pass.
        We may have relaxed more than one address.  */
     int stretched;     /* Have we stretched on this pass?  */
@@ -2302,7 +2308,7 @@ relax_segment (segment_frag_root, segment)
 
        for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next)
          {
-           long growth = 0;
+           offsetT growth = 0;
            addressT was_address;
            offsetT offset;
            symbolS *symbolP;
@@ -2437,7 +2443,7 @@ relax_segment (segment_frag_root, segment)
                         cannot have fewer than 0 chars.  That is, we can't
                         .org backwards.  */
                      as_bad_where (fragP->fr_file, fragP->fr_line,
-                                   _("attempt to .org backwards"));
+                                   _("attempt to move .org backwards"));
 
                      /* We've issued an error message.  Change the
                          frag to avoid cascading errors.  */
@@ -2496,7 +2502,7 @@ relax_segment (segment_frag_root, segment)
              case rs_leb128:
                {
                  valueT value;
-                 int size;
+                 offsetT size;
 
                  value = resolve_symbol_value (fragP->fr_symbol);
                  size = sizeof_leb128 (value, fragP->fr_subtype);
This page took 0.028551 seconds and 4 git commands to generate.