]> Git Repo - binutils.git/blobdiff - bfd/xcofflink.c
Cosmetic improvements
[binutils.git] / bfd / xcofflink.c
index 47ab49fdb6b8a4be9f4e18192495176c0834ec96..33251b1bd06e7014fb713fb1a306d7d861f53380 100644 (file)
@@ -25,10 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "coff/internal.h"
 #include "libcoff.h"
 
-/* This file holds the XCOFF linker code.  A lot of it is very similar
-   to the COFF linker code.  However, it is different enough that I
-   chose to avoid trying to hack up the COFF code to support XCOFF.
-   That leads to a certain amount of duplicated code, alas.  */
+/* This file holds the XCOFF linker code.  */
 
 #define STRING_SIZE_SIZE (4)
 
@@ -1032,6 +1029,14 @@ xcoff_link_add_symbols (abfd, info)
              bfd_size_type linoff;
 
              enclosing = xcoff_section_data (abfd, csect)->enclosing;
+             if (enclosing == NULL)
+               {
+                 (*_bfd_error_handler)
+                   ("%s: `%s' has line numbers but no enclosing section",
+                    bfd_get_filename (abfd), name);
+                 bfd_set_error (bfd_error_bad_value);
+                 goto error_return;
+               }
              linoff = (auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr
                        - enclosing->line_filepos);
              if (linoff < enclosing->lineno_count * linesz)
@@ -1208,34 +1213,47 @@ xcoff_link_add_symbols (abfd, info)
                                                                relbuf);
                      if (relname == NULL)
                        goto error_return;
-                     copy = (! info->keep_memory
-                             || relsym._n._n_n._n_zeroes != 0
-                             || relsym._n._n_n._n_offset == 0);
-                     h = xcoff_link_hash_lookup (xcoff_hash_table (info),
-                                                 relname, true, copy, false);
-                     if (h == NULL)
-                       goto error_return;
 
-                     /* At this point h->root.type could be
-                        bfd_link_hash_new.  That should be OK, since
-                        we know for sure that we will come across
-                        this symbol as we step through the file.  */
-
-                     /* We store h in *sym_hash for the convenience
-                        of the relocate_section function.  */
-                     *sym_hash = h;
-
-                     if (h->toc_section != NULL)
+                     /* We only merge TOC entries if the TC name is
+                         the same as the symbol name.  This handles
+                         the normal case, but not common cases like
+                         SYM.P4 which gcc generates to store SYM + 4
+                         in the TOC.  FIXME.  */
+                     if (strcmp (name, relname) == 0)
                        {
-                         /* We already have a TOC entry for this
-                            symbol, so we can just ignore this one.  */
-                         *rel_csect = bfd_und_section_ptr;
-                         break;
-                       }
+                         copy = (! info->keep_memory
+                                 || relsym._n._n_n._n_zeroes != 0
+                                 || relsym._n._n_n._n_offset == 0);
+                         h = xcoff_link_hash_lookup (xcoff_hash_table (info),
+                                                     relname, true, copy,
+                                                     false);
+                         if (h == NULL)
+                           goto error_return;
+
+                         /* At this point h->root.type could be
+                            bfd_link_hash_new.  That should be OK,
+                            since we know for sure that we will come
+                            across this symbol as we step through the
+                            file.  */
+
+                         /* We store h in *sym_hash for the
+                            convenience of the relocate_section
+                            function.  */
+                         *sym_hash = h;
+
+                         if (h->toc_section != NULL)
+                           {
+                             /* We already have a TOC entry for this
+                                symbol, so we can just ignore this
+                                one.  */
+                             *rel_csect = bfd_und_section_ptr;
+                             break;
+                           }
 
-                     /* We are about to create a TOC entry for this
-                        symbol.  */
-                     set_toc = h;
+                         /* We are about to create a TOC entry for
+                            this symbol.  */
+                         set_toc = h;
+                       }
                    }
                }
            }
@@ -1310,6 +1328,8 @@ xcoff_link_add_symbols (abfd, info)
                goto error_return;
              }
            xcoff_section_data (abfd, csect)->enclosing = enclosing;
