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 213

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 163 khays
  gold_assert(start <= this->size_
333
              && (static_cast<unsigned long long>(size)
334
                  <= static_cast<unsigned long long>(this->size_ - start)));
335
 
336 27 khays
  if (vshifted != NULL)
337
    *vshifted = NULL;
338
 
339
  // If we have the whole file mmapped, and the alignment is right,
340
  // we can return it.
341
  if (this->whole_file_view_)
342
    if (byteshift == -1U || byteshift == 0)
343
      return this->whole_file_view_;
344
 
345
  off_t page = File_read::page_offset(start);
346
 
347
  unsigned int bszero = 0;
348
  Views::const_iterator p = this->views_.upper_bound(std::make_pair(page - 1,
349
                                                                    bszero));
350
 
351
  while (p != this->views_.end() && p->first.first <= page)
352
    {
353
      if (p->second->start() <= start
354
          && (p->second->start() + static_cast<off_t>(p->second->size())
355
              >= start + static_cast<off_t>(size)))
356
        {
357
          if (byteshift == -1U || byteshift == p->second->byteshift())
358
            {
359
              p->second->set_accessed();
360
              return p->second;
361
            }
362
 
363
          if (vshifted != NULL && *vshifted == NULL)
364
            *vshifted = p->second;
365
        }
366
 
367
      ++p;
368
    }
369
 
370
  return NULL;
371
}
372
 
373
// Read SIZE bytes from the file starting at offset START.  Read into
374
// the buffer at P.
375
 
376
void
377
File_read::do_read(off_t start, section_size_type size, void* p)
378
{
379
  ssize_t bytes;
380
  if (this->whole_file_view_ != NULL)
381
    {
382
      bytes = this->size_ - start;
383
      if (static_cast<section_size_type>(bytes) >= size)
384
        {
385
          memcpy(p, this->whole_file_view_->data() + start, size);
386
          return;
387
        }
388
    }
389
  else
390
    {
391
      this->reopen_descriptor();
392
      bytes = ::pread(this->descriptor_, p, size, start);
393
      if (static_cast<section_size_type>(bytes) == size)
394
        return;
395
 
396
      if (bytes < 0)
397
        {
398
          gold_fatal(_("%s: pread failed: %s"),
399
                     this->filename().c_str(), strerror(errno));
400
          return;
401
        }
402
    }
403
 
404
  gold_fatal(_("%s: file too short: read only %lld of %lld bytes at %lld"),
405
             this->filename().c_str(),
406
             static_cast<long long>(bytes),
407
             static_cast<long long>(size),
408
             static_cast<long long>(start));
409
}
410
 
411
// Read data from the file.
412
 
413
void
414
File_read::read(off_t start, section_size_type size, void* p)
415
{
416
  const File_read::View* pv = this->find_view(start, size, -1U, NULL);
417
  if (pv != NULL)
418
    {
419
      memcpy(p, pv->data() + (start - pv->start() + pv->byteshift()), size);
420
      return;
421
    }
422
 
423
  this->do_read(start, size, p);
424
}
425
 
426
// Add a new view.  There may already be an existing view at this
427
// offset.  If there is, the new view will be larger, and should
428
// replace the old view.
429
 
430
void
431
File_read::add_view(File_read::View* v)
432
{
433
  std::pair<Views::iterator, bool> ins =
434
    this->views_.insert(std::make_pair(std::make_pair(v->start(),
435
                                                      v->byteshift()),
436
                                       v));
437
  if (ins.second)
438
    return;
439
 
440
  // There was an existing view at this offset.  It must not be large
441
  // enough.  We can't delete it here, since something might be using
442
  // it; we put it on a list to be deleted when the file is unlocked.
443
  File_read::View* vold = ins.first->second;
444
  gold_assert(vold->size() < v->size());
445
  if (vold->should_cache())
446
    {
447
      v->set_cache();
448
      vold->clear_cache();
449
    }
450
  this->saved_views_.push_back(vold);
451
 
452
  ins.first->second = v;
453
}
454
 
