aboutsummaryrefslogtreecommitdiff
path: root/include/elf
AgeCommit message (Expand)AuthorFilesLines
1995-11-28 * internal.h (struct elf_segment_map): Define.Ian Lance Taylor2-0/+250
1995-03-08fix typoMichael Meissner1-1/+1
1995-03-08Add ppc.hMichael Meissner2-0/+31
1995-01-29(arc.h): New file, contains ARC specific ELF definitions.David Edelsohn2-1/+80
1995-01-24Add EM_PPC macro.Michael Meissner1-0/+17
1994-11-30Initial ARC support.David Edelsohn1-0/+34
1994-06-17unsanitize v9Ken Raeburn1-30/+0
1994-05-16 * common.h (EM_HPPA): Delete.Jeff Law2-0/+21
1994-03-08Set Emacs local variables to never use version control.Ian Lance Taylor1-1/+4
1994-03-05 * internal.h: Remove Elf32_*, Elf64_* typedefs. These namesPeter Schauer2-16/+116
1994-02-02 * common.h: Add comments regarding value of EM_HPPA and how toJim Kingdon1-0/+46
1993-10-12 * mips.h: New file. MIPS ABI specific information.Ian Lance Taylor2-1/+153
1993-08-02Remove '.Sanitize' from explicit list of Things-to-lose. It is now implicitlyFred Fish1-1/+0
1993-07-30Add .Sanitize to Things-to-lose list.Fred Fish1-0/+2
1993-05-27added things-to-lose sectionsK. Richard Pixley1-0/+2
1993-05-27honor verbose flagK. Richard Pixley1-2/+12
1993-05-25add elf64 structures/macros/types, rename some old elf->elf32Ken Raeburn1-0/+19
1993-04-20Remove chill sanitizations.Fred Fish1-29/+0
1992-11-16First cut at sanitizing away chill stuff.Fred Fish1-3/+28
1992-11-15 * dwarf.h (AT_src_coords): Whitespace change only.Fred Fish2-3/+321
1992-08-01 * dwarf.h: Replace with current version from gcc distribution.Fred Fish2-0/+209
1991-12-01Initial revisionSteve Chamberlain1-0/+41
78 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
/* Plugin support for BFD.
   Copyright 2009
   Free Software Foundation, Inc.

   This file is part of BFD, the Binary File Descriptor library.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
   MA 02110-1301, USA.  */

#include "config.h"
#include <assert.h>
#include <dlfcn.h>
#include <stdarg.h>
#include "plugin-api.h"
#include "sysdep.h"
#include "plugin.h"
#include "libbfd.h"
#include "libiberty.h"
#include <dirent.h>

#define bfd_plugin_close_and_cleanup                  _bfd_generic_close_and_cleanup
#define bfd_plugin_bfd_free_cached_info               _bfd_generic_bfd_free_cached_info
#define bfd_plugin_new_section_hook                   _bfd_generic_new_section_hook
#define bfd_plugin_get_section_contents               _bfd_generic_get_section_contents
#define bfd_plugin_get_section_contents_in_window     _bfd_generic_get_section_contents_in_window
#define bfd_plugin_bfd_copy_private_header_data       _bfd_generic_bfd_copy_private_header_data
#define bfd_plugin_bfd_merge_private_bfd_data         _bfd_generic_bfd_merge_private_bfd_data
#define bfd_plugin_bfd_copy_private_header_data       _bfd_generic_bfd_copy_private_header_data
#define bfd_plugin_bfd_set_private_flags              _bfd_generic_bfd_set_private_flags
#define bfd_plugin_core_file_matches_executable_p     generic_core_file_matches_executable_p
#define bfd_plugin_bfd_is_local_label_name            _bfd_nosymbols_bfd_is_local_label_name
#define bfd_plugin_bfd_is_target_special_symbol       ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
#define bfd_plugin_get_lineno                         _bfd_nosymbols_get_lineno
#define bfd_plugin_find_nearest_line                  _bfd_nosymbols_find_nearest_line
#define bfd_plugin_find_inliner_info                  _bfd_nosymbols_find_inliner_info
#define bfd_plugin_bfd_make_debug_symbol              _bfd_nosymbols_bfd_make_debug_symbol
#define bfd_plugin_read_minisymbols                   _bfd_generic_read_minisymbols
#define bfd_plugin_minisymbol_to_symbol               _bfd_generic_minisymbol_to_symbol
#define bfd_plugin_set_arch_mach                      bfd_default_set_arch_mach
#define bfd_plugin_set_section_contents               _bfd_generic_set_section_contents
#define bfd_plugin_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
#define bfd_plugin_bfd_relax_section                  bfd_generic_relax_section
#define bfd_plugin_bfd_link_hash_table_create         _bfd_generic_link_hash_table_create
#define bfd_plugin_bfd_link_hash_table_free           _bfd_generic_link_hash_table_free
#define bfd_plugin_bfd_link_add_symbols               _bfd_generic_link_add_symbols
#define bfd_plugin_bfd_link_just_syms                 _bfd_generic_link_just_syms
#define bfd_plugin_bfd_final_link                     _bfd_generic_final_link
#define bfd_plugin_bfd_link_split_section             _bfd_generic_link_split_section
#define bfd_plugin_bfd_gc_sections                    bfd_generic_gc_sections
#define bfd_plugin_bfd_merge_sections                 bfd_generic_merge_sections
#define bfd_plugin_bfd_is_group_section               bfd_generic_is_group_section
#define bfd_plugin_bfd_discard_group                  bfd_generic_discard_group
#define bfd_plugin_section_already_linked             _bfd_generic_section_already_linked
#define bfd_plugin_bfd_define_common_symbol           bfd_generic_define_common_symbol

