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