455
// Make a new view with a specified byteshift, reading the data from
456
// the file.
457
 
458
File_read::View*
459
File_read::make_view(off_t start, section_size_type size,
460
                     unsigned int byteshift, bool cache)
461
{
462
  gold_assert(size > 0);
463 163 khays
  gold_assert(start <= this->size_
464
              && (static_cast<unsigned long long>(size)
465
                  <= static_cast<unsigned long long>(this->size_ - start)));
466 27 khays
 
467
  off_t poff = File_read::page_offset(start);
468
 
469
  section_size_type psize = File_read::pages(size + (start - poff));
470
 
471
  if (poff + static_cast<off_t>(psize) >= this->size_)
472
    {
473
      psize = this->size_ - poff;
474
      gold_assert(psize >= size);
475
    }
476
 
477
  void* p;
478
  View::Data_ownership ownership;
479
  if (byteshift != 0)
480
    {
481
      p = malloc(psize + byteshift);
482
      if (p == NULL)
483
        gold_nomem();
484
      memset(p, 0, byteshift);
485
      this->do_read(poff, psize, static_cast<unsigned char*>(p) + byteshift);
486
      ownership = View::DATA_ALLOCATED_ARRAY;
487
    }
488
  else
489
    {
490
      this->reopen_descriptor();
491
      p = ::mmap(NULL, psize, PROT_READ, MAP_PRIVATE, this->descriptor_, poff);
492
      if (p != MAP_FAILED)
493
        {
494
          ownership = View::DATA_MMAPPED;
495
          this->mapped_bytes_ += psize;
496
        }
497
      else
498
        {
499
          p = malloc(psize);
500
          if (p == NULL)
501
            gold_nomem();
502
          this->do_read(poff, psize, p);
503
          ownership = View::DATA_ALLOCATED_ARRAY;
504
        }
505
    }
506
 
507
  const unsigned char* pbytes = static_cast<const unsigned char*>(p);
508
  File_read::View* v = new File_read::View(poff, psize, pbytes, byteshift,
509
                                           cache, ownership);
510
 
511
  this->add_view(v);
512
 
513
  return v;
514
}
515
 
516
// Find a View or make a new one, shifted as required by the file
517
// offset OFFSET and ALIGNED.
518
 
519
File_read::View*
520
File_read::find_or_make_view(off_t offset, off_t start,
521
                             section_size_type size, bool aligned, bool cache)
