| 1 |
27 |
khays |
// readsyms.cc -- read input file symbols for gold
|
| 2 |
|
|
|
| 3 |
|
|
// Copyright 2006, 2007, 2008, 2009, 2010, 2011 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 |
|
|
#include "plugin.h"
|
| 36 |
|
|
#include "layout.h"
|
| 37 |
|
|
#include "incremental.h"
|
| 38 |
|
|
|
| 39 |
|
|
namespace gold
|
| 40 |
|
|
{
|
| 41 |
|
|
|
| 42 |
|
|
// If we fail to open the object, then we won't create an Add_symbols
|
| 43 |
|
|
// task. However, we still need to unblock the token, or else the
|
| 44 |
|
|
// link won't proceed to generate more error messages. We can only
|
| 45 |
|
|
// unblock tokens when the workqueue lock is held, so we need a dummy
|
| 46 |
|
|
// task to do that. The dummy task has to maintain the right sequence
|
| 47 |
|
|
// of blocks, so we need both this_blocker and next_blocker.
|
| 48 |
|
|
|
| 49 |
|
|
class Unblock_token : public Task
|
| 50 |
|
|
{
|
| 51 |
|
|
public:
|
| 52 |
|
|
Unblock_token(Task_token* this_blocker, Task_token* next_blocker)
|
| 53 |
|
|
: this_blocker_(this_blocker), next_blocker_(next_blocker)
|
| 54 |
|
|
{ }
|
| 55 |
|
|
|
| 56 |
|
|
~Unblock_token()
|
| 57 |
|
|
{
|
| 58 |
|
|
if (this->this_blocker_ != NULL)
|
| 59 |
|
|
delete this->this_blocker_;
|
| 60 |
|
|
}
|
| 61 |
|
|
|
| 62 |
|
|
Task_token*
|
| 63 |
|
|
is_runnable()
|
| 64 |
|
|
{
|
| 65 |
|
|
if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
|
| 66 |
|
|
return this->this_blocker_;
|
| 67 |
|
|
return NULL;
|
| 68 |
|
|
}
|
| 69 |
|
|
|
| 70 |
|
|
void
|
| 71 |
|
|
locks(Task_locker* tl)
|
| 72 |
|
|
{ tl->add(this, this->next_blocker_); }
|
| 73 |
|
|
|
| 74 |
|
|
void
|
| 75 |
|
|
run(Workqueue*)
|
| 76 |
|
|
{ }
|
| 77 |
|
|
|
| 78 |
|
|
std::string
|
| 79 |
|
|
get_name() const
|
| 80 |
|
|
{ return "Unblock_token"; }
|
| 81 |
|
|
|
| 82 |
|
|
private:
|
| 83 |
|
|
Task_token* this_blocker_;
|
| 84 |
|
|
Task_token* next_blocker_;
|
| 85 |
|
|
};
|
| 86 |
|
|
|
| 87 |
|
|
// Class read_symbols.
|
| 88 |
|
|
|
| 89 |
|
|
Read_symbols::~Read_symbols()
|
| 90 |
|
|
{
|
| 91 |
|
|
// The this_blocker_ and next_blocker_ pointers are passed on to the
|
| 92 |
|
|
// Add_symbols task.
|
| 93 |
|
|
}
|
| 94 |
|
|
|
| 95 |
|
|
// If appropriate, issue a warning about skipping an incompatible
|
| 96 |
|
|
// file.
|
| 97 |
|
|
|
| 98 |
|
|
void
|
| 99 |
|
|
Read_symbols::incompatible_warning(const Input_argument* input_argument,
|
| 100 |
|
|
const Input_file* input_file)
|
| 101 |
|
|
{
|
| 102 |
|
|
if (parameters->options().warn_search_mismatch())
|
| 103 |
|
|
gold_warning("skipping incompatible %s while searching for %s",
|
| 104 |
|
|
input_file->filename().c_str(),
|
| 105 |
|
|
input_argument->file().name());
|
| 106 |
|
|
}
|
| 107 |
|
|
|
| 108 |
|
|
// Requeue a Read_symbols task to search for the next object with the
|
| 109 |
|
|
// same name.
|
| 110 |
|
|
|
| 111 |
|
|
void
|
| 112 |
|
|
Read_symbols::requeue(Workqueue* workqueue, Input_objects* input_objects,
|
| 113 |
|
|
Symbol_table* symtab, Layout* layout, Dirsearch* dirpath,
|
| 114 |
|
|
int dirindex, Mapfile* mapfile,
|
| 115 |
|
|
const Input_argument* input_argument,
|
| 116 |
|
|
Input_group* input_group, Task_token* next_blocker)
|
| 117 |
|
|
{
|
| 118 |
|
|
// Bump the directory search index.
|
| 119 |
|
|
++dirindex;
|
| 120 |
|
|
|
| 121 |
|
|
// We don't need to worry about this_blocker, since we already
|
| 122 |
|
|
// reached it. However, we are removing the blocker on next_blocker
|
| 123 |
|
|
// because the calling task is completing. So we need to add a new
|
| 124 |
|
|
// blocker. Since next_blocker may be shared by several tasks, we
|
| 125 |
|
|
// need to increment the count with the workqueue lock held.
|
| 126 |
|
|
workqueue->add_blocker(next_blocker);
|
| 127 |
|
|
|
| 128 |
|
|
workqueue->queue(new Read_symbols(input_objects, symtab, layout, dirpath,
|
| 129 |
|
|
dirindex, mapfile, input_argument,
|
| 130 |
|
|
input_group, NULL, NULL, next_blocker));
|
| 131 |
|
|
}
|
| 132 |
|
|
|
| 133 |
|
|
// Return whether a Read_symbols task is runnable. We can read an
|
| 134 |
|
|
// ordinary input file immediately. For an archive specified using
|
| 135 |
|
|
// -l, we have to wait until the search path is complete.
|
| 136 |
|
|
|
| 137 |
|
|
Task_token*
|
| 138 |
|
|
Read_symbols::is_runnable()
|
| 139 |
|
|
{
|
| 140 |
|
|
if (this->input_argument_->is_file()
|
| 141 |
|
|
&& this->input_argument_->file().may_need_search()
|
| 142 |
|
|
&& this->dirpath_->token()->is_blocked())
|
| 143 |
|
|
return this->dirpath_->token();
|
| 144 |
|
|
|
| 145 |
|
|
return NULL;
|
| 146 |
|
|
}
|
| 147 |
|
|
|
| 148 |
|
|
// Return a Task_locker for a Read_symbols task. We don't need any
|
| 149 |
|
|
// locks here.
|
| 150 |
|
|
|
| 151 |
|
|
void
|
| 152 |
|
|
Read_symbols::locks(Task_locker* tl)
|
| 153 |
|
|
{
|
| 154 |
|
|
if (this->member_ != NULL)
|
| 155 |
|
|
tl->add(this, this->next_blocker_);
|
| 156 |
|
|
}
|
| 157 |
|
|
|
| 158 |
|
|
// Run a Read_symbols task.
|
| 159 |
|
|
|
| 160 |
|
|
void
|
| 161 |
|
|
Read_symbols::run(Workqueue* workqueue)
|
| 162 |
|
|
{
|
| 163 |
|
|
// If we didn't queue a new task, then we need to explicitly unblock
|
| 164 |
163 |
khays |
// the token. If the object is a member of a lib group, however,
|
| 165 |
|
|
// the token was already added to the list of locks for the task,
|
| 166 |
|
|
// and it will be unblocked automatically at the end of the task.
|
| 167 |
|
|
if (!this->do_read_symbols(workqueue) && this->member_ == NULL)
|
| 168 |
27 |
khays |
workqueue->queue_soon(new Unblock_token(this->this_blocker_,
|
| 169 |
|
|
this->next_blocker_));
|
| 170 |
|
|
}
|
| 171 |
|
|
|
| 172 |
|
|
// Handle a whole lib group. Other than collecting statistics, this just
|
| 173 |
|
|
// mimics what we do for regular object files in the command line.
|
| 174 |
|
|
|
| 175 |
|
|
bool
|
| 176 |
|
|
Read_symbols::do_whole_lib_group(Workqueue* workqueue)
|
| 177 |
|
|
{
|
| 178 |
|
|
const Input_file_lib* lib_group = this->input_argument_->lib();
|
| 179 |
|
|
|
| 180 |
|
|
++Lib_group::total_lib_groups;
|
| 181 |
|
|
|
| 182 |
|
|
Task_token* this_blocker = this->this_blocker_;
|
| 183 |
|
|
for (Input_file_lib::const_iterator i = lib_group->begin();
|
| 184 |
|
|
i != lib_group->end();
|
| 185 |
|
|
++i)
|
| 186 |
|
|
{
|
| 187 |
|
|
++Lib_group::total_members;
|
| 188 |
|
|
++Lib_group::total_members_loaded;
|
| 189 |
|
|
|
| 190 |
|
|
const Input_argument* arg = &*i;
|
| 191 |
|
|
|
| 192 |
|
|
Task_token* next_blocker;
|
| 193 |
|
|
if (i != lib_group->end() - 1)
|
| 194 |
|
|
{
|
| 195 |
|
|
next_blocker = new Task_token(true);
|
| 196 |
|
|
next_blocker->add_blocker();
|
| 197 |
|
|
}
|
| 198 |
|
|
else
|
| 199 |
|
|
next_blocker = this->next_blocker_;
|
| 200 |
|
|
|
| 201 |
|
|
workqueue->queue_soon(new Read_symbols(this->input_objects_,
|
| 202 |
|
|
this->symtab_, this->layout_,
|
| 203 |
|
|
this->dirpath_, this->dirindex_,
|
| 204 |
|
|
this->mapfile_, arg, NULL,
|
| 205 |
|
|
NULL, this_blocker, next_blocker));
|
| 206 |
|
|
this_blocker = next_blocker;
|
| 207 |
|
|
}
|
| 208 |
|
|
|
| 209 |
|
|
return true;
|
| 210 |
|
|
}
|
| 211 |
|
|
|
| 212 |
|
|
// Handle a lib group. We set Read_symbols Tasks as usual, but have them
|
| 213 |
|
|
// just record the symbol data instead of adding the objects. We also start
|
| 214 |
|
|
// a Add_lib_group_symbols Task which runs after we've read all the symbols.
|
| 215 |
|
|
// In that task we process the members in a loop until we are done.
|
| 216 |
|
|
|
| 217 |
|
|
bool
|
| 218 |
|
|
Read_symbols::do_lib_group(Workqueue* workqueue)
|
| 219 |
|
|
{
|
| 220 |
|
|
const Input_file_lib* lib_group = this->input_argument_->lib();
|
| 221 |
|
|
|
| 222 |
|
|
if (lib_group->options().whole_archive())
|
| 223 |
|
|
return this->do_whole_lib_group(workqueue);
|
| 224 |
|
|
|
| 225 |
|
|
Lib_group* lib = new Lib_group(lib_group, this);
|
| 226 |
|
|
|
| 227 |
|
|
Add_lib_group_symbols* add_lib_group_symbols =
|
| 228 |
|
|
new Add_lib_group_symbols(this->symtab_, this->layout_,
|
| 229 |
|
|
this->input_objects_,
|
| 230 |
|
|
lib, this->next_blocker_);
|
| 231 |
|
|
|
| 232 |
|
|
|
| 233 |
|
|
Task_token* next_blocker = new Task_token(true);
|
| 234 |
|
|
int j = 0;
|
| 235 |
|
|
for (Input_file_lib::const_iterator i = lib_group->begin();
|
| 236 |
|
|
i != lib_group->end();
|
| 237 |
|
|
++i, ++j)
|
| 238 |
|
|
{
|
| 239 |
|
|
const Input_argument* arg = &*i;
|
| 240 |
|
|
Archive_member* m = lib->get_member(j);
|
| 241 |
|
|
|
| 242 |
|
|
next_blocker->add_blocker();
|
| 243 |
|
|
|
| 244 |
|
|
// Since this Read_symbols will not create an Add_symbols,
|
| 245 |
|
|
// just pass NULL as this_blocker.
|
| 246 |
|
|
workqueue->queue_soon(new Read_symbols(this->input_objects_,
|
| 247 |
|
|
this->symtab_, this->layout_,
|
| 248 |
|
|
this->dirpath_, this->dirindex_,
|
| 249 |
|
|
this->mapfile_, arg, NULL,
|
| 250 |
|
|
m, NULL, next_blocker));
|
| 251 |
|
|
}
|
| 252 |
|
|
|
| 253 |
|
|
add_lib_group_symbols->set_blocker(next_blocker, this->this_blocker_);
|
| 254 |
|
|
workqueue->queue_soon(add_lib_group_symbols);
|
| 255 |
|
|
|
| 256 |
|
|
return true;
|
| 257 |
|
|
}
|
| 258 |
|
|
|
| 259 |
|
|
// Open the file and read the symbols. Return true if a new task was
|
| 260 |
|
|
// queued, false if that could not happen due to some error.
|
| 261 |
|
|
|
| 262 |
|
|
bool
|
| 263 |
|
|
Read_symbols::do_read_symbols(Workqueue* workqueue)
|
| 264 |
|
|
{
|
| 265 |
|
|
if (this->input_argument_->is_group())
|
| 266 |
|
|
{
|
| 267 |
|
|
gold_assert(this->input_group_ == NULL);
|
| 268 |
|
|
this->do_group(workqueue);
|
| 269 |
|
|
return true;
|
| 270 |
|
|
}
|
| 271 |
|
|
|
| 272 |
|
|
if (this->input_argument_->is_lib())
|
| 273 |
|
|
return this->do_lib_group(workqueue);
|
| 274 |
|
|
|
| 275 |
|
|
Input_file* input_file = new Input_file(&this->input_argument_->file());
|
| 276 |
|
|
if (!input_file->open(*this->dirpath_, this, &this->dirindex_))
|
| 277 |
|
|
return false;
|
| 278 |
|
|
|
| 279 |
|
|
// Read enough of the file to pick up the entire ELF header.
|
| 280 |
|
|
|
| 281 |
|
|
off_t filesize = input_file->file().filesize();
|
| 282 |
|
|
|
| 283 |
|
|
if (filesize == 0)
|
| 284 |
|
|
{
|
| 285 |
|
|
gold_error(_("%s: file is empty"),
|
| 286 |
|
|
input_file->file().filename().c_str());
|
| 287 |
|
|
return false;
|
| 288 |
|
|
}
|
| 289 |
|
|
|
| 290 |
|
|
const unsigned char* ehdr;
|
| 291 |
|
|
int read_size;
|
| 292 |
|
|
bool is_elf = is_elf_object(input_file, 0, &ehdr, &read_size);
|
| 293 |
|
|
|
| 294 |
|
|
if (read_size >= Archive::sarmag)
|
| 295 |
|
|
{
|
| 296 |
|
|
bool is_thin_archive
|
| 297 |
|
|
= memcmp(ehdr, Archive::armagt, Archive::sarmag) == 0;
|
| 298 |
|
|
if (is_thin_archive
|
| 299 |
|
|
|| memcmp(ehdr, Archive::armag, Archive::sarmag) == 0)
|
| 300 |
|
|
{
|
| 301 |
|
|
// This is an archive.
|
| 302 |
|
|
Archive* arch = new Archive(this->input_argument_->file().name(),
|
| 303 |
|
|
input_file, is_thin_archive,
|
| 304 |
|
|
this->dirpath_, this);
|
| 305 |
|
|
arch->setup();
|
| 306 |
|
|
|
| 307 |
|
|
// Unlock the archive so it can be used in the next task.
|
| 308 |
|
|
arch->unlock(this);
|
| 309 |
|
|
|
| 310 |
|
|
workqueue->queue_next(new Add_archive_symbols(this->symtab_,
|
| 311 |
|
|
this->layout_,
|
| 312 |
|
|
this->input_objects_,
|
| 313 |
|
|
this->dirpath_,
|
| 314 |
|
|
this->dirindex_,
|
| 315 |
|
|
this->mapfile_,
|
| 316 |
|
|
this->input_argument_,
|
| 317 |
|
|
arch,
|
| 318 |
|
|
this->input_group_,
|
| 319 |
|
|
this->this_blocker_,
|
| 320 |
|
|
this->next_blocker_));
|
| 321 |
|
|
return true;
|
| 322 |
|
|
}
|
| 323 |
|
|
}
|
| 324 |
|
|
|
| 325 |
159 |
khays |
Object* elf_obj = NULL;
|
| 326 |
|
|
bool unconfigured;
|
| 327 |
|
|
bool* punconfigured = NULL;
|
| 328 |
|
|
if (is_elf)
|
| 329 |
|
|
{
|
| 330 |
|
|
// This is an ELF object.
|
| 331 |
|
|
|
| 332 |
|
|
unconfigured = false;
|
| 333 |
|
|
punconfigured = (input_file->will_search_for()
|
| 334 |
|
|
? &unconfigured
|
| 335 |
|
|
: NULL);
|
| 336 |
|
|
elf_obj = make_elf_object(input_file->filename(),
|
| 337 |
|
|
input_file, 0, ehdr, read_size,
|
| 338 |
|
|
punconfigured);
|
| 339 |
|
|
}
|
| 340 |
|
|
|
| 341 |
27 |
khays |
if (parameters->options().has_plugins())
|
| 342 |
|
|
{
|
| 343 |
|
|
Pluginobj* obj = parameters->options().plugins()->claim_file(input_file,
|
| 344 |
159 |
khays |
0, filesize,
|
| 345 |
|
|
elf_obj);
|
| 346 |
27 |
khays |
if (obj != NULL)
|
| 347 |
|
|
{
|
| 348 |
159 |
khays |
// Delete the elf_obj, this file has been claimed.
|
| 349 |
|
|
if (elf_obj != NULL)
|
| 350 |
|
|
delete elf_obj;
|
| 351 |
|
|
|
| 352 |
27 |
khays |
// The input file was claimed by a plugin, and its symbols
|
| 353 |
|
|
// have been provided by the plugin.
|
| 354 |
|
|
|
| 355 |
|
|
// We are done with the file at this point, so unlock it.
|
| 356 |
|
|
obj->unlock(this);
|
| 357 |
|
|
|
| 358 |
|
|
if (this->member_ != NULL)
|
| 359 |
|
|
{
|
| 360 |
|
|
this->member_->sd_ = NULL;
|
| 361 |
|
|
this->member_->obj_ = obj;
|
| 362 |
|
|
return true;
|
| 363 |
|
|
}
|
| 364 |
|
|
|
| 365 |
|
|
workqueue->queue_next(new Add_symbols(this->input_objects_,
|
| 366 |
|
|
this->symtab_,
|
| 367 |
|
|
this->layout_,
|
| 368 |
|
|
this->dirpath_,
|
| 369 |
|
|
this->dirindex_,
|
| 370 |
|
|
this->mapfile_,
|
| 371 |
|
|
this->input_argument_,
|
| 372 |
|
|
obj,
|
| 373 |
|
|
NULL,
|
| 374 |
|
|
NULL,
|
| 375 |
|
|
this->this_blocker_,
|
| 376 |
|
|
this->next_blocker_));
|
| 377 |
|
|
return true;
|
| 378 |
|
|
}
|
| 379 |
|
|
}
|
| 380 |
|
|
|
| 381 |
|
|
if (is_elf)
|
| 382 |
|
|
{
|
| 383 |
|
|
// This is an ELF object.
|
| 384 |
|
|
|
| 385 |
159 |
khays |
if (elf_obj == NULL)
|
| 386 |
27 |
khays |
{
|
| 387 |
|
|
if (unconfigured)
|
| 388 |
|
|
{
|
| 389 |
|
|
Read_symbols::incompatible_warning(this->input_argument_,
|
| 390 |
|
|
input_file);
|
| 391 |
|
|
input_file->file().release();
|
| 392 |
|
|
input_file->file().unlock(this);
|
| 393 |
|
|
delete input_file;
|
| 394 |
|
|
++this->dirindex_;
|
| 395 |
|
|
return this->do_read_symbols(workqueue);
|
| 396 |
|
|
}
|
| 397 |
|
|
return false;
|
| 398 |
|
|
}
|
| 399 |
|
|
|
| 400 |
|
|
Read_symbols_data* sd = new Read_symbols_data;
|
| 401 |
159 |
khays |
elf_obj->read_symbols(sd);
|
| 402 |
27 |
khays |
|
| 403 |
|
|
// Opening the file locked it, so now we need to unlock it. We
|
| 404 |
|
|
// need to unlock it before queuing the Add_symbols task,
|
| 405 |
|
|
// because the workqueue doesn't know about our lock on the
|
| 406 |
|
|
// file. If we queue the Add_symbols task first, it will be
|
| 407 |
|
|
// stuck on the end of the file lock, but since the workqueue
|
| 408 |
|
|
// doesn't know about that lock, it will never release the
|
| 409 |
|
|
// Add_symbols task.
|
| 410 |
|
|
|
| 411 |
|
|
input_file->file().unlock(this);
|
| 412 |
|
|
|
| 413 |
|
|
if (this->member_ != NULL)
|
| 414 |
|
|
{
|
| 415 |
|
|
this->member_->sd_ = sd;
|
| 416 |
159 |
khays |
this->member_->obj_ = elf_obj;
|
| 417 |
27 |
khays |
this->member_->arg_serial_ =
|
| 418 |
|
|
this->input_argument_->file().arg_serial();
|
| 419 |
|
|
return true;
|
| 420 |
|
|
}
|
| 421 |
|
|
|
| 422 |
|
|
// We use queue_next because everything is cached for this
|
| 423 |
|
|
// task to run right away if possible.
|
| 424 |
|
|
|
| 425 |
|
|
workqueue->queue_next(new Add_symbols(this->input_objects_,
|
| 426 |
|
|
this->symtab_, this->layout_,
|
| 427 |
|
|
this->dirpath_,
|
| 428 |
|
|
this->dirindex_,
|
| 429 |
|
|
this->mapfile_,
|
| 430 |
|
|
this->input_argument_,
|
| 431 |
159 |
khays |
elf_obj,
|
| 432 |
27 |
khays |
NULL,
|
| 433 |
|
|
sd,
|
| 434 |
|
|
this->this_blocker_,
|
| 435 |
|
|
this->next_blocker_));
|
| 436 |
|
|
|
| 437 |
|
|
return true;
|
| 438 |
|
|
}
|
| 439 |
|
|
|
| 440 |
|
|
// Queue up a task to try to parse this file as a script. We use a
|
| 441 |
|
|
// separate task so that the script will be read in order with other
|
| 442 |
|
|
// objects named on the command line. Also so that we don't try to
|
| 443 |
|
|
// read multiple scripts simultaneously, which could lead to
|
| 444 |
|
|
// unpredictable changes to the General_options structure.
|
| 445 |
|
|
|
| 446 |
|
|
workqueue->queue_soon(new Read_script(this->symtab_,
|
| 447 |
|
|
this->layout_,
|
| 448 |
|
|
this->dirpath_,
|
| 449 |
|
|
this->dirindex_,
|
| 450 |
|
|
this->input_objects_,
|
| 451 |
|
|
this->mapfile_,
|
| 452 |
|
|
this->input_group_,
|
| 453 |
|
|
this->input_argument_,
|
| 454 |
|
|
input_file,
|
| 455 |
|
|
this->this_blocker_,
|
| 456 |
|
|
this->next_blocker_));
|
| 457 |
|
|
return true;
|
| 458 |
|
|
}
|
| 459 |
|
|
|
| 460 |
|
|
// Handle a group. We need to walk through the arguments over and
|
| 461 |
|
|
// over until we don't see any new undefined symbols. We do this by
|
| 462 |
|
|
// setting off Read_symbols Tasks as usual, but recording the archive
|
| 463 |
|
|
// entries instead of deleting them. We also start a Finish_group
|
| 464 |
|
|
// Task which runs after we've read all the symbols. In that task we
|
| 465 |
|
|
// process the archives in a loop until we are done.
|
| 466 |
|
|
|
| 467 |
|
|
void
|
| 468 |
|
|
Read_symbols::do_group(Workqueue* workqueue)
|
| 469 |
|
|
{
|
| 470 |
|
|
Input_group* input_group = new Input_group();
|
| 471 |
|
|
|
| 472 |
|
|
const Input_file_group* group = this->input_argument_->group();
|
| 473 |
|
|
Task_token* this_blocker = this->this_blocker_;
|
| 474 |
|
|
|
| 475 |
|
|
Finish_group* finish_group = new Finish_group(this->input_objects_,
|
| 476 |
|
|
this->symtab_,
|
| 477 |
|
|
this->layout_,
|
| 478 |
|
|
this->mapfile_,
|
| 479 |
|
|
input_group,
|
| 480 |
|
|
this->next_blocker_);
|
| 481 |
|
|
|
| 482 |
|
|
Task_token* next_blocker = new Task_token(true);
|
| 483 |
|
|
next_blocker->add_blocker();
|
| 484 |
|
|
workqueue->queue_soon(new Start_group(this->symtab_, finish_group,
|
| 485 |
|
|
this_blocker, next_blocker));
|
| 486 |
|
|
this_blocker = next_blocker;
|
| 487 |
|
|
|
| 488 |
|
|
for (Input_file_group::const_iterator p = group->begin();
|
| 489 |
|
|
p != group->end();
|
| 490 |
|
|
++p)
|
| 491 |
|
|
{
|
| 492 |
|
|
const Input_argument* arg = &*p;
|
| 493 |
|
|
gold_assert(arg->is_file());
|
| 494 |
|
|
|
| 495 |
|
|
next_blocker = new Task_token(true);
|
| 496 |
|
|
next_blocker->add_blocker();
|
| 497 |
|
|
workqueue->queue_soon(new Read_symbols(this->input_objects_,
|
| 498 |
|
|
this->symtab_, this->layout_,
|
| 499 |
|
|
this->dirpath_, this->dirindex_,
|
| 500 |
|
|
this->mapfile_, arg, input_group,
|
| 501 |
|
|
NULL, this_blocker, next_blocker));
|
| 502 |
|
|
this_blocker = next_blocker;
|
| 503 |
|
|
}
|
| 504 |
|
|
|
| 505 |
|
|
finish_group->set_blocker(this_blocker);
|
| 506 |
|
|
|
| 507 |
|
|
workqueue->queue_soon(finish_group);
|
| 508 |
|
|
}
|
| 509 |
|
|
|
| 510 |
|
|
// Return a debugging name for a Read_symbols task.
|
| 511 |
|
|
|
| 512 |
|
|
std::string
|
| 513 |
|
|
Read_symbols::get_name() const
|
| 514 |
|
|
{
|
| 515 |
|
|
if (this->input_argument_->is_group())
|
| 516 |
|
|
{
|
| 517 |
|
|
std::string ret("Read_symbols group (");
|
| 518 |
|
|
bool add_space = false;
|
| 519 |
|
|
const Input_file_group* group = this->input_argument_->group();
|
| 520 |
|
|
for (Input_file_group::const_iterator p = group->begin();
|
| 521 |
|
|
p != group->end();
|
| 522 |
|
|
++p)
|
| 523 |
|
|
{
|
| 524 |
|
|
if (add_space)
|
| 525 |
|
|
ret += ' ';
|
| 526 |
|
|
ret += p->file().name();
|
| 527 |
|
|
add_space = true;
|
| 528 |
|
|
}
|
| 529 |
|
|
return ret + ')';
|
| 530 |
|
|
}
|
| 531 |
|
|
else if (this->input_argument_->is_lib())
|
| 532 |
|
|
{
|
| 533 |
|
|
std::string ret("Read_symbols lib (");
|
| 534 |
|
|
bool add_space = false;
|
| 535 |
|
|
const Input_file_lib* lib = this->input_argument_->lib();
|
| 536 |
|
|
for (Input_file_lib::const_iterator p = lib->begin();
|
| 537 |
|
|
p != lib->end();
|
| 538 |
|
|
++p)
|
| 539 |
|
|
{
|
| 540 |
|
|
if (add_space)
|
| 541 |
|
|
ret += ' ';
|
| 542 |
|
|
ret += p->file().name();
|
| 543 |
|
|
add_space = true;
|
| 544 |
|
|
}
|
| 545 |
|
|
return ret + ')';
|
| 546 |
|
|
}
|
| 547 |
|
|
else
|
| 548 |
|
|
{
|
| 549 |
|
|
std::string ret("Read_symbols ");
|
| 550 |
|
|
if (this->input_argument_->file().is_lib())
|
| 551 |
|
|
ret += "-l";
|
| 552 |
|
|
else if (this->input_argument_->file().is_searched_file())
|
| 553 |
|
|
ret += "-l:";
|
| 554 |
|
|
ret += this->input_argument_->file().name();
|
| 555 |
|
|
return ret;
|
| 556 |
|
|
}
|
| 557 |
|
|
}
|
| 558 |
|
|
|
| 559 |
|
|
// Class Add_symbols.
|
| 560 |
|
|
|
| 561 |
|
|
Add_symbols::~Add_symbols()
|
| 562 |
|
|
{
|
| 563 |
|
|
if (this->this_blocker_ != NULL)
|
| 564 |
|
|
delete this->this_blocker_;
|
| 565 |
|
|
// next_blocker_ is deleted by the task associated with the next
|
| 566 |
|
|
// input file.
|
| 567 |
|
|
}
|
| 568 |
|
|
|
| 569 |
|
|
// We are blocked by this_blocker_. We block next_blocker_. We also
|
| 570 |
|
|
// lock the file.
|
| 571 |
|
|
|
| 572 |
|
|
Task_token*
|
| 573 |
|
|
Add_symbols::is_runnable()
|
| 574 |
|
|
{
|
| 575 |
|
|
if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
|
| 576 |
|
|
return this->this_blocker_;
|
| 577 |
|
|
if (this->object_->is_locked())
|
| 578 |
|
|
return this->object_->token();
|
| 579 |
|
|
return NULL;
|
| 580 |
|
|
}
|
| 581 |
|
|
|
| 582 |
|
|
void
|
| 583 |
|
|
Add_symbols::locks(Task_locker* tl)
|
| 584 |
|
|
{
|
| 585 |
|
|
tl->add(this, this->next_blocker_);
|
| 586 |
|
|
Task_token* token = this->object_->token();
|
| 587 |
|
|
if (token != NULL)
|
| 588 |
|
|
tl->add(this, token);
|
| 589 |
|
|
}
|
| 590 |
|
|
|
| 591 |
|
|
// Add the symbols in the object to the symbol table.
|
| 592 |
|
|
|
| 593 |
|
|
void
|
| 594 |
|
|
Add_symbols::run(Workqueue*)
|
| 595 |
|
|
{
|
| 596 |
|
|
Pluginobj* pluginobj = this->object_->pluginobj();
|
| 597 |
|
|
if (pluginobj != NULL)
|
| 598 |
|
|
{
|
| 599 |
|
|
this->object_->add_symbols(this->symtab_, this->sd_, this->layout_);
|
| 600 |
|
|
return;
|
| 601 |
|
|
}
|
| 602 |
|
|
|
| 603 |
|
|
if (!this->input_objects_->add_object(this->object_))
|
| 604 |
|
|
{
|
| 605 |
|
|
gold_assert(this->sd_ != NULL);
|
| 606 |
|
|
delete this->sd_;
|
| 607 |
|
|
this->sd_ = NULL;
|
| 608 |
|
|
this->object_->release();
|
| 609 |
|
|
delete this->object_;
|
| 610 |
|
|
}
|
| 611 |
|
|
else
|
| 612 |
|
|
{
|
| 613 |
|
|
Incremental_inputs* incremental_inputs =
|
| 614 |
|
|
this->layout_->incremental_inputs();
|
| 615 |
|
|
if (incremental_inputs != NULL)
|
| 616 |
|
|
{
|
| 617 |
|
|
if (this->library_ != NULL && !this->library_->is_reported())
|
| 618 |
|
|
{
|
| 619 |
|
|
Incremental_binary* ibase = this->layout_->incremental_base();
|
| 620 |
|
|
gold_assert(ibase != NULL);
|
| 621 |
|
|
unsigned int lib_serial = this->library_->arg_serial();
|
| 622 |
|
|
unsigned int lib_index = this->library_->input_file_index();
|
| 623 |
|
|
Script_info* lib_script_info = ibase->get_script_info(lib_index);
|
| 624 |
|
|
incremental_inputs->report_archive_begin(this->library_,
|
| 625 |
|
|
lib_serial,
|
| 626 |
|
|
lib_script_info);
|
| 627 |
|
|
}
|
| 628 |
|
|
unsigned int arg_serial = this->input_argument_->file().arg_serial();
|
| 629 |
|
|
Script_info* script_info = this->input_argument_->script_info();
|
| 630 |
|
|
incremental_inputs->report_object(this->object_, arg_serial,
|
| 631 |
|
|
this->library_, script_info);
|
| 632 |
|
|
}
|
| 633 |
|
|
this->object_->layout(this->symtab_, this->layout_, this->sd_);
|
| 634 |
|
|
this->object_->add_symbols(this->symtab_, this->sd_, this->layout_);
|
| 635 |
|
|
delete this->sd_;
|
| 636 |
|
|
this->sd_ = NULL;
|
| 637 |
|
|
this->object_->release();
|
| 638 |
|
|
}
|
| 639 |
|
|
}
|
| 640 |
|
|
|
| 641 |
|
|
// Class Read_member.
|
| 642 |
|
|
|
| 643 |
|
|
Read_member::~Read_member()
|
| 644 |
|
|
{
|
| 645 |
|
|
if (this->this_blocker_ != NULL)
|
| 646 |
|
|
delete this->this_blocker_;
|
| 647 |
|
|
// next_blocker_ is deleted by the task associated with the next
|
| 648 |
|
|
// input file.
|
| 649 |
|
|
}
|
| 650 |
|
|
|
| 651 |
|
|
// Return whether a Read_member task is runnable.
|
| 652 |
|
|
|
| 653 |
|
|
Task_token*
|
| 654 |
|
|
Read_member::is_runnable()
|
| 655 |
|
|
{
|
| 656 |
159 |
khays |
if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
|
| 657 |
|
|
return this->this_blocker_;
|
| 658 |
27 |
khays |
return NULL;
|
| 659 |
|
|
}
|
| 660 |
|
|
|
| 661 |
|
|
void
|
| 662 |
|
|
Read_member::locks(Task_locker* tl)
|
| 663 |
|
|
{
|
| 664 |
|
|
tl->add(this, this->next_blocker_);
|
| 665 |
|
|
}
|
| 666 |
|
|
|
| 667 |
|
|
// Run a Read_member task.
|
| 668 |
|
|
|
| 669 |
|
|
void
|
| 670 |
|
|
Read_member::run(Workqueue*)
|
| 671 |
|
|
{
|
| 672 |
|
|
// This task doesn't need to do anything for now. The Read_symbols task
|
| 673 |
|
|
// that is queued for the archive library will cause the archive to be
|
| 674 |
|
|
// processed from scratch.
|
| 675 |
|
|
}
|
| 676 |
|
|
|
| 677 |
|
|
// Class Check_script.
|
| 678 |
|
|
|
| 679 |
|
|
Check_script::~Check_script()
|
| 680 |
|
|
{
|
| 681 |
|
|
if (this->this_blocker_ != NULL)
|
| 682 |
|
|
delete this->this_blocker_;
|
| 683 |
|
|
// next_blocker_ is deleted by the task associated with the next
|
| 684 |
|
|
// input file.
|
| 685 |
|
|
}
|
| 686 |
|
|
|
| 687 |
|
|
// Return whether a Check_script task is runnable.
|
| 688 |
|
|
|
| 689 |
|
|
Task_token*
|
| 690 |
|
|
Check_script::is_runnable()
|
| 691 |
|
|
{
|
| 692 |
|
|
if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
|
| 693 |
|
|
return this->this_blocker_;
|
| 694 |
|
|
return NULL;
|
| 695 |
|
|
}
|
| 696 |
|
|
|
| 697 |
|
|
void
|
| 698 |
|
|
Check_script::locks(Task_locker* tl)
|
| 699 |
|
|
{
|
| 700 |
|
|
tl->add(this, this->next_blocker_);
|
| 701 |
|
|
}
|
| 702 |
|
|
|
| 703 |
|
|
// Run a Check_script task.
|
| 704 |
|
|
|
| 705 |
|
|
void
|
| 706 |
|
|
Check_script::run(Workqueue*)
|
| 707 |
|
|
{
|
| 708 |
|
|
Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs();
|
| 709 |
|
|
gold_assert(incremental_inputs != NULL);
|
| 710 |
|
|
unsigned int arg_serial = this->input_reader_->arg_serial();
|
| 711 |
|
|
Script_info* script_info =
|
| 712 |
|
|
this->ibase_->get_script_info(this->input_file_index_);
|
| 713 |
|
|
Timespec mtime = this->input_reader_->get_mtime();
|
| 714 |
|
|
incremental_inputs->report_script(script_info, arg_serial, mtime);
|
| 715 |
|
|
}
|
| 716 |
|
|
|
| 717 |
|
|
// Class Check_library.
|
| 718 |
|
|
|
| 719 |
|
|
Check_library::~Check_library()
|
| 720 |
|
|
{
|
| 721 |
|
|
if (this->this_blocker_ != NULL)
|
| 722 |
|
|
delete this->this_blocker_;
|
| 723 |
|
|
// next_blocker_ is deleted by the task associated with the next
|
| 724 |
|
|
// input file.
|
| 725 |
|
|
}
|
| 726 |
|
|
|
| 727 |
|
|
// Return whether a Check_library task is runnable.
|
| 728 |
|
|
|
| 729 |
|
|
Task_token*
|
| 730 |
|
|
Check_library::is_runnable()
|
| 731 |
|
|
{
|
| 732 |
|
|
if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
|
| 733 |
|
|
return this->this_blocker_;
|
| 734 |
|
|
return NULL;
|
| 735 |
|
|
}
|
| 736 |
|
|
|
| 737 |
|
|
void
|
| 738 |
|
|
Check_library::locks(Task_locker* tl)
|
| 739 |
|
|
{
|
| 740 |
|
|
tl->add(this, this->next_blocker_);
|
| 741 |
|
|
}
|
| 742 |
|
|
|
| 743 |
|
|
// Run a Check_library task.
|
| 744 |
|
|
|
| 745 |
|
|
void
|
| 746 |
|
|
Check_library::run(Workqueue*)
|
| 747 |
|
|
{
|
| 748 |
|
|
Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs();
|
| 749 |
|
|
gold_assert(incremental_inputs != NULL);
|
| 750 |
|
|
Incremental_library* lib = this->ibase_->get_library(this->input_file_index_);
|
| 751 |
|
|
gold_assert(lib != NULL);
|
| 752 |
|
|
lib->copy_unused_symbols();
|
| 753 |
|
|
// FIXME: Check that unused symbols remain unused.
|
| 754 |
|
|
if (!lib->is_reported())
|
| 755 |
|
|
{
|
| 756 |
|
|
unsigned int lib_serial = lib->arg_serial();
|
| 757 |
|
|
unsigned int lib_index = lib->input_file_index();
|
| 758 |
|
|
Script_info* script_info = this->ibase_->get_script_info(lib_index);
|
| 759 |
|
|
incremental_inputs->report_archive_begin(lib, lib_serial, script_info);
|
| 760 |
|
|
}
|
| 761 |
|
|
incremental_inputs->report_archive_end(lib);
|
| 762 |
|
|
}
|
| 763 |
|
|
|
| 764 |
|
|
// Class Input_group.
|
| 765 |
|
|
|
| 766 |
|
|
// When we delete an Input_group we can delete the archive
|
| 767 |
|
|
// information.
|
| 768 |
|
|
|
| 769 |
|
|
Input_group::~Input_group()
|
| 770 |
|
|
{
|
| 771 |
|
|
for (Input_group::const_iterator p = this->begin();
|
| 772 |
|
|
p != this->end();
|
| 773 |
|
|
++p)
|
| 774 |
|
|
delete *p;
|
| 775 |
|
|
}
|
| 776 |
|
|
|
| 777 |
|
|
// Class Start_group.
|
| 778 |
|
|
|
| 779 |
|
|
Start_group::~Start_group()
|
| 780 |
|
|
{
|
| 781 |
|
|
if (this->this_blocker_ != NULL)
|
| 782 |
|
|
delete this->this_blocker_;
|
| 783 |
|
|
// next_blocker_ is deleted by the task associated with the first
|
| 784 |
|
|
// file in the group.
|
| 785 |
|
|
}
|
| 786 |
|
|
|
| 787 |
|
|
// We need to wait for THIS_BLOCKER_ and unblock NEXT_BLOCKER_.
|
| 788 |
|
|
|
| 789 |
|
|
Task_token*
|
| 790 |
|
|
Start_group::is_runnable()
|
| 791 |
|
|
{
|
| 792 |
|
|
if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
|
| 793 |
|
|
return this->this_blocker_;
|
| 794 |
|
|
return NULL;
|
| 795 |
|
|
}
|
| 796 |
|
|
|
| 797 |
|
|
void
|
| 798 |
|
|
Start_group::locks(Task_locker* tl)
|
| 799 |
|
|
{
|
| 800 |
|
|
tl->add(this, this->next_blocker_);
|
| 801 |
|
|
}
|
| 802 |
|
|
|
| 803 |
|
|
// Store the number of undefined symbols we see now.
|
| 804 |
|
|
|
| 805 |
|
|
void
|
| 806 |
|
|
Start_group::run(Workqueue*)
|
| 807 |
|
|
{
|
| 808 |
|
|
this->finish_group_->set_saw_undefined(this->symtab_->saw_undefined());
|
| 809 |
|
|
}
|
| 810 |
|
|
|
| 811 |
|
|
// Class Finish_group.
|
| 812 |
|
|
|
| 813 |
|
|
Finish_group::~Finish_group()
|
| 814 |
|
|
{
|
| 815 |
|
|
if (this->this_blocker_ != NULL)
|
| 816 |
|
|
delete this->this_blocker_;
|
| 817 |
|
|
// next_blocker_ is deleted by the task associated with the next
|
| 818 |
|
|
// input file following the group.
|
| 819 |
|
|
}
|
| 820 |
|
|
|
| 821 |
|
|
// We need to wait for THIS_BLOCKER_ and unblock NEXT_BLOCKER_.
|
| 822 |
|
|
|
| 823 |
|
|
Task_token*
|
| 824 |
|
|
Finish_group::is_runnable()
|
| 825 |
|
|
{
|
| 826 |
|
|
if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
|
| 827 |
|
|
return this->this_blocker_;
|
| 828 |
|
|
return NULL;
|
| 829 |
|
|
}
|
| 830 |
|
|
|
| 831 |
|
|
void
|
| 832 |
|
|
Finish_group::locks(Task_locker* tl)
|
| 833 |
|
|
{
|
| 834 |
|
|
tl->add(this, this->next_blocker_);
|
| 835 |
|
|
}
|
| 836 |
|
|
|
| 837 |
|
|
// Loop over the archives until there are no new undefined symbols.
|
| 838 |
|
|
|
| 839 |
|
|
void
|
| 840 |
|
|
Finish_group::run(Workqueue*)
|
| 841 |
|
|
{
|
| 842 |
|
|
size_t saw_undefined = this->saw_undefined_;
|
| 843 |
|
|
while (saw_undefined != this->symtab_->saw_undefined())
|
| 844 |
|
|
{
|
| 845 |
|
|
saw_undefined = this->symtab_->saw_undefined();
|
| 846 |
|
|
|
| 847 |
|
|
for (Input_group::const_iterator p = this->input_group_->begin();
|
| 848 |
|
|
p != this->input_group_->end();
|
| 849 |
|
|
++p)
|
| 850 |
|
|
{
|
| 851 |
|
|
Task_lock_obj<Archive> tl(this, *p);
|
| 852 |
|
|
|
| 853 |
|
|
(*p)->add_symbols(this->symtab_, this->layout_,
|
| 854 |
|
|
this->input_objects_, this->mapfile_);
|
| 855 |
|
|
}
|
| 856 |
|
|
}
|
| 857 |
|
|
|
| 858 |
|
|
// Now that we're done with the archives, record the incremental
|
| 859 |
|
|
// layout information.
|
| 860 |
|
|
for (Input_group::const_iterator p = this->input_group_->begin();
|
| 861 |
|
|
p != this->input_group_->end();
|
| 862 |
|
|
++p)
|
| 863 |
|
|
{
|
| 864 |
|
|
// For an incremental link, finish recording the layout information.
|
| 865 |
|
|
Incremental_inputs* incremental_inputs =
|
| 866 |
|
|
this->layout_->incremental_inputs();
|
| 867 |
|
|
if (incremental_inputs != NULL)
|
| 868 |
|
|
incremental_inputs->report_archive_end(*p);
|
| 869 |
|
|
}
|
| 870 |
|
|
|
| 871 |
|
|
if (parameters->options().has_plugins())
|
| 872 |
|
|
parameters->options().plugins()->save_input_group(this->input_group_);
|
| 873 |
|
|
else
|
| 874 |
|
|
delete this->input_group_;
|
| 875 |
|
|
}
|
| 876 |
|
|
|
| 877 |
|
|
// Class Read_script
|
| 878 |
|
|
|
| 879 |
|
|
Read_script::~Read_script()
|
| 880 |
|
|
{
|
| 881 |
|
|
if (this->this_blocker_ != NULL)
|
| 882 |
|
|
delete this->this_blocker_;
|
| 883 |
|
|
// next_blocker_ is deleted by the task associated with the next
|
| 884 |
|
|
// input file.
|
| 885 |
|
|
}
|
| 886 |
|
|
|
| 887 |
|
|
// We are blocked by this_blocker_.
|
| 888 |
|
|
|
| 889 |
|
|
Task_token*
|
| 890 |
|
|
Read_script::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 |
|
|
// We don't unlock next_blocker_ here. If the script names any input
|
| 898 |
|
|
// files, then the last file will be responsible for unlocking it.
|
| 899 |
|
|
|
| 900 |
|
|
void
|
| 901 |
|
|
Read_script::locks(Task_locker*)
|
| 902 |
|
|
{
|
| 903 |
|
|
}
|
| 904 |
|
|
|
| 905 |
|
|
// Read the script, if it is a script.
|
| 906 |
|
|
|
| 907 |
|
|
void
|
| 908 |
|
|
Read_script::run(Workqueue* workqueue)
|
| 909 |
|
|
{
|
| 910 |
|
|
bool used_next_blocker;
|
| 911 |
|
|
if (!read_input_script(workqueue, this->symtab_, this->layout_,
|
| 912 |
|
|
this->dirpath_, this->dirindex_, this->input_objects_,
|
| 913 |
|
|
this->mapfile_, this->input_group_,
|
| 914 |
|
|
this->input_argument_, this->input_file_,
|
| 915 |
|
|
this->next_blocker_, &used_next_blocker))
|
| 916 |
|
|
{
|
| 917 |
|
|
// Here we have to handle any other input file types we need.
|
| 918 |
|
|
gold_error(_("%s: not an object or archive"),
|
| 919 |
|
|
this->input_file_->file().filename().c_str());
|
| 920 |
|
|
}
|
| 921 |
|
|
|
| 922 |
|
|
if (!used_next_blocker)
|
| 923 |
|
|
{
|
| 924 |
|
|
// Queue up a task to unlock next_blocker. We can't just unlock
|
| 925 |
|
|
// it here, as we don't hold the workqueue lock.
|
| 926 |
|
|
workqueue->queue_soon(new Unblock_token(NULL, this->next_blocker_));
|
| 927 |
|
|
}
|
| 928 |
|
|
}
|
| 929 |
|
|
|
| 930 |
|
|
// Return a debugging name for a Read_script task.
|
| 931 |
|
|
|
| 932 |
|
|
std::string
|
| 933 |
|
|
Read_script::get_name() const
|
| 934 |
|
|
{
|
| 935 |
|
|
std::string ret("Read_script ");
|
| 936 |
|
|
if (this->input_argument_->file().is_lib())
|
| 937 |
|
|
ret += "-l";
|
| 938 |
|
|
else if (this->input_argument_->file().is_searched_file())
|
| 939 |
|
|
ret += "-l:";
|
| 940 |
|
|
ret += this->input_argument_->file().name();
|
| 941 |
|
|
return ret;
|
| 942 |
|
|
}
|
| 943 |
|
|
|
| 944 |
|
|
} // End namespace gold.
|