Support all of the V.4 relocations
[deliverable/binutils-gdb.git] / bfd / ecofflink.c
index 596f169b7c2e806ea3a95b8f0e25768d7ed693c1..2d1f99b8c8851e99199a9cc60d1ebbdb80e26a4d 100644 (file)
@@ -519,10 +519,17 @@ bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
             hash reduces the chance that we will merge symbol
             information that should not be merged.  */
          name = input_debug->ss + fdr.issBase + fdr.rss;
-         lookup = (char *) alloca (strlen (name) + 20);
+
+         lookup = (char *) malloc (strlen (name) + 20);
+         if (lookup == NULL)
+           {
+             bfd_set_error (bfd_error_no_memory);
+             return false;
+           }
          sprintf (lookup, "%s %lx", name, fdr.csym);
 
          fh = string_hash_lookup (&ainfo->fdr_hash, lookup, true, true);
+         free (lookup);
          if (fh == (struct string_hash_entry *) NULL)
            return false;
 
@@ -584,6 +591,7 @@ bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
        fdr_ptr += fdr_add, i++)
     {
       FDR fdr;
+      bfd_vma fdr_adr;
       bfd_byte *sym_out;
       bfd_byte *lraw_src;
       bfd_byte *lraw_end;
@@ -600,6 +608,22 @@ bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
       else
        (*input_swap->swap_fdr_in) (input_bfd, (PTR) fdr_ptr, &fdr);
 
+      fdr_adr = fdr.adr;
+
+      /* Adjust the FDR address for any changes that may have been
+        made by relaxing.  */
+      if (input_debug->adjust != (struct ecoff_value_adjust *) NULL)
+       {
+         struct ecoff_value_adjust *adjust;
+
+         for (adjust = input_debug->adjust;
+              adjust != (struct ecoff_value_adjust *) NULL;
+              adjust = adjust->next)
+           if (fdr_adr >= adjust->start
+               && fdr_adr < adjust->end)
+             fdr.adr += adjust->adjust;
+       }
+
       /* FIXME: It is conceivable that this FDR points to the .init or
         .fini section, in which case this will not do the right
         thing.  */
@@ -615,7 +639,8 @@ bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
          bfd_set_error (bfd_error_no_memory);
          return false;
        }
-      if (!add_memory_shuffle (ainfo, &ainfo->sym, &ainfo->sym_end, sym_out, sz))
+      if (!add_memory_shuffle (ainfo, &ainfo->sym, &ainfo->sym_end, sym_out,
+                              sz))
        return false;
       lraw_src = ((bfd_byte *) input_debug->external_sym
                  + fdr.isymBase * input_swap->external_sym_size);
@@ -641,6 +666,19 @@ bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
            case stLabel:
            case stProc:
            case stStaticProc:
+             if (input_debug->adjust != (struct ecoff_value_adjust *) NULL)
+               {
+                 bfd_vma value;
+                 struct ecoff_value_adjust *adjust;
+
+                 value = internal_sym.value;
+                 for (adjust = input_debug->adjust;
+                      adjust != (struct ecoff_value_adjust *) NULL;
+                      adjust = adjust->next)
+                   if (value >= adjust->start
+                       && value < adjust->end)
+                     internal_sym.value += adjust->adjust;
+               }
              internal_sym.value += section_adjust[internal_sym.sc];
              break;
 
@@ -703,12 +741,17 @@ bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
       output_symhdr->isymMax += fdr.csym;
 
       /* Copy the information that does not need swapping.  */
+
+      /* FIXME: If we are relaxing, we need to adjust the line
+        numbers.  Frankly, forget it.  Anybody using stabs debugging
+        information will not use this line number information, and
+        stabs are adjusted correctly.  */
       if (fdr.cbLine > 0)
        {
          if (!add_file_shuffle (ainfo, &ainfo->line, &ainfo->line_end,
-                           input_bfd,
-                           input_symhdr->cbLineOffset + fdr.cbLineOffset,
-                           fdr.cbLine))
+                                input_bfd,
+                                input_symhdr->cbLineOffset + fdr.cbLineOffset,
+                                fdr.cbLine))
            return false;
          fdr.ilineBase = output_symhdr->ilineMax;
          fdr.cbLineOffset = output_symhdr->cbLine;
@@ -718,10 +761,10 @@ bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
       if (fdr.caux > 0)
        {
          if (!add_file_shuffle (ainfo, &ainfo->aux, &ainfo->aux_end,
-                           input_bfd,
-                           (input_symhdr->cbAuxOffset
-                            + fdr.iauxBase * sizeof (union aux_ext)),
-                           fdr.caux * sizeof (union aux_ext)))
+                                input_bfd,
+                                (input_symhdr->cbAuxOffset
+                                 + fdr.iauxBase * sizeof (union aux_ext)),
+                                fdr.caux * sizeof (union aux_ext)))
            return false;
          fdr.iauxBase = output_symhdr->iauxMax;
          output_symhdr->iauxMax += fdr.caux;