522
{
523 163 khays
  // Check that start and end of the view are within the file.
524
  if (start > this->size_
525
      || (static_cast<unsigned long long>(size)
526
          > static_cast<unsigned long long>(this->size_ - start)))
527
    gold_fatal(_("%s: attempt to map %lld bytes at offset %lld exceeds "
528
                 "size of file; the file may be corrupt"),
529
                   this->filename().c_str(),
530
                   static_cast<long long>(size),
531
                   static_cast<long long>(start));
532
 
533 27 khays
  unsigned int byteshift;
534
  if (offset == 0)
535
    byteshift = 0;
536
  else
537
    {
538
      unsigned int target_size = (!parameters->target_valid()
539
                                  ? 64
540
                                  : parameters->target().get_size());
541
      byteshift = offset & ((target_size / 8) - 1);
542
 
543
      // Set BYTESHIFT to the number of dummy bytes which must be
544
      // inserted before the data in order for this data to be
545
      // aligned.
546
      if (byteshift != 0)
547
        byteshift = (target_size / 8) - byteshift;
548
    }
549
 
550
  // If --map-whole-files is set, make sure we have a
551
  // whole file view.  Options may not yet be ready, e.g.,
552
  // when reading a version script.  We then default to
553
  // --no-map-whole-files.
554
  if (this->whole_file_view_ == NULL
555
      && parameters->options_valid()
556
      && parameters->options().map_whole_files())
557
    this->whole_file_view_ = this->make_view(0, this->size_, 0, cache);
558
 
559
  // Try to find a View with the required BYTESHIFT.
560
  File_read::View* vshifted;
561
  File_read::View* v = this->find_view(offset + start, size,
562
                                       aligned ? byteshift : -1U,
563
                                       &vshifted);
564
  if (v != NULL)
565
    {
566
      if (cache)
567
        v->set_cache();
568
      return v;
569
    }
570
 
571
  // If VSHIFTED is not NULL, then it has the data we need, but with
572
  // the wrong byteshift.
573
  v = vshifted;
574
  if (v != NULL)
575
    {
576
      gold_assert(aligned);
577
 
578
      unsigned char* pbytes;
579
      pbytes = static_cast<unsigned char*>(malloc(v->size() + byteshift));
580
      if (pbytes == NULL)
581
        gold_nomem();
582
      memset(pbytes, 0, byteshift);
583
      memcpy(pbytes + byteshift, v->data() + v->byteshift(), v->size());
584
 
585
      File_read::View* shifted_view =
586
          new File_read::View(v->start(), v->size(), pbytes, byteshift,
587
                              cache, View::DATA_ALLOCATED_ARRAY);
588
 
589
      this->add_view(shifted_view);
590
      return shifted_view;
591
    }
592
 
593
  // Make a new view.  If we don't need an aligned view, use a
594
  // byteshift of 0, so that we can use mmap.
595
  return this->make_view(offset + start, size,
596
                         aligned ? byteshift : 0,
597
                         cache);
598
}
599
 
600
// Get a view into the file.
601
 
602
const unsigned char*
603
File_read::get_view(off_t offset, off_t start, section_size_type size,
604
                    bool aligned, bool cache)
605
{
606
  File_read::View* pv = this->find_or_make_view(offset, start, size,
607
                                                aligned, cache);
608
  return pv->data() + (offset + start - pv->start() + pv->byteshift());
609
}
610
 
611
File_view*
612
File_read::get_lasting_view(off_t offset, off_t start, section_size_type size,
613
                            bool aligned, bool cache)
614
{
615
  File_read::View* pv = this->find_or_make_view(offset, start, size,
616
                                                aligned, cache);
617
  pv->lock();
618
  return new File_view(*this, pv,
619
                       (pv->data()
620
                        + (offset + start - pv->start() + pv->byteshift())));
621
}
622
 
623
// Use readv to read COUNT entries from RM starting at START.  BASE
624
// must be added to all file offsets in RM.
625
 
626
void
627
File_read::do_readv(off_t base, const Read_multiple& rm, size_t start,
628
                    size_t count)
629
{
630
  unsigned char discard[File_read::page_size];
631
  iovec iov[File_read::max_readv_entries * 2];
632
  size_t iov_index = 0;
633
 
634
  off_t first_offset = rm[start].file_offset;
635
  off_t last_offset = first_offset;
636
  ssize_t want = 0;
637
  for (size_t i = 0; i < count; ++i)
638
    {
639
      const Read_multiple_entry& i_entry(rm[start + i]);
640
 
641
      if (i_entry.file_offset > last_offset)
642
        {
643
          size_t skip = i_entry.file_offset - last_offset;
644
          gold_assert(skip <= sizeof discard);
645
 
646
          iov[iov_index].iov_base = discard;
647
          iov[iov_index].iov_len = skip;
648
          ++iov_index;
649
 
650
          want += skip;
651
        }
652
 
653
      iov[iov_index].iov_base = i_entry.buffer;
654
      iov[iov_index].iov_len = i_entry.size;
655
      ++iov_index;
656
 
657
      want += i_entry.size;
658
 
659
      last_offset = i_entry.file_offset + i_entry.size;
660
    }
661
 
662
  this->reopen_descriptor();
663
 
664
  gold_assert(iov_index < sizeof iov / sizeof iov[0]);
665
 
666
  if (::lseek(this->descriptor_, base + first_offset, SEEK_SET) < 0)
667
    gold_fatal(_("%s: lseek failed: %s"),
668
               this->filename().c_str(), strerror(errno));
669
 
670
  ssize_t got = ::readv(this->descriptor_, iov, iov_index);
671
 
672
  if (got < 0)
673
    gold_fatal(_("%s: readv failed: %s"),
674
               this->filename().c_str(), strerror(errno));
675
  if (got != want)
676
    gold_fatal(_("%s: file too short: read only %zd of %zd bytes at %lld"),
677
               this->filename().c_str(),
678
               got, want, static_cast<long long>(base + first_offset));
679
}
680
 
