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 213

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 159 khays
                                                                memsize,
657
                                                                NULL);
658 27 khays
      if (obj != NULL)
659
        {
660
          // The input file was claimed by a plugin, and its symbols
661
          // have been provided by the plugin.
662
          return obj;
663
        }
664
    }
665
 
666
  const unsigned char* ehdr;
667
  int read_size;
668
  if (!is_elf_object(input_file, memoff, &ehdr, &read_size))
669
    {
670
      gold_error(_("%s: member at %zu is not an ELF object"),
671
                 this->name().c_str(), static_cast<size_t>(off));
672
      return NULL;
673
    }
674
 
675
  Object* obj = make_elf_object((std::string(this->input_file_->filename())
676
                                 + "(" + member_name + ")"),
677
                                input_file, memoff, ehdr, read_size,
678
                                punconfigured);
679
  if (obj == NULL)
680
    return NULL;
681
  obj->set_no_export(this->no_export());
682
  return obj;
683
}
684
 
685
// Read the symbols from all the archive members in the link.
686
 
687
void
688
Archive::read_all_symbols()
689
{
690
  for (Archive::const_iterator p = this->begin();
691
       p != this->end();
692
       ++p)
693
    this->read_symbols(p->off);
694
}
695
 
696
// Read the symbols from an archive member in the link.  OFF is the file
697
// offset of the member header.
698
 
699
void
700
Archive::read_symbols(off_t off)
701
{
702
  Object* obj = this->get_elf_object_for_member(off, NULL);
703
  if (obj == NULL)
704
    return;
705
 
706
  Read_symbols_data* sd = new Read_symbols_data;
707
  obj->read_symbols(sd);
708
  Archive_member member(obj, sd);
709
  this->members_[off] = member;
710
}
711
 
712
// Select members from the archive and add them to the link.  We walk
713
// through the elements in the archive map, and look each one up in
714
// the symbol table.  If it exists as a strong undefined symbol, we
715
// pull in the corresponding element.  We have to do this in a loop,
716
// since pulling in one element may create new undefined symbols which
717
// may be satisfied by other objects in the archive.  Return true in
718
// the normal case, false if the first member we tried to add from
719
// this archive had an incompatible target.
720
 
721
bool
722
Archive::add_symbols(Symbol_table* symtab, Layout* layout,
723
                     Input_objects* input_objects, Mapfile* mapfile)
724
{
725
  ++Archive::total_archives;
726
 
727
  if (this->input_file_->options().whole_archive())
728
    return this->include_all_members(symtab, layout, input_objects,
729
                                     mapfile);
730
 
731
  Archive::total_members += this->num_members_;
732
 
733
  input_objects->archive_start(this);
734
 
735
  const size_t armap_size = this->armap_.size();
736
 
737
  // This is a quick optimization, since we usually see many symbols
738
  // in a row with the same offset.  last_seen_offset holds the last
739
  // offset we saw that was present in the seen_offsets_ set.
740
  off_t last_seen_offset = -1;
741
 
742
  // Track which symbols in the symbol table we've already found to be
743
  // defined.
744
 
745
  char* tmpbuf = NULL;
746
  size_t tmpbuflen = 0;
747
  bool added_new_object;
748
  do
749
    {
750
      added_new_object = false;
751
      for (size_t i = 0; i < armap_size; ++i)
752
        {
753
          if (this->armap_checked_[i])
754
            continue;
755
          if (this->armap_[i].file_offset == last_seen_offset)
756
            {
757
              this->armap_checked_[i] = true;
758
              continue;
759
            }
760
          if (this->seen_offsets_.find(this->armap_[i].file_offset)
761
              != this->seen_offsets_.end())
762
            {
763
              this->armap_checked_[i] = true;
764
              last_seen_offset = this->armap_[i].file_offset;
765
              continue;
766
            }
767
 
768
          const char* sym_name = (this->armap_names_.data()
769
                                  + this->armap_[i].name_offset);
770
 
771
          Symbol* sym;
772
          std::string why;
773
          Archive::Should_include t =
774
            Archive::should_include_member(symtab, layout, sym_name, &sym,
775
                                           &why, &tmpbuf, &tmpbuflen);
776
 
777
          if (t == Archive::SHOULD_INCLUDE_NO
778
              || t == Archive::SHOULD_INCLUDE_YES)
779
            this->armap_checked_[i] = true;
780
 
781
          if (t != Archive::SHOULD_INCLUDE_YES)
782
            continue;
783
 
784
          // We want to include this object in the link.
785
          last_seen_offset = this->armap_[i].file_offset;
786
          this->seen_offsets_.insert(last_seen_offset);
787
 
788
          if (!this->include_member(symtab, layout, input_objects,
789
                                    last_seen_offset, mapfile, sym,
790
                                    why.c_str()))
791
            {
792
              if (tmpbuf != NULL)
793
                free(tmpbuf);
794
              return false;
795
            }
796
 
797
          added_new_object = true;
798
        }
799
    }
800
  while (added_new_object);
801
 
802
  if (tmpbuf != NULL)
803
    free(tmpbuf);
804
 
805
  input_objects->archive_stop(this);
806
 
807
  return true;
808
}
809
 
