/* Test plugin for the GNU linker.
- Copyright 2010 Free Software Foundation, Inc.
+ Copyright (C) 2010-2020 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;
/* Finally we'll use sscanf to parse the numeric fields, then
we'll split out the strings which we need to allocate separate
storage for anyway so that we can add nul termination. */
- n = sscanf (colon2 + 1, "%i:%i:%lli", &sym->def, &sym->visibility, &size);
+ n = sscanf (colon2 + 1, "%hhi:%i:%lli", &sym->def, &sym->visibility, &size);
if (n != 3)
return LDPS_ERR;
/* Parsed successfully, so allocate strings and fill out fields. */
sym->size = size;
+ sym->unused = 0;
+ sym->section_kind = 0;
+ sym->symbol_type = 0;
sym->resolution = LDPR_UNKNOWN;
sym->name = malloc (colon1 - str + 1);
if (!sym->name)
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;
}
-