1 // parameters.cc -- general parameters for a link using gold 2 3 // Copyright 2006, 2007, 2008, 2009, 2010 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 #include "gold.h" 24 25 #include "debug.h" 26 #include "options.h" 27 #include "target.h" 28 #include "target-select.h" 29 30 namespace gold 31 { 32 33 // Our local version of the variable, which is not const. 34 35 static Parameters static_parameters; 36 37 // The global variable. 38 39 const Parameters* parameters = &static_parameters; 40 41 // A helper class to set the target once. 42 43 class Set_parameters_target_once : public Once 44 { 45 public: 46 Set_parameters_target_once(Parameters* parameters) 47 : parameters_(parameters) 48 { } 49 50 protected: 51 void 52 do_run_once(void* arg) 53 { this->parameters_->set_target_once(static_cast<Target*>(arg)); } 54 55 private: 56 Parameters* parameters_; 57 }; 58 59 // We only need one Set_parameters_target_once. 60 61 static 62 Set_parameters_target_once set_parameters_target_once(&static_parameters); 63 64 // Class Parameters. 65 66 Parameters::Parameters() 67 : errors_(NULL), options_(NULL), target_(NULL), 68 doing_static_link_valid_(false), doing_static_link_(false), 69 debug_(0), incremental_mode_(General_options::INCREMENTAL_OFF), 70 set_parameters_target_once_(&set_parameters_target_once) 71 { 72 } 73 74 void 75 Parameters::set_errors(Errors* errors) 76 { 77 gold_assert(this->errors_ == NULL); 78 this->errors_ = errors; 79 } 80 81 void 82 Parameters::set_options(const General_options* options) 83 { 84 gold_assert(!this->options_valid()); 85 this->options_ = options; 86 // For speed, we convert the options() debug var from a string to an 87 // enum (from debug.h). 88 this->debug_ = debug_string_to_enum(this->options().debug()); 89 // Set incremental_mode_ based on the value of the --incremental option. 90 // We copy the mode into parameters because it can change based on inputs. 91 this->incremental_mode_ = this->options().incremental_mode(); 92 // If --verbose is set, it acts as "--debug=files". 93 if (options->verbose()) 94 this->debug_ |= DEBUG_FILES; 95 if (this->target_valid()) 96 this->check_target_endianness(); 97 } 98 99 void 100 Parameters::set_doing_static_link(bool doing_static_link) 101 { 102 gold_assert(!this->doing_static_link_valid_); 103 this->doing_static_link_ = doing_static_link; 104 this->doing_static_link_valid_ = true; 105 } 106 107 void 108 Parameters::set_target(Target* target) 109 { 110 this->set_parameters_target_once_->run_once(static_cast<void*>(target)); 111 gold_assert(target == this->target_); 112 } 113 114 // This is called at most once. 115 116 void 117 Parameters::set_target_once(Target* target) 118 { 119 gold_assert(this->target_ == NULL); 120 this->target_ = target; 121 if (this->options_valid()) 122 this->check_target_endianness(); 123 } 124 125 // Clear the target, for testing. 126 127 void 128 Parameters::clear_target() 129 { 130 this->target_ = NULL; 131 // We need a new Set_parameters_target_once so that we can set the 132 // target again. 133 this->set_parameters_target_once_ = new Set_parameters_target_once(this); 134 } 135 136 // Return whether TARGET is compatible with the target we are using. 137 138 bool 139 Parameters::is_compatible_target(const Target* target) const 140 { 141 if (this->target_ == NULL) 142 return true; 143 return target == this->target_; 144 } 145 146 Parameters::Target_size_endianness 147 Parameters::size_and_endianness() const 148 { 149 if (this->target().get_size() == 32) 150 { 151 if (!this->target().is_big_endian()) 152 { 153 #ifdef HAVE_TARGET_32_LITTLE 154 return TARGET_32_LITTLE; 155 #else 156 gold_unreachable(); 157 #endif 158 } 159 else 160 { 161 #ifdef HAVE_TARGET_32_BIG 162 return TARGET_32_BIG; 163 #else 164 gold_unreachable(); 165 #endif 166 } 167 } 168 else if (parameters->target().get_size() == 64) 169 { 170 if (!parameters->target().is_big_endian()) 171 { 172 #ifdef HAVE_TARGET_64_LITTLE 173 return TARGET_64_LITTLE; 174 #else 175 gold_unreachable(); 176 #endif 177 } 178 else 179 { 180 #ifdef HAVE_TARGET_64_BIG 181 return TARGET_64_BIG; 182 #else 183 gold_unreachable(); 184 #endif 185 } 186 } 187 else 188 gold_unreachable(); 189 } 190 191 // If output endianness is specified in command line, check that it does 192 // not conflict with the target. 193 194 void 195 Parameters::check_target_endianness() 196 { 197 General_options::Endianness endianness = this->options().endianness(); 198 if (endianness != General_options::ENDIANNESS_NOT_SET) 199 { 200 bool big_endian; 201 if (endianness == General_options::ENDIANNESS_BIG) 202 big_endian = true; 203 else 204 { 205 gold_assert(endianness == General_options::ENDIANNESS_LITTLE); 206 big_endian = false;; 207 } 208 209 if (this->target().is_big_endian() != big_endian) 210 gold_error(_("input file does not match -EB/EL option")); 211 } 212 } 213 214 // Set the incremental linking mode to INCREMENTAL_FULL. Used when 215 // the linker determines that an incremental update is not possible. 216 // Returns false if the incremental mode was INCREMENTAL_UPDATE, 217 // indicating that the linker should exit if an update is not possible. 218 219 bool 220 Parameters::set_incremental_full() 221 { 222 gold_assert(this->incremental_mode_ != General_options::INCREMENTAL_OFF); 223 if (this->incremental_mode_ == General_options::INCREMENTAL_UPDATE) 224 return false; 225 this->incremental_mode_ = General_options::INCREMENTAL_FULL; 226 return true; 227 } 228 229 // Return true if we need to prepare incremental linking information. 230 231 bool 232 Parameters::incremental() const 233 { 234 return this->incremental_mode_ != General_options::INCREMENTAL_OFF; 235 } 236 237 // Return true if we are doing an incremental update. 238 239 bool 240 Parameters::incremental_update() const 241 { 242 return (this->incremental_mode_ == General_options::INCREMENTAL_UPDATE 243 || this->incremental_mode_ == General_options::INCREMENTAL_AUTO); 244 } 245 246 void 247 set_parameters_errors(Errors* errors) 248 { static_parameters.set_errors(errors); } 249 250 void 251 set_parameters_options(const General_options* options) 252 { static_parameters.set_options(options); } 253 254 void 255 set_parameters_target(Target* target) 256 { 257 static_parameters.set_target(target); 258 target->select_as_default_target(); 259 } 260 261 void 262 set_parameters_doing_static_link(bool doing_static_link) 263 { static_parameters.set_doing_static_link(doing_static_link); } 264 265 // Set the incremental linking mode to INCREMENTAL_FULL. Used when 266 // the linker determines that an incremental update is not possible. 267 // Returns false if the incremental mode was INCREMENTAL_UPDATE, 268 // indicating that the linker should exit if an update is not possible. 269 bool 270 set_parameters_incremental_full() 271 { return static_parameters.set_incremental_full(); } 272 273 // Force the target to be valid by using the default. Use the 274 // --oformat option is set; this supports the x86_64 kernel build, 275 // which converts a binary file to an object file using -r --format 276 // binary --oformat elf32-i386 foo.o. Otherwise use the configured 277 // default. 278 279 void 280 parameters_force_valid_target() 281 { 282 if (parameters->target_valid()) 283 return; 284 285 gold_assert(parameters->options_valid()); 286 if (parameters->options().user_set_oformat()) 287 { 288 Target* target = select_target_by_name(parameters->options().oformat()); 289 if (target != NULL) 290 { 291 set_parameters_target(target); 292 return; 293 } 294 295 gold_error(_("unrecognized output format %s"), 296 parameters->options().oformat()); 297 } 298 299 // The GOLD_DEFAULT_xx macros are defined by the configure script. 300 bool is_big_endian; 301 General_options::Endianness endianness = parameters->options().endianness(); 302 if (endianness == General_options::ENDIANNESS_BIG) 303 is_big_endian = true; 304 else if (endianness == General_options::ENDIANNESS_LITTLE) 305 is_big_endian = false; 306 else 307 is_big_endian = GOLD_DEFAULT_BIG_ENDIAN; 308 309 Target* target = select_target(elfcpp::GOLD_DEFAULT_MACHINE, 310 GOLD_DEFAULT_SIZE, 311 is_big_endian, 312 elfcpp::GOLD_DEFAULT_OSABI, 313 0); 314 gold_assert(target != NULL); 315 set_parameters_target(target); 316 } 317 318 // Clear the current target, for testing. 319 320 void 321 parameters_clear_target() 322 { 323 static_parameters.clear_target(); 324 } 325 326 } // End namespace gold. 327