PR 10980
[external/binutils.git] / gold / plugin.h
1 // plugin.h -- plugin manager for gold      -*- C++ -*-
2
3 // Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
4 // Written by Cary Coutant <ccoutant@google.com>.
5
6 // This file is part of gold.
7
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 3 of the License, or
11 // (at your option) any later version.
12
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 // MA 02110-1301, USA.
22
23 #ifndef GOLD_PLUGIN_H
24 #define GOLD_PLUGIN_H
25
26 #include <list>
27 #include <string>
28
29 #include "object.h"
30 #include "plugin-api.h"
31 #include "workqueue.h"
32
33 namespace gold
34 {
35
36 class General_options;
37 class Input_file;
38 class Input_objects;
39 class Symbol_table;
40 class Layout;
41 class Dirsearch;
42 class Mapfile;
43 class Task_token;
44 class Pluginobj;
45
46 // This class represents a single plugin library.
47
48 class Plugin
49 {
50  public:
51   Plugin(const char* filename)
52     : handle_(NULL),
53       filename_(filename),
54       args_(),
55       claim_file_handler_(NULL),
56       all_symbols_read_handler_(NULL),
57       cleanup_handler_(NULL),
58       cleanup_done_(false)
59   { }
60
61   ~Plugin()
62   { }
63
64   // Load the library and call its entry point.
65   void
66   load();
67
68   // Call the claim-file handler.
69   bool
70   claim_file(struct ld_plugin_input_file *plugin_input_file);
71
72   // Call the all-symbols-read handler.
73   void
74   all_symbols_read();
75
76   // Call the cleanup handler.
77   void
78   cleanup();
79
80   // Register a claim-file handler.
81   void
82   set_claim_file_handler(ld_plugin_claim_file_handler handler)
83   { this->claim_file_handler_ = handler; }
84
85   // Register an all-symbols-read handler.
86   void
87   set_all_symbols_read_handler(ld_plugin_all_symbols_read_handler handler)
88   { this->all_symbols_read_handler_ = handler; }
89
90   // Register a claim-file handler.
91   void
92   set_cleanup_handler(ld_plugin_cleanup_handler handler)
93   { this->cleanup_handler_ = handler; }
94
95   // Add an argument
96   void
97   add_option(const char *arg)
98   {
99     this->args_.push_back(arg);
100   }
101
102  private:
103   Plugin(const Plugin&);
104   Plugin& operator=(const Plugin&);
105
106   // The shared library handle returned by dlopen.
107   void* handle_;
108   // The argument string given to --plugin.
109   std::string filename_;
110   // The list of argument string given to --plugin-opt.
111   std::vector<std::string> args_;
112   // The plugin's event handlers.
113   ld_plugin_claim_file_handler claim_file_handler_;
114   ld_plugin_all_symbols_read_handler all_symbols_read_handler_;
115   ld_plugin_cleanup_handler cleanup_handler_;
116   // TRUE if the cleanup handlers have been called.
117   bool cleanup_done_;
118 };
119
120 // A manager class for plugins.
121
122 class Plugin_manager
123 {
124  public:
125   Plugin_manager(const General_options& options)
126     : plugins_(), objects_(), deferred_layout_objects_(), input_file_(NULL),
127       plugin_input_file_(), in_replacement_phase_(false),
128       options_(options), workqueue_(NULL), task_(NULL), input_objects_(NULL),
129       symtab_(NULL), layout_(NULL), dirpath_(NULL), mapfile_(NULL),
130       this_blocker_(NULL)
131   { this->current_ = plugins_.end(); }
132
133   ~Plugin_manager();
134
135   // Add a plugin library.
136   void
137   add_plugin(const char* filename)
138   { this->plugins_.push_back(new Plugin(filename)); }
139
140   // Add an argument to the current plugin.
141   void
142   add_plugin_option(const char* opt)
143   {
144     Plugin* last = this->plugins_.back();
145     last->add_option(opt);
146   }
147
148   // Load all plugin libraries.
149   void
150   load_plugins();
151
152   // Call the plugin claim-file handlers in turn to see if any claim the file.
153   Pluginobj*
154   claim_file(Input_file *input_file, off_t offset, off_t filesize);
155
156   // Call the all-symbols-read handlers.
157   void
158   all_symbols_read(Workqueue* workqueue, Task* task,
159                    Input_objects* input_objects, Symbol_table* symtab,
160                    Layout* layout, Dirsearch* dirpath, Mapfile* mapfile,
161                    Task_token** last_blocker);
162
163   // Run deferred layout.
164   void
165   layout_deferred_objects();
166
167   // Call the cleanup handlers.
168   void
169   cleanup();
170
171   // Register a claim-file handler.
172   void
173   set_claim_file_handler(ld_plugin_claim_file_handler handler)
174   {
175     gold_assert(this->current_ != plugins_.end());
176     (*this->current_)->set_claim_file_handler(handler);
177   }
178
179   // Register an all-symbols-read handler.
180   void
181   set_all_symbols_read_handler(ld_plugin_all_symbols_read_handler handler)
182   {
183     gold_assert(this->current_ != plugins_.end());
184     (*this->current_)->set_all_symbols_read_handler(handler);
185   }
186
187   // Register a claim-file handler.
188   void
189   set_cleanup_handler(ld_plugin_cleanup_handler handler)
190   {
191     gold_assert(this->current_ != plugins_.end());
192     (*this->current_)->set_cleanup_handler(handler);
193   }
194
195   // Make a new Pluginobj object.  This is called when the plugin calls
196   // the add_symbols API.
197   Pluginobj*
198   make_plugin_object(unsigned int handle);
199
200   // Return the Pluginobj associated with the given HANDLE.
201   Pluginobj*
202   object(unsigned int handle) const
203   {
204     if (handle >= this->objects_.size())
205       return NULL;
206     return this->objects_[handle];
207   }
208
209   // Return TRUE if any input files have been claimed by a plugin
210   // and we are still in the initial input phase.
211   bool
212   should_defer_layout() const
213   { return !this->objects_.empty() && !this->in_replacement_phase_; }
214
215   // Add a regular object to the deferred layout list.  These are
216   // objects whose layout has been deferred until after the
217   // replacement files have arrived.
218   void
219   add_deferred_layout_object(Relobj* obj)
220   { this->deferred_layout_objects_.push_back(obj); }
221
222   // Get input file information with an open (possibly re-opened)
223   // file descriptor.
224   ld_plugin_status
225   get_input_file(unsigned int handle, struct ld_plugin_input_file *file);
226
227   // Release an input file.
228   ld_plugin_status
229   release_input_file(unsigned int handle);
230
231   // Add a new input file.
232   ld_plugin_status
233   add_input_file(char *pathname, bool is_lib);
234
235   // Return TRUE if we are in the replacement phase.
236   bool
237   in_replacement_phase() const
238   { return this->in_replacement_phase_; }
239
240  private:
241   Plugin_manager(const Plugin_manager&);
242   Plugin_manager& operator=(const Plugin_manager&);
243
244   typedef std::list<Plugin*> Plugin_list;
245   typedef std::vector<Pluginobj*> Object_list;
246   typedef std::vector<Relobj*> Deferred_layout_list;
247
248   // The list of plugin libraries.
249   Plugin_list plugins_;
250   // A pointer to the current plugin.  Used while loading plugins.
251   Plugin_list::iterator current_;
252
253   // The list of plugin objects.  The index of an item in this list
254   // serves as the "handle" that we pass to the plugins.
255   Object_list objects_;
256
257   // The list of regular objects whose layout has been deferred.
258   Deferred_layout_list deferred_layout_objects_;
259
260   // The file currently up for claim by the plugins.
261   Input_file* input_file_;
262   struct ld_plugin_input_file plugin_input_file_;
263
264   // TRUE after the all symbols read event; indicates that we are
265   // processing replacement files whose symbols should replace the
266   // placeholder symbols from the Pluginobj objects.
267   bool in_replacement_phase_;
268
269   const General_options& options_;
270   Workqueue* workqueue_;
271   Task* task_;
272   Input_objects* input_objects_;
273   Symbol_table* symtab_;
274   Layout* layout_;
275   Dirsearch* dirpath_;
276   Mapfile* mapfile_;
277   Task_token* this_blocker_;
278 };
279
280
281 // An object file claimed by a plugin.  This is an abstract base class.
282 // The implementation is the template class Sized_pluginobj.
283
284 class Pluginobj : public Object
285 {
286  public:
287
288   typedef std::vector<Symbol*> Symbols;
289
290   Pluginobj(const std::string& name, Input_file* input_file, off_t offset,
291             off_t filesize);
292
293   // Fill in the symbol resolution status for the given plugin symbols.
294   ld_plugin_status
295   get_symbol_resolution_info(int nsyms, ld_plugin_symbol* syms) const;
296
297   // Store the incoming symbols from the plugin for later processing.
298   void
299   store_incoming_symbols(int nsyms, const struct ld_plugin_symbol* syms)
300   {
301     this->nsyms_ = nsyms;
302     this->syms_ = syms;
303   }
304
305   // Return TRUE if the comdat group with key COMDAT_KEY from this object
306   // should be kept.
307   bool
308   include_comdat_group(std::string comdat_key, Layout* layout);
309
310   // Return the filename.
311   const std::string&
312   filename() const
313   { return this->input_file()->filename(); }
314
315   // Return the file descriptor.
316   int
317   descriptor()
318   { return this->input_file()->file().descriptor(); }
319
320   // Return the size of the file or archive member.
321   off_t
322   filesize()
323   { return this->filesize_; }
324
325  protected:
326   // Return TRUE if this is an object claimed by a plugin.
327   virtual Pluginobj*
328   do_pluginobj()
329   { return this; }
330
331   // The number of symbols provided by the plugin.
332   int nsyms_;
333   
334   // The symbols provided by the plugin.
335   const struct ld_plugin_symbol* syms_;
336
337   // The entries in the symbol table for the external symbols.
338   Symbols symbols_;
339
340  private:
341   // Size of the file (or archive member).
342   off_t filesize_;
343   // Map a comdat key symbol to a boolean indicating whether the comdat
344   // group in this object with that key should be kept.
345   typedef Unordered_map<std::string, bool> Comdat_map;
346   Comdat_map comdat_map_;
347 };
348
349 // A plugin object, size-specific version.
350
351 template<int size, bool big_endian>
352 class Sized_pluginobj : public Pluginobj
353 {
354  public:
355   Sized_pluginobj(const std::string& name, Input_file* input_file,
356                   off_t offset, off_t filesize);
357
358   // Read the symbols.
359   void
360   do_read_symbols(Read_symbols_data*);
361
362   // Lay out the input sections.
363   void
364   do_layout(Symbol_table*, Layout*, Read_symbols_data*);
365
366   // Add the symbols to the symbol table.
367   void
368   do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*);
369
370   // Get the size of a section.
371   uint64_t
372   do_section_size(unsigned int shndx);
373
374   // Get the name of a section.
375   std::string
376   do_section_name(unsigned int shndx);
377
378   // Return a view of the contents of a section.
379   Object::Location
380   do_section_contents(unsigned int shndx);
381
382   // Return section flags.
383   uint64_t
384   do_section_flags(unsigned int shndx);
385
386   // Return section entsize.
387   uint64_t
388   do_section_entsize(unsigned int shndx);
389
390   // Return section address.
391   uint64_t
392   do_section_address(unsigned int shndx);
393
394   // Return section type.
395   unsigned int
396   do_section_type(unsigned int shndx);
397
398   // Return the section link field.
399   unsigned int
400   do_section_link(unsigned int shndx);
401
402   // Return the section link field.
403   unsigned int
404   do_section_info(unsigned int shndx);
405
406   // Return the section alignment.
407   uint64_t
408   do_section_addralign(unsigned int shndx);
409
410   // Return the Xindex structure to use.
411   Xindex*
412   do_initialize_xindex();
413
414   // Get symbol counts.
415   void
416   do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const;
417
418   // Get global symbols.
419   const Symbols*
420   do_get_global_symbols() const;
421
422   // Add placeholder symbols from a claimed file.
423   ld_plugin_status
424   add_symbols_from_plugin(int nsyms, const ld_plugin_symbol* syms);
425
426  protected:
427
428  private:
429 };
430
431 // This Task handles handles the "all symbols read" event hook.
432 // The plugin may add additional input files at this time, which must
433 // be queued for reading.
434
435 class Plugin_hook : public Task
436 {
437  public:
438   Plugin_hook(const General_options& options, Input_objects* input_objects,
439               Symbol_table* symtab, Layout* layout, Dirsearch* dirpath,
440               Mapfile* mapfile, Task_token* this_blocker,
441               Task_token* next_blocker)
442     : options_(options), input_objects_(input_objects), symtab_(symtab),
443       layout_(layout), dirpath_(dirpath), mapfile_(mapfile),
444       this_blocker_(this_blocker), next_blocker_(next_blocker)
445   { }
446
447   ~Plugin_hook();
448
449   // The standard Task methods.
450
451   Task_token*
452   is_runnable();
453
454   void
455   locks(Task_locker*);
456
457   void
458   run(Workqueue*);
459
460   std::string
461   get_name() const
462   { return "Plugin_hook"; }
463
464  private:
465   const General_options& options_;
466   Input_objects* input_objects_;
467   Symbol_table* symtab_;
468   Layout* layout_;
469   Dirsearch* dirpath_;
470   Mapfile* mapfile_;
471   Task_token* this_blocker_;
472   Task_token* next_blocker_;
473 };
474
475 } // End namespace gold.
476
477 #endif // !defined(GOLD_PLUGIN_H)