Support all of the V.4 relocations
[deliverable/binutils-gdb.git] / bfd / ecofflink.c
index 306f028e11637e0a9e25b7a2c8fcf57f46d4e000..2d1f99b8c8851e99199a9cc60d1ebbdb80e26a4d 100644 (file)
@@ -41,7 +41,7 @@ static boolean ecoff_write_symhdr PARAMS ((bfd *, struct ecoff_debug_info *,
                                           file_ptr where));
 
 /* Obstack allocation and deallocation routines.  */
-#define obstack_chunk_alloc bfd_xmalloc_by_size_t
+#define obstack_chunk_alloc malloc
 #define obstack_chunk_free free
 \f
 /* The minimum amount of data to allocate.  */
@@ -74,7 +74,7 @@ ecoff_add_bytes (buf, bufend, need)
     newbuf = (char *) realloc (*buf, have + want);
   if (newbuf == NULL)
     {
-      bfd_error = no_memory;
+      bfd_set_error (bfd_error_no_memory);
       return false;
     }
   *buf = newbuf;
@@ -115,14 +115,22 @@ string_hash_newfunc (entry, table, string)
   if (ret == (struct string_hash_entry *) NULL)
     ret = ((struct string_hash_entry *)
           bfd_hash_allocate (table, sizeof (struct string_hash_entry)));
+  if (ret == (struct string_hash_entry *) NULL)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return NULL;
+    }
 
   /* Call the allocation method of the superclass.  */
   ret = ((struct string_hash_entry *)
         bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
 
-  /* Initialize the local fields.  */
-  ret->val = -1;
-  ret->next = NULL;
+  if (ret)
+    {
+      /* Initialize the local fields.  */
+      ret->val = -1;
+      ret->next = NULL;
+    }
 
   return (struct bfd_hash_entry *) ret;
 }
@@ -197,12 +205,12 @@ struct accumulate
 
 /* Add a file entry to a shuffle list.  */
 
-static void add_file_shuffle PARAMS ((struct accumulate *,
+static boolean add_file_shuffle PARAMS ((struct accumulate *,
                                      struct shuffle **,
                                      struct shuffle **, bfd *, file_ptr,
                                      unsigned long));
 
-static void
+static boolean
 add_file_shuffle (ainfo, head, tail, input_bfd, offset, size)
      struct accumulate *ainfo;
      struct shuffle **head;
@@ -222,11 +230,16 @@ add_file_shuffle (ainfo, head, tail, input_bfd, offset, size)
       (*tail)->size += size;
       if ((*tail)->size > ainfo->largest_file_shuffle)
        ainfo->largest_file_shuffle = (*tail)->size;
-      return;
+      return true;
     }
 
   n = (struct shuffle *) obstack_alloc (&ainfo->memory,
                                        sizeof (struct shuffle));
+  if (!n)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return false;
+    }
   n->next = NULL;
   n->size = size;
   n->filep = true;
@@ -239,16 +252,17 @@ add_file_shuffle (ainfo, head, tail, input_bfd, offset, size)
   *tail = n;
   if (size > ainfo->largest_file_shuffle)
     ainfo->largest_file_shuffle = size;
+  return true;
 }
 
 /* Add a memory entry to a shuffle list.  */
 
-static void add_memory_shuffle PARAMS ((struct accumulate *,
-                                       struct shuffle **head,
-                                       struct shuffle **tail,
-                                       bfd_byte *data, unsigned long size));
+static boolean add_memory_shuffle PARAMS ((struct accumulate *,
+                                          struct shuffle **head,
+                                          struct shuffle **tail,
+                                          bfd_byte *data, unsigned long size));
 
-static void
+static boolean
 add_memory_shuffle (ainfo, head, tail, data, size)
      struct accumulate *ainfo;
      struct shuffle **head;
@@ -260,6 +274,11 @@ add_memory_shuffle (ainfo, head, tail, data, size)
      
   n = (struct shuffle *) obstack_alloc (&ainfo->memory,
                                        sizeof (struct shuffle));
+  if (!n)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return false;
+    }
   n->next = NULL;
   n->size = size;
   n->filep = false;
@@ -269,6 +288,7 @@ add_memory_shuffle (ainfo, head, tail, data, size)
   if (*tail != (struct shuffle *) NULL)
     (*tail)->next = n;
   *tail = n;
