gold/ChangeLog:
[platform/upstream/binutils.git] / gold / plugin.cc
1 // plugin.c -- plugin manager for gold      -*- C++ -*-
2
3 // Copyright 2008 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 #include <cstdio>
24 #include <cstdarg>
25 #include <cstring>
26 #include <string>
27 #include <vector>
28 #include <dlfcn.h>
29
30 #include "gold.h"
31 #include "parameters.h"
32 #include "errors.h"
33 #include "fileread.h"
34 #include "layout.h"
35 #include "options.h"
36 #include "plugin.h"
37 #include "target.h"
38 #include "readsyms.h"
39 #include "symtab.h"
40 #include "elfcpp.h"
41
42 namespace gold
43 {
44
45 #ifdef ENABLE_PLUGINS
46
47 // The linker's exported interfaces.
48
49 extern "C"
50 {
51
52 static enum ld_plugin_status
53 register_claim_file(ld_plugin_claim_file_handler handler);
54
55 static enum ld_plugin_status
56 register_all_symbols_read(ld_plugin_all_symbols_read_handler handler);
57
58 static enum ld_plugin_status
59 register_cleanup(ld_plugin_cleanup_handler handler);
60
61 static enum ld_plugin_status
62 add_symbols(void *handle, int nsyms, const struct ld_plugin_symbol *syms);
63
64 static enum ld_plugin_status
65 get_symbols(const void *handle, int nsyms, struct ld_plugin_symbol *syms);
66
67 static enum ld_plugin_status
68 add_input_file(char *pathname);
69
70 static enum ld_plugin_status
71 message(int level, const char *format, ...);
72
73 };
74
75 #endif // ENABLE_PLUGINS
76
77 static Pluginobj* make_sized_plugin_object(Input_file* input_file,
78                                            off_t offset);
79
80 // Plugin methods.
81
82 // Load one plugin library.
83
84 void
85 Plugin::load()
86 {
87 #ifdef ENABLE_PLUGINS
88   std::string filename;
89   std::vector<std::string> args;
90
91   // Parse the filename and arguments, each separated by commas.
92   // FIXME:  Temporarily allowing semicolon as an argument separator
93   // so args can be passed through gcc's -Wl,... option, which
94   // breaks arguments at the commas.
95   const char* p = this->args_;
96   int n = strcspn(p, ",;");
97   filename.assign(p, n);
98   p += n;
99   while (*p == ',' || *p == ';')
100     {
101       ++p;
102       n = strcspn(p, ",;");
103       args.push_back(std::string(p, n));
104       p += n;
105     }
106
107   // Load the plugin library.
108   // FIXME: Look for the library in standard locations.
109   this->handle_ = dlopen(filename.c_str(), RTLD_NOW);
110   if (this->handle_ == NULL)
111     {
112       gold_error(_("%s: could not load plugin library"), filename.c_str());
113       return;
114     }
115
116   // Find the plugin's onload entry point.
117   ld_plugin_onload onload = reinterpret_cast<ld_plugin_onload>
118     (dlsym(this->handle_, "onload"));
119   if (onload == NULL)
120     {
121       gold_error(_("%s: could not find onload entry point"), filename.c_str());
122       return;
123     }
124
125   // Get the linker's version number.
126   const char* ver = get_version_string();
127   int major = 0;
128   int minor = 0;
129   sscanf(ver, "%d.%d", &major, &minor);
130
131   // Allocate and populate a transfer vector.
132   const int tv_fixed_size = 11;
133   int tv_size = args.size() + tv_fixed_size;
134   ld_plugin_tv *tv = new ld_plugin_tv[tv_size];
135
136   int i = 0;
137   tv[i].tv_tag = LDPT_API_VERSION;
138   tv[i].tv_u.tv_val = LD_PLUGIN_API_VERSION;
139
140   ++i;
141   tv[i].tv_tag = LDPT_GOLD_VERSION;
142   tv[i].tv_u.tv_val = major * 100 + minor;
143
144   ++i;
145   tv[i].tv_tag = LDPT_LINKER_OUTPUT;
146   if (parameters->options().relocatable())
147     tv[i].tv_u.tv_val = LDPO_REL;
148   else if (parameters->options().shared())
149     tv[i].tv_u.tv_val = LDPO_DYN;
150   else
151     tv[i].tv_u.tv_val = LDPO_EXEC;
152
153   for (unsigned int j = 0; j < args.size(); ++j)
154     {
155       ++i;
156       tv[i].tv_tag = LDPT_OPTION;
157       tv[i].tv_u.tv_string = args[j].c_str();
158     }
159
160   ++i;
161   tv[i].tv_tag = LDPT_REGISTER_CLAIM_FILE_HOOK;
162   tv[i].tv_u.tv_register_claim_file = register_claim_file;
163
164   ++i;
165   tv[i].tv_tag = LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK;
166   tv[i].tv_u.tv_register_all_symbols_read = register_all_symbols_read;
167
168   ++i;
169   tv[i].tv_tag = LDPT_REGISTER_CLEANUP_HOOK;
170   tv[i].tv_u.tv_register_cleanup = register_cleanup;
171
172   ++i;
173   tv[i].tv_tag = LDPT_ADD_SYMBOLS;
174   tv[i].tv_u.tv_add_symbols = add_symbols;
175
176   ++i;
177   tv[i].tv_tag = LDPT_GET_SYMBOLS;
178   tv[i].tv_u.tv_get_symbols = get_symbols;
179
180   ++i;
181   tv[i].tv_tag = LDPT_ADD_INPUT_FILE;
182   tv[i].tv_u.tv_add_input_file = add_input_file;
183
184   ++i;
185   tv[i].tv_tag = LDPT_MESSAGE;
186   tv[i].tv_u.tv_message = message;
187
188   ++i;
189   tv[i].tv_tag = LDPT_NULL;
190   tv[i].tv_u.tv_val = 0;
191
192   gold_assert(i == tv_size - 1);
193
194   // Call the onload entry point.
195   (*onload)(tv);
196
197   delete[] tv;
198 #endif // ENABLE_PLUGINS
199 }
200
201 // Call the plugin claim-file handler.
202
203 inline bool
204 Plugin::claim_file(struct ld_plugin_input_file *plugin_input_file)
205 {
206   int claimed = 0;
207
208   if (this->claim_file_handler_ != NULL)
209     {
210       (*this->claim_file_handler_)(plugin_input_file, &claimed);
211       if (claimed)
212         return true;
213     }
214   return false;
215 }
216
217 // Call the all-symbols-read handler.
218
219 inline void
220 Plugin::all_symbols_read()
221 {
222   if (this->all_symbols_read_handler_ != NULL)
223     (*this->all_symbols_read_handler_)();
224 }
225
226 // Call the cleanup handler.
227
228 inline void
229 Plugin::cleanup()
230 {
231   if (this->cleanup_handler_ != NULL)
232     (*this->cleanup_handler_)();
233 }
234
235 // Plugin_manager methods.
236
237 Plugin_manager::~Plugin_manager()
238 {
239   for (Plugin_list::iterator p = this->plugins_.begin();
240        p != this->plugins_.end();
241        ++p)
242     delete *p;
243   this->plugins_.clear();
244   for (Object_list::iterator obj = this->objects_.begin();
245        obj != this->objects_.end();
246        ++obj)
247     delete *obj;
248   this->objects_.clear();
249 }
250
251 // Load all plugin libraries.
252
253 void
254 Plugin_manager::load_plugins()
255 {
256   for (this->current_ = this->plugins_.begin();
257        this->current_ != this->plugins_.end();
258        ++this->current_)
259     (*this->current_)->load();
260 }
261
262 // Call the plugin claim-file handlers in turn to see if any claim the file.
263
264 Pluginobj*
265 Plugin_manager::claim_file(Input_file* input_file, off_t offset,
266                            off_t filesize)
267 {
268   if (this->in_replacement_phase_)
269     return NULL;
270
271   unsigned int handle = this->objects_.size();
272   this->input_file_ = input_file;
273   this->plugin_input_file_.name = input_file->filename().c_str();
274   this->plugin_input_file_.fd = input_file->file().descriptor();
275   this->plugin_input_file_.offset = offset;
276   this->plugin_input_file_.filesize = filesize;
277   this->plugin_input_file_.handle = reinterpret_cast<void*>(handle);
278
279   for (this->current_ = this->plugins_.begin();
280        this->current_ != this->plugins_.end();
281        ++this->current_)
282     {
283       if ((*this->current_)->claim_file(&this->plugin_input_file_))
284         {
285           if (this->objects_.size() <= handle)
286             {
287               gold_error(_("%s: plugin claimed the file "
288                            "but did not provide any symbols"),
289                          this->plugin_input_file_.name);
290               return NULL;
291             }
292           return this->objects_[handle];
293         }
294     }
295
296   return NULL;
297 }
298
299 // Call the all-symbols-read handlers.
300
301 void
302 Plugin_manager::all_symbols_read(Workqueue* workqueue,
303                                  Input_objects* input_objects,
304                                  Symbol_table* symtab, Layout* layout,
305                                  Dirsearch* dirpath, Mapfile* mapfile,
306                                  Task_token** last_blocker)
307 {
308   this->in_replacement_phase_ = true;
309   this->workqueue_ = workqueue;
310   this->input_objects_ = input_objects;
311   this->symtab_ = symtab;
312   this->layout_ = layout;
313   this->dirpath_ = dirpath;
314   this->mapfile_ = mapfile;
315   this->this_blocker_ = NULL;
316
317   for (this->current_ = this->plugins_.begin();
318        this->current_ != this->plugins_.end();
319        ++this->current_)
320     (*this->current_)->all_symbols_read();
321
322   *last_blocker = this->this_blocker_;
323 }
324
325 // Call the cleanup handlers.
326
327 void
328 Plugin_manager::cleanup()
329 {
330   for (this->current_ = this->plugins_.begin();
331        this->current_ != this->plugins_.end();
332        ++this->current_)
333     (*this->current_)->cleanup();
334 }
335
336 // Make a new Pluginobj object.  This is called when the plugin calls
337 // the add_symbols API.
338
339 Pluginobj*
340 Plugin_manager::make_plugin_object(unsigned int handle)
341 {
342   // Make sure we aren't asked to make an object for the same handle twice.
343   if (this->objects_.size() != handle)
344     return NULL;
345
346   Pluginobj* obj = make_sized_plugin_object(this->input_file_,
347                                             this->plugin_input_file_.offset);
348   this->objects_.push_back(obj);
349   return obj;
350 }
351
352 // Add a new input file.
353
354 ld_plugin_status
355 Plugin_manager::add_input_file(char *pathname)
356 {
357   Input_file_argument file(pathname, false, "", false, this->options_);
358   Input_argument* input_argument = new Input_argument(file);
359   Task_token* next_blocker = new Task_token(true);
360   next_blocker->add_blocker();
361   this->workqueue_->queue_soon(new Read_symbols(this->options_,
362                                                 this->input_objects_,
363                                                 this->symtab_,
364                                                 this->layout_,
365                                                 this->dirpath_,
366                                                 this->mapfile_,
367                                                 input_argument,
368                                                 NULL,
369                                                 this->this_blocker_,
370                                                 next_blocker));
371   this->this_blocker_ = next_blocker;
372   return LDPS_OK;
373 }
374
375 // Class Pluginobj.
376
377 Pluginobj::Pluginobj(const std::string& name, Input_file* input_file,
378                      off_t offset)
379   : Object(name, input_file, false, offset),
380     nsyms_(0), syms_(NULL), symbols_(), comdat_map_()
381 {
382 }
383
384 // Get symbol resolution info.
385
386 ld_plugin_status
387 Pluginobj::get_symbol_resolution_info(int nsyms, ld_plugin_symbol* syms) const
388 {
389   if (this->nsyms_ == 0)
390     return LDPS_NO_SYMS;
391   for (int i = 0; i < nsyms; i++)
392     {
393       ld_plugin_symbol* isym = &syms[i];
394       Symbol* lsym = this->symbols_[i];
395       ld_plugin_symbol_resolution res = LDPR_UNKNOWN;
396
397       if (lsym->is_undefined())
398         // The symbol remains undefined.
399         res = LDPR_UNDEF;
400       else if (isym->def == LDPK_UNDEF
401                || isym->def == LDPK_WEAKUNDEF
402                || isym->def == LDPK_COMMON)
403         {
404           // The original symbol was undefined or common.
405           if (lsym->source() != Symbol::FROM_OBJECT)
406             res = LDPR_RESOLVED_EXEC;
407           else if (lsym->object()->pluginobj() != NULL)
408             res = LDPR_RESOLVED_IR;
409           else if (lsym->object()->is_dynamic())
410             res = LDPR_RESOLVED_DYN;
411           else
412             res = LDPR_RESOLVED_EXEC;
413         }
414       else
415         {
416           // The original symbol was a definition.
417           if (lsym->source() != Symbol::FROM_OBJECT)
418             res = LDPR_PREEMPTED_REG;
419           else if (lsym->object() == static_cast<const Object*>(this))
420             res = (lsym->in_real_elf()
421                    ? LDPR_PREVAILING_DEF
422                    : LDPR_PREVAILING_DEF_IRONLY);
423           else
424             res = (lsym->object()->pluginobj() != NULL
425                    ? LDPR_PREEMPTED_IR
426                    : LDPR_PREEMPTED_REG);
427         }
428       isym->resolution = res;
429     }
430   return LDPS_OK;
431 }
432
433 // Return TRUE if the comdat group with key COMDAT_KEY from this object
434 // should be kept.
435
436 bool
437 Pluginobj::include_comdat_group(std::string comdat_key, Layout* layout)
438 {
439   std::pair<Comdat_map::iterator, bool> ins =
440     this->comdat_map_.insert(std::make_pair(comdat_key, false));
441
442   // If this is the first time we've seen this comdat key, ask the
443   // layout object whether it should be included.
444   if (ins.second)
445     ins.first->second = layout->add_comdat(NULL, 1, comdat_key, true);
446
447   return ins.first->second;
448 }
449
450 // Class Sized_pluginobj.
451
452 template<int size, bool big_endian>
453 Sized_pluginobj<size, big_endian>::Sized_pluginobj(
454     const std::string& name,
455     Input_file* input_file,
456     off_t offset)
457   : Pluginobj(name, input_file, offset)
458 {
459 }
460
461 // Read the symbols.  Not used for plugin objects.
462
463 template<int size, bool big_endian>
464 void
465 Sized_pluginobj<size, big_endian>::do_read_symbols(Read_symbols_data*)
466 {
467   gold_unreachable();
468 }
469
470 // Lay out the input sections.  Not used for plugin objects.
471
472 template<int size, bool big_endian>
473 void
474 Sized_pluginobj<size, big_endian>::do_layout(Symbol_table*, Layout*,
475                                              Read_symbols_data*)
476 {
477   gold_unreachable();
478 }
479
480 // Add the symbols to the symbol table.
481
482 template<int size, bool big_endian>
483 void
484 Sized_pluginobj<size, big_endian>::do_add_symbols(Symbol_table*,
485                                                   Read_symbols_data*)
486 {
487   gold_unreachable();
488 }
489
490 template<int size, bool big_endian>
491 void
492 Sized_pluginobj<size, big_endian>::do_add_symbols(Symbol_table* symtab,
493                                                   Layout* layout)
494 {
495   const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
496   unsigned char symbuf[sym_size];
497   elfcpp::Sym<size, big_endian> sym(symbuf);
498   elfcpp::Sym_write<size, big_endian> osym(symbuf);
499
500   typedef typename elfcpp::Elf_types<size>::Elf_WXword Elf_size_type;
501
502   this->symbols_.resize(this->nsyms_);
503
504   for (int i = 0; i < this->nsyms_; ++i)
505     {
506       const struct ld_plugin_symbol *isym = &this->syms_[i];
507       const char* name = isym->name;
508       const char* ver = isym->version;
509       elfcpp::Elf_Half shndx;
510       elfcpp::STB bind;
511       elfcpp::STV vis;
512
513       if (name != NULL && name[0] == '\0')
514         name = NULL;
515       if (ver != NULL && ver[0] == '\0')
516         ver = NULL;
517
518       switch (isym->def)
519         {
520         case LDPK_WEAKDEF:
521         case LDPK_WEAKUNDEF:
522           bind = elfcpp::STB_WEAK;
523           break;
524         case LDPK_DEF:
525         case LDPK_UNDEF:
526         case LDPK_COMMON:
527         default:
528           bind = elfcpp::STB_GLOBAL;
529           break;
530         }
531
532       switch (isym->def)
533         {
534         case LDPK_DEF:
535         case LDPK_WEAKDEF:
536           shndx = elfcpp::SHN_ABS;
537           break;
538         case LDPK_COMMON:
539           shndx = elfcpp::SHN_COMMON;
540           break;
541         case LDPK_UNDEF:
542         case LDPK_WEAKUNDEF:
543         default:
544           shndx = elfcpp::SHN_UNDEF;
545           break;
546         }
547
548       switch (isym->visibility)
549         {
550         case LDPV_PROTECTED:
551           vis = elfcpp::STV_DEFAULT;
552           break;
553         case LDPV_INTERNAL:
554           vis = elfcpp::STV_DEFAULT;
555           break;
556         case LDPV_HIDDEN:
557           vis = elfcpp::STV_DEFAULT;
558           break;
559         case LDPV_DEFAULT:
560         default:
561           vis = elfcpp::STV_DEFAULT;
562           break;
563         }
564
565       if (isym->comdat_key != NULL
566           && isym->comdat_key[0] != '\0'
567           && !this->include_comdat_group(isym->comdat_key, layout))
568         shndx = elfcpp::SHN_UNDEF;
569
570       osym.put_st_name(0);
571       osym.put_st_value(0);
572       osym.put_st_size(static_cast<Elf_size_type>(isym->size));
573       osym.put_st_info(bind, elfcpp::STT_NOTYPE);
574       osym.put_st_other(vis, 0);
575       osym.put_st_shndx(shndx);
576
577       this->symbols_[i] =
578         symtab->add_from_pluginobj<size, big_endian>(this, name, ver, &sym);
579     }
580 }
581
582 // Get the size of a section.  Not used for plugin objects.
583
584 template<int size, bool big_endian>
585 uint64_t
586 Sized_pluginobj<size, big_endian>::do_section_size(unsigned int)
587 {
588   gold_unreachable();
589   return 0;
590 }
591
592 // Get the name of a section.  Not used for plugin objects.
593
594 template<int size, bool big_endian>
595 std::string
596 Sized_pluginobj<size, big_endian>::do_section_name(unsigned int)
597 {
598   gold_unreachable();
599   return std::string();
600 }
601
602 // Return a view of the contents of a section.  Not used for plugin objects.
603
604 template<int size, bool big_endian>
605 Object::Location
606 Sized_pluginobj<size, big_endian>::do_section_contents(unsigned int)
607 {
608   Location loc(0, 0);
609
610   gold_unreachable();
611   return loc;
612 }
613
614 // Return section flags.  Not used for plugin objects.
615
616 template<int size, bool big_endian>
617 uint64_t
618 Sized_pluginobj<size, big_endian>::do_section_flags(unsigned int)
619 {
620   gold_unreachable();
621   return 0;
622 }
623
624 // Return section address.  Not used for plugin objects.
625
626 template<int size, bool big_endian>
627 uint64_t
628 Sized_pluginobj<size, big_endian>::do_section_address(unsigned int)
629 {
630   gold_unreachable();
631   return 0;
632 }
633
634 // Return section type.  Not used for plugin objects.
635
636 template<int size, bool big_endian>
637 unsigned int
638 Sized_pluginobj<size, big_endian>::do_section_type(unsigned int)
639 {
640   gold_unreachable();
641   return 0;
642 }
643
644 // Return the section link field.  Not used for plugin objects.
645
646 template<int size, bool big_endian>
647 unsigned int
648 Sized_pluginobj<size, big_endian>::do_section_link(unsigned int)
649 {
650   gold_unreachable();
651   return 0;
652 }
653
654 // Return the section link field.  Not used for plugin objects.
655
656 template<int size, bool big_endian>
657 unsigned int
658 Sized_pluginobj<size, big_endian>::do_section_info(unsigned int)
659 {
660   gold_unreachable();
661   return 0;
662 }
663
664 // Return the section alignment.  Not used for plugin objects.
665
666 template<int size, bool big_endian>
667 uint64_t
668 Sized_pluginobj<size, big_endian>::do_section_addralign(unsigned int)
669 {
670   gold_unreachable();
671   return 0;
672 }
673
674 // Return the Xindex structure to use.  Not used for plugin objects.
675
676 template<int size, bool big_endian>
677 Xindex*
678 Sized_pluginobj<size, big_endian>::do_initialize_xindex()
679 {
680   gold_unreachable();
681   return NULL;
682 }
683
684 // Get symbol counts.  Not used for plugin objects.
685
686 template<int size, bool big_endian>
687 void
688 Sized_pluginobj<size, big_endian>::do_get_global_symbol_counts(const Symbol_table*,
689                                                    size_t*, size_t*) const
690 {
691   gold_unreachable();
692 }
693
694 // Class Add_plugin_symbols.
695
696 Add_plugin_symbols::~Add_plugin_symbols()
697 {
698   if (this->this_blocker_ != NULL)
699     delete this->this_blocker_;
700   // next_blocker_ is deleted by the task associated with the next
701   // input file.
702 }
703
704 // We are blocked by this_blocker_.  We block next_blocker_.  We also
705 // lock the file.
706
707 Task_token*
708 Add_plugin_symbols::is_runnable()
709 {
710   if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
711     return this->this_blocker_;
712   if (this->obj_->is_locked())
713     return this->obj_->token();
714   return NULL;
715 }
716
717 void
718 Add_plugin_symbols::locks(Task_locker* tl)
719 {
720   tl->add(this, this->next_blocker_);
721   tl->add(this, this->obj_->token());
722 }
723
724 // Add the symbols in the object to the symbol table.
725
726 void
727 Add_plugin_symbols::run(Workqueue*)
728 {
729   this->obj_->add_symbols(this->symtab_, this->layout_);
730 }
731
732 // Class Plugin_cleanup.  This task calls the plugin cleanup hooks once all
733 // replacement files have been added.
734
735 class Plugin_cleanup : public Task
736 {
737  public:
738   Plugin_cleanup(Task_token* this_blocker, Task_token* next_blocker)
739     : this_blocker_(this_blocker), next_blocker_(next_blocker)
740   { }
741
742   ~Plugin_cleanup()
743   {
744     if (this->this_blocker_ != NULL)
745       delete this->this_blocker_;
746   }
747
748   Task_token*
749   is_runnable()
750   {
751     if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
752       return this->this_blocker_;
753     return NULL;
754   }
755
756   void
757   locks(Task_locker* tl)
758   { tl->add(this, this->next_blocker_); }
759
760   void
761   run(Workqueue*)
762   { parameters->options().plugins()->cleanup(); }
763
764   std::string
765   get_name() const
766   { return "Plugin_cleanup"; }
767
768  private:
769   Task_token* this_blocker_;
770   Task_token* next_blocker_;
771 };
772
773 // Class Plugin_hook.
774
775 Plugin_hook::~Plugin_hook()
776 {
777 }
778
779 // Return whether a Plugin_hook task is runnable.
780
781 Task_token*
782 Plugin_hook::is_runnable()
783 {
784   if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
785     return this->this_blocker_;
786   return NULL;
787 }
788
789 // Return a Task_locker for a Plugin_hook task.  We don't need any
790 // locks here.
791
792 void
793 Plugin_hook::locks(Task_locker*)
794 {
795 }
796
797 // Run a Plugin_hook task.
798
799 void
800 Plugin_hook::run(Workqueue* workqueue)
801 {
802   this->do_plugin_hook(workqueue);
803 }
804
805 // Run the "all symbols read" plugin hook.
806
807 void
808 Plugin_hook::do_plugin_hook(Workqueue* workqueue)
809 {
810   gold_assert(this->options_.has_plugins());
811   this->options_.plugins()->all_symbols_read(workqueue,
812                                              this->input_objects_,
813                                              this->symtab_,
814                                              this->layout_,
815                                              this->dirpath_,
816                                              this->mapfile_,
817                                              &this->this_blocker_);
818   workqueue->queue_soon(new Plugin_cleanup(this->this_blocker_,
819                                            this->next_blocker_));
820 }
821
822 // The C interface routines called by the plugins.
823
824 #ifdef ENABLE_PLUGINS
825
826 // Register a claim-file handler.
827
828 static enum ld_plugin_status
829 register_claim_file(ld_plugin_claim_file_handler handler)
830 {
831   gold_assert(parameters->options().has_plugins());
832   parameters->options().plugins()->set_claim_file_handler(handler);
833   return LDPS_OK;
834 }
835
836 // Register an all-symbols-read handler.
837
838 static enum ld_plugin_status
839 register_all_symbols_read(ld_plugin_all_symbols_read_handler handler)
840 {
841   gold_assert(parameters->options().has_plugins());
842   parameters->options().plugins()->set_all_symbols_read_handler(handler);
843   return LDPS_OK;
844 }
845
846 // Register a cleanup handler.
847
848 static enum ld_plugin_status
849 register_cleanup(ld_plugin_cleanup_handler handler)
850 {
851   gold_assert(parameters->options().has_plugins());
852   parameters->options().plugins()->set_cleanup_handler(handler);
853   return LDPS_OK;
854 }
855
856 // Add symbols from a plugin-claimed input file.
857
858 static enum ld_plugin_status
859 add_symbols(void* handle, int nsyms, const ld_plugin_symbol *syms)
860 {
861   gold_assert(parameters->options().has_plugins());
862   Pluginobj* obj = parameters->options().plugins()->make_plugin_object(
863       static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle)));
864   if (obj == NULL)
865     return LDPS_ERR;
866   obj->store_incoming_symbols(nsyms, syms);
867   return LDPS_OK;
868 }
869
870 // Get the symbol resolution info for a plugin-claimed input file.
871
872 static enum ld_plugin_status
873 get_symbols(const void * handle, int nsyms, ld_plugin_symbol* syms)
874 {
875   gold_assert(parameters->options().has_plugins());
876   Pluginobj* obj = parameters->options().plugins()->object(
877       static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle)));
878   if (obj == NULL)
879     return LDPS_ERR;
880   return obj->get_symbol_resolution_info(nsyms, syms);
881 }
882
883 // Add a new (real) input file generated by a plugin.
884
885 static enum ld_plugin_status
886 add_input_file(char *pathname)
887 {
888   gold_assert(parameters->options().has_plugins());
889   return parameters->options().plugins()->add_input_file(pathname);
890 }
891
892 // Issue a diagnostic message from a plugin.
893
894 static enum ld_plugin_status
895 message(int level, const char * format, ...)
896 {
897   va_list args;
898   va_start(args, format);
899
900   switch (level)
901     {
902     case LDPL_INFO:
903       parameters->errors()->info(format, args);
904       break;
905     case LDPL_WARNING:
906       parameters->errors()->warning(format, args);
907       break;
908     case LDPL_ERROR:
909     default:
910       parameters->errors()->error(format, args);
911       break;
912     case LDPL_FATAL:
913       parameters->errors()->fatal(format, args);
914       break;
915     }
916
917   va_end(args);
918   return LDPS_OK;
919 }
920
921 #endif // ENABLE_PLUGINS
922
923 // Allocate a Pluginobj object of the appropriate size and endianness.
924
925 static Pluginobj*
926 make_sized_plugin_object(Input_file* input_file, off_t offset)
927 {
928   Target* target;
929   Pluginobj* obj = NULL;
930
931   if (parameters->target_valid())
932     target = const_cast<Target*>(&parameters->target());
933   else
934     target = const_cast<Target*>(&parameters->default_target());
935
936   if (target->get_size() == 32)
937     {
938       if (target->is_big_endian())
939 #ifdef HAVE_TARGET_32_BIG
940         obj = new Sized_pluginobj<32, true>(input_file->filename(),
941                                             input_file, offset);
942 #else
943         gold_error(_("%s: not configured to support "
944                      "32-bit big-endian object"),
945                    input_file->filename().c_str());
946 #endif
947       else
948 #ifdef HAVE_TARGET_32_LITTLE
949         obj = new Sized_pluginobj<32, false>(input_file->filename(),
950                                              input_file, offset);
951 #else
952         gold_error(_("%s: not configured to support "
953                      "32-bit little-endian object"),
954                    input_file->filename().c_str());
955 #endif
956     }
957   else if (target->get_size() == 64)
958     {
959       if (target->is_big_endian())
960 #ifdef HAVE_TARGET_64_BIG
961         obj = new Sized_pluginobj<64, true>(input_file->filename(),
962                                             input_file, offset);
963 #else
964         gold_error(_("%s: not configured to support "
965                      "64-bit big-endian object"),
966                    input_file->filename().c_str());
967 #endif
968       else
969 #ifdef HAVE_TARGET_64_LITTLE
970         obj = new Sized_pluginobj<64, false>(input_file->filename(),
971                                              input_file, offset);
972 #else
973         gold_error(_("%s: not configured to support "
974                      "64-bit little-endian object"),
975                    input_file->filename().c_str());
976 #endif
977     }
978
979   gold_assert(obj != NULL);
980   obj->set_target(target);
981   return obj;
982 }
983
984 } // End namespace gold.