@@ -739,19 +782,21 @@ bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
       else if (fdr.cbSs > 0)
        {
          if (!add_file_shuffle (ainfo, &ainfo->ss, &ainfo->ss_end,
-                           input_bfd,
-                           input_symhdr->cbSsOffset + fdr.issBase,
-                           fdr.cbSs))
+                                input_bfd,
+                                input_symhdr->cbSsOffset + fdr.issBase,
+                                fdr.cbSs))
            return false;
          fdr.issBase = output_symhdr->issMax;
          output_symhdr->issMax += fdr.cbSs;
        }
 
-      if (output_bfd->xvec->header_byteorder_big_p
-         == input_bfd->xvec->header_byteorder_big_p)
+      if ((output_bfd->xvec->header_byteorder_big_p
+          == input_bfd->xvec->header_byteorder_big_p)
+         && input_debug->adjust == (struct ecoff_value_adjust *) NULL)
        {
-         /* The two BFD's have the same endianness, so simply copying
-            the information will suffice.  */
+         /* The two BFD's have the same endianness, and we don't have
+            to adjust the PDR addresses, so simply copying the
+            information will suffice.  */
          BFD_ASSERT (external_pdr_size == input_swap->external_pdr_size);
          if (fdr.cpd > 0)
            {
@@ -795,13 +840,31 @@ bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
              bfd_set_error (bfd_error_no_memory);
              return false;
            }
-         if (!add_memory_shuffle (ainfo, &ainfo->pdr, &ainfo->pdr_end, out, sz))
+         if (!add_memory_shuffle (ainfo, &ainfo->pdr, &ainfo->pdr_end, out,
+                                  sz))
            return false;
          for (; in < end; in += insz, out += outsz)
            {
              PDR pdr;
 
              (*input_swap->swap_pdr_in) (input_bfd, (PTR) in, &pdr);
+
+             /* If we have been relaxing, we may have to adjust the
+                address.  */
+             if (input_debug->adjust != (struct ecoff_value_adjust *) NULL)
+               {
+                 bfd_vma adr;
+                 struct ecoff_value_adjust *adjust;
+
+                 adr = fdr_adr + pdr.adr;
+                 for (adjust = input_debug->adjust;
+                      adjust != (struct ecoff_value_adjust *) NULL;
+                      adjust = adjust->next)
+                   if (adr >= adjust->start
+                       && adr < adjust->end)
+                     pdr.adr += adjust->adjust;
+               }
+
              (*output_swap->swap_pdr_out) (output_bfd, &pdr, (PTR) out);
            }
 
@@ -818,7 +881,8 @@ bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
              bfd_set_error (bfd_error_no_memory);
              return false;
            }