+  return true;
 }
 
 /* Initialize the FDR hash table.  This returns a handle which is then
@@ -284,7 +304,12 @@ bfd_ecoff_debug_init (output_bfd, output_debug, output_swap, info)
 {
   struct accumulate *ainfo;
 
-  ainfo = (struct accumulate *) bfd_xmalloc (sizeof (struct accumulate));
+  ainfo = (struct accumulate *) malloc (sizeof (struct accumulate));
+  if (!ainfo)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return NULL;
+    }
   if (! bfd_hash_table_init_n (&ainfo->fdr_hash.table, string_hash_newfunc,
                               1021))
     return NULL;
@@ -319,7 +344,11 @@ bfd_ecoff_debug_init (output_bfd, output_debug, output_swap, info)
       output_debug->symbolic_header.issMax = 1;
     }
 
-  obstack_begin (&ainfo->memory, 4050);
+  if (!obstack_begin (&ainfo->memory, 4050))
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return NULL;
+    }
 
   return (PTR) ainfo;
 }
@@ -447,7 +476,13 @@ bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
 
   sz = (input_symhdr->crfd + input_symhdr->ifdMax) * external_rfd_size;
   rfd_out = (bfd_byte *) obstack_alloc (&ainfo->memory, sz);
-  add_memory_shuffle (ainfo, &ainfo->rfd, &ainfo->rfd_end, rfd_out, sz);
+  if (!input_debug->ifdmap || !rfd_out)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return false;
+    }
+  if (!add_memory_shuffle (ainfo, &ainfo->rfd, &ainfo->rfd_end, rfd_out, sz))
+    return false;
 
   copied = 0;
 
@@ -484,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;
 
@@ -537,12 +579,19 @@ bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
      information.  */
   sz = copied * external_fdr_size;
   fdr_out = (bfd_byte *) obstack_alloc (&ainfo->memory, sz);
-  add_memory_shuffle (ainfo, &ainfo->fdr, &ainfo->fdr_end, fdr_out, sz);
+  if (!fdr_out)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return false;
+    }
+  if (!add_memory_shuffle (ainfo, &ainfo->fdr, &ainfo->fdr_end, fdr_out, sz))
+    return false;
   for (fdr_ptr = fdr_start, i = 0;
        fdr_ptr < fdr_end;
        fdr_ptr += fdr_add, i++)
     {
       FDR fdr;
+      bfd_vma fdr_adr;
       bfd_byte *sym_out;
       bfd_byte *lraw_src;
       bfd_byte *lraw_end;
@@ -559,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.  */
@@ -569,7 +634,14 @@ bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
       fgotfilename = false;
       sz = fdr.csym * external_sym_size;
       sym_out = (bfd_byte *) obstack_alloc (&ainfo->memory, sz);
-      add_memory_shuffle (ainfo, &ainfo->sym, &ainfo->sym_end, sym_out, sz);
+      if (!sym_out)
+       {
+         bfd_set_error (bfd_error_no_memory);
+         return false;
+       }
+      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);
       lraw_end = lraw_src + fdr.csym * input_swap->external_sym_size;
@@ -594,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;
 
@@ -656,12 +741,18 @@ 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)
        {
-         add_file_shuffle (ainfo, &ainfo->line, &ainfo->line_end,
-                           input_bfd,
-                           input_symhdr->cbLineOffset + fdr.cbLineOffset,
-                           fdr.cbLine);
+         if (!add_file_shuffle (ainfo, &ainfo->line, &ainfo->line_end,
+                                input_bfd,
+                                input_symhdr->cbLineOffset + fdr.cbLineOffset,
+                                fdr.cbLine))
+           return false;
          fdr.ilineBase = output_symhdr->ilineMax;
          fdr.cbLineOffset = output_symhdr->cbLine;
          output_symhdr->ilineMax += fdr.cline;
@@ -669,11 +760,12 @@ bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
        }
       if (fdr.caux > 0)
        {
-         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));
+         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)))
+           return false;
          fdr.iauxBase = output_symhdr->iauxMax;
          output_symhdr->iauxMax += fdr.caux;
        }
