Subversion Repositories Kolibri OS

Rev

Rev 5197 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5197 serge 1
/* VxWorks support for ELF
6324 serge 2
   Copyright (C) 2005-2015 Free Software Foundation, Inc.
5197 serge 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. */
6324 serge 67
  if ((bfd_link_pic (info) || abfd->flags & DYNAMIC)
5197 serge 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
 
6324 serge 92
  if (!bfd_link_pic (info))
5197 serge 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