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 159

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 159 khays
  Object* elf_obj = NULL;
324
  bool unconfigured;
325
  bool* punconfigured = NULL;
326
  if (is_elf)
327
    {
328
      // This is an ELF object.
329
 
330
      unconfigured = false;
331
      punconfigured = (input_file->will_search_for()
332
                       ? &unconfigured
333
                       : NULL);
334
      elf_obj = make_elf_object(input_file->filename(),
335
                                input_file, 0, ehdr, read_size,
336
                                punconfigured);
337
    }
338
 
339 27 khays
  if (parameters->options().has_plugins())
340
    {
341
      Pluginobj* obj = parameters->options().plugins()->claim_file(input_file,
342 159 khays
                                                                   0, filesize,
343
                                                                   elf_obj);
344 27 khays
      if (obj != NULL)
345
        {
346 159 khays
          // Delete the elf_obj, this file has been claimed.
347
          if (elf_obj != NULL)
348
            delete elf_obj;
349
 
350 27 khays
          // The input file was claimed by a plugin, and its symbols
351
          // have been provided by the plugin.
352
 
353
          // We are done with the file at this point, so unlock it.
354
          obj->unlock(this);
355
 
356
          if (this->member_ != NULL)
357
            {
358
              this->member_->sd_ = NULL;
359
              this->member_->obj_ = obj;
360
              return true;
361
            }
362
 
363
          workqueue->queue_next(new Add_symbols(this->input_objects_,
364
                                                this->symtab_,
365
                                                this->layout_,
366
                                                this->dirpath_,
367
                                                this->dirindex_,
368
                                                this->mapfile_,
369
                                                this->input_argument_,
370
                                                obj,
371
                                                NULL,
372
                                                NULL,
373
                                                this->this_blocker_,
374
                                                this->next_blocker_));
375
          return true;
376
        }
377
    }
378
 
379
  if (is_elf)
380
    {
381
      // This is an ELF object.
382
 
383 159 khays
      if (elf_obj == NULL)
384 27 khays
        {
385
          if (unconfigured)
386
            {
387
              Read_symbols::incompatible_warning(this->input_argument_,
388
                                                 input_file);
389
              input_file->file().release();
390
              input_file->file().unlock(this);
391
              delete input_file;
392
              ++this->dirindex_;
393
              return this->do_read_symbols(workqueue);
394
            }
395
          return false;
396
        }
397
 
398
      Read_symbols_data* sd = new Read_symbols_data;
399 159 khays
      elf_obj->read_symbols(sd);
400 27 khays
 
401
      // Opening the file locked it, so now we need to unlock it.  We
402
      // need to unlock it before queuing the Add_symbols task,
403
      // because the workqueue doesn't know about our lock on the
404
      // file.  If we queue the Add_symbols task first, it will be
405
      // stuck on the end of the file lock, but since the workqueue
406
      // doesn't know about that lock, it will never release the
407
      // Add_symbols task.
408
 
409
      input_file->file().unlock(this);
410
 
411
      if (this->member_ != NULL)
412
        {
413
          this->member_->sd_ = sd;
414 159 khays
          this->member_->obj_ = elf_obj;
415 27 khays
          this->member_->arg_serial_ =
416
              this->input_argument_->file().arg_serial();
417
          return true;
418
        }
419
 
420
      // We use queue_next because everything is cached for this
421
      // task to run right away if possible.
422
 
423
      workqueue->queue_next(new Add_symbols(this->input_objects_,
424
                                            this->symtab_, this->layout_,
425
                                            this->dirpath_,
426
                                            this->dirindex_,
427
                                            this->mapfile_,
428
                                            this->input_argument_,
429 159 khays
                                            elf_obj,
430 27 khays
                                            NULL,
431
                                            sd,
432
                                            this->this_blocker_,
433
                                            this->next_blocker_));
434
 
435
      return true;
436
    }
437
 
438
  // Queue up a task to try to parse this file as a script.  We use a
