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