]> Git Repo - binutils.git/blob - bfd/plugin.c
* gdb.cp/cplusfuncs.cc (class foo): Add operators
[binutils.git] / bfd / plugin.c
1 /* Plugin support for BFD.
2    Copyright 2009
3    Free Software Foundation, Inc.
4
5    This file is part of BFD, the Binary File Descriptor library.
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 "config.h"
23 #include "bfd.h"
24
25 #if BFD_SUPPORTS_PLUGINS
26
27 #include <assert.h>
28 #include <dlfcn.h>
29 #include <stdarg.h>
30 #include "plugin-api.h"
31 #include "sysdep.h"
32 #include "plugin.h"
33 #include "libbfd.h"
34 #include "libiberty.h"
35 #include <dirent.h>
36
37 #define bfd_plugin_close_and_cleanup                  _bfd_generic_close_and_cleanup
38 #define bfd_plugin_bfd_free_cached_info               _bfd_generic_bfd_free_cached_info
39 #define bfd_plugin_new_section_hook                   _bfd_generic_new_section_hook
40 #define bfd_plugin_get_section_contents               _bfd_generic_get_section_contents
41 #define bfd_plugin_get_section_contents_in_window     _bfd_generic_get_section_contents_in_window
42 #define bfd_plugin_bfd_copy_private_header_data       _bfd_generic_bfd_copy_private_header_data
43 #define bfd_plugin_bfd_merge_private_bfd_data         _bfd_generic_bfd_merge_private_bfd_data
44 #define bfd_plugin_bfd_copy_private_header_data       _bfd_generic_bfd_copy_private_header_data
45 #define bfd_plugin_bfd_set_private_flags              _bfd_generic_bfd_set_private_flags
46 #define bfd_plugin_core_file_matches_executable_p     generic_core_file_matches_executable_p
47 #define bfd_plugin_bfd_is_local_label_name            _bfd_nosymbols_bfd_is_local_label_name
48 #define bfd_plugin_bfd_is_target_special_symbol       ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
49 #define bfd_plugin_get_lineno                         _bfd_nosymbols_get_lineno
50 #define bfd_plugin_find_nearest_line                  _bfd_nosymbols_find_nearest_line
51 #define bfd_plugin_find_inliner_info                  _bfd_nosymbols_find_inliner_info
52 #define bfd_plugin_bfd_make_debug_symbol              _bfd_nosymbols_bfd_make_debug_symbol
53 #define bfd_plugin_read_minisymbols                   _bfd_generic_read_minisymbols
54 #define bfd_plugin_minisymbol_to_symbol               _bfd_generic_minisymbol_to_symbol
55 #define bfd_plugin_set_arch_mach                      bfd_default_set_arch_mach
56 #define bfd_plugin_set_section_contents               _bfd_generic_set_section_contents
57 #define bfd_plugin_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
58 #define bfd_plugin_bfd_relax_section                  bfd_generic_relax_section
59 #define bfd_plugin_bfd_link_hash_table_create         _bfd_generic_link_hash_table_create
60 #define bfd_plugin_bfd_link_hash_table_free           _bfd_generic_link_hash_table_free
61 #define bfd_plugin_bfd_link_add_symbols               _bfd_generic_link_add_symbols
62 #define bfd_plugin_bfd_link_just_syms                 _bfd_generic_link_just_syms
63 #define bfd_plugin_bfd_final_link                     _bfd_generic_final_link
64 #define bfd_plugin_bfd_link_split_section             _bfd_generic_link_split_section
65 #define bfd_plugin_bfd_gc_sections                    bfd_generic_gc_sections
66 #define bfd_plugin_bfd_merge_sections                 bfd_generic_merge_sections
67 #define bfd_plugin_bfd_is_group_section               bfd_generic_is_group_section
68 #define bfd_plugin_bfd_discard_group                  bfd_generic_discard_group
69 #define bfd_plugin_section_already_linked             _bfd_generic_section_already_linked
70 #define bfd_plugin_bfd_define_common_symbol           bfd_generic_define_common_symbol
71
72 static enum ld_plugin_status
73 message (int level ATTRIBUTE_UNUSED,
74          const char * format, ...)
75 {
76   va_list args;
77   va_start (args, format);
78   printf ("bfd plugin: ");
79   vprintf (format, args);
80   va_end (args);
81   return LDPS_OK;
82 }
83
84 /* Register a claim-file handler. */
85 static ld_plugin_claim_file_handler claim_file;
86
87 static enum ld_plugin_status
88 register_claim_file (ld_plugin_claim_file_handler handler)
89 {
90   claim_file = handler;
91   return LDPS_OK;
92 }
93
94 static enum ld_plugin_status
95 add_symbols (void * handle,
96              int nsyms,
97              const struct ld_plugin_symbol * syms)
98 {
99   bfd *abfd = handle;
100   struct plugin_data_struct *plugin_data =
101     bfd_alloc (abfd, sizeof (plugin_data_struct));;
102
103   plugin_data->nsyms = nsyms;
104   plugin_data->syms = syms;
105
106   if (nsyms != 0)
107     abfd->flags |= HAS_SYMS;
108
109   abfd->tdata.plugin_data = plugin_data;
110   return LDPS_OK;
111 }
112
113 static const char *plugin_program_name;
114
115 void
116 bfd_plugin_set_program_name (const char *program_name)
117 {
118   plugin_program_name = program_name;
119 }
120
121 static int
122 try_load_plugin (const char *pname)
123 {
124   static void *plugin_handle;
125   int tv_size = 4;
126   struct ld_plugin_tv tv[tv_size];
127   int i;
128   ld_plugin_onload onload;
129   enum ld_plugin_status status;
130
131   plugin_handle = dlopen (pname, RTLD_NOW);
132   if (!plugin_handle)
133     {
134       (*_bfd_error_handler)("%s\n", dlerror ());
135       return 0;
136     }
137
138   onload = dlsym (plugin_handle, "onload");
139   if (!onload)
140     goto err;
141
142   i = 0;
143   tv[i].tv_tag = LDPT_MESSAGE;
144   tv[i].tv_u.tv_message = message;
145
146   ++i;
147   tv[i].tv_tag = LDPT_REGISTER_CLAIM_FILE_HOOK;
148   tv[i].tv_u.tv_register_claim_file = register_claim_file;
149
150   ++i;
151   tv[i].tv_tag = LDPT_ADD_SYMBOLS;
152   tv[i].tv_u.tv_add_symbols = add_symbols;
153
154   ++i;
155   tv[i].tv_tag = LDPT_NULL;
156   tv[i].tv_u.tv_val = 0;
157
158   status = (*onload)(tv);
159
160   if (status != LDPS_OK)
161     goto err;
162
163   if (!claim_file)
164     goto err;
165
166   return 1;
167
168  err:
169   plugin_handle = NULL;
170   return 0;
171 }
172
173 static const char *plugin_name;
174
175 void
176 bfd_plugin_set_plugin (const char *p)
177 {
178   plugin_name = p;
179 }
180
181 static int
182 load_plugin (void)
183 {
184   char *plugin_dir;
185   char *p;
186   DIR *d;
187   struct dirent *ent;
188   int found = 0;
189
190   if (plugin_name)
191     return try_load_plugin (plugin_name);
192
193   if (plugin_program_name == NULL)
194     return 0;
195
196   plugin_dir = concat (BINDIR, "/../lib/bfd-plugins", NULL);
197   p = make_relative_prefix (plugin_program_name,
198                             BINDIR,
199                             plugin_dir);
200   free (plugin_dir);
201   plugin_dir = NULL;
202
203   d = opendir (p);
204   if (!d)
205     goto out;
206
207   while ((ent = readdir (d)))
208     {
209       char *full_name;
210       struct stat s;
211
212       full_name = concat (p, "/", ent->d_name, NULL);
213       if (stat(full_name, &s) == 0 && S_ISREG (s.st_mode))
214         found = try_load_plugin (full_name);
215       free (full_name);
216       if (found)
217         break;
218     }
219
220  out:
221   free (p);
222   if (d)
223     closedir (d);
224
225   return found;
226 }
227
228
229 static const bfd_target *
230 bfd_plugin_object_p (bfd *abfd)
231 {
232   int claimed = 0;
233   int t = load_plugin ();
234   struct ld_plugin_input_file file;
235   if (!t)
236     return NULL;
237
238   file.name = abfd->filename;
239
240   if (abfd->iostream)
241     {
242       file.fd = fileno (abfd->iostream);
243       file.offset = 0;
244       file.filesize = 0; /*FIXME*/
245     }
246   else
247     {
248       bfd *archive = abfd->my_archive;
249       BFD_ASSERT (archive);
250       file.fd = fileno (archive->iostream);
251       file.offset = abfd->origin;
252       file.filesize = arelt_size (abfd);
253
254     }
255   file.handle = abfd;
256   claim_file (&file, &claimed);
257   if (!claimed)
258     return NULL;
259
260   return abfd->xvec;
261 }
262
263 /* Copy any private info we understand from the input bfd
264    to the output bfd.  */
265
266 static bfd_boolean
267 bfd_plugin_bfd_copy_private_bfd_data (bfd *ibfd ATTRIBUTE_UNUSED,
268                                       bfd *obfd ATTRIBUTE_UNUSED)
269 {
270   BFD_ASSERT (0);
271   return TRUE;
272 }
273
274 /* Copy any private info we understand from the input section
275    to the output section.  */
276
277 static bfd_boolean
278 bfd_plugin_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED,
279                                           asection *isection ATTRIBUTE_UNUSED,
280                                           bfd *obfd ATTRIBUTE_UNUSED,
281                                           asection *osection ATTRIBUTE_UNUSED)
282 {
283   BFD_ASSERT (0);
284   return TRUE;
285 }
286
287 /* Copy any private info we understand from the input symbol
288    to the output symbol.  */
289
290 static bfd_boolean
291 bfd_plugin_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED,
292                                          asymbol *isymbol ATTRIBUTE_UNUSED,
293                                          bfd *obfd ATTRIBUTE_UNUSED,
294                                          asymbol *osymbol ATTRIBUTE_UNUSED)
295 {
296   BFD_ASSERT (0);
297   return TRUE;
298 }
299
300 static bfd_boolean
301 bfd_plugin_bfd_print_private_bfd_data (bfd *abfd ATTRIBUTE_UNUSED, PTR ptr ATTRIBUTE_UNUSED)
302 {
303   BFD_ASSERT (0);
304   return TRUE;
305 }
306
307 static char *
308 bfd_plugin_core_file_failing_command (bfd *abfd ATTRIBUTE_UNUSED)
309 {
310   BFD_ASSERT (0);
311   return NULL;
312 }
313
314 static int
315 bfd_plugin_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
316 {
317   BFD_ASSERT (0);
318   return 0;
319 }
320
321 static long
322 bfd_plugin_get_symtab_upper_bound (bfd *abfd)
323 {
324   struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
325   long nsyms = plugin_data->nsyms;
326
327   BFD_ASSERT (nsyms >= 0);
328
329   return ((nsyms + 1) * sizeof (asymbol *));
330 }
331
332 static flagword
333 convert_flags (const struct ld_plugin_symbol *sym)
334 {
335  switch (sym->def)
336    { 
337    case LDPK_DEF:
338    case LDPK_COMMON:
339    case LDPK_UNDEF:
340      return BSF_GLOBAL;
341
342    case LDPK_WEAKUNDEF:
343    case LDPK_WEAKDEF:
344      return BSF_GLOBAL | BSF_WEAK;
345
346    default:
347      BFD_ASSERT (0);
348      return 0;
349    }
350 }
351
352 static long
353 bfd_plugin_canonicalize_symtab (bfd *abfd,
354                                 asymbol **alocation)
355 {
356   struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
357   long nsyms = plugin_data->nsyms;
358   const struct ld_plugin_symbol *syms = plugin_data->syms;
359   static asection fake_section;
360   static asection fake_common_section;
361   int i;
362
363   fake_section.name = ".text";
364   fake_common_section.flags = SEC_IS_COMMON;
365
366   for (i = 0; i < nsyms; i++)
367     {
368       asymbol *s = bfd_alloc (abfd, sizeof (asymbol)); 
369
370       BFD_ASSERT (s);
371       alocation[i] = s;
372
373       s->the_bfd = abfd;
374       s->name = syms[i].name;
375       s->value = 0;
376       s->flags = convert_flags (&syms[i]);
377       switch (syms[i].def)
378         {
379         case LDPK_COMMON:
380           s->section = &fake_common_section;
381           break;
382         case LDPK_UNDEF:
383         case LDPK_WEAKUNDEF:
384           s->section = bfd_und_section_ptr;
385           break;
386         case LDPK_DEF:
387         case LDPK_WEAKDEF:
388           s->section = &fake_section;
389           break;
390         default:
391           BFD_ASSERT (0);
392         }
393
394       s->udata.p = (void *) &syms[i];
395     }
396
397   return nsyms;
398 }
399
400 static void
401 bfd_plugin_print_symbol (bfd *abfd ATTRIBUTE_UNUSED,
402                          PTR afile ATTRIBUTE_UNUSED,
403                          asymbol *symbol ATTRIBUTE_UNUSED,
404                          bfd_print_symbol_type how ATTRIBUTE_UNUSED)
405 {
406   BFD_ASSERT (0);
407 }
408
409 static void
410 bfd_plugin_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
411                             asymbol *symbol,
412                             symbol_info *ret)
413 {
414   bfd_symbol_info (symbol, ret);
415 }
416
417 /* Make an empty symbol. */
418
419 static asymbol *
420 bfd_plugin_make_empty_symbol (bfd *abfd)
421 {
422   asymbol *new_symbol = bfd_zalloc (abfd, sizeof (asymbol));
423   if (new_symbol == NULL)
424     return new_symbol;
425   new_symbol->the_bfd = abfd;
426   return new_symbol;
427 }
428
429 static int
430 bfd_plugin_sizeof_headers (bfd *a ATTRIBUTE_UNUSED,
431                            struct bfd_link_info *info ATTRIBUTE_UNUSED)
432 {
433   BFD_ASSERT (0);
434   return 0;
435 }
436
437 static bfd_boolean
438 bfd_plugin_mkobject (bfd *abfd ATTRIBUTE_UNUSED)
439 {
440   BFD_ASSERT (0);
441   return 0;
442 }
443
444 const bfd_target plugin_vec =
445 {
446   "plugin",                     /* Name.  */
447   bfd_target_unknown_flavour,
448   BFD_ENDIAN_LITTLE,            /* Target byte order.  */
449   BFD_ENDIAN_LITTLE,            /* Target headers byte order.  */
450   (HAS_RELOC | EXEC_P |         /* Object flags.  */
451    HAS_LINENO | HAS_DEBUG |
452    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
453   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
454    | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags.  */
455   0,                            /* symbol_leading_char.  */
456   '/',                          /* ar_pad_char.  */
457   15,                           /* ar_max_namelen.  */
458
459   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
460   bfd_getl32, bfd_getl_signed_32, bfd_putl32,
461   bfd_getl16, bfd_getl_signed_16, bfd_putl16,   /* data */
462   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
463   bfd_getl32, bfd_getl_signed_32, bfd_putl32,
464   bfd_getl16, bfd_getl_signed_16, bfd_putl16,   /* hdrs */
465
466   {                             /* bfd_check_format.  */
467     _bfd_dummy_target,
468     bfd_plugin_object_p,
469     bfd_generic_archive_p,
470     _bfd_dummy_target
471   },
472   {                             /* bfd_set_format.  */
473     bfd_false,
474     bfd_plugin_mkobject,
475     _bfd_generic_mkarchive,
476     bfd_false,
477   },
478   {                             /* bfd_write_contents.  */
479     bfd_false,
480     bfd_false,
481     _bfd_write_archive_contents,
482     bfd_false,
483   },
484
485   BFD_JUMP_TABLE_GENERIC (bfd_plugin),
486   BFD_JUMP_TABLE_COPY (bfd_plugin),
487   BFD_JUMP_TABLE_CORE (bfd_plugin),
488   BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
489   BFD_JUMP_TABLE_SYMBOLS (bfd_plugin),
490   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
491   BFD_JUMP_TABLE_WRITE (bfd_plugin),
492   BFD_JUMP_TABLE_LINK (bfd_plugin),
493   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
494
495   NULL,
496
497   NULL                          /* backend_data.  */
498 };
499 #endif /* BFD_SUPPORTS_PLUGIN */
This page took 0.052403 seconds and 4 git commands to generate.