static enum ld_plugin_status
message (int level ATTRIBUTE_UNUSED,
	 const char * format, ...)
{
  va_list args;
  va_start (args, format);
  printf ("bfd plugin: ");
  vprintf (format, args);
  va_end (args);
  return LDPS_OK;
}

/* Register a claim-file handler. */
static ld_plugin_claim_file_handler claim_file;

static enum ld_plugin_status
register_claim_file (ld_plugin_claim_file_handler handler)
{
  claim_file = handler;
  return LDPS_OK;
}

static enum ld_plugin_status
add_symbols (void * handle,
	     int nsyms,
	     const struct ld_plugin_symbol * syms)
{
  bfd *abfd = handle;
  struct plugin_data_struct *plugin_data =
    bfd_alloc (abfd, sizeof (plugin_data_struct));;

  plugin_data->nsyms = nsyms;
  plugin_data->syms = syms;

  if (nsyms != 0)
    abfd->flags |= HAS_SYMS;

  abfd->tdata.plugin_data = plugin_data;
  return LDPS_OK;
}

static const char *plugin_program_name;

void
bfd_plugin_set_program_name (const char *program_name)
{
  plugin_program_name = program_name;
}

static int
try_load_plugin (const char *pname)
{
  static void *plugin_handle;
  int tv_size = 4;
  struct ld_plugin_tv tv[tv_size];
  int i;
  ld_plugin_onload onload;
  enum ld_plugin_status status;

  plugin_handle = dlopen (pname, RTLD_NOW);
  if (!plugin_handle)
    {
      (*_bfd_error_handler)("%s\n", dlerror ());
      return 0;
    }

  onload = dlsym (plugin_handle, "onload");
  if (!onload)
    goto err;

  i = 0;
  tv[i].tv_tag = LDPT_MESSAGE;
  tv[i].tv_u.tv_message = message;

  ++i;
  tv[i].tv_tag = LDPT_REGISTER_CLAIM_FILE_HOOK;
  tv[i].tv_u.tv_register_claim_file = register_claim_file;

  ++i;
  tv[i].tv_tag = LDPT_ADD_SYMBOLS;
  tv[i].tv_u.tv_add_symbols = add_symbols;

  ++i;
  tv[i].tv_tag = LDPT_NULL;
  tv[i].tv_u.tv_val = 0;

  status = (*onload)(tv);

  if (status != LDPS_OK)
    goto err;

  if (!claim_file)
    goto err;

  return 1;

 err:
  plugin_handle = NULL;
  return 0;
}

static const char *plugin_name;

void
bfd_plugin_set_plugin (const char *p)
{
  plugin_name = p;
}

