/* Test plugin for the GNU linker.
- Copyright 2010 Free Software Foundation, Inc.
+ Copyright (C) 2010-2019 Free Software Foundation, Inc.
This file is part of the GNU Binutils.
/* For ARRAY_SIZE macro only - we don't link the library itself. */
#include "libiberty.h"
+#include <ctype.h> /* For isdigit. */
+
extern enum ld_plugin_status onload (struct ld_plugin_tv *tv);
static enum ld_plugin_status onclaim_file (const struct ld_plugin_input_file *file,
int *claimed);
ADDENTRY(LDPT_REGISTER_CLEANUP_HOOK),
ADDENTRY(LDPT_ADD_SYMBOLS),
ADDENTRY(LDPT_GET_SYMBOLS),
+ ADDENTRY(LDPT_GET_SYMBOLS_V2),
ADDENTRY(LDPT_ADD_INPUT_FILE),
ADDENTRY(LDPT_MESSAGE),
ADDENTRY(LDPT_GET_INPUT_FILE),
+ ADDENTRY(LDPT_GET_VIEW),
ADDENTRY(LDPT_RELEASE_INPUT_FILE),
ADDENTRY(LDPT_ADD_INPUT_LIBRARY),
ADDENTRY(LDPT_OUTPUT_NAME),
static ld_plugin_register_cleanup tv_register_cleanup = 0;
static ld_plugin_add_symbols tv_add_symbols = 0;
static ld_plugin_get_symbols tv_get_symbols = 0;
+static ld_plugin_get_symbols tv_get_symbols_v2 = 0;
static ld_plugin_add_input_file tv_add_input_file = 0;
static ld_plugin_message tv_message = 0;
static ld_plugin_get_input_file tv_get_input_file = 0;
+static ld_plugin_get_view tv_get_view = 0;
static ld_plugin_release_input_file tv_release_input_file = 0;
static ld_plugin_add_input_library tv_add_input_library = 0;
static ld_plugin_set_extra_library_path tv_set_extra_library_path = 0;
/* We keep a tail pointer for easy linking on the end. */
static add_file_t **addfiles_tail_chain_ptr = &addfiles_list;
+/* Number of bytes read in claim file before deciding if the file can be
+ claimed. */
+static int bytes_to_read_before_claim = 0;
+
/* Add a new claimfile on the end of the chain. */
static enum ld_plugin_status
record_claim_file (const char *file)
return LDPS_OK;
}
+/* How many bytes to read before claiming (or not) an input file. */
+static enum ld_plugin_status
+record_read_length (const char *length)
+{
+ const char *tmp;
+
+ tmp = length;
+ while (*tmp != '\0' && isdigit (*tmp))
+ ++tmp;
+ if (*tmp != '\0' || *length == '\0')
+ {
+ fprintf (stderr, "APB: Bad length string: %s\n", tmp);
+ return LDPS_ERR;
+ }
+
+ bytes_to_read_before_claim = atoi (length);
+ return LDPS_OK;
+}
+
/* Add a new addfile on the end of the chain. */
static enum ld_plugin_status
record_add_file (const char *file, addfile_enum_t type)
return LDPS_ERR;
newfile->next = NULL;
newfile->name = file;
- newfile->type = type;;
+ newfile->type = type;
/* Chain it on the end of the list. */
*addfiles_tail_chain_ptr = newfile;
addfiles_tail_chain_ptr = &newfile->next;
return set_register_hook (opt + 10, FALSE);
else if (!strncmp ("claim:", opt, 6))
return record_claim_file (opt + 6);
+ else if (!strncmp ("read:", opt, 5))
+ return record_read_length (opt + 5);
else if (!strncmp ("sym:", opt, 4))
return record_claimed_file_symbol (opt + 4);
else if (!strncmp ("add:", opt, 4))
break;
sprintf (unknownbuf, "unknown tag #%d", tv->tv_tag);
name = (tag < ARRAY_SIZE (tag_names)) ? tag_names[tag].name : unknownbuf;
- TV_MESSAGE (LDPL_INFO, "tv[%d]: %s ", n, name);
switch (tv->tv_tag)
{
case LDPT_OPTION:
case LDPT_OUTPUT_NAME:
- TV_MESSAGE (LDPL_INFO, "'%s'\n", tv->tv_u.tv_string);
+ 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, "func@0x%p\n",
- (void *)(tv->tv_u.tv_message));
+ 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_LINKER_OUTPUT:
case LDPT_GNU_LD_VERSION:
default:
- TV_MESSAGE (LDPL_INFO, "value %W (%d)\n",
- (bfd_vma)tv->tv_u.tv_val, tv->tv_u.tv_val);
+ 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;
}
}
case LDPT_GET_SYMBOLS:
SETVAR(tv_get_symbols);
break;
+ case LDPT_GET_SYMBOLS_V2:
+ tv_get_symbols_v2 = tv->tv_u.tv_get_symbols;
+ break;
case LDPT_ADD_INPUT_FILE:
SETVAR(tv_add_input_file);
break;
case LDPT_GET_INPUT_FILE:
SETVAR(tv_get_input_file);
break;
+ case LDPT_GET_VIEW:
+ SETVAR(tv_get_view);
+ break;
case LDPT_RELEASE_INPUT_FILE:
SETVAR(tv_release_input_file);
break;
tv_message = tv[0].tv_u.tv_message;
fflush (NULL);
- TV_MESSAGE (LDPL_INFO, "Hello from testplugin.\n");
+ 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);
- TV_MESSAGE (LDPL_INFO, "\n");
-
/* 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\n");
+ TV_MESSAGE (LDPL_FATAL, "No register_claim_file hook");
fflush (NULL);
return LDPS_ERR;
}
{
if (!tv_register_all_symbols_read)
{
- TV_MESSAGE (LDPL_FATAL, "No register_all_symbols_read hook\n");
+ TV_MESSAGE (LDPL_FATAL, "No register_all_symbols_read hook");
fflush (NULL);
return LDPS_ERR;
}
{
if (!tv_register_cleanup)
{
- TV_MESSAGE (LDPL_FATAL, "No register_cleanup hook\n");
+ TV_MESSAGE (LDPL_FATAL, "No register_cleanup hook");
fflush (NULL);
return LDPS_ERR;
}
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)
}
/* Inform the user/testsuite. */
- TV_MESSAGE (LDPL_INFO, "hook called: claim_file %s [@%ld/%ld] %s\n",
- file->name, (long)file->offset, (long)file->filesize,
- claimfile ? "CLAIMED" : "not claimed");
+ 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
"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.\n");
+ 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)
+ if (claimfile->n_syms_used && !tv_get_symbols_v2)
return LDPS_ERR;
else if (!claimfile->n_syms_used)
continue;
- rv = tv_get_symbols (claimfile->file.handle, claimfile->n_syms_used,
- claimfile->symbols);
+ 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\n",
- claimfile->symbols[n].name,
- claimfile->symbols[n].version ? "@" : "",
- claimfile->symbols[n].version ? claimfile->symbols[n].version
- : "",
- resolutions[claimfile->symbols[n].resolution]);
+ 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)
{
static enum ld_plugin_status
oncleanup (void)
{
- TV_MESSAGE (LDPL_INFO, "hook called: cleanup.\n");
+ TV_MESSAGE (LDPL_INFO, "hook called: cleanup.");
fflush (NULL);
return cleanup_ret;
}
-