439
  // separate task so that the script will be read in order with other
440
  // objects named on the command line.  Also so that we don't try to
441
  // read multiple scripts simultaneously, which could lead to
442
  // unpredictable changes to the General_options structure.
443
 
444
  workqueue->queue_soon(new Read_script(this->symtab_,
445
                                        this->layout_,
446
                                        this->dirpath_,
447
                                        this->dirindex_,
448
                                        this->input_objects_,
449
                                        this->mapfile_,
450
                                        this->input_group_,
451
                                        this->input_argument_,
452
                                        input_file,
453
                                        this->this_blocker_,
454
                                        this->next_blocker_));
455
  return true;
456
}
457
 
458
// Handle a group.  We need to walk through the arguments over and
459
// over until we don't see any new undefined symbols.  We do this by
460
// setting off Read_symbols Tasks as usual, but recording the archive
461
// entries instead of deleting them.  We also start a Finish_group
462
// Task which runs after we've read all the symbols.  In that task we
463
// process the archives in a loop until we are done.
464
 
465
void
466
Read_symbols::do_group(Workqueue* workqueue)
467
{
468
  Input_group* input_group = new Input_group();
469
 
470
  const Input_file_group* group = this->input_argument_->group();
471
  Task_token* this_blocker = this->this_blocker_;
472
 
473
  Finish_group* finish_group = new Finish_group(this->input_objects_,
474
                                                this->symtab_,
475
                                                this->layout_,
476
                                                this->mapfile_,
477
                                                input_group,
478
                                                this->next_blocker_);
479
 
480
  Task_token* next_blocker = new Task_token(true);
481
  next_blocker->add_blocker();
482
  workqueue->queue_soon(new Start_group(this->symtab_, finish_group,
483
                                        this_blocker, next_blocker));
484
  this_blocker = next_blocker;
485
 
486
  for (Input_file_group::const_iterator p = group->begin();
487
       p != group->end();
488
       ++p)
489
    {
490
      const Input_argument* arg = &*p;
491
      gold_assert(arg->is_file());
492
 
493
      next_blocker = new Task_token(true);
494
      next_blocker->add_blocker();
495
      workqueue->queue_soon(new Read_symbols(this->input_objects_,
496
                                             this->symtab_, this->layout_,
497
                                             this->dirpath_, this->dirindex_,
498
                                             this->mapfile_, arg, input_group,
499
                                             NULL, this_blocker, next_blocker));
500
      this_blocker = next_blocker;
501
    }
502
 
503
  finish_group->set_blocker(this_blocker);
504
 
505
  workqueue->queue_soon(finish_group);
506
}
507
 
508
// Return a debugging name for a Read_symbols task.
509
 
510
std::string
511
Read_symbols::get_name() const
512
{
513
  if (this->input_argument_->is_group())
514
    {
515
      std::string ret("Read_symbols group (");
516
      bool add_space = false;
517
      const Input_file_group* group = this->input_argument_->group();
518
      for (Input_file_group::const_iterator p = group->begin();
519
           p != group->end();
520
           ++p)
521
      {
522
        if (add_space)
523
          ret += ' ';
524
        ret += p->file().name();
525
        add_space = true;
526
      }
527
      return ret + ')';
528
    }
529
  else if (this->input_argument_->is_lib())
530
    {
531
      std::string ret("Read_symbols lib (");
532
      bool add_space = false;
533
      const Input_file_lib* lib = this->input_argument_->lib();
534
      for (Input_file_lib::const_iterator p = lib->begin();
535
           p != lib->end();
536
           ++p)
537
      {
538
        if (add_space)
539
          ret += ' ';
540
        ret += p->file().name();
541
        add_space = true;
542
      }
543
      return ret + ')';
544
    }
545
  else
546
    {
547
      std::string ret("Read_symbols ");
548
      if (this->input_argument_->file().is_lib())
549
        ret += "-l";
550
      else if (this->input_argument_->file().is_searched_file())
551
        ret += "-l:";
552
      ret += this->input_argument_->file().name();
553
      return ret;
554
    }
555
}
556
 