681
// Portable IOV_MAX.
682
 
683
#if !defined(HAVE_READV)
684
#define GOLD_IOV_MAX 1
685
#elif defined(IOV_MAX)
686
#define GOLD_IOV_MAX IOV_MAX
687
#else
688
#define GOLD_IOV_MAX (File_read::max_readv_entries * 2)
689
#endif
690
 
691
// Read several pieces of data from the file.
692
 
693
void
694
File_read::read_multiple(off_t base, const Read_multiple& rm)
695
{
696
  static size_t iov_max = GOLD_IOV_MAX;
697
  size_t count = rm.size();
698
  size_t i = 0;
699
  while (i < count)
700
    {
701
      // Find up to MAX_READV_ENTRIES consecutive entries which are
702
      // less than one page apart.
703
      const Read_multiple_entry& i_entry(rm[i]);
704
      off_t i_off = i_entry.file_offset;
705
      off_t end_off = i_off + i_entry.size;
706
      size_t j;
707
      for (j = i + 1; j < count; ++j)
708
        {
709
          if (j - i >= File_read::max_readv_entries || j - i >= iov_max / 2)
710
            break;
711
          const Read_multiple_entry& j_entry(rm[j]);
712
          off_t j_off = j_entry.file_offset;
713
          gold_assert(j_off >= end_off);
714
          off_t j_end_off = j_off + j_entry.size;
715
          if (j_end_off - end_off >= File_read::page_size)
716
            break;
717
          end_off = j_end_off;
718
        }
719
 
720
      if (j == i + 1)
721
        this->read(base + i_off, i_entry.size, i_entry.buffer);
722
      else
723
        {
724
          File_read::View* view = this->find_view(base + i_off,
725
                                                  end_off - i_off,
726
                                                  -1U, NULL);
727
          if (view == NULL)
728
            this->do_readv(base, rm, i, j - i);
729
          else
730
            {
731
              const unsigned char* v = (view->data()
732
                                        + (base + i_off - view->start()
733
                                           + view->byteshift()));
734
              for (size_t k = i; k < j; ++k)
735
                {
736
                  const Read_multiple_entry& k_entry(rm[k]);
737
                  gold_assert((convert_to_section_size_type(k_entry.file_offset
738
                                                           - i_off)
739
                               + k_entry.size)
740
                              <= convert_to_section_size_type(end_off
741
                                                              - i_off));
742
                  memcpy(k_entry.buffer,
743
                         v + (k_entry.file_offset - i_off),
744
                         k_entry.size);
745
                }
746
            }
747
        }
748
 
749
      i = j;
750
    }
751
}
752
 
753
// Mark all views as no longer cached.
754
 
755
void
756
File_read::clear_view_cache_marks()
757
{
758
  // Just ignore this if there are multiple objects associated with
759
  // the file.  Otherwise we will wind up uncaching and freeing some
760
  // views for other objects.
761
  if (this->object_count_ > 1)
762
    return;
763
 
764
  for (Views::iterator p = this->views_.begin();
765
       p != this->views_.end();
766
       ++p)
767
    p->second->clear_cache();
768
  for (Saved_views::iterator p = this->saved_views_.begin();
769
       p != this->saved_views_.end();
770
       ++p)
771
    (*p)->clear_cache();
772
}
773
 
