Automatic date update in version.in
[binutils-gdb.git] / bfd / xcofflink.c
index 84048620b8e77c01b697ff3c730b1b457f80c81b..70d371e4aeddf153f8a97d6d1f79a4faf1a1ceb0 100644 (file)
@@ -1,5 +1,5 @@
 /* POWER/PowerPC XCOFF linker support.
-   Copyright (C) 1995-2021 Free Software Foundation, Inc.
+   Copyright (C) 1995-2022 Free Software Foundation, Inc.
    Written by Ian Lance Taylor <ian@cygnus.com>, Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
 #undef  STRING_SIZE_SIZE
 #define STRING_SIZE_SIZE 4
 
-/* We reuse the SEC_ROM flag as a mark flag for garbage collection.
-   This flag will only be used on input sections.  */
-
-#define SEC_MARK (SEC_ROM)
-
 /* The list of import files.  */
 
 struct xcoff_import_file
@@ -592,6 +587,7 @@ struct bfd_link_hash_table *
 _bfd_xcoff_bfd_link_hash_table_create (bfd *abfd)
 {
   struct xcoff_link_hash_table *ret;
+  bool isxcoff64 = false;
   size_t amt = sizeof (* ret);
 
   ret = bfd_zmalloc (amt);
@@ -604,7 +600,9 @@ _bfd_xcoff_bfd_link_hash_table_create (bfd *abfd)
       return NULL;
     }
 
-  ret->debug_strtab = _bfd_xcoff_stringtab_init ();
+  isxcoff64 = bfd_coff_debug_string_prefix_length (abfd) == 4;
+
+  ret->debug_strtab = _bfd_xcoff_stringtab_init (isxcoff64);
   ret->archive_info = htab_create (37, xcoff_archive_info_hash,
                                   xcoff_archive_info_eq, NULL);
   if (!ret->debug_strtab || !ret->archive_info)
@@ -800,10 +798,14 @@ xcoff_dynamic_definition_p (struct xcoff_link_hash_entry *h,
          || h->root.type == bfd_link_hash_undefweak))
     return true;
 
-  /* If H is currently undefined, LDSYM defines it.  */
+  /* If H is currently undefined, LDSYM defines it.
+     However, if H has a hidden visibility, LDSYM must not
+     define it.  */
   if ((h->flags & XCOFF_DEF_DYNAMIC) == 0
       && (h->root.type == bfd_link_hash_undefined
-         || h->root.type == bfd_link_hash_undefweak))
+         || h->root.type == bfd_link_hash_undefweak)
+      && (h->visibility != SYM_V_HIDDEN
+         && h->visibility != SYM_V_INTERNAL))
     return true;
 
   return false;
@@ -1180,6 +1182,26 @@ xcoff_find_reloc (struct internal_reloc *relocs,
   return min;
 }
 
