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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gold/] [fileread.cc] - Blame information for rev 98

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

Line No. Rev Author Line
1 27 khays
// fileread.cc -- read files for gold
2
 
3
// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4
// Written by Ian Lance Taylor <iant@google.com>.
5
 
6
// This file is part of gold.
7
 
8
// This program is free software; you can redistribute it and/or modify
9
// it under the terms of the GNU General Public License as published by
10
// the Free Software Foundation; either version 3 of the License, or
11
// (at your option) any later version.
12
 
13
// This program is distributed in the hope that it will be useful,
14
// but WITHOUT ANY WARRANTY; without even the implied warranty of
15
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
// GNU General Public License for more details.
17
 
18
// You should have received a copy of the GNU General Public License
19
// along with this program; if not, write to the Free Software
20
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21
// MA 02110-1301, USA.
22
 
23
#include "gold.h"
24
 
25
#include <cstring>
26
#include <cerrno>
27
#include <climits>
28
#include <fcntl.h>
29
#include <unistd.h>
30
 
31
#ifdef HAVE_SYS_MMAN_H
32
#include <sys/mman.h>
33
#endif
34
 
35
#ifdef HAVE_READV
36
#include <sys/uio.h>
37
#endif
38
 
39
#include <sys/stat.h>
40
#include "filenames.h"
41
 
42
#include "debug.h"
43
#include "parameters.h"
44
#include "options.h"
45
#include "dirsearch.h"
46
#include "target.h"
47
#include "binary.h"
48
#include "descriptors.h"
49
#include "gold-threads.h"
50
#include "fileread.h"
51
 
52
// For systems without mmap support.
53
#ifndef HAVE_MMAP
54
# define mmap gold_mmap
55
# define munmap gold_munmap
56
# ifndef MAP_FAILED
57
#  define MAP_FAILED (reinterpret_cast<void*>(-1))
58
# endif
59
# ifndef PROT_READ
60
#  define PROT_READ 0
61
# endif
62
# ifndef MAP_PRIVATE
63
#  define MAP_PRIVATE 0
64
# endif
65
 
66
# ifndef ENOSYS
67
#  define ENOSYS EINVAL
68
# endif
69
 
70
static void *
71
gold_mmap(void *, size_t, int, int, int, off_t)
72
{
73
  errno = ENOSYS;
74
  return MAP_FAILED;
75
}
76
 
77
static int
78
gold_munmap(void *, size_t)
79
{
80
  errno = ENOSYS;
81
  return -1;
82
}
83
 
84
#endif
85
 
86
#ifndef HAVE_READV
87
struct iovec { void* iov_base; size_t iov_len; };
88
ssize_t
89
readv(int, const iovec*, int)
90
{
91
  gold_unreachable();
92
}
93
#endif
94
 
