Merge branch 'vendor/GCC50'
[dragonfly.git] / contrib / binutils-2.25 / bfd / elf-vxworks.c
1 /* VxWorks support for ELF
2    Copyright (C) 2005-2014 Free Software Foundation, Inc.
3
4    This file is part of BFD, the Binary File Descriptor library.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19    MA 02111-1307, USA.  */
20
21 /* This file provides routines used by all VxWorks targets.  */
22
23 #include "sysdep.h"
24 #include "bfd.h"
25 #include "libbfd.h"
26 #include "elf-bfd.h"
27 #include "elf-vxworks.h"
28 #include "elf/vxworks.h"
29
30 /* Return true if symbol NAME, as defined by ABFD, is one of the special
31    __GOTT_BASE__ or __GOTT_INDEX__ symbols.  */
32
33 static bfd_boolean
34 elf_vxworks_gott_symbol_p (bfd *abfd, const char *name)
35 {
36   char leading;
37
38   leading = bfd_get_symbol_leading_char (abfd);
39   if (leading)
40     {
41       if (*name != leading)
42         return FALSE;
43       name++;
44     }
45   return (strcmp (name, "__GOTT_BASE__") == 0
46           || strcmp (name, "__GOTT_INDEX__") == 0);
47 }
48
49 /* Tweak magic VxWorks symbols as they are loaded.  */
50 bfd_boolean
51 elf_vxworks_add_symbol_hook (bfd *abfd,
52                              struct bfd_link_info *info,
53                              Elf_Internal_Sym *sym,
54                              const char **namep,
55                              flagword *flagsp,
56                              asection **secp ATTRIBUTE_UNUSED,
57                              bfd_vma *valp ATTRIBUTE_UNUSED)
58 {
59   /* Ideally these "magic" symbols would be exported by libc.so.1
60      which would be found via a DT_NEEDED tag, and then handled
61      specially by the linker at runtime.  Except shared libraries
62      don't even link to libc.so.1 by default...
63      If the symbol is imported from, or will be put in a shared library,
64      give the symbol weak binding to get the desired samantics.
65      This transformation will be undone in
66      elf_i386_vxworks_link_output_symbol_hook. */
67   if ((info->shared || abfd->flags & DYNAMIC)
68       && elf_vxworks_gott_symbol_p (abfd, *namep))
69     {
70       sym->st_info = ELF_ST_INFO (STB_WEAK, ELF_ST_TYPE (sym->st_info));
71       *flagsp |= BSF_WEAK;
72     }
73
74   return TRUE;
75 }
76
77 /* Perform VxWorks-specific handling of the create_dynamic_sections hook.
78    When creating an executable, set *SRELPLT2_OUT to the .rel(a).plt.unloaded
79    section.  */
80
81 bfd_boolean
82 elf_vxworks_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info,
83                                      asection **srelplt2_out)
84 {
85   struct elf_link_hash_table *htab;
86   const struct elf_backend_data *bed;
87   asection *s;
88
89   htab = elf_hash_table (info);
90   bed = get_elf_backend_data (dynobj);
91
92   if (!info->shared)
93     {
94       s = bfd_make_section_anyway_with_flags (dynobj,
95                                               bed->default_use_rela_p
96                                               ? ".rela.plt.unloaded"
97                                               : ".rel.plt.unloaded",
98                                               SEC_HAS_CONTENTS | SEC_IN_MEMORY
99                                               | SEC_READONLY
100                                               | SEC_LINKER_CREATED);
101       if (s == NULL
102           || !bfd_set_section_alignment (dynobj, s, bed->s->log_file_align))
103         return FALSE;
104
105       *srelplt2_out = s;
106     }
107
108   /* Mark the GOT and PLT symbols as having relocations; they might
109      not, but we won't know for sure until we build the GOT in
110      finish_dynamic_symbol.  Also make sure that the GOT symbol
111      is entered into the dynamic symbol table; the loader uses it
112      to initialize __GOTT_BASE__[__GOTT_INDEX__].  */
113   if (htab->hgot)
114     {
115       htab->hgot->indx = -2;
116       htab->hgot->other &= ~ELF_ST_VISIBILITY (-1);
117       htab->hgot->forced_local = 0;
118       if (!bfd_elf_link_record_dynamic_symbol (info, htab->hgot))
119         return FALSE;
120     }
121   if (htab->hplt)
122     {
123       htab->hplt->indx = -2;
124       htab->hplt->type = STT_FUNC;
125     }
126
127   return TRUE;
128 }
129
130 /* Tweak magic VxWorks symbols as they are written to the output file.  */
131 int
132 elf_vxworks_link_output_symbol_hook (struct bfd_link_info *info
133                                        ATTRIBUTE_UNUSED,
134                                      const char *name,
135                                      Elf_Internal_Sym *sym,
136                                      asection *input_sec ATTRIBUTE_UNUSED,
137                                      struct elf_link_hash_entry *h)
138 {
139   /* Reverse the effects of the hack in elf_vxworks_add_symbol_hook.  */
140   if (h
141       && h->root.type == bfd_link_hash_undefweak
142       && elf_vxworks_gott_symbol_p (h->root.u.undef.abfd, name))
143     sym->st_info = ELF_ST_INFO (STB_GLOBAL, ELF_ST_TYPE (sym->st_info));
144
145   return 1;
146 }
147
148 /* Copy relocations into the output file.  Fixes up relocations against PLT
149    entries, then calls the generic routine.  */
150
151 bfd_boolean
152 elf_vxworks_emit_relocs (bfd *output_bfd,
153                          asection *input_section,
154                          Elf_Internal_Shdr *input_rel_hdr,
155                          Elf_Internal_Rela *internal_relocs,
156                          struct elf_link_hash_entry **rel_hash)
157 {
158   const struct elf_backend_data *bed;
159   int j;
160
161   bed = get_elf_backend_data (output_bfd);
162
163   if (output_bfd->flags & (DYNAMIC|EXEC_P))
164     {
165       Elf_Internal_Rela *irela;
166       Elf_Internal_Rela *irelaend;
167       struct elf_link_hash_entry **hash_ptr;
168
169       for (irela = internal_relocs,
170              irelaend = irela + (NUM_SHDR_ENTRIES (input_rel_hdr)
171                                  * bed->s->int_rels_per_ext_rel),
172              hash_ptr = rel_hash;
173            irela < irelaend;
174            irela += bed->s->int_rels_per_ext_rel,
175              hash_ptr++)
176         {
177           if (*hash_ptr
178               && (*hash_ptr)->def_dynamic
179               && !(*hash_ptr)->def_regular
180               && ((*hash_ptr)->root.type == bfd_link_hash_defined
181                   || (*hash_ptr)->root.type == bfd_link_hash_defweak)
182               && (*hash_ptr)->root.u.def.section->output_section != NULL)
183             {
184               /* This is a relocation from an executable or shared
185                  library against a symbol in a different shared
186                  library.  We are creating a definition in the output
187                  file but it does not come from any of our normal (.o)
188                  files. ie. a PLT stub.  Normally this would be a
189                  relocation against against SHN_UNDEF with the VMA of
190                  the PLT stub.  This upsets the VxWorks loader.
191                  Convert it to a section-relative relocation.  This
192                  gets some other symbols (for instance .dynbss), but
193                  is conservatively correct.  */
194               for (j = 0; j < bed->s->int_rels_per_ext_rel; j++)
195                 {
196                   asection *sec = (*hash_ptr)->root.u.def.section;
197                   int this_idx = sec->output_section->target_index;
198
199                   irela[j].r_info
200                     = ELF32_R_INFO (this_idx, ELF32_R_TYPE (irela[j].r_info));
201                   irela[j].r_addend += (*hash_ptr)->root.u.def.value;
202                   irela[j].r_addend += sec->output_offset;
203                 }
204               /* Stop the generic routine adjusting this entry.  */
205               *hash_ptr = NULL;
206             }
207         }
208     }
209   return _bfd_elf_link_output_relocs (output_bfd, input_section,
210                                       input_rel_hdr, internal_relocs,
211                                       rel_hash);
212 }
213
214
215 /* Set the sh_link and sh_info fields on the static plt relocation secton.  */
216
217 void
218 elf_vxworks_final_write_processing (bfd *abfd,
219                                     bfd_boolean linker ATTRIBUTE_UNUSED)
220 {
221   asection * sec;
222   struct bfd_elf_section_data *d;
223
224   sec = bfd_get_section_by_name (abfd, ".rel.plt.unloaded");
225   if (!sec)
226     sec = bfd_get_section_by_name (abfd, ".rela.plt.unloaded");
227   if (!sec)
228     return;
229   d = elf_section_data (sec);
230   d->this_hdr.sh_link = elf_onesymtab (abfd);
231   sec = bfd_get_section_by_name (abfd, ".plt");
232   if (sec)
233     d->this_hdr.sh_info = elf_section_data (sec)->this_idx;
234 }
235
236 /* Add the dynamic entries required by VxWorks.  These point to the
237    tls sections.  */
238
239 bfd_boolean
240 elf_vxworks_add_dynamic_entries (bfd *output_bfd, struct bfd_link_info *info)
241 {
242   if (bfd_get_section_by_name (output_bfd, ".tls_data"))
243     {
244       if (!_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_DATA_START, 0)
245           || !_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_DATA_SIZE, 0)
246           || !_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_DATA_ALIGN, 0))
247         return FALSE;
248     }
249   if (bfd_get_section_by_name (output_bfd, ".tls_vars"))
250     {
251       if (!_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_VARS_START, 0)
252           || !_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_VARS_SIZE, 0))
253         return FALSE;
254     }
255   return TRUE;
256 }
257
258 /* If *DYN is one of the VxWorks-specific dynamic entries, then fill
259    in the value now  and return TRUE.  Otherwise return FALSE.  */
260
261 bfd_boolean
262 elf_vxworks_finish_dynamic_entry (bfd *output_bfd, Elf_Internal_Dyn *dyn)
263 {
264   asection *sec;
265
266   switch (dyn->d_tag)
267     {
268     default:
269       return FALSE;
270
271     case DT_VX_WRS_TLS_DATA_START:
272       sec = bfd_get_section_by_name (output_bfd, ".tls_data");
273       dyn->d_un.d_ptr = sec->vma;
274       break;
275
276     case DT_VX_WRS_TLS_DATA_SIZE:
277       sec = bfd_get_section_by_name (output_bfd, ".tls_data");
278       dyn->d_un.d_val = sec->size;
279       break;
280
281     case DT_VX_WRS_TLS_DATA_ALIGN:
282       sec = bfd_get_section_by_name (output_bfd, ".tls_data");
283       dyn->d_un.d_val
284         = (bfd_size_type)1 << bfd_get_section_alignment (output_bfd,
285                                                          sec);
286       break;
287
288     case DT_VX_WRS_TLS_VARS_START:
289       sec = bfd_get_section_by_name (output_bfd, ".tls_vars");
290       dyn->d_un.d_ptr = sec->vma;
291       break;
292
293     case DT_VX_WRS_TLS_VARS_SIZE:
294       sec = bfd_get_section_by_name (output_bfd, ".tls_vars");
295       dyn->d_un.d_val = sec->size;
296       break;
297     }
298   return TRUE;
299 }
300
301