From Robin Kirkham <Robin.Kirkham@mlb.dmt.csiro.au>:
[deliverable/binutils-gdb.git] / bfd / cofflink.c
index c721bdf9de1fa75588eea9f1ee5e0baf0bedd939..58c6d94d6482ad9b56ec0cf53bf8faa26a64a315 100644 (file)
@@ -38,6 +38,7 @@ static char *dores_com PARAMS ((char *, bfd *, int));
 static char *get_name PARAMS ((char *, char **));
 static int process_embedded_commands
   PARAMS ((bfd *, struct bfd_link_info *, bfd *));
+static void mark_relocs PARAMS ((struct coff_final_link_info *, bfd *));
 
 /* Create an entry in a COFF linker hash table.  */
 
@@ -373,7 +374,8 @@ coff_link_add_symbols (abfd, info)
            {
              flags = BSF_EXPORT | BSF_GLOBAL;
              section = coff_section_from_bfd_index (abfd, sym.n_scnum);
-             value -= section->vma;
+             if (! obj_pe (abfd))
+               value -= section->vma;
            }
 
          if (! (bfd_coff_link_add_one_symbol
@@ -530,6 +532,7 @@ _bfd_coff_final_link (abfd, info)
   finfo.contents = NULL;
   finfo.external_relocs = NULL;
   finfo.internal_relocs = NULL;
+  finfo.global_to_static = false;
   debug_merge_allocated = false;
 
   coff_data (abfd)->link_info = info;
@@ -838,6 +841,18 @@ _bfd_coff_final_link (abfd, info)
        return false;
     }
 
+  /* If doing task linking (ld --task-link) then make a pass through the
+     global symbols, writing out any that are defined, and making them
+     static. */
+  if (info->task_link)
+    {
+      finfo.failed = false;
+      coff_link_hash_traverse (coff_hash_table (info), _bfd_coff_write_task_globals,
+                              (PTR) &finfo);
+      if (finfo.failed)
+       goto error_return;
+    }
+
   /* Write out the global symbols.  */
   finfo.failed = false;
   coff_link_hash_traverse (coff_hash_table (info), _bfd_coff_write_global_sym,
@@ -1551,9 +1566,10 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
            {
              isym.n_scnum = (*secpp)->output_section->target_index;
              isym.n_value += (*secpp)->output_offset;
+             if (! obj_pe (input_bfd))
+               isym.n_value -= (*secpp)->vma;
              if (! obj_pe (finfo->output_bfd))
-               isym.n_value += ((*secpp)->output_section->vma
-                                - (*secpp)->vma);
+               isym.n_value += (*secpp)->output_section->vma;
            }
 
          /* The value of a C_FILE symbol is the symbol index of the
@@ -1604,6 +1620,12 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
              finfo->last_file = isym;
            }
 
+         /* If doing task linking, convert normal global function symbols to
+            static functions. */
+
+         if (finfo->info->task_link && isym.n_sclass == C_EXT)
+           isym.n_sclass = C_STAT;
+
          /* Output the symbol.  */
 
          bfd_coff_swap_sym_out (output_bfd, (PTR) &isym, (PTR) outsym);
@@ -2290,6 +2312,18 @@ _bfd_coff_write_global_sym (h, data)
   if (isym.n_sclass == C_NULL)
     isym.n_sclass = C_EXT;
 
+  /* If doing task linking and this is the pass where we convert defined globals to
+     statics, then do that conversion now.  If the symbol is not being converted,
+     just ignore it and it will be output during a later pass. */
+  if (finfo->global_to_static)
+    {
+      if (isym.n_sclass != C_EXT)
+       {
+         return true;
+       }
+      isym.n_sclass = C_STAT;
+    }
+
   isym.n_numaux = h->numaux;
   
   bfd_coff_swap_sym_out (output_bfd, (PTR) &isym, (PTR) finfo->outsyms);
@@ -2328,6 +2362,33 @@ _bfd_coff_write_global_sym (h, data)
   return true;
 }
 
+/* Write out task global symbols, converting them to statics.  Called
+   via coff_link_hash_traverse.  Calls bfd_coff_write_global_sym to do
+   the dirty work, if the symbol we are processing needs conversion. */
+
+boolean
+_bfd_coff_write_task_globals (h, data)
+     struct coff_link_hash_entry *h;
+     PTR data;
+{
+  struct coff_final_link_info *finfo = (struct coff_final_link_info *) data;
+  boolean rtnval = true;
+
+  if (h->indx < 0)
+    {
+      switch (h->root.type)
+       {
+       case bfd_link_hash_defined:
+       case bfd_link_hash_defweak:
+         finfo->global_to_static = true;
+         rtnval = _bfd_coff_write_global_sym (h, data);
+         finfo->global_to_static = false;
+         break;
+       }
+    }
+  return (rtnval);
+}
+
 /* Handle a link order which is supposed to generate a reloc.  */
 
 boolean
@@ -2547,7 +2608,7 @@ _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
               val = (sec->output_section->vma
                     + sec->output_offset
                     + sym->n_value);
-             if (! obj_pe (output_bfd))
+             if (! obj_pe (input_bfd))
                val -= sec->vma;
            }
        }
@@ -2576,19 +2637,26 @@ _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
       if (info->base_file)
        {
          /* Emit a reloc if the backend thinks it needs it. */
-         if (sym && pe_data(output_bfd)->in_reloc_p(output_bfd, howto))
+         if (sym && pe_data (output_bfd)->in_reloc_p (output_bfd, howto))
            {
-             /* relocation to a symbol in a section which
-                isn't absolute - we output the address here 
-                to a file */
-             bfd_vma addr = rel->r_vaddr 
-               - input_section->vma 
-               + input_section->output_offset 
-                 + input_section->output_section->vma;
-             if (coff_data(output_bfd)->pe)
+             /* Relocation to a symbol in a section which isn't
+                absolute.  We output the address here to a file.
+                This file is then read by dlltool when generating the
+                reloc section.  Note that the base file is not
+                portable between systems.  We write out a long here,
+                and dlltool reads in a long.  */
+             long addr = (rel->r_vaddr 
+                          - input_section->vma 
+                          + input_section->output_offset 
+                          + input_section->output_section->vma);
+             if (coff_data (output_bfd)->pe)
                addr -= pe_data(output_bfd)->pe_opthdr.ImageBase;
-             /* FIXME: Shouldn't 4 be sizeof (addr)?  */
-             fwrite (&addr, 1,4, (FILE *) info->base_file);
+             if (fwrite (&addr, 1, sizeof (long), (FILE *) info->base_file)
+                 != sizeof (long))
+               {
+                 bfd_set_error (bfd_error_system_call);
+                 return false;
+               }
            }
        }
   
This page took 0.031423 seconds and 4 git commands to generate.