static int
load_plugin (void)
{
  char *plugin_dir;
  char *p;
  DIR *d;
  struct dirent *ent;
  int found = 0;

  if (plugin_name)
    return try_load_plugin (plugin_name);

  if (plugin_program_name == NULL)
    return 0;

  plugin_dir = concat (BINDIR, "/../lib/bfd-plugins", NULL);
  p = make_relative_prefix (plugin_program_name,
			    BINDIR,
			    plugin_dir);
  free (plugin_dir);
  plugin_dir = NULL;

  d = opendir (p);
  if (!d)
    goto out;

  while ((ent = readdir (d)))
    {
      char *full_name;
      struct stat s;

      full_name = concat (p, "/", ent->d_name, NULL);
      if (stat(full_name, &s) == 0 && S_ISREG (s.st_mode))
	found = try_load_plugin (full_name);
      free (full_name);
      if (found)
	break;
    }

 out:
  free (p);
  if (d)
    closedir (d);

  return found;
}


static const bfd_target *
bfd_plugin_object_p (bfd *abfd)
{
  int claimed = 0;
  int t = load_plugin ();
  struct ld_plugin_input_file file;
  if (!t)
    return NULL;

  file.name = abfd->filename;

  if (abfd->iostream)
    {
      file.fd = fileno (abfd->iostream);
      file.offset = 0;
      file.filesize = 0; /*FIXME*/
    }
  else
    {
      bfd *archive = abfd->my_archive;
      BFD_ASSERT (archive);
      file.fd = fileno (archive->iostream);
      file.offset = abfd->origin;
      file.filesize = arelt_size (abfd);

    }
  file.handle = abfd;
  claim_file (&file, &claimed);
  if (!claimed)
    return NULL;

  return abfd->xvec;
}

/* Copy any private info we understand from the input bfd
   to the output bfd.  */

static bfd_boolean
bfd_plugin_bfd_copy_private_bfd_data (bfd *ibfd ATTRIBUTE_UNUSED,
				      bfd *obfd ATTRIBUTE_UNUSED)
{
  BFD_ASSERT (0);
  return TRUE;
}

/* Copy any private info we understand from the input section
   to the output section.  */

static bfd_boolean
bfd_plugin_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED,
					  asection *isection ATTRIBUTE_UNUSED,
					  bfd *obfd ATTRIBUTE_UNUSED,
					  asection *osection ATTRIBUTE_UNUSED)
{
  BFD_ASSERT (0);
  return TRUE;
}

/* Copy any private info we understand from the input symbol
   to the output symbol.  */

static bfd_boolean
bfd_plugin_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED,
					 asymbol *isymbol ATTRIBUTE_UNUSED,
					 bfd *obfd ATTRIBUTE_UNUSED,
					 asymbol *osymbol ATTRIBUTE_UNUSED)
{
  BFD_ASSERT (0);
  return TRUE;
}

static bfd_boolean
bfd_plugin_bfd_print_private_bfd_data (bfd *abfd ATTRIBUTE_UNUSED, PTR ptr ATTRIBUTE_UNUSED)
{
  BFD_ASSERT (0);
  return TRUE;
}

static char *
bfd_plugin_core_file_failing_command (bfd *abfd ATTRIBUTE_UNUSED)
{
  BFD_ASSERT (0);
  return NULL;
}

static int
bfd_plugin_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
{
  BFD_ASSERT (0);
  return 0;
}

static long
bfd_plugin_get_symtab_upper_bound (bfd *abfd)
{
  struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
  long nsyms = plugin_data->nsyms;

  BFD_ASSERT (nsyms >= 0);

  return ((nsyms + 1) * sizeof (asymbol *));
}

static flagword
convert_flags (const struct ld_plugin_symbol *sym)
{
 switch (sym->def)
   { 
   case LDPK_DEF:
   case LDPK_COMMON:
   case LDPK_UNDEF:
     return BSF_GLOBAL;

   case LDPK_WEAKUNDEF:
   case LDPK_WEAKDEF:
     return BSF_GLOBAL | BSF_WEAK;

   default:
     BFD_ASSERT (0);
     return 0;
   }
}

