Subversion Repositories Kolibri OS

Rev

Rev 5197 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5197 Rev 6324
Line 1... Line 1...
1
/* ELF STT_GNU_IFUNC support.
1
/* ELF STT_GNU_IFUNC support.
2
   Copyright 2009-2013
-
 
3
   Free Software Foundation, Inc.
2
   Copyright (C) 2009-2015 Free Software Foundation, Inc.
Line 4... Line 3...
4
 
3
 
Line 5... Line 4...
5
   This file is part of BFD, the Binary File Descriptor library.
4
   This file is part of BFD, the Binary File Descriptor library.
6
 
5
 
Line 52... Line 51...
52
  else
51
  else
53
    pltflags |= SEC_ALLOC | SEC_CODE | SEC_LOAD;
52
    pltflags |= SEC_ALLOC | SEC_CODE | SEC_LOAD;
54
  if (bed->plt_readonly)
53
  if (bed->plt_readonly)
55
    pltflags |= SEC_READONLY;
54
    pltflags |= SEC_READONLY;
Line 56... Line 55...
56
 
55
 
57
  if (info->shared)
56
  if (bfd_link_pic (info))
58
    {
57
    {
59
      /* We need to create .rel[a].ifunc for shared objects.  */
58
      /* We need to create .rel[a].ifunc for shared objects.  */