810
// Return whether the archive includes a member which defines the
811
// symbol SYM.
812
 
813
bool
814
Archive::defines_symbol(Symbol* sym) const
815
{
816
  const char* symname = sym->name();
817
  size_t symname_len = strlen(symname);
818
  size_t armap_size = this->armap_.size();
819
  for (size_t i = 0; i < armap_size; ++i)
820
    {
821
      if (this->armap_checked_[i])
822
        continue;
823
      const char* archive_symname = (this->armap_names_.data()
824
                                     + this->armap_[i].name_offset);
825
      if (strncmp(archive_symname, symname, symname_len) != 0)
826
        continue;
827
      char c = archive_symname[symname_len];
828
      if (c == '\0' && sym->version() == NULL)
829
        return true;
830
      if (c == '@')
831
        {
832
          const char* ver = archive_symname + symname_len + 1;
833
          if (*ver == '@')
834
            {
835
              if (sym->version() == NULL)
836
                return true;
837
              ++ver;
838
            }
839
          if (sym->version() != NULL && strcmp(sym->version(), ver) == 0)
840
            return true;
841
        }
842
    }
843
  return false;
844
}
845
 
846
// Include all the archive members in the link.  This is for --whole-archive.
847
 
848
bool
849
Archive::include_all_members(Symbol_table* symtab, Layout* layout,
850
                             Input_objects* input_objects, Mapfile* mapfile)
851
{
852
  // Don't include the same archive twice.  This can happen if
853
  // --whole-archive is nested inside --start-group (PR gold/12163).
854
  if (this->included_all_members_)
855
    return true;
856
 
857
  this->included_all_members_ = true;
858
 
859
  input_objects->archive_start(this);
860
 
861
  if (this->members_.size() > 0)
862
    {
863
      std::map<off_t, Archive_member>::const_iterator p;
864
      for (p = this->members_.begin();
865
           p != this->members_.end();
866
           ++p)
867
        {
868
          if (!this->include_member(symtab, layout, input_objects, p->first,
869
                                    mapfile, NULL, "--whole-archive"))
870
            return false;
871
          ++Archive::total_members;
872
        }
873
    }
874
  else
875
    {
876
      for (Archive::const_iterator p = this->begin();
877
           p != this->end();
878
           ++p)
879
        {
880
          if (!this->include_member(symtab, layout, input_objects, p->off,
881
                                    mapfile, NULL, "--whole-archive"))
882
            return false;
883
          ++Archive::total_members;
884
        }
885
    }
886
 
887
  input_objects->archive_stop(this);
888
 
889
  return true;
890
}
891
 
892
// Return the number of members in the archive.  This is only used for
893
// reports.
894
 
895
size_t
896
Archive::count_members()
897
{
898
  size_t ret = 0;
899
  for (Archive::const_iterator p = this->begin();
900
       p != this->end();
901
       ++p)
902
    ++ret;
903
  return ret;
904
}
905
 
906
// Include an archive member in the link.  OFF is the file offset of
907
// the member header.  WHY is the reason we are including this member.
908
// Return true if we added the member or if we had an error, return
909
// false if this was the first member we tried to add from this
910
// archive and it had an incompatible format.
911
 
912
bool
913
Archive::include_member(Symbol_table* symtab, Layout* layout,
914
                        Input_objects* input_objects, off_t off,
915
                        Mapfile* mapfile, Symbol* sym, const char* why)