-         if (!add_memory_shuffle (ainfo, &ainfo->opt, &ainfo->opt_end, out, sz))
+         if (!add_memory_shuffle (ainfo, &ainfo->opt, &ainfo->opt_end, out,
+                                  sz))
            return false;
          for (; in < end; in += insz, out += outsz)
            {
@@ -930,9 +994,11 @@ bfd_ecoff_debug_accumulate_other (handle, output_bfd, output_debug,
   asymbol **symbols;
   asymbol **sym_ptr;
   asymbol **sym_end;
+  long symsize;
+  long symcount;
   PTR external_fdr;
 
-  memset (&fdr, 0, sizeof fdr);
+  memset ((PTR) &fdr, 0, sizeof fdr);
 
   sec = bfd_get_section_by_name (input_bfd, ".text");
   if (sec != NULL)
@@ -952,14 +1018,19 @@ bfd_ecoff_debug_accumulate_other (handle, output_bfd, output_debug,
   fdr.isymBase = output_symhdr->isymMax;
 
   /* Get the local symbols from the input BFD.  */
-  symbols = (asymbol **) bfd_alloc (output_bfd,
-                                   get_symtab_upper_bound (input_bfd));
+  symsize = bfd_get_symtab_upper_bound (input_bfd);
+  if (symsize < 0)
+    return false;
+  symbols = (asymbol **) bfd_alloc (output_bfd, symsize);
   if (symbols == (asymbol **) NULL)
     {
       bfd_set_error (bfd_error_no_memory);
       return false;
     }
-  sym_end = symbols + bfd_canonicalize_symtab (input_bfd, symbols);
+  symcount = bfd_canonicalize_symtab (input_bfd, symbols);
+  if (symcount < 0)
+    return false;
+  sym_end = symbols + symcount;
 
   /* Handle the local symbols.  Any external symbols are handled
      separately.  */
@@ -971,7 +1042,7 @@ bfd_ecoff_debug_accumulate_other (handle, output_bfd, output_debug,
 
       if (((*sym_ptr)->flags & BSF_EXPORT) != 0)
        continue;
-      memset (&internal_sym, 0, sizeof internal_sym);
+      memset ((PTR) &internal_sym, 0, sizeof internal_sym);
       internal_sym.iss = ecoff_add_string (ainfo, info, output_debug, &fdr,
                                           (*sym_ptr)->name);
 
@@ -1168,7 +1239,7 @@ ecoff_align_debug (abfd, debug, swap)
   if (add != debug_align)
     {
       if (debug->line != (unsigned char *) NULL)
-       memset (debug->line + symhdr->cbLine, 0, add);
+       memset ((PTR) (debug->line + symhdr->cbLine), 0, add);
       symhdr->cbLine += add;
     }
 
@@ -1176,7 +1247,7 @@ ecoff_align_debug (abfd, debug, swap)
   if (add != debug_align)
     {
       if (debug->ss != (char *) NULL)
-       memset (debug->ss + symhdr->issMax, 0, add);
+       memset ((PTR) (debug->ss + symhdr->issMax), 0, add);
       symhdr->issMax += add;
     }
 
@@ -1184,7 +1255,7 @@ ecoff_align_debug (abfd, debug, swap)
   if (add != debug_align)
     {
       if (debug->ssext != (char *) NULL)
-       memset (debug->ssext + symhdr->issExtMax, 0, add);
+       memset ((PTR) (debug->ssext + symhdr->issExtMax), 0, add);
       symhdr->issExtMax += add;
     }
 
@@ -1192,7 +1263,7 @@ ecoff_align_debug (abfd, debug, swap)
   if (add != aux_align)
     {
       if (debug->external_aux != (union aux_ext *) NULL)
-       memset (debug->external_aux + symhdr->iauxMax, 0,
+       memset ((PTR) (debug->external_aux + symhdr->iauxMax), 0,
                add * sizeof (union aux_ext));
       symhdr->iauxMax += add;
     }
@@ -1201,8 +1272,8 @@ ecoff_align_debug (abfd, debug, swap)
   if (add != rfd_align)
     {
       if (debug->external_rfd != (PTR) NULL)
-       memset (((char *) debug->external_rfd
-                + symhdr->crfd * swap->external_rfd_size),
+       memset ((PTR) ((char *) debug->external_rfd
+                      + symhdr->crfd * swap->external_rfd_size),
                0, add * swap->external_rfd_size);
       symhdr->crfd += add;
     }
@@ -1253,7 +1324,7 @@ ecoff_write_symhdr (abfd, debug, swap, where)
      file_ptr where;
 {
   HDRR * const symhdr = &debug->symbolic_header;
-  char *buff;
+  char *buff = NULL;
 
   ecoff_align_debug (abfd, debug, swap);
 
@@ -1263,6 +1334,8 @@ ecoff_write_symhdr (abfd, debug, swap, where)
 
   where += swap->external_hdr_size;
 
+  symhdr->magic = swap->sym_magic;
+
   /* Fill in the file offsets.  */
 #define SET(offset, count, size) \
   if (symhdr->count == 0) \
@@ -1286,13 +1359,25 @@ ecoff_write_symhdr (abfd, debug, swap, where)
   SET (cbExtOffset, iextMax, swap->external_ext_size);
 #undef SET
 
-  buff = (PTR) alloca (swap->external_hdr_size);
+  buff = (PTR) malloc (swap->external_hdr_size);
+  if (buff == NULL && swap->external_hdr_size != 0)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      goto error_return;
+    }
+
   (*swap->swap_hdr_out) (abfd, symhdr, buff);
   if (bfd_write (buff, 1, swap->external_hdr_size, abfd)
       != swap->external_hdr_size)
-    return false;
+    goto error_return;
 
+  if (buff != NULL)
+    free (buff);
   return true;
+ error_return:
+  if (buff != NULL)
+    free (buff);
+  return false;
 }
 
 /* Write out the ECOFF debugging information.  This function assumes
@@ -1375,10 +1460,20 @@ ecoff_write_shuffle (abfd, swap, shuffle, space)
       bfd_byte *s;
 
       i = swap->debug_align - (total & (swap->debug_align - 1));
-      s = (bfd_byte *) alloca (i);
-      memset (s, 0, i);
+      s = (bfd_byte *) malloc (i);
+      if (s == NULL && i != 0)
+       {
+         bfd_set_error (bfd_error_no_memory);
+         return false;
+       }
+
+      memset ((PTR) s, 0, i);
       if (bfd_write ((PTR) s, 1, i, abfd) != i)
-       return false;
+       {
+         free (s);
+         return false;
+       }
+      free (s);
     }
 
   return true;
@@ -1397,19 +1492,24 @@ bfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where)
      file_ptr where;
 {
   struct accumulate *ainfo = (struct accumulate *) handle;
-  PTR space;
+  PTR space = NULL;
 
   if (! ecoff_write_symhdr (abfd, debug, swap, where))
-    return false;
+    goto error_return;
 
-  space = (PTR) alloca (ainfo->largest_file_shuffle);
+  space = (PTR) malloc (ainfo->largest_file_shuffle);
+  if (space == NULL && ainfo->largest_file_shuffle != 0)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      goto error_return;
+    }
 
   if (! ecoff_write_shuffle (abfd, swap, ainfo->line, space)
       || ! ecoff_write_shuffle (abfd, swap, ainfo->pdr, space)
       || ! ecoff_write_shuffle (abfd, swap, ainfo->sym, space)
       || ! ecoff_write_shuffle (abfd, swap, ainfo->opt, space)
       || ! ecoff_write_shuffle (abfd, swap, ainfo->aux, space))
-    return false;
+    goto error_return;
 
   /* The string table is written out from the hash table if this is a
      final link.  */
@@ -1417,7 +1517,7 @@ bfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where)
     {
       BFD_ASSERT (ainfo->ss_hash == (struct string_hash_entry *) NULL);
       if (! ecoff_write_shuffle (abfd, swap, ainfo->ss, space))
-       return false;
+       goto error_return;
     }
   else
     {
@@ -1428,7 +1528,7 @@ bfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where)
       BFD_ASSERT (ainfo->ss == (struct shuffle *) NULL);
       null = 0;
       if (bfd_write ((PTR) &null, 1, 1, abfd) != 1)
-       return false;
+       goto error_return;
       total = 1;
       BFD_ASSERT (ainfo->ss_hash == NULL || ainfo->ss_hash->val == 1);
       for (sh = ainfo->ss_hash;
@@ -1439,7 +1539,7 @@ bfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where)
 
          len = strlen (sh->root.string);
          if (bfd_write ((PTR) sh->root.string, 1, len + 1, abfd) != len + 1)
-           return false;
+           goto error_return;
          total += len + 1;
        }
 
@@ -1449,10 +1549,19 @@ bfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where)
          bfd_byte *s;
 
          i = swap->debug_align - (total & (swap->debug_align - 1));
-         s = (bfd_byte *) alloca (i);
-         memset (s, 0, i);
+         s = (bfd_byte *) malloc (i);
+         if (s == NULL && i != 0)
+           {
+             bfd_set_error (bfd_error_no_memory);
+             goto error_return;
+           }
+         memset ((PTR) s, 0, i);
          if (bfd_write ((PTR) s, 1, i, abfd) != i)
-           return false;
+           {
+             free (s);
+             goto error_return;
+           }
+         free (s);
        }
     }
 
