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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [binutils-2.20.1/] [gold/] [archive.cc] - Blame information for rev 824

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

Line No. Rev Author Line
1 205 julius
// archive.cc -- archive support for gold
2
 
3
// Copyright 2006, 2007, 2008, 2009 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 <cerrno>
26
#include <cstring>
27
#include <climits>
28
#include <vector>
29
#include "libiberty.h"
30
#include "filenames.h"
31
 
32
#include "elfcpp.h"
33
#include "options.h"
34
#include "mapfile.h"
35
#include "fileread.h"
36
#include "readsyms.h"
37
#include "symtab.h"
38
#include "object.h"
39
#include "archive.h"
40
#include "plugin.h"
41
 
42
namespace gold
43
{
44
 
45
// The header of an entry in the archive.  This is all readable text,
46
// padded with spaces where necesary.  If the contents of an archive
47
// are all text file, the entire archive is readable.
48
 
49
struct Archive::Archive_header
50
{
51
  // The entry name.
52
  char ar_name[16];
53
  // The file modification time.
54
  char ar_date[12];
55
  // The user's UID in decimal.
56
  char ar_uid[6];
57
  // The user's GID in decimal.
58
  char ar_gid[6];
59
  // The file mode in octal.
60
  char ar_mode[8];
61
  // The file size in decimal.
62
  char ar_size[10];
63
  // The final magic code.
64
  char ar_fmag[2];
65
};
66
 
67
// Class Archive static variables.
68
unsigned int Archive::total_archives;
69
unsigned int Archive::total_members;
70
unsigned int Archive::total_members_loaded;
71
 
72
// Archive methods.
73
 
74
const char Archive::armag[sarmag] =
75
{
76
  '!', '<', 'a', 'r', 'c', 'h', '>', '\n'
77
};
78
 
79
const char Archive::armagt[sarmag] =
80
{
81
  '!', '<', 't', 'h', 'i', 'n', '>', '\n'
82
};
83
 
84
const char Archive::arfmag[2] = { '`', '\n' };
85
 
86
Archive::Archive(const std::string& name, Input_file* input_file,
87
                 bool is_thin_archive, Dirsearch* dirpath, Task* task)
88
  : name_(name), input_file_(input_file), armap_(), armap_names_(),
89
    extended_names_(), armap_checked_(), seen_offsets_(), members_(),
90
    is_thin_archive_(is_thin_archive), included_member_(false),
91
    nested_archives_(), dirpath_(dirpath), task_(task), num_members_(0)
92
{
93
  this->no_export_ =
94
    parameters->options().check_excluded_libs(input_file->found_name());
95
}
96
 
97
// Set up the archive: read the symbol map and the extended name
98
// table.
99
 
100
void
101
Archive::setup()
102
{
103
  // We need to ignore empty archives.
104
  if (this->input_file_->file().filesize() == sarmag)
105
    return;
106
 
107
  // The first member of the archive should be the symbol table.
108
  std::string armap_name;
109
  section_size_type armap_size =
110
    convert_to_section_size_type(this->read_header(sarmag, false,
111
                                                   &armap_name, NULL));
112
  off_t off = sarmag;
113
  if (armap_name.empty())
114
    {
115
      this->read_armap(sarmag + sizeof(Archive_header), armap_size);
116
      off = sarmag + sizeof(Archive_header) + armap_size;
117
    }
118
  else if (!this->input_file_->options().whole_archive())
119
    gold_error(_("%s: no archive symbol table (run ranlib)"),
120
               this->name().c_str());
121
 
122
  // See if there is an extended name table.  We cache these views
123
  // because it is likely that we will want to read the following
124
  // header in the add_symbols routine.
125
  if ((off & 1) != 0)
126
    ++off;
127
  std::string xname;
128
  section_size_type extended_size =
129
    convert_to_section_size_type(this->read_header(off, true, &xname, NULL));
130
  if (xname == "/")
131
    {
132
      const unsigned char* p = this->get_view(off + sizeof(Archive_header),
133
                                              extended_size, false, true);
134
      const char* px = reinterpret_cast<const char*>(p);
135
      this->extended_names_.assign(px, extended_size);
136
    }
137
  bool preread_syms = (parameters->options().threads()
138
                       && parameters->options().preread_archive_symbols());
139
#ifndef ENABLE_THREADS
140
  preread_syms = false;
141
#else
142
  if (parameters->options().has_plugins())
143
    preread_syms = false;
144
#endif
145
  if (preread_syms)
146
    this->read_all_symbols();
147
}
148
 
149
// Unlock any nested archives.
150
 
151
void
152
Archive::unlock_nested_archives()
153
{
154
  for (Nested_archive_table::iterator p = this->nested_archives_.begin();
155
       p != this->nested_archives_.end();
156
       ++p)
157
    {
158
      p->second->unlock(this->task_);
159
    }
160
}
161
 
162
// Read the archive symbol map.
163
 
164
void
165
Archive::read_armap(off_t start, section_size_type size)
166
{
167
  // To count the total number of archive members, we'll just count
168
  // the number of times the file offset changes.  Since most archives
169
  // group the symbols in the armap by object, this ought to give us
170
  // an accurate count.
171
  off_t last_seen_offset = -1;
172
 
173
  // Read in the entire armap.
174
  const unsigned char* p = this->get_view(start, size, true, false);
175
 
176
  // Numbers in the armap are always big-endian.
177
  const elfcpp::Elf_Word* pword = reinterpret_cast<const elfcpp::Elf_Word*>(p);
178
  unsigned int nsyms = elfcpp::Swap<32, true>::readval(pword);
179
  ++pword;
180
 
181
  // Note that the addition is in units of sizeof(elfcpp::Elf_Word).
182
  const char* pnames = reinterpret_cast<const char*>(pword + nsyms);
183
  section_size_type names_size =
184
    reinterpret_cast<const char*>(p) + size - pnames;
185
  this->armap_names_.assign(pnames, names_size);
186
 
187
  this->armap_.resize(nsyms);
188
 
189
  section_offset_type name_offset = 0;
190
  for (unsigned int i = 0; i < nsyms; ++i)
191
    {
192
      this->armap_[i].name_offset = name_offset;
193
      this->armap_[i].file_offset = elfcpp::Swap<32, true>::readval(pword);
194
      name_offset += strlen(pnames + name_offset) + 1;
195
      ++pword;
196
      if (this->armap_[i].file_offset != last_seen_offset)
197
        {
198
          last_seen_offset = this->armap_[i].file_offset;
199
          ++this->num_members_;
200
        }
201
    }
202
 
203
  if (static_cast<section_size_type>(name_offset) > names_size)
204
    gold_error(_("%s: bad archive symbol table names"),
205
               this->name().c_str());
206
 
207
  // This array keeps track of which symbols are for archive elements
208
  // which we have already included in the link.
209
  this->armap_checked_.resize(nsyms);
210
}
211
 
212
// Read the header of an archive member at OFF.  Fail if something
213
// goes wrong.  Return the size of the member.  Set *PNAME to the name
214
// of the member.
215
 
216
off_t
217
Archive::read_header(off_t off, bool cache, std::string* pname,
218
                     off_t* nested_off)
219
{
220
  const unsigned char* p = this->get_view(off, sizeof(Archive_header), true,
221
                                          cache);
222
  const Archive_header* hdr = reinterpret_cast<const Archive_header*>(p);
223
  return this->interpret_header(hdr, off,  pname, nested_off);
224
}
225
 
226
// Interpret the header of HDR, the header of the archive member at
227
// file offset OFF.  Fail if something goes wrong.  Return the size of
228
// the member.  Set *PNAME to the name of the member.
229
 
230
off_t
231
Archive::interpret_header(const Archive_header* hdr, off_t off,
232
                          std::string* pname, off_t* nested_off) const
233
{
234
  if (memcmp(hdr->ar_fmag, arfmag, sizeof arfmag) != 0)
235
    {
236
      gold_error(_("%s: malformed archive header at %zu"),
237
                 this->name().c_str(), static_cast<size_t>(off));
238
      return this->input_file_->file().filesize() - off;
239
    }
240
 
241
  const int size_string_size = sizeof hdr->ar_size;
242
  char size_string[size_string_size + 1];
243
  memcpy(size_string, hdr->ar_size, size_string_size);
244
  char* ps = size_string + size_string_size;
245
  while (ps[-1] == ' ')
246
    --ps;
247
  *ps = '\0';
248
 
249
  errno = 0;
250
  char* end;
251
  off_t member_size = strtol(size_string, &end, 10);
252
  if (*end != '\0'
253
      || member_size < 0
254
      || (member_size == LONG_MAX && errno == ERANGE))
255
    {
256
      gold_error(_("%s: malformed archive header size at %zu"),
257
                 this->name().c_str(), static_cast<size_t>(off));
258
      return this->input_file_->file().filesize() - off;
259
    }
260
 
261
  if (hdr->ar_name[0] != '/')
262
    {
263
      const char* name_end = strchr(hdr->ar_name, '/');
264
      if (name_end == NULL
265
          || name_end - hdr->ar_name >= static_cast<int>(sizeof hdr->ar_name))
266
        {
267
          gold_error(_("%s: malformed archive header name at %zu"),
268
                     this->name().c_str(), static_cast<size_t>(off));
269
          return this->input_file_->file().filesize() - off;
270
        }
271
      pname->assign(hdr->ar_name, name_end - hdr->ar_name);
272
      if (nested_off != NULL)
273
        *nested_off = 0;
274
    }
275
  else if (hdr->ar_name[1] == ' ')
276
    {
277
      // This is the symbol table.
278
      pname->clear();
279
    }
280
  else if (hdr->ar_name[1] == '/')
281
    {
282
      // This is the extended name table.
283
      pname->assign(1, '/');
284
    }
285
  else
286
    {
287
      errno = 0;
288
      long x = strtol(hdr->ar_name + 1, &end, 10);
289
      long y = 0;
290
      if (*end == ':')
291
        y = strtol(end + 1, &end, 10);
292
      if (*end != ' '
293
          || x < 0
294
          || (x == LONG_MAX && errno == ERANGE)
295
          || static_cast<size_t>(x) >= this->extended_names_.size())
296
        {
297
          gold_error(_("%s: bad extended name index at %zu"),
298
                     this->name().c_str(), static_cast<size_t>(off));
299
          return this->input_file_->file().filesize() - off;
300
        }
301
 
302
      const char* name = this->extended_names_.data() + x;
303
      const char* name_end = strchr(name, '\n');
304
      if (static_cast<size_t>(name_end - name) > this->extended_names_.size()
305
          || name_end[-1] != '/')
306
        {
307
          gold_error(_("%s: bad extended name entry at header %zu"),
308
                     this->name().c_str(), static_cast<size_t>(off));
309
          return this->input_file_->file().filesize() - off;
310
        }
311
      pname->assign(name, name_end - 1 - name);
312
      if (nested_off != NULL)
313
        *nested_off = y;
314
    }
315
 
316
  return member_size;
317
}
318
 
319
// An archive member iterator.
320
 
321
class Archive::const_iterator
322
{
323
 public:
324
  // The header of an archive member.  This is what this iterator
325
  // points to.
326
  struct Header
327
  {
328
    // The name of the member.
329
    std::string name;
330
    // The file offset of the member.
331
    off_t off;
332
    // The file offset of a nested archive member.
333
    off_t nested_off;
334
    // The size of the member.
335
    off_t size;
336
  };
337
 
338
  const_iterator(Archive* archive, off_t off)
339
    : archive_(archive), off_(off)
340
  { this->read_next_header(); }
341
 
342
  const Header&
343
  operator*() const
344
  { return this->header_; }
345
 
346
  const Header*
347
  operator->() const
348
  { return &this->header_; }
349
 
350
  const_iterator&
351
  operator++()
352
  {
353
    if (this->off_ == this->archive_->file().filesize())
354
      return *this;
355
    this->off_ += sizeof(Archive_header);
356
    if (!this->archive_->is_thin_archive())
357
      this->off_ += this->header_.size;
358
    if ((this->off_ & 1) != 0)
359
      ++this->off_;
360
    this->read_next_header();
361
    return *this;
362
  }
363
 
364
  const_iterator
365
  operator++(int)
366
  {
367
    const_iterator ret = *this;
368
    ++*this;
369
    return ret;
370
  }
371
 
372
  bool
373
  operator==(const const_iterator p) const
374
  { return this->off_ == p->off; }
375
 
376
  bool
377
  operator!=(const const_iterator p) const
378
  { return this->off_ != p->off; }
379
 
380
 private:
381
  void
382
  read_next_header();
383
 
384
  // The underlying archive.
385
  Archive* archive_;
386
  // The current offset in the file.
387
  off_t off_;
388
  // The current archive header.
389
  Header header_;
390
};
391
 
392
// Read the next archive header.
393
 
394
void
395
Archive::const_iterator::read_next_header()
396
{
397
  off_t filesize = this->archive_->file().filesize();
398
  while (true)
399
    {
400
      if (filesize - this->off_ < static_cast<off_t>(sizeof(Archive_header)))
401
        {
402
          if (filesize != this->off_)
403
            {
404
              gold_error(_("%s: short archive header at %zu"),
405
                         this->archive_->filename().c_str(),
406
                         static_cast<size_t>(this->off_));
407
              this->off_ = filesize;
408
            }
409
          this->header_.off = filesize;
410
          return;
411
        }
412
 
413
      unsigned char buf[sizeof(Archive_header)];
414
      this->archive_->file().read(this->off_, sizeof(Archive_header), buf);
415
 
416
      const Archive_header* hdr = reinterpret_cast<const Archive_header*>(buf);
417
      this->header_.size =
418
        this->archive_->interpret_header(hdr, this->off_, &this->header_.name,
419
                                         &this->header_.nested_off);
420
      this->header_.off = this->off_;
421
 
422
      // Skip special members.
423
      if (!this->header_.name.empty() && this->header_.name != "/")
424
        return;
425
 
426
      this->off_ += sizeof(Archive_header) + this->header_.size;
427
      if ((this->off_ & 1) != 0)
428
        ++this->off_;
429
    }
430
}
431
 
432
// Initial iterator.
433
 
434
Archive::const_iterator
435
Archive::begin()
436
{
437
  return Archive::const_iterator(this, sarmag);
438
}
439
 
440
// Final iterator.
441
 
442
Archive::const_iterator
443
Archive::end()
444
{
445
  return Archive::const_iterator(this, this->input_file_->file().filesize());
446
}
447
 
448
// Get the file and offset for an archive member, which may be an
449
// external member of a thin archive.  Set *INPUT_FILE to the
450
// file containing the actual member, *MEMOFF to the offset
451
// within that file (0 if not a nested archive), and *MEMBER_NAME
452
// to the name of the archive member.  Return TRUE on success.
453
 
454
bool
455
Archive::get_file_and_offset(off_t off, Input_file** input_file, off_t* memoff,
456
                             off_t* memsize, std::string* member_name)
457
{
458
  off_t nested_off;
459
 
460
  *memsize = this->read_header(off, false, member_name, &nested_off);
461
 
462
  *input_file = this->input_file_;
463
  *memoff = off + static_cast<off_t>(sizeof(Archive_header));
464
 
465
  if (!this->is_thin_archive_)
466
    return true;
467
 
468
  // Adjust a relative pathname so that it is relative
469
  // to the directory containing the archive.
470
  if (!IS_ABSOLUTE_PATH(member_name->c_str()))
471
    {
472
      const char* arch_path = this->filename().c_str();
473
      const char* basename = lbasename(arch_path);
474
      if (basename > arch_path)
475
        member_name->replace(0, 0,
476
                             this->filename().substr(0, basename - arch_path));
477
    }
478
 
479
  if (nested_off > 0)
480
    {
481
      // This is a member of a nested archive.  Open the containing
482
      // archive if we don't already have it open, then do a recursive
483
      // call to include the member from that archive.
484
      Archive* arch;
485
      Nested_archive_table::const_iterator p =
486
        this->nested_archives_.find(*member_name);
487
      if (p != this->nested_archives_.end())
488
        arch = p->second;
489
      else
490
        {
491
          Input_file_argument* input_file_arg =
492
            new Input_file_argument(member_name->c_str(),
493
                                    Input_file_argument::INPUT_FILE_TYPE_FILE,
494
                                    "", false, parameters->options());
495
          *input_file = new Input_file(input_file_arg);
496
          int dummy = 0;
497
          if (!(*input_file)->open(*this->dirpath_, this->task_, &dummy))
498
            return false;
499
          arch = new Archive(*member_name, *input_file, false, this->dirpath_,
500
                             this->task_);
501
          arch->setup();
502
          std::pair<Nested_archive_table::iterator, bool> ins =
503
            this->nested_archives_.insert(std::make_pair(*member_name, arch));
504
          gold_assert(ins.second);
505
        }
506
      return arch->get_file_and_offset(nested_off, input_file, memoff,
507
                                       memsize, member_name);
508
    }
509
 
510
  // This is an external member of a thin archive.  Open the
511
  // file as a regular relocatable object file.
512
  Input_file_argument* input_file_arg =
513
      new Input_file_argument(member_name->c_str(),
514
                              Input_file_argument::INPUT_FILE_TYPE_FILE,
515
                              "", false, this->input_file_->options());
516
  *input_file = new Input_file(input_file_arg);
517
  int dummy = 0;
518
  if (!(*input_file)->open(*this->dirpath_, this->task_, &dummy))
519
    return false;
520
 
521
  *memoff = 0;
522
  *memsize = (*input_file)->file().filesize();
523
  return true;
524
}
525
 
526
// Return an ELF object for the member at offset OFF.  If the ELF
527
// object has an unsupported target type, set *PUNCONFIGURED to true
528
// and return NULL.
529
 
530
Object*
531
Archive::get_elf_object_for_member(off_t off, bool* punconfigured)
532
{
533
  *punconfigured = false;
534
 
535
  Input_file* input_file;
536
  off_t memoff;
537
  off_t memsize;
538
  std::string member_name;
539
  if (!this->get_file_and_offset(off, &input_file, &memoff, &memsize,
540
                                 &member_name))
541
    return NULL;
542
 
543
  if (parameters->options().has_plugins())
544
    {
545
      Object* obj = parameters->options().plugins()->claim_file(input_file,
546
                                                                memoff,
547
                                                                memsize);
548
      if (obj != NULL)
549
        {
550
          // The input file was claimed by a plugin, and its symbols
551
          // have been provided by the plugin.
552
          return obj;
553
        }
554
    }
555
 
556
  const unsigned char* ehdr;
557
  int read_size;
558
  if (!is_elf_object(input_file, memoff, &ehdr, &read_size))
559
    {
560
      gold_error(_("%s: member at %zu is not an ELF object"),
561
                 this->name().c_str(), static_cast<size_t>(off));
562
      return NULL;
563
    }
564
 
565
  Object *obj = make_elf_object((std::string(this->input_file_->filename())
566
                                 + "(" + member_name + ")"),
567
                                input_file, memoff, ehdr, read_size,
568
                                punconfigured);
569
  if (obj == NULL)
570
    return NULL;
571
  obj->set_no_export(this->no_export());
572
  return obj;
573
}
574
 
575
// Read the symbols from all the archive members in the link.
576
 
577
void
578
Archive::read_all_symbols()
579
{
580
  for (Archive::const_iterator p = this->begin();
581
       p != this->end();
582
       ++p)
583
    this->read_symbols(p->off);
584
}
585
 
586
// Read the symbols from an archive member in the link.  OFF is the file
587
// offset of the member header.
588
 
589
void
590
Archive::read_symbols(off_t off)
591
{
592
  bool dummy;
593
  Object* obj = this->get_elf_object_for_member(off, &dummy);
594
 
595
  if (obj == NULL)
596
    return;
597
 
598
  Read_symbols_data* sd = new Read_symbols_data;
599
  obj->read_symbols(sd);
600
  Archive_member member(obj, sd);
601
  this->members_[off] = member;
602
}
603
 
604
// Select members from the archive and add them to the link.  We walk
605
// through the elements in the archive map, and look each one up in
606
// the symbol table.  If it exists as a strong undefined symbol, we
607
// pull in the corresponding element.  We have to do this in a loop,
608
// since pulling in one element may create new undefined symbols which
609
// may be satisfied by other objects in the archive.  Return true in
610
// the normal case, false if the first member we tried to add from
611
// this archive had an incompatible target.
612
 
613
bool
614
Archive::add_symbols(Symbol_table* symtab, Layout* layout,
615
                     Input_objects* input_objects, Mapfile* mapfile)
616
{
617
  ++Archive::total_archives;
618
 
619
  if (this->input_file_->options().whole_archive())
620
    return this->include_all_members(symtab, layout, input_objects,
621
                                     mapfile);
622
 
623
  Archive::total_members += this->num_members_;
624
 
625
  input_objects->archive_start(this);
626
 
627
  const size_t armap_size = this->armap_.size();
628
 
629
  // This is a quick optimization, since we usually see many symbols
630
  // in a row with the same offset.  last_seen_offset holds the last
631
  // offset we saw that was present in the seen_offsets_ set.
632
  off_t last_seen_offset = -1;
633
 
634
  // Track which symbols in the symbol table we've already found to be
635
  // defined.
636
 
637
  char* tmpbuf = NULL;
638
  size_t tmpbuflen = 0;
639
  bool added_new_object;
640
  do
641
    {
642
      added_new_object = false;
643
      for (size_t i = 0; i < armap_size; ++i)
644
        {
645
          if (this->armap_checked_[i])
646
            continue;
647
          if (this->armap_[i].file_offset == last_seen_offset)
648
            {
649
              this->armap_checked_[i] = true;
650
              continue;
651
            }
652
          if (this->seen_offsets_.find(this->armap_[i].file_offset)
653
              != this->seen_offsets_.end())
654
            {
655
              this->armap_checked_[i] = true;
656
              last_seen_offset = this->armap_[i].file_offset;
657
              continue;
658
            }
659
 
660
          const char* sym_name = (this->armap_names_.data()
661
                                  + this->armap_[i].name_offset);
662
 
663
          // In an object file, and therefore in an archive map, an
664
          // '@' in the name separates the symbol name from the
665
          // version name.  If there are two '@' characters, this is
666
          // the default version.
667
          const char* ver = strchr(sym_name, '@');
668
          bool def = false;
669
          if (ver != NULL)
670
            {
671
              size_t symlen = ver - sym_name;
672
              if (symlen + 1 > tmpbuflen)
673
                {
674
                  tmpbuf = static_cast<char*>(realloc(tmpbuf, symlen + 1));
675
                  tmpbuflen = symlen + 1;
676
                }
677
              memcpy(tmpbuf, sym_name, symlen);
678
              tmpbuf[symlen] = '\0';
679
              sym_name = tmpbuf;
680
 
681
              ++ver;
682
              if (*ver == '@')
683
                {
684
                  ++ver;
685
                  def = true;
686
                }
687
            }
688
 
689
          Symbol* sym = symtab->lookup(sym_name, ver);
690
          if (def
691
              && (sym == NULL
692
                  || !sym->is_undefined()
693
                  || sym->binding() == elfcpp::STB_WEAK))
694
            sym = symtab->lookup(sym_name, NULL);
695
 
696
          if (sym == NULL)
697
            {
698
              // Check whether the symbol was named in a -u option.
699
              if (!parameters->options().is_undefined(sym_name))
700
                continue;
701
            }
702
          else if (!sym->is_undefined())
703
            {
704
              this->armap_checked_[i] = true;
705
              continue;
706
            }
707
          else if (sym->binding() == elfcpp::STB_WEAK)
708
            continue;
709
 
710
          // We want to include this object in the link.
711
          last_seen_offset = this->armap_[i].file_offset;
712
          this->seen_offsets_.insert(last_seen_offset);
713
          this->armap_checked_[i] = true;
714
 
715
          std::string why;
716
          if (sym == NULL)
717
            {
718
              why = "-u ";
719
              why += sym_name;
720
            }
721
          if (!this->include_member(symtab, layout, input_objects,
722
                                    last_seen_offset, mapfile, sym,
723
                                    why.c_str()))
724
            {
725
              if (tmpbuf != NULL)
726
                free(tmpbuf);
727
              return false;
728
            }
729
 
730
          added_new_object = true;
731
        }
732
    }
733
  while (added_new_object);
734
 
735
  if (tmpbuf != NULL)
736
    free(tmpbuf);
737
 
738
  input_objects->archive_stop(this);
739
 
740
  return true;
741
}
742
 
743
// Include all the archive members in the link.  This is for --whole-archive.
744
 
745
bool
746
Archive::include_all_members(Symbol_table* symtab, Layout* layout,
747
                             Input_objects* input_objects, Mapfile* mapfile)
748
{
749
  input_objects->archive_start(this);
750
 
751
  if (this->members_.size() > 0)
752
    {
753
      std::map<off_t, Archive_member>::const_iterator p;
754
      for (p = this->members_.begin();
755
           p != this->members_.end();
756
           ++p)
757
        {
758
          if (!this->include_member(symtab, layout, input_objects, p->first,
759
                                    mapfile, NULL, "--whole-archive"))
760
            return false;
761
          ++Archive::total_members;
762
        }
763
    }
764
  else
765
    {
766
      for (Archive::const_iterator p = this->begin();
767
           p != this->end();
768
           ++p)
769
        {
770
          if (!this->include_member(symtab, layout, input_objects, p->off,
771
                                    mapfile, NULL, "--whole-archive"))
772
            return false;
773
          ++Archive::total_members;
774
        }
775
    }
776
 
777
  input_objects->archive_stop(this);
778
 
779
  return true;
780
}
781
 
782
// Return the number of members in the archive.  This is only used for
783
// reports.
784
 
785
size_t
786
Archive::count_members()
787
{
788
  size_t ret = 0;
789
  for (Archive::const_iterator p = this->begin();
790
       p != this->end();
791
       ++p)
792
    ++ret;
793
  return ret;
794
}
795
 
796
// Include an archive member in the link.  OFF is the file offset of
797
// the member header.  WHY is the reason we are including this member.
798
// Return true if we added the member or if we had an error, return
799
// false if this was the first member we tried to add from this
800
// archive and it had an incompatible format.
801
 
802
bool
803
Archive::include_member(Symbol_table* symtab, Layout* layout,
804
                        Input_objects* input_objects, off_t off,
805
                        Mapfile* mapfile, Symbol* sym, const char* why)
806
{
807
  ++Archive::total_members_loaded;
808
 
809
  std::map<off_t, Archive_member>::const_iterator p = this->members_.find(off);
810
  if (p != this->members_.end())
811
    {
812
      Object *obj = p->second.obj_;
813
 
814
      Read_symbols_data *sd = p->second.sd_;
815
      if (mapfile != NULL)
816
        mapfile->report_include_archive_member(obj->name(), sym, why);
817
      if (input_objects->add_object(obj))
818
        {
819
          obj->layout(symtab, layout, sd);
820
          obj->add_symbols(symtab, sd, layout);
821
          this->included_member_ = true;
822
        }
823
      delete sd;
824
      return true;
825
    }
826
 
827
  bool unconfigured;
828
  Object* obj = this->get_elf_object_for_member(off, &unconfigured);
829
 
830
  if (!this->included_member_
831
      && this->searched_for()
832
      && obj == NULL
833
      && unconfigured)
834
    {
835
      if (obj != NULL)
836
        delete obj;
837
      return false;
838
    }
839
 
840
  if (obj == NULL)
841
    return true;
842
 
843
  if (mapfile != NULL)
844
    mapfile->report_include_archive_member(obj->name(), sym, why);
845
 
846
  Pluginobj* pluginobj = obj->pluginobj();
847
  if (pluginobj != NULL)
848
    {
849
      pluginobj->add_symbols(symtab, NULL, layout);
850
      this->included_member_ = true;
851
      return true;
852
    }
853
 
854
  if (!input_objects->add_object(obj))
855
    delete obj;
856
  else
857
    {
858
      Read_symbols_data sd;
859
      obj->read_symbols(&sd);
860
      obj->layout(symtab, layout, &sd);
861
      obj->add_symbols(symtab, &sd, layout);
862
 
863
      // If this is an external member of a thin archive, unlock the file
864
      // for the next task.
865
      if (obj->offset() == 0)
866
        obj->unlock(this->task_);
867
 
868
      this->included_member_ = true;
869
    }
870
 
871
  return true;
872
}
873
 
874
// Print statistical information to stderr.  This is used for --stats.
875
 
876
void
877
Archive::print_stats()
878
{
879
  fprintf(stderr, _("%s: archive libraries: %u\n"),
880
          program_name, Archive::total_archives);
881
  fprintf(stderr, _("%s: total archive members: %u\n"),
882
          program_name, Archive::total_members);
883
  fprintf(stderr, _("%s: loaded archive members: %u\n"),
884
          program_name, Archive::total_members_loaded);
885
}
886
 
887
// Add_archive_symbols methods.
888
 
889
Add_archive_symbols::~Add_archive_symbols()
890
{
891
  if (this->this_blocker_ != NULL)
892
    delete this->this_blocker_;
893
  // next_blocker_ is deleted by the task associated with the next
894
  // input file.
895
}
896
 
897
// Return whether we can add the archive symbols.  We are blocked by
898
// this_blocker_.  We block next_blocker_.  We also lock the file.
899
 
900
Task_token*
901
Add_archive_symbols::is_runnable()
902
{
903
  if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
904
    return this->this_blocker_;
905
  return NULL;
906
}
907
 
908
void
909
Add_archive_symbols::locks(Task_locker* tl)
910
{
911
  tl->add(this, this->next_blocker_);
912
  tl->add(this, this->archive_->token());
913
}
914
 
915
void
916
Add_archive_symbols::run(Workqueue* workqueue)
917
{
918
  bool added = this->archive_->add_symbols(this->symtab_, this->layout_,
919
                                           this->input_objects_,
920
                                           this->mapfile_);
921
  this->archive_->unlock_nested_archives();
922
 
923
  this->archive_->release();
924
  this->archive_->clear_uncached_views();
925
 
926
  if (!added)
927
    {
928
      // This archive holds object files which are incompatible with
929
      // our output file.
930
      Read_symbols::incompatible_warning(this->input_argument_,
931
                                         this->archive_->input_file());
932
      Read_symbols::requeue(workqueue, this->input_objects_, this->symtab_,
933
                            this->layout_, this->dirpath_, this->dirindex_,
934
                            this->mapfile_, this->input_argument_,
935
                            this->input_group_, this->next_blocker_);
936
      delete this->archive_;
937
      return;
938
    }
939
 
940
  if (this->input_group_ != NULL)
941
    this->input_group_->add_archive(this->archive_);
942
  else
943
    {
944
      // We no longer need to know about this archive.
945
      delete this->archive_;
946
      this->archive_ = NULL;
947
    }
948
}
949
 
950
} // End namespace gold.

powered by: WebSVN 2.1.0

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