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