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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gold/] [archive.cc] - Blame information for rev 90

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

Line No. Rev Author Line
1 27 khays
// archive.cc -- archive support 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 <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 "layout.h"
40
#include "archive.h"
41
#include "plugin.h"
42
#include "incremental.h"
43
 
44
namespace gold
45
{
46
 
47
// Library_base methods.
48
 
49
// Determine whether a definition of SYM_NAME should cause an archive
50
// library member to be included in the link.  Returns SHOULD_INCLUDE_YES
51
// if the symbol is referenced but not defined, SHOULD_INCLUDE_NO if the
52
// symbol is already defined, and SHOULD_INCLUDE_UNKNOWN if the symbol is
53
// neither referenced nor defined.
54
 
55
Library_base::Should_include
56
Library_base::should_include_member(Symbol_table* symtab, Layout* layout,
57
                                    const char* sym_name, Symbol** symp,
58
                                    std::string* why, char** tmpbufp,
59
                                    size_t* tmpbuflen)
60
{
61
  // In an object file, and therefore in an archive map, an
62
  // '@' in the name separates the symbol name from the
63
  // version name.  If there are two '@' characters, this is
64
  // the default version.
65
  char* tmpbuf = *tmpbufp;
66
  const char* ver = strchr(sym_name, '@');
67
  bool def = false;
68
  if (ver != NULL)
69
    {
70
      size_t symlen = ver - sym_name;
71
      if (symlen + 1 > *tmpbuflen)
72
        {
73
          tmpbuf = static_cast<char*>(xrealloc(tmpbuf, symlen + 1));
74
          *tmpbufp = tmpbuf;
75
          *tmpbuflen = symlen + 1;
76
        }
77
      memcpy(tmpbuf, sym_name, symlen);
78
      tmpbuf[symlen] = '\0';
79
      sym_name = tmpbuf;
80
 
81
      ++ver;
82
      if (*ver == '@')
83
        {
84
          ++ver;
85
          def = true;
86
        }
87
    }
88
 
89
  Symbol* sym = symtab->lookup(sym_name, ver);
90
  if (def
91
      && ver != NULL
92
      && (sym == NULL
93
          || !sym->is_undefined()
94
          || sym->binding() == elfcpp::STB_WEAK))
95
    sym = symtab->lookup(sym_name, NULL);
96
 
97
  *symp = sym;
98
 
99
  if (sym == NULL)
100
    {
101
      // Check whether the symbol was named in a -u option.
102
      if (parameters->options().is_undefined(sym_name))
103
        {
104
          *why = "-u ";
105
          *why += sym_name;
106
        }
107
      else if (layout->script_options()->is_referenced(sym_name))
108
        {
109
          size_t alc = 100 + strlen(sym_name);
110
          char* buf = new char[alc];
111
          snprintf(buf, alc, _("script or expression reference to %s"),
112
                   sym_name);
113
          *why = buf;
114
          delete[] buf;
115
        }
116
      else if (strcmp(sym_name, parameters->entry()) == 0)
117
        {
118
          *why = "entry symbol ";
119
          *why += sym_name;
120
        }
121
      else
122
        return Library_base::SHOULD_INCLUDE_UNKNOWN;
123
    }
124
  else if (!sym->is_undefined())
125
    return Library_base::SHOULD_INCLUDE_NO;
126
  // PR 12001: Do not include an archive when the undefined
127
  // symbol has actually been defined on the command line.
128
  else if (layout->script_options()->is_pending_assignment(sym_name))
129
    return Library_base::SHOULD_INCLUDE_NO;
130
  else if (sym->binding() == elfcpp::STB_WEAK)
131
    return Library_base::SHOULD_INCLUDE_UNKNOWN;
132
 
133
  return Library_base::SHOULD_INCLUDE_YES;
134
}
135
 
136
// The header of an entry in the archive.  This is all readable text,
137
// padded with spaces where necessary.  If the contents of an archive
138
// are all text file, the entire archive is readable.
139
 
140
struct Archive::Archive_header
141
{
142
  // The entry name.
143
  char ar_name[16];
144
  // The file modification time.
145
  char ar_date[12];
146
  // The user's UID in decimal.
147
  char ar_uid[6];
148
  // The user's GID in decimal.
149
  char ar_gid[6];
150
  // The file mode in octal.
151
  char ar_mode[8];
152
  // The file size in decimal.
153
  char ar_size[10];
154
  // The final magic code.
155
  char ar_fmag[2];
156
};
157
 
158
// Class Archive static variables.
159
unsigned int Archive::total_archives;
160
unsigned int Archive::total_members;
161
unsigned int Archive::total_members_loaded;
162
 
163
// Archive methods.
164
 
165
const char Archive::armag[sarmag] =
166
{
167
  '!', '<', 'a', 'r', 'c', 'h', '>', '\n'
168
};
169
 
170
const char Archive::armagt[sarmag] =
171
{
172
  '!', '<', 't', 'h', 'i', 'n', '>', '\n'
173
};
174
 
175
const char Archive::arfmag[2] = { '`', '\n' };
176
 
177
Archive::Archive(const std::string& name, Input_file* input_file,
178
                 bool is_thin_archive, Dirsearch* dirpath, Task* task)
179
  : Library_base(task), name_(name), input_file_(input_file), armap_(),
180
    armap_names_(), extended_names_(), armap_checked_(), seen_offsets_(),
181
    members_(), is_thin_archive_(is_thin_archive), included_member_(false),
182
    nested_archives_(), dirpath_(dirpath), num_members_(0),
183
    included_all_members_(false)
184
{
185
  this->no_export_ =
186
    parameters->options().check_excluded_libs(input_file->found_name());
187
}
188
 
189
// Set up the archive: read the symbol map and the extended name
190
// table.
191
 
192
void
193
Archive::setup()
194
{
195
  // We need to ignore empty archives.
196
  if (this->input_file_->file().filesize() == sarmag)
197
    return;
198
 
199
  // The first member of the archive should be the symbol table.
200
  std::string armap_name;
201
  off_t header_size = this->read_header(sarmag, false, &armap_name, NULL);
202
  if (header_size == -1)
203
    return;
204
 
205
  section_size_type armap_size = convert_to_section_size_type(header_size);
206
  off_t off = sarmag;
207
  if (armap_name.empty())
208
    {
209
      this->read_armap(sarmag + sizeof(Archive_header), armap_size);
210
      off = sarmag + sizeof(Archive_header) + armap_size;
211
    }
212
  else if (!this->input_file_->options().whole_archive())
213
    gold_error(_("%s: no archive symbol table (run ranlib)"),
214
               this->name().c_str());
215
 
216
  // See if there is an extended name table.  We cache these views
217
  // because it is likely that we will want to read the following
218
  // header in the add_symbols routine.
219
  if ((off & 1) != 0)
220
    ++off;
221
  std::string xname;
222
  header_size = this->read_header(off, true, &xname, NULL);
223
  if (header_size == -1)
224
    return;
225
 
226
  section_size_type extended_size = convert_to_section_size_type(header_size);
227
  if (xname == "/")
228
    {
229
      const unsigned char* p = this->get_view(off + sizeof(Archive_header),
230
                                              extended_size, false, true);
231
      const char* px = reinterpret_cast<const char*>(p);
232
      this->extended_names_.assign(px, extended_size);
233
    }
234
  bool preread_syms = (parameters->options().threads()
235
                       && parameters->options().preread_archive_symbols());
236
#ifndef ENABLE_THREADS
237
  preread_syms = false;
238
#else
239
  if (parameters->options().has_plugins())
240
    preread_syms = false;
241
#endif
242
  if (preread_syms)
243
    this->read_all_symbols();
244
}
245
 
246
// Unlock any nested archives.
247
 
248
void
249
Archive::unlock_nested_archives()
250
{
251
  for (Nested_archive_table::iterator p = this->nested_archives_.begin();
252
       p != this->nested_archives_.end();
253
       ++p)
254
    {
255
      p->second->unlock(this->task_);
256
    }
257
}
258
 
259
// Read the archive symbol map.
260
 
261
void
262
Archive::read_armap(off_t start, section_size_type size)
263
{
264
  // To count the total number of archive members, we'll just count
265
  // the number of times the file offset changes.  Since most archives
266
  // group the symbols in the armap by object, this ought to give us
267
  // an accurate count.
268
  off_t last_seen_offset = -1;
269
 
270
  // Read in the entire armap.
271
  const unsigned char* p = this->get_view(start, size, true, false);
272
 
273
  // Numbers in the armap are always big-endian.
274
  const elfcpp::Elf_Word* pword = reinterpret_cast<const elfcpp::Elf_Word*>(p);
275
  unsigned int nsyms = elfcpp::Swap<32, true>::readval(pword);
276
  ++pword;
277
 
278
  // Note that the addition is in units of sizeof(elfcpp::Elf_Word).
279
  const char* pnames = reinterpret_cast<const char*>(pword + nsyms);
280
  section_size_type names_size =
281
    reinterpret_cast<const char*>(p) + size - pnames;
282
  this->armap_names_.assign(pnames, names_size);
283
 
284
  this->armap_.resize(nsyms);
285
 
286
  section_offset_type name_offset = 0;
287
  for (unsigned int i = 0; i < nsyms; ++i)
288
    {
289
      this->armap_[i].name_offset = name_offset;
290
      this->armap_[i].file_offset = elfcpp::Swap<32, true>::readval(pword);
291
      name_offset += strlen(pnames + name_offset) + 1;
292
      ++pword;
293
      if (this->armap_[i].file_offset != last_seen_offset)
294
        {
295
          last_seen_offset = this->armap_[i].file_offset;
296
          ++this->num_members_;
297
        }
298
    }
299
 
300
  if (static_cast<section_size_type>(name_offset) > names_size)
301
    gold_error(_("%s: bad archive symbol table names"),
302
               this->name().c_str());
303
 
304
  // This array keeps track of which symbols are for archive elements
305
  // which we have already included in the link.
306
  this->armap_checked_.resize(nsyms);
307
}
308
 
309
// Read the header of an archive member at OFF.  Fail if something
310
// goes wrong.  Return the size of the member.  Set *PNAME to the name
311
// of the member.
312
 
313
off_t
314
Archive::read_header(off_t off, bool cache, std::string* pname,
315
                     off_t* nested_off)
316
{
317
  const unsigned char* p = this->get_view(off, sizeof(Archive_header), true,
318
                                          cache);
319
  const Archive_header* hdr = reinterpret_cast<const Archive_header*>(p);
320
  return this->interpret_header(hdr, off,  pname, nested_off);
321
}
322
 
323
// Interpret the header of HDR, the header of the archive member at
324
// file offset OFF.  Return the size of the member, or -1 if something
325
// has gone wrong.  Set *PNAME to the name of the member.
326
 
327
off_t
328
Archive::interpret_header(const Archive_header* hdr, off_t off,
329
                          std::string* pname, off_t* nested_off) const
330
{
331
  if (memcmp(hdr->ar_fmag, arfmag, sizeof arfmag) != 0)
332
    {
333
      gold_error(_("%s: malformed archive header at %zu"),
334
                 this->name().c_str(), static_cast<size_t>(off));
335
      return -1;
336
    }
337
 
338
  const int size_string_size = sizeof hdr->ar_size;
339
  char size_string[size_string_size + 1];
340
  memcpy(size_string, hdr->ar_size, size_string_size);
341
  char* ps = size_string + size_string_size;
342
  while (ps[-1] == ' ')
343
    --ps;
344
  *ps = '\0';
345
 
346
  errno = 0;
347
  char* end;
348
  off_t member_size = strtol(size_string, &end, 10);
349
  if (*end != '\0'
350
      || member_size < 0
351
      || (member_size == LONG_MAX && errno == ERANGE))
352
    {
353
      gold_error(_("%s: malformed archive header size at %zu"),
354
                 this->name().c_str(), static_cast<size_t>(off));
355
      return -1;
356
    }
357
 
358
  if (hdr->ar_name[0] != '/')
359
    {
360
      const char* name_end = strchr(hdr->ar_name, '/');
361
      if (name_end == NULL
362
          || name_end - hdr->ar_name >= static_cast<int>(sizeof hdr->ar_name))
363
        {
364
          gold_error(_("%s: malformed archive header name at %zu"),
365
                     this->name().c_str(), static_cast<size_t>(off));
366
          return -1;
367
        }
368
      pname->assign(hdr->ar_name, name_end - hdr->ar_name);
369
      if (nested_off != NULL)
370
        *nested_off = 0;
371
    }
372
  else if (hdr->ar_name[1] == ' ')
373
    {
374
      // This is the symbol table.
375
      if (!pname->empty())
376
        pname->clear();
377
    }
378
  else if (hdr->ar_name[1] == '/')
379
    {
380
      // This is the extended name table.
381
      pname->assign(1, '/');
382
    }
383
  else
384
    {
385
      errno = 0;
386
      long x = strtol(hdr->ar_name + 1, &end, 10);
387
      long y = 0;
388
      if (*end == ':')
389
        y = strtol(end + 1, &end, 10);
390
      if (*end != ' '
391
          || x < 0
392
          || (x == LONG_MAX && errno == ERANGE)
393
          || static_cast<size_t>(x) >= this->extended_names_.size())
394
        {
395
          gold_error(_("%s: bad extended name index at %zu"),
396
                     this->name().c_str(), static_cast<size_t>(off));
397
          return -1;
398
        }
399
 
400
      const char* name = this->extended_names_.data() + x;
401
      const char* name_end = strchr(name, '\n');
402
      if (static_cast<size_t>(name_end - name) > this->extended_names_.size()
403
          || name_end[-1] != '/')
404
        {
405
          gold_error(_("%s: bad extended name entry at header %zu"),
406
                     this->name().c_str(), static_cast<size_t>(off));
407
          return -1;
408
        }
409
      pname->assign(name, name_end - 1 - name);
410
      if (nested_off != NULL)
411
        *nested_off = y;
412
    }
413
 
414
  return member_size;
415
}
416
 
417
// An archive member iterator.
418
 
419
class Archive::const_iterator
420
{
421
 public:
422
  // The header of an archive member.  This is what this iterator
423
  // points to.
424
  struct Header
425
  {
426
    // The name of the member.
427
    std::string name;
428
    // The file offset of the member.
429
    off_t off;
430
    // The file offset of a nested archive member.
431
    off_t nested_off;
432
    // The size of the member.
433
    off_t size;
434
  };
435
 
436
  const_iterator(Archive* archive, off_t off)
437
    : archive_(archive), off_(off)
438
  { this->read_next_header(); }
439
 
440
  const Header&
441
  operator*() const
442
  { return this->header_; }
443
 
444
  const Header*
445
  operator->() const
446
  { return &this->header_; }
447
 
448
  const_iterator&
449
  operator++()
450
  {
451
    if (this->off_ == this->archive_->file().filesize())
452
      return *this;
453
    this->off_ += sizeof(Archive_header);
454
    if (!this->archive_->is_thin_archive())
455
      this->off_ += this->header_.size;
456
    if ((this->off_ & 1) != 0)
457
      ++this->off_;
458
    this->read_next_header();
459
    return *this;
460
  }
461
 
462
  const_iterator
463
  operator++(int)
464
  {
465
    const_iterator ret = *this;
466
    ++*this;
467
    return ret;
468
  }
469
 
470
  bool
471
  operator==(const const_iterator p) const
472
  { return this->off_ == p->off; }
473
 
474
  bool
475
  operator!=(const const_iterator p) const
476
  { return this->off_ != p->off; }
477
 
478
 private:
479
  void
480
  read_next_header();
481
 
482
  // The underlying archive.
483
  Archive* archive_;
484
  // The current offset in the file.
485
  off_t off_;
486
  // The current archive header.
487
  Header header_;
488
};
489
 
490
// Read the next archive header.
491
 
492
void
493
Archive::const_iterator::read_next_header()
494
{
495
  off_t filesize = this->archive_->file().filesize();
496
  while (true)
497
    {
498
      if (filesize - this->off_ < static_cast<off_t>(sizeof(Archive_header)))
499
        {
500
          if (filesize != this->off_)
501
            {
502
              gold_error(_("%s: short archive header at %zu"),
503
                         this->archive_->filename().c_str(),
504
                         static_cast<size_t>(this->off_));
505
              this->off_ = filesize;
506
            }
507
          this->header_.off = filesize;
508
          return;
509
        }
510
 
511
      unsigned char buf[sizeof(Archive_header)];
512
      this->archive_->file().read(this->off_, sizeof(Archive_header), buf);
513
 
514
      const Archive_header* hdr = reinterpret_cast<const Archive_header*>(buf);
515
      off_t size = this->archive_->interpret_header(hdr, this->off_,
516
                                                    &this->header_.name,
517
                                                    &this->header_.nested_off);
518
      if (size == -1)
519
        {
520
          this->header_.off = filesize;
521
          return;
522
        }
523
 
524
      this->header_.size = size;
525
      this->header_.off = this->off_;
526
 
527
      // Skip special members.
528
      if (!this->header_.name.empty() && this->header_.name != "/")
529
        return;
530
 
531
      this->off_ += sizeof(Archive_header) + this->header_.size;
532
      if ((this->off_ & 1) != 0)
533
        ++this->off_;
534
    }
535
}
536
 
537
// Initial iterator.
538
 
539
Archive::const_iterator
540
Archive::begin()
541
{
542
  return Archive::const_iterator(this, sarmag);
543
}
544
 
545
// Final iterator.
546
 
547
Archive::const_iterator
548
Archive::end()
549
{
550
  return Archive::const_iterator(this, this->input_file_->file().filesize());
551
}
552
 
553
// Get the file and offset for an archive member, which may be an
554
// external member of a thin archive.  Set *INPUT_FILE to the
555
// file containing the actual member, *MEMOFF to the offset
556
// within that file (0 if not a nested archive), and *MEMBER_NAME
557
// to the name of the archive member.  Return TRUE on success.
558
 
559
bool
560
Archive::get_file_and_offset(off_t off, Input_file** input_file, off_t* memoff,
561
                             off_t* memsize, std::string* member_name)
562
{
563
  off_t nested_off;
564
 
565
  *memsize = this->read_header(off, false, member_name, &nested_off);
566
  if (*memsize == -1)
567
    return false;
568
 
569
  *input_file = this->input_file_;
570
  *memoff = off + static_cast<off_t>(sizeof(Archive_header));
571
 
572
  if (!this->is_thin_archive_)
573
    return true;
574
 
575
  // Adjust a relative pathname so that it is relative
576
  // to the directory containing the archive.
577
  if (!IS_ABSOLUTE_PATH(member_name->c_str()))
578
    {
579
      const char* arch_path = this->filename().c_str();
580
      const char* basename = lbasename(arch_path);
581
      if (basename > arch_path)
582
        member_name->replace(0, 0,
583
                             this->filename().substr(0, basename - arch_path));
584
    }
585
 
586
  if (nested_off > 0)
587
    {
588
      // This is a member of a nested archive.  Open the containing
589
      // archive if we don't already have it open, then do a recursive
590
      // call to include the member from that archive.
591
      Archive* arch;
592
      Nested_archive_table::const_iterator p =
593
        this->nested_archives_.find(*member_name);
594
      if (p != this->nested_archives_.end())
595
        arch = p->second;
596
      else
597
        {
598
          Input_file_argument* input_file_arg =
599
            new Input_file_argument(member_name->c_str(),
600
                                    Input_file_argument::INPUT_FILE_TYPE_FILE,
601
                                    "", false, parameters->options());
602
          *input_file = new Input_file(input_file_arg);
603
          int dummy = 0;
604
          if (!(*input_file)->open(*this->dirpath_, this->task_, &dummy))
605
            return false;
606
          arch = new Archive(*member_name, *input_file, false, this->dirpath_,
607
                             this->task_);
608
          arch->setup();
609
          std::pair<Nested_archive_table::iterator, bool> ins =
610
            this->nested_archives_.insert(std::make_pair(*member_name, arch));
611
          gold_assert(ins.second);
612
        }
613
      return arch->get_file_and_offset(nested_off, input_file, memoff,
614
                                       memsize, member_name);
615
    }
616
 
617
  // This is an external member of a thin archive.  Open the
618
  // file as a regular relocatable object file.
619
  Input_file_argument* input_file_arg =
620
      new Input_file_argument(member_name->c_str(),
621
                              Input_file_argument::INPUT_FILE_TYPE_FILE,
622
                              "", false, this->input_file_->options());
623
  *input_file = new Input_file(input_file_arg);
624
  int dummy = 0;
625
  if (!(*input_file)->open(*this->dirpath_, this->task_, &dummy))
626
    return false;
627
 
628
  *memoff = 0;
629
  *memsize = (*input_file)->file().filesize();
630
  return true;
631
}
632
 
633
// Return an ELF object for the member at offset OFF.  If
634
// PUNCONFIGURED is not NULL, then if the ELF object has an
635
// unsupported target type, set *PUNCONFIGURED to true and return
636
// NULL.
637
 
638
Object*
639
Archive::get_elf_object_for_member(off_t off, bool* punconfigured)
640
{
641
  if (punconfigured != NULL)
642
    *punconfigured = false;
643
 
644
  Input_file* input_file;
645
  off_t memoff;
646
  off_t memsize;
647
  std::string member_name;
648
  if (!this->get_file_and_offset(off, &input_file, &memoff, &memsize,
649
                                 &member_name))
650
    return NULL;
651
 
652
  if (parameters->options().has_plugins())
653
    {
654
      Object* obj = parameters->options().plugins()->claim_file(input_file,
655
                                                                memoff,
656
                                                                memsize);
657
      if (obj != NULL)
658
        {
659
          // The input file was claimed by a plugin, and its symbols
660
          // have been provided by the plugin.
661
          return obj;
662
        }
663
    }
664
 
665
  const unsigned char* ehdr;
666
  int read_size;
667
  if (!is_elf_object(input_file, memoff, &ehdr, &read_size))
668
    {
669
      gold_error(_("%s: member at %zu is not an ELF object"),
670
                 this->name().c_str(), static_cast<size_t>(off));
671
      return NULL;
672
    }
673
 
674
  Object* obj = make_elf_object((std::string(this->input_file_->filename())
675
                                 + "(" + member_name + ")"),
676
                                input_file, memoff, ehdr, read_size,
677
                                punconfigured);
678
  if (obj == NULL)
679
    return NULL;
680
  obj->set_no_export(this->no_export());
681
  return obj;
682
}
683
 
684
// Read the symbols from all the archive members in the link.
685
 
686
void
687
Archive::read_all_symbols()
688
{
689
  for (Archive::const_iterator p = this->begin();
690
       p != this->end();
691
       ++p)
692
    this->read_symbols(p->off);
693
}
694
 
695
// Read the symbols from an archive member in the link.  OFF is the file
696
// offset of the member header.
697
 
698
void
699
Archive::read_symbols(off_t off)
700
{
701
  Object* obj = this->get_elf_object_for_member(off, NULL);
702
  if (obj == NULL)
703
    return;
704
 
705
  Read_symbols_data* sd = new Read_symbols_data;
706
  obj->read_symbols(sd);
707
  Archive_member member(obj, sd);
708
  this->members_[off] = member;
709
}
710
 
711
// Select members from the archive and add them to the link.  We walk
712
// through the elements in the archive map, and look each one up in
713
// the symbol table.  If it exists as a strong undefined symbol, we
714
// pull in the corresponding element.  We have to do this in a loop,
715
// since pulling in one element may create new undefined symbols which
716
// may be satisfied by other objects in the archive.  Return true in
717
// the normal case, false if the first member we tried to add from
718
// this archive had an incompatible target.
719
 
720
bool
721
Archive::add_symbols(Symbol_table* symtab, Layout* layout,
722
                     Input_objects* input_objects, Mapfile* mapfile)
723
{
724
  ++Archive::total_archives;
725
 
726
  if (this->input_file_->options().whole_archive())
727
    return this->include_all_members(symtab, layout, input_objects,
728
                                     mapfile);
729
 
730
  Archive::total_members += this->num_members_;
731
 
732
  input_objects->archive_start(this);
733
 
734
  const size_t armap_size = this->armap_.size();
735
 
736
  // This is a quick optimization, since we usually see many symbols
737
  // in a row with the same offset.  last_seen_offset holds the last
738
  // offset we saw that was present in the seen_offsets_ set.
739
  off_t last_seen_offset = -1;
740
 
741
  // Track which symbols in the symbol table we've already found to be
742
  // defined.
743
 
744
  char* tmpbuf = NULL;
745
  size_t tmpbuflen = 0;
746
  bool added_new_object;
747
  do
748
    {
749
      added_new_object = false;
750
      for (size_t i = 0; i < armap_size; ++i)
751
        {
752
          if (this->armap_checked_[i])
753
            continue;
754
          if (this->armap_[i].file_offset == last_seen_offset)
755
            {
756
              this->armap_checked_[i] = true;
757
              continue;
758
            }
759
          if (this->seen_offsets_.find(this->armap_[i].file_offset)
760
              != this->seen_offsets_.end())
761
            {
762
              this->armap_checked_[i] = true;
763
              last_seen_offset = this->armap_[i].file_offset;
764
              continue;
765
            }
766
 
767
          const char* sym_name = (this->armap_names_.data()
768
                                  + this->armap_[i].name_offset);
769
 
770
          Symbol* sym;
771
          std::string why;
772
          Archive::Should_include t =
773
            Archive::should_include_member(symtab, layout, sym_name, &sym,
774
                                           &why, &tmpbuf, &tmpbuflen);
775
 
776
          if (t == Archive::SHOULD_INCLUDE_NO
777
              || t == Archive::SHOULD_INCLUDE_YES)
778
            this->armap_checked_[i] = true;
779
 
780
          if (t != Archive::SHOULD_INCLUDE_YES)
781
            continue;
782
 
783
          // We want to include this object in the link.
784
          last_seen_offset = this->armap_[i].file_offset;
785
          this->seen_offsets_.insert(last_seen_offset);
786
 
787
          if (!this->include_member(symtab, layout, input_objects,
788
                                    last_seen_offset, mapfile, sym,
789
                                    why.c_str()))
790
            {
791
              if (tmpbuf != NULL)
792
                free(tmpbuf);
793
              return false;
794
            }
795
 
796
          added_new_object = true;
797
        }
798
    }
799
  while (added_new_object);
800
 
801
  if (tmpbuf != NULL)
802
    free(tmpbuf);
803
 
804
  input_objects->archive_stop(this);
805
 
806
  return true;
807
}
808
 
809
// Return whether the archive includes a member which defines the
810
// symbol SYM.
811
 
812
bool
813
Archive::defines_symbol(Symbol* sym) const
814
{
815
  const char* symname = sym->name();
816
  size_t symname_len = strlen(symname);
817
  size_t armap_size = this->armap_.size();
818
  for (size_t i = 0; i < armap_size; ++i)
819
    {
820
      if (this->armap_checked_[i])
821
        continue;
822
      const char* archive_symname = (this->armap_names_.data()
823
                                     + this->armap_[i].name_offset);
824
      if (strncmp(archive_symname, symname, symname_len) != 0)
825
        continue;
826
      char c = archive_symname[symname_len];
827
      if (c == '\0' && sym->version() == NULL)
828
        return true;
829
      if (c == '@')
830
        {
831
          const char* ver = archive_symname + symname_len + 1;
832
          if (*ver == '@')
833
            {
834
              if (sym->version() == NULL)
835
                return true;
836
              ++ver;
837
            }
838
          if (sym->version() != NULL && strcmp(sym->version(), ver) == 0)
839
            return true;
840
        }
841
    }
842
  return false;
843
}
844
 
845
// Include all the archive members in the link.  This is for --whole-archive.
846
 
847
bool
848
Archive::include_all_members(Symbol_table* symtab, Layout* layout,
849
                             Input_objects* input_objects, Mapfile* mapfile)
850
{
851
  // Don't include the same archive twice.  This can happen if
852
  // --whole-archive is nested inside --start-group (PR gold/12163).
853
  if (this->included_all_members_)
854
    return true;
855
 
856
  this->included_all_members_ = true;
857
 
858
  input_objects->archive_start(this);
859
 
860
  if (this->members_.size() > 0)
861
    {
862
      std::map<off_t, Archive_member>::const_iterator p;
863
      for (p = this->members_.begin();
864
           p != this->members_.end();
865
           ++p)
866
        {
867
          if (!this->include_member(symtab, layout, input_objects, p->first,
868
                                    mapfile, NULL, "--whole-archive"))
869
            return false;
870
          ++Archive::total_members;
871
        }
872
    }
873
  else
874
    {
875
      for (Archive::const_iterator p = this->begin();
876
           p != this->end();
877
           ++p)
878
        {
879
          if (!this->include_member(symtab, layout, input_objects, p->off,
880
                                    mapfile, NULL, "--whole-archive"))
881
            return false;
882
          ++Archive::total_members;
883
        }
884
    }
885
 
886
  input_objects->archive_stop(this);
887
 
888
  return true;
889
}
890
 
891
// Return the number of members in the archive.  This is only used for
892
// reports.
893
 
894
size_t
895
Archive::count_members()
896
{
897
  size_t ret = 0;
898
  for (Archive::const_iterator p = this->begin();
899
       p != this->end();
900
       ++p)
901
    ++ret;
902
  return ret;
903
}
904
 
905
// Include an archive member in the link.  OFF is the file offset of
906
// the member header.  WHY is the reason we are including this member.
907
// Return true if we added the member or if we had an error, return
908
// false if this was the first member we tried to add from this
909
// archive and it had an incompatible format.
910
 
911
bool
912
Archive::include_member(Symbol_table* symtab, Layout* layout,
913
                        Input_objects* input_objects, off_t off,
914
                        Mapfile* mapfile, Symbol* sym, const char* why)
915
{
916
  ++Archive::total_members_loaded;
917
 
918
  std::map<off_t, Archive_member>::const_iterator p = this->members_.find(off);
919
  if (p != this->members_.end())
920
    {
921
      Object* obj = p->second.obj_;
922
 
923
      Read_symbols_data* sd = p->second.sd_;
924
      if (mapfile != NULL)
925
        mapfile->report_include_archive_member(obj->name(), sym, why);
926
      if (input_objects->add_object(obj))
927
        {
928
          obj->layout(symtab, layout, sd);
929
          obj->add_symbols(symtab, sd, layout);
930
          this->included_member_ = true;
931
        }
932
      delete sd;
933
      return true;
934
    }
935
 
936
  // If this is the first object we are including from this archive,
937
  // and we searched for this archive, most likely because it was
938
  // found via a -l option, then if the target is incompatible we want
939
  // to move on to the next archive found in the search path.
940
  bool unconfigured = false;
941
  bool* punconfigured = NULL;
942
  if (!this->included_member_ && this->searched_for())
943
    punconfigured = &unconfigured;
944
 
945
  Object* obj = this->get_elf_object_for_member(off, punconfigured);
946
  if (obj == NULL)
947
    {
948
      // Return false to search for another archive, true if we found
949
      // an error.
950
      return unconfigured ? false : true;
951
    }
952
 
953
  if (mapfile != NULL)
954
    mapfile->report_include_archive_member(obj->name(), sym, why);
955
 
956
  Pluginobj* pluginobj = obj->pluginobj();
957
  if (pluginobj != NULL)
958
    {
959
      pluginobj->add_symbols(symtab, NULL, layout);
960
      this->included_member_ = true;
961
      return true;
962
    }
963
 
964
  if (!input_objects->add_object(obj))
965
    {
966
      // If this is an external member of a thin archive, unlock the
967
      // file.
968
      if (obj->offset() == 0)
969
        obj->unlock(this->task_);
970
      delete obj;
971
    }
972
  else
973
    {
974
      {
975
        if (layout->incremental_inputs() != NULL)
976
          layout->incremental_inputs()->report_object(obj, 0, this, NULL);
977
        Read_symbols_data sd;
978
        obj->read_symbols(&sd);
979
        obj->layout(symtab, layout, &sd);
980
        obj->add_symbols(symtab, &sd, layout);
981
      }
982
 
983
      // If this is an external member of a thin archive, unlock the file
984
      // for the next task.
985
      if (obj->offset() == 0)
986
        obj->unlock(this->task_);
987
 
988
      this->included_member_ = true;
989
    }
990
 
991
  return true;
992
}
993
 
994
// Iterate over all unused symbols, and call the visitor class V for each.
995
 
996
void
997
Archive::do_for_all_unused_symbols(Symbol_visitor_base* v) const
998
{
999
  for (std::vector<Armap_entry>::const_iterator p = this->armap_.begin();
1000
       p != this->armap_.end();
1001
       ++p)
1002
    {
1003
      if (this->seen_offsets_.find(p->file_offset)
1004
          == this->seen_offsets_.end())
1005
        v->visit(this->armap_names_.data() + p->name_offset);
1006
    }
1007
}
1008
 
1009
// Print statistical information to stderr.  This is used for --stats.
1010
 
1011
void
1012
Archive::print_stats()
1013
{
1014
  fprintf(stderr, _("%s: archive libraries: %u\n"),
1015
          program_name, Archive::total_archives);
1016
  fprintf(stderr, _("%s: total archive members: %u\n"),
1017
          program_name, Archive::total_members);
1018
  fprintf(stderr, _("%s: loaded archive members: %u\n"),
1019
          program_name, Archive::total_members_loaded);
1020
}
1021
 
1022
// Add_archive_symbols methods.
1023
 
1024
Add_archive_symbols::~Add_archive_symbols()
1025
{
1026
  if (this->this_blocker_ != NULL)
1027
    delete this->this_blocker_;
1028
  // next_blocker_ is deleted by the task associated with the next
1029
  // input file.
1030
}
1031
 
1032
// Return whether we can add the archive symbols.  We are blocked by
1033
// this_blocker_.  We block next_blocker_.  We also lock the file.
1034
 
1035
Task_token*
1036
Add_archive_symbols::is_runnable()
1037
{
1038
  if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
1039
    return this->this_blocker_;
1040
  return NULL;
1041
}
1042
 
1043
void
1044
Add_archive_symbols::locks(Task_locker* tl)
1045
{
1046
  tl->add(this, this->next_blocker_);
1047
  tl->add(this, this->archive_->token());
1048
}
1049
 
1050
void
1051
Add_archive_symbols::run(Workqueue* workqueue)
1052
{
1053
  // For an incremental link, begin recording layout information.
1054
  Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs();
1055
  if (incremental_inputs != NULL)
1056
    {
1057
      unsigned int arg_serial = this->input_argument_->file().arg_serial();
1058
      Script_info* script_info = this->input_argument_->script_info();
1059
      incremental_inputs->report_archive_begin(this->archive_, arg_serial,
1060
                                               script_info);
1061
    }
1062
 
1063
  bool added = this->archive_->add_symbols(this->symtab_, this->layout_,
1064
                                           this->input_objects_,
1065
                                           this->mapfile_);
1066
  this->archive_->unlock_nested_archives();
1067
 
1068
  this->archive_->release();
1069
  this->archive_->clear_uncached_views();
1070
 
1071
  if (!added)
1072
    {
1073
      // This archive holds object files which are incompatible with
1074
      // our output file.
1075
      Read_symbols::incompatible_warning(this->input_argument_,
1076
                                         this->archive_->input_file());
1077
      Read_symbols::requeue(workqueue, this->input_objects_, this->symtab_,
1078
                            this->layout_, this->dirpath_, this->dirindex_,
1079
                            this->mapfile_, this->input_argument_,
1080
                            this->input_group_, this->next_blocker_);
1081
      delete this->archive_;
1082
      return;
1083
    }
1084
 
1085
  if (this->input_group_ != NULL)
1086
    this->input_group_->add_archive(this->archive_);
1087
  else
1088
    {
1089
      // For an incremental link, finish recording the layout information.
1090
      if (incremental_inputs != NULL)
1091
        incremental_inputs->report_archive_end(this->archive_);
1092
 
1093
      if (!parameters->options().has_plugins()
1094
          || this->archive_->input_file()->options().whole_archive())
1095
        {
1096
          // We no longer need to know about this archive.
1097
          delete this->archive_;
1098
        }
1099
      else
1100
        {
1101
          // The plugin interface may want to rescan this archive.
1102
          parameters->options().plugins()->save_archive(this->archive_);
1103
        }
1104
 
1105
      this->archive_ = NULL;
1106
    }
1107
}
1108
 
1109
// Class Lib_group static variables.
1110
unsigned int Lib_group::total_lib_groups;
1111
unsigned int Lib_group::total_members;
1112
unsigned int Lib_group::total_members_loaded;
1113
 
1114
Lib_group::Lib_group(const Input_file_lib* lib, Task* task)
1115
  : Library_base(task), lib_(lib), members_()
1116
{
1117
  this->members_.resize(lib->size());
1118
}
1119
 
1120
const std::string&
1121
Lib_group::do_filename() const
1122
{
1123
  std::string *filename = new std::string("/group/");
1124
  return *filename;
1125
}
1126
 
1127
// Select members from the lib group and add them to the link.  We walk
1128
// through the members, and check if each one up should be included.
1129
// If the object says it should be included, we do so.  We have to do
1130
// this in a loop, since including one member may create new undefined
1131
// symbols which may be satisfied by other members.
1132
 
1133
void
1134
Lib_group::add_symbols(Symbol_table* symtab, Layout* layout,
1135
                       Input_objects* input_objects)
1136
{
1137
  ++Lib_group::total_lib_groups;
1138
 
1139
  Lib_group::total_members += this->members_.size();
1140
 
1141
  bool added_new_object;
1142
  do
1143
    {
1144
      added_new_object = false;
1145
      unsigned int i = 0;
1146
      while (i < this->members_.size())
1147
        {
1148
          const Archive_member& member = this->members_[i];
1149
          Object* obj = member.obj_;
1150
          std::string why;
1151
 
1152
          // Skip files with no symbols. Plugin objects have
1153
          // member.sd_ == NULL.
1154
          if (obj != NULL
1155
              && (member.sd_ == NULL || member.sd_->symbol_names != NULL))
1156
            {
1157
              Archive::Should_include t = obj->should_include_member(symtab,
1158
                                                                     layout,
1159
                                                                     member.sd_,
1160
                                                                     &why);
1161
 
1162
              if (t != Archive::SHOULD_INCLUDE_YES)
1163
                {
1164
                  ++i;
1165
                  continue;
1166
                }
1167
 
1168
              this->include_member(symtab, layout, input_objects, member);
1169
 
1170
              added_new_object = true;
1171
            }
1172
          else
1173
            {
1174
              if (member.sd_ != NULL)
1175
                {
1176
                  // The file must be locked in order to destroy the views
1177
                  // associated with it.
1178
                  gold_assert(obj != NULL);
1179
                  obj->lock(this->task_);
1180
                  delete member.sd_;
1181
                  obj->unlock(this->task_);
1182
                }
1183
            }
1184
 
1185
          this->members_[i] = this->members_.back();
1186
          this->members_.pop_back();
1187
        }
1188
    }
1189
  while (added_new_object);
1190
}
1191
 
1192
// Include a lib group member in the link.
1193
 
1194
void
1195
Lib_group::include_member(Symbol_table* symtab, Layout* layout,
1196
                          Input_objects* input_objects,
1197
                          const Archive_member& member)
1198
{
1199
  ++Lib_group::total_members_loaded;
1200
 
1201
  Object* obj = member.obj_;
1202
  gold_assert(obj != NULL);
1203
 
1204
  Pluginobj* pluginobj = obj->pluginobj();
1205
  if (pluginobj != NULL)
1206
    {
1207
      pluginobj->add_symbols(symtab, NULL, layout);
1208
      return;
1209
    }
1210
 
1211
  Read_symbols_data* sd = member.sd_;
1212
  gold_assert(sd != NULL);
1213
  obj->lock(this->task_);
1214
  if (input_objects->add_object(obj))
1215
    {
1216
      if (layout->incremental_inputs() != NULL)
1217
        layout->incremental_inputs()->report_object(obj, member.arg_serial_,
1218
                                                    this, NULL);
1219
      obj->layout(symtab, layout, sd);
1220
      obj->add_symbols(symtab, sd, layout);
1221
    }
1222
  delete sd;
1223
  // Unlock the file for the next task.
1224
  obj->unlock(this->task_);
1225
}
1226
 
1227
// Iterate over all unused symbols, and call the visitor class V for each.
1228
 
1229
void
1230
Lib_group::do_for_all_unused_symbols(Symbol_visitor_base* v) const
1231
{
1232
  // Files are removed from the members list when used, so all the
1233
  // files remaining on the list are unused.
1234
  for (std::vector<Archive_member>::const_iterator p = this->members_.begin();
1235
       p != this->members_.end();
1236
       ++p)
1237
    {
1238
      Object* obj = p->obj_;
1239
      obj->for_all_global_symbols(p->sd_, v);
1240
    }
1241
}
1242
 
1243
// Print statistical information to stderr.  This is used for --stats.
1244
 
1245
void
1246
Lib_group::print_stats()
1247
{
1248
  fprintf(stderr, _("%s: lib groups: %u\n"),
1249
          program_name, Lib_group::total_lib_groups);
1250
  fprintf(stderr, _("%s: total lib groups members: %u\n"),
1251
          program_name, Lib_group::total_members);
1252
  fprintf(stderr, _("%s: loaded lib groups members: %u\n"),
1253
          program_name, Lib_group::total_members_loaded);
1254
}
1255
 
1256
Task_token*
1257
Add_lib_group_symbols::is_runnable()
1258
{
1259
  if (this->readsyms_blocker_ != NULL && this->readsyms_blocker_->is_blocked())
1260
    return this->readsyms_blocker_;
1261
  if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
1262
    return this->this_blocker_;
1263
  return NULL;
1264
}
1265
 
1266
void
1267
Add_lib_group_symbols::locks(Task_locker* tl)
1268
{
1269
  tl->add(this, this->next_blocker_);
1270
}
1271
 
1272
void
1273
Add_lib_group_symbols::run(Workqueue*)
1274
{
1275
  // For an incremental link, begin recording layout information.
1276
  Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs();
1277
  if (incremental_inputs != NULL)
1278
    incremental_inputs->report_archive_begin(this->lib_, 0, NULL);
1279
 
1280
  this->lib_->add_symbols(this->symtab_, this->layout_, this->input_objects_);
1281
 
1282
  if (incremental_inputs != NULL)
1283
    incremental_inputs->report_archive_end(this->lib_);
1284
}
1285
 
1286
Add_lib_group_symbols::~Add_lib_group_symbols()
1287
{
1288
  if (this->this_blocker_ != NULL)
1289
    delete this->this_blocker_;
1290
  // next_blocker_ is deleted by the task associated with the next
1291
  // input file.
1292
}
1293
 
1294
} // End namespace gold.

powered by: WebSVN 2.1.0

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