+           xcoff_section_data (abfd, csect)->lineno_count =
+             enclosing->lineno_count;
 
            /* XCOFF requires that relocs be sorted by address, so we
                could do a binary search here.  FIXME.  (XCOFF
@@ -1421,7 +1441,7 @@ xcoff_link_add_symbols (abfd, info)
          csect = bfd_make_section_anyway (abfd, ".bss");
          if (csect == NULL)
            goto error_return;
-         csect->vma = 0;
+         csect->vma = sym.n_value;
          csect->_raw_size = aux.x_csect.x_scnlen.l;
          csect->flags |= SEC_ALLOC;
          csect->alignment_power = SMTYP_ALIGN (aux.x_csect.x_smtyp);
@@ -1514,6 +1534,21 @@ xcoff_link_add_symbols (abfd, info)
                  (struct bfd_link_hash_entry **) sym_hash)))
            goto error_return;
 
+         if (smtyp == XTY_CM)
+           {
+             if ((*sym_hash)->root.type != bfd_link_hash_common
+                 || (*sym_hash)->root.u.c.p->section != csect)
+               {
+                 /* We don't need the common csect we just created.  */
+                 csect->_raw_size = 0;
+               }
+             else
+               {
+                 (*sym_hash)->root.u.c.p->alignment_power
+                    = csect->alignment_power;
+               }
+           }
+
          if (info->hash->creator == abfd->xvec)
            {
              int flag;
@@ -1564,75 +1599,49 @@ xcoff_link_add_symbols (abfd, info)
                  goto error_return;
                }
 
-             /* We need to copy all relocs which are not PC relative
-                and not TOC relative into the .loader section.
-
-                We also identify all symbols which are called, so
-                that we can create glue code for calls to functions
-                imported from dynamic objects.  */
-
+             /* We identify all symbols which are called, so that we
+                can create glue code for calls to functions imported
+                from dynamic objects.  */
              if (info->hash->creator == abfd->xvec
-                 && *rel_csect != bfd_und_section_ptr)
+                 && *rel_csect != bfd_und_section_ptr
+                 && (rel->r_type == R_BR
+                     || rel->r_type == R_RBR)
+                 && obj_xcoff_sym_hashes (abfd)[rel->r_symndx] != NULL)
                {
                  struct xcoff_link_hash_entry *h;
 
-                 switch (rel->r_type)
+                 h = obj_xcoff_sym_hashes (abfd)[rel->r_symndx];
+                 h->flags |= XCOFF_CALLED;
+                 /* If the symbol name starts with a period, it is
+                     the code of a function.  If the symbol is
+                     currently undefined, then add an undefined symbol
+                     for the function descriptor.  This should do no
+                     harm, because any regular object that defines the
+                     function should also define the function
+                     descriptor.  It helps, because it means that we
+                     will identify the function descriptor with a
+                     dynamic object if a dynamic object defines it.  */
+                 if (h->root.root.string[0] == '.'
+                     && h->descriptor == NULL)
                    {
-                   default:
-                     break;
-                   case R_POS:
-                   case R_NEG:
-                   case R_RL:
-                   case R_RLA:
-                     ++xcoff_hash_table (info)->ldrel_count;
-                     ++xcoff_section_data (abfd, *rel_csect)->ldrel_count;
-                     h = obj_xcoff_sym_hashes (abfd)[rel->r_symndx];
-                     if (h != NULL)
-                       h->flags |= XCOFF_LDREL;
-                     break;
-                   case R_BR:
-                   case R_RBR:
-                     h = obj_xcoff_sym_hashes (abfd)[rel->r_symndx];
-                     if (h != NULL)
+                     struct xcoff_link_hash_entry *hds;
+
+                     hds = xcoff_link_hash_lookup (xcoff_hash_table (info),
+                                                   h->root.root.string + 1,
+                                                   true, false, true);
+                     if (hds == NULL)
+                       goto error_return;
+                     if (hds->root.type == bfd_link_hash_new)
                        {
-                         h->flags |= XCOFF_CALLED;
-                         /* If the symbol name starts with a period,
-                             it is the code of a function.  If the
-                             symbol is currently undefined, then add
-                             an undefined symbol for the function
-                             descriptor.  This should do no harm,
-                             because any regular object that defines
-                             the function should also define the
-                             function descriptor.  It helps, because
-                             it means that we will identify the
-                             function descriptor with a dynamic object
-                             if a dynamic object defines it.  */
-                         if (h->root.root.string[0] == '.'
-                             && h->descriptor == NULL)
-                           {
-                             struct xcoff_link_hash_entry *hds;
-
-                             hds = (xcoff_link_hash_lookup
-                                    (xcoff_hash_table (info),
-                                     h->root.root.string + 1, true, false,
-                                     true));
-                             if (hds == NULL)
-                               goto error_return;
-                             if (hds->root.type == bfd_link_hash_new)
-                               {
-                                 if (! (_bfd_generic_link_add_one_symbol
-                                        (info, abfd, hds->root.root.string,
-                                         (flagword) 0, bfd_und_section_ptr,
-                                         (bfd_vma) 0, (const char *) NULL,
-                                         false, false,
-                                         ((struct bfd_link_hash_entry **)
-                                          NULL))))
-                                   goto error_return;
-                               }
-                             h->descriptor = hds;
-                           }
+                         if (! (_bfd_generic_link_add_one_symbol
+                                (info, abfd, hds->root.root.string,
+                                 (flagword) 0, bfd_und_section_ptr,
+                                 (bfd_vma) 0, (const char *) NULL, false,
+                                 false,
+                                 (struct bfd_link_hash_entry **) NULL)))
+                           goto error_return;
                        }
-                     break;
+                     h->descriptor = hds;
                    }
                }
            }