774
// Remove all the file views.  For a file which has multiple
775
// associated objects (i.e., an archive), we keep accessed views
776
// around until next time, in the hopes that they will be useful for
777
// the next object.
778
 
779
void
780
File_read::clear_views(Clear_views_mode mode)
781
{
782
  bool keep_files_mapped = (parameters->options_valid()
783
                            && parameters->options().keep_files_mapped());
784
  Views::iterator p = this->views_.begin();
785
  while (p != this->views_.end())
786
    {
787
      bool should_delete;
788
      if (p->second->is_locked() || p->second->is_permanent_view())
789
        should_delete = false;
790
      else if (mode == CLEAR_VIEWS_ALL)
791
        should_delete = true;
792
      else if ((p->second->should_cache()
793
                || p->second == this->whole_file_view_)
794
               && keep_files_mapped)
795
        should_delete = false;
796
      else if (this->object_count_ > 1
797
               && p->second->accessed()
798
               && mode != CLEAR_VIEWS_ARCHIVE)
799
        should_delete = false;
800
      else
801
        should_delete = true;
802
 
803
      if (should_delete)
804
        {
805
          if (p->second == this->whole_file_view_)
806
            this->whole_file_view_ = NULL;
807
          delete p->second;
808
 
809
          // map::erase invalidates only the iterator to the deleted
810
          // element.
811
          Views::iterator pe = p;
812
          ++p;
813
          this->views_.erase(pe);
814
        }
815
      else
816
        {
817
          p->second->clear_accessed();
818
          ++p;
819
        }
820
    }
821
 
822
  Saved_views::iterator q = this->saved_views_.begin();
823
  while (q != this->saved_views_.end())
824
    {
825
      if (!(*q)->is_locked())
826
        {
827
          delete *q;
828
          q = this->saved_views_.erase(q);
829
        }
830
      else
831
        {
832
          gold_assert(mode != CLEAR_VIEWS_ALL);
833
          ++q;
834
        }
835
    }
836
}
837
 
838
// Print statistical information to stderr.  This is used for --stats.
839
 
840
void
841
File_read::print_stats()
842
{
843
  fprintf(stderr, _("%s: total bytes mapped for read: %llu\n"),
844
          program_name, File_read::total_mapped_bytes);
845
  fprintf(stderr, _("%s: maximum bytes mapped for read at one time: %llu\n"),
846
          program_name, File_read::maximum_mapped_bytes);
847
}
848
 
849
// Class File_view.
850
 
851
File_view::~File_view()
852
{
853
  gold_assert(this->file_.is_locked());
854
  this->view_->unlock();
855
}
856
 
857
// Class Input_file.
858
 
859
// Create a file for testing.
860
 
861
Input_file::Input_file(const Task* task, const char* name,
862
                       const unsigned char* contents, off_t size)
863
  : file_()
864
{
865
  this->input_argument_ =
866
    new Input_file_argument(name, Input_file_argument::INPUT_FILE_TYPE_FILE,
867
                            "", false, Position_dependent_options());
868
  bool ok = this->file_.open(task, name, contents, size);
869
  gold_assert(ok);
870
}
871
 
872
// Return the position dependent options in force for this file.
873
 
874
const Position_dependent_options&
875
Input_file::options() const
876
{
877
  return this->input_argument_->options();
878
}
879
 
880
// Return the name given by the user.  For -lc this will return "c".
881
 
882
const char*
883
Input_file::name() const
884
{
885
  return this->input_argument_->name();
886
}
887
 
888
// Return whether this file is in a system directory.
889
 
890
bool
891
Input_file::is_in_system_directory() const
892
{
893
  if (this->is_in_sysroot())
894
    return true;
895
  return parameters->options().is_in_system_directory(this->filename());
896
}
897
 
