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