@@ -1763,10 +1772,12 @@ xcoff_link_add_dynamic_symbols (abfd, info)
 
              /* If the symbol is undefined, and the current BFD is
                 not a dynamic object, change the BFD to this dynamic
-                object, so that we can get the import file ID
-                correctly.  */
-             if (h->root.u.undef.abfd == NULL
-                 || (h->root.u.undef.abfd->flags & DYNAMIC) == 0)
+                object, so that we can get the correct import file
+                ID.  */
+             if ((h->root.type == bfd_link_hash_undefined
+                  || h->root.type == bfd_link_hash_undefweak)
+                 && (h->root.u.undef.abfd == NULL
+                     || (h->root.u.undef.abfd->flags & DYNAMIC) == 0))
                h->root.u.undef.abfd = abfd;
 
              if (h->smclas == XMC_UA
@@ -1989,6 +2000,7 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
   size_t impsize, impcount;
   struct xcoff_import_file *fl;
   struct internal_ldhdr *ldhdr;
+  bfd_size_type stoff;
   register char *out;
   asection *sec;
   bfd *sub;
@@ -2013,7 +2025,13 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
   hentry = xcoff_link_hash_lookup (xcoff_hash_table (info), entry,
                                   false, false, true);
   if (hentry != NULL)
-    hentry->flags |= XCOFF_ENTRY;
+    {
+      hentry->flags |= XCOFF_ENTRY;
+      if (hentry->root.type == bfd_link_hash_defined
+         || hentry->root.type == bfd_link_hash_defweak)
+       xcoff_data (output_bfd)->entry_section =
+         hentry->root.u.def.section->output_section;
+    }
 
   /* Garbage collect unused sections.  */
   if (info->relocateable
@@ -2024,6 +2042,22 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
     {
       gc = false;
       xcoff_hash_table (info)->gc = false;
+
+      /* We still need to call xcoff_mark, in order to set ldrel_count
+         correctly.  */
+      for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+       {
+         asection *o;
+
+         for (o = sub->sections; o != NULL; o = o->next)
+           {
+             if ((o->flags & SEC_MARK) == 0)
+               {
+                 if (! xcoff_mark (info, o))
+                   goto error_return;
+               }
+           }
+       }
     }
   else
     {
@@ -2072,12 +2106,16 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
                     + ldhdr->l_nsyms * LDSYMSZ
                     + ldhdr->l_nreloc * LDRELSZ);
   ldhdr->l_stlen = ldinfo.string_size;
-  ldhdr->l_stoff = ldhdr->l_impoff + impsize;
+  stoff = ldhdr->l_impoff + impsize;
+  if (ldinfo.string_size == 0)
+    ldhdr->l_stoff = 0;
+  else
+    ldhdr->l_stoff = stoff;
 
   /* We now know the final size of the .loader section.  Allocate
      space for it.  */
   lsec = xcoff_hash_table (info)->loader_section;
-  lsec->_raw_size = ldhdr->l_stoff + ldhdr->l_stlen;
+  lsec->_raw_size = stoff + ldhdr->l_stlen;
   lsec->contents = (bfd_byte *) bfd_zalloc (output_bfd, lsec->_raw_size);
   if (lsec->contents == NULL)
     {
@@ -2110,8 +2148,7 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
        ;
     }
 
-  BFD_ASSERT ((bfd_size_type) ((bfd_byte *) out - lsec->contents)
-             == ldhdr->l_stoff);
+  BFD_ASSERT ((bfd_size_type) ((bfd_byte *) out - lsec->contents) == stoff);
 
   /* Set up the symbol string table.  */
   if (ldinfo.string_size > 0)
@@ -2270,7 +2307,10 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
 }
 
 /* The mark phase of garbage collection.  For a given section, mark
-   it, and all the sections which define symbols to which it refers.  */
+   it, and all the sections which define symbols to which it refers.
+   Because this function needs to look at the relocs, we also count
+   the number of relocs which need to be copied into the .loader
+   section.  */
 
 static boolean
 xcoff_mark (info, sec)
@@ -2379,6 +2419,41 @@ xcoff_mark (info, sec)
                  if (! xcoff_mark (info, rsec))
                    return false;
                }