+/* Return true if the symbol has to be added to the linker hash
+   table.  */
+static bool
+xcoff_link_add_symbols_to_hash_table (struct internal_syment sym,
+                                     union internal_auxent aux)
+{
+  /* External symbols must be added.  */
+  if (EXTERN_SYM_P (sym.n_sclass))
+    return true;
+
+  /* Hidden TLS symbols must be added to verify TLS relocations
+     in xcoff_reloc_type_tls.  */
+  if (sym.n_sclass == C_HIDEXT
+      && ((aux.x_csect.x_smclas == XMC_TL
+          || aux.x_csect.x_smclas == XMC_UL)))
+    return true;
+
+  return false;
+}
+
 /* Add all the symbols from an object file to the hash table.
 
    XCOFF is a weird format.  A normal XCOFF .o files will have three
@@ -1225,6 +1247,7 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
     bfd_byte *linenos;
   } *reloc_info = NULL;
   bfd_size_type amt;
+  unsigned short visibility;
 
   keep_syms = obj_coff_keep_syms (abfd);
 
@@ -1462,6 +1485,9 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
            }
        }
 
+      /* Record visibility.  */
+      visibility = sym.n_type & SYM_V_MASK;
+
       /* Pick up the csect auxiliary information.  */
       if (sym.n_numaux == 0)
        {
@@ -1553,6 +1579,11 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
             32 bit has a csect length of 4 for TOC
             64 bit has a csect length of 8 for TOC
 
+            An exception is made for TOC entries with a R_TLSML
+            relocation.  This relocation is made for the loader.
+            We must check that the referenced symbol is the TOC entry
+            itself.
+
             The conditions to get past the if-check are not that bad.
             They are what is used to create the TOC csects in the first
             place.  */
@@ -1582,7 +1613,8 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
                 64 bit R_POS r_size is 63  */
              if (relindx < enclosing->reloc_count
                  && rel->r_vaddr == (bfd_vma) sym.n_value
-                 && rel->r_type == R_POS
+                 && (rel->r_type == R_POS ||
+                     rel->r_type == R_TLSML)
                  && ((bfd_xcoff_is_xcoff32 (abfd)
                       && rel->r_size == 31)
                      || (bfd_xcoff_is_xcoff64 (abfd)
@@ -1654,6 +1686,22 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
                          set_toc = h;
                        }
                    }
+                 else if (rel->r_type == R_TLSML)
+                   {
+                       csect_index = ((esym
+                                       - (bfd_byte *) obj_coff_external_syms (abfd))
+                                      / symesz);
+                       if (((unsigned long) rel->r_symndx) != csect_index)
+                         {
+                           _bfd_error_handler
+                             /* xgettext:c-format */
+                             (_("%pB: TOC entry `%s' has a R_TLSML"
+                                "relocation not targeting itself"),
+                              abfd, name);
+                           bfd_set_error (bfd_error_bad_value);
+                           goto error_return;
+                         }
+                   }
                }
            }
 
@@ -1751,9 +1799,10 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
            if (first_csect == NULL)
              first_csect = csect;
 