557
// Class Add_symbols.
558
 
559
Add_symbols::~Add_symbols()
560
{
561
  if (this->this_blocker_ != NULL)
562
    delete this->this_blocker_;
563
  // next_blocker_ is deleted by the task associated with the next
564
  // input file.
565
}
566
 
567
// We are blocked by this_blocker_.  We block next_blocker_.  We also
568
// lock the file.
569
 
570
Task_token*
571
Add_symbols::is_runnable()
572
{
573
  if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
574
    return this->this_blocker_;
575
  if (this->object_->is_locked())
576
    return this->object_->token();
577
  return NULL;
578
}
579
 
580
void
581
Add_symbols::locks(Task_locker* tl)
582
{
583
  tl->add(this, this->next_blocker_);
584
  Task_token* token = this->object_->token();
585
  if (token != NULL)
586
    tl->add(this, token);
587
}
588
 
589
// Add the symbols in the object to the symbol table.
590
 
591
void
592
Add_symbols::run(Workqueue*)
593
{
594
  Pluginobj* pluginobj = this->object_->pluginobj();
595
  if (pluginobj != NULL)
596
    {
597
      this->object_->add_symbols(this->symtab_, this->sd_, this->layout_);
598
      return;
599
    }
600
 
601
  if (!this->input_objects_->add_object(this->object_))
602
    {
603
      gold_assert(this->sd_ != NULL);
604
      delete this->sd_;
605
      this->sd_ = NULL;
606
      this->object_->release();
607
      delete this->object_;
608
    }
609
  else
610
    {
611
      Incremental_inputs* incremental_inputs =
612
          this->layout_->incremental_inputs();
613
      if (incremental_inputs != NULL)
614
        {
615
          if (this->library_ != NULL && !this->library_->is_reported())
616
            {
617
              Incremental_binary* ibase = this->layout_->incremental_base();
618
              gold_assert(ibase != NULL);
619
              unsigned int lib_serial = this->library_->arg_serial();
620
              unsigned int lib_index = this->library_->input_file_index();
621
              Script_info* lib_script_info = ibase->get_script_info(lib_index);
622
              incremental_inputs->report_archive_begin(this->library_,
623
                                                       lib_serial,
624
                                                       lib_script_info);
625
            }
626
          unsigned int arg_serial = this->input_argument_->file().arg_serial();
627
          Script_info* script_info = this->input_argument_->script_info();
628
          incremental_inputs->report_object(this->object_, arg_serial,
629
                                            this->library_, script_info);
630
        }
631
      this->object_->layout(this->symtab_, this->layout_, this->sd_);
632
      this->object_->add_symbols(this->symtab_, this->sd_, this->layout_);
633
      delete this->sd_;
634
      this->sd_ = NULL;
635
      this->object_->release();
636
    }
637
}
638
 
639
// Class Read_member.
640
 
641
Read_member::~Read_member()
642
{
643
  if (this->this_blocker_ != NULL)
644
    delete this->this_blocker_;
645
  // next_blocker_ is deleted by the task associated with the next
646
  // input file.
647
}
648
 
649
// Return whether a Read_member task is runnable.
650
 
651
Task_token*
652
Read_member::is_runnable()
653
{
654 159 khays
  if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
655
    return this->this_blocker_;
656 27 khays
  return NULL;
657
}
658
 
659
void
660
Read_member::locks(Task_locker* tl)
661
{
662
  tl->add(this, this->next_blocker_);
663
}
664
 
665
// Run a Read_member task.
666
 
667
void
668
Read_member::run(Workqueue*)
669
{
670
  // This task doesn't need to do anything for now.  The Read_symbols task
671
  // that is queued for the archive library will cause the archive to be
672
  // processed from scratch.
673
}
674
 
675
// Class Check_script.
676
 
