Annotation of src/external/gpl3/binutils/dist/ld/testplug4.c, Revision 1.1
1.1 ! christos 1: /* Test plugin for the GNU linker. Check non-object IR file as well as
! 2: get_input_file, get_view, release_input_file and get_symbols interfaces.
! 3: Copyright (C) 2016 Free Software Foundation, Inc.
! 4:
! 5: This file is part of the GNU Binutils.
! 6:
! 7: This program is free software; you can redistribute it and/or modify
! 8: it under the terms of the GNU General Public License as published by
! 9: the Free Software Foundation; either version 3 of the License, or
! 10: (at your option) any later version.
! 11:
! 12: This program is distributed in the hope that it will be useful,
! 13: but WITHOUT ANY WARRANTY; without even the implied warranty of
! 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 15: GNU General Public License for more details.
! 16:
! 17: You should have received a copy of the GNU General Public License
! 18: along with this program; if not, write to the Free Software
! 19: Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
! 20: MA 02110-1301, USA. */
! 21:
! 22: #include "sysdep.h"
! 23: #include "bfd.h"
! 24: #include "plugin-api.h"
! 25: #include "filenames.h"
! 26: /* For ARRAY_SIZE macro only - we don't link the library itself. */
! 27: #include "libiberty.h"
! 28:
! 29: extern enum ld_plugin_status onload (struct ld_plugin_tv *tv);
! 30: static enum ld_plugin_status onclaim_file (const struct ld_plugin_input_file *file,
! 31: int *claimed);
! 32: static enum ld_plugin_status onall_symbols_read (void);
! 33: static enum ld_plugin_status oncleanup (void);
! 34:
! 35: /* Helper for calling plugin api message function. */
! 36: #define TV_MESSAGE if (tv_message) (*tv_message)
! 37:
! 38: /* Struct for recording files to claim / files claimed. */
! 39: typedef struct claim_file
! 40: {
! 41: struct claim_file *next;
! 42: struct ld_plugin_input_file file;
! 43: bfd_boolean claimed;
! 44: struct ld_plugin_symbol *symbols;
! 45: int n_syms_allocated;
! 46: int n_syms_used;
! 47: } claim_file_t;
! 48:
! 49: /* Types of things that can be added at all symbols read time. */
! 50: typedef enum addfile_enum
! 51: {
! 52: ADD_FILE,
! 53: ADD_LIB,
! 54: ADD_DIR
! 55: } addfile_enum_t;
! 56:
! 57: /* Struct for recording files to add to final link. */
! 58: typedef struct add_file
! 59: {
! 60: struct add_file *next;
! 61: const char *name;
! 62: addfile_enum_t type;
! 63: } add_file_t;
! 64:
! 65: /* Helper macro for defining array of transfer vector tags and names. */
! 66: #define ADDENTRY(tag) { tag, #tag }
! 67:
! 68: /* Struct for looking up human-readable versions of tag names. */
! 69: typedef struct tag_name
! 70: {
! 71: enum ld_plugin_tag tag;
! 72: const char *name;
! 73: } tag_name_t;
! 74:
! 75: /* Array of all known tags and their names. */
! 76: static const tag_name_t tag_names[] =
! 77: {
! 78: ADDENTRY(LDPT_NULL),
! 79: ADDENTRY(LDPT_API_VERSION),
! 80: ADDENTRY(LDPT_GOLD_VERSION),
! 81: ADDENTRY(LDPT_LINKER_OUTPUT),
! 82: ADDENTRY(LDPT_OPTION),
! 83: ADDENTRY(LDPT_REGISTER_CLAIM_FILE_HOOK),
! 84: ADDENTRY(LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK),
! 85: ADDENTRY(LDPT_REGISTER_CLEANUP_HOOK),
! 86: ADDENTRY(LDPT_ADD_SYMBOLS),
! 87: ADDENTRY(LDPT_GET_SYMBOLS),
! 88: ADDENTRY(LDPT_GET_SYMBOLS_V2),
! 89: ADDENTRY(LDPT_ADD_INPUT_FILE),
! 90: ADDENTRY(LDPT_MESSAGE),
! 91: ADDENTRY(LDPT_GET_INPUT_FILE),
! 92: ADDENTRY(LDPT_GET_VIEW),
! 93: ADDENTRY(LDPT_RELEASE_INPUT_FILE),
! 94: ADDENTRY(LDPT_ADD_INPUT_LIBRARY),
! 95: ADDENTRY(LDPT_OUTPUT_NAME),
! 96: ADDENTRY(LDPT_SET_EXTRA_LIBRARY_PATH),
! 97: ADDENTRY(LDPT_GNU_LD_VERSION)
! 98: };
! 99:
! 100: /* Function pointers to cache hooks passed at onload time. */
! 101: static ld_plugin_register_claim_file tv_register_claim_file = 0;
! 102: static ld_plugin_register_all_symbols_read tv_register_all_symbols_read = 0;
! 103: static ld_plugin_register_cleanup tv_register_cleanup = 0;
! 104: static ld_plugin_add_symbols tv_add_symbols = 0;
! 105: static ld_plugin_get_symbols tv_get_symbols = 0;
! 106: static ld_plugin_get_symbols tv_get_symbols_v2 = 0;
! 107: static ld_plugin_add_input_file tv_add_input_file = 0;
! 108: static ld_plugin_message tv_message = 0;
! 109: static ld_plugin_get_input_file tv_get_input_file = 0;
! 110: static ld_plugin_get_view tv_get_view = 0;
! 111: static ld_plugin_release_input_file tv_release_input_file = 0;
! 112: static ld_plugin_add_input_library tv_add_input_library = 0;
! 113: static ld_plugin_set_extra_library_path tv_set_extra_library_path = 0;
! 114:
! 115: /* Other cached info from the transfer vector. */
! 116: static enum ld_plugin_output_file_type linker_output;
! 117: static const char *output_name;
! 118:
! 119: /* Behaviour control flags set by plugin options. */
! 120: static enum ld_plugin_status onload_ret = LDPS_OK;
! 121: static enum ld_plugin_status claim_file_ret = LDPS_OK;
! 122: static enum ld_plugin_status all_symbols_read_ret = LDPS_OK;
! 123: static enum ld_plugin_status cleanup_ret = LDPS_OK;
! 124: static bfd_boolean register_claimfile_hook = TRUE;
! 125: static bfd_boolean register_allsymbolsread_hook = FALSE;
! 126: static bfd_boolean register_cleanup_hook = FALSE;
! 127: static bfd_boolean dumpresolutions = FALSE;
! 128: static bfd_boolean allsymbolsread_silent = FALSE;
! 129:
! 130: /* The master list of all claimable/claimed files. */
! 131: static claim_file_t *claimfiles_list = NULL;
! 132:
! 133: /* We keep a tail pointer for easy linking on the end. */
! 134: static claim_file_t **claimfiles_tail_chain_ptr = &claimfiles_list;
! 135:
! 136: /* The last claimed file added to the list, for receiving syms. */
! 137: static claim_file_t *last_claimfile = NULL;
! 138:
! 139: /* The master list of all files to add to the final link. */
! 140: static add_file_t *addfiles_list = NULL;
! 141:
! 142: /* We keep a tail pointer for easy linking on the end. */
! 143: static add_file_t **addfiles_tail_chain_ptr = &addfiles_list;
! 144:
! 145: /* Add a new claimfile on the end of the chain. */
! 146: static enum ld_plugin_status
! 147: record_claim_file (const char *file, off_t filesize)
! 148: {
! 149: claim_file_t *newfile;
! 150:
! 151: newfile = malloc (sizeof *newfile);
! 152: if (!newfile)
! 153: return LDPS_ERR;
! 154: memset (newfile, 0, sizeof *newfile);
! 155: /* Only setup for now is remembering the name to look for. */
! 156: newfile->file.name = file;
! 157: newfile->file.filesize = filesize;
! 158: /* Chain it on the end of the list. */
! 159: *claimfiles_tail_chain_ptr = newfile;
! 160: claimfiles_tail_chain_ptr = &newfile->next;
! 161: /* Record it as active for receiving symbols to register. */
! 162: last_claimfile = newfile;
! 163: return LDPS_OK;
! 164: }
! 165:
! 166: /* Add a new addfile on the end of the chain. */
! 167: static enum ld_plugin_status
! 168: record_add_file (const char *file, addfile_enum_t type)
! 169: {
! 170: add_file_t *newfile;
! 171:
! 172: newfile = malloc (sizeof *newfile);
! 173: if (!newfile)
! 174: return LDPS_ERR;
! 175: newfile->next = NULL;
! 176: newfile->name = file;
! 177: newfile->type = type;
! 178: /* Chain it on the end of the list. */
! 179: *addfiles_tail_chain_ptr = newfile;
! 180: addfiles_tail_chain_ptr = &newfile->next;
! 181: return LDPS_OK;
! 182: }
! 183:
! 184: /* Parse a command-line argument string into a symbol definition.
! 185: Symbol-strings follow the colon-separated format:
! 186: NAME:VERSION:def:vis:size:COMDATKEY
! 187: where the fields in capitals are strings and those in lower
! 188: case are integers. We don't allow to specify a resolution as
! 189: doing so is not meaningful when calling the add symbols hook. */
! 190: static enum ld_plugin_status
! 191: parse_symdefstr (const char *str, struct ld_plugin_symbol *sym)
! 192: {
! 193: int n;
! 194: long long size;
! 195: const char *colon1, *colon2, *colon5;
! 196:
! 197: /* Locate the colons separating the first two strings. */
! 198: colon1 = strchr (str, ':');
! 199: if (!colon1)
! 200: return LDPS_ERR;
! 201: colon2 = strchr (colon1+1, ':');
! 202: if (!colon2)
! 203: return LDPS_ERR;
! 204: /* Name must not be empty (version may be). */
! 205: if (colon1 == str)
! 206: return LDPS_ERR;
! 207:
! 208: /* The fifth colon and trailing comdat key string are optional,
! 209: but the intermediate ones must all be present. */
! 210: colon5 = strchr (colon2+1, ':'); /* Actually only third so far. */
! 211: if (!colon5)
! 212: return LDPS_ERR;
! 213: colon5 = strchr (colon5+1, ':'); /* Hopefully fourth now. */
! 214: if (!colon5)
! 215: return LDPS_ERR;
! 216: colon5 = strchr (colon5+1, ':'); /* Optional fifth now. */
! 217:
! 218: /* Finally we'll use sscanf to parse the numeric fields, then
! 219: we'll split out the strings which we need to allocate separate
! 220: storage for anyway so that we can add nul termination. */
! 221: n = sscanf (colon2 + 1, "%i:%i:%lli", &sym->def, &sym->visibility, &size);
! 222: if (n != 3)
! 223: return LDPS_ERR;
! 224:
! 225: /* Parsed successfully, so allocate strings and fill out fields. */
! 226: sym->size = size;
! 227: sym->resolution = LDPR_UNKNOWN;
! 228: sym->name = malloc (colon1 - str + 1);
! 229: if (!sym->name)
! 230: return LDPS_ERR;
! 231: memcpy (sym->name, str, colon1 - str);
! 232: sym->name[colon1 - str] = '\0';
! 233: if (colon2 > (colon1 + 1))
! 234: {
! 235: sym->version = malloc (colon2 - colon1);
! 236: if (!sym->version)
! 237: return LDPS_ERR;
! 238: memcpy (sym->version, colon1 + 1, colon2 - (colon1 + 1));
! 239: sym->version[colon2 - (colon1 + 1)] = '\0';
! 240: }
! 241: else
! 242: sym->version = NULL;
! 243: if (colon5 && colon5[1])
! 244: {
! 245: sym->comdat_key = malloc (strlen (colon5 + 1) + 1);
! 246: if (!sym->comdat_key)
! 247: return LDPS_ERR;
! 248: strcpy (sym->comdat_key, colon5 + 1);
! 249: }
! 250: else
! 251: sym->comdat_key = 0;
! 252: return LDPS_OK;
! 253: }
! 254:
! 255: /* Record a symbol to be added for the last-added claimfile. */
! 256: static enum ld_plugin_status
! 257: record_claimed_file_symbol (const char *symdefstr)
! 258: {
! 259: struct ld_plugin_symbol sym;
! 260:
! 261: /* Can't add symbols except as belonging to claimed files. */
! 262: if (!last_claimfile)
! 263: return LDPS_ERR;
! 264:
! 265: /* If string doesn't parse correctly, give an error. */
! 266: if (parse_symdefstr (symdefstr, &sym) != LDPS_OK)
! 267: return LDPS_ERR;
! 268:
! 269: /* Check for enough space, resize array if needed, and add it. */
! 270: if (last_claimfile->n_syms_allocated == last_claimfile->n_syms_used)
! 271: {
! 272: int new_n_syms = last_claimfile->n_syms_allocated
! 273: ? 2 * last_claimfile->n_syms_allocated
! 274: : 10;
! 275: last_claimfile->symbols = realloc (last_claimfile->symbols,
! 276: new_n_syms * sizeof *last_claimfile->symbols);
! 277: if (!last_claimfile->symbols)
! 278: return LDPS_ERR;
! 279: last_claimfile->n_syms_allocated = new_n_syms;
! 280: }
! 281: last_claimfile->symbols[last_claimfile->n_syms_used++] = sym;
! 282:
! 283: return LDPS_OK;
! 284: }
! 285:
! 286: /* Records the status to return from one of the registered hooks. */
! 287: static enum ld_plugin_status
! 288: set_ret_val (const char *whichval, enum ld_plugin_status retval)
! 289: {
! 290: if (!strcmp ("onload", whichval))
! 291: onload_ret = retval;
! 292: else if (!strcmp ("claimfile", whichval))
! 293: claim_file_ret = retval;
! 294: else if (!strcmp ("allsymbolsread", whichval))
! 295: all_symbols_read_ret = retval;
! 296: else if (!strcmp ("cleanup", whichval))
! 297: cleanup_ret = retval;
! 298: else
! 299: return LDPS_ERR;
! 300: return LDPS_OK;
! 301: }
! 302:
! 303: /* Records hooks which should be registered. */
! 304: static enum ld_plugin_status
! 305: set_register_hook (const char *whichhook, bfd_boolean yesno)
! 306: {
! 307: if (!strcmp ("claimfile", whichhook))
! 308: register_claimfile_hook = yesno;
! 309: else if (!strcmp ("allsymbolsread", whichhook))
! 310: register_allsymbolsread_hook = yesno;
! 311: else if (!strcmp ("allsymbolsreadsilent", whichhook))
! 312: {
! 313: register_allsymbolsread_hook = yesno;
! 314: allsymbolsread_silent = TRUE;
! 315: }
! 316: else if (!strcmp ("cleanup", whichhook))
! 317: register_cleanup_hook = yesno;
! 318: else
! 319: return LDPS_ERR;
! 320: return LDPS_OK;
! 321: }
! 322:
! 323: /* Determine type of plugin option and pass to individual parsers. */
! 324: static enum ld_plugin_status
! 325: parse_option (const char *opt)
! 326: {
! 327: if (!strncmp ("fatal", opt, 5))
! 328: {
! 329: TV_MESSAGE (LDPL_FATAL, "Fatal error");
! 330: fflush (NULL);
! 331: }
! 332: else if (!strncmp ("error", opt, 5))
! 333: {
! 334: TV_MESSAGE (LDPL_ERROR, "Error");
! 335: fflush (NULL);
! 336: }
! 337: else if (!strncmp ("warning", opt, 7))
! 338: {
! 339: TV_MESSAGE (LDPL_WARNING, "Warning");
! 340: fflush (NULL);
! 341: }
! 342: else if (!strncmp ("fail", opt, 4))
! 343: return set_ret_val (opt + 4, LDPS_ERR);
! 344: else if (!strncmp ("pass", opt, 4))
! 345: return set_ret_val (opt + 4, LDPS_OK);
! 346: else if (!strncmp ("register", opt, 8))
! 347: return set_register_hook (opt + 8, TRUE);
! 348: else if (!strncmp ("noregister", opt, 10))
! 349: return set_register_hook (opt + 10, FALSE);
! 350: else if (!strncmp ("claim:", opt, 6))
! 351: return record_claim_file (opt + 6, 0);
! 352: else if (!strncmp ("sym:", opt, 4))
! 353: return record_claimed_file_symbol (opt + 4);
! 354: else if (!strncmp ("add:", opt, 4))
! 355: return record_add_file (opt + 4, ADD_FILE);
! 356: else if (!strncmp ("lib:", opt, 4))
! 357: return record_add_file (opt + 4, ADD_LIB);
! 358: else if (!strncmp ("dir:", opt, 4))
! 359: return record_add_file (opt + 4, ADD_DIR);
! 360: else if (!strcmp ("dumpresolutions", opt))
! 361: dumpresolutions = TRUE;
! 362: else
! 363: return LDPS_ERR;
! 364: return LDPS_OK;
! 365: }
! 366:
! 367: /* Handle/record information received in a transfer vector entry. */
! 368: static enum ld_plugin_status
! 369: parse_tv_tag (struct ld_plugin_tv *tv)
! 370: {
! 371: #define SETVAR(x) x = tv->tv_u.x
! 372: switch (tv->tv_tag)
! 373: {
! 374: case LDPT_OPTION:
! 375: return parse_option (tv->tv_u.tv_string);
! 376: case LDPT_NULL:
! 377: case LDPT_GOLD_VERSION:
! 378: case LDPT_GNU_LD_VERSION:
! 379: case LDPT_API_VERSION:
! 380: default:
! 381: break;
! 382: case LDPT_OUTPUT_NAME:
! 383: output_name = tv->tv_u.tv_string;
! 384: break;
! 385: case LDPT_LINKER_OUTPUT:
! 386: linker_output = tv->tv_u.tv_val;
! 387: break;
! 388: case LDPT_REGISTER_CLAIM_FILE_HOOK:
! 389: SETVAR(tv_register_claim_file);
! 390: break;
! 391: case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
! 392: SETVAR(tv_register_all_symbols_read);
! 393: break;
! 394: case LDPT_REGISTER_CLEANUP_HOOK:
! 395: SETVAR(tv_register_cleanup);
! 396: break;
! 397: case LDPT_ADD_SYMBOLS:
! 398: SETVAR(tv_add_symbols);
! 399: break;
! 400: case LDPT_GET_SYMBOLS:
! 401: SETVAR(tv_get_symbols);
! 402: break;
! 403: case LDPT_GET_SYMBOLS_V2:
! 404: tv_get_symbols_v2 = tv->tv_u.tv_get_symbols;
! 405: break;
! 406: case LDPT_ADD_INPUT_FILE:
! 407: SETVAR(tv_add_input_file);
! 408: break;
! 409: case LDPT_MESSAGE:
! 410: SETVAR(tv_message);
! 411: break;
! 412: case LDPT_GET_INPUT_FILE:
! 413: SETVAR(tv_get_input_file);
! 414: break;
! 415: case LDPT_GET_VIEW:
! 416: SETVAR(tv_get_view);
! 417: break;
! 418: case LDPT_RELEASE_INPUT_FILE:
! 419: SETVAR(tv_release_input_file);
! 420: break;
! 421: case LDPT_ADD_INPUT_LIBRARY:
! 422: SETVAR(tv_add_input_library);
! 423: break;
! 424: case LDPT_SET_EXTRA_LIBRARY_PATH:
! 425: SETVAR(tv_set_extra_library_path);
! 426: break;
! 427: }
! 428: #undef SETVAR
! 429: return LDPS_OK;
! 430: }
! 431:
! 432: /* Standard plugin API entry point. */
! 433: enum ld_plugin_status
! 434: onload (struct ld_plugin_tv *tv)
! 435: {
! 436: enum ld_plugin_status rv;
! 437:
! 438: /* This plugin does nothing but dump the tv array. It would
! 439: be an error if this function was called without one. */
! 440: if (!tv)
! 441: return LDPS_ERR;
! 442:
! 443: /* First entry should always be LDPT_MESSAGE, letting us get
! 444: hold of it easily so we can send output straight away. */
! 445: if (tv[0].tv_tag == LDPT_MESSAGE)
! 446: tv_message = tv[0].tv_u.tv_message;
! 447:
! 448: do
! 449: if ((rv = parse_tv_tag (tv)) != LDPS_OK)
! 450: return rv;
! 451: while ((tv++)->tv_tag != LDPT_NULL);
! 452:
! 453: /* Register hooks only if instructed by options. */
! 454: if (register_claimfile_hook)
! 455: {
! 456: if (!tv_register_claim_file)
! 457: {
! 458: TV_MESSAGE (LDPL_FATAL, "No register_claim_file hook");
! 459: fflush (NULL);
! 460: return LDPS_ERR;
! 461: }
! 462: (*tv_register_claim_file) (onclaim_file);
! 463: }
! 464: if (register_allsymbolsread_hook)
! 465: {
! 466: if (!tv_register_all_symbols_read)
! 467: {
! 468: TV_MESSAGE (LDPL_FATAL, "No register_all_symbols_read hook");
! 469: fflush (NULL);
! 470: return LDPS_ERR;
! 471: }
! 472: (*tv_register_all_symbols_read) (onall_symbols_read);
! 473: }
! 474: if (register_cleanup_hook)
! 475: {
! 476: if (!tv_register_cleanup)
! 477: {
! 478: TV_MESSAGE (LDPL_FATAL, "No register_cleanup hook");
! 479: fflush (NULL);
! 480: return LDPS_ERR;
! 481: }
! 482: (*tv_register_cleanup) (oncleanup);
! 483: }
! 484:
! 485: /* Claim testsuite/ld-plugin/pr20070b.c, standalone or in a library.
! 486: Its size must be SIZE_OF_PR20070B_C bytes. */
! 487: #define SIZE_OF_PR20070B_C 248
! 488: if (onload_ret == LDPS_OK
! 489: && (record_claim_file ("pr20070b.c", SIZE_OF_PR20070B_C) != LDPS_OK
! 490: || record_claimed_file_symbol ("def::0:0:0") != LDPS_OK
! 491: || record_claimed_file_symbol ("weakdef::1:0:0") != LDPS_OK
! 492: || record_claimed_file_symbol ("undef::2:0:0") != LDPS_OK
! 493: || record_claimed_file_symbol ("weakundef::3:0:0") != LDPS_OK
! 494: || record_claimed_file_symbol ("common::4:0:0") != LDPS_OK
! 495: || record_claim_file ("libpr20070.a", SIZE_OF_PR20070B_C) != LDPS_OK
! 496: || record_claimed_file_symbol ("def::0:0:0") != LDPS_OK
! 497: || record_claimed_file_symbol ("weakdef::1:0:0") != LDPS_OK
! 498: || record_claimed_file_symbol ("undef::2:0:0") != LDPS_OK
! 499: || record_claimed_file_symbol ("weakundef::3:0:0") != LDPS_OK
! 500: || record_claimed_file_symbol ("common::4:0:0") != LDPS_OK))
! 501: onload_ret = LDPS_ERR;
! 502:
! 503: return onload_ret;
! 504: }
! 505:
! 506: char *
! 507: xstrdup (const char *s)
! 508: {
! 509: size_t len = strlen (s) + 1;
! 510: char *ret = malloc (len + 1);
! 511: return (char *) memcpy (ret, s, len);
! 512: }
! 513:
! 514: /* Standard plugin API registerable hook. */
! 515: static enum ld_plugin_status
! 516: onclaim_file (const struct ld_plugin_input_file *file, int *claimed)
! 517: {
! 518: /* Let's see if we want to claim this file. */
! 519: claim_file_t *claimfile = claimfiles_list;
! 520: size_t len = strlen (file->name);
! 521: char *name = xstrdup (file->name);
! 522: char *p = name + len;
! 523: bfd_boolean islib;
! 524:
! 525: /* Only match the file name without the directory part. */
! 526: islib = *p == 'a' && *(p - 1) == '.';
! 527: for (; p != name; p--)
! 528: if (IS_DIR_SEPARATOR (*p))
! 529: {
! 530: p++;
! 531: break;
! 532: }
! 533:
! 534: while (claimfile)
! 535: {
! 536: /* Claim the file only if the file name and size match and don't
! 537: match the whole library. */
! 538: if (!strcmp (p, claimfile->file.name)
! 539: && claimfile->file.filesize == file->filesize
! 540: && (!islib || file->offset != 0))
! 541: break;
! 542: claimfile = claimfile->next;
! 543: }
! 544:
! 545: free (name);
! 546:
! 547: /* If we decided to claim it, record that fact, and add any symbols
! 548: that were defined for it by plugin options. */
! 549: *claimed = (claimfile != 0);
! 550: if (claimfile)
! 551: {
! 552: claimfile->claimed = TRUE;
! 553: claimfile->file = *file;
! 554: if (claimfile->n_syms_used && !tv_add_symbols)
! 555: return LDPS_ERR;
! 556: else if (claimfile->n_syms_used)
! 557: return (*tv_add_symbols) (claimfile->file.handle,
! 558: claimfile->n_syms_used, claimfile->symbols);
! 559: }
! 560:
! 561: return claim_file_ret;
! 562: }
! 563:
! 564: /* Standard plugin API registerable hook. */
! 565: static enum ld_plugin_status
! 566: onall_symbols_read (void)
! 567: {
! 568: static const char *resolutions[] =
! 569: {
! 570: "LDPR_UNKNOWN",
! 571: "LDPR_UNDEF",
! 572: "LDPR_PREVAILING_DEF",
! 573: "LDPR_PREVAILING_DEF_IRONLY",
! 574: "LDPR_PREEMPTED_REG",
! 575: "LDPR_PREEMPTED_IR",
! 576: "LDPR_RESOLVED_IR",
! 577: "LDPR_RESOLVED_EXEC",
! 578: "LDPR_RESOLVED_DYN",
! 579: "LDPR_PREVAILING_DEF_IRONLY_EXP",
! 580: };
! 581: claim_file_t *claimfile = dumpresolutions ? claimfiles_list : NULL;
! 582: add_file_t *addfile = addfiles_list;
! 583: struct ld_plugin_input_file file;
! 584: const void *view;
! 585: char buffer[30];
! 586: int fd;
! 587: char *filename;
! 588: if (! allsymbolsread_silent)
! 589: TV_MESSAGE (LDPL_INFO, "hook called: all symbols read.");
! 590: for ( ; claimfile; claimfile = claimfile->next)
! 591: {
! 592: enum ld_plugin_status rv;
! 593: int n;
! 594: if (claimfile->n_syms_used && !tv_get_symbols_v2)
! 595: return LDPS_ERR;
! 596: else if (!claimfile->n_syms_used)
! 597: continue;
! 598: else if (!claimfile->file.handle)
! 599: continue;
! 600: rv = tv_get_input_file (claimfile->file.handle, &file);
! 601: if (rv != LDPS_OK)
! 602: return rv;
! 603: TV_MESSAGE (LDPL_INFO, "Input: %s (%s)", file.name,
! 604: claimfile->file.name);
! 605: rv = tv_get_view (claimfile->file.handle, &view);
! 606: if (rv != LDPS_OK)
! 607: return rv;
! 608: #define EXPECTED_VIEW "/* The first line of this file must match the expectation of"
! 609: #define EXPECTED_VIEW_LENGTH (sizeof (EXPECTED_VIEW) - 1)
! 610: if (file.filesize != SIZE_OF_PR20070B_C
! 611: || SIZE_OF_PR20070B_C < EXPECTED_VIEW_LENGTH
! 612: || memcmp (view, EXPECTED_VIEW, EXPECTED_VIEW_LENGTH) != 0)
! 613: {
! 614: char result[EXPECTED_VIEW_LENGTH + 1];
! 615: memcpy (result, view, sizeof (result));
! 616: result[EXPECTED_VIEW_LENGTH] = '\0';
! 617: TV_MESSAGE (LDPL_INFO, "Incorrect view:");
! 618: TV_MESSAGE (LDPL_INFO, " Expect: " EXPECTED_VIEW);
! 619: TV_MESSAGE (LDPL_INFO, " Result: %s", result);
! 620: }
! 621: rv = tv_get_symbols_v2 (claimfile->file.handle, claimfile->n_syms_used,
! 622: claimfile->symbols);
! 623: if (rv != LDPS_OK)
! 624: return rv;
! 625: for (n = 0; n < claimfile->n_syms_used; n++)
! 626: TV_MESSAGE (LDPL_INFO, "Sym: '%s%s%s' Resolution: %s",
! 627: claimfile->symbols[n].name,
! 628: claimfile->symbols[n].version ? "@" : "",
! 629: (claimfile->symbols[n].version
! 630: ? claimfile->symbols[n].version : ""),
! 631: resolutions[claimfile->symbols[n].resolution]);
! 632: fd = claimfile->file.fd;
! 633: filename = xstrdup (claimfile->file.name);
! 634: rv = tv_release_input_file (claimfile->file.handle);
! 635: if (rv != LDPS_OK)
! 636: {
! 637: free (filename);
! 638: return rv;
! 639: }
! 640: if (read (fd, buffer, sizeof (buffer)) >= 0)
! 641: {
! 642: TV_MESSAGE (LDPL_FATAL, "Unreleased file descriptor on: %s",
! 643: claimfile->file.name);
! 644: free (filename);
! 645: return LDPS_ERR;
! 646: }
! 647: free (filename);
! 648: }
! 649: for ( ; addfile ; addfile = addfile->next)
! 650: {
! 651: enum ld_plugin_status rv;
! 652: if (addfile->type == ADD_LIB && tv_add_input_library)
! 653: rv = (*tv_add_input_library) (addfile->name);
! 654: else if (addfile->type == ADD_FILE && tv_add_input_file)
! 655: rv = (*tv_add_input_file) (addfile->name);
! 656: else if (addfile->type == ADD_DIR && tv_set_extra_library_path)
! 657: rv = (*tv_set_extra_library_path) (addfile->name);
! 658: else
! 659: rv = LDPS_ERR;
! 660: if (rv != LDPS_OK)
! 661: return rv;
! 662: }
! 663: fflush (NULL);
! 664: return all_symbols_read_ret;
! 665: }
! 666:
! 667: /* Standard plugin API registerable hook. */
! 668: static enum ld_plugin_status
! 669: oncleanup (void)
! 670: {
! 671: TV_MESSAGE (LDPL_INFO, "hook called: cleanup.");
! 672: fflush (NULL);
! 673: return cleanup_ret;
! 674: }
CVSweb <webmaster@jp.NetBSD.org>