-           /* If this symbol is external, we treat it as starting at the
-              beginning of the newly created section.  */
-           if (EXTERN_SYM_P (sym.n_sclass))
+           /* If this symbol must be added to the linker hash table,
+              we treat it as starting at the beginning of the newly
+              created section.  */
+           if (xcoff_link_add_symbols_to_hash_table (sym, aux))
              {
                section = csect;
                value = 0;
@@ -1849,7 +1898,7 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
          if (first_csect == NULL)
            first_csect = csect;
 
-         if (EXTERN_SYM_P (sym.n_sclass))
+         if (xcoff_link_add_symbols_to_hash_table (sym, aux))
            {
              csect->flags |= SEC_IS_COMMON;
              csect->size = 0;
@@ -1890,7 +1939,7 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
       /* Now we have enough information to add the symbol to the
         linker hash table.  */
 
-      if (EXTERN_SYM_P (sym.n_sclass))
+      if (xcoff_link_add_symbols_to_hash_table (sym, aux))
        {
          bool copy, ok;
          flagword flags;
@@ -2017,6 +2066,22 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
                  /* Try not to give this error too many times.  */
                  (*sym_hash)->flags &= ~XCOFF_MULTIPLY_DEFINED;
                }
+
+
+             /* If the symbol is hidden or internal, completely undo
+                any dynamic link state.  */
+             if ((*sym_hash)->flags & XCOFF_DEF_DYNAMIC
+                 && (visibility == SYM_V_HIDDEN
+                     || visibility == SYM_V_INTERNAL))
+                 (*sym_hash)->flags &= ~XCOFF_DEF_DYNAMIC;
+             else
+               {
+                 /* Keep the most constraining visibility.  */
+                 unsigned short hvis = (*sym_hash)->visibility;
+                 if (visibility && ( !hvis || visibility < hvis))
+                   (*sym_hash)->visibility = visibility;
+               }
+
            }
 
          /* _bfd_generic_link_add_one_symbol may call the linker to
@@ -2349,6 +2414,7 @@ xcoff_link_check_ar_symbols (bfd *abfd,
       struct internal_syment sym;
 
       bfd_coff_swap_sym_in (abfd, (void *) esym, (void *) &sym);
+      esym += (sym.n_numaux + 1) * symesz;
 
       if (EXTERN_SYM_P (sym.n_sclass) && sym.n_scnum != N_UNDEF)
        {
@@ -2382,8 +2448,6 @@ xcoff_link_check_ar_symbols (bfd *abfd,
              return true;
            }
        }
-
-      esym += (sym.n_numaux + 1) * symesz;
     }
 
   /* We do not need this object file.  */
@@ -2610,6 +2674,11 @@ xcoff_auto_export_p (struct bfd_link_info *info,
   if (h->root.root.string[0] == '.')
     return false;
 
+  /* Don't export hidden or internal symbols.  */
+  if (h->visibility == SYM_V_HIDDEN
+      || h->visibility == SYM_V_INTERNAL)
+    return false;
+
   /* We don't export a symbol which is being defined by an object
      included from an archive which contains a shared object.  The
      rationale is that if an archive contains both an unshared and
@@ -2654,7 +2723,7 @@ xcoff_auto_export_p (struct bfd_link_info *info,
 
 static bool
 xcoff_need_ldrel_p (struct bfd_link_info *info, struct internal_reloc *rel,
-                   struct xcoff_link_hash_entry *h)
+                   struct xcoff_link_hash_entry *h, asection *ssec)
 {
   if (!xcoff_hash_table (info)->loader_section)
     return false;
@@ -2702,6 +2771,14 @@ xcoff_need_ldrel_p (struct bfd_link_info *info, struct internal_reloc *rel,
                  && bfd_is_abs_section (sec->output_section)))
            return false;
        }
+
+      /* Absolute relocations from read-only sections are forbidden
+        by AIX loader. However, they can appear in their section's
+         relocations.  */
+      if (ssec != NULL
+         && (ssec->output_section->flags & SEC_READONLY) != 0)
+       return false;
+
       return true;
 
     case R_TLS:
@@ -2870,7 +2947,7 @@ xcoff_mark_symbol (struct bfd_link_info *info, struct xcoff_link_hash_entry *h)
 
       hsec = h->root.u.def.section;
       if (! bfd_is_abs_section (hsec)
-         && (hsec->flags & SEC_MARK) == 0)
+         && hsec->gc_mark == 0)
        {
          if (! xcoff_mark (info, hsec))
            return false;
@@ -2878,7 +2955,7 @@ xcoff_mark_symbol (struct bfd_link_info *info, struct xcoff_link_hash_entry *h)
     }
 
   if (h->toc_section != NULL
-      && (h->toc_section->flags & SEC_MARK) == 0)
+      && h->toc_section->gc_mark == 0)
     {
       if (! xcoff_mark (info, h->toc_section))
        return false;
@@ -2921,17 +2998,21 @@ static bool
 xcoff_mark (struct bfd_link_info *info, asection *sec)
 {
   if (bfd_is_const_section (sec)
-      || (sec->flags & SEC_MARK) != 0)
+      || sec->gc_mark != 0)
+    return true;
+
+  sec->gc_mark = 1;
+
+  if (sec->owner->xvec != info->output_bfd->xvec)
+    return true;
+
+  if (coff_section_data (sec->owner, sec) == NULL)
     return true;
 
-  sec->flags |= SEC_MARK;
 
-  if (sec->owner->xvec == info->output_bfd->xvec
-      && coff_section_data (sec->owner, sec) != NULL
-      && xcoff_section_data (sec->owner, sec) != NULL)
+  if (xcoff_section_data (sec->owner, sec) != NULL)
     {
       struct xcoff_link_hash_entry **syms;
-      struct internal_reloc *rel, *relend;
       asection **csects;
       unsigned long i, first, last;
 
@@ -2948,64 +3029,67 @@ xcoff_mark (struct bfd_link_info *info, asection *sec)
            if (!xcoff_mark_symbol (info, syms[i]))
              return false;
          }
+    }
 
