xref: /dflybsd-src/contrib/binutils-2.27/ld/plugin.c (revision e656dc90e3d65d744d534af2f5ea88cf8101ebcf)
1*a9fa9459Szrj /* Plugin control for the GNU linker.
2*a9fa9459Szrj    Copyright (C) 2010-2016 Free Software Foundation, Inc.
3*a9fa9459Szrj 
4*a9fa9459Szrj    This file is part of the GNU Binutils.
5*a9fa9459Szrj 
6*a9fa9459Szrj    This program is free software; you can redistribute it and/or modify
7*a9fa9459Szrj    it under the terms of the GNU General Public License as published by
8*a9fa9459Szrj    the Free Software Foundation; either version 3 of the License, or
9*a9fa9459Szrj    (at your option) any later version.
10*a9fa9459Szrj 
11*a9fa9459Szrj    This program is distributed in the hope that it will be useful,
12*a9fa9459Szrj    but WITHOUT ANY WARRANTY; without even the implied warranty of
13*a9fa9459Szrj    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*a9fa9459Szrj    GNU General Public License for more details.
15*a9fa9459Szrj 
16*a9fa9459Szrj    You should have received a copy of the GNU General Public License
17*a9fa9459Szrj    along with this program; if not, write to the Free Software
18*a9fa9459Szrj    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19*a9fa9459Szrj    MA 02110-1301, USA.  */
20*a9fa9459Szrj 
21*a9fa9459Szrj #include "sysdep.h"
22*a9fa9459Szrj #include "libiberty.h"
23*a9fa9459Szrj #include "bfd.h"
24*a9fa9459Szrj #include "libbfd.h"
25*a9fa9459Szrj #include "bfdlink.h"
26*a9fa9459Szrj #include "bfdver.h"
27*a9fa9459Szrj #include "ld.h"
28*a9fa9459Szrj #include "ldmain.h"
29*a9fa9459Szrj #include "ldmisc.h"
30*a9fa9459Szrj #include "ldexp.h"
31*a9fa9459Szrj #include "ldlang.h"
32*a9fa9459Szrj #include "ldfile.h"
33*a9fa9459Szrj #include "../bfd/plugin.h"
34*a9fa9459Szrj #include "plugin.h"
35*a9fa9459Szrj #include "plugin-api.h"
36*a9fa9459Szrj #include "elf-bfd.h"
37*a9fa9459Szrj #if HAVE_MMAP
38*a9fa9459Szrj # include <sys/mman.h>
39*a9fa9459Szrj # ifndef MAP_FAILED
40*a9fa9459Szrj #  define MAP_FAILED ((void *) -1)
41*a9fa9459Szrj # endif
42*a9fa9459Szrj # ifndef PROT_READ
43*a9fa9459Szrj #  define PROT_READ 0
44*a9fa9459Szrj # endif
45*a9fa9459Szrj # ifndef MAP_PRIVATE
46*a9fa9459Szrj #  define MAP_PRIVATE 0
47*a9fa9459Szrj # endif
48*a9fa9459Szrj #endif
49*a9fa9459Szrj #include <errno.h>
50*a9fa9459Szrj #if !(defined(errno) || defined(_MSC_VER) && defined(_INC_ERRNO))
51*a9fa9459Szrj extern int errno;
52*a9fa9459Szrj #endif
53*a9fa9459Szrj #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
54*a9fa9459Szrj #include <windows.h>
55*a9fa9459Szrj #endif
56*a9fa9459Szrj 
57*a9fa9459Szrj /* Report plugin symbols.  */
58*a9fa9459Szrj bfd_boolean report_plugin_symbols;
59*a9fa9459Szrj 
60*a9fa9459Szrj /* The suffix to append to the name of the real (claimed) object file
61*a9fa9459Szrj    when generating a dummy BFD to hold the IR symbols sent from the
62*a9fa9459Szrj    plugin.  For cosmetic use only; appears in maps, crefs etc.  */
63*a9fa9459Szrj #define IRONLY_SUFFIX " (symbol from plugin)"
64*a9fa9459Szrj 
65*a9fa9459Szrj /* Stores a single argument passed to a plugin.  */
66*a9fa9459Szrj typedef struct plugin_arg
67*a9fa9459Szrj {
68*a9fa9459Szrj   struct plugin_arg *next;
69*a9fa9459Szrj   const char *arg;
70*a9fa9459Szrj } plugin_arg_t;
71*a9fa9459Szrj 
72*a9fa9459Szrj /* Holds all details of a single plugin.  */
73*a9fa9459Szrj typedef struct plugin
74*a9fa9459Szrj {
75*a9fa9459Szrj   /* Next on the list of plugins, or NULL at end of chain.  */
76*a9fa9459Szrj   struct plugin *next;
77*a9fa9459Szrj   /* The argument string given to --plugin.  */
78*a9fa9459Szrj   const char *name;
79*a9fa9459Szrj   /* The shared library handle returned by dlopen.  */
80*a9fa9459Szrj   void *dlhandle;
81*a9fa9459Szrj   /* The list of argument string given to --plugin-opt.  */
82*a9fa9459Szrj   plugin_arg_t *args;
83*a9fa9459Szrj   /* Number of args in the list, for convenience.  */
84*a9fa9459Szrj   size_t n_args;
85*a9fa9459Szrj   /* The plugin's event handlers.  */
86*a9fa9459Szrj   ld_plugin_claim_file_handler claim_file_handler;
87*a9fa9459Szrj   ld_plugin_all_symbols_read_handler all_symbols_read_handler;
88*a9fa9459Szrj   ld_plugin_cleanup_handler cleanup_handler;
89*a9fa9459Szrj   /* TRUE if the cleanup handlers have been called.  */
90*a9fa9459Szrj   bfd_boolean cleanup_done;
91*a9fa9459Szrj } plugin_t;
92*a9fa9459Szrj 
93*a9fa9459Szrj typedef struct view_buffer
94*a9fa9459Szrj {
95*a9fa9459Szrj   char *addr;
96*a9fa9459Szrj   size_t filesize;
97*a9fa9459Szrj   off_t offset;
98*a9fa9459Szrj } view_buffer_t;
99*a9fa9459Szrj 
100*a9fa9459Szrj /* The internal version of struct ld_plugin_input_file with a BFD
101*a9fa9459Szrj    pointer.  */
102*a9fa9459Szrj typedef struct plugin_input_file
103*a9fa9459Szrj {
104*a9fa9459Szrj   bfd *abfd;
105*a9fa9459Szrj   view_buffer_t view_buffer;
106*a9fa9459Szrj   char *name;
107*a9fa9459Szrj   int fd;
108*a9fa9459Szrj   bfd_boolean use_mmap;
109*a9fa9459Szrj   off_t offset;
110*a9fa9459Szrj   off_t filesize;
111*a9fa9459Szrj } plugin_input_file_t;
112*a9fa9459Szrj 
113*a9fa9459Szrj /* The master list of all plugins.  */
114*a9fa9459Szrj static plugin_t *plugins_list = NULL;
115*a9fa9459Szrj 
116*a9fa9459Szrj /* We keep a tail pointer for easy linking on the end.  */
117*a9fa9459Szrj static plugin_t **plugins_tail_chain_ptr = &plugins_list;
118*a9fa9459Szrj 
119*a9fa9459Szrj /* The last plugin added to the list, for receiving args.  */
120*a9fa9459Szrj static plugin_t *last_plugin = NULL;
121*a9fa9459Szrj 
122*a9fa9459Szrj /* The tail of the arg chain of the last plugin added to the list.  */
123*a9fa9459Szrj static plugin_arg_t **last_plugin_args_tail_chain_ptr = NULL;
124*a9fa9459Szrj 
125*a9fa9459Szrj /* The plugin which is currently having a callback executed.  */
126*a9fa9459Szrj static plugin_t *called_plugin = NULL;
127*a9fa9459Szrj 
128*a9fa9459Szrj /* Last plugin to cause an error, if any.  */
129*a9fa9459Szrj static const char *error_plugin = NULL;
130*a9fa9459Szrj 
131*a9fa9459Szrj /* State of linker "notice" interface before we poked at it.  */
132*a9fa9459Szrj static bfd_boolean orig_notice_all;
133*a9fa9459Szrj 
134*a9fa9459Szrj /* Original linker callbacks, and the plugin version.  */
135*a9fa9459Szrj static const struct bfd_link_callbacks *orig_callbacks;
136*a9fa9459Szrj static struct bfd_link_callbacks plugin_callbacks;
137*a9fa9459Szrj 
138*a9fa9459Szrj /* Set at all symbols read time, to avoid recursively offering the plugin
139*a9fa9459Szrj    its own newly-added input files and libs to claim.  */
140*a9fa9459Szrj bfd_boolean no_more_claiming = FALSE;
141*a9fa9459Szrj 
142*a9fa9459Szrj #if HAVE_MMAP && HAVE_GETPAGESIZE
143*a9fa9459Szrj /* Page size used by mmap.  */
144*a9fa9459Szrj static off_t plugin_pagesize;
145*a9fa9459Szrj #endif
146*a9fa9459Szrj 
147*a9fa9459Szrj /* List of tags to set in the constant leading part of the tv array. */
148*a9fa9459Szrj static const enum ld_plugin_tag tv_header_tags[] =
149*a9fa9459Szrj {
150*a9fa9459Szrj   LDPT_MESSAGE,
151*a9fa9459Szrj   LDPT_API_VERSION,
152*a9fa9459Szrj   LDPT_GNU_LD_VERSION,
153*a9fa9459Szrj   LDPT_LINKER_OUTPUT,
154*a9fa9459Szrj   LDPT_OUTPUT_NAME,
155*a9fa9459Szrj   LDPT_REGISTER_CLAIM_FILE_HOOK,
156*a9fa9459Szrj   LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK,
157*a9fa9459Szrj   LDPT_REGISTER_CLEANUP_HOOK,
158*a9fa9459Szrj   LDPT_ADD_SYMBOLS,
159*a9fa9459Szrj   LDPT_GET_INPUT_FILE,
160*a9fa9459Szrj   LDPT_GET_VIEW,
161*a9fa9459Szrj   LDPT_RELEASE_INPUT_FILE,
162*a9fa9459Szrj   LDPT_GET_SYMBOLS,
163*a9fa9459Szrj   LDPT_GET_SYMBOLS_V2,
164*a9fa9459Szrj   LDPT_ADD_INPUT_FILE,
165*a9fa9459Szrj   LDPT_ADD_INPUT_LIBRARY,
166*a9fa9459Szrj   LDPT_SET_EXTRA_LIBRARY_PATH
167*a9fa9459Szrj };
168*a9fa9459Szrj 
169*a9fa9459Szrj /* How many entries in the constant leading part of the tv array.  */
170*a9fa9459Szrj static const size_t tv_header_size = ARRAY_SIZE (tv_header_tags);
171*a9fa9459Szrj 
172*a9fa9459Szrj /* Forward references.  */
173*a9fa9459Szrj static bfd_boolean plugin_notice (struct bfd_link_info *,
174*a9fa9459Szrj 				  struct bfd_link_hash_entry *,
175*a9fa9459Szrj 				  struct bfd_link_hash_entry *,
176*a9fa9459Szrj 				  bfd *, asection *, bfd_vma, flagword);
177*a9fa9459Szrj 
178*a9fa9459Szrj static const bfd_target * plugin_object_p (bfd *);
179*a9fa9459Szrj 
180*a9fa9459Szrj #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
181*a9fa9459Szrj 
182*a9fa9459Szrj #define RTLD_NOW 0	/* Dummy value.  */
183*a9fa9459Szrj 
184*a9fa9459Szrj static void *
dlopen(const char * file,int mode ATTRIBUTE_UNUSED)185*a9fa9459Szrj dlopen (const char *file, int mode ATTRIBUTE_UNUSED)
186*a9fa9459Szrj {
187*a9fa9459Szrj   return LoadLibrary (file);
188*a9fa9459Szrj }
189*a9fa9459Szrj 
190*a9fa9459Szrj static void *
dlsym(void * handle,const char * name)191*a9fa9459Szrj dlsym (void *handle, const char *name)
192*a9fa9459Szrj {
193*a9fa9459Szrj   return GetProcAddress (handle, name);
194*a9fa9459Szrj }
195*a9fa9459Szrj 
196*a9fa9459Szrj static int
dlclose(void * handle)197*a9fa9459Szrj dlclose (void *handle)
198*a9fa9459Szrj {
199*a9fa9459Szrj   FreeLibrary (handle);
200*a9fa9459Szrj   return 0;
201*a9fa9459Szrj }
202*a9fa9459Szrj 
203*a9fa9459Szrj #endif /* !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)  */
204*a9fa9459Szrj 
205*a9fa9459Szrj #ifndef HAVE_DLFCN_H
206*a9fa9459Szrj static const char *
dlerror(void)207*a9fa9459Szrj dlerror (void)
208*a9fa9459Szrj {
209*a9fa9459Szrj   return "";
210*a9fa9459Szrj }
211*a9fa9459Szrj #endif
212*a9fa9459Szrj 
213*a9fa9459Szrj /* Helper function for exiting with error status.  */
214*a9fa9459Szrj static int
set_plugin_error(const char * plugin)215*a9fa9459Szrj set_plugin_error (const char *plugin)
216*a9fa9459Szrj {
217*a9fa9459Szrj   error_plugin = plugin;
218*a9fa9459Szrj   return -1;
219*a9fa9459Szrj }
220*a9fa9459Szrj 
221*a9fa9459Szrj /* Test if an error occurred.  */
222*a9fa9459Szrj static bfd_boolean
plugin_error_p(void)223*a9fa9459Szrj plugin_error_p (void)
224*a9fa9459Szrj {
225*a9fa9459Szrj   return error_plugin != NULL;
226*a9fa9459Szrj }
227*a9fa9459Szrj 
228*a9fa9459Szrj /* Return name of plugin which caused an error if any.  */
229*a9fa9459Szrj const char *
plugin_error_plugin(void)230*a9fa9459Szrj plugin_error_plugin (void)
231*a9fa9459Szrj {
232*a9fa9459Szrj   return error_plugin ? error_plugin : _("<no plugin>");
233*a9fa9459Szrj }
234*a9fa9459Szrj 
235*a9fa9459Szrj /* Handle -plugin arg: find and load plugin, or return error.  */
236*a9fa9459Szrj void
plugin_opt_plugin(const char * plugin)237*a9fa9459Szrj plugin_opt_plugin (const char *plugin)
238*a9fa9459Szrj {
239*a9fa9459Szrj   plugin_t *newplug;
240*a9fa9459Szrj 
241*a9fa9459Szrj   newplug = xmalloc (sizeof *newplug);
242*a9fa9459Szrj   memset (newplug, 0, sizeof *newplug);
243*a9fa9459Szrj   newplug->name = plugin;
244*a9fa9459Szrj   newplug->dlhandle = dlopen (plugin, RTLD_NOW);
245*a9fa9459Szrj   if (!newplug->dlhandle)
246*a9fa9459Szrj     einfo (_("%P%F: %s: error loading plugin: %s\n"), plugin, dlerror ());
247*a9fa9459Szrj 
248*a9fa9459Szrj   /* Chain on end, so when we run list it is in command-line order.  */
249*a9fa9459Szrj   *plugins_tail_chain_ptr = newplug;
250*a9fa9459Szrj   plugins_tail_chain_ptr = &newplug->next;
251*a9fa9459Szrj 
252*a9fa9459Szrj   /* Record it as current plugin for receiving args.  */
253*a9fa9459Szrj   last_plugin = newplug;
254*a9fa9459Szrj   last_plugin_args_tail_chain_ptr = &newplug->args;
255*a9fa9459Szrj }
256*a9fa9459Szrj 
257*a9fa9459Szrj /* Accumulate option arguments for last-loaded plugin, or return
258*a9fa9459Szrj    error if none.  */
259*a9fa9459Szrj int
plugin_opt_plugin_arg(const char * arg)260*a9fa9459Szrj plugin_opt_plugin_arg (const char *arg)
261*a9fa9459Szrj {
262*a9fa9459Szrj   plugin_arg_t *newarg;
263*a9fa9459Szrj 
264*a9fa9459Szrj   if (!last_plugin)
265*a9fa9459Szrj     return set_plugin_error (_("<no plugin>"));
266*a9fa9459Szrj 
267*a9fa9459Szrj   /* Ignore -pass-through= from GCC driver.  */
268*a9fa9459Szrj   if (*arg == '-')
269*a9fa9459Szrj     {
270*a9fa9459Szrj       const char *p = arg + 1;
271*a9fa9459Szrj 
272*a9fa9459Szrj       if (*p == '-')
273*a9fa9459Szrj 	++p;
274*a9fa9459Szrj       if (strncmp (p, "pass-through=", 13) == 0)
275*a9fa9459Szrj 	return 0;
276*a9fa9459Szrj     }
277*a9fa9459Szrj 
278*a9fa9459Szrj   newarg = xmalloc (sizeof *newarg);
279*a9fa9459Szrj   newarg->arg = arg;
280*a9fa9459Szrj   newarg->next = NULL;
281*a9fa9459Szrj 
282*a9fa9459Szrj   /* Chain on end to preserve command-line order.  */
283*a9fa9459Szrj   *last_plugin_args_tail_chain_ptr = newarg;
284*a9fa9459Szrj   last_plugin_args_tail_chain_ptr = &newarg->next;
285*a9fa9459Szrj   last_plugin->n_args++;
286*a9fa9459Szrj   return 0;
287*a9fa9459Szrj }
288*a9fa9459Szrj 
289*a9fa9459Szrj /* Generate a dummy BFD to represent an IR file, for any callers of
290*a9fa9459Szrj    plugin_call_claim_file to use as the handle in the ld_plugin_input_file
291*a9fa9459Szrj    struct that they build to pass in.  The BFD is initially writable, so
292*a9fa9459Szrj    that symbols can be added to it; it must be made readable after the
293*a9fa9459Szrj    add_symbols hook has been called so that it can be read when linking.  */
294*a9fa9459Szrj static bfd *
plugin_get_ir_dummy_bfd(const char * name,bfd * srctemplate)295*a9fa9459Szrj plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate)
296*a9fa9459Szrj {
297*a9fa9459Szrj   bfd *abfd;
298*a9fa9459Szrj   bfd_boolean bfd_plugin_target;
299*a9fa9459Szrj 
300*a9fa9459Szrj   bfd_use_reserved_id = 1;
301*a9fa9459Szrj   bfd_plugin_target = bfd_plugin_target_p (srctemplate->xvec);
302*a9fa9459Szrj   abfd = bfd_create (concat (name, IRONLY_SUFFIX, (const char *) NULL),
303*a9fa9459Szrj 		     bfd_plugin_target ? link_info.output_bfd : srctemplate);
304*a9fa9459Szrj   if (abfd != NULL)
305*a9fa9459Szrj     {
306*a9fa9459Szrj       abfd->flags |= BFD_LINKER_CREATED | BFD_PLUGIN;
307*a9fa9459Szrj       if (!bfd_make_writable (abfd))
308*a9fa9459Szrj 	goto report_error;
309*a9fa9459Szrj       if (!bfd_plugin_target)
310*a9fa9459Szrj 	{
311*a9fa9459Szrj 	  bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate));
312*a9fa9459Szrj 	  bfd_set_gp_size (abfd, bfd_get_gp_size (srctemplate));
313*a9fa9459Szrj 	  if (!bfd_copy_private_bfd_data (srctemplate, abfd))
314*a9fa9459Szrj 	    goto report_error;
315*a9fa9459Szrj 	}
316*a9fa9459Szrj 	{
317*a9fa9459Szrj 	  flagword flags;
318*a9fa9459Szrj 
319*a9fa9459Szrj 	  /* Create section to own the symbols.  */
320*a9fa9459Szrj 	  flags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
321*a9fa9459Szrj 		   | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE);
322*a9fa9459Szrj 	  if (bfd_make_section_anyway_with_flags (abfd, ".text", flags))
323*a9fa9459Szrj 	    return abfd;
324*a9fa9459Szrj 	}
325*a9fa9459Szrj     }
326*a9fa9459Szrj report_error:
327*a9fa9459Szrj   einfo (_("could not create dummy IR bfd: %F%E\n"));
328*a9fa9459Szrj   return NULL;
329*a9fa9459Szrj }
330*a9fa9459Szrj 
331*a9fa9459Szrj /* Check if the BFD passed in is an IR dummy object file.  */
332*a9fa9459Szrj static inline bfd_boolean
is_ir_dummy_bfd(const bfd * abfd)333*a9fa9459Szrj is_ir_dummy_bfd (const bfd *abfd)
334*a9fa9459Szrj {
335*a9fa9459Szrj   /* ABFD can sometimes legitimately be NULL, e.g. when called from one
336*a9fa9459Szrj      of the linker callbacks for a symbol in the *ABS* or *UND* sections.  */
337*a9fa9459Szrj   return abfd != NULL && (abfd->flags & BFD_PLUGIN) != 0;
338*a9fa9459Szrj }
339*a9fa9459Szrj 
340*a9fa9459Szrj /* Helpers to convert between BFD and GOLD symbol formats.  */
341*a9fa9459Szrj static enum ld_plugin_status
asymbol_from_plugin_symbol(bfd * abfd,asymbol * asym,const struct ld_plugin_symbol * ldsym)342*a9fa9459Szrj asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym,
343*a9fa9459Szrj 			    const struct ld_plugin_symbol *ldsym)
344*a9fa9459Szrj {
345*a9fa9459Szrj   flagword flags = BSF_NO_FLAGS;
346*a9fa9459Szrj   struct bfd_section *section;
347*a9fa9459Szrj 
348*a9fa9459Szrj   asym->the_bfd = abfd;
349*a9fa9459Szrj   asym->name = (ldsym->version
350*a9fa9459Szrj 		? concat (ldsym->name, "@", ldsym->version, (const char *) NULL)
351*a9fa9459Szrj 		: ldsym->name);
352*a9fa9459Szrj   asym->value = 0;
353*a9fa9459Szrj   switch (ldsym->def)
354*a9fa9459Szrj     {
355*a9fa9459Szrj     case LDPK_WEAKDEF:
356*a9fa9459Szrj       flags = BSF_WEAK;
357*a9fa9459Szrj       /* FALLTHRU */
358*a9fa9459Szrj     case LDPK_DEF:
359*a9fa9459Szrj       flags |= BSF_GLOBAL;
360*a9fa9459Szrj       if (ldsym->comdat_key)
361*a9fa9459Szrj 	{
362*a9fa9459Szrj 	  char *name = concat (".gnu.linkonce.t.", ldsym->comdat_key,
363*a9fa9459Szrj 			       (const char *) NULL);
364*a9fa9459Szrj 	  section = bfd_get_section_by_name (abfd, name);
365*a9fa9459Szrj 	  if (section != NULL)
366*a9fa9459Szrj 	    free (name);
367*a9fa9459Szrj 	  else
368*a9fa9459Szrj 	    {
369*a9fa9459Szrj 	      flagword sflags;
370*a9fa9459Szrj 
371*a9fa9459Szrj 	      sflags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
372*a9fa9459Szrj 			| SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE
373*a9fa9459Szrj 			| SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD);
374*a9fa9459Szrj 	      section = bfd_make_section_anyway_with_flags (abfd, name, sflags);
375*a9fa9459Szrj 	      if (section == NULL)
376*a9fa9459Szrj 		return LDPS_ERR;
377*a9fa9459Szrj 	    }
378*a9fa9459Szrj 	}
379*a9fa9459Szrj       else
380*a9fa9459Szrj 	section = bfd_get_section_by_name (abfd, ".text");
381*a9fa9459Szrj       break;
382*a9fa9459Szrj 
383*a9fa9459Szrj     case LDPK_WEAKUNDEF:
384*a9fa9459Szrj       flags = BSF_WEAK;
385*a9fa9459Szrj       /* FALLTHRU */
386*a9fa9459Szrj     case LDPK_UNDEF:
387*a9fa9459Szrj       section = bfd_und_section_ptr;
388*a9fa9459Szrj       break;
389*a9fa9459Szrj 
390*a9fa9459Szrj     case LDPK_COMMON:
391*a9fa9459Szrj       flags = BSF_GLOBAL;
392*a9fa9459Szrj       section = bfd_com_section_ptr;
393*a9fa9459Szrj       asym->value = ldsym->size;
394*a9fa9459Szrj       /* For ELF targets, set alignment of common symbol to 1.  */
395*a9fa9459Szrj       if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
396*a9fa9459Szrj 	{
397*a9fa9459Szrj 	  ((elf_symbol_type *) asym)->internal_elf_sym.st_shndx = SHN_COMMON;
398*a9fa9459Szrj 	  ((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1;
399*a9fa9459Szrj 	}
400*a9fa9459Szrj       break;
401*a9fa9459Szrj 
402*a9fa9459Szrj     default:
403*a9fa9459Szrj       return LDPS_ERR;
404*a9fa9459Szrj     }
405*a9fa9459Szrj   asym->flags = flags;
406*a9fa9459Szrj   asym->section = section;
407*a9fa9459Szrj 
408*a9fa9459Szrj   /* Visibility only applies on ELF targets.  */
409*a9fa9459Szrj   if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
410*a9fa9459Szrj     {
411*a9fa9459Szrj       elf_symbol_type *elfsym = elf_symbol_from (abfd, asym);
412*a9fa9459Szrj       unsigned char visibility;
413*a9fa9459Szrj 
414*a9fa9459Szrj       if (!elfsym)
415*a9fa9459Szrj 	einfo (_("%P%F: %s: non-ELF symbol in ELF BFD!\n"), asym->name);
416*a9fa9459Szrj       switch (ldsym->visibility)
417*a9fa9459Szrj 	{
418*a9fa9459Szrj 	default:
419*a9fa9459Szrj 	  einfo (_("%P%F: unknown ELF symbol visibility: %d!\n"),
420*a9fa9459Szrj 		 ldsym->visibility);
421*a9fa9459Szrj 	case LDPV_DEFAULT:
422*a9fa9459Szrj 	  visibility = STV_DEFAULT;
423*a9fa9459Szrj 	  break;
424*a9fa9459Szrj 	case LDPV_PROTECTED:
425*a9fa9459Szrj 	  visibility = STV_PROTECTED;
426*a9fa9459Szrj 	  break;
427*a9fa9459Szrj 	case LDPV_INTERNAL:
428*a9fa9459Szrj 	  visibility = STV_INTERNAL;
429*a9fa9459Szrj 	  break;
430*a9fa9459Szrj 	case LDPV_HIDDEN:
431*a9fa9459Szrj 	  visibility = STV_HIDDEN;
432*a9fa9459Szrj 	  break;
433*a9fa9459Szrj 	}
434*a9fa9459Szrj       elfsym->internal_elf_sym.st_other
435*a9fa9459Szrj 	= (visibility | (elfsym->internal_elf_sym.st_other
436*a9fa9459Szrj 			 & ~ELF_ST_VISIBILITY (-1)));
437*a9fa9459Szrj     }
438*a9fa9459Szrj 
439*a9fa9459Szrj   return LDPS_OK;
440*a9fa9459Szrj }
441*a9fa9459Szrj 
442*a9fa9459Szrj /* Register a claim-file handler.  */
443*a9fa9459Szrj static enum ld_plugin_status
register_claim_file(ld_plugin_claim_file_handler handler)444*a9fa9459Szrj register_claim_file (ld_plugin_claim_file_handler handler)
445*a9fa9459Szrj {
446*a9fa9459Szrj   ASSERT (called_plugin);
447*a9fa9459Szrj   called_plugin->claim_file_handler = handler;
448*a9fa9459Szrj   return LDPS_OK;
449*a9fa9459Szrj }
450*a9fa9459Szrj 
451*a9fa9459Szrj /* Register an all-symbols-read handler.  */
452*a9fa9459Szrj static enum ld_plugin_status
register_all_symbols_read(ld_plugin_all_symbols_read_handler handler)453*a9fa9459Szrj register_all_symbols_read (ld_plugin_all_symbols_read_handler handler)
454*a9fa9459Szrj {
455*a9fa9459Szrj   ASSERT (called_plugin);
456*a9fa9459Szrj   called_plugin->all_symbols_read_handler = handler;
457*a9fa9459Szrj   return LDPS_OK;
458*a9fa9459Szrj }
459*a9fa9459Szrj 
460*a9fa9459Szrj /* Register a cleanup handler.  */
461*a9fa9459Szrj static enum ld_plugin_status
register_cleanup(ld_plugin_cleanup_handler handler)462*a9fa9459Szrj register_cleanup (ld_plugin_cleanup_handler handler)
463*a9fa9459Szrj {
464*a9fa9459Szrj   ASSERT (called_plugin);
465*a9fa9459Szrj   called_plugin->cleanup_handler = handler;
466*a9fa9459Szrj   return LDPS_OK;
467*a9fa9459Szrj }
468*a9fa9459Szrj 
469*a9fa9459Szrj /* Add symbols from a plugin-claimed input file.  */
470*a9fa9459Szrj static enum ld_plugin_status
add_symbols(void * handle,int nsyms,const struct ld_plugin_symbol * syms)471*a9fa9459Szrj add_symbols (void *handle, int nsyms, const struct ld_plugin_symbol *syms)
472*a9fa9459Szrj {
473*a9fa9459Szrj   asymbol **symptrs;
474*a9fa9459Szrj   plugin_input_file_t *input = handle;
475*a9fa9459Szrj   bfd *abfd = input->abfd;
476*a9fa9459Szrj   int n;
477*a9fa9459Szrj 
478*a9fa9459Szrj   ASSERT (called_plugin);
479*a9fa9459Szrj   symptrs = xmalloc (nsyms * sizeof *symptrs);
480*a9fa9459Szrj   for (n = 0; n < nsyms; n++)
481*a9fa9459Szrj     {
482*a9fa9459Szrj       enum ld_plugin_status rv;
483*a9fa9459Szrj       asymbol *bfdsym;
484*a9fa9459Szrj 
485*a9fa9459Szrj       bfdsym = bfd_make_empty_symbol (abfd);
486*a9fa9459Szrj       symptrs[n] = bfdsym;
487*a9fa9459Szrj       rv = asymbol_from_plugin_symbol (abfd, bfdsym, syms + n);
488*a9fa9459Szrj       if (rv != LDPS_OK)
489*a9fa9459Szrj 	return rv;
490*a9fa9459Szrj     }
491*a9fa9459Szrj   bfd_set_symtab (abfd, symptrs, nsyms);
492*a9fa9459Szrj   return LDPS_OK;
493*a9fa9459Szrj }
494*a9fa9459Szrj 
495*a9fa9459Szrj /* Get the input file information with an open (possibly re-opened)
496*a9fa9459Szrj    file descriptor.  */
497*a9fa9459Szrj static enum ld_plugin_status
get_input_file(const void * handle,struct ld_plugin_input_file * file)498*a9fa9459Szrj get_input_file (const void *handle, struct ld_plugin_input_file *file)
499*a9fa9459Szrj {
500*a9fa9459Szrj   const plugin_input_file_t *input = handle;
501*a9fa9459Szrj 
502*a9fa9459Szrj   ASSERT (called_plugin);
503*a9fa9459Szrj 
504*a9fa9459Szrj   file->name = input->name;
505*a9fa9459Szrj   file->offset = input->offset;
506*a9fa9459Szrj   file->filesize = input->filesize;
507*a9fa9459Szrj   file->handle = (void *) handle;
508*a9fa9459Szrj 
509*a9fa9459Szrj   return LDPS_OK;
510*a9fa9459Szrj }
511*a9fa9459Szrj 
512*a9fa9459Szrj /* Get view of the input file.  */
513*a9fa9459Szrj static enum ld_plugin_status
get_view(const void * handle,const void ** viewp)514*a9fa9459Szrj get_view (const void *handle, const void **viewp)
515*a9fa9459Szrj {
516*a9fa9459Szrj   plugin_input_file_t *input = (plugin_input_file_t *) handle;
517*a9fa9459Szrj   char *buffer;
518*a9fa9459Szrj   size_t size = input->filesize;
519*a9fa9459Szrj   off_t offset = input->offset;
520*a9fa9459Szrj #if HAVE_MMAP && HAVE_GETPAGESIZE
521*a9fa9459Szrj   off_t bias;
522*a9fa9459Szrj #endif
523*a9fa9459Szrj 
524*a9fa9459Szrj   ASSERT (called_plugin);
525*a9fa9459Szrj 
526*a9fa9459Szrj   /* FIXME: einfo should support %lld.  */
527*a9fa9459Szrj   if ((off_t) size != input->filesize)
528*a9fa9459Szrj     einfo (_("%P%F: unsupported input file size: %s (%ld bytes)\n"),
529*a9fa9459Szrj 	   input->name, (long) input->filesize);
530*a9fa9459Szrj 
531*a9fa9459Szrj   /* Check the cached view buffer.  */
532*a9fa9459Szrj   if (input->view_buffer.addr != NULL
533*a9fa9459Szrj       && input->view_buffer.filesize == size
534*a9fa9459Szrj       && input->view_buffer.offset == offset)
535*a9fa9459Szrj     {
536*a9fa9459Szrj       *viewp = input->view_buffer.addr;
537*a9fa9459Szrj       return LDPS_OK;
538*a9fa9459Szrj     }
539*a9fa9459Szrj 
540*a9fa9459Szrj   input->view_buffer.filesize = size;
541*a9fa9459Szrj   input->view_buffer.offset = offset;
542*a9fa9459Szrj 
543*a9fa9459Szrj #if HAVE_MMAP
544*a9fa9459Szrj # if HAVE_GETPAGESIZE
545*a9fa9459Szrj   bias = offset % plugin_pagesize;
546*a9fa9459Szrj   offset -= bias;
547*a9fa9459Szrj   size += bias;
548*a9fa9459Szrj # endif
549*a9fa9459Szrj   buffer = mmap (NULL, size, PROT_READ, MAP_PRIVATE, input->fd, offset);
550*a9fa9459Szrj   if (buffer != MAP_FAILED)
551*a9fa9459Szrj     {
552*a9fa9459Szrj       input->use_mmap = TRUE;
553*a9fa9459Szrj # if HAVE_GETPAGESIZE
554*a9fa9459Szrj       buffer += bias;
555*a9fa9459Szrj # endif
556*a9fa9459Szrj     }
557*a9fa9459Szrj   else
558*a9fa9459Szrj #endif
559*a9fa9459Szrj     {
560*a9fa9459Szrj       char *p;
561*a9fa9459Szrj 
562*a9fa9459Szrj       input->use_mmap = FALSE;
563*a9fa9459Szrj 
564*a9fa9459Szrj       if (lseek (input->fd, offset, SEEK_SET) < 0)
565*a9fa9459Szrj 	return LDPS_ERR;
566*a9fa9459Szrj 
567*a9fa9459Szrj       buffer = bfd_alloc (input->abfd, size);
568*a9fa9459Szrj       if (buffer == NULL)
569*a9fa9459Szrj 	return LDPS_ERR;
570*a9fa9459Szrj 
571*a9fa9459Szrj       p = buffer;
572*a9fa9459Szrj       do
573*a9fa9459Szrj 	{
574*a9fa9459Szrj 	  ssize_t got = read (input->fd, p, size);
575*a9fa9459Szrj 	  if (got == 0)
576*a9fa9459Szrj 	    break;
577*a9fa9459Szrj 	  else if (got > 0)
578*a9fa9459Szrj 	    {
579*a9fa9459Szrj 	      p += got;
580*a9fa9459Szrj 	      size -= got;
581*a9fa9459Szrj 	    }
582*a9fa9459Szrj 	  else if (errno != EINTR)
583*a9fa9459Szrj 	    return LDPS_ERR;
584*a9fa9459Szrj 	}
585*a9fa9459Szrj       while (size > 0);
586*a9fa9459Szrj     }
587*a9fa9459Szrj 
588*a9fa9459Szrj   input->view_buffer.addr = buffer;
589*a9fa9459Szrj   *viewp = buffer;
590*a9fa9459Szrj 
591*a9fa9459Szrj   return LDPS_OK;
592*a9fa9459Szrj }
593*a9fa9459Szrj 
594*a9fa9459Szrj /* Release the input file.  */
595*a9fa9459Szrj static enum ld_plugin_status
release_input_file(const void * handle)596*a9fa9459Szrj release_input_file (const void *handle)
597*a9fa9459Szrj {
598*a9fa9459Szrj   plugin_input_file_t *input = (plugin_input_file_t *) handle;
599*a9fa9459Szrj   ASSERT (called_plugin);
600*a9fa9459Szrj   if (input->fd != -1)
601*a9fa9459Szrj     {
602*a9fa9459Szrj       close (input->fd);
603*a9fa9459Szrj       input->fd = -1;
604*a9fa9459Szrj     }
605*a9fa9459Szrj   return LDPS_OK;
606*a9fa9459Szrj }
607*a9fa9459Szrj 
608*a9fa9459Szrj /* Return TRUE if a defined symbol might be reachable from outside the
609*a9fa9459Szrj    universe of claimed objects.  */
610*a9fa9459Szrj static inline bfd_boolean
is_visible_from_outside(struct ld_plugin_symbol * lsym,struct bfd_link_hash_entry * blhe)611*a9fa9459Szrj is_visible_from_outside (struct ld_plugin_symbol *lsym,
612*a9fa9459Szrj 			 struct bfd_link_hash_entry *blhe)
613*a9fa9459Szrj {
614*a9fa9459Szrj   struct bfd_sym_chain *sym;
615*a9fa9459Szrj 
616*a9fa9459Szrj   if (bfd_link_relocatable (&link_info))
617*a9fa9459Szrj     return TRUE;
618*a9fa9459Szrj   if (link_info.export_dynamic || bfd_link_dll (&link_info))
619*a9fa9459Szrj     {
620*a9fa9459Szrj       /* Check if symbol is hidden by version script.  */
621*a9fa9459Szrj       if (bfd_hide_sym_by_version (link_info.version_info,
622*a9fa9459Szrj 				   blhe->root.string))
623*a9fa9459Szrj 	return FALSE;
624*a9fa9459Szrj       /* Only ELF symbols really have visibility.  */
625*a9fa9459Szrj       if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour)
626*a9fa9459Szrj 	{
627*a9fa9459Szrj 	  struct elf_link_hash_entry *el = (struct elf_link_hash_entry *)blhe;
628*a9fa9459Szrj 	  int vis = ELF_ST_VISIBILITY (el->other);
629*a9fa9459Szrj 	  return vis == STV_DEFAULT || vis == STV_PROTECTED;
630*a9fa9459Szrj 	}
631*a9fa9459Szrj       /* On non-ELF targets, we can safely make inferences by considering
632*a9fa9459Szrj 	 what visibility the plugin would have liked to apply when it first
633*a9fa9459Szrj 	 sent us the symbol.  During ELF symbol processing, visibility only
634*a9fa9459Szrj 	 ever becomes more restrictive, not less, when symbols are merged,
635*a9fa9459Szrj 	 so this is a conservative estimate; it may give false positives,
636*a9fa9459Szrj 	 declaring something visible from outside when it in fact would
637*a9fa9459Szrj 	 not have been, but this will only lead to missed optimisation
638*a9fa9459Szrj 	 opportunities during LTRANS at worst; it will not give false
639*a9fa9459Szrj 	 negatives, which can lead to the disastrous conclusion that the
640*a9fa9459Szrj 	 related symbol is IRONLY.  (See GCC PR46319 for an example.)  */
641*a9fa9459Szrj       return (lsym->visibility == LDPV_DEFAULT
642*a9fa9459Szrj 	      || lsym->visibility == LDPV_PROTECTED);
643*a9fa9459Szrj     }
644*a9fa9459Szrj 
645*a9fa9459Szrj   for (sym = &entry_symbol; sym != NULL; sym = sym->next)
646*a9fa9459Szrj     if (sym->name
647*a9fa9459Szrj 	&& strcmp (sym->name, blhe->root.string) == 0)
648*a9fa9459Szrj       return TRUE;
649*a9fa9459Szrj 
650*a9fa9459Szrj   return FALSE;
651*a9fa9459Szrj }
652*a9fa9459Szrj 
653*a9fa9459Szrj /* Get the symbol resolution info for a plugin-claimed input file.  */
654*a9fa9459Szrj static enum ld_plugin_status
get_symbols(const void * handle,int nsyms,struct ld_plugin_symbol * syms,int def_ironly_exp)655*a9fa9459Szrj get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms,
656*a9fa9459Szrj 	     int def_ironly_exp)
657*a9fa9459Szrj {
658*a9fa9459Szrj   const plugin_input_file_t *input = handle;
659*a9fa9459Szrj   const bfd *abfd = (const bfd *) input->abfd;
660*a9fa9459Szrj   int n;
661*a9fa9459Szrj 
662*a9fa9459Szrj   ASSERT (called_plugin);
663*a9fa9459Szrj   for (n = 0; n < nsyms; n++)
664*a9fa9459Szrj     {
665*a9fa9459Szrj       struct bfd_link_hash_entry *blhe;
666*a9fa9459Szrj       asection *owner_sec;
667*a9fa9459Szrj       int res;
668*a9fa9459Szrj 
669*a9fa9459Szrj       if (syms[n].def != LDPK_UNDEF)
670*a9fa9459Szrj 	blhe = bfd_link_hash_lookup (link_info.hash, syms[n].name,
671*a9fa9459Szrj 				     FALSE, FALSE, TRUE);
672*a9fa9459Szrj       else
673*a9fa9459Szrj 	blhe = bfd_wrapped_link_hash_lookup (link_info.output_bfd, &link_info,
674*a9fa9459Szrj 					     syms[n].name, FALSE, FALSE, TRUE);
675*a9fa9459Szrj       if (!blhe)
676*a9fa9459Szrj 	{
677*a9fa9459Szrj 	  /* The plugin is called to claim symbols in an archive element
678*a9fa9459Szrj 	     from plugin_object_p.  But those symbols aren't needed to
679*a9fa9459Szrj 	     create output.  They are defined and referenced only within
680*a9fa9459Szrj 	     IR.  */
681*a9fa9459Szrj 	  switch (syms[n].def)
682*a9fa9459Szrj 	    {
683*a9fa9459Szrj 	    default:
684*a9fa9459Szrj 	      abort ();
685*a9fa9459Szrj 	    case LDPK_UNDEF:
686*a9fa9459Szrj 	    case LDPK_WEAKUNDEF:
687*a9fa9459Szrj 	      res = LDPR_UNDEF;
688*a9fa9459Szrj 	      break;
689*a9fa9459Szrj 	    case LDPK_DEF:
690*a9fa9459Szrj 	    case LDPK_WEAKDEF:
691*a9fa9459Szrj 	    case LDPK_COMMON:
692*a9fa9459Szrj 	      res = LDPR_PREVAILING_DEF_IRONLY;
693*a9fa9459Szrj 	      break;
694*a9fa9459Szrj 	    }
695*a9fa9459Szrj 	  goto report_symbol;
696*a9fa9459Szrj 	}
697*a9fa9459Szrj 
698*a9fa9459Szrj       /* Determine resolution from blhe type and symbol's original type.  */
699*a9fa9459Szrj       if (blhe->type == bfd_link_hash_undefined
700*a9fa9459Szrj 	  || blhe->type == bfd_link_hash_undefweak)
701*a9fa9459Szrj 	{
702*a9fa9459Szrj 	  res = LDPR_UNDEF;
703*a9fa9459Szrj 	  goto report_symbol;
704*a9fa9459Szrj 	}
705*a9fa9459Szrj       if (blhe->type != bfd_link_hash_defined
706*a9fa9459Szrj 	  && blhe->type != bfd_link_hash_defweak
707*a9fa9459Szrj 	  && blhe->type != bfd_link_hash_common)
708*a9fa9459Szrj 	{
709*a9fa9459Szrj 	  /* We should not have a new, indirect or warning symbol here.  */
710*a9fa9459Szrj 	  einfo ("%P%F: %s: plugin symbol table corrupt (sym type %d)\n",
711*a9fa9459Szrj 		 called_plugin->name, blhe->type);
712*a9fa9459Szrj 	}
713*a9fa9459Szrj 
714*a9fa9459Szrj       /* Find out which section owns the symbol.  Since it's not undef,
715*a9fa9459Szrj 	 it must have an owner; if it's not a common symbol, both defs
716*a9fa9459Szrj 	 and weakdefs keep it in the same place. */
717*a9fa9459Szrj       owner_sec = (blhe->type == bfd_link_hash_common
718*a9fa9459Szrj 		   ? blhe->u.c.p->section
719*a9fa9459Szrj 		   : blhe->u.def.section);
720*a9fa9459Szrj 
721*a9fa9459Szrj 
722*a9fa9459Szrj       /* If it was originally undefined or common, then it has been
723*a9fa9459Szrj 	 resolved; determine how.  */
724*a9fa9459Szrj       if (syms[n].def == LDPK_UNDEF
725*a9fa9459Szrj 	  || syms[n].def == LDPK_WEAKUNDEF
726*a9fa9459Szrj 	  || syms[n].def == LDPK_COMMON)
727*a9fa9459Szrj 	{
728*a9fa9459Szrj 	  if (owner_sec->owner == link_info.output_bfd)
729*a9fa9459Szrj 	    res = LDPR_RESOLVED_EXEC;
730*a9fa9459Szrj 	  else if (owner_sec->owner == abfd)
731*a9fa9459Szrj 	    res = LDPR_PREVAILING_DEF_IRONLY;
732*a9fa9459Szrj 	  else if (is_ir_dummy_bfd (owner_sec->owner))
733*a9fa9459Szrj 	    res = LDPR_RESOLVED_IR;
734*a9fa9459Szrj 	  else if (owner_sec->owner != NULL
735*a9fa9459Szrj 		   && (owner_sec->owner->flags & DYNAMIC) != 0)
736*a9fa9459Szrj 	    res = LDPR_RESOLVED_DYN;
737*a9fa9459Szrj 	  else
738*a9fa9459Szrj 	    res = LDPR_RESOLVED_EXEC;
739*a9fa9459Szrj 	}
740*a9fa9459Szrj 
741*a9fa9459Szrj       /* Was originally def, or weakdef.  Does it prevail?  If the
742*a9fa9459Szrj 	 owner is the original dummy bfd that supplied it, then this
743*a9fa9459Szrj 	 is the definition that has prevailed.  */
744*a9fa9459Szrj       else if (owner_sec->owner == link_info.output_bfd)
745*a9fa9459Szrj 	res = LDPR_PREEMPTED_REG;
746*a9fa9459Szrj       else if (owner_sec->owner == abfd)
747*a9fa9459Szrj 	res = LDPR_PREVAILING_DEF_IRONLY;
748*a9fa9459Szrj 
749*a9fa9459Szrj       /* Was originally def, weakdef, or common, but has been pre-empted.  */
750*a9fa9459Szrj       else if (is_ir_dummy_bfd (owner_sec->owner))
751*a9fa9459Szrj 	res = LDPR_PREEMPTED_IR;
752*a9fa9459Szrj       else
753*a9fa9459Szrj 	res = LDPR_PREEMPTED_REG;
754*a9fa9459Szrj 
755*a9fa9459Szrj       if (res == LDPR_PREVAILING_DEF_IRONLY)
756*a9fa9459Szrj 	{
757*a9fa9459Szrj 	  /* We need to know if the sym is referenced from non-IR files.  Or
758*a9fa9459Szrj 	     even potentially-referenced, perhaps in a future final link if
759*a9fa9459Szrj 	     this is a partial one, perhaps dynamically at load-time if the
760*a9fa9459Szrj 	     symbol is externally visible.  */
761*a9fa9459Szrj 	  if (blhe->non_ir_ref)
762*a9fa9459Szrj 	    res = LDPR_PREVAILING_DEF;
763*a9fa9459Szrj 	  else if (is_visible_from_outside (&syms[n], blhe))
764*a9fa9459Szrj 	    res = def_ironly_exp;
765*a9fa9459Szrj 	}
766*a9fa9459Szrj 
767*a9fa9459Szrj     report_symbol:
768*a9fa9459Szrj       syms[n].resolution = res;
769*a9fa9459Szrj       if (report_plugin_symbols)
770*a9fa9459Szrj 	einfo (_("%P: %B: symbol `%s' "
771*a9fa9459Szrj 		 "definition: %d, visibility: %d, resolution: %d\n"),
772*a9fa9459Szrj 	       abfd, syms[n].name,
773*a9fa9459Szrj 	       syms[n].def, syms[n].visibility, res);
774*a9fa9459Szrj     }
775*a9fa9459Szrj   return LDPS_OK;
776*a9fa9459Szrj }
777*a9fa9459Szrj 
778*a9fa9459Szrj static enum ld_plugin_status
get_symbols_v1(const void * handle,int nsyms,struct ld_plugin_symbol * syms)779*a9fa9459Szrj get_symbols_v1 (const void *handle, int nsyms, struct ld_plugin_symbol *syms)
780*a9fa9459Szrj {
781*a9fa9459Szrj   return get_symbols (handle, nsyms, syms, LDPR_PREVAILING_DEF);
782*a9fa9459Szrj }
783*a9fa9459Szrj 
784*a9fa9459Szrj static enum ld_plugin_status
get_symbols_v2(const void * handle,int nsyms,struct ld_plugin_symbol * syms)785*a9fa9459Szrj get_symbols_v2 (const void *handle, int nsyms, struct ld_plugin_symbol *syms)
786*a9fa9459Szrj {
787*a9fa9459Szrj   return get_symbols (handle, nsyms, syms, LDPR_PREVAILING_DEF_IRONLY_EXP);
788*a9fa9459Szrj }
789*a9fa9459Szrj 
790*a9fa9459Szrj /* Add a new (real) input file generated by a plugin.  */
791*a9fa9459Szrj static enum ld_plugin_status
add_input_file(const char * pathname)792*a9fa9459Szrj add_input_file (const char *pathname)
793*a9fa9459Szrj {
794*a9fa9459Szrj   lang_input_statement_type *is;
795*a9fa9459Szrj 
796*a9fa9459Szrj   ASSERT (called_plugin);
797*a9fa9459Szrj   is = lang_add_input_file (xstrdup (pathname), lang_input_file_is_file_enum,
798*a9fa9459Szrj 			    NULL);
799*a9fa9459Szrj   if (!is)
800*a9fa9459Szrj     return LDPS_ERR;
801*a9fa9459Szrj   is->flags.lto_output = 1;
802*a9fa9459Szrj   return LDPS_OK;
803*a9fa9459Szrj }
804*a9fa9459Szrj 
805*a9fa9459Szrj /* Add a new (real) library required by a plugin.  */
806*a9fa9459Szrj static enum ld_plugin_status
add_input_library(const char * pathname)807*a9fa9459Szrj add_input_library (const char *pathname)
808*a9fa9459Szrj {
809*a9fa9459Szrj   lang_input_statement_type *is;
810*a9fa9459Szrj 
811*a9fa9459Szrj   ASSERT (called_plugin);
812*a9fa9459Szrj   is = lang_add_input_file (xstrdup (pathname), lang_input_file_is_l_enum,
813*a9fa9459Szrj 			    NULL);
814*a9fa9459Szrj   if (!is)
815*a9fa9459Szrj     return LDPS_ERR;
816*a9fa9459Szrj   is->flags.lto_output = 1;
817*a9fa9459Szrj   return LDPS_OK;
818*a9fa9459Szrj }
819*a9fa9459Szrj 
820*a9fa9459Szrj /* Set the extra library path to be used by libraries added via
821*a9fa9459Szrj    add_input_library.  */
822*a9fa9459Szrj static enum ld_plugin_status
set_extra_library_path(const char * path)823*a9fa9459Szrj set_extra_library_path (const char *path)
824*a9fa9459Szrj {
825*a9fa9459Szrj   ASSERT (called_plugin);
826*a9fa9459Szrj   ldfile_add_library_path (xstrdup (path), FALSE);
827*a9fa9459Szrj   return LDPS_OK;
828*a9fa9459Szrj }
829*a9fa9459Szrj 
830*a9fa9459Szrj /* Issue a diagnostic message from a plugin.  */
831*a9fa9459Szrj static enum ld_plugin_status
message(int level,const char * format,...)832*a9fa9459Szrj message (int level, const char *format, ...)
833*a9fa9459Szrj {
834*a9fa9459Szrj   va_list args;
835*a9fa9459Szrj   va_start (args, format);
836*a9fa9459Szrj 
837*a9fa9459Szrj   switch (level)
838*a9fa9459Szrj     {
839*a9fa9459Szrj     case LDPL_INFO:
840*a9fa9459Szrj       vfinfo (stdout, format, args, FALSE);
841*a9fa9459Szrj       putchar ('\n');
842*a9fa9459Szrj       break;
843*a9fa9459Szrj     case LDPL_WARNING:
844*a9fa9459Szrj       {
845*a9fa9459Szrj 	char *newfmt = concat ("%P: warning: ", format, "\n",
846*a9fa9459Szrj 			       (const char *) NULL);
847*a9fa9459Szrj 	vfinfo (stdout, newfmt, args, TRUE);
848*a9fa9459Szrj 	free (newfmt);
849*a9fa9459Szrj       }
850*a9fa9459Szrj       break;
851*a9fa9459Szrj     case LDPL_FATAL:
852*a9fa9459Szrj     case LDPL_ERROR:
853*a9fa9459Szrj     default:
854*a9fa9459Szrj       {
855*a9fa9459Szrj 	char *newfmt = concat (level == LDPL_FATAL ? "%P%F" : "%P%X",
856*a9fa9459Szrj 			       ": error: ", format, "\n",
857*a9fa9459Szrj 			       (const char *) NULL);
858*a9fa9459Szrj 	fflush (stdout);
859*a9fa9459Szrj 	vfinfo (stderr, newfmt, args, TRUE);
860*a9fa9459Szrj 	fflush (stderr);
861*a9fa9459Szrj 	free (newfmt);
862*a9fa9459Szrj       }
863*a9fa9459Szrj       break;
864*a9fa9459Szrj     }
865*a9fa9459Szrj 
866*a9fa9459Szrj   va_end (args);
867*a9fa9459Szrj   return LDPS_OK;
868*a9fa9459Szrj }
869*a9fa9459Szrj 
870*a9fa9459Szrj /* Helper to size leading part of tv array and set it up. */
871*a9fa9459Szrj static void
set_tv_header(struct ld_plugin_tv * tv)872*a9fa9459Szrj set_tv_header (struct ld_plugin_tv *tv)
873*a9fa9459Szrj {
874*a9fa9459Szrj   size_t i;
875*a9fa9459Szrj 
876*a9fa9459Szrj   /* Version info.  */
877*a9fa9459Szrj   static const unsigned int major = (unsigned)(BFD_VERSION / 100000000UL);
878*a9fa9459Szrj   static const unsigned int minor = (unsigned)(BFD_VERSION / 1000000UL) % 100;
879*a9fa9459Szrj 
880*a9fa9459Szrj   for (i = 0; i < tv_header_size; i++)
881*a9fa9459Szrj     {
882*a9fa9459Szrj       tv[i].tv_tag = tv_header_tags[i];
883*a9fa9459Szrj #define TVU(x) tv[i].tv_u.tv_ ## x
884*a9fa9459Szrj       switch (tv[i].tv_tag)
885*a9fa9459Szrj 	{
886*a9fa9459Szrj 	case LDPT_MESSAGE:
887*a9fa9459Szrj 	  TVU(message) = message;
888*a9fa9459Szrj 	  break;
889*a9fa9459Szrj 	case LDPT_API_VERSION:
890*a9fa9459Szrj 	  TVU(val) = LD_PLUGIN_API_VERSION;
891*a9fa9459Szrj 	  break;
892*a9fa9459Szrj 	case LDPT_GNU_LD_VERSION:
893*a9fa9459Szrj 	  TVU(val) = major * 100 + minor;
894*a9fa9459Szrj 	  break;
895*a9fa9459Szrj 	case LDPT_LINKER_OUTPUT:
896*a9fa9459Szrj 	  TVU(val) = (bfd_link_relocatable (&link_info) ? LDPO_REL
897*a9fa9459Szrj 		      : bfd_link_pde (&link_info) ? LDPO_EXEC
898*a9fa9459Szrj 		      : bfd_link_pie (&link_info) ? LDPO_PIE
899*a9fa9459Szrj 		      : LDPO_DYN);
900*a9fa9459Szrj 	  break;
901*a9fa9459Szrj 	case LDPT_OUTPUT_NAME:
902*a9fa9459Szrj 	  TVU(string) = output_filename;
903*a9fa9459Szrj 	  break;
904*a9fa9459Szrj 	case LDPT_REGISTER_CLAIM_FILE_HOOK:
905*a9fa9459Szrj 	  TVU(register_claim_file) = register_claim_file;
906*a9fa9459Szrj 	  break;
907*a9fa9459Szrj 	case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
908*a9fa9459Szrj 	  TVU(register_all_symbols_read) = register_all_symbols_read;
909*a9fa9459Szrj 	  break;
910*a9fa9459Szrj 	case LDPT_REGISTER_CLEANUP_HOOK:
911*a9fa9459Szrj 	  TVU(register_cleanup) = register_cleanup;
912*a9fa9459Szrj 	  break;
913*a9fa9459Szrj 	case LDPT_ADD_SYMBOLS:
914*a9fa9459Szrj 	  TVU(add_symbols) = add_symbols;
915*a9fa9459Szrj 	  break;
916*a9fa9459Szrj 	case LDPT_GET_INPUT_FILE:
917*a9fa9459Szrj 	  TVU(get_input_file) = get_input_file;
918*a9fa9459Szrj 	  break;
919*a9fa9459Szrj 	case LDPT_GET_VIEW:
920*a9fa9459Szrj 	  TVU(get_view) = get_view;
921*a9fa9459Szrj 	  break;
922*a9fa9459Szrj 	case LDPT_RELEASE_INPUT_FILE:
923*a9fa9459Szrj 	  TVU(release_input_file) = release_input_file;
924*a9fa9459Szrj 	  break;
925*a9fa9459Szrj 	case LDPT_GET_SYMBOLS:
926*a9fa9459Szrj 	  TVU(get_symbols) = get_symbols_v1;
927*a9fa9459Szrj 	  break;
928*a9fa9459Szrj 	case LDPT_GET_SYMBOLS_V2:
929*a9fa9459Szrj 	  TVU(get_symbols) = get_symbols_v2;
930*a9fa9459Szrj 	  break;
931*a9fa9459Szrj 	case LDPT_ADD_INPUT_FILE:
932*a9fa9459Szrj 	  TVU(add_input_file) = add_input_file;
933*a9fa9459Szrj 	  break;
934*a9fa9459Szrj 	case LDPT_ADD_INPUT_LIBRARY:
935*a9fa9459Szrj 	  TVU(add_input_library) = add_input_library;
936*a9fa9459Szrj 	  break;
937*a9fa9459Szrj 	case LDPT_SET_EXTRA_LIBRARY_PATH:
938*a9fa9459Szrj 	  TVU(set_extra_library_path) = set_extra_library_path;
939*a9fa9459Szrj 	  break;
940*a9fa9459Szrj 	default:
941*a9fa9459Szrj 	  /* Added a new entry to the array without adding
942*a9fa9459Szrj 	     a new case to set up its value is a bug.  */
943*a9fa9459Szrj 	  FAIL ();
944*a9fa9459Szrj 	}
945*a9fa9459Szrj #undef TVU
946*a9fa9459Szrj     }
947*a9fa9459Szrj }
948*a9fa9459Szrj 
949*a9fa9459Szrj /* Append the per-plugin args list and trailing LDPT_NULL to tv.  */
950*a9fa9459Szrj static void
set_tv_plugin_args(plugin_t * plugin,struct ld_plugin_tv * tv)951*a9fa9459Szrj set_tv_plugin_args (plugin_t *plugin, struct ld_plugin_tv *tv)
952*a9fa9459Szrj {
953*a9fa9459Szrj   plugin_arg_t *arg = plugin->args;
954*a9fa9459Szrj   while (arg)
955*a9fa9459Szrj     {
956*a9fa9459Szrj       tv->tv_tag = LDPT_OPTION;
957*a9fa9459Szrj       tv->tv_u.tv_string = arg->arg;
958*a9fa9459Szrj       arg = arg->next;
959*a9fa9459Szrj       tv++;
960*a9fa9459Szrj     }
961*a9fa9459Szrj   tv->tv_tag = LDPT_NULL;
962*a9fa9459Szrj   tv->tv_u.tv_val = 0;
963*a9fa9459Szrj }
964*a9fa9459Szrj 
965*a9fa9459Szrj /* Load up and initialise all plugins after argument parsing.  */
966*a9fa9459Szrj void
plugin_load_plugins(void)967*a9fa9459Szrj plugin_load_plugins (void)
968*a9fa9459Szrj {
969*a9fa9459Szrj   struct ld_plugin_tv *my_tv;
970*a9fa9459Szrj   unsigned int max_args = 0;
971*a9fa9459Szrj   plugin_t *curplug = plugins_list;
972*a9fa9459Szrj 
973*a9fa9459Szrj   /* If there are no plugins, we need do nothing this run.  */
974*a9fa9459Szrj   if (!curplug)
975*a9fa9459Szrj     return;
976*a9fa9459Szrj 
977*a9fa9459Szrj   /* First pass over plugins to find max # args needed so that we
978*a9fa9459Szrj      can size and allocate the tv array.  */
979*a9fa9459Szrj   while (curplug)
980*a9fa9459Szrj     {
981*a9fa9459Szrj       if (curplug->n_args > max_args)
982*a9fa9459Szrj 	max_args = curplug->n_args;
983*a9fa9459Szrj       curplug = curplug->next;
984*a9fa9459Szrj     }
985*a9fa9459Szrj 
986*a9fa9459Szrj   /* Allocate tv array and initialise constant part.  */
987*a9fa9459Szrj   my_tv = xmalloc ((max_args + 1 + tv_header_size) * sizeof *my_tv);
988*a9fa9459Szrj   set_tv_header (my_tv);
989*a9fa9459Szrj 
990*a9fa9459Szrj   /* Pass over plugins again, activating them.  */
991*a9fa9459Szrj   curplug = plugins_list;
992*a9fa9459Szrj   while (curplug)
993*a9fa9459Szrj     {
994*a9fa9459Szrj       enum ld_plugin_status rv;
995*a9fa9459Szrj       ld_plugin_onload onloadfn;
996*a9fa9459Szrj 
997*a9fa9459Szrj       onloadfn = (ld_plugin_onload) dlsym (curplug->dlhandle, "onload");
998*a9fa9459Szrj       if (!onloadfn)
999*a9fa9459Szrj 	onloadfn = (ld_plugin_onload) dlsym (curplug->dlhandle, "_onload");
1000*a9fa9459Szrj       if (!onloadfn)
1001*a9fa9459Szrj         einfo (_("%P%F: %s: error loading plugin: %s\n"),
1002*a9fa9459Szrj 	       curplug->name, dlerror ());
1003*a9fa9459Szrj       set_tv_plugin_args (curplug, &my_tv[tv_header_size]);
1004*a9fa9459Szrj       called_plugin = curplug;
1005*a9fa9459Szrj       rv = (*onloadfn) (my_tv);
1006*a9fa9459Szrj       called_plugin = NULL;
1007*a9fa9459Szrj       if (rv != LDPS_OK)
1008*a9fa9459Szrj 	einfo (_("%P%F: %s: plugin error: %d\n"), curplug->name, rv);
1009*a9fa9459Szrj       curplug = curplug->next;
1010*a9fa9459Szrj     }
1011*a9fa9459Szrj 
1012*a9fa9459Szrj   /* Since plugin(s) inited ok, assume they're going to want symbol
1013*a9fa9459Szrj      resolutions, which needs us to track which symbols are referenced
1014*a9fa9459Szrj      by non-IR files using the linker's notice callback.  */
1015*a9fa9459Szrj   orig_notice_all = link_info.notice_all;
1016*a9fa9459Szrj   orig_callbacks = link_info.callbacks;
1017*a9fa9459Szrj   plugin_callbacks = *orig_callbacks;
1018*a9fa9459Szrj   plugin_callbacks.notice = &plugin_notice;
1019*a9fa9459Szrj   link_info.notice_all = TRUE;
1020*a9fa9459Szrj   link_info.lto_plugin_active = TRUE;
1021*a9fa9459Szrj   link_info.callbacks = &plugin_callbacks;
1022*a9fa9459Szrj 
1023*a9fa9459Szrj   register_ld_plugin_object_p (plugin_object_p);
1024*a9fa9459Szrj 
1025*a9fa9459Szrj #if HAVE_MMAP && HAVE_GETPAGESIZE
1026*a9fa9459Szrj   plugin_pagesize = getpagesize ();
1027*a9fa9459Szrj #endif
1028*a9fa9459Szrj }
1029*a9fa9459Szrj 
1030*a9fa9459Szrj /* Call 'claim file' hook for all plugins.  */
1031*a9fa9459Szrj static int
plugin_call_claim_file(const struct ld_plugin_input_file * file,int * claimed)1032*a9fa9459Szrj plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed)
1033*a9fa9459Szrj {
1034*a9fa9459Szrj   plugin_t *curplug = plugins_list;
1035*a9fa9459Szrj   *claimed = FALSE;
1036*a9fa9459Szrj   while (curplug && !*claimed)
1037*a9fa9459Szrj     {
1038*a9fa9459Szrj       if (curplug->claim_file_handler)
1039*a9fa9459Szrj 	{
1040*a9fa9459Szrj 	  enum ld_plugin_status rv;
1041*a9fa9459Szrj 	  called_plugin = curplug;
1042*a9fa9459Szrj 	  rv = (*curplug->claim_file_handler) (file, claimed);
1043*a9fa9459Szrj 	  called_plugin = NULL;
1044*a9fa9459Szrj 	  if (rv != LDPS_OK)
1045*a9fa9459Szrj 	    set_plugin_error (curplug->name);
1046*a9fa9459Szrj 	}
1047*a9fa9459Szrj       curplug = curplug->next;
1048*a9fa9459Szrj     }
1049*a9fa9459Szrj   return plugin_error_p () ? -1 : 0;
1050*a9fa9459Szrj }
1051*a9fa9459Szrj 
1052*a9fa9459Szrj /* Duplicates a character string with memory attached to ABFD.  */
1053*a9fa9459Szrj 
1054*a9fa9459Szrj static char *
plugin_strdup(bfd * abfd,const char * str)1055*a9fa9459Szrj plugin_strdup (bfd *abfd, const char *str)
1056*a9fa9459Szrj {
1057*a9fa9459Szrj   size_t strlength;
1058*a9fa9459Szrj   char *copy;
1059*a9fa9459Szrj   strlength = strlen (str) + 1;
1060*a9fa9459Szrj   copy = bfd_alloc (abfd, strlength);
1061*a9fa9459Szrj   if (copy == NULL)
1062*a9fa9459Szrj     einfo (_("%P%F: plugin_strdup failed to allocate memory: %s\n"),
1063*a9fa9459Szrj 	   bfd_get_error ());
1064*a9fa9459Szrj   memcpy (copy, str, strlength);
1065*a9fa9459Szrj   return copy;
1066*a9fa9459Szrj }
1067*a9fa9459Szrj 
1068*a9fa9459Szrj static const bfd_target *
plugin_object_p(bfd * ibfd)1069*a9fa9459Szrj plugin_object_p (bfd *ibfd)
1070*a9fa9459Szrj {
1071*a9fa9459Szrj   int claimed;
1072*a9fa9459Szrj   plugin_input_file_t *input;
1073*a9fa9459Szrj   off_t offset, filesize;
1074*a9fa9459Szrj   struct ld_plugin_input_file file;
1075*a9fa9459Szrj   bfd *abfd;
1076*a9fa9459Szrj   bfd_boolean inarchive;
1077*a9fa9459Szrj   const char *name;
1078*a9fa9459Szrj   int fd;
1079*a9fa9459Szrj 
1080*a9fa9459Szrj   /* Don't try the dummy object file.  */
1081*a9fa9459Szrj   if ((ibfd->flags & BFD_PLUGIN) != 0)
1082*a9fa9459Szrj     return NULL;
1083*a9fa9459Szrj 
1084*a9fa9459Szrj   if (ibfd->plugin_format != bfd_plugin_unknown)
1085*a9fa9459Szrj     {
1086*a9fa9459Szrj       if (ibfd->plugin_format == bfd_plugin_yes)
1087*a9fa9459Szrj 	return ibfd->plugin_dummy_bfd->xvec;
1088*a9fa9459Szrj       else
1089*a9fa9459Szrj 	return NULL;
1090*a9fa9459Szrj     }
1091*a9fa9459Szrj 
1092*a9fa9459Szrj   inarchive = (ibfd->my_archive != NULL
1093*a9fa9459Szrj 	       && !bfd_is_thin_archive (ibfd->my_archive));
1094*a9fa9459Szrj   name = inarchive ? ibfd->my_archive->filename : ibfd->filename;
1095*a9fa9459Szrj   fd = open (name, O_RDONLY | O_BINARY);
1096*a9fa9459Szrj 
1097*a9fa9459Szrj   if (fd < 0)
1098*a9fa9459Szrj     return NULL;
1099*a9fa9459Szrj 
1100*a9fa9459Szrj   /* We create a dummy BFD, initially empty, to house whatever symbols
1101*a9fa9459Szrj      the plugin may want to add.  */
1102*a9fa9459Szrj   abfd = plugin_get_ir_dummy_bfd (ibfd->filename, ibfd);
1103*a9fa9459Szrj 
1104*a9fa9459Szrj   input = bfd_alloc (abfd, sizeof (*input));
1105*a9fa9459Szrj   if (input == NULL)
1106*a9fa9459Szrj     einfo (_("%P%F: plugin failed to allocate memory for input: %s\n"),
1107*a9fa9459Szrj 	   bfd_get_error ());
1108*a9fa9459Szrj 
1109*a9fa9459Szrj   if (inarchive)
1110*a9fa9459Szrj     {
1111*a9fa9459Szrj       /* Offset and filesize must refer to the individual archive
1112*a9fa9459Szrj 	 member, not the whole file, and must exclude the header.
1113*a9fa9459Szrj 	 Fortunately for us, that is how the data is stored in the
1114*a9fa9459Szrj 	 origin field of the bfd and in the arelt_data.  */
1115*a9fa9459Szrj       offset = ibfd->origin;
1116*a9fa9459Szrj       filesize = arelt_size (ibfd);
1117*a9fa9459Szrj     }
1118*a9fa9459Szrj   else
1119*a9fa9459Szrj     {
1120*a9fa9459Szrj       offset = 0;
1121*a9fa9459Szrj       filesize = lseek (fd, 0, SEEK_END);
1122*a9fa9459Szrj 
1123*a9fa9459Szrj       /* We must copy filename attached to ibfd if it is not an archive
1124*a9fa9459Szrj 	 member since it may be freed by bfd_close below.  */
1125*a9fa9459Szrj       name = plugin_strdup (abfd, name);
1126*a9fa9459Szrj     }
1127*a9fa9459Szrj 
1128*a9fa9459Szrj   file.name = name;
1129*a9fa9459Szrj   file.offset = offset;
1130*a9fa9459Szrj   file.filesize = filesize;
1131*a9fa9459Szrj   file.fd = fd;
1132*a9fa9459Szrj   file.handle = input;
1133*a9fa9459Szrj 
1134*a9fa9459Szrj   input->abfd = abfd;
1135*a9fa9459Szrj   input->view_buffer.addr = NULL;
1136*a9fa9459Szrj   input->view_buffer.filesize = 0;
1137*a9fa9459Szrj   input->view_buffer.offset = 0;
1138*a9fa9459Szrj   input->fd = fd;
1139*a9fa9459Szrj   input->use_mmap = FALSE;
1140*a9fa9459Szrj   input->offset = offset;
1141*a9fa9459Szrj   input->filesize = filesize;
1142*a9fa9459Szrj   input->name = plugin_strdup (abfd, ibfd->filename);
1143*a9fa9459Szrj 
1144*a9fa9459Szrj   claimed = 0;
1145*a9fa9459Szrj 
1146*a9fa9459Szrj   if (plugin_call_claim_file (&file, &claimed))
1147*a9fa9459Szrj     einfo (_("%P%F: %s: plugin reported error claiming file\n"),
1148*a9fa9459Szrj 	   plugin_error_plugin ());
1149*a9fa9459Szrj 
1150*a9fa9459Szrj   if (input->fd != -1 && ! bfd_plugin_target_p (ibfd->xvec))
1151*a9fa9459Szrj     {
1152*a9fa9459Szrj       /* FIXME: fd belongs to us, not the plugin.  GCC plugin, which
1153*a9fa9459Szrj 	 doesn't need fd after plugin_call_claim_file, doesn't use
1154*a9fa9459Szrj 	 BFD plugin target vector.  Since GCC plugin doesn't call
1155*a9fa9459Szrj 	 release_input_file, we close it here.  LLVM plugin, which
1156*a9fa9459Szrj 	 needs fd after plugin_call_claim_file and calls
1157*a9fa9459Szrj 	 release_input_file after it is done, uses BFD plugin target
1158*a9fa9459Szrj 	 vector.  This scheme doesn't work when a plugin needs fd and
1159*a9fa9459Szrj 	 doesn't use BFD plugin target vector neither.  */
1160*a9fa9459Szrj       close (fd);
1161*a9fa9459Szrj       input->fd = -1;
1162*a9fa9459Szrj     }
1163*a9fa9459Szrj 
1164*a9fa9459Szrj   if (claimed)
1165*a9fa9459Szrj     {
1166*a9fa9459Szrj       ibfd->plugin_format = bfd_plugin_yes;
1167*a9fa9459Szrj       ibfd->plugin_dummy_bfd = abfd;
1168*a9fa9459Szrj       bfd_make_readable (abfd);
1169*a9fa9459Szrj       return abfd->xvec;
1170*a9fa9459Szrj     }
1171*a9fa9459Szrj   else
1172*a9fa9459Szrj     {
1173*a9fa9459Szrj #if HAVE_MMAP
1174*a9fa9459Szrj       if (input->use_mmap)
1175*a9fa9459Szrj 	{
1176*a9fa9459Szrj 	  /* If plugin didn't claim the file, unmap the buffer.  */
1177*a9fa9459Szrj 	  char *addr = input->view_buffer.addr;
1178*a9fa9459Szrj 	  off_t size = input->view_buffer.filesize;
1179*a9fa9459Szrj # if HAVE_GETPAGESIZE
1180*a9fa9459Szrj 	  off_t bias = input->view_buffer.offset % plugin_pagesize;
1181*a9fa9459Szrj 	  size += bias;
1182*a9fa9459Szrj 	  addr -= bias;
1183*a9fa9459Szrj # endif
1184*a9fa9459Szrj 	  munmap (addr, size);
1185*a9fa9459Szrj 	}
1186*a9fa9459Szrj #endif
1187*a9fa9459Szrj 
1188*a9fa9459Szrj       /* If plugin didn't claim the file, we don't need the dummy bfd.
1189*a9fa9459Szrj 	 Can't avoid speculatively creating it, alas.  */
1190*a9fa9459Szrj       ibfd->plugin_format = bfd_plugin_no;
1191*a9fa9459Szrj       bfd_close_all_done (abfd);
1192*a9fa9459Szrj       return NULL;
1193*a9fa9459Szrj     }
1194*a9fa9459Szrj }
1195*a9fa9459Szrj 
1196*a9fa9459Szrj void
plugin_maybe_claim(lang_input_statement_type * entry)1197*a9fa9459Szrj plugin_maybe_claim (lang_input_statement_type *entry)
1198*a9fa9459Szrj {
1199*a9fa9459Szrj   if (plugin_object_p (entry->the_bfd))
1200*a9fa9459Szrj     {
1201*a9fa9459Szrj       bfd *abfd = entry->the_bfd->plugin_dummy_bfd;
1202*a9fa9459Szrj 
1203*a9fa9459Szrj       /* Discard the real file's BFD and substitute the dummy one.  */
1204*a9fa9459Szrj 
1205*a9fa9459Szrj       /* We can't call bfd_close on archives.  BFD archive handling
1206*a9fa9459Szrj 	 caches elements, and add_archive_element keeps pointers to
1207*a9fa9459Szrj 	 the_bfd and the_bfd->filename in a lang_input_statement_type
1208*a9fa9459Szrj 	 linker script statement.  */
1209*a9fa9459Szrj       if (entry->the_bfd->my_archive == NULL)
1210*a9fa9459Szrj 	bfd_close (entry->the_bfd);
1211*a9fa9459Szrj       entry->the_bfd = abfd;
1212*a9fa9459Szrj       entry->flags.claimed = 1;
1213*a9fa9459Szrj     }
1214*a9fa9459Szrj }
1215*a9fa9459Szrj 
1216*a9fa9459Szrj /* Call 'all symbols read' hook for all plugins.  */
1217*a9fa9459Szrj int
plugin_call_all_symbols_read(void)1218*a9fa9459Szrj plugin_call_all_symbols_read (void)
1219*a9fa9459Szrj {
1220*a9fa9459Szrj   plugin_t *curplug = plugins_list;
1221*a9fa9459Szrj 
1222*a9fa9459Szrj   /* Disable any further file-claiming.  */
1223*a9fa9459Szrj   no_more_claiming = TRUE;
1224*a9fa9459Szrj 
1225*a9fa9459Szrj   while (curplug)
1226*a9fa9459Szrj     {
1227*a9fa9459Szrj       if (curplug->all_symbols_read_handler)
1228*a9fa9459Szrj 	{
1229*a9fa9459Szrj 	  enum ld_plugin_status rv;
1230*a9fa9459Szrj 	  called_plugin = curplug;
1231*a9fa9459Szrj 	  rv = (*curplug->all_symbols_read_handler) ();
1232*a9fa9459Szrj 	  called_plugin = NULL;
1233*a9fa9459Szrj 	  if (rv != LDPS_OK)
1234*a9fa9459Szrj 	    set_plugin_error (curplug->name);
1235*a9fa9459Szrj 	}
1236*a9fa9459Szrj       curplug = curplug->next;
1237*a9fa9459Szrj     }
1238*a9fa9459Szrj   return plugin_error_p () ? -1 : 0;
1239*a9fa9459Szrj }
1240*a9fa9459Szrj 
1241*a9fa9459Szrj /* Call 'cleanup' hook for all plugins at exit.  */
1242*a9fa9459Szrj void
plugin_call_cleanup(void)1243*a9fa9459Szrj plugin_call_cleanup (void)
1244*a9fa9459Szrj {
1245*a9fa9459Szrj   plugin_t *curplug = plugins_list;
1246*a9fa9459Szrj   while (curplug)
1247*a9fa9459Szrj     {
1248*a9fa9459Szrj       if (curplug->cleanup_handler && !curplug->cleanup_done)
1249*a9fa9459Szrj 	{
1250*a9fa9459Szrj 	  enum ld_plugin_status rv;
1251*a9fa9459Szrj 	  curplug->cleanup_done = TRUE;
1252*a9fa9459Szrj 	  called_plugin = curplug;
1253*a9fa9459Szrj 	  rv = (*curplug->cleanup_handler) ();
1254*a9fa9459Szrj 	  called_plugin = NULL;
1255*a9fa9459Szrj 	  if (rv != LDPS_OK)
1256*a9fa9459Szrj 	    info_msg (_("%P: %s: error in plugin cleanup: %d (ignored)\n"),
1257*a9fa9459Szrj 		      curplug->name, rv);
1258*a9fa9459Szrj 	  dlclose (curplug->dlhandle);
1259*a9fa9459Szrj 	}
1260*a9fa9459Szrj       curplug = curplug->next;
1261*a9fa9459Szrj     }
1262*a9fa9459Szrj }
1263*a9fa9459Szrj 
1264*a9fa9459Szrj /* To determine which symbols should be resolved LDPR_PREVAILING_DEF
1265*a9fa9459Szrj    and which LDPR_PREVAILING_DEF_IRONLY, we notice all the symbols as
1266*a9fa9459Szrj    the linker adds them to the linker hash table.  Mark those
1267*a9fa9459Szrj    referenced from a non-IR file with non_ir_ref.  We have to
1268*a9fa9459Szrj    notice_all symbols, because we won't necessarily know until later
1269*a9fa9459Szrj    which ones will be contributed by IR files.  */
1270*a9fa9459Szrj static bfd_boolean
plugin_notice(struct bfd_link_info * info,struct bfd_link_hash_entry * h,struct bfd_link_hash_entry * inh,bfd * abfd,asection * section,bfd_vma value,flagword flags)1271*a9fa9459Szrj plugin_notice (struct bfd_link_info *info,
1272*a9fa9459Szrj 	       struct bfd_link_hash_entry *h,
1273*a9fa9459Szrj 	       struct bfd_link_hash_entry *inh,
1274*a9fa9459Szrj 	       bfd *abfd,
1275*a9fa9459Szrj 	       asection *section,
1276*a9fa9459Szrj 	       bfd_vma value,
1277*a9fa9459Szrj 	       flagword flags)
1278*a9fa9459Szrj {
1279*a9fa9459Szrj   struct bfd_link_hash_entry *orig_h = h;
1280*a9fa9459Szrj 
1281*a9fa9459Szrj   if (h != NULL)
1282*a9fa9459Szrj     {
1283*a9fa9459Szrj       bfd *sym_bfd;
1284*a9fa9459Szrj 
1285*a9fa9459Szrj       if (h->type == bfd_link_hash_warning)
1286*a9fa9459Szrj 	h = h->u.i.link;
1287*a9fa9459Szrj 
1288*a9fa9459Szrj       /* Nothing to do here if this def/ref is from an IR dummy BFD.  */
1289*a9fa9459Szrj       if (is_ir_dummy_bfd (abfd))
1290*a9fa9459Szrj 	;
1291*a9fa9459Szrj 
1292*a9fa9459Szrj       /* Making an indirect symbol counts as a reference unless this
1293*a9fa9459Szrj 	 is a brand new symbol.  */
1294*a9fa9459Szrj       else if (bfd_is_ind_section (section)
1295*a9fa9459Szrj 	       || (flags & BSF_INDIRECT) != 0)
1296*a9fa9459Szrj 	{
1297*a9fa9459Szrj 	  /* ??? Some of this is questionable.  See comments in
1298*a9fa9459Szrj 	     _bfd_generic_link_add_one_symbol for case IND.  */
1299*a9fa9459Szrj 	  if (h->type != bfd_link_hash_new)
1300*a9fa9459Szrj 	    {
1301*a9fa9459Szrj 	      h->non_ir_ref = TRUE;
1302*a9fa9459Szrj 	      inh->non_ir_ref = TRUE;
1303*a9fa9459Szrj 	    }
1304*a9fa9459Szrj 	  else if (inh->type == bfd_link_hash_new)
1305*a9fa9459Szrj 	    inh->non_ir_ref = TRUE;
1306*a9fa9459Szrj 	}
1307*a9fa9459Szrj 
1308*a9fa9459Szrj       /* Nothing to do here for warning symbols.  */
1309*a9fa9459Szrj       else if ((flags & BSF_WARNING) != 0)
1310*a9fa9459Szrj 	;
1311*a9fa9459Szrj 
1312*a9fa9459Szrj       /* Nothing to do here for constructor symbols.  */
1313*a9fa9459Szrj       else if ((flags & BSF_CONSTRUCTOR) != 0)
1314*a9fa9459Szrj 	;
1315*a9fa9459Szrj 
1316*a9fa9459Szrj       /* If this is a ref, set non_ir_ref.  */
1317*a9fa9459Szrj       else if (bfd_is_und_section (section))
1318*a9fa9459Szrj 	{
1319*a9fa9459Szrj 	  /* Replace the undefined dummy bfd with the real one.  */
1320*a9fa9459Szrj 	  if ((h->type == bfd_link_hash_undefined
1321*a9fa9459Szrj 	       || h->type == bfd_link_hash_undefweak)
1322*a9fa9459Szrj 	      && (h->u.undef.abfd == NULL
1323*a9fa9459Szrj 		  || (h->u.undef.abfd->flags & BFD_PLUGIN) != 0))
1324*a9fa9459Szrj 	    h->u.undef.abfd = abfd;
1325*a9fa9459Szrj 	  h->non_ir_ref = TRUE;
1326*a9fa9459Szrj 	}
1327*a9fa9459Szrj 
1328*a9fa9459Szrj       /* Otherwise, it must be a new def.  */
1329*a9fa9459Szrj       else
1330*a9fa9459Szrj 	{
1331*a9fa9459Szrj 	  /* A common symbol should be merged with other commons or
1332*a9fa9459Szrj 	     defs with the same name.  In particular, a common ought
1333*a9fa9459Szrj 	     to be overridden by a def in a -flto object.  In that
1334*a9fa9459Szrj 	     sense a common is also a ref.  */
1335*a9fa9459Szrj 	  if (bfd_is_com_section (section))
1336*a9fa9459Szrj 	    h->non_ir_ref = TRUE;
1337*a9fa9459Szrj 
1338*a9fa9459Szrj 	  /* Ensure any symbol defined in an IR dummy BFD takes on a
1339*a9fa9459Szrj 	     new value from a real BFD.  Weak symbols are not normally
1340*a9fa9459Szrj 	     overridden by a new weak definition, and strong symbols
1341*a9fa9459Szrj 	     will normally cause multiple definition errors.  Avoid
1342*a9fa9459Szrj 	     this by making the symbol appear to be undefined.  */
1343*a9fa9459Szrj 	  if (((h->type == bfd_link_hash_defweak
1344*a9fa9459Szrj 		|| h->type == bfd_link_hash_defined)
1345*a9fa9459Szrj 	       && is_ir_dummy_bfd (sym_bfd = h->u.def.section->owner))
1346*a9fa9459Szrj 	      || (h->type == bfd_link_hash_common
1347*a9fa9459Szrj 		  && is_ir_dummy_bfd (sym_bfd = h->u.c.p->section->owner)))
1348*a9fa9459Szrj 	    {
1349*a9fa9459Szrj 	      h->type = bfd_link_hash_undefweak;
1350*a9fa9459Szrj 	      h->u.undef.abfd = sym_bfd;
1351*a9fa9459Szrj 	    }
1352*a9fa9459Szrj 	}
1353*a9fa9459Szrj     }
1354*a9fa9459Szrj 
1355*a9fa9459Szrj   /* Continue with cref/nocrossref/trace-sym processing.  */
1356*a9fa9459Szrj   if (orig_h == NULL
1357*a9fa9459Szrj       || orig_notice_all
1358*a9fa9459Szrj       || (info->notice_hash != NULL
1359*a9fa9459Szrj 	  && bfd_hash_lookup (info->notice_hash, orig_h->root.string,
1360*a9fa9459Szrj 			      FALSE, FALSE) != NULL))
1361*a9fa9459Szrj     return (*orig_callbacks->notice) (info, orig_h, inh,
1362*a9fa9459Szrj 				      abfd, section, value, flags);
1363*a9fa9459Szrj   return TRUE;
1364*a9fa9459Szrj }
1365