1// target-select.h -- select a target for an object file  -*- C++ -*-
2
3// Copyright (C) 2006-2017 Free Software Foundation, Inc.
4// Written by Ian Lance Taylor <iant@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_TARGET_SELECT_H
24#define GOLD_TARGET_SELECT_H
25
26#include <vector>
27
28#include "gold-threads.h"
29
30namespace gold
31{
32
33class Input_file;
34class Target;
35class Target_selector;
36
37// Used to set the target only once.
38
39class Set_target_once : public Once
40{
41 public:
42  Set_target_once(Target_selector* target_selector)
43    : target_selector_(target_selector)
44  { }
45
46 protected:
47  void
48  do_run_once(void*);
49
50 private:
51  Target_selector* target_selector_;
52};
53
54// We want to avoid a master list of targets, which implies using a
55// global constructor.  And we also want the program to start up as
56// quickly as possible, which implies avoiding global constructors.
57// We compromise on a very simple global constructor.  We use a target
58// selector, which specifies an ELF machine number and a recognition
59// function.  We use global constructors to build a linked list of
60// target selectors--a simple pointer list, not a std::list.
61
62class Target_selector
63{
64 public:
65  // Create a target selector for a specific machine number, size (32
66  // or 64), and endianness.  The machine number can be EM_NONE to
67  // test for any machine number.  BFD_NAME is the name of the target
68  // used by the GNU linker, for backward compatibility; it may be
69  // NULL.  EMULATION is the name of the emulation used by the GNU
70  // linker; it is similar to BFD_NAME.
71  Target_selector(int machine, int size, bool is_big_endian,
72		  const char* bfd_name, const char* emulation);
73
74  virtual ~Target_selector()
75  { }
76
77  // If we can handle this target, return a pointer to a target
78  // structure.  The size and endianness are known.
79  Target*
80  recognize(Input_file* input_file, off_t offset,
81	    int machine, int osabi, int abiversion)
82  { return this->do_recognize(input_file, offset, machine, osabi, abiversion); }
83
84  // If NAME matches the target, return a pointer to a target
85  // structure.
86  Target*
87  recognize_by_bfd_name(const char* name)
88  { return this->do_recognize_by_bfd_name(name); }
89
90  // Push all supported BFD names onto the vector.  This is only used
91  // for help output.
92  void
93  supported_bfd_names(std::vector<const char*>* names)
94  { this->do_supported_bfd_names(names); }
95
96  // If NAME matches the target emulation, return a pointer to a
97  // target structure.
98  Target*
99  recognize_by_emulation(const char* name)
100  { return this->do_recognize_by_emulation(name); }
101
102  // Push all supported emulations onto the vector.  This is only used
103  // for help output.
104  void
105  supported_emulations(std::vector<const char*>* names)
106  { this->do_supported_emulations(names); }
107
108  // Return the next Target_selector in the linked list.
109  Target_selector*
110  next() const
111  { return this->next_; }
112
113  // Return the machine number this selector is looking for.  This can
114  // be EM_NONE to match any machine number, in which case the
115  // do_recognize hook will be responsible for matching the machine
116  // number.
117  int
118  machine() const
119  { return this->machine_; }
120
121  // Return the size this is looking for (32 or 64).
122  int
123  get_size() const
124  { return this->size_; }
125
126  // Return the endianness this is looking for.
127  bool
128  is_big_endian() const
129  { return this->is_big_endian_; }
130
131  // Return the BFD name.  This may return NULL, in which case the
132  // do_recognize_by_bfd_name hook will be responsible for matching
133  // the BFD name.
134  const char*
135  bfd_name() const
136  { return this->bfd_name_; }
137
138  // Return the emulation.  This may return NULL, in which case the
139  // do_recognize_by_emulation hook will be responsible for matching
140  // the emulation.
141  const char*
142  emulation() const
143  { return this->emulation_; }
144
145  // The reverse mapping, for --print-output-format: if we
146  // instantiated TARGET, return our BFD_NAME.  If we did not
147  // instantiate it, return NULL.
148  const char*
149  target_bfd_name(const Target* target)
150  { return this->do_target_bfd_name(target); }
151
152 protected:
153  // Return an instance of the real target.  This must be implemented
154  // by the child class.
155  virtual Target*
156  do_instantiate_target() = 0;
157
158  // Recognize an object file given a machine code, OSABI code, and
159  // ELF version value.  When this is called we already know that they
160  // match the machine_, size_, and is_big_endian_ fields.  The child
161  // class may implement a different version of this to do additional
162  // checks, or to check for multiple machine codes if the machine_
163  // field is EM_NONE.
164  virtual Target*
165  do_recognize(Input_file*, off_t, int, int, int)
166  { return this->instantiate_target(); }
167
168  // Recognize a target by name.  When this is called we already know
169  // that the name matches (or that the bfd_name_ field is NULL).  The
170  // child class may implement a different version of this to
171  // recognize more than one name.
172  virtual Target*
173  do_recognize_by_bfd_name(const char*)
174  { return this->instantiate_target(); }
175
176  // Return a list of supported BFD names.  The child class may
177  // implement a different version of this to handle more than one
178  // name.
179  virtual void
180  do_supported_bfd_names(std::vector<const char*>* names)
181  {
182    gold_assert(this->bfd_name_ != NULL);
183    names->push_back(this->bfd_name_);
184  }
185
186  // Recognize a target by emulation.  When this is called we already
187  // know that the name matches (or that the emulation_ field is
188  // NULL).  The child class may implement a different version of this
189  // to recognize more than one emulation.
190  virtual Target*
191  do_recognize_by_emulation(const char*)
192  { return this->instantiate_target(); }
193
194  // Return a list of supported emulations.  The child class may
195  // implement a different version of this to handle more than one
196  // emulation.
197  virtual void
198  do_supported_emulations(std::vector<const char*>* emulations)
199  {
200    gold_assert(this->emulation_ != NULL);
201    emulations->push_back(this->emulation_);
202  }
203
204  // Map from target to BFD name.
205  virtual const char*
206  do_target_bfd_name(const Target*);
207
208  // Instantiate the target and return it.
209  Target*
210  instantiate_target();
211
212  // Return whether TARGET is the target we instantiated.
213  bool
214  is_our_target(const Target* target)
215  { return target == this->instantiated_target_; }
216
217 private:
218  // Set the target.
219  void
220  set_target();
221
222  friend class Set_target_once;
223
224  // ELF machine code.
225  const int machine_;
226  // Target size--32 or 64.
227  const int size_;
228  // Whether the target is big endian.
229  const bool is_big_endian_;
230  // BFD name of target, for compatibility.
231  const char* const bfd_name_;
232  // GNU linker emulation for this target, for compatibility.
233  const char* const emulation_;
234  // Next entry in list built at global constructor time.
235  Target_selector* next_;
236  // The singleton Target structure--this points to an instance of the
237  // real implementation.
238  Target* instantiated_target_;
239  // Used to set the target only once.
240  Set_target_once set_target_once_;
241};
242
243// Select the target for an ELF file.
244
245extern Target*
246select_target(Input_file*, off_t,
247	      int machine, int size, bool big_endian, int osabi,
248	      int abiversion);
249
250// Select a target using a BFD name.
251
252extern Target*
253select_target_by_bfd_name(const char* name);
254
255// Select a target using a GNU linker emulation.
256
257extern Target*
258select_target_by_emulation(const char* name);
259
260// Fill in a vector with the list of supported targets.  This returns
261// a list of BFD names.
262
263extern void
264supported_target_names(std::vector<const char*>*);
265
266// Fill in a vector with the list of supported emulations.
267
268extern void
269supported_emulation_names(std::vector<const char*>*);
270
271// Print the output format, for the --print-output-format option.
272
273extern void
274print_output_format();
275
276} // End namespace gold.
277
278#endif // !defined(GOLD_TARGET_SELECT_H)
279