-      /* Look through the section relocs.  */
-      if ((sec->flags & SEC_RELOC) != 0
-         && sec->reloc_count > 0)
+  /* Look through the section relocs.  */
+  if ((sec->flags & SEC_RELOC) != 0
+      && sec->reloc_count > 0)
+    {
+      struct internal_reloc *rel, *relend;
+
+      rel = xcoff_read_internal_relocs (sec->owner, sec, true,
+                                       NULL, false, NULL);
+      if (rel == NULL)
+       return false;
+      relend = rel + sec->reloc_count;
+      for (; rel < relend; rel++)
        {
-         rel = xcoff_read_internal_relocs (sec->owner, sec, true,
-                                           NULL, false, NULL);
-         if (rel == NULL)
-           return false;
-         relend = rel + sec->reloc_count;
-         for (; rel < relend; rel++)
-           {
-             struct xcoff_link_hash_entry *h;
+         struct xcoff_link_hash_entry *h;
 
-             if ((unsigned int) rel->r_symndx
-                 > obj_raw_syment_count (sec->owner))
-               continue;
+         if ((unsigned int) rel->r_symndx
+             > obj_raw_syment_count (sec->owner))
+           continue;
 
-             h = obj_xcoff_sym_hashes (sec->owner)[rel->r_symndx];
-             if (h != NULL)
-               {
-                 if ((h->flags & XCOFF_MARK) == 0)
-                   {
-                     if (!xcoff_mark_symbol (info, h))
-                       return false;
-                   }
-               }
-             else
+         h = obj_xcoff_sym_hashes (sec->owner)[rel->r_symndx];
+         if (h != NULL)
+           {
+             if ((h->flags & XCOFF_MARK) == 0)
                {
-                 asection *rsec;
-
-                 rsec = xcoff_data (sec->owner)->csects[rel->r_symndx];
-                 if (rsec != NULL
-                     && (rsec->flags & SEC_MARK) == 0)
-                   {
-                     if (!xcoff_mark (info, rsec))
-                       return false;
-                   }
+                 if (!xcoff_mark_symbol (info, h))
+                   return false;
                }
+           }
+         else
+           {
+             asection *rsec;
 
-             /* See if this reloc needs to be copied into the .loader
-                section.  */
-             if (xcoff_need_ldrel_p (info, rel, h))
+             rsec = xcoff_data (sec->owner)->csects[rel->r_symndx];
+             if (rsec != NULL
+                 && rsec->gc_mark == 0)
                {
-                 ++xcoff_hash_table (info)->ldrel_count;
-                 if (h != NULL)
-                   h->flags |= XCOFF_LDREL;
+                 if (!xcoff_mark (info, rsec))
+                   return false;
                }
            }
 
-         if (! info->keep_memory
-             && coff_section_data (sec->owner, sec) != NULL
-             && ! coff_section_data (sec->owner, sec)->keep_relocs)
+         /* See if this reloc needs to be copied into the .loader
+            section.  */
+         if ((sec->flags & SEC_DEBUGGING) == 0
+             && xcoff_need_ldrel_p (info, rel, h, sec))
            {
-             free (coff_section_data (sec->owner, sec)->relocs);
-             coff_section_data (sec->owner, sec)->relocs = NULL;
+             ++xcoff_hash_table (info)->ldrel_count;
+             if (h != NULL)
+               h->flags |= XCOFF_LDREL;
            }
        }
+
+      if (! info->keep_memory
+         && coff_section_data (sec->owner, sec) != NULL
+         && ! coff_section_data (sec->owner, sec)->keep_relocs)
+       {
+         free (coff_section_data (sec->owner, sec)->relocs);
+         coff_section_data (sec->owner, sec)->relocs = NULL;
+       }
     }
 
   return true;
@@ -3025,27 +3109,52 @@ xcoff_sweep (struct bfd_link_info *info)
   for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
     {
       asection *o;
+      bool some_kept = false;
 
+      /* As says below keep all sections from non-XCOFF
+         input files.  */
+      if (sub->xvec != info->output_bfd->xvec)
+       some_kept = true;
+      else
+       {
+         /* See whether any section is already marked.  */
+         for (o = sub->sections; o != NULL; o = o->next)
+           if (o->gc_mark)
+             some_kept = true;
+       }
+
+      /* If no section in this file will be kept, then we can
+        toss out debug sections.  */
+      if (!some_kept)
+       {
+         for (o = sub->sections; o != NULL; o = o->next)
+           {
+             o->size = 0;
+             o->reloc_count = 0;
+           }
+         continue;
+       }
+
+      /* Keep all sections from non-XCOFF input files.  Keep
+        special sections.  Keep .debug sections for the
+        moment.  */
       for (o = sub->sections; o != NULL; o = o->next)
        {
-         if ((o->flags & SEC_MARK) == 0)
+         if (o->gc_mark == 1)
+           continue;
+
+         if (sub->xvec != info->output_bfd->xvec
+             || o == xcoff_hash_table (info)->debug_section
+             || o == xcoff_hash_table (info)->loader_section
+             || o == xcoff_hash_table (info)->linkage_section
+             || o == xcoff_hash_table (info)->descriptor_section
+             || (bfd_section_flags (o) & SEC_DEBUGGING)
+             || strcmp (o->name, ".debug") == 0)
+           xcoff_mark (info, o);
+         else
            {
-             /* Keep all sections from non-XCOFF input files.  Keep
-                special sections.  Keep .debug sections for the
-                moment.  */
-             if (sub->xvec != info->output_bfd->xvec
-                 || o == xcoff_hash_table (info)->debug_section
-                 || o == xcoff_hash_table (info)->loader_section
-                 || o == xcoff_hash_table (info)->linkage_section
-                 || o == xcoff_hash_table (info)->descriptor_section
-                 || (bfd_section_flags (o) & SEC_DEBUGGING)
-                 || strcmp (o->name, ".debug") == 0)
-               o->flags |= SEC_MARK;
-             else
-               {
-                 o->size = 0;
-                 o->reloc_count = 0;
-               }
+             o->size = 0;
+             o->reloc_count = 0;
            }
        }
     }
@@ -3168,6 +3277,19 @@ bfd_xcoff_export_symbol (bfd *output_bfd,
   if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour)
     return true;
 
+  /* As AIX linker, symbols exported with hidden visibility are
+     silently ignored.  */
+  if (h->visibility == SYM_V_HIDDEN)
+    return true;
+
+  if (h->visibility == SYM_V_INTERNAL)
+    {
+      _bfd_error_handler (_("%pB: cannot export internal symbol `%s`."),
+                         output_bfd, h->root.root.string);
+      bfd_set_error (bfd_error_bad_value);
+      return false;
+    }
+
   h->flags |= XCOFF_EXPORT;
 
   /* FIXME: I'm not at all sure what syscall is supposed to mean, so
@@ -3276,8 +3398,6 @@ xcoff_mark_auto_exports (struct xcoff_link_hash_entry *h, void *data)
   return true;
 }
 
-/* Add a symbol to the .loader symbols, if necessary.  */
-
 /* INPUT_BFD has an external symbol associated with hash table entry H
    and csect CSECT.   Return true if INPUT_BFD defines H.  */
 
@@ -3447,7 +3567,7 @@ xcoff_keep_symbol_p (struct bfd_link_info *info, bfd *input_bfd,
   if (xcoff_hash_table (info)->gc
       && !bfd_is_abs_section (csect)
       && !bfd_is_und_section (csect)
-      && (csect->flags & SEC_MARK) == 0)
+      && csect->gc_mark == 0)
     return 0;
 
   /* An XCOFF linker always removes C_STAT symbols.  */
@@ -3759,7 +3879,7 @@ bfd_xcoff_size_dynamic_sections (bfd *output_bfd,
                 (a) one of the input files did or (b) we end up
                 creating TOC references as part of the link process.  */
              if (o != xcoff_hash_table (info)->toc_section
-                 && (o->flags & SEC_MARK) == 0)
+                 && o->gc_mark == 0)
                {
                  if (! xcoff_mark (info, o))
                    goto error_return;
@@ -3796,7 +3916,7 @@ bfd_xcoff_size_dynamic_sections (bfd *output_bfd,
 
       if (sec != NULL
          && gc
-         && (sec->flags & SEC_MARK) == 0)
+         && sec->gc_mark == 0)
        sec = NULL;
 
       special_sections[i] = sec;
@@ -3982,7 +4102,8 @@ bfd_xcoff_size_dynamic_sections (bfd *output_bfd,
        }
     }
 
-  if (info->strip != strip_all)
+  if (info->strip != strip_all
+      && xcoff_hash_table (info)->debug_section != NULL)
     xcoff_hash_table (info)->debug_section->size =
       _bfd_stringtab_size (debug_strtab);
 
@@ -4493,6 +4614,13 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *flinfo,
                               - (*csectpp)->vma);
            }
 