898
// Return whether we are only reading symbols.
899
 
900
bool
901
Input_file::just_symbols() const
902
{
903
  return this->input_argument_->just_symbols();
904
}
905
 
906
// Return whether this is a file that we will search for in the list
907
// of directories.
908
 
909
bool
910
Input_file::will_search_for() const
911
{
912
  return (!IS_ABSOLUTE_PATH(this->input_argument_->name())
913
          && (this->input_argument_->is_lib()
914
              || this->input_argument_->is_searched_file()
915
              || this->input_argument_->extra_search_path() != NULL));
916
}
917
 
918
// Return the file last modification time.  Calls gold_fatal if the stat
919
// system call failed.
920
 
921
Timespec
922
File_read::get_mtime()
923
{
924
  struct stat file_stat;
925
  this->reopen_descriptor();
926
 
927
  if (fstat(this->descriptor_, &file_stat) < 0)
928
    gold_fatal(_("%s: stat failed: %s"), this->name_.c_str(),
929
               strerror(errno));
930
#ifdef HAVE_STAT_ST_MTIM
931
  return Timespec(file_stat.st_mtim.tv_sec, file_stat.st_mtim.tv_nsec);
932
#else
933
  return Timespec(file_stat.st_mtime, 0);
934
#endif
935
}
936
 
937
// Try to find a file in the extra search dirs.  Returns true on success.
938
 
939
bool
940
Input_file::try_extra_search_path(int* pindex,
941
                                  const Input_file_argument* input_argument,
942
                                  std::string filename, std::string* found_name,
943
                                  std::string* namep)
944
{
945
  if (input_argument->extra_search_path() == NULL)
946
    return false;
947
 
948
  std::string name = input_argument->extra_search_path();
949
  if (!IS_DIR_SEPARATOR(name[name.length() - 1]))
950
    name += '/';
951
  name += filename;
952
 
953
  struct stat dummy_stat;
954
  if (*pindex > 0 || ::stat(name.c_str(), &dummy_stat) < 0)
955
    return false;
956
 
957
  *found_name = filename;
958
  *namep = name;
959
  return true;
960
}
961
 
962
// Find the actual file.
963
// If the filename is not absolute, we assume it is in the current
964
// directory *except* when:
965
//    A) input_argument_->is_lib() is true;
966
//    B) input_argument_->is_searched_file() is true; or
967
//    C) input_argument_->extra_search_path() is not empty.
968
// In each, we look in extra_search_path + library_path to find
969
// the file location, rather than the current directory.
970
 
971
bool
972
Input_file::find_file(const Dirsearch& dirpath, int* pindex,
973
                      const Input_file_argument* input_argument,
974
                      bool* is_in_sysroot,
975
                      std::string* found_name, std::string* namep)
