1 /* Test plugin for the GNU linker. Check non-object IR file as well as
2 get_input_file, get_view and release_input_file interfaces.
3 Copyright (C) 2015-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
record_claim_file(const char * file,off_t filesize)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
record_add_file(const char * file,addfile_enum_t type)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
parse_symdefstr(const char * str,struct ld_plugin_symbol * sym)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
record_claimed_file_symbol(const char * symdefstr)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
set_ret_val(const char * whichval,enum ld_plugin_status retval)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
set_register_hook(const char * whichhook,bfd_boolean yesno)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
parse_option(const char * opt)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
parse_tv_tag(struct ld_plugin_tv * tv)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
onload(struct ld_plugin_tv * tv)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/func.c, standalone or in a library. Its
486 size must be SIZE_OF_FUNC_C bytes. */
487 #define SIZE_OF_FUNC_C 248
488 if (onload_ret == LDPS_OK
489 && (record_claim_file ("func.c", SIZE_OF_FUNC_C) != LDPS_OK
490 || record_claimed_file_symbol ("func::0:0:0") != LDPS_OK
491 || record_claimed_file_symbol ("_func::0:0:0") != LDPS_OK
492 || record_claim_file ("libfunc.a", SIZE_OF_FUNC_C) != LDPS_OK
493 || record_claimed_file_symbol ("func::0:0:0") != LDPS_OK
494 || record_claimed_file_symbol ("_func::0:0:0") != LDPS_OK))
495 onload_ret = LDPS_ERR;
496
497 return onload_ret;
498 }
499
500 char *
xstrdup(const char * s)501 xstrdup (const char *s)
502 {
503 size_t len = strlen (s) + 1;
504 char *ret = malloc (len + 1);
505 return (char *) memcpy (ret, s, len);
506 }
507
508 /* Standard plugin API registerable hook. */
509 static enum ld_plugin_status
onclaim_file(const struct ld_plugin_input_file * file,int * claimed)510 onclaim_file (const struct ld_plugin_input_file *file, int *claimed)
511 {
512 /* Let's see if we want to claim this file. */
513 claim_file_t *claimfile = claimfiles_list;
514 size_t len = strlen (file->name);
515 char *name = xstrdup (file->name);
516 char *p = name + len;
517 bfd_boolean islib;
518
519 /* Only match the file name without the directory part. */
520 islib = *p == 'a' && *(p - 1) == '.';
521 for (; p != name; p--)
522 if (IS_DIR_SEPARATOR (*p))
523 {
524 p++;
525 break;
526 }
527
528 while (claimfile)
529 {
530 /* Claim the file only if the file name and size match and don't
531 match the whole library. */
532 if (!strcmp (p, claimfile->file.name)
533 && claimfile->file.filesize == file->filesize
534 && (!islib || file->offset != 0))
535 break;
536 claimfile = claimfile->next;
537 }
538
539 free (name);
540
541 /* If we decided to claim it, record that fact, and add any symbols
542 that were defined for it by plugin options. */
543 *claimed = (claimfile != 0);
544 if (claimfile)
545 {
546 claimfile->claimed = TRUE;
547 claimfile->file = *file;
548 if (claimfile->n_syms_used && !tv_add_symbols)
549 return LDPS_ERR;
550 else if (claimfile->n_syms_used)
551 return (*tv_add_symbols) (claimfile->file.handle,
552 claimfile->n_syms_used, claimfile->symbols);
553 }
554
555 return claim_file_ret;
556 }
557
558 /* Standard plugin API registerable hook. */
559 static enum ld_plugin_status
onall_symbols_read(void)560 onall_symbols_read (void)
561 {
562 static const char *resolutions[] =
563 {
564 "LDPR_UNKNOWN",
565 "LDPR_UNDEF",
566 "LDPR_PREVAILING_DEF",
567 "LDPR_PREVAILING_DEF_IRONLY",
568 "LDPR_PREEMPTED_REG",
569 "LDPR_PREEMPTED_IR",
570 "LDPR_RESOLVED_IR",
571 "LDPR_RESOLVED_EXEC",
572 "LDPR_RESOLVED_DYN",
573 "LDPR_PREVAILING_DEF_IRONLY_EXP",
574 };
575 claim_file_t *claimfile = dumpresolutions ? claimfiles_list : NULL;
576 add_file_t *addfile = addfiles_list;
577 struct ld_plugin_input_file file;
578 const void *view;
579 char buffer[30];
580 int fd;
581 char *filename;
582 if (! allsymbolsread_silent)
583 TV_MESSAGE (LDPL_INFO, "hook called: all symbols read.");
584 for ( ; claimfile; claimfile = claimfile->next)
585 {
586 enum ld_plugin_status rv;
587 int n;
588 if (claimfile->n_syms_used && !tv_get_symbols_v2)
589 return LDPS_ERR;
590 else if (!claimfile->n_syms_used)
591 continue;
592 else if (!claimfile->file.handle)
593 continue;
594 rv = tv_get_input_file (claimfile->file.handle, &file);
595 if (rv != LDPS_OK)
596 return rv;
597 TV_MESSAGE (LDPL_INFO, "Input: %s (%s)", file.name,
598 claimfile->file.name);
599 rv = tv_get_view (claimfile->file.handle, &view);
600 if (rv != LDPS_OK)
601 return rv;
602 #define EXPECTED_VIEW "/* The first line of this file must match the expectation of"
603 #define EXPECTED_VIEW_LENGTH (sizeof (EXPECTED_VIEW) - 1)
604 if (file.filesize != SIZE_OF_FUNC_C
605 || SIZE_OF_FUNC_C < EXPECTED_VIEW_LENGTH
606 || memcmp (view, EXPECTED_VIEW, EXPECTED_VIEW_LENGTH) != 0)
607 {
608 char result[EXPECTED_VIEW_LENGTH + 1];
609 memcpy (result, view, sizeof (result));
610 result[EXPECTED_VIEW_LENGTH] = '\0';
611 TV_MESSAGE (LDPL_INFO, "Incorrect view:");
612 TV_MESSAGE (LDPL_INFO, " Expect: " EXPECTED_VIEW);
613 TV_MESSAGE (LDPL_INFO, " Result: %s", result);
614 }
615 rv = tv_get_symbols_v2 (claimfile->file.handle, claimfile->n_syms_used,
616 claimfile->symbols);
617 if (rv != LDPS_OK)
618 return rv;
619 for (n = 0; n < claimfile->n_syms_used; n++)
620 TV_MESSAGE (LDPL_INFO, "Sym: '%s%s%s' Resolution: %s",
621 claimfile->symbols[n].name,
622 claimfile->symbols[n].version ? "@" : "",
623 (claimfile->symbols[n].version
624 ? claimfile->symbols[n].version : ""),
625 resolutions[claimfile->symbols[n].resolution]);
626 fd = claimfile->file.fd;
627 filename = xstrdup (claimfile->file.name);
628 rv = tv_release_input_file (claimfile->file.handle);
629 if (rv != LDPS_OK)
630 {
631 free (filename);
632 return rv;
633 }
634 if (read (fd, buffer, sizeof (buffer)) >= 0)
635 {
636 TV_MESSAGE (LDPL_FATAL, "Unreleased file descriptor on: %s",
637 claimfile->file.name);
638 free (filename);
639 return LDPS_ERR;
640 }
641 free (filename);
642 }
643 for ( ; addfile ; addfile = addfile->next)
644 {
645 enum ld_plugin_status rv;
646 if (addfile->type == ADD_LIB && tv_add_input_library)
647 rv = (*tv_add_input_library) (addfile->name);
648 else if (addfile->type == ADD_FILE && tv_add_input_file)
649 rv = (*tv_add_input_file) (addfile->name);
650 else if (addfile->type == ADD_DIR && tv_set_extra_library_path)
651 rv = (*tv_set_extra_library_path) (addfile->name);
652 else
653 rv = LDPS_ERR;
654 if (rv != LDPS_OK)
655 return rv;
656 }
657 fflush (NULL);
658 return all_symbols_read_ret;
659 }
660
661 /* Standard plugin API registerable hook. */
662 static enum ld_plugin_status
oncleanup(void)663 oncleanup (void)
664 {
665 TV_MESSAGE (LDPL_INFO, "hook called: cleanup.");
666 fflush (NULL);
667 return cleanup_ret;
668 }
669