+
+             /* See if this reloc needs to be copied into the .loader
+                 section.  */
+             switch (rel->r_type)
+               {
+               default:
+                 if (h == NULL
+                     || h->root.type == bfd_link_hash_defined
+                     || h->root.type == bfd_link_hash_defweak
+                     || h->root.type == bfd_link_hash_common
+                     || ((h->flags & XCOFF_CALLED) != 0
+                         && (h->flags & XCOFF_DEF_REGULAR) == 0
+                         && (h->flags & XCOFF_REF_DYNAMIC) != 0
+                         && (h->root.type == bfd_link_hash_undefined
+                             || h->root.type == bfd_link_hash_undefweak)
+                         && h->root.root.string[0] == '.'))
+                   break;
+                 /* Fall through.  */
+               case R_POS:
+               case R_NEG:
+               case R_RL:
+               case R_RLA:
+                 ++xcoff_hash_table (info)->ldrel_count;
+                 if (h != NULL)
+                   h->flags |= XCOFF_LDREL;
+                 break;
+               case R_TOC:
+               case R_GL:
+               case R_TCL:
+               case R_TRL:
+               case R_TRLA:
+                 /* We should never need a .loader reloc for a TOC
+                    relative reloc.  */
+                 break;
+               }
            }
 
          if (! info->keep_memory
@@ -2427,10 +2502,6 @@ xcoff_sweep (info)
                  o->_raw_size = 0;
                  o->reloc_count = 0;
                  o->lineno_count = 0;
-                 if (coff_section_data (sub, o) != NULL
-                     && xcoff_section_data (sub, o) != NULL)
-                   xcoff_hash_table (info)->ldrel_count -=
-                     xcoff_section_data (sub, o)->ldrel_count;
                }
            }
        }
@@ -2506,11 +2577,12 @@ xcoff_build_ldsyms (h, p)
 
   /* We need to add a symbol to the .loader section if it is mentioned
      in a reloc which we are copying to the .loader section and it was
-     not defined, or if it is the entry point.  */
+     not defined or common, or if it is the entry point.  */
 
   if (((h->flags & XCOFF_LDREL) == 0
        || h->root.type == bfd_link_hash_defined
-       || h->root.type == bfd_link_hash_defweak)
+       || h->root.type == bfd_link_hash_defweak
+       || h->root.type == bfd_link_hash_common)
       && (h->flags & XCOFF_ENTRY) == 0)
     {
       h->ldsym = NULL;
@@ -2646,6 +2718,7 @@ _bfd_xcoff_bfd_final_link (abfd, info)
                  + xcoff_hash_table (info)->ldhdr.l_nsyms * LDSYMSZ));
 
   xcoff_data (abfd)->coff.link_info = info;