static long
bfd_plugin_canonicalize_symtab (bfd *abfd,
				asymbol **alocation)
{
  struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
  long nsyms = plugin_data->nsyms;
  const struct ld_plugin_symbol *syms = plugin_data->syms;
  static asection fake_section;
  static asection fake_common_section;
  int i;

  fake_section.name = ".text";
  fake_common_section.flags = SEC_IS_COMMON;

  for (i = 0; i < nsyms; i++)
    {
      asymbol *s = bfd_alloc (abfd, sizeof (asymbol)); 

      BFD_ASSERT (s);
      alocation[i] = s;

      s->the_bfd = abfd;
      s->name = syms[i].name;
      s->value = 0;
      s->flags = convert_flags (&syms[i]);
      switch (syms[i].def)
	{
	case LDPK_COMMON:
	  s->section = &fake_common_section;
	  break;
	case LDPK_UNDEF:
	case LDPK_WEAKUNDEF:
	  s->section = bfd_und_section_ptr;
	  break;
	case LDPK_DEF:
	case LDPK_WEAKDEF:
	  s->section = &fake_section;
	  break;
	default:
	  BFD_ASSERT (0);
	}

      s->udata.p = (void *) &syms[i];
    }

  return nsyms;
}

static void
bfd_plugin_print_symbol (bfd *abfd ATTRIBUTE_UNUSED,
			 PTR afile ATTRIBUTE_UNUSED,
			 asymbol *symbol ATTRIBUTE_UNUSED,
			 bfd_print_symbol_type how ATTRIBUTE_UNUSED)
{
  BFD_ASSERT (0);
}

static void
bfd_plugin_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
			    asymbol *symbol,
			    symbol_info *ret)
{
  bfd_symbol_info (symbol, ret);
}

/* Make an empty symbol. */

static asymbol *
bfd_plugin_make_empty_symbol (bfd *abfd)
{
  asymbol *new_symbol = bfd_zalloc (abfd, sizeof (asymbol));
  if (new_symbol == NULL)
    return new_symbol;
  new_symbol->the_bfd = abfd;
  return new_symbol;
}

static int
bfd_plugin_sizeof_headers (bfd *a ATTRIBUTE_UNUSED,
			   struct bfd_link_info *info ATTRIBUTE_UNUSED)
{
  BFD_ASSERT (0);
  return 0;
}

static bfd_boolean
bfd_plugin_mkobject (bfd *abfd ATTRIBUTE_UNUSED)
{
  BFD_ASSERT (0);
  return 0;
}

const bfd_target plugin_vec =
{
  "plugin",			/* Name.  */
  bfd_target_unknown_flavour,
  BFD_ENDIAN_LITTLE,		/* Target byte order.  */
  BFD_ENDIAN_LITTLE,		/* Target headers byte order.  */
  (HAS_RELOC | EXEC_P |		/* Object flags.  */
   HAS_LINENO | HAS_DEBUG |
   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
  (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
   | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
  0,				/* symbol_leading_char.  */
  '/',				/* ar_pad_char.  */
  15,				/* ar_max_namelen.  */

  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
  bfd_getl32, bfd_getl_signed_32, bfd_putl32,
  bfd_getl16, bfd_getl_signed_16, bfd_putl16,	/* data */
  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
  bfd_getl32, bfd_getl_signed_32, bfd_putl32,
  bfd_getl16, bfd_getl_signed_16, bfd_putl16,	/* hdrs */

  {				/* bfd_check_format.  */
    _bfd_dummy_target,
    bfd_plugin_object_p,
    bfd_generic_archive_p,
    _bfd_dummy_target
  },
  {				/* bfd_set_format.  */
    bfd_false,
    bfd_plugin_mkobject,
    _bfd_generic_mkarchive,
    bfd_false,
  },
  {				/* bfd_write_contents.  */
    bfd_false,
    bfd_false,
    _bfd_write_archive_contents,
    bfd_false,
  },

  BFD_JUMP_TABLE_GENERIC (bfd_plugin),
  BFD_JUMP_TABLE_COPY (bfd_plugin),
  BFD_JUMP_TABLE_CORE (bfd_plugin),
  BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
  BFD_JUMP_TABLE_SYMBOLS (bfd_plugin),
  BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
  BFD_JUMP_TABLE_WRITE (bfd_plugin),
  BFD_JUMP_TABLE_LINK (bfd_plugin),
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),

  NULL,

  NULL  			/* backend_data.  */
};