916
{
917
  ++Archive::total_members_loaded;
918
 
919
  std::map<off_t, Archive_member>::const_iterator p = this->members_.find(off);
920
  if (p != this->members_.end())
921
    {
922
      Object* obj = p->second.obj_;
923
 
924
      Read_symbols_data* sd = p->second.sd_;
925
      if (mapfile != NULL)
926
        mapfile->report_include_archive_member(obj->name(), sym, why);
927
      if (input_objects->add_object(obj))
928
        {
929
          obj->layout(symtab, layout, sd);
930
          obj->add_symbols(symtab, sd, layout);
931
          this->included_member_ = true;
932
        }
933
      delete sd;
934
      return true;
935
    }
936
 
937
  // If this is the first object we are including from this archive,
938
  // and we searched for this archive, most likely because it was
939
  // found via a -l option, then if the target is incompatible we want
940
  // to move on to the next archive found in the search path.
941
  bool unconfigured = false;
942
  bool* punconfigured = NULL;
943
  if (!this->included_member_ && this->searched_for())
944
    punconfigured = &unconfigured;
945
 
946
  Object* obj = this->get_elf_object_for_member(off, punconfigured);
947
  if (obj == NULL)
948
    {
949
      // Return false to search for another archive, true if we found
950
      // an error.
951
      return unconfigured ? false : true;
952
    }
953
 
954
  if (mapfile != NULL)
955
    mapfile->report_include_archive_member(obj->name(), sym, why);
956
 
957
  Pluginobj* pluginobj = obj->pluginobj();
958
  if (pluginobj != NULL)
959
    {
960
      pluginobj->add_symbols(symtab, NULL, layout);
961
      this->included_member_ = true;
962
      return true;
963
    }
964
 
965
  if (!input_objects->add_object(obj))
966
    {
967
      // If this is an external member of a thin archive, unlock the
968
      // file.
969
      if (obj->offset() == 0)
970
        obj->unlock(this->task_);
971
      delete obj;
972
    }
973
  else
974
    {
975
      {
976
        if (layout->incremental_inputs() != NULL)
977
          layout->incremental_inputs()->report_object(obj, 0, this, NULL);
978
        Read_symbols_data sd;
979
        obj->read_symbols(&sd);
980
        obj->layout(symtab, layout, &sd);
981
        obj->add_symbols(symtab, &sd, layout);
982
      }
983
 
984
      // If this is an external member of a thin archive, unlock the file
985
      // for the next task.
986
      if (obj->offset() == 0)
987
        obj->unlock(this->task_);
988
 
989
      this->included_member_ = true;
990
    }
991
 
992
  return true;
993
}
994
 
995
// Iterate over all unused symbols, and call the visitor class V for each.
996
 
997
void
998
Archive::do_for_all_unused_symbols(Symbol_visitor_base* v) const
999
{
1000
  for (std::vector<Armap_entry>::const_iterator p = this->armap_.begin();
1001
       p != this->armap_.end();
1002
       ++p)
1003
    {
1004
      if (this->seen_offsets_.find(p->file_offset)
1005
          == this->seen_offsets_.end())
1006
        v->visit(this->armap_names_.data() + p->name_offset);
1007
    }
1008
}
1009
 
1010
// Print statistical information to stderr.  This is used for --stats.
1011
 
1012
void
1013
Archive::print_stats()
1014
{
1015
  fprintf(stderr, _("%s: archive libraries: %u\n"),
1016
          program_name, Archive::total_archives);
1017
  fprintf(stderr, _("%s: total archive members: %u\n"),
1018
          program_name, Archive::total_members);
1019
  fprintf(stderr, _("%s: loaded archive members: %u\n"),
1020
          program_name, Archive::total_members_loaded);
1021
}
1022
 
1023
// Add_archive_symbols methods.
1024
 
1025
Add_archive_symbols::~Add_archive_symbols()
1026
{
1027
  if (this->this_blocker_ != NULL)
1028
    delete this->this_blocker_;
1029
  // next_blocker_ is deleted by the task associated with the next
1030
  // input file.
1031
}
1032
 
1033
// Return whether we can add the archive symbols.  We are blocked by
1034
// this_blocker_.  We block next_blocker_.  We also lock the file.
1035
 
1036
Task_token*
1037
Add_archive_symbols::is_runnable()
1038
{
1039
  if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
1040
    return this->this_blocker_;
1041
  return NULL;
1042
}
1043
 
1044
void
1045
Add_archive_symbols::locks(Task_locker* tl)
1046
{
1047
  tl->add(this, this->next_blocker_);
1048
  tl->add(this, this->archive_->token());
1049
}
1050
 