@@ -689,33 +781,42 @@ bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
        }
       else if (fdr.cbSs > 0)
        {
-         add_file_shuffle (ainfo, &ainfo->ss, &ainfo->ss_end,
-                           input_bfd,
-                           input_symhdr->cbSsOffset + fdr.issBase,
-                           fdr.cbSs);
+         if (!add_file_shuffle (ainfo, &ainfo->ss, &ainfo->ss_end,
+                                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)
-           add_file_shuffle (ainfo, &ainfo->pdr, &ainfo->pdr_end,
-                             input_bfd,
-                             (input_symhdr->cbPdOffset
-                              + fdr.ipdFirst * external_pdr_size),
-                             fdr.cpd * external_pdr_size);
+           {
+             if (!add_file_shuffle (ainfo, &ainfo->pdr, &ainfo->pdr_end,
+                                    input_bfd,
+                                    (input_symhdr->cbPdOffset
+                                     + fdr.ipdFirst * external_pdr_size),
+                                    fdr.cpd * external_pdr_size))
+               return false;
+           }
          BFD_ASSERT (external_opt_size == input_swap->external_opt_size);
          if (fdr.copt > 0)
-           add_file_shuffle (ainfo, &ainfo->opt, &ainfo->opt_end,
-                             input_bfd,
-                             (input_symhdr->cbOptOffset
-                              + fdr.ioptBase * external_opt_size),
-                             fdr.copt * external_opt_size);
+           {
+             if (!add_file_shuffle (ainfo, &ainfo->opt, &ainfo->opt_end,
+                                    input_bfd,
+                                    (input_symhdr->cbOptOffset
+                                     + fdr.ioptBase * external_opt_size),
+                                    fdr.copt * external_opt_size))
+               return false;
+           }
        }
       else
        {
@@ -734,12 +835,36 @@ bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
          end = in + fdr.cpd * insz;
          sz = fdr.cpd * outsz;
          out = (bfd_byte *) obstack_alloc (&ainfo->memory, sz);
-         add_memory_shuffle (ainfo, &ainfo->pdr, &ainfo->pdr_end, out, sz);
+         if (!out)
+           {
+             bfd_set_error (bfd_error_no_memory);
+             return false;
+           }
+         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);
            }
 
@@ -751,7 +876,14 @@ bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
          end = in + fdr.copt * insz;
          sz = fdr.copt * outsz;
          out = (bfd_byte *) obstack_alloc (&ainfo->memory, sz);
-         add_memory_shuffle (ainfo, &ainfo->opt, &ainfo->opt_end, out, sz);
+         if (!out)
+           {
+             bfd_set_error (bfd_error_no_memory);
+             return false;
+           }
+         if (!add_memory_shuffle (ainfo, &ainfo->opt, &ainfo->opt_end, out,
+                                  sz))
+           return false;
          for (; in < end; in += insz, out += outsz)
            {
              OPTR opt;
@@ -810,8 +942,9 @@ ecoff_add_string (ainfo, info, debug, fdr, string)
   len = strlen (string);
   if (info->relocateable)
     {
-      add_memory_shuffle (ainfo, &ainfo->ss, &ainfo->ss_end, (PTR) string,
-                         len + 1);
+      if (!add_memory_shuffle (ainfo, &ainfo->ss, &ainfo->ss_end, (PTR) string,
+                              len + 1))
+       return -1;
       ret = symhdr->issMax;
       symhdr->issMax += len + 1;
       fdr->cbSs += len + 1;
@@ -822,7 +955,7 @@ ecoff_add_string (ainfo, info, debug, fdr, string)
 
       sh = string_hash_lookup (&ainfo->str_hash, string, true, true);
       if (sh == (struct string_hash_entry *) NULL)
-       return (bfd_size_type) -1;
+       return -1;
       if (sh->val == -1)
        {
          sh->val = symhdr->issMax;
@@ -861,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)
@@ -883,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_error = no_memory;
+      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.  */
@@ -902,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);
 
@@ -921,6 +1061,11 @@ bfd_ecoff_debug_accumulate_other (handle, output_bfd, output_debug,
 
       external_sym = (PTR) obstack_alloc (&ainfo->memory,
                                          output_swap->external_sym_size);
+      if (!external_sym)
+       {
+         bfd_set_error (bfd_error_no_memory);
+         return false;
+       }
       (*swap_sym_out) (output_bfd, &internal_sym, external_sym);
       add_memory_shuffle (ainfo, &ainfo->sym, &ainfo->sym_end,
                          external_sym, output_swap->external_sym_size);
@@ -936,6 +1081,11 @@ bfd_ecoff_debug_accumulate_other (handle, output_bfd, output_debug,
      it only applies to aux fields and there are none.  */
   external_fdr = (PTR) obstack_alloc (&ainfo->memory,
                                      output_swap->external_fdr_size);
+  if (!external_fdr)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return false;
+    }
   (*output_swap->swap_fdr_out) (output_bfd, &fdr, external_fdr);
   add_memory_shuffle (ainfo, &ainfo->fdr, &ainfo->fdr_end,
                      external_fdr, output_swap->external_fdr_size);
@@ -1089,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;
     }
 
@@ -1097,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;
     }
 
@@ -1105,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;
     }
 
@@ -1113,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;
     }
@@ -1122,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;
     }
@@ -1174,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);
 
@@ -1184,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) \
@@ -1207,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
@@ -1296,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;
@@ -1318,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.  */
@@ -1338,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
     {
@@ -1349,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;
@@ -1360,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;
        }
 
@@ -1370,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);
        }
     }
 
@@ -1381,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;
@@ -1389,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));
@@ -1405,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.034398 seconds and 4 git commands to generate.