677
Check_script::~Check_script()
678
{
679
  if (this->this_blocker_ != NULL)
680
    delete this->this_blocker_;
681
  // next_blocker_ is deleted by the task associated with the next
682
  // input file.
683
}
684
 
685
// Return whether a Check_script task is runnable.
686
 
687
Task_token*
688
Check_script::is_runnable()
689
{
690
  if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
691
    return this->this_blocker_;
692
  return NULL;
693
}
694
 
695
void
696
Check_script::locks(Task_locker* tl)
697
{
698
  tl->add(this, this->next_blocker_);
699
}
700
 
701
// Run a Check_script task.
702
 
703
void
704
Check_script::run(Workqueue*)
705
{
706
  Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs();
707
  gold_assert(incremental_inputs != NULL);
708
  unsigned int arg_serial = this->input_reader_->arg_serial();
709
  Script_info* script_info =
710
      this->ibase_->get_script_info(this->input_file_index_);
711
  Timespec mtime = this->input_reader_->get_mtime();
712
  incremental_inputs->report_script(script_info, arg_serial, mtime);
713
}
714
 
715
// Class Check_library.
716
 
717
Check_library::~Check_library()
718
{
719
  if (this->this_blocker_ != NULL)
720
    delete this->this_blocker_;
721
  // next_blocker_ is deleted by the task associated with the next
722
  // input file.
723
}
724
 
725
// Return whether a Check_library task is runnable.
726
 
727
Task_token*
728
Check_library::is_runnable()
729
{
730
  if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
731
    return this->this_blocker_;
732
  return NULL;
733
}
734
 
735
void
736
Check_library::locks(Task_locker* tl)
737
{
738
  tl->add(this, this->next_blocker_);
739
}
740
 
741
// Run a Check_library task.
742
 
743
void
744
Check_library::run(Workqueue*)
745
{
746
  Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs();
747
  gold_assert(incremental_inputs != NULL);
748
  Incremental_library* lib = this->ibase_->get_library(this->input_file_index_);
749
  gold_assert(lib != NULL);
750
  lib->copy_unused_symbols();
751
  // FIXME: Check that unused symbols remain unused.
752
  if (!lib->is_reported())
753
    {
754
      unsigned int lib_serial = lib->arg_serial();
755
      unsigned int lib_index = lib->input_file_index();
756
      Script_info* script_info = this->ibase_->get_script_info(lib_index);
757
      incremental_inputs->report_archive_begin(lib, lib_serial, script_info);
758
    }
759
  incremental_inputs->report_archive_end(lib);
760
}
761
 
762
// Class Input_group.
763
 
764
// When we delete an Input_group we can delete the archive
765
// information.
766
 
767
Input_group::~Input_group()
768
{
769
  for (Input_group::const_iterator p = this->begin();
770
       p != this->end();
771
       ++p)
772
    delete *p;
773
}
774
 
775
// Class Start_group.
776
 
777
Start_group::~Start_group()
778
{
779
  if (this->this_blocker_ != NULL)
780
    delete this->this_blocker_;
781
  // next_blocker_ is deleted by the task associated with the first
782
  // file in the group.
783
}
784
 
785
// We need to wait for THIS_BLOCKER_ and unblock NEXT_BLOCKER_.
786
 
787
Task_token*
788
Start_group::is_runnable()
789
{
790
  if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
791
    return this->this_blocker_;
792
  return NULL;
793
}
794
 
795
void
796
Start_group::locks(Task_locker* tl)
797
{
798
  tl->add(this, this->next_blocker_);
799
}
800
 
801
// Store the number of undefined symbols we see now.
802
 
803
void
804
Start_group::run(Workqueue*)
805
{
806
  this->finish_group_->set_saw_undefined(this->symtab_->saw_undefined());
807
}
808
 
809
// Class Finish_group.
810
 
811
Finish_group::~Finish_group()
812
{
813
  if (this->this_blocker_ != NULL)
814
    delete this->this_blocker_;
815
  // next_blocker_ is deleted by the task associated with the next
816
  // input file following the group.
817
}
818
 
