xref: /dflybsd-src/contrib/gdb-7/bfd/elf-vxworks.c (revision de8e141f24382815c10a4012d209bbbf7abf1112)
15796c8dcSSimon Schubert /* VxWorks support for ELF
2*ef5ccd6cSJohn Marino    Copyright 2005, 2006, 2007, 2009, 2012 Free Software Foundation, Inc.
35796c8dcSSimon Schubert 
45796c8dcSSimon Schubert    This file is part of BFD, the Binary File Descriptor library.
55796c8dcSSimon Schubert 
65796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
75796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
85796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
95796c8dcSSimon Schubert    (at your option) any later version.
105796c8dcSSimon Schubert 
115796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
125796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
135796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
145796c8dcSSimon Schubert    GNU General Public License for more details.
155796c8dcSSimon Schubert 
165796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
175796c8dcSSimon Schubert    along with this program; if not, write to the Free Software
185796c8dcSSimon Schubert    Foundation, Inc., 59 Temple Place - Suite 330, Boston,
195796c8dcSSimon Schubert    MA 02111-1307, USA.  */
205796c8dcSSimon Schubert 
215796c8dcSSimon Schubert /* This file provides routines used by all VxWorks targets.  */
225796c8dcSSimon Schubert 
235796c8dcSSimon Schubert #include "sysdep.h"
245796c8dcSSimon Schubert #include "bfd.h"
255796c8dcSSimon Schubert #include "libbfd.h"
265796c8dcSSimon Schubert #include "elf-bfd.h"
275796c8dcSSimon Schubert #include "elf-vxworks.h"
285796c8dcSSimon Schubert #include "elf/vxworks.h"
295796c8dcSSimon Schubert 
305796c8dcSSimon Schubert /* Return true if symbol NAME, as defined by ABFD, is one of the special
315796c8dcSSimon Schubert    __GOTT_BASE__ or __GOTT_INDEX__ symbols.  */
325796c8dcSSimon Schubert 
335796c8dcSSimon Schubert static bfd_boolean
elf_vxworks_gott_symbol_p(bfd * abfd,const char * name)345796c8dcSSimon Schubert elf_vxworks_gott_symbol_p (bfd *abfd, const char *name)
355796c8dcSSimon Schubert {
365796c8dcSSimon Schubert   char leading;
375796c8dcSSimon Schubert 
385796c8dcSSimon Schubert   leading = bfd_get_symbol_leading_char (abfd);
395796c8dcSSimon Schubert   if (leading)
405796c8dcSSimon Schubert     {
415796c8dcSSimon Schubert       if (*name != leading)
425796c8dcSSimon Schubert 	return FALSE;
435796c8dcSSimon Schubert       name++;
445796c8dcSSimon Schubert     }
455796c8dcSSimon Schubert   return (strcmp (name, "__GOTT_BASE__") == 0
465796c8dcSSimon Schubert 	  || strcmp (name, "__GOTT_INDEX__") == 0);
475796c8dcSSimon Schubert }
485796c8dcSSimon Schubert 
495796c8dcSSimon Schubert /* Tweak magic VxWorks symbols as they are loaded.  */
505796c8dcSSimon Schubert bfd_boolean
elf_vxworks_add_symbol_hook(bfd * abfd,struct bfd_link_info * info,Elf_Internal_Sym * sym,const char ** namep,flagword * flagsp,asection ** secp ATTRIBUTE_UNUSED,bfd_vma * valp ATTRIBUTE_UNUSED)515796c8dcSSimon Schubert elf_vxworks_add_symbol_hook (bfd *abfd,
525796c8dcSSimon Schubert 			     struct bfd_link_info *info,
535796c8dcSSimon Schubert 			     Elf_Internal_Sym *sym,
545796c8dcSSimon Schubert 			     const char **namep,
555796c8dcSSimon Schubert 			     flagword *flagsp,
565796c8dcSSimon Schubert 			     asection **secp ATTRIBUTE_UNUSED,
575796c8dcSSimon Schubert 			     bfd_vma *valp ATTRIBUTE_UNUSED)
585796c8dcSSimon Schubert {
595796c8dcSSimon Schubert   /* Ideally these "magic" symbols would be exported by libc.so.1
605796c8dcSSimon Schubert      which would be found via a DT_NEEDED tag, and then handled
615796c8dcSSimon Schubert      specially by the linker at runtime.  Except shared libraries
625796c8dcSSimon Schubert      don't even link to libc.so.1 by default...
635796c8dcSSimon Schubert      If the symbol is imported from, or will be put in a shared library,
645796c8dcSSimon Schubert      give the symbol weak binding to get the desired samantics.
655796c8dcSSimon Schubert      This transformation will be undone in
665796c8dcSSimon Schubert      elf_i386_vxworks_link_output_symbol_hook. */
675796c8dcSSimon Schubert   if ((info->shared || abfd->flags & DYNAMIC)
685796c8dcSSimon Schubert       && elf_vxworks_gott_symbol_p (abfd, *namep))
695796c8dcSSimon Schubert     {
705796c8dcSSimon Schubert       sym->st_info = ELF_ST_INFO (STB_WEAK, ELF_ST_TYPE (sym->st_info));
715796c8dcSSimon Schubert       *flagsp |= BSF_WEAK;
725796c8dcSSimon Schubert     }
735796c8dcSSimon Schubert 
745796c8dcSSimon Schubert   return TRUE;
755796c8dcSSimon Schubert }
765796c8dcSSimon Schubert 
775796c8dcSSimon Schubert /* Perform VxWorks-specific handling of the create_dynamic_sections hook.
785796c8dcSSimon Schubert    When creating an executable, set *SRELPLT2_OUT to the .rel(a).plt.unloaded
795796c8dcSSimon Schubert    section.  */
805796c8dcSSimon Schubert 
815796c8dcSSimon Schubert bfd_boolean
elf_vxworks_create_dynamic_sections(bfd * dynobj,struct bfd_link_info * info,asection ** srelplt2_out)825796c8dcSSimon Schubert elf_vxworks_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info,
835796c8dcSSimon Schubert 				     asection **srelplt2_out)
845796c8dcSSimon Schubert {
855796c8dcSSimon Schubert   struct elf_link_hash_table *htab;
865796c8dcSSimon Schubert   const struct elf_backend_data *bed;
875796c8dcSSimon Schubert   asection *s;
885796c8dcSSimon Schubert 
895796c8dcSSimon Schubert   htab = elf_hash_table (info);
905796c8dcSSimon Schubert   bed = get_elf_backend_data (dynobj);
915796c8dcSSimon Schubert 
925796c8dcSSimon Schubert   if (!info->shared)
935796c8dcSSimon Schubert     {
94*ef5ccd6cSJohn Marino       s = bfd_make_section_anyway_with_flags (dynobj,
955796c8dcSSimon Schubert 					      bed->default_use_rela_p
965796c8dcSSimon Schubert 					      ? ".rela.plt.unloaded"
975796c8dcSSimon Schubert 					      : ".rel.plt.unloaded",
985796c8dcSSimon Schubert 					      SEC_HAS_CONTENTS | SEC_IN_MEMORY
99*ef5ccd6cSJohn Marino 					      | SEC_READONLY
100*ef5ccd6cSJohn Marino 					      | SEC_LINKER_CREATED);
1015796c8dcSSimon Schubert       if (s == NULL
1025796c8dcSSimon Schubert 	  || !bfd_set_section_alignment (dynobj, s, bed->s->log_file_align))
1035796c8dcSSimon Schubert 	return FALSE;
1045796c8dcSSimon Schubert 
1055796c8dcSSimon Schubert       *srelplt2_out = s;
1065796c8dcSSimon Schubert     }
1075796c8dcSSimon Schubert 
1085796c8dcSSimon Schubert   /* Mark the GOT and PLT symbols as having relocations; they might
1095796c8dcSSimon Schubert      not, but we won't know for sure until we build the GOT in
1105796c8dcSSimon Schubert      finish_dynamic_symbol.  Also make sure that the GOT symbol
1115796c8dcSSimon Schubert      is entered into the dynamic symbol table; the loader uses it
1125796c8dcSSimon Schubert      to initialize __GOTT_BASE__[__GOTT_INDEX__].  */
1135796c8dcSSimon Schubert   if (htab->hgot)
1145796c8dcSSimon Schubert     {
1155796c8dcSSimon Schubert       htab->hgot->indx = -2;
1165796c8dcSSimon Schubert       htab->hgot->other &= ~ELF_ST_VISIBILITY (-1);
1175796c8dcSSimon Schubert       htab->hgot->forced_local = 0;
1185796c8dcSSimon Schubert       if (!bfd_elf_link_record_dynamic_symbol (info, htab->hgot))
1195796c8dcSSimon Schubert 	return FALSE;
1205796c8dcSSimon Schubert     }
1215796c8dcSSimon Schubert   if (htab->hplt)
1225796c8dcSSimon Schubert     {
1235796c8dcSSimon Schubert       htab->hplt->indx = -2;
1245796c8dcSSimon Schubert       htab->hplt->type = STT_FUNC;
1255796c8dcSSimon Schubert     }
1265796c8dcSSimon Schubert 
1275796c8dcSSimon Schubert   return TRUE;
1285796c8dcSSimon Schubert }
1295796c8dcSSimon Schubert 
1305796c8dcSSimon Schubert /* Tweak magic VxWorks symbols as they are written to the output file.  */
1315796c8dcSSimon Schubert int
elf_vxworks_link_output_symbol_hook(struct bfd_link_info * info ATTRIBUTE_UNUSED,const char * name,Elf_Internal_Sym * sym,asection * input_sec ATTRIBUTE_UNUSED,struct elf_link_hash_entry * h)1325796c8dcSSimon Schubert elf_vxworks_link_output_symbol_hook (struct bfd_link_info *info
1335796c8dcSSimon Schubert 				       ATTRIBUTE_UNUSED,
1345796c8dcSSimon Schubert 				     const char *name,
1355796c8dcSSimon Schubert 				     Elf_Internal_Sym *sym,
1365796c8dcSSimon Schubert 				     asection *input_sec ATTRIBUTE_UNUSED,
1375796c8dcSSimon Schubert 				     struct elf_link_hash_entry *h)
1385796c8dcSSimon Schubert {
1395796c8dcSSimon Schubert   /* Reverse the effects of the hack in elf_vxworks_add_symbol_hook.  */
1405796c8dcSSimon Schubert   if (h
1415796c8dcSSimon Schubert       && h->root.type == bfd_link_hash_undefweak
1425796c8dcSSimon Schubert       && elf_vxworks_gott_symbol_p (h->root.u.undef.abfd, name))
1435796c8dcSSimon Schubert     sym->st_info = ELF_ST_INFO (STB_GLOBAL, ELF_ST_TYPE (sym->st_info));
1445796c8dcSSimon Schubert 
1455796c8dcSSimon Schubert   return 1;
1465796c8dcSSimon Schubert }
1475796c8dcSSimon Schubert 
1485796c8dcSSimon Schubert /* Copy relocations into the output file.  Fixes up relocations against PLT
1495796c8dcSSimon Schubert    entries, then calls the generic routine.  */
1505796c8dcSSimon Schubert 
1515796c8dcSSimon Schubert bfd_boolean
elf_vxworks_emit_relocs(bfd * output_bfd,asection * input_section,Elf_Internal_Shdr * input_rel_hdr,Elf_Internal_Rela * internal_relocs,struct elf_link_hash_entry ** rel_hash)1525796c8dcSSimon Schubert elf_vxworks_emit_relocs (bfd *output_bfd,
1535796c8dcSSimon Schubert 			 asection *input_section,
1545796c8dcSSimon Schubert 			 Elf_Internal_Shdr *input_rel_hdr,
1555796c8dcSSimon Schubert 			 Elf_Internal_Rela *internal_relocs,
1565796c8dcSSimon Schubert 			 struct elf_link_hash_entry **rel_hash)
1575796c8dcSSimon Schubert {
1585796c8dcSSimon Schubert   const struct elf_backend_data *bed;
1595796c8dcSSimon Schubert   int j;
1605796c8dcSSimon Schubert 
1615796c8dcSSimon Schubert   bed = get_elf_backend_data (output_bfd);
1625796c8dcSSimon Schubert 
1635796c8dcSSimon Schubert   if (output_bfd->flags & (DYNAMIC|EXEC_P))
1645796c8dcSSimon Schubert     {
1655796c8dcSSimon Schubert       Elf_Internal_Rela *irela;
1665796c8dcSSimon Schubert       Elf_Internal_Rela *irelaend;
1675796c8dcSSimon Schubert       struct elf_link_hash_entry **hash_ptr;
1685796c8dcSSimon Schubert 
1695796c8dcSSimon Schubert       for (irela = internal_relocs,
1705796c8dcSSimon Schubert 	     irelaend = irela + (NUM_SHDR_ENTRIES (input_rel_hdr)
1715796c8dcSSimon Schubert 				 * bed->s->int_rels_per_ext_rel),
1725796c8dcSSimon Schubert 	     hash_ptr = rel_hash;
1735796c8dcSSimon Schubert 	   irela < irelaend;
1745796c8dcSSimon Schubert 	   irela += bed->s->int_rels_per_ext_rel,
1755796c8dcSSimon Schubert 	     hash_ptr++)
1765796c8dcSSimon Schubert 	{
1775796c8dcSSimon Schubert 	  if (*hash_ptr
1785796c8dcSSimon Schubert 	      && (*hash_ptr)->def_dynamic
1795796c8dcSSimon Schubert 	      && !(*hash_ptr)->def_regular
1805796c8dcSSimon Schubert 	      && ((*hash_ptr)->root.type == bfd_link_hash_defined
1815796c8dcSSimon Schubert 		  || (*hash_ptr)->root.type == bfd_link_hash_defweak)
1825796c8dcSSimon Schubert 	      && (*hash_ptr)->root.u.def.section->output_section != NULL)
1835796c8dcSSimon Schubert 	    {
1845796c8dcSSimon Schubert 	      /* This is a relocation from an executable or shared
1855796c8dcSSimon Schubert 	         library against a symbol in a different shared
1865796c8dcSSimon Schubert 	         library.  We are creating a definition in the output
1875796c8dcSSimon Schubert 	         file but it does not come from any of our normal (.o)
1885796c8dcSSimon Schubert 	         files. ie. a PLT stub.  Normally this would be a
1895796c8dcSSimon Schubert 	         relocation against against SHN_UNDEF with the VMA of
1905796c8dcSSimon Schubert 	         the PLT stub.  This upsets the VxWorks loader.
1915796c8dcSSimon Schubert 	         Convert it to a section-relative relocation.  This
1925796c8dcSSimon Schubert 	         gets some other symbols (for instance .dynbss), but
1935796c8dcSSimon Schubert 	         is conservatively correct.  */
1945796c8dcSSimon Schubert 	      for (j = 0; j < bed->s->int_rels_per_ext_rel; j++)
1955796c8dcSSimon Schubert 		{
1965796c8dcSSimon Schubert 		  asection *sec = (*hash_ptr)->root.u.def.section;
1975796c8dcSSimon Schubert 		  int this_idx = sec->output_section->target_index;
1985796c8dcSSimon Schubert 
1995796c8dcSSimon Schubert 		  irela[j].r_info
2005796c8dcSSimon Schubert 		    = ELF32_R_INFO (this_idx, ELF32_R_TYPE (irela[j].r_info));
2015796c8dcSSimon Schubert 		  irela[j].r_addend += (*hash_ptr)->root.u.def.value;
2025796c8dcSSimon Schubert 		  irela[j].r_addend += sec->output_offset;
2035796c8dcSSimon Schubert 		}
2045796c8dcSSimon Schubert 	      /* Stop the generic routine adjusting this entry.  */
2055796c8dcSSimon Schubert 	      *hash_ptr = NULL;
2065796c8dcSSimon Schubert 	    }
2075796c8dcSSimon Schubert 	}
2085796c8dcSSimon Schubert     }
2095796c8dcSSimon Schubert   return _bfd_elf_link_output_relocs (output_bfd, input_section,
2105796c8dcSSimon Schubert 				      input_rel_hdr, internal_relocs,
2115796c8dcSSimon Schubert 				      rel_hash);
2125796c8dcSSimon Schubert }
2135796c8dcSSimon Schubert 
2145796c8dcSSimon Schubert 
2155796c8dcSSimon Schubert /* Set the sh_link and sh_info fields on the static plt relocation secton.  */
2165796c8dcSSimon Schubert 
2175796c8dcSSimon Schubert void
elf_vxworks_final_write_processing(bfd * abfd,bfd_boolean linker ATTRIBUTE_UNUSED)2185796c8dcSSimon Schubert elf_vxworks_final_write_processing (bfd *abfd,
2195796c8dcSSimon Schubert 				    bfd_boolean linker ATTRIBUTE_UNUSED)
2205796c8dcSSimon Schubert {
2215796c8dcSSimon Schubert   asection * sec;
2225796c8dcSSimon Schubert   struct bfd_elf_section_data *d;
2235796c8dcSSimon Schubert 
2245796c8dcSSimon Schubert   sec = bfd_get_section_by_name (abfd, ".rel.plt.unloaded");
2255796c8dcSSimon Schubert   if (!sec)
2265796c8dcSSimon Schubert     sec = bfd_get_section_by_name (abfd, ".rela.plt.unloaded");
2275796c8dcSSimon Schubert   if (!sec)
2285796c8dcSSimon Schubert     return;
2295796c8dcSSimon Schubert   d = elf_section_data (sec);
230*ef5ccd6cSJohn Marino   d->this_hdr.sh_link = elf_onesymtab (abfd);
2315796c8dcSSimon Schubert   sec = bfd_get_section_by_name (abfd, ".plt");
2325796c8dcSSimon Schubert   if (sec)
2335796c8dcSSimon Schubert     d->this_hdr.sh_info = elf_section_data (sec)->this_idx;
2345796c8dcSSimon Schubert }
2355796c8dcSSimon Schubert 
2365796c8dcSSimon Schubert /* Add the dynamic entries required by VxWorks.  These point to the
2375796c8dcSSimon Schubert    tls sections.  */
2385796c8dcSSimon Schubert 
2395796c8dcSSimon Schubert bfd_boolean
elf_vxworks_add_dynamic_entries(bfd * output_bfd,struct bfd_link_info * info)2405796c8dcSSimon Schubert elf_vxworks_add_dynamic_entries (bfd *output_bfd, struct bfd_link_info *info)
2415796c8dcSSimon Schubert {
2425796c8dcSSimon Schubert   if (bfd_get_section_by_name (output_bfd, ".tls_data"))
2435796c8dcSSimon Schubert     {
2445796c8dcSSimon Schubert       if (!_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_DATA_START, 0)
2455796c8dcSSimon Schubert 	  || !_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_DATA_SIZE, 0)
2465796c8dcSSimon Schubert 	  || !_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_DATA_ALIGN, 0))
2475796c8dcSSimon Schubert 	return FALSE;
2485796c8dcSSimon Schubert     }
2495796c8dcSSimon Schubert   if (bfd_get_section_by_name (output_bfd, ".tls_vars"))
2505796c8dcSSimon Schubert     {
2515796c8dcSSimon Schubert       if (!_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_VARS_START, 0)
2525796c8dcSSimon Schubert 	  || !_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_VARS_SIZE, 0))
2535796c8dcSSimon Schubert 	return FALSE;
2545796c8dcSSimon Schubert     }
2555796c8dcSSimon Schubert   return TRUE;
2565796c8dcSSimon Schubert }
2575796c8dcSSimon Schubert 
2585796c8dcSSimon Schubert /* If *DYN is one of the VxWorks-specific dynamic entries, then fill
2595796c8dcSSimon Schubert    in the value now  and return TRUE.  Otherwise return FALSE.  */
2605796c8dcSSimon Schubert 
2615796c8dcSSimon Schubert bfd_boolean
elf_vxworks_finish_dynamic_entry(bfd * output_bfd,Elf_Internal_Dyn * dyn)2625796c8dcSSimon Schubert elf_vxworks_finish_dynamic_entry (bfd *output_bfd, Elf_Internal_Dyn *dyn)
2635796c8dcSSimon Schubert {
2645796c8dcSSimon Schubert   asection *sec;
2655796c8dcSSimon Schubert 
2665796c8dcSSimon Schubert   switch (dyn->d_tag)
2675796c8dcSSimon Schubert     {
2685796c8dcSSimon Schubert     default:
2695796c8dcSSimon Schubert       return FALSE;
2705796c8dcSSimon Schubert 
2715796c8dcSSimon Schubert     case DT_VX_WRS_TLS_DATA_START:
2725796c8dcSSimon Schubert       sec = bfd_get_section_by_name (output_bfd, ".tls_data");
2735796c8dcSSimon Schubert       dyn->d_un.d_ptr = sec->vma;
2745796c8dcSSimon Schubert       break;
2755796c8dcSSimon Schubert 
2765796c8dcSSimon Schubert     case DT_VX_WRS_TLS_DATA_SIZE:
2775796c8dcSSimon Schubert       sec = bfd_get_section_by_name (output_bfd, ".tls_data");
2785796c8dcSSimon Schubert       dyn->d_un.d_val = sec->size;
2795796c8dcSSimon Schubert       break;
2805796c8dcSSimon Schubert 
2815796c8dcSSimon Schubert     case DT_VX_WRS_TLS_DATA_ALIGN:
2825796c8dcSSimon Schubert       sec = bfd_get_section_by_name (output_bfd, ".tls_data");
2835796c8dcSSimon Schubert       dyn->d_un.d_val
284*ef5ccd6cSJohn Marino 	= (bfd_size_type)1 << bfd_get_section_alignment (output_bfd,
285*ef5ccd6cSJohn Marino 							 sec);
2865796c8dcSSimon Schubert       break;
2875796c8dcSSimon Schubert 
2885796c8dcSSimon Schubert     case DT_VX_WRS_TLS_VARS_START:
2895796c8dcSSimon Schubert       sec = bfd_get_section_by_name (output_bfd, ".tls_vars");
2905796c8dcSSimon Schubert       dyn->d_un.d_ptr = sec->vma;
2915796c8dcSSimon Schubert       break;
2925796c8dcSSimon Schubert 
2935796c8dcSSimon Schubert     case DT_VX_WRS_TLS_VARS_SIZE:
2945796c8dcSSimon Schubert       sec = bfd_get_section_by_name (output_bfd, ".tls_vars");
2955796c8dcSSimon Schubert       dyn->d_un.d_val = sec->size;
2965796c8dcSSimon Schubert       break;
2975796c8dcSSimon Schubert     }
2985796c8dcSSimon Schubert   return TRUE;
2995796c8dcSSimon Schubert }
3005796c8dcSSimon Schubert 
3015796c8dcSSimon Schubert 
302