(do_relocs_for): Don't allocate storage or process relocs if there aren't any
authorKen Raeburn <raeburn@cygnus>
Tue, 23 Mar 1993 13:34:55 +0000 (13:34 +0000)
committerKen Raeburn <raeburn@cygnus>
Tue, 23 Mar 1993 13:34:55 +0000 (13:34 +0000)
relocs to process.  Avoids malloc/free bug on SCO too.

gas/config/obj-coffbfd.c

index c8b70603fc70eed60fbf076407295b61abc3a9e2..2cce1aebd88c7b503becae55765369225c1d64cf 100644 (file)
@@ -364,95 +364,108 @@ DEFUN (do_relocs_for, (abfd, h, file_cursor),
          fixS *fix_ptr = segment_info[idx].fix_root;
          nrelocs = count_entries_in_chain (idx);
 
-         external_reloc_size = nrelocs * RELSZ;
-         external_reloc_vec =
-           (struct external_reloc *) malloc (external_reloc_size);
-
-         ext_ptr = external_reloc_vec;
-
-         /* Fill in the internal coff style reloc struct from the
-            internal fix list.  */
-         while (fix_ptr)
+         if (nrelocs)
+           /* Bypass this stuff if no relocs.  This also incidentally
+              avoids a SCO bug, where free(malloc(0)) tends to crash.  */
            {
-             symbolS *symbol_ptr;
-             struct internal_reloc intr;
+             external_reloc_size = nrelocs * RELSZ;
+             external_reloc_vec =
+               (struct external_reloc *) malloc (external_reloc_size);
+
+             ext_ptr = external_reloc_vec;
 
-             /* Only output some of the relocations */
-             if (TC_COUNT_RELOC (fix_ptr))
+             /* Fill in the internal coff style reloc struct from the
+                internal fix list.  */
+             while (fix_ptr)
                {
+                 symbolS *symbol_ptr;
+                 struct internal_reloc intr;
+
+                 /* Only output some of the relocations */
+                 if (TC_COUNT_RELOC (fix_ptr))
+                   {
 #ifdef TC_RELOC_MANGLE
-                 TC_RELOC_MANGLE (fix_ptr, &intr, base);
+                     TC_RELOC_MANGLE (fix_ptr, &intr, base);
 
 #else
-                 symbolS *dot;
-                 symbol_ptr = fix_ptr->fx_addsy;
+                     symbolS *dot;
+                     symbol_ptr = fix_ptr->fx_addsy;
 
-                 intr.r_type = TC_COFF_FIX2RTYPE (fix_ptr);
-                 intr.r_vaddr =
-                   base + fix_ptr->fx_frag->fr_address + fix_ptr->fx_where;
+                     intr.r_type = TC_COFF_FIX2RTYPE (fix_ptr);
+                     intr.r_vaddr =
+                       base + fix_ptr->fx_frag->fr_address + fix_ptr->fx_where;
 
-                 intr.r_offset = fix_ptr->fx_offset;
+                     intr.r_offset = fix_ptr->fx_offset;
 
-                 intr.r_offset = 0;
+                     intr.r_offset = 0;
 
-                 /* Turn the segment of the symbol into an offset.  */
-                 if (symbol_ptr)
-                   {
-                     dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot;
-                     if (dot)
+                     /* Turn the segment of the symbol into an offset.  */
+                     if (symbol_ptr)
                        {
-                         intr.r_symndx = dot->sy_number;
+                         dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot;
+                         if (dot)
+                           {
+                             intr.r_symndx = dot->sy_number;
+                           }
+                         else
+                           {
+                             intr.r_symndx = symbol_ptr->sy_number;
+                           }
+
                        }
                      else
                        {
-                         intr.r_symndx = symbol_ptr->sy_number;
+                         intr.r_symndx = -1;
                        }
-
-                   }
-                 else
-                   {
-                     intr.r_symndx = -1;
-                   }
 #endif
 
-                 (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr);
-                 ext_ptr++;
+                     (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr);
+                     ext_ptr++;
 
 #if defined(TC_A29K)
 
-                 /* The 29k has a special kludge for the high 16 bit
-                    reloc.  Two relocations are emited, R_IHIHALF,
-                    and R_IHCONST. The second one doesn't contain a
-                    symbol, but uses the value for offset.  */
+                     /* The 29k has a special kludge for the high 16 bit
+                        reloc.  Two relocations are emited, R_IHIHALF,
+                        and R_IHCONST. The second one doesn't contain a
+                        symbol, but uses the value for offset.  */
 
-                 if (intr.r_type == R_IHIHALF)
-                   {
-                     /* now emit the second bit */
-                     intr.r_type = R_IHCONST;
-                     intr.r_symndx = fix_ptr->fx_addnumber;
-
-                     /* The offset to the segment holding the symbol
-                        has already been counted in the R_IHIHALF.
-                        We don't want to add it in again for the
-                        R_IHCONST.  */
-                     if (symbol_ptr)
-                       intr.r_symndx -=
-                         segment_info[S_GET_SEGMENT (symbol_ptr)].scnhdr.s_paddr;
-                     (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr);
-                     ext_ptr++;
-                   }
+                     if (intr.r_type == R_IHIHALF)
+                       {
+                         /* now emit the second bit */
+                         intr.r_type = R_IHCONST;
+                         intr.r_symndx = fix_ptr->fx_addnumber;
+
+                         /* The offset to the segment holding the symbol
+                            has already been counted in the R_IHIHALF.
+                            We don't want to add it in again for the
+                            R_IHCONST.  */
+                         if (symbol_ptr)
+                           intr.r_symndx -=
+                             segment_info[S_GET_SEGMENT (symbol_ptr)].scnhdr.s_paddr;
+                         (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr);
+                         ext_ptr++;
+                       }
 #endif
+                   }
+
+                 fix_ptr = fix_ptr->fx_next;
                }
 
-             fix_ptr = fix_ptr->fx_next;
-           }
+             /* Write out the reloc table */
+             bfd_write ((PTR) external_reloc_vec, 1, external_reloc_size,
+                        abfd);
+             free (external_reloc_vec);
 
-         /* Write out the reloc table */
-         segment_info[idx].scnhdr.s_relptr = nrelocs ? *file_cursor : 0;
-         segment_info[idx].scnhdr.s_nreloc = nrelocs;
-         bfd_write ((PTR) external_reloc_vec, 1, external_reloc_size, abfd);
-         *file_cursor += external_reloc_size;
-         free (external_reloc_vec);
+             /* Fill in section header info.  */
+             segment_info[idx].scnhdr.s_relptr = *file_cursor;
+             *file_cursor += external_reloc_size;
+           }
+         else
+           {
+             /* No relocs */
+             segment_info[idx].scnhdr.s_relptr = 0;
+           }
+         segment_info[idx].scnhdr.s_nreloc = 0;
        }
     }
   /* Set relocation_size field in file headers */