[BACK]Return to testplug4.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / gpl3 / binutils / dist / ld

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>