1051
void
1052
Add_archive_symbols::run(Workqueue* workqueue)
1053
{
1054
  // For an incremental link, begin recording layout information.
1055
  Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs();
1056
  if (incremental_inputs != NULL)
1057
    {
1058
      unsigned int arg_serial = this->input_argument_->file().arg_serial();
1059
      Script_info* script_info = this->input_argument_->script_info();
1060
      incremental_inputs->report_archive_begin(this->archive_, arg_serial,
1061
                                               script_info);
1062
    }
1063
 
1064
  bool added = this->archive_->add_symbols(this->symtab_, this->layout_,
1065
                                           this->input_objects_,
1066
                                           this->mapfile_);
1067
  this->archive_->unlock_nested_archives();
1068
 
1069
  this->archive_->release();
1070
  this->archive_->clear_uncached_views();
1071
 
1072
  if (!added)
1073
    {
1074
      // This archive holds object files which are incompatible with
1075
      // our output file.
1076
      Read_symbols::incompatible_warning(this->input_argument_,
1077
                                         this->archive_->input_file());
1078
      Read_symbols::requeue(workqueue, this->input_objects_, this->symtab_,
1079
                            this->layout_, this->dirpath_, this->dirindex_,
1080
                            this->mapfile_, this->input_argument_,
1081
                            this->input_group_, this->next_blocker_);
1082
      delete this->archive_;
1083
      return;
1084
    }
1085
 
1086
  if (this->input_group_ != NULL)
1087
    this->input_group_->add_archive(this->archive_);
1088
  else
1089
    {
1090
      // For an incremental link, finish recording the layout information.
1091
      if (incremental_inputs != NULL)
1092
        incremental_inputs->report_archive_end(this->archive_);
1093
 
1094
      if (!parameters->options().has_plugins()
1095
          || this->archive_->input_file()->options().whole_archive())
1096
        {
1097
          // We no longer need to know about this archive.
1098
          delete this->archive_;
1099
        }
1100
      else
1101
        {
1102
          // The plugin interface may want to rescan this archive.
1103
          parameters->options().plugins()->save_archive(this->archive_);
1104
        }
1105
 
1106
      this->archive_ = NULL;
1107
    }
1108
}
1109
 
1110
// Class Lib_group static variables.
1111
unsigned int Lib_group::total_lib_groups;
1112
unsigned int Lib_group::total_members;
1113
unsigned int Lib_group::total_members_loaded;
1114
 
1115
Lib_group::Lib_group(const Input_file_lib* lib, Task* task)
1116
  : Library_base(task), lib_(lib), members_()
1117
{
1118
  this->members_.resize(lib->size());
1119
}
1120
 
1121
const std::string&
1122
Lib_group::do_filename() const
1123
{
1124
  std::string *filename = new std::string("/group/");
1125
  return *filename;
1126
}
1127
 
1128
// Select members from the lib group and add them to the link.  We walk
1129
// through the members, and check if each one up should be included.
1130
// If the object says it should be included, we do so.  We have to do
1131
// this in a loop, since including one member may create new undefined
1132
// symbols which may be satisfied by other members.
1133
 
1134
void
1135
Lib_group::add_symbols(Symbol_table* symtab, Layout* layout,
1136
                       Input_objects* input_objects)
1137
{
1138
  ++Lib_group::total_lib_groups;
1139
 
1140
  Lib_group::total_members += this->members_.size();
1141
 
1142
  bool added_new_object;
1143
  do
1144
    {
1145
      added_new_object = false;
1146
      unsigned int i = 0;
1147
      while (i < this->members_.size())
1148
        {
1149
          const Archive_member& member = this->members_[i];
1150
          Object* obj = member.obj_;
1151
          std::string why;
1152
 
1153
          // Skip files with no symbols. Plugin objects have
1154
          // member.sd_ == NULL.
1155
          if (obj != NULL
1156
              && (member.sd_ == NULL || member.sd_->symbol_names != NULL))
1157
            {
1158
              Archive::Should_include t = obj->should_include_member(symtab,
1159
                                                                     layout,
1160
                                                                     member.sd_,
1161
                                                                     &why);
1162
 
1163
              if (t != Archive::SHOULD_INCLUDE_YES)
1164
                {
1165
                  ++i;
1166
                  continue;
1167
                }
1168
 
1169
              this->include_member(symtab, layout, input_objects, member);
1170
 
1171
              added_new_object = true;
1172
            }
1173
          else
1174
            {
1175
              if (member.sd_ != NULL)
1176
                {
1177
                  // The file must be locked in order to destroy the views
1178
                  // associated with it.
1179
                  gold_assert(obj != NULL);
1180
                  obj->lock(this->task_);
1181
                  delete member.sd_;
1182
                  obj->unlock(this->task_);
1183
                }
1184
            }
1185
 
1186
          this->members_[i] = this->members_.back();
1187
          this->members_.pop_back();
1188
        }
1189
    }
1190
  while (added_new_object);
1191
}
1192
 