60
      const char *rel_sec = (bed->rela_plts_and_copies_p
59
      const char *rel_sec = (bed->rela_plts_and_copies_p
Line 124... Line 123...
124
  /* When a shared library references a STT_GNU_IFUNC symbol defined
123
  /* When a shared library references a STT_GNU_IFUNC symbol defined
125
     in executable, the address of the resolved function may be used.
124
     in executable, the address of the resolved function may be used.
126
     But in non-shared executable, the address of its .plt slot may
125
     But in non-shared executable, the address of its .plt slot may
127
     be used.  Pointer equality may not work correctly.  PIE should
126
     be used.  Pointer equality may not work correctly.  PIE should
128
     be used if pointer equality is required here.  */
127
     be used if pointer equality is required here.  */
129
  if (!info->shared
128
  if (!bfd_link_pic (info)
130
      && (h->dynindx != -1
129
      && (h->dynindx != -1
131
	  || info->export_dynamic)
130
	  || info->export_dynamic)
132
      && h->pointer_equality_needed)
131
      && h->pointer_equality_needed)
133
    {
132
    {
134
      info->callbacks->einfo
133
      info->callbacks->einfo
Line 144... Line 143...
144
  htab = elf_hash_table (info);
143
  htab = elf_hash_table (info);
Line 145... Line 144...
145
 
144
 
146
  /* When building shared library, we need to handle the case where it is
145
  /* When building shared library, we need to handle the case where it is
147
     marked with regular reference, but not non-GOT reference since the
146
     marked with regular reference, but not non-GOT reference since the
148
     non-GOT reference bit may not be set here.  */
147
     non-GOT reference bit may not be set here.  */
149
  if (info->shared && !h->non_got_ref && h->ref_regular)
148
  if (bfd_link_pic (info) && !h->non_got_ref && h->ref_regular)
150
    for (p = *head; p != NULL; p = p->next)
149
    for (p = *head; p != NULL; p = p->next)
151
      if (p->count)
150
      if (p->count)
152
	{
151
	{
153
	  h->non_got_ref = 1;
152
	  h->non_got_ref = 1;
Line 219... Line 218...
219
  relplt->size += sizeof_reloc;
218
  relplt->size += sizeof_reloc;
220
  relplt->reloc_count++;
219
  relplt->reloc_count++;
Line 221... Line 220...
221
 
220
 
222
  /* We need dynamic relocation for STT_GNU_IFUNC symbol only when
221
  /* We need dynamic relocation for STT_GNU_IFUNC symbol only when
223
     there is a non-GOT reference in a shared object.  */
222
     there is a non-GOT reference in a shared object.  */
224
  if (!info->shared
223
  if (!bfd_link_pic (info)
225
      || !h->non_got_ref)
224
      || !h->non_got_ref)
Line 226... Line 225...
226
    *head = NULL;
225
    *head = NULL;
227
 
226
 
Line 251... Line 250...
251
     4. Use .got.plt if .got isn't used.
250
     4. Use .got.plt if .got isn't used.
252
     5. Otherwise use .got so that it can be shared among different
251
     5. Otherwise use .got so that it can be shared among different
253
     objects at run-time.
252
     objects at run-time.
254
     We only need to relocate .got entry in shared object.  */
253
     We only need to relocate .got entry in shared object.  */
255
  if (h->got.refcount <= 0
254
  if (h->got.refcount <= 0
256
      || (info->shared
255
      || (bfd_link_pic (info)
257
	  && (h->dynindx == -1
256
	  && (h->dynindx == -1
258
	      || h->forced_local))
257
	      || h->forced_local))
259
      || (!info->shared
258
      || (!bfd_link_pic (info)
260
	  && !h->pointer_equality_needed)
259
	  && !h->pointer_equality_needed)
261
      || (info->executable && info->shared)
260
      || bfd_link_pie (info)
262
      || htab->sgot == NULL)
261
      || htab->sgot == NULL)
263
    {
262
    {
264
      /* Use .got.plt.  */
263
      /* Use .got.plt.  */
265
      h->got.offset = (bfd_vma) -1;
264
      h->got.offset = (bfd_vma) -1;
266
    }
265
    }
267
  else
266
  else
268
    {
267
    {
269
      h->got.offset = htab->sgot->size;
268
      h->got.offset = htab->sgot->size;
270
      htab->sgot->size += got_entry_size;
269
      htab->sgot->size += got_entry_size;
271
      if (info->shared)
270
      if (bfd_link_pic (info))
272
	htab->srelgot->size += sizeof_reloc;
271
	htab->srelgot->size += sizeof_reloc;
273
    }
272
    }
Line 274... Line 273...
274
 
273
 
275
  return TRUE;
274
  return TRUE;
-
 
275
}
-
 
276
 
-
 
277
/* Similar to _bfd_elf_get_synthetic_symtab, optimized for unsorted PLT
-
 
278
   entries.  PLT is the PLT section.  PLT_SYM_VAL is a function pointer
-
 
279
   which returns an array of PLT entry symbol values.  */
-
 
280
 
-
 
281
long
-
 
282
_bfd_elf_ifunc_get_synthetic_symtab
-
 
283
  (bfd *abfd, long symcount ATTRIBUTE_UNUSED,
-
 
284
   asymbol **syms ATTRIBUTE_UNUSED, long dynsymcount, asymbol **dynsyms,
-
 
285
   asymbol **ret, asection *plt,
-
 
286
   bfd_vma *(*get_plt_sym_val) (bfd *, asymbol **, asection *, asection *))
-
 
287
{
-
 
288
  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-
 
289
  asection *relplt;
-
 
290
  asymbol *s;
-
 
291
  const char *relplt_name;
-
 
292
  bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
-
 
293
  arelent *p;
-
 
294
  long count, i, n;
-
 
295
  size_t size;
-
 
296
  Elf_Internal_Shdr *hdr;
-
 
297
  char *names;
-
 
298
  bfd_vma *plt_sym_val;
-
 
299
 
-
 
300
  *ret = NULL;
-
 
301
 
-
 
302
  if (plt == NULL)
-
 
303
    return 0;
-
 
304
 
-
 
305
  if ((abfd->flags & (DYNAMIC | EXEC_P)) == 0)
-
 
306
    return 0;
-
 
307
 
-
 
308
  if (dynsymcount <= 0)
-
 
309
    return 0;
-
 
310
 
-
 
311
  relplt_name = bed->relplt_name;
-
 
312
  if (relplt_name == NULL)
-
 
313
    relplt_name = bed->rela_plts_and_copies_p ? ".rela.plt" : ".rel.plt";
-
 
314
  relplt = bfd_get_section_by_name (abfd, relplt_name);
-
 
315
  if (relplt == NULL)
-
 
316
    return 0;
-
 
317
 
-
 
318
  hdr = &elf_section_data (relplt)->this_hdr;
-
 
319
  if (hdr->sh_link != elf_dynsymtab (abfd)
-
 
320
      || (hdr->sh_type != SHT_REL && hdr->sh_type != SHT_RELA))
-
 
321
    return 0;
-
 
322
 
-
 
323
  slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
-
 
324
  if (! (*slurp_relocs) (abfd, relplt, dynsyms, TRUE))
-
 
325
    return -1;
-
 
326
 
-
 
327
  count = relplt->size / hdr->sh_entsize;
-
 
328
  size = count * sizeof (asymbol);
-
 
329
  p = relplt->relocation;
-
 
330
  for (i = 0; i < count; i++, p += bed->s->int_rels_per_ext_rel)
-
 
331
    {
-
 
332
      size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt");
-
 
333
      if (p->addend != 0)
-
 
334
	{
-
 
335
#ifdef BFD64
-
 
336
	  size += sizeof ("+0x") - 1 + 8 + 8 * (bed->s->elfclass == ELFCLASS64);
-
 
337
#else
-
 
338
	  size += sizeof ("+0x") - 1 + 8;
-
 
339
#endif
-
 
340
	}
-
 
341
    }
-
 
342
 
-
 
343
  plt_sym_val = get_plt_sym_val (abfd, dynsyms, plt, relplt);
-
 
344
  if (plt_sym_val == NULL)
-
 
345
    return -1;
-
 
346
 
-
 
347
  s = *ret = (asymbol *) bfd_malloc (size);
-
 
348
  if (s == NULL)
-
 
349
    {
-
 
350
      free (plt_sym_val);
-
 
351
      return -1;
-
 
352
    }
-
 
353
 
-
 
354
  names = (char *) (s + count);
-
 
355
  p = relplt->relocation;
-
 
356
  n = 0;
-
 
357
  for (i = 0; i < count; i++, p += bed->s->int_rels_per_ext_rel)
-
 
358
    {
-
 
359
      size_t len;
-
 
360
      bfd_vma addr;
-
 
361
 
-
 
362
      addr = plt_sym_val[i];
-
 
363
      if (addr == (bfd_vma) -1)
-
 
364
	continue;
-
 
365
 
-
 
366
      *s = **p->sym_ptr_ptr;
-
 
367
      /* Undefined syms won't have BSF_LOCAL or BSF_GLOBAL set.  Since
-
 
368
	 we are defining a symbol, ensure one of them is set.  */
-
 
369
      if ((s->flags & BSF_LOCAL) == 0)
-
 
370
	s->flags |= BSF_GLOBAL;
-
 
371
      s->flags |= BSF_SYNTHETIC;
-
 
372
      s->section = plt;
-
 
373
      s->value = addr - plt->vma;
-
 
374
      s->name = names;
-
 
375
      s->udata.p = NULL;
-
 
376
      len = strlen ((*p->sym_ptr_ptr)->name);
-
 
377
      memcpy (names, (*p->sym_ptr_ptr)->name, len);
-
 
378
      names += len;
-
 
379
      if (p->addend != 0)
-
 
380
	{
-
 
381
	  char buf[30], *a;
-
 
382
 
-
 
383
	  memcpy (names, "+0x", sizeof ("+0x") - 1);
-
 
384
	  names += sizeof ("+0x") - 1;
-
 
385
	  bfd_sprintf_vma (abfd, buf, p->addend);
-
 
386
	  for (a = buf; *a == '0'; ++a)
-
 
387
	    ;
-
 
388
	  len = strlen (a);
-
 
389
	  memcpy (names, a, len);
-
 
390
	  names += len;
-
 
391
	}
-
 
392
      memcpy (names, "@plt", sizeof ("@plt"));
-
 
393
      names += sizeof ("@plt");
-
 
394
      ++s, ++n;
-
 
395
    }
-
 
396
 
-
 
397
  free (plt_sym_val);
-
 
398
 
-
 
399
  return n;