@@ -1460,7 +1569,7 @@ bfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where)
      shuffles.  FIXME: They probably should be.  */
   if (bfd_write (debug->ssext, 1, debug->symbolic_header.issExtMax, abfd)
       != debug->symbolic_header.issExtMax)
-    return false;
+    goto error_return;
   if ((debug->symbolic_header.issExtMax & (swap->debug_align - 1)) != 0)
     {
       int i;
@@ -1468,15 +1577,24 @@ bfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where)
 
       i = (swap->debug_align
           - (debug->symbolic_header.issExtMax & (swap->debug_align - 1)));
-      s = (bfd_byte *) alloca (i);
-      memset (s, 0, i);
+      s = (bfd_byte *) malloc (i);
+      if (s == NULL && i != 0)
+       {
+         bfd_set_error (bfd_error_no_memory);
+         goto error_return;
+       }
+      memset ((PTR) s, 0, i);
       if (bfd_write ((PTR) s, 1, i, abfd) != i)
-       return false;
+       {
+         free (s);
+         goto error_return;
+       }
+      free (s);
     }
 
   if (! ecoff_write_shuffle (abfd, swap, ainfo->fdr, space)
       || ! ecoff_write_shuffle (abfd, swap, ainfo->rfd, space))
-    return false;
+    goto error_return;
 
   BFD_ASSERT (debug->symbolic_header.cbExtOffset == 0
              || debug->symbolic_header.cbExtOffset == bfd_tell (abfd));
@@ -1484,7 +1602,14 @@ bfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where)
   if (bfd_write (debug->external_ext, swap->external_ext_size,
                 debug->symbolic_header.iextMax, abfd)
       != debug->symbolic_header.iextMax * swap->external_ext_size)
-    return false;
+    goto error_return;
 
+  if (space != NULL)
+    free (space);
   return true;
+
+ error_return:
+  if (space != NULL)
+    free (space);
+  return false;
 }
This page took 0.031272 seconds and 4 git commands to generate.