1193
// Include a lib group member in the link.
1194
 
1195
void
1196
Lib_group::include_member(Symbol_table* symtab, Layout* layout,
1197
                          Input_objects* input_objects,
1198
                          const Archive_member& member)
1199
{
1200
  ++Lib_group::total_members_loaded;
1201
 
1202
  Object* obj = member.obj_;
1203
  gold_assert(obj != NULL);
1204
 
1205
  Pluginobj* pluginobj = obj->pluginobj();
1206
  if (pluginobj != NULL)
1207
    {
1208
      pluginobj->add_symbols(symtab, NULL, layout);
1209
      return;
1210
    }
1211
 
1212
  Read_symbols_data* sd = member.sd_;
1213
  gold_assert(sd != NULL);
1214
  obj->lock(this->task_);
1215
  if (input_objects->add_object(obj))
1216
    {
1217
      if (layout->incremental_inputs() != NULL)
1218
        layout->incremental_inputs()->report_object(obj, member.arg_serial_,
1219
                                                    this, NULL);
1220
      obj->layout(symtab, layout, sd);
1221
      obj->add_symbols(symtab, sd, layout);
1222
    }
1223
  delete sd;
1224
  // Unlock the file for the next task.
1225
  obj->unlock(this->task_);
1226
}
1227
 
1228
// Iterate over all unused symbols, and call the visitor class V for each.
1229
 
1230
void
1231
Lib_group::do_for_all_unused_symbols(Symbol_visitor_base* v) const
1232
{
1233
  // Files are removed from the members list when used, so all the
1234
  // files remaining on the list are unused.
1235
  for (std::vector<Archive_member>::const_iterator p = this->members_.begin();
1236
       p != this->members_.end();
1237
       ++p)
1238
    {
1239
      Object* obj = p->obj_;
1240
      obj->for_all_global_symbols(p->sd_, v);
1241
    }
1242
}
1243
 
1244
// Print statistical information to stderr.  This is used for --stats.
1245
 
1246
void
1247
Lib_group::print_stats()
1248
{
1249
  fprintf(stderr, _("%s: lib groups: %u\n"),
1250
          program_name, Lib_group::total_lib_groups);
1251
  fprintf(stderr, _("%s: total lib groups members: %u\n"),
1252
          program_name, Lib_group::total_members);
1253
  fprintf(stderr, _("%s: loaded lib groups members: %u\n"),
1254
          program_name, Lib_group::total_members_loaded);
1255
}
1256
 
1257
Task_token*
1258
Add_lib_group_symbols::is_runnable()
1259
{
1260
  if (this->readsyms_blocker_ != NULL && this->readsyms_blocker_->is_blocked())
1261
    return this->readsyms_blocker_;
1262
  if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
1263
    return this->this_blocker_;
1264
  return NULL;
1265
}
1266
 
1267
void
1268
Add_lib_group_symbols::locks(Task_locker* tl)
1269
{
1270
  tl->add(this, this->next_blocker_);
1271
}
1272
 
1273
void
1274
Add_lib_group_symbols::run(Workqueue*)
1275
{
1276
  // For an incremental link, begin recording layout information.
1277
  Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs();
1278
  if (incremental_inputs != NULL)
1279
    incremental_inputs->report_archive_begin(this->lib_, 0, NULL);
1280
 
1281
  this->lib_->add_symbols(this->symtab_, this->layout_, this->input_objects_);
1282
 
1283
  if (incremental_inputs != NULL)
1284
    incremental_inputs->report_archive_end(this->lib_);
1285
}
1286
 
1287
Add_lib_group_symbols::~Add_lib_group_symbols()
1288
{
1289
  if (this->this_blocker_ != NULL)
1290
    delete this->this_blocker_;
1291
  // next_blocker_ is deleted by the task associated with the next
1292
  // input file.
1293
}
1294
 
1295
} // End namespace gold.

powered by: WebSVN 2.1.0

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