+  xcoff_data (abfd)->full_aouthdr = true;
 
   finfo.strtab = _bfd_stringtab_init ();
   if (finfo.strtab == NULL)
@@ -2714,13 +2787,7 @@ _bfd_xcoff_bfd_final_link (abfd, info)
              code knows what compute_section_file_positions is going
              to do.  */
          sofar = bfd_coff_filhsz (abfd);
-         if ((abfd->flags & EXEC_P) != 0)
-           sofar += bfd_coff_aoutsz (abfd);
-         else
-           {
-             /* FIXME.  */
-             sofar += 28;
-           }
+         sofar += bfd_coff_aoutsz (abfd);
          sofar += abfd->section_count * bfd_coff_scnhsz (abfd);
 
          for (o = abfd->sections; o != NULL; o = o->next)
@@ -2779,6 +2846,12 @@ _bfd_xcoff_bfd_final_link (abfd, info)
                max_contents_size = sec->_raw_size;
              if (sec->lineno_count > max_lineno_count)
                max_lineno_count = sec->lineno_count;
+             if (coff_section_data (sec->owner, sec) != NULL
+                 && xcoff_section_data (sec->owner, sec) != NULL
+                 && (xcoff_section_data (sec->owner, sec)->lineno_count
+                     > max_lineno_count))
+               max_lineno_count =
+                 xcoff_section_data (sec->owner, sec)->lineno_count;
              if (sec->reloc_count > max_reloc_count)
                max_reloc_count = sec->reloc_count;
            }
@@ -3197,13 +3270,14 @@ xcoff_link_input_bfd (finfo, input_bfd)
   bfd_size_type linesz;
   bfd_byte *esym;
   bfd_byte *esym_end;
+  struct xcoff_link_hash_entry **sym_hash;
   struct internal_syment *isymp;
   asection **csectpp;
   unsigned long *debug_index;
   long *indexp;
   unsigned long output_index;
   bfd_byte *outsym;
-  struct xcoff_link_hash_entry **sym_hash;
+  asection *oline;
   boolean keep_syms;
   asection *o;
 
@@ -3248,6 +3322,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
   indexp = finfo->sym_indices;
   output_index = syment_base;
   outsym = finfo->outsyms;
+  oline = NULL;
 
   while (esym < esym_end)
     {
@@ -3398,6 +3473,8 @@ xcoff_link_input_bfd (finfo, input_bfd)
                 + (*csectpp)->output_offset
                 + isym.n_value
                 - (*csectpp)->vma);
+             xcoff_data (finfo->output_bfd)->toc_section =
+               (*csectpp)->output_section;
              require = true;
            }
        }
@@ -3419,7 +3496,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
       if (! skip
          && isym.n_sclass == C_EXT
          && smtyp == XTY_CM
-         && ((*sym_hash)->flags & XCOFF_DEF_REGULAR) != 0)
+         && (*sym_hash)->root.type != bfd_link_hash_common)
        skip = true;
 
       /* Skip local symbols if we are discarding them.  */
@@ -3509,26 +3586,9 @@ xcoff_link_input_bfd (finfo, input_bfd)
                }
            }
 