+         /* Update visibility.  */
+         if (*sym_hash)
+           {
+             isym.n_type &= ~SYM_V_MASK;
+             isym.n_type |= (*sym_hash)->visibility;
+           }
+
          /* Output the symbol.  */
          bfd_coff_swap_sym_out (output_bfd, (void *) &isym, (void *) outsym);
 
@@ -4512,13 +4640,13 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *flinfo,
                  /* This is the file name (or some comment put in by
                     the compiler).  If it is long, we must put it in
                     the string table.  */
-                 if (aux.x_file.x_n.x_zeroes == 0
-                     && aux.x_file.x_n.x_offset != 0)
+                 if (aux.x_file.x_n.x_n.x_zeroes == 0
+                     && aux.x_file.x_n.x_n.x_offset != 0)
                    {
                      const char *filename;
                      bfd_size_type indx;
 
-                     BFD_ASSERT (aux.x_file.x_n.x_offset
+                     BFD_ASSERT (aux.x_file.x_n.x_n.x_offset
                                  >= STRING_SIZE_SIZE);
                      if (strings == NULL)
                        {
@@ -4526,15 +4654,15 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *flinfo,
                          if (strings == NULL)
                            return false;
                        }
-                     if ((bfd_size_type) aux.x_file.x_n.x_offset >= obj_coff_strings_len (input_bfd))
+                     if ((bfd_size_type) aux.x_file.x_n.x_n.x_offset >= obj_coff_strings_len (input_bfd))
                        filename = _("<corrupt>");
                      else
-                       filename = strings + aux.x_file.x_n.x_offset;
+                       filename = strings + aux.x_file.x_n.x_n.x_offset;
                      indx = _bfd_stringtab_add (flinfo->strtab, filename,
                                                 hash, copy);
                      if (indx == (bfd_size_type) -1)
                        return false;
-                     aux.x_file.x_n.x_offset = STRING_SIZE_SIZE + indx;
+                     aux.x_file.x_n.x_n.x_offset = STRING_SIZE_SIZE + indx;
                    }
                }
              else if (CSECT_SYM_P (isymp->n_sclass)
@@ -4983,7 +5111,7 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *flinfo,
                }
 
              if ((o->flags & SEC_DEBUGGING) == 0
-                 && xcoff_need_ldrel_p (flinfo->info, irel, h))
+                 && xcoff_need_ldrel_p (flinfo->info, irel, h, o))
                {
                  asection *sec;
 
@@ -5092,7 +5220,7 @@ xcoff_find_tc0 (bfd *output_bfd, struct xcoff_final_link_info *flinfo)
        input_bfd != NULL;
        input_bfd = input_bfd->link.next)
     for (sec = input_bfd->sections; sec != NULL; sec = sec->next)
-      if ((sec->flags & SEC_MARK) != 0 && xcoff_toc_section_p (sec))
+      if (sec->gc_mark != 0 && xcoff_toc_section_p (sec))
        {
          start = sec->output_section->vma + sec->output_offset;
          if (toc_start > start)
@@ -5124,7 +5252,7 @@ xcoff_find_tc0 (bfd *output_bfd, struct xcoff_final_link_info *flinfo)
           input_bfd != NULL;
           input_bfd = input_bfd->link.next)
        for (sec = input_bfd->sections; sec != NULL; sec = sec->next)
-         if ((sec->flags & SEC_MARK) != 0 && xcoff_toc_section_p (sec))
+         if (sec->gc_mark != 0 && xcoff_toc_section_p (sec))
            {
              start = sec->output_section->vma + sec->output_offset;
              if (start < best_address