Пример #1
0
/* Standard plugin API entry point.  */
enum ld_plugin_status
onload (struct ld_plugin_tv *tv)
{
  size_t n = 0;
  enum ld_plugin_status rv;

  /* This plugin does nothing but dump the tv array.  It would
     be an error if this function was called without one.  */
  if (!tv)
    return LDPS_ERR;

  /* First entry should always be LDPT_MESSAGE, letting us get
     hold of it easily so we can send output straight away.  */
  if (tv[0].tv_tag == LDPT_MESSAGE)
    tv_message = tv[0].tv_u.tv_message;

  fflush (NULL);
  TV_MESSAGE (LDPL_INFO, "Hello from testplugin.");

  do
    if ((rv = parse_and_dump_tv_tag (n++, tv)) != LDPS_OK)
      return rv;
  while ((tv++)->tv_tag != LDPT_NULL);

  /* Register hooks only if instructed by options.  */
  if (register_claimfile_hook)
    {
      if (!tv_register_claim_file)
	{
	  TV_MESSAGE (LDPL_FATAL, "No register_claim_file hook");
	  fflush (NULL);
	  return LDPS_ERR;
	}
      (*tv_register_claim_file) (onclaim_file);
    }
  if (register_allsymbolsread_hook)
    {
      if (!tv_register_all_symbols_read)
	{
	  TV_MESSAGE (LDPL_FATAL, "No register_all_symbols_read hook");
	  fflush (NULL);
	  return LDPS_ERR;
	}
      (*tv_register_all_symbols_read) (onall_symbols_read);
    }
  if (register_cleanup_hook)
    {
      if (!tv_register_cleanup)
	{
	  TV_MESSAGE (LDPL_FATAL, "No register_cleanup hook");
	  fflush (NULL);
	  return LDPS_ERR;
	}
      (*tv_register_cleanup) (oncleanup);
    }
  fflush (NULL);
  return onload_ret;
}
Пример #2
0
/* Standard plugin API registerable hook.  */
static enum ld_plugin_status
onall_symbols_read (void)
{
  static const char *resolutions[] =
    {
      "LDPR_UNKNOWN",
      "LDPR_UNDEF",
      "LDPR_PREVAILING_DEF",
      "LDPR_PREVAILING_DEF_IRONLY",
      "LDPR_PREEMPTED_REG",
      "LDPR_PREEMPTED_IR",
      "LDPR_RESOLVED_IR",
      "LDPR_RESOLVED_EXEC",
      "LDPR_RESOLVED_DYN",
      "LDPR_PREVAILING_DEF_IRONLY_EXP",
    };
  claim_file_t *claimfile = dumpresolutions ? claimfiles_list : NULL;
  add_file_t *addfile = addfiles_list;
  TV_MESSAGE (LDPL_INFO, "hook called: all symbols read.");
  for ( ; claimfile; claimfile = claimfile->next)
    {
      enum ld_plugin_status rv;
      int n;
      if (claimfile->n_syms_used && !tv_get_symbols_v2)
	return LDPS_ERR;
      else if (!claimfile->n_syms_used)
        continue;
      else if (!claimfile->file.handle)
        continue;
      rv = tv_get_symbols_v2 (claimfile->file.handle, claimfile->n_syms_used,
			      claimfile->symbols);
      if (rv != LDPS_OK)
	return rv;
      for (n = 0; n < claimfile->n_syms_used; n++)
	TV_MESSAGE (LDPL_INFO, "Sym: '%s%s%s' Resolution: %s",
		    claimfile->symbols[n].name,
		    claimfile->symbols[n].version ? "@" : "",
		    (claimfile->symbols[n].version
		     ? claimfile->symbols[n].version : ""),
		    resolutions[claimfile->symbols[n].resolution]);
    }
  for ( ; addfile ; addfile = addfile->next)
    {
      enum ld_plugin_status rv;
      if (addfile->type == ADD_LIB && tv_add_input_library)
	rv = (*tv_add_input_library) (addfile->name);
      else if (addfile->type == ADD_FILE && tv_add_input_file)
	rv = (*tv_add_input_file) (addfile->name);
      else if (addfile->type == ADD_DIR && tv_set_extra_library_path)
	rv = (*tv_set_extra_library_path) (addfile->name);
      else
	rv = LDPS_ERR;
      if (rv != LDPS_OK)
	return rv;
    }
  fflush (NULL);
  return all_symbols_read_ret;
}
Пример #3
0
/* Standard plugin API registerable hook.  */
static enum ld_plugin_status
oncleanup (void)
{
  TV_MESSAGE (LDPL_INFO, "hook called: cleanup.");
  fflush (NULL);
  return cleanup_ret;
}
Пример #4
0
/* Standard plugin API registerable hook.  */
static enum ld_plugin_status
onclaim_file (const struct ld_plugin_input_file *file, int *claimed)
{
  /* Let's see if we want to claim this file.  */
  claim_file_t *claimfile = claimfiles_list;
  while (claimfile)
    {
      if (!strcmp (file->name, claimfile->file.name))
	break;
      claimfile = claimfile->next;
    }

  /* Inform the user/testsuite.  */
  TV_MESSAGE (LDPL_INFO, "hook called: claim_file %s [@%ld/%ld] %s",
	      file->name, (long)file->offset, (long)file->filesize,
	      claimfile ? "CLAIMED" : "not claimed");
  fflush (NULL);

  /* If we decided to claim it, record that fact, and add any symbols
     that were defined for it by plugin options.  */
  *claimed = (claimfile != 0);
  if (claimfile)
    {
      claimfile->claimed = TRUE;
      claimfile->file = *file;
      if (claimfile->n_syms_used && !tv_add_symbols)
	return LDPS_ERR;
      else if (claimfile->n_syms_used)
	return (*tv_add_symbols) (claimfile->file.handle,
				claimfile->n_syms_used, claimfile->symbols);
    }

  return claim_file_ret;
}
Пример #5
0
/* Output contents of transfer vector array entry in human-readable form.  */
static void
dump_tv_tag (size_t n, struct ld_plugin_tv *tv)
{
  size_t tag;
  char unknownbuf[40];
  const char *name;

  for (tag = 0; tag < ARRAY_SIZE (tag_names); tag++)
    if (tag_names[tag].tag == tv->tv_tag)
      break;
  sprintf (unknownbuf, "unknown tag #%d", tv->tv_tag);
  name = (tag < ARRAY_SIZE (tag_names)) ? tag_names[tag].name : unknownbuf;
  switch (tv->tv_tag)
    {
      case LDPT_OPTION:
      case LDPT_OUTPUT_NAME:
	TV_MESSAGE (LDPL_INFO, "tv[%d]: %s '%s'", n, name,
		    tv->tv_u.tv_string);
        break;
      case LDPT_REGISTER_CLAIM_FILE_HOOK:
      case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
      case LDPT_REGISTER_CLEANUP_HOOK:
      case LDPT_ADD_SYMBOLS:
      case LDPT_GET_SYMBOLS:
      case LDPT_GET_SYMBOLS_V2:
      case LDPT_ADD_INPUT_FILE:
      case LDPT_MESSAGE:
      case LDPT_GET_INPUT_FILE:
      case LDPT_GET_VIEW:
      case LDPT_RELEASE_INPUT_FILE:
      case LDPT_ADD_INPUT_LIBRARY:
      case LDPT_SET_EXTRA_LIBRARY_PATH:
	TV_MESSAGE (LDPL_INFO, "tv[%d]: %s func@0x%p", n, name,
		    (void *)(tv->tv_u.tv_message));
        break;
      case LDPT_NULL:
      case LDPT_API_VERSION:
      case LDPT_GOLD_VERSION:
      case LDPT_LINKER_OUTPUT:
      case LDPT_GNU_LD_VERSION:
      default:
	TV_MESSAGE (LDPL_INFO, "tv[%d]: %s value %W (%d)", n, name,
		    (bfd_vma)tv->tv_u.tv_val, tv->tv_u.tv_val);
	break;
    }
}
Пример #6
0
/* Determine type of plugin option and pass to individual parsers.  */
static enum ld_plugin_status
parse_option (const char *opt)
{
  if (!strncmp ("fatal", opt, 5))
    {
      TV_MESSAGE (LDPL_FATAL, "Fatal error");
      fflush (NULL);
    }
  else if (!strncmp ("error", opt, 5))
    {
      TV_MESSAGE (LDPL_ERROR, "Error");
      fflush (NULL);
    }
  else if (!strncmp ("warning", opt, 7))
    {
      TV_MESSAGE (LDPL_WARNING, "Warning");
      fflush (NULL);
    }
  else if (!strncmp ("fail", opt, 4))
    return set_ret_val (opt + 4, LDPS_ERR);
  else if (!strncmp ("pass", opt, 4))
    return set_ret_val (opt + 4, LDPS_OK);
  else if (!strncmp ("register", opt, 8))
    return set_register_hook (opt + 8, TRUE);
  else if (!strncmp ("noregister", opt, 10))
    return set_register_hook (opt + 10, FALSE);
  else if (!strncmp ("claim:", opt, 6))
    return record_claim_file (opt + 6, 0);
  else if (!strncmp ("sym:", opt, 4))
    return record_claimed_file_symbol (opt + 4);
  else if (!strncmp ("add:", opt, 4))
    return record_add_file (opt + 4, ADD_FILE);
  else if (!strncmp ("lib:", opt, 4))
    return record_add_file (opt + 4, ADD_LIB);
  else if (!strncmp ("dir:", opt, 4))
    return record_add_file (opt + 4, ADD_DIR);
  else if (!strcmp ("dumpresolutions", opt))
    dumpresolutions = TRUE;
  else
    return LDPS_ERR;
  return LDPS_OK;
}
Пример #7
0
/* Standard plugin API registerable hook.  */
static enum ld_plugin_status
onclaim_file (const struct ld_plugin_input_file *file, int *claimed)
{
  /* Possible read of some bytes out of the input file into a buffer.  This
     simulates a plugin that reads some file content in order to decide if
     the file should be claimed or not.  */
  if (bytes_to_read_before_claim > 0)
    {
      char *buffer = malloc (bytes_to_read_before_claim);

      if (buffer == NULL)
        return LDPS_ERR;
      if (read (file->fd, buffer, bytes_to_read_before_claim) < 0)
        return LDPS_ERR;
      free (buffer);
    }

  /* Let's see if we want to claim this file.  */
  claim_file_t *claimfile = claimfiles_list;
  while (claimfile)
    {
      if (!strcmp (file->name, claimfile->file.name))
	break;
      claimfile = claimfile->next;
    }

  /* Inform the user/testsuite.  */
  TV_MESSAGE (LDPL_INFO, "hook called: claim_file %s [@%ld/%ld] %s",
	      file->name, (long)file->offset, (long)file->filesize,
	      claimfile ? "CLAIMED" : "not claimed");
  fflush (NULL);

  /* If we decided to claim it, record that fact, and add any symbols
     that were defined for it by plugin options.  */
  *claimed = (claimfile != 0);
  if (claimfile)
    {
      claimfile->claimed = TRUE;
      claimfile->file = *file;
      if (claimfile->n_syms_used && !tv_add_symbols)
	return LDPS_ERR;
      else if (claimfile->n_syms_used)
	return (*tv_add_symbols) (claimfile->file.handle,
				claimfile->n_syms_used, claimfile->symbols);
    }

  return claim_file_ret;
}
Пример #8
0
/* Standard plugin API registerable hook.  */
static enum ld_plugin_status
onclaim_file (const struct ld_plugin_input_file *file, int *claimed)
{
  /* Let's see if we want to claim this file.  */
  claim_file_t *claimfile = claimfiles_list;
  size_t len = strlen (file->name);
  char *name = xstrdup (file->name);
  char *p = name + len;
  bfd_boolean islib;

  /* Only match the file name without the directory part.  */
  islib = *p == 'a' && *(p - 1) == '.';
  for (; p != name; p--)
    if (IS_DIR_SEPARATOR (*p))
      {
	p++;
	break;
      }

  while (claimfile)
    {
      /* Claim the file only if the file name and size match and don't
	 match the whole library.  */
      if (!strcmp (p, claimfile->file.name)
	  && claimfile->file.filesize == file->filesize
	  && (!islib || file->offset != 0))
	break;
      claimfile = claimfile->next;
    }

  free (name);

  /* If we decided to claim it, record that fact, and add any symbols
     that were defined for it by plugin options.  */
  *claimed = (claimfile != 0);
  if (claimfile)
    {
      char buffer[30];
      int fd;

      TV_MESSAGE (LDPL_INFO, "Claimed: %s [@%ld/%ld]", file->name,
		  (long)file->offset, (long)file->filesize);

      claimfile->claimed = TRUE;
      claimfile->file = *file;
      if (claimfile->n_syms_used && !tv_add_symbols)
	claim_file_ret = LDPS_ERR;
      else if (claimfile->n_syms_used)
	claim_file_ret = (*tv_add_symbols) (claimfile->file.handle,
					    claimfile->n_syms_used,
					    claimfile->symbols);

      fd = claimfile->file.fd;
      name = xstrdup (claimfile->file.name);
      claim_file_ret = tv_release_input_file (claimfile->file.handle);
      if (claim_file_ret != LDPS_OK)
	{
	  free (name);
	  return claim_file_ret;
	}
      if (read (fd, buffer, sizeof (buffer)) >= 0)
	{
	  claim_file_ret = LDPS_ERR;
	  TV_MESSAGE (LDPL_FATAL, "Unreleased file descriptor on: %s", name);
	}
      free (name);
    }

  return claim_file_ret;
}
Пример #9
0
/* Standard plugin API entry point.  */
enum ld_plugin_status
onload (struct ld_plugin_tv *tv)
{
  enum ld_plugin_status rv;

  /* This plugin does nothing but dump the tv array.  It would
     be an error if this function was called without one.  */
  if (!tv)
    return LDPS_ERR;

  /* First entry should always be LDPT_MESSAGE, letting us get
     hold of it easily so we can send output straight away.  */
  if (tv[0].tv_tag == LDPT_MESSAGE)
    tv_message = tv[0].tv_u.tv_message;

  do
    if ((rv = parse_tv_tag (tv)) != LDPS_OK)
      return rv;
  while ((tv++)->tv_tag != LDPT_NULL);

  /* Register hooks only if instructed by options.  */
  if (register_claimfile_hook)
    {
      if (!tv_register_claim_file)
	{
	  TV_MESSAGE (LDPL_FATAL, "No register_claim_file hook");
	  fflush (NULL);
	  return LDPS_ERR;
	}
      (*tv_register_claim_file) (onclaim_file);
    }
  if (register_allsymbolsread_hook)
    {
      if (!tv_register_all_symbols_read)
	{
	  TV_MESSAGE (LDPL_FATAL, "No register_all_symbols_read hook");
	  fflush (NULL);
	  return LDPS_ERR;
	}
      (*tv_register_all_symbols_read) (onall_symbols_read);
    }
  if (register_cleanup_hook)
    {
      if (!tv_register_cleanup)
	{
	  TV_MESSAGE (LDPL_FATAL, "No register_cleanup hook");
	  fflush (NULL);
	  return LDPS_ERR;
	}
      (*tv_register_cleanup) (oncleanup);
    }

  /* Claim testsuite/ld-plugin/func.c, standalone or in a library.  Its
     size must be SIZE_OF_FUNC_C bytes.  */
#define SIZE_OF_FUNC_C	248
  if (onload_ret == LDPS_OK
      && (record_claim_file ("func.c", SIZE_OF_FUNC_C) != LDPS_OK
	  || record_claimed_file_symbol ("func::0:0:0") != LDPS_OK
	  || record_claimed_file_symbol ("_func::0:0:0") != LDPS_OK
	  || record_claim_file ("libfunc.a", SIZE_OF_FUNC_C) != LDPS_OK
	  || record_claimed_file_symbol ("func::0:0:0") != LDPS_OK
	  || record_claimed_file_symbol ("_func::0:0:0") != LDPS_OK))
    onload_ret = LDPS_ERR;

  return onload_ret;
}
Пример #10
0
/* Standard plugin API registerable hook.  */
static enum ld_plugin_status
onall_symbols_read (void)
{
  static const char *resolutions[] =
    {
      "LDPR_UNKNOWN",
      "LDPR_UNDEF",
      "LDPR_PREVAILING_DEF",
      "LDPR_PREVAILING_DEF_IRONLY",
      "LDPR_PREEMPTED_REG",
      "LDPR_PREEMPTED_IR",
      "LDPR_RESOLVED_IR",
      "LDPR_RESOLVED_EXEC",
      "LDPR_RESOLVED_DYN",
      "LDPR_PREVAILING_DEF_IRONLY_EXP",
    };
  claim_file_t *claimfile = dumpresolutions ? claimfiles_list : NULL;
  add_file_t *addfile = addfiles_list;
  struct ld_plugin_input_file file;
  const void *view;
  char buffer[30];
  int fd;
  char *filename;
  if (! allsymbolsread_silent)
    TV_MESSAGE (LDPL_INFO, "hook called: all symbols read.");
  for ( ; claimfile; claimfile = claimfile->next)
    {
      enum ld_plugin_status rv;
      int n;
      if (claimfile->n_syms_used && !tv_get_symbols_v2)
	return LDPS_ERR;
      else if (!claimfile->n_syms_used)
        continue;
      else if (!claimfile->file.handle)
        continue;
      rv = tv_get_input_file (claimfile->file.handle, &file);
      if (rv != LDPS_OK)
	return rv;
      TV_MESSAGE (LDPL_INFO, "Input: %s (%s)", file.name,
		  claimfile->file.name);
      rv = tv_get_view (claimfile->file.handle, &view);
      if (rv != LDPS_OK)
	return rv;
#define EXPECTED_VIEW "/* The first line of this file must match the expectation of"
#define EXPECTED_VIEW_LENGTH (sizeof (EXPECTED_VIEW) - 1)
      if (file.filesize != SIZE_OF_FUNC_C
	  || SIZE_OF_FUNC_C < EXPECTED_VIEW_LENGTH
	  || memcmp (view, EXPECTED_VIEW, EXPECTED_VIEW_LENGTH) != 0)
	{
	  char result[EXPECTED_VIEW_LENGTH + 1];
	  memcpy (result, view, sizeof (result));
	  result[EXPECTED_VIEW_LENGTH] = '\0';
	  TV_MESSAGE (LDPL_INFO, "Incorrect view:");
	  TV_MESSAGE (LDPL_INFO, "  Expect: " EXPECTED_VIEW);
	  TV_MESSAGE (LDPL_INFO, "  Result: %s", result);
	}
      rv = tv_get_symbols_v2 (claimfile->file.handle, claimfile->n_syms_used,
			      claimfile->symbols);
      if (rv != LDPS_OK)
	return rv;
      for (n = 0; n < claimfile->n_syms_used; n++)
	TV_MESSAGE (LDPL_INFO, "Sym: '%s%s%s' Resolution: %s",
		    claimfile->symbols[n].name,
		    claimfile->symbols[n].version ? "@" : "",
		    (claimfile->symbols[n].version
		     ? claimfile->symbols[n].version : ""),
		    resolutions[claimfile->symbols[n].resolution]);
      fd = claimfile->file.fd;
      filename = xstrdup (claimfile->file.name);
      rv = tv_release_input_file (claimfile->file.handle);
      if (rv != LDPS_OK)
	{
	  free (filename);
	  return rv;
	}
      if (read (fd, buffer, sizeof (buffer)) >= 0)
	{
	  TV_MESSAGE (LDPL_FATAL, "Unreleased file descriptor on: %s",
		      claimfile->file.name);
	  free (filename);
	  return LDPS_ERR;
	}
      free (filename);
    }
  for ( ; addfile ; addfile = addfile->next)
    {
      enum ld_plugin_status rv;
      if (addfile->type == ADD_LIB && tv_add_input_library)
	rv = (*tv_add_input_library) (addfile->name);
      else if (addfile->type == ADD_FILE && tv_add_input_file)
	rv = (*tv_add_input_file) (addfile->name);
      else if (addfile->type == ADD_DIR && tv_set_extra_library_path)
	rv = (*tv_set_extra_library_path) (addfile->name);
      else
	rv = LDPS_ERR;
      if (rv != LDPS_OK)
	return rv;
    }
  fflush (NULL);
  return all_symbols_read_ret;
}