976
{
977
  std::string name;
978
 
979
  // Case 1: name is an absolute file, just try to open it
980
  // Case 2: name is relative but is_lib is false, is_searched_file is false,
981
  //         and extra_search_path is empty
982
  if (IS_ABSOLUTE_PATH(input_argument->name())
983
      || (!input_argument->is_lib()
984
          && !input_argument->is_searched_file()
985
          && input_argument->extra_search_path() == NULL))
986
    {
987
      name = input_argument->name();
988
      *found_name = name;
989
      *namep = name;
990
      return true;
991
    }
992
  // Case 3: is_lib is true or is_searched_file is true
993
  else if (input_argument->is_lib()
994
           || input_argument->is_searched_file())
995
    {
996
      std::vector<std::string> names;
997
      names.reserve(2);
998
      if (input_argument->is_lib())
999
        {
1000
          std::string prefix = "lib";
1001
          prefix += input_argument->name();
1002
          if (parameters->options().is_static()
1003
              || !input_argument->options().Bdynamic())
1004
            names.push_back(prefix + ".a");
1005
          else
1006
            {
1007
              names.push_back(prefix + ".so");
1008
              names.push_back(prefix + ".a");
1009
            }
1010
        }
1011
      else
1012
        names.push_back(input_argument->name());
1013
 
1014
      for (std::vector<std::string>::const_iterator n = names.begin();
1015
           n != names.end();
1016
           ++n)
1017
        if (Input_file::try_extra_search_path(pindex, input_argument, *n,
1018
                                              found_name, namep))
1019
          return true;
1020
 
1021
      // It is not in the extra_search_path.
1022
      name = dirpath.find(names, is_in_sysroot, pindex, found_name);
1023
      if (name.empty())
1024
        {
1025
          gold_error(_("cannot find %s%s"),
1026
                     input_argument->is_lib() ? "-l" : "",
1027
                     input_argument->name());
1028
          return false;
1029
        }
1030
      *namep = name;
1031
      return true;
1032
    }
1033
  // Case 4: extra_search_path is not empty
1034
  else
1035
    {
1036
      gold_assert(input_argument->extra_search_path() != NULL);
1037
 
1038
      if (try_extra_search_path(pindex, input_argument, input_argument->name(),
1039
                                found_name, namep))
1040
        return true;
1041
 
1042
      // extra_search_path failed, so check the normal search-path.
1043
      int index = *pindex;
1044
      if (index > 0)
1045
        --index;
1046
      name = dirpath.find(std::vector<std::string>(1, input_argument->name()),
1047
                          is_in_sysroot, &index, found_name);
1048
      if (name.empty())
1049
        {
1050
          gold_error(_("cannot find %s"),
1051
                     input_argument->name());
1052
          return false;
1053
        }
1054
      *namep = name;
1055
      *pindex = index + 1;
1056
      return true;
1057
    }
1058
}
1059
 
1060
// Open the file.
1061
 
1062
bool
1063
Input_file::open(const Dirsearch& dirpath, const Task* task, int* pindex)
1064
{
1065
  std::string name;
1066
  if (!Input_file::find_file(dirpath, pindex, this->input_argument_,
1067
                             &this->is_in_sysroot_, &this->found_name_, &name))
1068
    return false;
1069
 
1070
  // Now that we've figured out where the file lives, try to open it.
1071
 
1072
  General_options::Object_format format =
1073
    this->input_argument_->options().format_enum();
1074
  bool ok;
1075
  if (format == General_options::OBJECT_FORMAT_ELF)
1076
    {
1077
      ok = this->file_.open(task, name);
1078
      this->format_ = FORMAT_ELF;
1079
    }
1080
  else
1081
    {
1082
      gold_assert(format == General_options::OBJECT_FORMAT_BINARY);
1083
      ok = this->open_binary(task, name);
1084
      this->format_ = FORMAT_BINARY;
1085
    }
1086
 
1087
  if (!ok)
1088
    {
1089
      gold_error(_("cannot open %s: %s"),
1090
                 name.c_str(), strerror(errno));
1091
      this->format_ = FORMAT_NONE;
1092
      return false;
1093
    }
1094
 
1095
  return true;
1096
}
1097
 
1098
// Open a file for --format binary.
1099
 
1100
bool
1101
Input_file::open_binary(const Task* task, const std::string& name)
1102
{
1103
  // In order to open a binary file, we need machine code, size, and
1104
  // endianness.  We may not have a valid target at this point, in
1105
  // which case we use the default target.
1106
  parameters_force_valid_target();
1107
  const Target& target(parameters->target());
1108
 
1109
  Binary_to_elf binary_to_elf(target.machine_code(),
1110
                              target.get_size(),
1111
                              target.is_big_endian(),
1112
                              name);
1113
  if (!binary_to_elf.convert(task))
1114
    return false;
1115
  return this->file_.open(task, name, binary_to_elf.converted_data_leak(),
1116
                          binary_to_elf.converted_size());
1117
}
1118
 
1119
} // End namespace gold.

powered by: WebSVN 2.1.0

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