95
namespace gold
96
{
97
 
98
// Get the last modified time of an unopened file.
99
 
100
bool
101
get_mtime(const char* filename, Timespec* mtime)
102
{
103
  struct stat file_stat;
104
 
105
  if (stat(filename, &file_stat) < 0)
106
    return false;
107
#ifdef HAVE_STAT_ST_MTIM
108
  mtime->seconds = file_stat.st_mtim.tv_sec;
109
  mtime->nanoseconds = file_stat.st_mtim.tv_nsec;
110
#else
111
  mtime->seconds = file_stat.st_mtime;
112
  mtime->nanoseconds = 0;
113
#endif
114
  return true;
115
}
116
 
117
// Class File_read.
118
 
119
// A lock for the File_read static variables.
120
static Lock* file_counts_lock = NULL;
121
static Initialize_lock file_counts_initialize_lock(&file_counts_lock);
122
 
123
// The File_read static variables.
124
unsigned long long File_read::total_mapped_bytes;
125
unsigned long long File_read::current_mapped_bytes;
126
unsigned long long File_read::maximum_mapped_bytes;
127
 
128
// Class File_read::View.
129
 
130
File_read::View::~View()
131
{
132
  gold_assert(!this->is_locked());
133
  switch (this->data_ownership_)
134
    {
135
    case DATA_ALLOCATED_ARRAY:
136
      free(const_cast<unsigned char*>(this->data_));
137
      break;
138
    case DATA_MMAPPED:
139
      if (::munmap(const_cast<unsigned char*>(this->data_), this->size_) != 0)
140
        gold_warning(_("munmap failed: %s"), strerror(errno));
141
      if (!parameters->options_valid() || parameters->options().stats())
142
        {
143
          file_counts_initialize_lock.initialize();
144
          Hold_optional_lock hl(file_counts_lock);
145
          File_read::current_mapped_bytes -= this->size_;
146
        }
147
      break;
148
    case DATA_NOT_OWNED:
149
      break;
150
    default:
151
      gold_unreachable();
152
    }
153
}
154
 
155
void
156
File_read::View::lock()
157
{
158
  ++this->lock_count_;
159
}
160
 
161
void
162
File_read::View::unlock()
163
{
164
  gold_assert(this->lock_count_ > 0);
165
  --this->lock_count_;
166
}
167
 
168
bool
169
File_read::View::is_locked()
170
{
171
  return this->lock_count_ > 0;
172
}
173
 
174
// Class File_read.
175
 
176
File_read::~File_read()
177
{
178
  gold_assert(this->token_.is_writable());
179
  if (this->is_descriptor_opened_)
180
    {
181
      release_descriptor(this->descriptor_, true);
182
      this->descriptor_ = -1;
183
      this->is_descriptor_opened_ = false;
184
    }
185
  this->name_.clear();
186
  this->clear_views(CLEAR_VIEWS_ALL);
187
}
188
 
189
// Open the file.
190
 
191
bool
192
File_read::open(const Task* task, const std::string& name)
193
{
194
  gold_assert(this->token_.is_writable()
195
              && this->descriptor_ < 0
196
              && !this->is_descriptor_opened_
197
              && this->name_.empty());
198
  this->name_ = name;
199
 
200
  this->descriptor_ = open_descriptor(-1, this->name_.c_str(),
201
                                      O_RDONLY);
202
 
203
  if (this->descriptor_ >= 0)
204
    {
205
      this->is_descriptor_opened_ = true;
206
      struct stat s;
207
      if (::fstat(this->descriptor_, &s) < 0)
208
        gold_error(_("%s: fstat failed: %s"),
209
                   this->name_.c_str(), strerror(errno));
210
      this->size_ = s.st_size;
211
      gold_debug(DEBUG_FILES, "Attempt to open %s succeeded",
212
                 this->name_.c_str());
213
      this->token_.add_writer(task);
214
    }
215
 
216
  return this->descriptor_ >= 0;
217
}
218
 
219
// Open the file with the contents in memory.
220
 
221
bool
222
File_read::open(const Task* task, const std::string& name,
223
                const unsigned char* contents, off_t size)
224
{
225
  gold_assert(this->token_.is_writable()
226
              && this->descriptor_ < 0
227
              && !this->is_descriptor_opened_
228
              && this->name_.empty());
229
  this->name_ = name;
230
  this->whole_file_view_ = new View(0, size, contents, 0, false,
231
                                    View::DATA_NOT_OWNED);
232
  this->add_view(this->whole_file_view_);
233
  this->size_ = size;
234
  this->token_.add_writer(task);
235
  return true;
236
}
237
 
238
// Reopen a descriptor if necessary.
239
 
240
void
241
File_read::reopen_descriptor()
242
{
243
  if (!this->is_descriptor_opened_)
244
    {
245
      this->descriptor_ = open_descriptor(this->descriptor_,
246
                                          this->name_.c_str(),
247
                                          O_RDONLY);
248
      if (this->descriptor_ < 0)
249
        gold_fatal(_("could not reopen file %s"), this->name_.c_str());
250
      this->is_descriptor_opened_ = true;
251
    }
252
}
253
 
254
// Release the file.  This is called when we are done with the file in
255
// a Task.
256
 
257
void
258
File_read::release()
259
{
260
  gold_assert(this->is_locked());
261
 
262
  if (!parameters->options_valid() || parameters->options().stats())
263
    {
264
      file_counts_initialize_lock.initialize();
265
      Hold_optional_lock hl(file_counts_lock);
266
      File_read::total_mapped_bytes += this->mapped_bytes_;
267
      File_read::current_mapped_bytes += this->mapped_bytes_;
268
      if (File_read::current_mapped_bytes > File_read::maximum_mapped_bytes)
269
        File_read::maximum_mapped_bytes = File_read::current_mapped_bytes;
270
    }
271
 
272
  this->mapped_bytes_ = 0;
273
 
274
  // Only clear views if there is only one attached object.  Otherwise
275
  // we waste time trying to clear cached archive views.  Similarly
276
  // for releasing the descriptor.
277
  if (this->object_count_ <= 1)
278
    {
279
      this->clear_views(CLEAR_VIEWS_NORMAL);
280
      if (this->is_descriptor_opened_)
281
        {
282
          release_descriptor(this->descriptor_, false);
283
          this->is_descriptor_opened_ = false;
284
        }
285
    }
286
 
287
  this->released_ = true;
288
}
289
 
290
// Lock the file.
291
 
292
void
293
File_read::lock(const Task* task)
294
{
295
  gold_assert(this->released_);
296
  this->token_.add_writer(task);
297
  this->released_ = false;
298
}
299
 
300
// Unlock the file.
301
 
302
void
303
File_read::unlock(const Task* task)
304
{
305
  this->release();
306
  this->token_.remove_writer(task);
307
}
308
 
309
// Return whether the file is locked.
310
 
311
bool
312
File_read::is_locked() const
313
{
314
  if (!this->token_.is_writable())
315
    return true;
316
  // The file is not locked, so it should have been released.
317
  gold_assert(this->released_);
318
  return false;
319
}
320
 
321
// See if we have a view which covers the file starting at START for
322
// SIZE bytes.  Return a pointer to the View if found, NULL if not.
323
// If BYTESHIFT is not -1U, the returned View must have the specified
324
// byte shift; otherwise, it may have any byte shift.  If VSHIFTED is
325
// not NULL, this sets *VSHIFTED to a view which would have worked if
326
// not for the requested BYTESHIFT.
327
 
328
inline File_read::View*
329
File_read::find_view(off_t start, section_size_type size,
330
                     unsigned int byteshift, File_read::View** vshifted) const
331
{
332
  if (vshifted != NULL)
333
    *vshifted = NULL;
334
 
335
  // If we have the whole file mmapped, and the alignment is right,
336
  // we can return it.
337
  if (this->whole_file_view_)
338
    if (byteshift == -1U || byteshift == 0)
339
      return this->whole_file_view_;
340
 
341
  off_t page = File_read::page_offset(start);
342
 
343
  unsigned int bszero = 0;
344
  Views::const_iterator p = this->views_.upper_bound(std::make_pair(page - 1,
345
                                                                    bszero));
346
 
347
  while (p != this->views_.end() && p->first.first <= page)
348
    {
349
      if (p->second->start() <= start
350
          && (p->second->start() + static_cast<off_t>(p->second->size())
351
              >= start + static_cast<off_t>(size)))
352
        {
353
          if (byteshift == -1U || byteshift == p->second->byteshift())
354
            {
355
              p->second->set_accessed();
356
              return p->second;
357
            }
358
 
359
          if (vshifted != NULL && *vshifted == NULL)
360
            *vshifted = p->second;
361
        }
362
 
363
      ++p;
364
    }
365
 
366
  return NULL;
367
}
368
 
369
// Read SIZE bytes from the file starting at offset START.  Read into
370
// the buffer at P.
371
 
372
void
373
File_read::do_read(off_t start, section_size_type size, void* p)
374
{
375
  ssize_t bytes;
376
  if (this->whole_file_view_ != NULL)
377
    {
378
      bytes = this->size_ - start;
379
      if (static_cast<section_size_type>(bytes) >= size)
380
        {
381
          memcpy(p, this->whole_file_view_->data() + start, size);
382
          return;
383
        }
384
    }
385
  else
386
    {
387
      this->reopen_descriptor();
388
      bytes = ::pread(this->descriptor_, p, size, start);
389
      if (static_cast<section_size_type>(bytes) == size)
390
        return;
391
 
392
      if (bytes < 0)
393
        {
394
          gold_fatal(_("%s: pread failed: %s"),
395
                     this->filename().c_str(), strerror(errno));
396
          return;
397
        }
398
    }
399
 
400
  gold_fatal(_("%s: file too short: read only %lld of %lld bytes at %lld"),
401
             this->filename().c_str(),
402
             static_cast<long long>(bytes),
403
             static_cast<long long>(size),
404
             static_cast<long long>(start));
405
}
406
 
407
// Read data from the file.
408
 
409
void
410
File_read::read(off_t start, section_size_type size, void* p)
411
{
412
  const File_read::View* pv = this->find_view(start, size, -1U, NULL);
413
  if (pv != NULL)
414
    {
415
      memcpy(p, pv->data() + (start - pv->start() + pv->byteshift()), size);
416
      return;
417
    }
418
 
419
  this->do_read(start, size, p);
420
}
421
 
422
// Add a new view.  There may already be an existing view at this
423
// offset.  If there is, the new view will be larger, and should
424
// replace the old view.
425
 
426
void
427
File_read::add_view(File_read::View* v)
428
{
429
  std::pair<Views::iterator, bool> ins =
430
    this->views_.insert(std::make_pair(std::make_pair(v->start(),
431
                                                      v->byteshift()),
432
                                       v));
433
  if (ins.second)
434
    return;
435
 
436
  // There was an existing view at this offset.  It must not be large
437
  // enough.  We can't delete it here, since something might be using
438
  // it; we put it on a list to be deleted when the file is unlocked.
439
  File_read::View* vold = ins.first->second;
440
  gold_assert(vold->size() < v->size());
441
  if (vold->should_cache())
442
    {
443
      v->set_cache();
444
      vold->clear_cache();
445
    }
446
  this->saved_views_.push_back(vold);
447
 
448
  ins.first->second = v;
449
}
450
 
451
// Make a new view with a specified byteshift, reading the data from
452
// the file.
453
 
454
File_read::View*
455
File_read::make_view(off_t start, section_size_type size,
456
                     unsigned int byteshift, bool cache)
457
{
458
  gold_assert(size > 0);
459
 
460
  // Check that start and end of the view are within the file.
461
  if (start > this->size_
462
      || (static_cast<unsigned long long>(size)
463
          > static_cast<unsigned long long>(this->size_ - start)))
464
    gold_fatal(_("%s: attempt to map %lld bytes at offset %lld exceeds "
465
                 "size of file; the file may be corrupt"),
466
                   this->filename().c_str(),
467
                   static_cast<long long>(size),
468
                   static_cast<long long>(start));
469
 
470
  off_t poff = File_read::page_offset(start);
471
 
472
  section_size_type psize = File_read::pages(size + (start - poff));
473
 
474
  if (poff + static_cast<off_t>(psize) >= this->size_)
475
    {
476
      psize = this->size_ - poff;
477
      gold_assert(psize >= size);
478
    }
479
 
480
  void* p;
481
  View::Data_ownership ownership;
482
  if (byteshift != 0)
483
    {
484
      p = malloc(psize + byteshift);
485
      if (p == NULL)
486
        gold_nomem();
487
      memset(p, 0, byteshift);
488
      this->do_read(poff, psize, static_cast<unsigned char*>(p) + byteshift);
489
      ownership = View::DATA_ALLOCATED_ARRAY;
490
    }
491
  else
492
    {
493
      this->reopen_descriptor();
494
      p = ::mmap(NULL, psize, PROT_READ, MAP_PRIVATE, this->descriptor_, poff);
495
      if (p != MAP_FAILED)
496
        {
497
          ownership = View::DATA_MMAPPED;
498
          this->mapped_bytes_ += psize;
499
        }
500
      else
501
        {
502
          p = malloc(psize);
503
          if (p == NULL)
504
            gold_nomem();
505
          this->do_read(poff, psize, p);
506
          ownership = View::DATA_ALLOCATED_ARRAY;
507
        }
508
    }
509
 
510
  const unsigned char* pbytes = static_cast<const unsigned char*>(p);
511
  File_read::View* v = new File_read::View(poff, psize, pbytes, byteshift,
512
                                           cache, ownership);
513
 
514
  this->add_view(v);
515
 
516
  return v;
517
}
518
 
519
// Find a View or make a new one, shifted as required by the file
520
// offset OFFSET and ALIGNED.
521
 
522
File_read::View*
523
File_read::find_or_make_view(off_t offset, off_t start,
524
                             section_size_type size, bool aligned, bool cache)
525
{
526
  unsigned int byteshift;
527
  if (offset == 0)
528
    byteshift = 0;
529
  else
530
    {
531
      unsigned int target_size = (!parameters->target_valid()
532
                                  ? 64
533
                                  : parameters->target().get_size());
534
      byteshift = offset & ((target_size / 8) - 1);
535
 
536
      // Set BYTESHIFT to the number of dummy bytes which must be
537
      // inserted before the data in order for this data to be
538
      // aligned.
539
      if (byteshift != 0)
540
        byteshift = (target_size / 8) - byteshift;
541
    }
542
 
543
  // If --map-whole-files is set, make sure we have a
544
  // whole file view.  Options may not yet be ready, e.g.,
545
  // when reading a version script.  We then default to
546
  // --no-map-whole-files.
547
  if (this->whole_file_view_ == NULL
548
      && parameters->options_valid()
549
      && parameters->options().map_whole_files())
550
    this->whole_file_view_ = this->make_view(0, this->size_, 0, cache);
551
 
552
  // Try to find a View with the required BYTESHIFT.
553
  File_read::View* vshifted;
554
  File_read::View* v = this->find_view(offset + start, size,
555
                                       aligned ? byteshift : -1U,
556
                                       &vshifted);
557
  if (v != NULL)
558
    {
559
      if (cache)
560
        v->set_cache();
561
      return v;
562
    }
563
 
564
  // If VSHIFTED is not NULL, then it has the data we need, but with
565
  // the wrong byteshift.
566
  v = vshifted;
567
  if (v != NULL)
568
    {
569
      gold_assert(aligned);
570
 
571
      unsigned char* pbytes;
572
      pbytes = static_cast<unsigned char*>(malloc(v->size() + byteshift));
573
      if (pbytes == NULL)
574
        gold_nomem();
575
      memset(pbytes, 0, byteshift);
576
      memcpy(pbytes + byteshift, v->data() + v->byteshift(), v->size());
577
 
578
      File_read::View* shifted_view =
579
          new File_read::View(v->start(), v->size(), pbytes, byteshift,
580
                              cache, View::DATA_ALLOCATED_ARRAY);
581
 
582
      this->add_view(shifted_view);
583
      return shifted_view;
584
    }
585
 
586
  // Make a new view.  If we don't need an aligned view, use a
587
  // byteshift of 0, so that we can use mmap.
588
  return this->make_view(offset + start, size,
589
                         aligned ? byteshift : 0,
590
                         cache);
591
}
592
 
593
// Get a view into the file.
594
 
595
const unsigned char*
596
File_read::get_view(off_t offset, off_t start, section_size_type size,
597
                    bool aligned, bool cache)
598
{
599
  File_read::View* pv = this->find_or_make_view(offset, start, size,
600
                                                aligned, cache);
601
  return pv->data() + (offset + start - pv->start() + pv->byteshift());
602
}
603
 
604
File_view*
605
File_read::get_lasting_view(off_t offset, off_t start, section_size_type size,
606
                            bool aligned, bool cache)
607
{
608
  File_read::View* pv = this->find_or_make_view(offset, start, size,
609
                                                aligned, cache);
610
  pv->lock();
611
  return new File_view(*this, pv,
612
                       (pv->data()
613
                        + (offset + start - pv->start() + pv->byteshift())));
614
}
615
 
616
// Use readv to read COUNT entries from RM starting at START.  BASE
617
// must be added to all file offsets in RM.
618
 
619
void
620
File_read::do_readv(off_t base, const Read_multiple& rm, size_t start,
621
                    size_t count)
622
{
623
  unsigned char discard[File_read::page_size];
624
  iovec iov[File_read::max_readv_entries * 2];
625
  size_t iov_index = 0;
626
 
627
  off_t first_offset = rm[start].file_offset;
628
  off_t last_offset = first_offset;
629
  ssize_t want = 0;
630
  for (size_t i = 0; i < count; ++i)
631
    {
632
      const Read_multiple_entry& i_entry(rm[start + i]);
633
 
634
      if (i_entry.file_offset > last_offset)
635
        {
636
          size_t skip = i_entry.file_offset - last_offset;
637
          gold_assert(skip <= sizeof discard);
638
 
639
          iov[iov_index].iov_base = discard;
640
          iov[iov_index].iov_len = skip;
641
          ++iov_index;
642
 
643
          want += skip;
644
        }
645
 
646
      iov[iov_index].iov_base = i_entry.buffer;
647
      iov[iov_index].iov_len = i_entry.size;
648
      ++iov_index;
649
 
650
      want += i_entry.size;
651
 
652
      last_offset = i_entry.file_offset + i_entry.size;
653
    }
654
 
655
  this->reopen_descriptor();
656
 
657
  gold_assert(iov_index < sizeof iov / sizeof iov[0]);
658
 
659
  if (::lseek(this->descriptor_, base + first_offset, SEEK_SET) < 0)
660
    gold_fatal(_("%s: lseek failed: %s"),
661
               this->filename().c_str(), strerror(errno));
662
 
663
  ssize_t got = ::readv(this->descriptor_, iov, iov_index);
664
 
665
  if (got < 0)
666
    gold_fatal(_("%s: readv failed: %s"),
667
               this->filename().c_str(), strerror(errno));
668
  if (got != want)
669
    gold_fatal(_("%s: file too short: read only %zd of %zd bytes at %lld"),
670
               this->filename().c_str(),
671
               got, want, static_cast<long long>(base + first_offset));
672
}
673
 
674
// Portable IOV_MAX.
675
 
676
#if !defined(HAVE_READV)
677
#define GOLD_IOV_MAX 1
678
#elif defined(IOV_MAX)
679
#define GOLD_IOV_MAX IOV_MAX
680
#else
681
#define GOLD_IOV_MAX (File_read::max_readv_entries * 2)
682
#endif
683
 
684
// Read several pieces of data from the file.
685
 
686
void
687
File_read::read_multiple(off_t base, const Read_multiple& rm)
688
{
689
  static size_t iov_max = GOLD_IOV_MAX;
690
  size_t count = rm.size();
691
  size_t i = 0;
692
  while (i < count)
693
    {
694
      // Find up to MAX_READV_ENTRIES consecutive entries which are
695
      // less than one page apart.
696
      const Read_multiple_entry& i_entry(rm[i]);
697
      off_t i_off = i_entry.file_offset;
698
      off_t end_off = i_off + i_entry.size;
699
      size_t j;
700
      for (j = i + 1; j < count; ++j)
701
        {
702
          if (j - i >= File_read::max_readv_entries || j - i >= iov_max / 2)
703
            break;
704
          const Read_multiple_entry& j_entry(rm[j]);
705
          off_t j_off = j_entry.file_offset;
706
          gold_assert(j_off >= end_off);
707
          off_t j_end_off = j_off + j_entry.size;
708
          if (j_end_off - end_off >= File_read::page_size)
709
            break;
710
          end_off = j_end_off;
711
        }
712
 
713
      if (j == i + 1)
714
        this->read(base + i_off, i_entry.size, i_entry.buffer);
715
      else
716
        {
717
          File_read::View* view = this->find_view(base + i_off,
718
                                                  end_off - i_off,
719
                                                  -1U, NULL);
720
          if (view == NULL)
721
            this->do_readv(base, rm, i, j - i);
722
          else
723
            {
724
              const unsigned char* v = (view->data()
725
                                        + (base + i_off - view->start()
726
                                           + view->byteshift()));
727
              for (size_t k = i; k < j; ++k)
728
                {
729
                  const Read_multiple_entry& k_entry(rm[k]);
730
                  gold_assert((convert_to_section_size_type(k_entry.file_offset
731
                                                           - i_off)
732
                               + k_entry.size)
733
                              <= convert_to_section_size_type(end_off
734
                                                              - i_off));
735
                  memcpy(k_entry.buffer,
736
                         v + (k_entry.file_offset - i_off),
737
                         k_entry.size);
738
                }
739
            }
740
        }
741
 
742
      i = j;
743
    }
744
}
745
 
746
// Mark all views as no longer cached.
747
 
748
void
749
File_read::clear_view_cache_marks()
750
{
751
  // Just ignore this if there are multiple objects associated with
752
  // the file.  Otherwise we will wind up uncaching and freeing some
753
  // views for other objects.
754
  if (this->object_count_ > 1)
755
    return;
756
 
757
  for (Views::iterator p = this->views_.begin();
758
       p != this->views_.end();
759
       ++p)
760
    p->second->clear_cache();
761
  for (Saved_views::iterator p = this->saved_views_.begin();
762
       p != this->saved_views_.end();
763
       ++p)
764
    (*p)->clear_cache();
765
}
766
 
767
// Remove all the file views.  For a file which has multiple
768
// associated objects (i.e., an archive), we keep accessed views
769
// around until next time, in the hopes that they will be useful for
770
// the next object.
771
 
772
void
773
File_read::clear_views(Clear_views_mode mode)
774
{
775
  bool keep_files_mapped = (parameters->options_valid()
776
                            && parameters->options().keep_files_mapped());
777
  Views::iterator p = this->views_.begin();
778
  while (p != this->views_.end())
779
    {
780
      bool should_delete;
781
      if (p->second->is_locked() || p->second->is_permanent_view())
782
        should_delete = false;
783
      else if (mode == CLEAR_VIEWS_ALL)
784
        should_delete = true;
785
      else if ((p->second->should_cache()
786
                || p->second == this->whole_file_view_)
787
               && keep_files_mapped)
788
        should_delete = false;
789
      else if (this->object_count_ > 1
790
               && p->second->accessed()
791
               && mode != CLEAR_VIEWS_ARCHIVE)
792
        should_delete = false;
793
      else
794
        should_delete = true;
795
 
796
      if (should_delete)
797
        {
798
          if (p->second == this->whole_file_view_)
799
            this->whole_file_view_ = NULL;
800
          delete p->second;
801
 
802
          // map::erase invalidates only the iterator to the deleted
803
          // element.
804
          Views::iterator pe = p;
805
          ++p;
806
          this->views_.erase(pe);
807
        }
808
      else
809
        {
810
          p->second->clear_accessed();
811
          ++p;
812
        }
813
    }
814
 
815
  Saved_views::iterator q = this->saved_views_.begin();
816
  while (q != this->saved_views_.end())
817
    {
818
      if (!(*q)->is_locked())
819
        {
820
          delete *q;
821
          q = this->saved_views_.erase(q);
822
        }
823
      else
824
        {
825
          gold_assert(mode != CLEAR_VIEWS_ALL);
826
          ++q;
827
        }
828
    }
829
}
830
 
831
// Print statistical information to stderr.  This is used for --stats.
832
 
833
void
834
File_read::print_stats()
835
{
836
  fprintf(stderr, _("%s: total bytes mapped for read: %llu\n"),
837
          program_name, File_read::total_mapped_bytes);
838
  fprintf(stderr, _("%s: maximum bytes mapped for read at one time: %llu\n"),
839
          program_name, File_read::maximum_mapped_bytes);
840
}
841
 
842
// Class File_view.
843
 
844
File_view::~File_view()
845
{
846
  gold_assert(this->file_.is_locked());
847
  this->view_->unlock();
848
}
849
 
850
// Class Input_file.
851
 
852
// Create a file for testing.
853
 
854
Input_file::Input_file(const Task* task, const char* name,
855
                       const unsigned char* contents, off_t size)
856
  : file_()
857
{
858
  this->input_argument_ =
859
    new Input_file_argument(name, Input_file_argument::INPUT_FILE_TYPE_FILE,
860
                            "", false, Position_dependent_options());
861
  bool ok = this->file_.open(task, name, contents, size);
862
  gold_assert(ok);
863
}
864
 
865
// Return the position dependent options in force for this file.
866
 
867
const Position_dependent_options&
868
Input_file::options() const
869
{
870
  return this->input_argument_->options();
871
}
872
 
873
// Return the name given by the user.  For -lc this will return "c".
874
 
875
const char*
876
Input_file::name() const
877
{
878
  return this->input_argument_->name();
879
}
880
 
881
// Return whether this file is in a system directory.
882
 
883
bool
884
Input_file::is_in_system_directory() const
885
{
886
  if (this->is_in_sysroot())
887
    return true;
888
  return parameters->options().is_in_system_directory(this->filename());
889
}
890
 
891
// Return whether we are only reading symbols.
892
 
893
bool
894
Input_file::just_symbols() const
895
{
896
  return this->input_argument_->just_symbols();
897
}
898
 
899
// Return whether this is a file that we will search for in the list
900
// of directories.
901
 
902
bool
903
Input_file::will_search_for() const
904
{
905
  return (!IS_ABSOLUTE_PATH(this->input_argument_->name())
906
          && (this->input_argument_->is_lib()
907
              || this->input_argument_->is_searched_file()
908
              || this->input_argument_->extra_search_path() != NULL));
909
}
910
 
911
// Return the file last modification time.  Calls gold_fatal if the stat
912
// system call failed.
913
 
914
Timespec
915
File_read::get_mtime()
916
{
917
  struct stat file_stat;
918
  this->reopen_descriptor();
919
 
920
  if (fstat(this->descriptor_, &file_stat) < 0)
921
    gold_fatal(_("%s: stat failed: %s"), this->name_.c_str(),
922
               strerror(errno));
923
#ifdef HAVE_STAT_ST_MTIM
924
  return Timespec(file_stat.st_mtim.tv_sec, file_stat.st_mtim.tv_nsec);
925
#else
926
  return Timespec(file_stat.st_mtime, 0);
927
#endif
928
}
929
 
930
// Try to find a file in the extra search dirs.  Returns true on success.
931
 
932
bool
933
Input_file::try_extra_search_path(int* pindex,
934
                                  const Input_file_argument* input_argument,
935
                                  std::string filename, std::string* found_name,
936
                                  std::string* namep)
937
{
938
  if (input_argument->extra_search_path() == NULL)
939
    return false;
940
 
941
  std::string name = input_argument->extra_search_path();
942
  if (!IS_DIR_SEPARATOR(name[name.length() - 1]))
943
    name += '/';
944
  name += filename;
945
 
946
  struct stat dummy_stat;
947
  if (*pindex > 0 || ::stat(name.c_str(), &dummy_stat) < 0)
948
    return false;
949
 
950
  *found_name = filename;
951
  *namep = name;
952
  return true;
953
}
954
 
955
// Find the actual file.
956
// If the filename is not absolute, we assume it is in the current
957
// directory *except* when:
958
//    A) input_argument_->is_lib() is true;
959
//    B) input_argument_->is_searched_file() is true; or
960
//    C) input_argument_->extra_search_path() is not empty.
961
// In each, we look in extra_search_path + library_path to find
962
// the file location, rather than the current directory.
963
 
964
bool
965
Input_file::find_file(const Dirsearch& dirpath, int* pindex,
966
                      const Input_file_argument* input_argument,
967
                      bool* is_in_sysroot,
968
                      std::string* found_name, std::string* namep)
969
{
970
  std::string name;
971
 
972
  // Case 1: name is an absolute file, just try to open it
973
  // Case 2: name is relative but is_lib is false, is_searched_file is false,
974
  //         and extra_search_path is empty
975
  if (IS_ABSOLUTE_PATH(input_argument->name())
976
      || (!input_argument->is_lib()
977
          && !input_argument->is_searched_file()
978
          && input_argument->extra_search_path() == NULL))
979
    {
980
      name = input_argument->name();
981
      *found_name = name;
982
      *namep = name;
983
      return true;
984
    }
985
  // Case 3: is_lib is true or is_searched_file is true
986
  else if (input_argument->is_lib()
987
           || input_argument->is_searched_file())
988
    {
989
      std::vector<std::string> names;
990
      names.reserve(2);
991
      if (input_argument->is_lib())
992
        {
993
          std::string prefix = "lib";
994
          prefix += input_argument->name();
995
          if (parameters->options().is_static()
996
              || !input_argument->options().Bdynamic())
997
            names.push_back(prefix + ".a");
998
          else
999
            {
1000
              names.push_back(prefix + ".so");
1001
              names.push_back(prefix + ".a");
1002
            }
1003
        }
1004
      else
1005
        names.push_back(input_argument->name());
1006
 
1007
      for (std::vector<std::string>::const_iterator n = names.begin();
1008
           n != names.end();
1009
           ++n)
1010
        if (Input_file::try_extra_search_path(pindex, input_argument, *n,
1011
                                              found_name, namep))
1012
          return true;
1013
 
1014
      // It is not in the extra_search_path.
1015
      name = dirpath.find(names, is_in_sysroot, pindex, found_name);
1016
      if (name.empty())
1017
        {
1018
          gold_error(_("cannot find %s%s"),
1019
                     input_argument->is_lib() ? "-l" : "",
1020
                     input_argument->name());
1021
          return false;
1022
        }
1023
      *namep = name;
1024
      return true;
1025
    }
1026
  // Case 4: extra_search_path is not empty
1027
  else
1028
    {
1029
      gold_assert(input_argument->extra_search_path() != NULL);
1030
 
1031
      if (try_extra_search_path(pindex, input_argument, input_argument->name(),
1032
                                found_name, namep))
1033
        return true;
1034
 
1035
      // extra_search_path failed, so check the normal search-path.
1036
      int index = *pindex;
1037
      if (index > 0)
1038
        --index;
1039
      name = dirpath.find(std::vector<std::string>(1, input_argument->name()),
1040
                          is_in_sysroot, &index, found_name);
1041
      if (name.empty())
1042
        {
1043
          gold_error(_("cannot find %s"),
1044
                     input_argument->name());
1045
          return false;
1046
        }
1047
      *namep = name;
1048
      *pindex = index + 1;
1049
      return true;
1050
    }
1051
}
1052
 
1053
// Open the file.
1054
 
1055
bool
1056
Input_file::open(const Dirsearch& dirpath, const Task* task, int* pindex)
1057
{
1058
  std::string name;
1059
  if (!Input_file::find_file(dirpath, pindex, this->input_argument_,
1060
                             &this->is_in_sysroot_, &this->found_name_, &name))
1061
    return false;
1062
 
1063
  // Now that we've figured out where the file lives, try to open it.
1064
 
1065
  General_options::Object_format format =
1066
    this->input_argument_->options().format_enum();
1067
  bool ok;
1068
  if (format == General_options::OBJECT_FORMAT_ELF)
1069
    {
1070
      ok = this->file_.open(task, name);
1071
      this->format_ = FORMAT_ELF;
1072
    }
1073
  else
1074
    {
1075
      gold_assert(format == General_options::OBJECT_FORMAT_BINARY);
1076
      ok = this->open_binary(task, name);
1077
      this->format_ = FORMAT_BINARY;
1078
    }
1079
 
1080
  if (!ok)
1081
    {
1082
      gold_error(_("cannot open %s: %s"),
1083
                 name.c_str(), strerror(errno));
1084
      this->format_ = FORMAT_NONE;
1085
      return false;
1086
    }
1087
 
1088
  return true;
1089
}
1090
 
1091
// Open a file for --format binary.
1092
 
1093
bool
1094
Input_file::open_binary(const Task* task, const std::string& name)
1095
{
1096
  // In order to open a binary file, we need machine code, size, and
1097
  // endianness.  We may not have a valid target at this point, in
1098
  // which case we use the default target.
1099
  parameters_force_valid_target();
1100
  const Target& target(parameters->target());
1101
 
1102
  Binary_to_elf binary_to_elf(target.machine_code(),
1103
                              target.get_size(),
1104
                              target.is_big_endian(),
1105
                              name);
1106
  if (!binary_to_elf.convert(task))
1107
    return false;
1108
  return this->file_.open(task, name, binary_to_elf.converted_data_leak(),
1109
                          binary_to_elf.converted_size());
1110
}
1111
 
1112
} // End namespace gold.

powered by: WebSVN 2.1.0

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