-         if (isym.n_sclass == C_BSTAT)
-           {
-             unsigned long indx;
-
-             /* The value of a C_BSTAT symbol is the symbol table
-                 index of the containing csect.  */
-
-             indx = isym.n_value;
-             if (indx < obj_raw_syment_count (input_bfd))
-               {
-                 long symindx;
-
-                 symindx = finfo->sym_indices[indx];
-                 if (symindx < 0)
-                   isym.n_value = 0;
-                 else
-                   isym.n_value = symindx;
-               }
-           }
-         else if (isym.n_scnum > 0)
+         if (isym.n_sclass != C_BSTAT
+             && isym.n_sclass != C_ESTAT
+             && isym.n_scnum > 0)
            {
              isym.n_scnum = (*csectpp)->output_section->target_index;
              isym.n_value += ((*csectpp)->output_section->vma
@@ -3613,9 +3673,10 @@ xcoff_link_input_bfd (finfo, input_bfd)
        *indexp++ = -1;
     }
 
-  /* Fix up the aux entries.  This must be done in a separate pass,
-     because we don't know the correct symbol indices until we have
-     already decided which symbols we are going to keep.  */
+  /* Fix up the aux entries and the C_BSTAT symbols.  This must be
+     done in a separate pass, because we don't know the correct symbol
+     indices until we have already decided which symbols we are going
+     to keep.  */
 
   esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
   esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
@@ -3635,6 +3696,27 @@ xcoff_link_input_bfd (finfo, input_bfd)
        {
          int i;
 
+         if (isymp->n_sclass == C_BSTAT)
+           {
+             unsigned long indx;
+
+             /* The value of a C_BSTAT symbol is the symbol table
+                 index of the containing csect.  */
+             indx = isymp->n_value;
+             if (indx < obj_raw_syment_count (input_bfd))
+               {
+                 long symindx;
+
+                 symindx = finfo->sym_indices[indx];
+                 if (symindx < 0)
+                   isymp->n_value = 0;
+                 else
+                   isymp->n_value = symindx;
+                 bfd_coff_swap_sym_out (output_bfd, (PTR) isymp,
+                                        (PTR) outsym);
+               }
+           }
+
          esym += isymesz;
          outsym += osymesz;
 
@@ -3757,24 +3839,30 @@ xcoff_link_input_bfd (finfo, input_bfd)
                  else
                    {
                      asection *enclosing;
+                     unsigned int enc_count;
                      bfd_size_type linoff;
                      struct internal_lineno lin;
 
                      o = *csectpp;
                      enclosing = xcoff_section_data (abfd, o)->enclosing;
+                     enc_count = xcoff_section_data (abfd, o)->lineno_count;
+                     if (oline != enclosing)
+                       {
+                         if (bfd_seek (input_bfd,
+                                       enclosing->line_filepos,
+                                       SEEK_SET) != 0
+                             || (bfd_read (finfo->linenos, linesz,
+                                           enc_count, input_bfd)
+                                 != linesz * enc_count))
+                           return false;
+                         oline = enclosing;
+                       }
+
                      linoff = (aux.x_sym.x_fcnary.x_fcn.x_lnnoptr
                                - enclosing->line_filepos);
 
-                     if (bfd_seek (input_bfd,
-                                   enclosing->line_filepos + linoff,
-                                   SEEK_SET != 0)
-                         || (bfd_read (finfo->linenos, linesz,
-                                       o->lineno_count, input_bfd)
-                             != linesz * o->lineno_count))
-                       return false;
-
                      bfd_coff_swap_lineno_in (input_bfd,
-                                              (PTR) finfo->linenos,
+                                              (PTR) (finfo->linenos + linoff),
                                               (PTR) &lin);
                      if (lin.l_lnno != 0
                          || ((bfd_size_type) lin.l_addr.l_symndx
@@ -3792,14 +3880,15 @@ xcoff_link_input_bfd (finfo, input_bfd)
 
                          lin.l_addr.l_symndx = *indexp;
                          bfd_coff_swap_lineno_out (output_bfd, (PTR) &lin,
-                                                   (PTR) finfo->linenos);
+                                                   (PTR) (finfo->linenos
+                                                          + linoff));
 
                          linpend = (finfo->linenos
-                                    + o->lineno_count * linesz);
+                                    + enc_count * linesz);
                          offset = (o->output_section->vma
                                    + o->output_offset
                                    - o->vma);
-                         for (linp = finfo->linenos + linesz;
+                         for (linp = finfo->linenos + linoff + linesz;
                               linp < linpend;
                               linp += linesz)
                            {
@@ -3813,7 +3902,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
                                                        (PTR) linp);
                            }
 
-                         count = (linp - finfo->linenos) / linesz;
+                         count = (linp - (finfo->linenos + linoff)) / linesz;
 
                          aux.x_sym.x_fcnary.x_fcn.x_lnnoptr =
                            (o->output_section->line_filepos
@@ -3822,8 +3911,8 @@ xcoff_link_input_bfd (finfo, input_bfd)
                          if (bfd_seek (output_bfd,
                                        aux.x_sym.x_fcnary.x_fcn.x_lnnoptr,
                                        SEEK_SET) != 0
-                             || (bfd_write (finfo->linenos, linesz, count,
-                                            output_bfd)
+                             || (bfd_write (finfo->linenos + linoff,
+                                            linesz, count, output_bfd)
                                  != linesz * count))
                            return false;
 
@@ -4037,7 +4126,12 @@ xcoff_link_input_bfd (finfo, input_bfd)
              switch (irel->r_type)
                {
                default:
-                 break;
+                 if (h == NULL
+                     || h->root.type == bfd_link_hash_defined
+                     || h->root.type == bfd_link_hash_defweak
+                     || h->root.type == bfd_link_hash_common)
+                   break;
+                 /* Fall through.  */
                case R_POS:
                case R_NEG:
                case R_RL:
@@ -4047,30 +4141,36 @@ xcoff_link_input_bfd (finfo, input_bfd)
                  ldrel.l_vaddr = irel->r_vaddr;
                  if (r_symndx == -1)
                    ldrel.l_symndx = -1;
-                 else if (h == NULL)
+                 else if (h == NULL
+                          || (h->root.type == bfd_link_hash_defined
+                              || h->root.type == bfd_link_hash_defweak
+                              || h->root.type == bfd_link_hash_common))
                    {
                      asection *sec;
 
-                     sec = xcoff_data (input_bfd)->csects[r_symndx];
-                     if ((sec->flags & SEC_CODE) != 0)
-                       ldrel.l_symndx = 0;
-                     else if ((sec->flags & SEC_HAS_CONTENTS) != 0)
-                       ldrel.l_symndx = 1;
+                     if (h == NULL)
+                       sec = xcoff_data (input_bfd)->csects[r_symndx];
+                     else if (h->root.type == bfd_link_hash_common)
+                       sec = h->root.u.c.p->section;
                      else
-                       ldrel.l_symndx = 2;
-                   }
-                 else if (h->root.type == bfd_link_hash_defined
-                          || h->root.type == bfd_link_hash_defweak)
-                   {
-                     asection *sec;
+                       sec = h->root.u.def.section;
+                     sec = sec->output_section;
 
-                     sec = h->root.u.def.section->output_section;
-                     if ((sec->flags & SEC_CODE) != 0)
+                     if (strcmp (sec->name, ".text") == 0)
                        ldrel.l_symndx = 0;
-                     else if ((sec->flags & SEC_HAS_CONTENTS) != 0)
+                     else if (strcmp (sec->name, ".data") == 0)
                        ldrel.l_symndx = 1;
-                     else
+                     else if (strcmp (sec->name, ".bss") == 0)
                        ldrel.l_symndx = 2;
+                     else
+                       {
+                         (*_bfd_error_handler)
+                           ("%s: loader reloc in unrecognized section `%s'",
+                            bfd_get_filename (input_bfd),
+                            sec->name);
+                         bfd_set_error (bfd_error_nonrepresentable_section);
+                         return false;
+                       }
                    }
                  else
                    {
@@ -4088,7 +4188,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
                  ldrel.l_rtype = (irel->r_size << 8) | irel->r_type;
                  ldrel.l_rsecnm = o->output_section->target_index;
                  if (xcoff_hash_table (finfo->info)->textro
-                     && (o->output_section->flags & SEC_CODE) != 0)
+                     && strcmp (o->output_section->name, ".text") == 0)
                    {
                      (*_bfd_error_handler)
                        ("%s: loader reloc in read-only section %s",
@@ -4102,6 +4202,16 @@ xcoff_link_input_bfd (finfo, input_bfd)
                                        finfo->ldrel);
                  BFD_ASSERT (sizeof (struct external_ldrel) == LDRELSZ);
                  ++finfo->ldrel;
+                 break;
+
+               case R_TOC:
+               case R_GL:
+               case R_TCL:
+               case R_TRL:
+               case R_TRLA:
+                 /* We should never need a .loader reloc for a TOC
+                    relative reloc.  */
+                 break;
                }
            }
 
This page took 0.046791 seconds and 4 git commands to generate.