xref: /dflybsd-src/contrib/binutils-2.34/bfd/plugin.c (revision a72d4fb11b2b988dc5145de33d627d77bb17732b)
1fae548d3Szrj /* Plugin support for BFD.
2fae548d3Szrj    Copyright (C) 2009-2020 Free Software Foundation, Inc.
3fae548d3Szrj 
4fae548d3Szrj    This file is part of BFD, the Binary File Descriptor library.
5fae548d3Szrj 
6fae548d3Szrj    This program is free software; you can redistribute it and/or modify
7fae548d3Szrj    it under the terms of the GNU General Public License as published by
8fae548d3Szrj    the Free Software Foundation; either version 3 of the License, or
9fae548d3Szrj    (at your option) any later version.
10fae548d3Szrj 
11fae548d3Szrj    This program is distributed in the hope that it will be useful,
12fae548d3Szrj    but WITHOUT ANY WARRANTY; without even the implied warranty of
13fae548d3Szrj    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14fae548d3Szrj    GNU General Public License for more details.
15fae548d3Szrj 
16fae548d3Szrj    You should have received a copy of the GNU General Public License
17fae548d3Szrj    along with this program; if not, write to the Free Software
18fae548d3Szrj    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19fae548d3Szrj    MA 02110-1301, USA.  */
20fae548d3Szrj 
21fae548d3Szrj #include "sysdep.h"
22fae548d3Szrj #include "bfd.h"
23fae548d3Szrj 
24fae548d3Szrj #if BFD_SUPPORTS_PLUGINS
25fae548d3Szrj 
26fae548d3Szrj #include <assert.h>
27fae548d3Szrj #ifdef HAVE_DLFCN_H
28fae548d3Szrj #include <dlfcn.h>
29fae548d3Szrj #elif defined (HAVE_WINDOWS_H)
30fae548d3Szrj #include <windows.h>
31fae548d3Szrj #else
32fae548d3Szrj #error Unknown how to handle dynamic-load-libraries.
33fae548d3Szrj #endif
34fae548d3Szrj #include <stdarg.h>
35fae548d3Szrj #include "plugin-api.h"
36fae548d3Szrj #include "plugin.h"
37fae548d3Szrj #include "libbfd.h"
38fae548d3Szrj #include "libiberty.h"
39fae548d3Szrj #include <dirent.h>
40fae548d3Szrj 
41fae548d3Szrj #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
42fae548d3Szrj 
43fae548d3Szrj #define RTLD_NOW 0      /* Dummy value.  */
44fae548d3Szrj 
45fae548d3Szrj static void *
dlopen(const char * file,int mode ATTRIBUTE_UNUSED)46fae548d3Szrj dlopen (const char *file, int mode ATTRIBUTE_UNUSED)
47fae548d3Szrj {
48fae548d3Szrj   return LoadLibrary (file);
49fae548d3Szrj }
50fae548d3Szrj 
51fae548d3Szrj static void *
dlsym(void * handle,const char * name)52fae548d3Szrj dlsym (void *handle, const char *name)
53fae548d3Szrj {
54fae548d3Szrj   return GetProcAddress (handle, name);
55fae548d3Szrj }
56fae548d3Szrj 
57fae548d3Szrj static int ATTRIBUTE_UNUSED
dlclose(void * handle)58fae548d3Szrj dlclose (void *handle)
59fae548d3Szrj {
60fae548d3Szrj   FreeLibrary (handle);
61fae548d3Szrj   return 0;
62fae548d3Szrj }
63fae548d3Szrj 
64fae548d3Szrj static const char *
dlerror(void)65fae548d3Szrj dlerror (void)
66fae548d3Szrj {
67fae548d3Szrj   return "Unable to load DLL.";
68fae548d3Szrj }
69fae548d3Szrj 
70fae548d3Szrj #endif /* !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)  */
71fae548d3Szrj 
72fae548d3Szrj #define bfd_plugin_close_and_cleanup		      _bfd_generic_close_and_cleanup
73fae548d3Szrj #define bfd_plugin_bfd_free_cached_info		      _bfd_generic_bfd_free_cached_info
74fae548d3Szrj #define bfd_plugin_new_section_hook		      _bfd_generic_new_section_hook
75fae548d3Szrj #define bfd_plugin_get_section_contents		      _bfd_generic_get_section_contents
76fae548d3Szrj #define bfd_plugin_get_section_contents_in_window     _bfd_generic_get_section_contents_in_window
77fae548d3Szrj #define bfd_plugin_bfd_copy_private_header_data	      _bfd_generic_bfd_copy_private_header_data
78fae548d3Szrj #define bfd_plugin_bfd_merge_private_bfd_data	      _bfd_generic_bfd_merge_private_bfd_data
79fae548d3Szrj #define bfd_plugin_bfd_copy_private_header_data	      _bfd_generic_bfd_copy_private_header_data
80fae548d3Szrj #define bfd_plugin_bfd_set_private_flags	      _bfd_generic_bfd_set_private_flags
81fae548d3Szrj #define bfd_plugin_core_file_matches_executable_p     generic_core_file_matches_executable_p
82fae548d3Szrj #define bfd_plugin_bfd_is_local_label_name	      _bfd_nosymbols_bfd_is_local_label_name
83fae548d3Szrj #define bfd_plugin_bfd_is_target_special_symbol	      _bfd_bool_bfd_asymbol_false
84fae548d3Szrj #define bfd_plugin_get_lineno			      _bfd_nosymbols_get_lineno
85fae548d3Szrj #define bfd_plugin_find_nearest_line		      _bfd_nosymbols_find_nearest_line
86fae548d3Szrj #define bfd_plugin_find_line			      _bfd_nosymbols_find_line
87fae548d3Szrj #define bfd_plugin_find_inliner_info		      _bfd_nosymbols_find_inliner_info
88fae548d3Szrj #define bfd_plugin_get_symbol_version_string	      _bfd_nosymbols_get_symbol_version_string
89fae548d3Szrj #define bfd_plugin_bfd_make_debug_symbol	      _bfd_nosymbols_bfd_make_debug_symbol
90fae548d3Szrj #define bfd_plugin_read_minisymbols		      _bfd_generic_read_minisymbols
91fae548d3Szrj #define bfd_plugin_minisymbol_to_symbol		      _bfd_generic_minisymbol_to_symbol
92fae548d3Szrj #define bfd_plugin_set_arch_mach		      bfd_default_set_arch_mach
93fae548d3Szrj #define bfd_plugin_set_section_contents		      _bfd_generic_set_section_contents
94fae548d3Szrj #define bfd_plugin_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
95fae548d3Szrj #define bfd_plugin_bfd_relax_section		      bfd_generic_relax_section
96fae548d3Szrj #define bfd_plugin_bfd_link_hash_table_create	      _bfd_generic_link_hash_table_create
97fae548d3Szrj #define bfd_plugin_bfd_link_add_symbols		      _bfd_generic_link_add_symbols
98fae548d3Szrj #define bfd_plugin_bfd_link_just_syms		      _bfd_generic_link_just_syms
99fae548d3Szrj #define bfd_plugin_bfd_final_link		      _bfd_generic_final_link
100fae548d3Szrj #define bfd_plugin_bfd_link_split_section	      _bfd_generic_link_split_section
101fae548d3Szrj #define bfd_plugin_bfd_gc_sections		      bfd_generic_gc_sections
102fae548d3Szrj #define bfd_plugin_bfd_lookup_section_flags	      bfd_generic_lookup_section_flags
103fae548d3Szrj #define bfd_plugin_bfd_merge_sections		      bfd_generic_merge_sections
104fae548d3Szrj #define bfd_plugin_bfd_is_group_section		      bfd_generic_is_group_section
105fae548d3Szrj #define bfd_plugin_bfd_group_name		      bfd_generic_group_name
106fae548d3Szrj #define bfd_plugin_bfd_discard_group		      bfd_generic_discard_group
107fae548d3Szrj #define bfd_plugin_section_already_linked	      _bfd_generic_section_already_linked
108fae548d3Szrj #define bfd_plugin_bfd_define_common_symbol	      bfd_generic_define_common_symbol
109fae548d3Szrj #define bfd_plugin_bfd_link_hide_symbol		      _bfd_generic_link_hide_symbol
110fae548d3Szrj #define bfd_plugin_bfd_define_start_stop	      bfd_generic_define_start_stop
111fae548d3Szrj #define bfd_plugin_bfd_copy_link_hash_symbol_type     _bfd_generic_copy_link_hash_symbol_type
112fae548d3Szrj #define bfd_plugin_bfd_link_check_relocs	      _bfd_generic_link_check_relocs
113fae548d3Szrj 
114fae548d3Szrj static enum ld_plugin_status
message(int level ATTRIBUTE_UNUSED,const char * format,...)115fae548d3Szrj message (int level ATTRIBUTE_UNUSED,
116fae548d3Szrj 	 const char * format, ...)
117fae548d3Szrj {
118fae548d3Szrj   va_list args;
119fae548d3Szrj   va_start (args, format);
120fae548d3Szrj   printf ("bfd plugin: ");
121fae548d3Szrj   vprintf (format, args);
122fae548d3Szrj   putchar ('\n');
123fae548d3Szrj   va_end (args);
124fae548d3Szrj   return LDPS_OK;
125fae548d3Szrj }
126fae548d3Szrj 
127fae548d3Szrj /* Register a claim-file handler. */
128fae548d3Szrj static ld_plugin_claim_file_handler claim_file = NULL;
129fae548d3Szrj 
130fae548d3Szrj static enum ld_plugin_status
register_claim_file(ld_plugin_claim_file_handler handler)131fae548d3Szrj register_claim_file (ld_plugin_claim_file_handler handler)
132fae548d3Szrj {
133fae548d3Szrj   claim_file = handler;
134fae548d3Szrj   return LDPS_OK;
135fae548d3Szrj }
136fae548d3Szrj 
137fae548d3Szrj static enum ld_plugin_status
add_symbols(void * handle,int nsyms,const struct ld_plugin_symbol * syms)138fae548d3Szrj add_symbols (void * handle,
139fae548d3Szrj 	     int nsyms,
140fae548d3Szrj 	     const struct ld_plugin_symbol * syms)
141fae548d3Szrj {
142fae548d3Szrj   bfd *abfd = handle;
143fae548d3Szrj   struct plugin_data_struct *plugin_data =
144fae548d3Szrj     bfd_alloc (abfd, sizeof (plugin_data_struct));
145fae548d3Szrj 
146fae548d3Szrj   plugin_data->nsyms = nsyms;
147fae548d3Szrj   plugin_data->syms = syms;
148fae548d3Szrj 
149fae548d3Szrj   if (nsyms != 0)
150fae548d3Szrj     abfd->flags |= HAS_SYMS;
151fae548d3Szrj 
152fae548d3Szrj   abfd->tdata.plugin_data = plugin_data;
153fae548d3Szrj   return LDPS_OK;
154fae548d3Szrj }
155fae548d3Szrj 
156fae548d3Szrj static const char *plugin_program_name;
157fae548d3Szrj 
158fae548d3Szrj void
bfd_plugin_set_program_name(const char * program_name)159fae548d3Szrj bfd_plugin_set_program_name (const char *program_name)
160fae548d3Szrj {
161fae548d3Szrj   plugin_program_name = program_name;
162fae548d3Szrj }
163fae548d3Szrj 
164fae548d3Szrj int
bfd_plugin_open_input(bfd * ibfd,struct ld_plugin_input_file * file)165fae548d3Szrj bfd_plugin_open_input (bfd *ibfd, struct ld_plugin_input_file *file)
166fae548d3Szrj {
167fae548d3Szrj   bfd *iobfd;
168fae548d3Szrj 
169fae548d3Szrj   iobfd = ibfd;
170fae548d3Szrj   while (iobfd->my_archive
171fae548d3Szrj 	 && !bfd_is_thin_archive (iobfd->my_archive))
172fae548d3Szrj     iobfd = iobfd->my_archive;
173fae548d3Szrj   file->name = iobfd->filename;
174fae548d3Szrj 
175fae548d3Szrj   if (!iobfd->iostream && !bfd_open_file (iobfd))
176fae548d3Szrj     return 0;
177fae548d3Szrj 
178fae548d3Szrj   /* The plugin API expects that the file descriptor won't be closed
179fae548d3Szrj      and reused as done by the bfd file cache.  So open it again.
180fae548d3Szrj      dup isn't good enough.  plugin IO uses lseek/read while BFD uses
181fae548d3Szrj      fseek/fread.  It isn't wise to mix the unistd and stdio calls on
182fae548d3Szrj      the same underlying file descriptor.  */
183fae548d3Szrj   file->fd = open (file->name, O_RDONLY | O_BINARY);
184fae548d3Szrj   if (file->fd < 0)
185fae548d3Szrj     return 0;
186fae548d3Szrj 
187fae548d3Szrj   if (iobfd == ibfd)
188fae548d3Szrj     {
189fae548d3Szrj       struct stat stat_buf;
190fae548d3Szrj 
191fae548d3Szrj       if (fstat (file->fd, &stat_buf))
192fae548d3Szrj 	{
193fae548d3Szrj 	  close(file->fd);
194fae548d3Szrj 	  return 0;
195fae548d3Szrj 	}
196fae548d3Szrj 
197fae548d3Szrj       file->offset = 0;
198fae548d3Szrj       file->filesize = stat_buf.st_size;
199fae548d3Szrj     }
200fae548d3Szrj   else
201fae548d3Szrj     {
202fae548d3Szrj       file->offset = ibfd->origin;
203fae548d3Szrj       file->filesize = arelt_size (ibfd);
204fae548d3Szrj     }
205fae548d3Szrj   return 1;
206fae548d3Szrj }
207fae548d3Szrj 
208fae548d3Szrj static int
try_claim(bfd * abfd)209fae548d3Szrj try_claim (bfd *abfd)
210fae548d3Szrj {
211fae548d3Szrj   int claimed = 0;
212fae548d3Szrj   struct ld_plugin_input_file file;
213fae548d3Szrj 
214fae548d3Szrj   file.handle = abfd;
215fae548d3Szrj   if (!bfd_plugin_open_input (abfd, &file))
216fae548d3Szrj     return 0;
217fae548d3Szrj   if (claim_file)
218fae548d3Szrj     claim_file (&file, &claimed);
219fae548d3Szrj   close (file.fd);
220fae548d3Szrj   return claimed;
221fae548d3Szrj }
222fae548d3Szrj 
223fae548d3Szrj struct plugin_list_entry
224fae548d3Szrj {
225fae548d3Szrj   void *                        handle;
226fae548d3Szrj   ld_plugin_claim_file_handler  claim_file;
227fae548d3Szrj   struct plugin_list_entry *    next;
228fae548d3Szrj };
229fae548d3Szrj 
230fae548d3Szrj static struct plugin_list_entry * plugin_list = NULL;
231fae548d3Szrj 
232fae548d3Szrj static int
try_load_plugin(const char * pname,bfd * abfd,int * has_plugin_p)233fae548d3Szrj try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p)
234fae548d3Szrj {
235fae548d3Szrj   void *plugin_handle = NULL;
236fae548d3Szrj   struct ld_plugin_tv tv[4];
237fae548d3Szrj   int i;
238fae548d3Szrj   ld_plugin_onload onload;
239fae548d3Szrj   enum ld_plugin_status status;
240fae548d3Szrj   struct plugin_list_entry *plugin_list_iter;
241fae548d3Szrj 
242fae548d3Szrj   *has_plugin_p = 0;
243fae548d3Szrj 
244fae548d3Szrj   plugin_handle = dlopen (pname, RTLD_NOW);
245fae548d3Szrj   if (!plugin_handle)
246fae548d3Szrj     {
247fae548d3Szrj       _bfd_error_handler ("%s\n", dlerror ());
248fae548d3Szrj       return 0;
249fae548d3Szrj     }
250fae548d3Szrj 
251fae548d3Szrj   for (plugin_list_iter = plugin_list;
252fae548d3Szrj        plugin_list_iter;
253fae548d3Szrj        plugin_list_iter = plugin_list_iter->next)
254fae548d3Szrj     {
255fae548d3Szrj       if (plugin_handle == plugin_list_iter->handle)
256fae548d3Szrj 	{
257fae548d3Szrj 	  dlclose (plugin_handle);
258fae548d3Szrj 	  if (!plugin_list_iter->claim_file)
259fae548d3Szrj 	    return 0;
260fae548d3Szrj 
261fae548d3Szrj 	  register_claim_file (plugin_list_iter->claim_file);
262fae548d3Szrj 	  goto have_claim_file;
263fae548d3Szrj 	}
264fae548d3Szrj     }
265fae548d3Szrj 
266fae548d3Szrj   plugin_list_iter = bfd_malloc (sizeof *plugin_list_iter);
267fae548d3Szrj   if (plugin_list_iter == NULL)
268fae548d3Szrj     return 0;
269fae548d3Szrj   plugin_list_iter->handle = plugin_handle;
270fae548d3Szrj   plugin_list_iter->claim_file = NULL;
271fae548d3Szrj   plugin_list_iter->next = plugin_list;
272fae548d3Szrj   plugin_list = plugin_list_iter;
273fae548d3Szrj 
274fae548d3Szrj   onload = dlsym (plugin_handle, "onload");
275fae548d3Szrj   if (!onload)
276fae548d3Szrj     return 0;
277fae548d3Szrj 
278fae548d3Szrj   i = 0;
279fae548d3Szrj   tv[i].tv_tag = LDPT_MESSAGE;
280fae548d3Szrj   tv[i].tv_u.tv_message = message;
281fae548d3Szrj 
282fae548d3Szrj   ++i;
283fae548d3Szrj   tv[i].tv_tag = LDPT_REGISTER_CLAIM_FILE_HOOK;
284fae548d3Szrj   tv[i].tv_u.tv_register_claim_file = register_claim_file;
285fae548d3Szrj 
286fae548d3Szrj   ++i;
287fae548d3Szrj   tv[i].tv_tag = LDPT_ADD_SYMBOLS;
288fae548d3Szrj   tv[i].tv_u.tv_add_symbols = add_symbols;
289fae548d3Szrj 
290fae548d3Szrj   ++i;
291fae548d3Szrj   tv[i].tv_tag = LDPT_NULL;
292fae548d3Szrj   tv[i].tv_u.tv_val = 0;
293fae548d3Szrj 
294fae548d3Szrj   status = (*onload)(tv);
295fae548d3Szrj 
296fae548d3Szrj   if (status != LDPS_OK)
297fae548d3Szrj     return 0;
298fae548d3Szrj 
299fae548d3Szrj   plugin_list_iter->claim_file = claim_file;
300fae548d3Szrj 
301fae548d3Szrj have_claim_file:
302fae548d3Szrj   *has_plugin_p = 1;
303fae548d3Szrj 
304fae548d3Szrj   abfd->plugin_format = bfd_plugin_no;
305fae548d3Szrj 
306fae548d3Szrj   if (!claim_file)
307fae548d3Szrj     return 0;
308fae548d3Szrj 
309fae548d3Szrj   if (!try_claim (abfd))
310fae548d3Szrj     return 0;
311fae548d3Szrj 
312fae548d3Szrj   abfd->plugin_format = bfd_plugin_yes;
313fae548d3Szrj   return 1;
314fae548d3Szrj }
315fae548d3Szrj 
316fae548d3Szrj /* There may be plugin libraries in lib/bfd-plugins.  */
317fae548d3Szrj 
318fae548d3Szrj static int has_plugin = -1;
319fae548d3Szrj 
320fae548d3Szrj static const bfd_target *(*ld_plugin_object_p) (bfd *);
321fae548d3Szrj 
322fae548d3Szrj static const char *plugin_name;
323fae548d3Szrj 
324fae548d3Szrj void
bfd_plugin_set_plugin(const char * p)325fae548d3Szrj bfd_plugin_set_plugin (const char *p)
326fae548d3Szrj {
327fae548d3Szrj   plugin_name = p;
328fae548d3Szrj   has_plugin = p != NULL;
329fae548d3Szrj }
330fae548d3Szrj 
331fae548d3Szrj /* Return TRUE if a plugin library is used.  */
332fae548d3Szrj 
333fae548d3Szrj bfd_boolean
bfd_plugin_specified_p(void)334fae548d3Szrj bfd_plugin_specified_p (void)
335fae548d3Szrj {
336fae548d3Szrj   return has_plugin > 0;
337fae548d3Szrj }
338fae548d3Szrj 
339fae548d3Szrj /* Return TRUE if ABFD can be claimed by linker LTO plugin.  */
340fae548d3Szrj 
341fae548d3Szrj bfd_boolean
bfd_link_plugin_object_p(bfd * abfd)342fae548d3Szrj bfd_link_plugin_object_p (bfd *abfd)
343fae548d3Szrj {
344fae548d3Szrj   if (ld_plugin_object_p)
345fae548d3Szrj     return ld_plugin_object_p (abfd) != NULL;
346fae548d3Szrj   return FALSE;
347fae548d3Szrj }
348fae548d3Szrj 
349fae548d3Szrj extern const bfd_target plugin_vec;
350fae548d3Szrj 
351fae548d3Szrj /* Return TRUE if TARGET is a pointer to plugin_vec.  */
352fae548d3Szrj 
353fae548d3Szrj bfd_boolean
bfd_plugin_target_p(const bfd_target * target)354fae548d3Szrj bfd_plugin_target_p (const bfd_target *target)
355fae548d3Szrj {
356fae548d3Szrj   return target == &plugin_vec;
357fae548d3Szrj }
358fae548d3Szrj 
359fae548d3Szrj /* Register OBJECT_P to be used by bfd_plugin_object_p.  */
360fae548d3Szrj 
361fae548d3Szrj void
register_ld_plugin_object_p(const bfd_target * (* object_p)(bfd *))362fae548d3Szrj register_ld_plugin_object_p (const bfd_target *(*object_p) (bfd *))
363fae548d3Szrj {
364fae548d3Szrj   ld_plugin_object_p = object_p;
365fae548d3Szrj }
366fae548d3Szrj 
367fae548d3Szrj static int
load_plugin(bfd * abfd)368fae548d3Szrj load_plugin (bfd *abfd)
369fae548d3Szrj {
370fae548d3Szrj   /* The intent was to search ${libdir}/bfd-plugins for plugins, but
371fae548d3Szrj      unfortunately the original implementation wasn't precisely that
372fae548d3Szrj      when configuring binutils using --libdir.  Search in the proper
373fae548d3Szrj      path first, then the old one for backwards compatibility.  */
374fae548d3Szrj   static const char *path[]
375*a72d4fb1Szrj     = { PLUGINLIBDIR "/bfd-plugins", BINDIR RELPLUGINDIR};
376fae548d3Szrj   struct stat last_st;
377fae548d3Szrj   int found = 0;
378fae548d3Szrj   unsigned int i;
379fae548d3Szrj 
380fae548d3Szrj   if (!has_plugin)
381fae548d3Szrj     return found;
382fae548d3Szrj 
383fae548d3Szrj   if (plugin_name)
384fae548d3Szrj     return try_load_plugin (plugin_name, abfd, &has_plugin);
385fae548d3Szrj 
386fae548d3Szrj   if (plugin_program_name == NULL)
387fae548d3Szrj     return found;
388fae548d3Szrj 
389fae548d3Szrj   /* Try not to search the same dir twice, by looking at st_dev and
390fae548d3Szrj      st_ino for the dir.  If we are on a file system that always sets
391fae548d3Szrj      st_ino to zero or the actual st_ino is zero we might waste some
392fae548d3Szrj      time, but that doesn't matter too much.  */
393fae548d3Szrj   last_st.st_dev = 0;
394fae548d3Szrj   last_st.st_ino = 0;
395fae548d3Szrj   for (i = 0; i < sizeof (path) / sizeof (path[0]); i++)
396fae548d3Szrj     {
397fae548d3Szrj       char *plugin_dir = make_relative_prefix (plugin_program_name,
398fae548d3Szrj 					       BINDIR,
399fae548d3Szrj 					       path[i]);
400fae548d3Szrj       if (plugin_dir)
401fae548d3Szrj 	{
402fae548d3Szrj 	  struct stat st;
403fae548d3Szrj 	  DIR *d;
404fae548d3Szrj 
405fae548d3Szrj 	  if (stat (plugin_dir, &st) == 0
406fae548d3Szrj 	      && S_ISDIR (st.st_mode)
407fae548d3Szrj 	      && !(last_st.st_dev == st.st_dev
408fae548d3Szrj 		   && last_st.st_ino == st.st_ino
409fae548d3Szrj 		   && st.st_ino != 0)
410fae548d3Szrj 	      && (d = opendir (plugin_dir)) != NULL)
411fae548d3Szrj 	    {
412fae548d3Szrj 	      struct dirent *ent;
413fae548d3Szrj 
414fae548d3Szrj 	      last_st.st_dev = st.st_dev;
415fae548d3Szrj 	      last_st.st_ino = st.st_ino;
416fae548d3Szrj 	      while ((ent = readdir (d)) != NULL)
417fae548d3Szrj 		{
418fae548d3Szrj 		  char *full_name;
419fae548d3Szrj 
420fae548d3Szrj 		  full_name = concat (plugin_dir, "/", ent->d_name, NULL);
421fae548d3Szrj 		  if (stat (full_name, &st) == 0 && S_ISREG (st.st_mode))
422fae548d3Szrj 		    {
423fae548d3Szrj 		      int valid_plugin;
424fae548d3Szrj 
425fae548d3Szrj 		      found = try_load_plugin (full_name, abfd, &valid_plugin);
426fae548d3Szrj 		      if (has_plugin <= 0)
427fae548d3Szrj 			has_plugin = valid_plugin;
428fae548d3Szrj 		    }
429fae548d3Szrj 		  free (full_name);
430fae548d3Szrj 		  if (found)
431fae548d3Szrj 		    break;
432fae548d3Szrj 		}
433fae548d3Szrj 	      closedir (d);
434fae548d3Szrj 	    }
435fae548d3Szrj 	  free (plugin_dir);
436fae548d3Szrj 	}
437fae548d3Szrj       if (found)
438fae548d3Szrj 	break;
439fae548d3Szrj     }
440fae548d3Szrj 
441fae548d3Szrj   return found;
442fae548d3Szrj }
443fae548d3Szrj 
444fae548d3Szrj 
445fae548d3Szrj static const bfd_target *
bfd_plugin_object_p(bfd * abfd)446fae548d3Szrj bfd_plugin_object_p (bfd *abfd)
447fae548d3Szrj {
448fae548d3Szrj   if (ld_plugin_object_p)
449fae548d3Szrj     return ld_plugin_object_p (abfd);
450fae548d3Szrj 
451fae548d3Szrj   if (abfd->plugin_format == bfd_plugin_unknown && !load_plugin (abfd))
452fae548d3Szrj     return NULL;
453fae548d3Szrj 
454fae548d3Szrj   return abfd->plugin_format == bfd_plugin_yes ? abfd->xvec : NULL;
455fae548d3Szrj }
456fae548d3Szrj 
457fae548d3Szrj /* Copy any private info we understand from the input bfd
458fae548d3Szrj    to the output bfd.  */
459fae548d3Szrj 
460fae548d3Szrj static bfd_boolean
bfd_plugin_bfd_copy_private_bfd_data(bfd * ibfd ATTRIBUTE_UNUSED,bfd * obfd ATTRIBUTE_UNUSED)461fae548d3Szrj bfd_plugin_bfd_copy_private_bfd_data (bfd *ibfd ATTRIBUTE_UNUSED,
462fae548d3Szrj 				      bfd *obfd ATTRIBUTE_UNUSED)
463fae548d3Szrj {
464fae548d3Szrj   BFD_ASSERT (0);
465fae548d3Szrj   return TRUE;
466fae548d3Szrj }
467fae548d3Szrj 
468fae548d3Szrj /* Copy any private info we understand from the input section
469fae548d3Szrj    to the output section.  */
470fae548d3Szrj 
471fae548d3Szrj static bfd_boolean
bfd_plugin_bfd_copy_private_section_data(bfd * ibfd ATTRIBUTE_UNUSED,asection * isection ATTRIBUTE_UNUSED,bfd * obfd ATTRIBUTE_UNUSED,asection * osection ATTRIBUTE_UNUSED)472fae548d3Szrj bfd_plugin_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED,
473fae548d3Szrj 					  asection *isection ATTRIBUTE_UNUSED,
474fae548d3Szrj 					  bfd *obfd ATTRIBUTE_UNUSED,
475fae548d3Szrj 					  asection *osection ATTRIBUTE_UNUSED)
476fae548d3Szrj {
477fae548d3Szrj   BFD_ASSERT (0);
478fae548d3Szrj   return TRUE;
479fae548d3Szrj }
480fae548d3Szrj 
481fae548d3Szrj /* Copy any private info we understand from the input symbol
482fae548d3Szrj    to the output symbol.  */
483fae548d3Szrj 
484fae548d3Szrj static bfd_boolean
bfd_plugin_bfd_copy_private_symbol_data(bfd * ibfd ATTRIBUTE_UNUSED,asymbol * isymbol ATTRIBUTE_UNUSED,bfd * obfd ATTRIBUTE_UNUSED,asymbol * osymbol ATTRIBUTE_UNUSED)485fae548d3Szrj bfd_plugin_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED,
486fae548d3Szrj 					 asymbol *isymbol ATTRIBUTE_UNUSED,
487fae548d3Szrj 					 bfd *obfd ATTRIBUTE_UNUSED,
488fae548d3Szrj 					 asymbol *osymbol ATTRIBUTE_UNUSED)
489fae548d3Szrj {
490fae548d3Szrj   BFD_ASSERT (0);
491fae548d3Szrj   return TRUE;
492fae548d3Szrj }
493fae548d3Szrj 
494fae548d3Szrj static bfd_boolean
bfd_plugin_bfd_print_private_bfd_data(bfd * abfd ATTRIBUTE_UNUSED,PTR ptr ATTRIBUTE_UNUSED)495fae548d3Szrj bfd_plugin_bfd_print_private_bfd_data (bfd *abfd ATTRIBUTE_UNUSED, PTR ptr ATTRIBUTE_UNUSED)
496fae548d3Szrj {
497fae548d3Szrj   BFD_ASSERT (0);
498fae548d3Szrj   return TRUE;
499fae548d3Szrj }
500fae548d3Szrj 
501fae548d3Szrj static char *
bfd_plugin_core_file_failing_command(bfd * abfd ATTRIBUTE_UNUSED)502fae548d3Szrj bfd_plugin_core_file_failing_command (bfd *abfd ATTRIBUTE_UNUSED)
503fae548d3Szrj {
504fae548d3Szrj   BFD_ASSERT (0);
505fae548d3Szrj   return NULL;
506fae548d3Szrj }
507fae548d3Szrj 
508fae548d3Szrj static int
bfd_plugin_core_file_failing_signal(bfd * abfd ATTRIBUTE_UNUSED)509fae548d3Szrj bfd_plugin_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
510fae548d3Szrj {
511fae548d3Szrj   BFD_ASSERT (0);
512fae548d3Szrj   return 0;
513fae548d3Szrj }
514fae548d3Szrj 
515fae548d3Szrj static int
bfd_plugin_core_file_pid(bfd * abfd ATTRIBUTE_UNUSED)516fae548d3Szrj bfd_plugin_core_file_pid (bfd *abfd ATTRIBUTE_UNUSED)
517fae548d3Szrj {
518fae548d3Szrj   BFD_ASSERT (0);
519fae548d3Szrj   return 0;
520fae548d3Szrj }
521fae548d3Szrj 
522fae548d3Szrj static long
bfd_plugin_get_symtab_upper_bound(bfd * abfd)523fae548d3Szrj bfd_plugin_get_symtab_upper_bound (bfd *abfd)
524fae548d3Szrj {
525fae548d3Szrj   struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
526fae548d3Szrj   long nsyms = plugin_data->nsyms;
527fae548d3Szrj 
528fae548d3Szrj   BFD_ASSERT (nsyms >= 0);
529fae548d3Szrj 
530fae548d3Szrj   return ((nsyms + 1) * sizeof (asymbol *));
531fae548d3Szrj }
532fae548d3Szrj 
533fae548d3Szrj static flagword
convert_flags(const struct ld_plugin_symbol * sym)534fae548d3Szrj convert_flags (const struct ld_plugin_symbol *sym)
535fae548d3Szrj {
536fae548d3Szrj  switch (sym->def)
537fae548d3Szrj    {
538fae548d3Szrj    case LDPK_DEF:
539fae548d3Szrj    case LDPK_COMMON:
540fae548d3Szrj    case LDPK_UNDEF:
541fae548d3Szrj      return BSF_GLOBAL;
542fae548d3Szrj 
543fae548d3Szrj    case LDPK_WEAKUNDEF:
544fae548d3Szrj    case LDPK_WEAKDEF:
545fae548d3Szrj      return BSF_GLOBAL | BSF_WEAK;
546fae548d3Szrj 
547fae548d3Szrj    default:
548fae548d3Szrj      BFD_ASSERT (0);
549fae548d3Szrj      return 0;
550fae548d3Szrj    }
551fae548d3Szrj }
552fae548d3Szrj 
553fae548d3Szrj static long
bfd_plugin_canonicalize_symtab(bfd * abfd,asymbol ** alocation)554fae548d3Szrj bfd_plugin_canonicalize_symtab (bfd *abfd,
555fae548d3Szrj 				asymbol **alocation)
556fae548d3Szrj {
557fae548d3Szrj   struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
558fae548d3Szrj   long nsyms = plugin_data->nsyms;
559fae548d3Szrj   const struct ld_plugin_symbol *syms = plugin_data->syms;
560fae548d3Szrj   static asection fake_section
561fae548d3Szrj     = BFD_FAKE_SECTION (fake_section, NULL, "plug", 0,
562fae548d3Szrj 			SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS);
563fae548d3Szrj   static asection fake_common_section
564fae548d3Szrj     = BFD_FAKE_SECTION (fake_common_section, NULL, "plug", 0, SEC_IS_COMMON);
565fae548d3Szrj   int i;
566fae548d3Szrj 
567fae548d3Szrj   for (i = 0; i < nsyms; i++)
568fae548d3Szrj     {
569fae548d3Szrj       asymbol *s = bfd_alloc (abfd, sizeof (asymbol));
570fae548d3Szrj 
571fae548d3Szrj       BFD_ASSERT (s);
572fae548d3Szrj       alocation[i] = s;
573fae548d3Szrj 
574fae548d3Szrj       s->the_bfd = abfd;
575fae548d3Szrj       s->name = syms[i].name;
576fae548d3Szrj       s->value = 0;
577fae548d3Szrj       s->flags = convert_flags (&syms[i]);
578fae548d3Szrj       switch (syms[i].def)
579fae548d3Szrj 	{
580fae548d3Szrj 	case LDPK_COMMON:
581fae548d3Szrj 	  s->section = &fake_common_section;
582fae548d3Szrj 	  break;
583fae548d3Szrj 	case LDPK_UNDEF:
584fae548d3Szrj 	case LDPK_WEAKUNDEF:
585fae548d3Szrj 	  s->section = bfd_und_section_ptr;
586fae548d3Szrj 	  break;
587fae548d3Szrj 	case LDPK_DEF:
588fae548d3Szrj 	case LDPK_WEAKDEF:
589fae548d3Szrj 	  s->section = &fake_section;
590fae548d3Szrj 	  break;
591fae548d3Szrj 	default:
592fae548d3Szrj 	  BFD_ASSERT (0);
593fae548d3Szrj 	}
594fae548d3Szrj 
595fae548d3Szrj       s->udata.p = (void *) &syms[i];
596fae548d3Szrj     }
597fae548d3Szrj 
598fae548d3Szrj   return nsyms;
599fae548d3Szrj }
600fae548d3Szrj 
601fae548d3Szrj static void
bfd_plugin_print_symbol(bfd * abfd ATTRIBUTE_UNUSED,PTR afile ATTRIBUTE_UNUSED,asymbol * symbol ATTRIBUTE_UNUSED,bfd_print_symbol_type how ATTRIBUTE_UNUSED)602fae548d3Szrj bfd_plugin_print_symbol (bfd *abfd ATTRIBUTE_UNUSED,
603fae548d3Szrj 			 PTR afile ATTRIBUTE_UNUSED,
604fae548d3Szrj 			 asymbol *symbol ATTRIBUTE_UNUSED,
605fae548d3Szrj 			 bfd_print_symbol_type how ATTRIBUTE_UNUSED)
606fae548d3Szrj {
607fae548d3Szrj   BFD_ASSERT (0);
608fae548d3Szrj }
609fae548d3Szrj 
610fae548d3Szrj static void
bfd_plugin_get_symbol_info(bfd * abfd ATTRIBUTE_UNUSED,asymbol * symbol,symbol_info * ret)611fae548d3Szrj bfd_plugin_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
612fae548d3Szrj 			    asymbol *symbol,
613fae548d3Szrj 			    symbol_info *ret)
614fae548d3Szrj {
615fae548d3Szrj   bfd_symbol_info (symbol, ret);
616fae548d3Szrj }
617fae548d3Szrj 
618fae548d3Szrj /* Make an empty symbol. */
619fae548d3Szrj 
620fae548d3Szrj static asymbol *
bfd_plugin_make_empty_symbol(bfd * abfd)621fae548d3Szrj bfd_plugin_make_empty_symbol (bfd *abfd)
622fae548d3Szrj {
623fae548d3Szrj   asymbol *new_symbol = bfd_zalloc (abfd, sizeof (asymbol));
624fae548d3Szrj   if (new_symbol == NULL)
625fae548d3Szrj     return new_symbol;
626fae548d3Szrj   new_symbol->the_bfd = abfd;
627fae548d3Szrj   return new_symbol;
628fae548d3Szrj }
629fae548d3Szrj 
630fae548d3Szrj static int
bfd_plugin_sizeof_headers(bfd * a ATTRIBUTE_UNUSED,struct bfd_link_info * info ATTRIBUTE_UNUSED)631fae548d3Szrj bfd_plugin_sizeof_headers (bfd *a ATTRIBUTE_UNUSED,
632fae548d3Szrj 			   struct bfd_link_info *info ATTRIBUTE_UNUSED)
633fae548d3Szrj {
634fae548d3Szrj   BFD_ASSERT (0);
635fae548d3Szrj   return 0;
636fae548d3Szrj }
637fae548d3Szrj 
638fae548d3Szrj const bfd_target plugin_vec =
639fae548d3Szrj {
640fae548d3Szrj   "plugin",			/* Name.  */
641fae548d3Szrj   bfd_target_unknown_flavour,
642fae548d3Szrj   BFD_ENDIAN_LITTLE,		/* Target byte order.  */
643fae548d3Szrj   BFD_ENDIAN_LITTLE,		/* Target headers byte order.  */
644fae548d3Szrj   (HAS_RELOC | EXEC_P |		/* Object flags.  */
645fae548d3Szrj    HAS_LINENO | HAS_DEBUG |
646fae548d3Szrj    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
647fae548d3Szrj   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
648fae548d3Szrj    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
649fae548d3Szrj   0,				/* symbol_leading_char.  */
650fae548d3Szrj   '/',				/* ar_pad_char.  */
651fae548d3Szrj   15,				/* ar_max_namelen.  */
652fae548d3Szrj   255,				/* match priority.  */
653fae548d3Szrj 
654fae548d3Szrj   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
655fae548d3Szrj   bfd_getl32, bfd_getl_signed_32, bfd_putl32,
656fae548d3Szrj   bfd_getl16, bfd_getl_signed_16, bfd_putl16,	/* data */
657fae548d3Szrj   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
658fae548d3Szrj   bfd_getl32, bfd_getl_signed_32, bfd_putl32,
659fae548d3Szrj   bfd_getl16, bfd_getl_signed_16, bfd_putl16,	/* hdrs */
660fae548d3Szrj 
661fae548d3Szrj   {				/* bfd_check_format.  */
662fae548d3Szrj     _bfd_dummy_target,
663fae548d3Szrj     bfd_plugin_object_p,
664fae548d3Szrj     bfd_generic_archive_p,
665fae548d3Szrj     _bfd_dummy_target
666fae548d3Szrj   },
667fae548d3Szrj   {				/* bfd_set_format.  */
668fae548d3Szrj     _bfd_bool_bfd_false_error,
669fae548d3Szrj     _bfd_bool_bfd_false_error,
670fae548d3Szrj     _bfd_generic_mkarchive,
671fae548d3Szrj     _bfd_bool_bfd_false_error,
672fae548d3Szrj   },
673fae548d3Szrj   {				/* bfd_write_contents.  */
674fae548d3Szrj     _bfd_bool_bfd_false_error,
675fae548d3Szrj     _bfd_bool_bfd_false_error,
676fae548d3Szrj     _bfd_write_archive_contents,
677fae548d3Szrj     _bfd_bool_bfd_false_error,
678fae548d3Szrj   },
679fae548d3Szrj 
680fae548d3Szrj   BFD_JUMP_TABLE_GENERIC (bfd_plugin),
681fae548d3Szrj   BFD_JUMP_TABLE_COPY (bfd_plugin),
682fae548d3Szrj   BFD_JUMP_TABLE_CORE (bfd_plugin),
683fae548d3Szrj #ifdef USE_64_BIT_ARCHIVE
684fae548d3Szrj   BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_64_bit),
685fae548d3Szrj #else
686fae548d3Szrj   BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
687fae548d3Szrj #endif
688fae548d3Szrj   BFD_JUMP_TABLE_SYMBOLS (bfd_plugin),
689fae548d3Szrj   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
690fae548d3Szrj   BFD_JUMP_TABLE_WRITE (bfd_plugin),
691fae548d3Szrj   BFD_JUMP_TABLE_LINK (bfd_plugin),
692fae548d3Szrj   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
693fae548d3Szrj 
694fae548d3Szrj   NULL,
695fae548d3Szrj 
696fae548d3Szrj   NULL				/* backend_data.  */
697fae548d3Szrj };
698fae548d3Szrj #endif /* BFD_SUPPORTS_PLUGIN */
699