1 // target-select.h -- select a target for an object file -*- C++ -*- 2 3 // Copyright (C) 2006-2014 Free Software Foundation, Inc. 4 // Written by Ian Lance Taylor <iant (at) 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 30 namespace gold 31 { 32 33 class Input_file; 34 class Target; 35 class Target_selector; 36 37 // Used to set the target only once. 38 39 class 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 62 class 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 245 extern Target* 246 select_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 252 extern Target* 253 select_target_by_bfd_name(const char* name); 254 255 // Select a target using a GNU linker emulation. 256 257 extern Target* 258 select_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 263 extern void 264 supported_target_names(std::vector<const char*>*); 265 266 // Fill in a vector with the list of supported emulations. 267 268 extern void 269 supported_emulation_names(std::vector<const char*>*); 270 271 // Print the output format, for the --print-output-format option. 272 273 extern void 274 print_output_format(); 275 276 } // End namespace gold. 277 278 #endif // !defined(GOLD_TARGET_SELECT_H) 279