1 // readsyms.cc -- read input file symbols for gold 2 3 // Copyright 2006, 2007, 2008 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 <cstring> 26 27 #include "elfcpp.h" 28 #include "options.h" 29 #include "dirsearch.h" 30 #include "symtab.h" 31 #include "object.h" 32 #include "archive.h" 33 #include "script.h" 34 #include "readsyms.h" 35 36 namespace gold 37 { 38 39 // If we fail to open the object, then we won't create an Add_symbols 40 // task. However, we still need to unblock the token, or else the 41 // link won't proceed to generate more error messages. We can only 42 // unblock tokens when the workqueue lock is held, so we need a dummy 43 // task to do that. The dummy task has to maintain the right sequence 44 // of blocks, so we need both this_blocker and next_blocker. 45 46 class Unblock_token : public Task 47 { 48 public: 49 Unblock_token(Task_token* this_blocker, Task_token* next_blocker) 50 : this_blocker_(this_blocker), next_blocker_(next_blocker) 51 { } 52 53 ~Unblock_token() 54 { 55 if (this->this_blocker_ != NULL) 56 delete this->this_blocker_; 57 } 58 59 Task_token* 60 is_runnable() 61 { 62 if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked()) 63 return this->this_blocker_; 64 return NULL; 65 } 66 67 void 68 locks(Task_locker* tl) 69 { tl->add(this, this->next_blocker_); } 70 71 void 72 run(Workqueue*) 73 { } 74 75 std::string 76 get_name() const 77 { return "Unblock_token"; } 78 79 private: 80 Task_token* this_blocker_; 81 Task_token* next_blocker_; 82 }; 83 84 // Class read_symbols. 85 86 Read_symbols::~Read_symbols() 87 { 88 // The this_blocker_ and next_blocker_ pointers are passed on to the 89 // Add_symbols task. 90 } 91 92 // Return whether a Read_symbols task is runnable. We can read an 93 // ordinary input file immediately. For an archive specified using 94 // -l, we have to wait until the search path is complete. 95 96 Task_token* 97 Read_symbols::is_runnable() 98 { 99 if (this->input_argument_->is_file() 100 && this->input_argument_->file().may_need_search() 101 && this->dirpath_->token()->is_blocked()) 102 return this->dirpath_->token(); 103 104 return NULL; 105 } 106 107 // Return a Task_locker for a Read_symbols task. We don't need any 108 // locks here. 109 110 void 111 Read_symbols::locks(Task_locker*) 112 { 113 } 114 115 // Run a Read_symbols task. 116 117 void 118 Read_symbols::run(Workqueue* workqueue) 119 { 120 // If we didn't queue a new task, then we need to explicitly unblock 121 // the token. 122 if (!this->do_read_symbols(workqueue)) 123 workqueue->queue_soon(new Unblock_token(this->this_blocker_, 124 this->next_blocker_)); 125 } 126 127 // Open the file and read the symbols. Return true if a new task was 128 // queued, false if that could not happen due to some error. 129 130 bool 131 Read_symbols::do_read_symbols(Workqueue* workqueue) 132 { 133 if (this->input_argument_->is_group()) 134 { 135 gold_assert(this->input_group_ == NULL); 136 this->do_group(workqueue); 137 return true; 138 } 139 140 Input_file* input_file = new Input_file(&this->input_argument_->file()); 141 if (!input_file->open(this->options_, *this->dirpath_, this)) 142 return false; 143 144 // Read enough of the file to pick up the entire ELF header. 145 146 off_t filesize = input_file->file().filesize(); 147 148 if (filesize == 0) 149 { 150 gold_error(_("%s: file is empty"), 151 input_file->file().filename().c_str()); 152 return false; 153 } 154 155 int read_size = elfcpp::Elf_sizes<64>::ehdr_size; 156 if (filesize < read_size) 157 read_size = filesize; 158 159 const unsigned char* ehdr = input_file->file().get_view(0, 0, read_size, 160 true, false); 161 162 if (read_size >= 4) 163 { 164 static unsigned char elfmagic[4] = 165 { 166 elfcpp::ELFMAG0, elfcpp::ELFMAG1, 167 elfcpp::ELFMAG2, elfcpp::ELFMAG3 168 }; 169 if (memcmp(ehdr, elfmagic, 4) == 0) 170 { 171 // This is an ELF object. 172 173 Object* obj = make_elf_object(input_file->filename(), 174 input_file, 0, ehdr, read_size); 175 if (obj == NULL) 176 return false; 177 178 Read_symbols_data* sd = new Read_symbols_data; 179 obj->read_symbols(sd); 180 181 // Opening the file locked it, so now we need to unlock it. 182 // We need to unlock it before queuing the Add_symbols task, 183 // because the workqueue doesn't know about our lock on the 184 // file. If we queue the Add_symbols task first, it will be 185 // stuck on the end of the file lock, but since the 186 // workqueue doesn't know about that lock, it will never 187 // release the Add_symbols task. 188 189 input_file->file().unlock(this); 190 191 // We use queue_next because everything is cached for this 192 // task to run right away if possible. 193 194 workqueue->queue_next(new Add_symbols(this->input_objects_, 195 this->symtab_, this->layout_, 196 obj, sd, 197 this->this_blocker_, 198 this->next_blocker_)); 199 200 return true; 201 } 202 } 203 204 if (read_size >= Archive::sarmag) 205 { 206 bool is_thin_archive 207 = memcmp(ehdr, Archive::armagt, Archive::sarmag) == 0; 208 if (is_thin_archive 209 || memcmp(ehdr, Archive::armag, Archive::sarmag) == 0) 210 { 211 // This is an archive. 212 Archive* arch = new Archive(this->input_argument_->file().name(), 213 input_file, is_thin_archive, 214 this->dirpath_, this); 215 arch->setup(this->input_objects_); 216 217 // Unlock the archive so it can be used in the next task. 218 arch->unlock(this); 219 220 workqueue->queue_next(new Add_archive_symbols(this->symtab_, 221 this->layout_, 222 this->input_objects_, 223 this->mapfile_, 224 arch, 225 this->input_group_, 226 this->this_blocker_, 227 this->next_blocker_)); 228 return true; 229 } 230 } 231 232 // Queue up a task to try to parse this file as a script. We use a 233 // separate task so that the script will be read in order with other 234 // objects named on the command line. Also so that we don't try to 235 // read multiple scripts simultaneously, which could lead to 236 // unpredictable changes to the General_options structure. 237 238 workqueue->queue_soon(new Read_script(this->options_, 239 this->symtab_, 240 this->layout_, 241 this->dirpath_, 242 this->input_objects_, 243 this->mapfile_, 244 this->input_group_, 245 this->input_argument_, 246 input_file, 247 this->this_blocker_, 248 this->next_blocker_)); 249 return true; 250 } 251 252 // Handle a group. We need to walk through the arguments over and 253 // over until we don't see any new undefined symbols. We do this by 254 // setting off Read_symbols Tasks as usual, but recording the archive 255 // entries instead of deleting them. We also start a Finish_group 256 // Task which runs after we've read all the symbols. In that task we 257 // process the archives in a loop until we are done. 258 259 void 260 Read_symbols::do_group(Workqueue* workqueue) 261 { 262 Input_group* input_group = new Input_group(); 263 264 const Input_file_group* group = this->input_argument_->group(); 265 Task_token* this_blocker = this->this_blocker_; 266 267 for (Input_file_group::const_iterator p = group->begin(); 268 p != group->end(); 269 ++p) 270 { 271 const Input_argument* arg = &*p; 272 gold_assert(arg->is_file()); 273 274 Task_token* next_blocker = new Task_token(true); 275 next_blocker->add_blocker(); 276 workqueue->queue_soon(new Read_symbols(this->options_, 277 this->input_objects_, 278 this->symtab_, this->layout_, 279 this->dirpath_, this->mapfile_, 280 arg, input_group, 281 this_blocker, next_blocker)); 282 this_blocker = next_blocker; 283 } 284 285 const int saw_undefined = this->symtab_->saw_undefined(); 286 workqueue->queue_soon(new Finish_group(this->input_objects_, 287 this->symtab_, 288 this->layout_, 289 this->mapfile_, 290 input_group, 291 saw_undefined, 292 this_blocker, 293 this->next_blocker_)); 294 } 295 296 // Return a debugging name for a Read_symbols task. 297 298 std::string 299 Read_symbols::get_name() const 300 { 301 if (!this->input_argument_->is_group()) 302 { 303 std::string ret("Read_symbols "); 304 if (this->input_argument_->file().is_lib()) 305 ret += "-l"; 306 ret += this->input_argument_->file().name(); 307 return ret; 308 } 309 310 std::string ret("Read_symbols group ("); 311 bool add_space = false; 312 const Input_file_group* group = this->input_argument_->group(); 313 for (Input_file_group::const_iterator p = group->begin(); 314 p != group->end(); 315 ++p) 316 { 317 if (add_space) 318 ret += ' '; 319 ret += p->file().name(); 320 add_space = true; 321 } 322 return ret + ')'; 323 } 324 325 // Class Add_symbols. 326 327 Add_symbols::~Add_symbols() 328 { 329 if (this->this_blocker_ != NULL) 330 delete this->this_blocker_; 331 // next_blocker_ is deleted by the task associated with the next 332 // input file. 333 } 334 335 // We are blocked by this_blocker_. We block next_blocker_. We also 336 // lock the file. 337 338 Task_token* 339 Add_symbols::is_runnable() 340 { 341 if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked()) 342 return this->this_blocker_; 343 if (this->object_->is_locked()) 344 return this->object_->token(); 345 return NULL; 346 } 347 348 void 349 Add_symbols::locks(Task_locker* tl) 350 { 351 tl->add(this, this->next_blocker_); 352 tl->add(this, this->object_->token()); 353 } 354 355 // Add the symbols in the object to the symbol table. 356 357 void 358 Add_symbols::run(Workqueue*) 359 { 360 if (!this->input_objects_->add_object(this->object_)) 361 { 362 // FIXME: We need to close the descriptor here. 363 delete this->object_; 364 } 365 else 366 { 367 this->object_->layout(this->symtab_, this->layout_, this->sd_); 368 this->object_->add_symbols(this->symtab_, this->sd_); 369 this->object_->release(); 370 } 371 delete this->sd_; 372 this->sd_ = NULL; 373 } 374 375 // Class Finish_group. 376 377 Finish_group::~Finish_group() 378 { 379 if (this->this_blocker_ != NULL) 380 delete this->this_blocker_; 381 // next_blocker_ is deleted by the task associated with the next 382 // input file following the group. 383 } 384 385 // We need to wait for THIS_BLOCKER_ and unblock NEXT_BLOCKER_. 386 387 Task_token* 388 Finish_group::is_runnable() 389 { 390 if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked()) 391 return this->this_blocker_; 392 return NULL; 393 } 394 395 void 396 Finish_group::locks(Task_locker* tl) 397 { 398 tl->add(this, this->next_blocker_); 399 } 400 401 // Loop over the archives until there are no new undefined symbols. 402 403 void 404 Finish_group::run(Workqueue*) 405 { 406 int saw_undefined = this->saw_undefined_; 407 while (saw_undefined != this->symtab_->saw_undefined()) 408 { 409 saw_undefined = this->symtab_->saw_undefined(); 410 411 for (Input_group::const_iterator p = this->input_group_->begin(); 412 p != this->input_group_->end(); 413 ++p) 414 { 415 Task_lock_obj<Archive> tl(this, *p); 416 417 (*p)->add_symbols(this->symtab_, this->layout_, 418 this->input_objects_, this->mapfile_); 419 } 420 } 421 422 // Delete all the archives now that we no longer need them. 423 for (Input_group::const_iterator p = this->input_group_->begin(); 424 p != this->input_group_->end(); 425 ++p) 426 delete *p; 427 delete this->input_group_; 428 } 429 430 // Class Read_script 431 432 Read_script::~Read_script() 433 { 434 if (this->this_blocker_ != NULL) 435 delete this->this_blocker_; 436 // next_blocker_ is deleted by the task associated with the next 437 // input file. 438 } 439 440 // We are blocked by this_blocker_. 441 442 Task_token* 443 Read_script::is_runnable() 444 { 445 if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked()) 446 return this->this_blocker_; 447 return NULL; 448 } 449 450 // We don't unlock next_blocker_ here. If the script names any input 451 // files, then the last file will be responsible for unlocking it. 452 453 void 454 Read_script::locks(Task_locker*) 455 { 456 } 457 458 // Read the script, if it is a script. 459 460 void 461 Read_script::run(Workqueue* workqueue) 462 { 463 bool used_next_blocker; 464 if (!read_input_script(workqueue, this->options_, this->symtab_, 465 this->layout_, this->dirpath_, this->input_objects_, 466 this->mapfile_, this->input_group_, 467 this->input_argument_, this->input_file_, 468 this->next_blocker_, &used_next_blocker)) 469 { 470 // Here we have to handle any other input file types we need. 471 gold_error(_("%s: not an object or archive"), 472 this->input_file_->file().filename().c_str()); 473 } 474 475 if (!used_next_blocker) 476 { 477 // Queue up a task to unlock next_blocker. We can't just unlock 478 // it here, as we don't hold the workqueue lock. 479 workqueue->queue_soon(new Unblock_token(NULL, this->next_blocker_)); 480 } 481 } 482 483 // Return a debugging name for a Read_script task. 484 485 std::string 486 Read_script::get_name() const 487 { 488 std::string ret("Read_script "); 489 if (this->input_argument_->file().is_lib()) 490 ret += "-l"; 491 ret += this->input_argument_->file().name(); 492 return ret; 493 } 494 495 } // End namespace gold. 496