OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gold/] [readsyms.cc] - Blame information for rev 41

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.