819
// We need to wait for THIS_BLOCKER_ and unblock NEXT_BLOCKER_.
820
 
821
Task_token*
822
Finish_group::is_runnable()
823
{
824
  if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
825
    return this->this_blocker_;
826
  return NULL;
827
}
828
 
829
void
830
Finish_group::locks(Task_locker* tl)
831
{
832
  tl->add(this, this->next_blocker_);
833
}
834
 
835
// Loop over the archives until there are no new undefined symbols.
836
 
837
void
838
Finish_group::run(Workqueue*)
839
{
840
  size_t saw_undefined = this->saw_undefined_;
841
  while (saw_undefined != this->symtab_->saw_undefined())
842
    {
843
      saw_undefined = this->symtab_->saw_undefined();
844
 
845
      for (Input_group::const_iterator p = this->input_group_->begin();
846
           p != this->input_group_->end();
847
           ++p)
848
        {
849
          Task_lock_obj<Archive> tl(this, *p);
850
 
851
          (*p)->add_symbols(this->symtab_, this->layout_,
852
                            this->input_objects_, this->mapfile_);
853
        }
854
    }
855
 
856
  // Now that we're done with the archives, record the incremental
857
  // layout information.
858
  for (Input_group::const_iterator p = this->input_group_->begin();
859
       p != this->input_group_->end();
860
       ++p)
861
    {
862
      // For an incremental link, finish recording the layout information.
863
      Incremental_inputs* incremental_inputs =
864
          this->layout_->incremental_inputs();
865
      if (incremental_inputs != NULL)
866
        incremental_inputs->report_archive_end(*p);
867
    }
868
 
869
  if (parameters->options().has_plugins())
870
    parameters->options().plugins()->save_input_group(this->input_group_);
871
  else
872
    delete this->input_group_;
873
}
874
 
875
// Class Read_script
876
 
877
Read_script::~Read_script()
878
{
879
  if (this->this_blocker_ != NULL)
880
    delete this->this_blocker_;
881
  // next_blocker_ is deleted by the task associated with the next
882
  // input file.
883
}
884
 
885
// We are blocked by this_blocker_.
886
 
887
Task_token*
888
Read_script::is_runnable()
889
{
890
  if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
891
    return this->this_blocker_;
892
  return NULL;
893
}
894
 
895
// We don't unlock next_blocker_ here.  If the script names any input
896
// files, then the last file will be responsible for unlocking it.
897
 
898
void
899
Read_script::locks(Task_locker*)
900
{
901
}
902
 
903
// Read the script, if it is a script.
904
 
905
void
906
Read_script::run(Workqueue* workqueue)
907
{
908
  bool used_next_blocker;
909
  if (!read_input_script(workqueue, this->symtab_, this->layout_,
910
                         this->dirpath_, this->dirindex_, this->input_objects_,
911
                         this->mapfile_, this->input_group_,
912
                         this->input_argument_, this->input_file_,
913
                         this->next_blocker_, &used_next_blocker))
914
    {
915
      // Here we have to handle any other input file types we need.
916
      gold_error(_("%s: not an object or archive"),
917
                 this->input_file_->file().filename().c_str());
918
    }
919
 
920
  if (!used_next_blocker)
921
    {
922
      // Queue up a task to unlock next_blocker.  We can't just unlock
923
      // it here, as we don't hold the workqueue lock.
924
      workqueue->queue_soon(new Unblock_token(NULL, this->next_blocker_));
925
    }
926
}
927
 
928
// Return a debugging name for a Read_script task.
929
 
930
std::string
931
Read_script::get_name() const
932
{
933
  std::string ret("Read_script ");
934
  if (this->input_argument_->file().is_lib())
935
    ret += "-l";
936
  else if (this->input_argument_->file().is_searched_file())
937
    ret += "-l:";
938
  ret += this->input_argument_->file().name();
939
  return ret;
940
}
941
 
942
} // End namespace gold.

powered by: WebSVN 2.1.0

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