1// plugin.h -- plugin manager for gold      -*- C++ -*-
2
3// Copyright 2008, 2009, 2010, 2011 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
33namespace gold
34{
35
36class General_options;
37class Input_file;
38class Input_objects;
39class Archive;
40class Input_group;
41class Symbol;
42class Symbol_table;
43class Layout;
44class Dirsearch;
45class Mapfile;
46class Task;
47class Task_token;
48class Pluginobj;
49class Plugin_rescan;
50
51// This class represents a single plugin library.
52
53class Plugin
54{
55 public:
56  Plugin(const char* filename)
57    : handle_(NULL),
58      filename_(filename),
59      args_(),
60      claim_file_handler_(NULL),
61      all_symbols_read_handler_(NULL),
62      cleanup_handler_(NULL),
63      cleanup_done_(false)
64  { }
65
66  ~Plugin()
67  { }
68
69  // Load the library and call its entry point.
70  void
71  load();
72
73  // Call the claim-file handler.
74  bool
75  claim_file(struct ld_plugin_input_file* plugin_input_file);
76
77  // Call the all-symbols-read handler.
78  void
79  all_symbols_read();
80
81  // Call the cleanup handler.
82  void
83  cleanup();
84
85  // Register a claim-file handler.
86  void
87  set_claim_file_handler(ld_plugin_claim_file_handler handler)
88  { this->claim_file_handler_ = handler; }
89
90  // Register an all-symbols-read handler.
91  void
92  set_all_symbols_read_handler(ld_plugin_all_symbols_read_handler handler)
93  { this->all_symbols_read_handler_ = handler; }
94
95  // Register a claim-file handler.
96  void
97  set_cleanup_handler(ld_plugin_cleanup_handler handler)
98  { this->cleanup_handler_ = handler; }
99
100  // Add an argument
101  void
102  add_option(const char* arg)
103  {
104    this->args_.push_back(arg);
105  }
106
107 private:
108  Plugin(const Plugin&);
109  Plugin& operator=(const Plugin&);
110
111  // The shared library handle returned by dlopen.
112  void* handle_;
113  // The argument string given to --plugin.
114  std::string filename_;
115  // The list of argument string given to --plugin-opt.
116  std::vector<std::string> args_;
117  // The plugin's event handlers.
118  ld_plugin_claim_file_handler claim_file_handler_;
119  ld_plugin_all_symbols_read_handler all_symbols_read_handler_;
120  ld_plugin_cleanup_handler cleanup_handler_;
121  // TRUE if the cleanup handlers have been called.
122  bool cleanup_done_;
123};
124
125// A manager class for plugins.
126
127class Plugin_manager
128{
129 public:
130  Plugin_manager(const General_options& options)
131    : plugins_(), objects_(), deferred_layout_objects_(), input_file_(NULL),
132      plugin_input_file_(), rescannable_(), undefined_symbols_(),
133      any_claimed_(false), in_replacement_phase_(false), any_added_(false),
134      options_(options), workqueue_(NULL), task_(NULL), input_objects_(NULL),
135      symtab_(NULL), layout_(NULL), dirpath_(NULL), mapfile_(NULL),
136      this_blocker_(NULL), extra_search_path_()
137  { this->current_ = plugins_.end(); }
138
139  ~Plugin_manager();
140
141  // Add a plugin library.
142  void
143  add_plugin(const char* filename)
144  { this->plugins_.push_back(new Plugin(filename)); }
145
146  // Add an argument to the current plugin.
147  void
148  add_plugin_option(const char* opt)
149  {
150    Plugin* last = this->plugins_.back();
151    last->add_option(opt);
152  }
153
154  // Load all plugin libraries.
155  void
156  load_plugins();
157
158  // Call the plugin claim-file handlers in turn to see if any claim the file.
159  Pluginobj*
160  claim_file(Input_file* input_file, off_t offset, off_t filesize);
161
162  // Let the plugin manager save an archive for later rescanning.
163  // This takes ownership of the Archive pointer.
164  void
165  save_archive(Archive*);
166
167  // Let the plugin manager save an input group for later rescanning.
168  // This takes ownership of the Input_group pointer.
169  void
170  save_input_group(Input_group*);
171
172  // Call the all-symbols-read handlers.
173  void
174  all_symbols_read(Workqueue* workqueue, Task* task,
175                   Input_objects* input_objects, Symbol_table* symtab,
176                   Layout* layout, Dirsearch* dirpath, Mapfile* mapfile,
177                   Task_token** last_blocker);
178
179  // Tell the plugin manager that we've a new undefined symbol which
180  // may require rescanning.
181  void
182  new_undefined_symbol(Symbol*);
183
184  // Run deferred layout.
185  void
186  layout_deferred_objects();
187
188  // Call the cleanup handlers.
189  void
190  cleanup();
191
192  // Register a claim-file handler.
193  void
194  set_claim_file_handler(ld_plugin_claim_file_handler handler)
195  {
196    gold_assert(this->current_ != plugins_.end());
197    (*this->current_)->set_claim_file_handler(handler);
198  }
199
200  // Register an all-symbols-read handler.
201  void
202  set_all_symbols_read_handler(ld_plugin_all_symbols_read_handler handler)
203  {
204    gold_assert(this->current_ != plugins_.end());
205    (*this->current_)->set_all_symbols_read_handler(handler);
206  }
207
208  // Register a claim-file handler.
209  void
210  set_cleanup_handler(ld_plugin_cleanup_handler handler)
211  {
212    gold_assert(this->current_ != plugins_.end());
213    (*this->current_)->set_cleanup_handler(handler);
214  }
215
216  // Make a new Pluginobj object.  This is called when the plugin calls
217  // the add_symbols API.
218  Pluginobj*
219  make_plugin_object(unsigned int handle);
220
221  // Return the Pluginobj associated with the given HANDLE.
222  Pluginobj*
223  object(unsigned int handle) const
224  {
225    if (handle >= this->objects_.size())
226      return NULL;
227    return this->objects_[handle];
228  }
229
230  // Return TRUE if any input files have been claimed by a plugin
231  // and we are still in the initial input phase.
232  bool
233  should_defer_layout() const
234  { return !this->objects_.empty() && !this->in_replacement_phase_; }
235
236  // Add a regular object to the deferred layout list.  These are
237  // objects whose layout has been deferred until after the
238  // replacement files have arrived.
239  void
240  add_deferred_layout_object(Relobj* obj)
241  { this->deferred_layout_objects_.push_back(obj); }
242
243  // Get input file information with an open (possibly re-opened)
244  // file descriptor.
245  ld_plugin_status
246  get_input_file(unsigned int handle, struct ld_plugin_input_file* file);
247
248  // Release an input file.
249  ld_plugin_status
250  release_input_file(unsigned int handle);
251
252  // Add a new input file.
253  ld_plugin_status
254  add_input_file(const char* pathname, bool is_lib);
255
256  // Set the extra library path.
257  ld_plugin_status
258  set_extra_library_path(const char* path);
259
260  // Return TRUE if we are in the replacement phase.
261  bool
262  in_replacement_phase() const
263  { return this->in_replacement_phase_; }
264
265 private:
266  Plugin_manager(const Plugin_manager&);
267  Plugin_manager& operator=(const Plugin_manager&);
268
269  // Plugin_rescan is a Task which calls the private rescan method.
270  friend class Plugin_rescan;
271
272  // An archive or input group which may have to be rescanned if a
273  // plugin adds a new file.
274  struct Rescannable
275  {
276    bool is_archive;
277    union
278    {
279      Archive* archive;
280      Input_group* input_group;
281    } u;
282
283    Rescannable(Archive* archive)
284      : is_archive(true)
285    { this->u.archive = archive; }
286
287    Rescannable(Input_group* input_group)
288      : is_archive(false)
289    { this->u.input_group = input_group; }
290  };
291
292  typedef std::list<Plugin*> Plugin_list;
293  typedef std::vector<Pluginobj*> Object_list;
294  typedef std::vector<Relobj*> Deferred_layout_list;
295  typedef std::vector<Rescannable> Rescannable_list;
296  typedef std::vector<Symbol*> Undefined_symbol_list;
297
298  // Rescan archives for undefined symbols.
299  void
300  rescan(Task*);
301
302  // See whether the rescannable at index I defines SYM.
303  bool
304  rescannable_defines(size_t i, Symbol* sym);
305
306  // The list of plugin libraries.
307  Plugin_list plugins_;
308  // A pointer to the current plugin.  Used while loading plugins.
309  Plugin_list::iterator current_;
310
311  // The list of plugin objects.  The index of an item in this list
312  // serves as the "handle" that we pass to the plugins.
313  Object_list objects_;
314
315  // The list of regular objects whose layout has been deferred.
316  Deferred_layout_list deferred_layout_objects_;
317
318  // The file currently up for claim by the plugins.
319  Input_file* input_file_;
320  struct ld_plugin_input_file plugin_input_file_;
321
322  // A list of archives and input groups being saved for possible
323  // later rescanning.
324  Rescannable_list rescannable_;
325
326  // A list of undefined symbols found in added files.
327  Undefined_symbol_list undefined_symbols_;
328
329  // Whether any input files have been claimed by a plugin.
330  bool any_claimed_;
331
332  // Set to true after the all symbols read event; indicates that we
333  // are processing replacement files whose symbols should replace the
334  // placeholder symbols from the Pluginobj objects.
335  bool in_replacement_phase_;
336
337  // Whether any input files or libraries were added by a plugin.
338  bool any_added_;
339
340  const General_options& options_;
341  Workqueue* workqueue_;
342  Task* task_;
343  Input_objects* input_objects_;
344  Symbol_table* symtab_;
345  Layout* layout_;
346  Dirsearch* dirpath_;
347  Mapfile* mapfile_;
348  Task_token* this_blocker_;
349
350  // An extra directory to seach for the libraries passed by
351  // add_input_library.
352  std::string extra_search_path_;
353};
354
355
356// An object file claimed by a plugin.  This is an abstract base class.
357// The implementation is the template class Sized_pluginobj.
358
359class Pluginobj : public Object
360{
361 public:
362
363  typedef std::vector<Symbol*> Symbols;
364
365  Pluginobj(const std::string& name, Input_file* input_file, off_t offset,
366            off_t filesize);
367
368  // Fill in the symbol resolution status for the given plugin symbols.
369  ld_plugin_status
370  get_symbol_resolution_info(int nsyms, ld_plugin_symbol* syms) const;
371
372  // Store the incoming symbols from the plugin for later processing.
373  void
374  store_incoming_symbols(int nsyms, const struct ld_plugin_symbol* syms)
375  {
376    this->nsyms_ = nsyms;
377    this->syms_ = syms;
378  }
379
380  // Return TRUE if the comdat group with key COMDAT_KEY from this object
381  // should be kept.
382  bool
383  include_comdat_group(std::string comdat_key, Layout* layout);
384
385  // Return the filename.
386  const std::string&
387  filename() const
388  { return this->input_file()->filename(); }
389
390  // Return the file descriptor.
391  int
392  descriptor()
393  { return this->input_file()->file().descriptor(); }
394
395  // Return the size of the file or archive member.
396  off_t
397  filesize()
398  { return this->filesize_; }
399
400 protected:
401  // Return TRUE if this is an object claimed by a plugin.
402  virtual Pluginobj*
403  do_pluginobj()
404  { return this; }
405
406  // The number of symbols provided by the plugin.
407  int nsyms_;
408
409  // The symbols provided by the plugin.
410  const struct ld_plugin_symbol* syms_;
411
412  // The entries in the symbol table for the external symbols.
413  Symbols symbols_;
414
415 private:
416  // Size of the file (or archive member).
417  off_t filesize_;
418  // Map a comdat key symbol to a boolean indicating whether the comdat
419  // group in this object with that key should be kept.
420  typedef Unordered_map<std::string, bool> Comdat_map;
421  Comdat_map comdat_map_;
422};
423
424// A plugin object, size-specific version.
425
426template<int size, bool big_endian>
427class Sized_pluginobj : public Pluginobj
428{
429 public:
430  Sized_pluginobj(const std::string& name, Input_file* input_file,
431                  off_t offset, off_t filesize);
432
433  // Read the symbols.
434  void
435  do_read_symbols(Read_symbols_data*);
436
437  // Lay out the input sections.
438  void
439  do_layout(Symbol_table*, Layout*, Read_symbols_data*);
440
441  // Add the symbols to the symbol table.
442  void
443  do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*);
444
445  Archive::Should_include
446  do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*,
447                           std::string* why);
448
449  // Get the size of a section.
450  uint64_t
451  do_section_size(unsigned int shndx);
452
453  // Get the name of a section.
454  std::string
455  do_section_name(unsigned int shndx);
456
457  // Return a view of the contents of a section.
458  Object::Location
459  do_section_contents(unsigned int shndx);
460
461  // Return section flags.
462  uint64_t
463  do_section_flags(unsigned int shndx);
464
465  // Return section entsize.
466  uint64_t
467  do_section_entsize(unsigned int shndx);
468
469  // Return section address.
470  uint64_t
471  do_section_address(unsigned int shndx);
472
473  // Return section type.
474  unsigned int
475  do_section_type(unsigned int shndx);
476
477  // Return the section link field.
478  unsigned int
479  do_section_link(unsigned int shndx);
480
481  // Return the section link field.
482  unsigned int
483  do_section_info(unsigned int shndx);
484
485  // Return the section alignment.
486  uint64_t
487  do_section_addralign(unsigned int shndx);
488
489  // Return the Xindex structure to use.
490  Xindex*
491  do_initialize_xindex();
492
493  // Get symbol counts.
494  void
495  do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const;
496
497  // Get global symbols.
498  const Symbols*
499  do_get_global_symbols() const;
500
501  // Add placeholder symbols from a claimed file.
502  ld_plugin_status
503  add_symbols_from_plugin(int nsyms, const ld_plugin_symbol* syms);
504
505 protected:
506
507 private:
508};
509
510// This Task handles handles the "all symbols read" event hook.
511// The plugin may add additional input files at this time, which must
512// be queued for reading.
513
514class Plugin_hook : public Task
515{
516 public:
517  Plugin_hook(const General_options& options, Input_objects* input_objects,
518	      Symbol_table* symtab, Layout* layout, Dirsearch* dirpath,
519	      Mapfile* mapfile, Task_token* this_blocker,
520	      Task_token* next_blocker)
521    : options_(options), input_objects_(input_objects), symtab_(symtab),
522      layout_(layout), dirpath_(dirpath), mapfile_(mapfile),
523      this_blocker_(this_blocker), next_blocker_(next_blocker)
524  { }
525
526  ~Plugin_hook();
527
528  // The standard Task methods.
529
530  Task_token*
531  is_runnable();
532
533  void
534  locks(Task_locker*);
535
536  void
537  run(Workqueue*);
538
539  std::string
540  get_name() const
541  { return "Plugin_hook"; }
542
543 private:
544  const General_options& options_;
545  Input_objects* input_objects_;
546  Symbol_table* symtab_;
547  Layout* layout_;
548  Dirsearch* dirpath_;
549  Mapfile* mapfile_;
550  Task_token* this_blocker_;
551  Task_token* next_blocker_;
552};
553
554} // End namespace gold.
555
556#endif // !defined(GOLD_PLUGIN_H)
557