* fileread.cc (File_read::find_view): Add byteshift and vshifted
parameters. Update for new key type to views_. Change all callers. (File_read::read): Adjust for byteshift in returned view. (File_read::add_view): New function, broken out of find_and_make_view. (File_read::make_view): New function, broken out of find_and_make_view. (File_read::find_or_make_view): Add offset and aligned parameters. Rewrite accordingly. Change all callers. (File_read::get_view): Add offset and aligned parameters. Adjust for byteshift in return value. (File_read::get_lasting_view): Likewise. * fileread.h (class File_read): Update declarations. (class File_read::View): Add byteshift_ field. Add byteshift to constructor. Add byteshift method. * archive.h (Archive::clear_uncached_views): New function. (Archive::get_view): Add aligned parameter. Change all callers. * object.h (Object::get_view): Add aligned parameter. Change all callers. (Object::get_lasting_view): Likewise. * fileread.cc (File_read::release): Don't call clear_views if there are multiple objects. * fileread.h (File_read::clear_uncached_views): New function. * archive.cc (Add_archive_symbols::run): Call clear_uncached_views on the archive.
This commit is contained in:
parent
5caffa0e9b
commit
39d0cb0e83
@ -1,3 +1,33 @@
|
||||
2008-04-02 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* fileread.cc (File_read::find_view): Add byteshift and vshifted
|
||||
parameters. Update for new key type to views_. Change all
|
||||
callers.
|
||||
(File_read::read): Adjust for byteshift in returned view.
|
||||
(File_read::add_view): New function, broken out of
|
||||
find_and_make_view.
|
||||
(File_read::make_view): New function, broken out of
|
||||
find_and_make_view.
|
||||
(File_read::find_or_make_view): Add offset and aligned
|
||||
parameters. Rewrite accordingly. Change all callers.
|
||||
(File_read::get_view): Add offset and aligned parameters. Adjust
|
||||
for byteshift in return value.
|
||||
(File_read::get_lasting_view): Likewise.
|
||||
* fileread.h (class File_read): Update declarations.
|
||||
(class File_read::View): Add byteshift_ field. Add byteshift to
|
||||
constructor. Add byteshift method.
|
||||
* archive.h (Archive::clear_uncached_views): New function.
|
||||
(Archive::get_view): Add aligned parameter. Change all callers.
|
||||
* object.h (Object::get_view): Add aligned parameter. Change all
|
||||
callers.
|
||||
(Object::get_lasting_view): Likewise.
|
||||
|
||||
* fileread.cc (File_read::release): Don't call clear_views if
|
||||
there are multiple objects.
|
||||
* fileread.h (File_read::clear_uncached_views): New function.
|
||||
* archive.cc (Add_archive_symbols::run): Call clear_uncached_views
|
||||
on the archive.
|
||||
|
||||
2008-03-31 Cary Coutant <ccoutant@google.com>
|
||||
|
||||
Add thin archive support.
|
||||
|
@ -112,7 +112,7 @@ Archive::setup()
|
||||
if (xname == "/")
|
||||
{
|
||||
const unsigned char* p = this->get_view(off + sizeof(Archive_header),
|
||||
extended_size, true);
|
||||
extended_size, false, true);
|
||||
const char* px = reinterpret_cast<const char*>(p);
|
||||
this->extended_names_.assign(px, extended_size);
|
||||
}
|
||||
@ -137,7 +137,7 @@ void
|
||||
Archive::read_armap(off_t start, section_size_type size)
|
||||
{
|
||||
// Read in the entire armap.
|
||||
const unsigned char* p = this->get_view(start, size, false);
|
||||
const unsigned char* p = this->get_view(start, size, true, false);
|
||||
|
||||
// Numbers in the armap are always big-endian.
|
||||
const elfcpp::Elf_Word* pword = reinterpret_cast<const elfcpp::Elf_Word*>(p);
|
||||
@ -178,7 +178,8 @@ off_t
|
||||
Archive::read_header(off_t off, bool cache, std::string* pname,
|
||||
off_t* nested_off)
|
||||
{
|
||||
const unsigned char* p = this->get_view(off, sizeof(Archive_header), cache);
|
||||
const unsigned char* p = this->get_view(off, sizeof(Archive_header), true,
|
||||
cache);
|
||||
const Archive_header* hdr = reinterpret_cast<const Archive_header*>(p);
|
||||
return this->interpret_header(hdr, off, pname, nested_off);
|
||||
}
|
||||
@ -554,6 +555,7 @@ Add_archive_symbols::run(Workqueue*)
|
||||
this->archive_->unlock_nested_archives();
|
||||
|
||||
this->archive_->release();
|
||||
this->archive_->clear_uncached_views();
|
||||
|
||||
if (this->input_group_ != NULL)
|
||||
this->input_group_->add_archive(this->archive_);
|
||||
|
@ -100,6 +100,11 @@ class Archive
|
||||
release()
|
||||
{ this->input_file_->file().release(); }
|
||||
|
||||
// Clear uncached views in the underlying file.
|
||||
void
|
||||
clear_uncached_views()
|
||||
{ this->input_file_->file().clear_uncached_views(); }
|
||||
|
||||
// Unlock any nested archives.
|
||||
void
|
||||
unlock_nested_archives();
|
||||
@ -117,8 +122,8 @@ class Archive
|
||||
|
||||
// Get a view into the underlying file.
|
||||
const unsigned char*
|
||||
get_view(off_t start, section_size_type size, bool cache)
|
||||
{ return this->input_file_->file().get_view(start, size, cache); }
|
||||
get_view(off_t start, section_size_type size, bool aligned, bool cache)
|
||||
{ return this->input_file_->file().get_view(0, start, size, aligned, cache); }
|
||||
|
||||
// Read the archive symbol map.
|
||||
void
|
||||
|
@ -132,7 +132,7 @@ Binary_to_elf::sized_convert(const Task* task)
|
||||
}
|
||||
|
||||
section_size_type filesize = convert_to_section_size_type(f.filesize());
|
||||
const unsigned char* fileview = f.get_view(0, filesize, false);
|
||||
const unsigned char* fileview = f.get_view(0, 0, filesize, false, false);
|
||||
|
||||
unsigned int align;
|
||||
if (size == 32)
|
||||
|
@ -183,7 +183,7 @@ Sized_dynobj<size, big_endian>::read_dynsym_section(
|
||||
shndx, shdr.get_sh_link(), link);
|
||||
|
||||
*view = this->get_lasting_view(shdr.get_sh_offset(), shdr.get_sh_size(),
|
||||
false);
|
||||
true, false);
|
||||
*view_size = convert_to_section_size_type(shdr.get_sh_size());
|
||||
*view_info = shdr.get_sh_info();
|
||||
}
|
||||
@ -208,7 +208,7 @@ Sized_dynobj<size, big_endian>::read_dynamic(const unsigned char* pshdrs,
|
||||
|
||||
const off_t dynamic_size = dynamicshdr.get_sh_size();
|
||||
const unsigned char* pdynamic = this->get_view(dynamicshdr.get_sh_offset(),
|
||||
dynamic_size, false);
|
||||
dynamic_size, true, false);
|
||||
|
||||
const unsigned int link = dynamicshdr.get_sh_link();
|
||||
if (link != strtab_shndx)
|
||||
@ -229,7 +229,8 @@ Sized_dynobj<size, big_endian>::read_dynamic(const unsigned char* pshdrs,
|
||||
}
|
||||
|
||||
strtab_size = strtabshdr.get_sh_size();
|
||||
strtabu = this->get_view(strtabshdr.get_sh_offset(), strtab_size, false);
|
||||
strtabu = this->get_view(strtabshdr.get_sh_offset(), strtab_size, false,
|
||||
false);
|
||||
}
|
||||
|
||||
const char* const strtab = reinterpret_cast<const char*>(strtabu);
|
||||
@ -313,7 +314,8 @@ Sized_dynobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
|
||||
gold_assert(dynsymshdr.get_sh_type() == elfcpp::SHT_DYNSYM);
|
||||
|
||||
sd->symbols = this->get_lasting_view(dynsymshdr.get_sh_offset(),
|
||||
dynsymshdr.get_sh_size(), false);
|
||||
dynsymshdr.get_sh_size(), true,
|
||||
false);
|
||||
sd->symbols_size =
|
||||
convert_to_section_size_type(dynsymshdr.get_sh_size());
|
||||
|
||||
@ -336,7 +338,7 @@ Sized_dynobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
|
||||
|
||||
sd->symbol_names = this->get_lasting_view(strtabshdr.get_sh_offset(),
|
||||
strtabshdr.get_sh_size(),
|
||||
false);
|
||||
false, false);
|
||||
sd->symbol_names_size =
|
||||
convert_to_section_size_type(strtabshdr.get_sh_size());
|
||||
|
||||
|
219
gold/fileread.cc
219
gold/fileread.cc
@ -158,7 +158,10 @@ File_read::release()
|
||||
if (File_read::current_mapped_bytes > File_read::maximum_mapped_bytes)
|
||||
File_read::maximum_mapped_bytes = File_read::current_mapped_bytes;
|
||||
|
||||
this->clear_views(false);
|
||||
// Only clear views if there is only one attached object. Otherwise
|
||||
// we waste time trying to clear cached archive views.
|
||||
if (this->object_count_ <= 1)
|
||||
this->clear_views(false);
|
||||
|
||||
this->released_ = true;
|
||||
}
|
||||
@ -196,27 +199,44 @@ File_read::is_locked() const
|
||||
|
||||
// See if we have a view which covers the file starting at START for
|
||||
// SIZE bytes. Return a pointer to the View if found, NULL if not.
|
||||
// If BYTESHIFT is not -1U, the returned View must have the specified
|
||||
// byte shift; otherwise, it may have any byte shift. If VSHIFTED is
|
||||
// not NULL, this sets *VSHIFTED to a view which would have worked if
|
||||
// not for the requested BYTESHIFT.
|
||||
|
||||
inline File_read::View*
|
||||
File_read::find_view(off_t start, section_size_type size) const
|
||||
File_read::find_view(off_t start, section_size_type size,
|
||||
unsigned int byteshift, File_read::View** vshifted) const
|
||||
{
|
||||
if (vshifted != NULL)
|
||||
*vshifted = NULL;
|
||||
|
||||
off_t page = File_read::page_offset(start);
|
||||
|
||||
Views::const_iterator p = this->views_.lower_bound(page);
|
||||
if (p == this->views_.end() || p->first > page)
|
||||
unsigned int bszero = 0;
|
||||
Views::const_iterator p = this->views_.upper_bound(std::make_pair(page - 1,
|
||||
bszero));
|
||||
|
||||
while (p != this->views_.end() && p->first.first <= page)
|
||||
{
|
||||
if (p == this->views_.begin())
|
||||
return NULL;
|
||||
--p;
|
||||
if (p->second->start() <= start
|
||||
&& (p->second->start() + static_cast<off_t>(p->second->size())
|
||||
>= start + static_cast<off_t>(size)))
|
||||
{
|
||||
if (byteshift == -1U || byteshift == p->second->byteshift())
|
||||
{
|
||||
p->second->set_accessed();
|
||||
return p->second;
|
||||
}
|
||||
|
||||
if (vshifted != NULL && *vshifted == NULL)
|
||||
*vshifted = p->second;
|
||||
}
|
||||
|
||||
++p;
|
||||
}
|
||||
|
||||
if (p->second->start() + static_cast<off_t>(p->second->size())
|
||||
< start + static_cast<off_t>(size))
|
||||
return NULL;
|
||||
|
||||
p->second->set_accessed();
|
||||
|
||||
return p->second;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read SIZE bytes from the file starting at offset START. Read into
|
||||
@ -261,54 +281,54 @@ File_read::do_read(off_t start, section_size_type size, void* p) const
|
||||
void
|
||||
File_read::read(off_t start, section_size_type size, void* p) const
|
||||
{
|
||||
const File_read::View* pv = this->find_view(start, size);
|
||||
const File_read::View* pv = this->find_view(start, size, -1U, NULL);
|
||||
if (pv != NULL)
|
||||
{
|
||||
memcpy(p, pv->data() + (start - pv->start()), size);
|
||||
memcpy(p, pv->data() + (start - pv->start() + pv->byteshift()), size);
|
||||
return;
|
||||
}
|
||||
|
||||
this->do_read(start, size, p);
|
||||
}
|
||||
|
||||
// Find an existing view or make a new one.
|
||||
// Add a new view. There may already be an existing view at this
|
||||
// offset. If there is, the new view will be larger, and should
|
||||
// replace the old view.
|
||||
|
||||
void
|
||||
File_read::add_view(File_read::View* v)
|
||||
{
|
||||
std::pair<Views::iterator, bool> ins =
|
||||
this->views_.insert(std::make_pair(std::make_pair(v->start(),
|
||||
v->byteshift()),
|
||||
v));
|
||||
if (ins.second)
|
||||
return;
|
||||
|
||||
// There was an existing view at this offset. It must not be large
|
||||
// enough. We can't delete it here, since something might be using
|
||||
// it; we put it on a list to be deleted when the file is unlocked.
|
||||
File_read::View* vold = ins.first->second;
|
||||
gold_assert(vold->size() < v->size());
|
||||
if (vold->should_cache())
|
||||
{
|
||||
v->set_cache();
|
||||
vold->clear_cache();
|
||||
}
|
||||
this->saved_views_.push_back(vold);
|
||||
|
||||
ins.first->second = v;
|
||||
}
|
||||
|
||||
// Make a new view with a specified byteshift, reading the data from
|
||||
// the file.
|
||||
|
||||
File_read::View*
|
||||
File_read::find_or_make_view(off_t start, section_size_type size, bool cache)
|
||||
File_read::make_view(off_t start, section_size_type size,
|
||||
unsigned int byteshift, bool cache)
|
||||
{
|
||||
gold_assert(!this->token_.is_writable());
|
||||
this->released_ = false;
|
||||
|
||||
File_read::View* v = this->find_view(start, size);
|
||||
if (v != NULL)
|
||||
{
|
||||
if (cache)
|
||||
v->set_cache();
|
||||
return v;
|
||||
}
|
||||
|
||||
off_t poff = File_read::page_offset(start);
|
||||
|
||||
File_read::View* const vnull = NULL;
|
||||
std::pair<Views::iterator, bool> ins =
|
||||
this->views_.insert(std::make_pair(poff, vnull));
|
||||
|
||||
if (!ins.second)
|
||||
{
|
||||
// There was an existing view at this offset. It must not be
|
||||
// large enough. We can't delete it here, since something might
|
||||
// be using it; put it on a list to be deleted when the file is
|
||||
// unlocked.
|
||||
v = ins.first->second;
|
||||
gold_assert(v->size() - (start - v->start()) < size);
|
||||
if (v->should_cache())
|
||||
cache = true;
|
||||
v->clear_cache();
|
||||
this->saved_views_.push_back(v);
|
||||
}
|
||||
|
||||
// We need to map data from the file.
|
||||
|
||||
section_size_type psize = File_read::pages(size + (start - poff));
|
||||
|
||||
if (poff + static_cast<off_t>(psize) >= this->size_)
|
||||
@ -317,11 +337,13 @@ File_read::find_or_make_view(off_t start, section_size_type size, bool cache)
|
||||
gold_assert(psize >= size);
|
||||
}
|
||||
|
||||
if (this->contents_ != NULL)
|
||||
File_read::View* v;
|
||||
if (this->contents_ != NULL || byteshift != 0)
|
||||
{
|
||||
unsigned char* p = new unsigned char[psize];
|
||||
this->do_read(poff, psize, p);
|
||||
v = new File_read::View(poff, psize, p, cache, false);
|
||||
unsigned char* p = new unsigned char[psize + byteshift];
|
||||
memset(p, 0, byteshift);
|
||||
this->do_read(poff, psize, p + byteshift);
|
||||
v = new File_read::View(poff, psize, p, byteshift, cache, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -337,28 +359,97 @@ File_read::find_or_make_view(off_t start, section_size_type size, bool cache)
|
||||
this->mapped_bytes_ += psize;
|
||||
|
||||
const unsigned char* pbytes = static_cast<const unsigned char*>(p);
|
||||
v = new File_read::View(poff, psize, pbytes, cache, true);
|
||||
v = new File_read::View(poff, psize, pbytes, 0, cache, true);
|
||||
}
|
||||
|
||||
ins.first->second = v;
|
||||
this->add_view(v);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
// Find a View or make a new one, shifted as required by the file
|
||||
// offset OFFSET and ALIGNED.
|
||||
|
||||
File_read::View*
|
||||
File_read::find_or_make_view(off_t offset, off_t start,
|
||||
section_size_type size, bool aligned, bool cache)
|
||||
{
|
||||
unsigned int byteshift;
|
||||
if (offset == 0)
|
||||
byteshift = 0;
|
||||
else
|
||||
{
|
||||
unsigned int target_size = (!parameters->target_valid()
|
||||
? 64
|
||||
: parameters->target().get_size());
|
||||
byteshift = offset & ((target_size / 8) - 1);
|
||||
|
||||
// Set BYTESHIFT to the number of dummy bytes which must be
|
||||
// inserted before the data in order for this data to be
|
||||
// aligned.
|
||||
if (byteshift != 0)
|
||||
byteshift = (target_size / 8) - byteshift;
|
||||
}
|
||||
|
||||
// Try to find a View with the required BYTESHIFT.
|
||||
File_read::View* vshifted;
|
||||
File_read::View* v = this->find_view(offset + start, size,
|
||||
aligned ? byteshift : -1U,
|
||||
&vshifted);
|
||||
if (v != NULL)
|
||||
{
|
||||
if (cache)
|
||||
v->set_cache();
|
||||
return v;
|
||||
}
|
||||
|
||||
// If VSHIFTED is not NULL, then it has the data we need, but with
|
||||
// the wrong byteshift.
|
||||
v = vshifted;
|
||||
if (v != NULL)
|
||||
{
|
||||
gold_assert(aligned);
|
||||
|
||||
unsigned char* pbytes = new unsigned char[v->size() + byteshift];
|
||||
memset(pbytes, 0, byteshift);
|
||||
memcpy(pbytes + byteshift, v->data() + v->byteshift(), v->size());
|
||||
|
||||
File_read::View* shifted_view = new File_read::View(v->start(), v->size(),
|
||||
pbytes, byteshift,
|
||||
cache, false);
|
||||
|
||||
this->add_view(shifted_view);
|
||||
return shifted_view;
|
||||
}
|
||||
|
||||
// Make a new view. If we don't need an aligned view, use a
|
||||
// byteshift of 0, so that we can use mmap.
|
||||
return this->make_view(offset + start, size,
|
||||
aligned ? byteshift : 0,
|
||||
cache);
|
||||
}
|
||||
|
||||
// Get a view into the file.
|
||||
|
||||
const unsigned char*
|
||||
File_read::get_view(off_t start, section_size_type size, bool cache)
|
||||
File_read::get_view(off_t offset, off_t start, section_size_type size,
|
||||
bool aligned, bool cache)
|
||||
{
|
||||
File_read::View* pv = this->find_or_make_view(start, size, cache);
|
||||
return pv->data() + (start - pv->start());
|
||||
File_read::View* pv = this->find_or_make_view(offset, start, size,
|
||||
aligned, cache);
|
||||
return pv->data() + (offset + start - pv->start() + pv->byteshift());
|
||||
}
|
||||
|
||||
File_view*
|
||||
File_read::get_lasting_view(off_t start, section_size_type size, bool cache)
|
||||
File_read::get_lasting_view(off_t offset, off_t start, section_size_type size,
|
||||
bool aligned, bool cache)
|
||||
{
|
||||
File_read::View* pv = this->find_or_make_view(start, size, cache);
|
||||
File_read::View* pv = this->find_or_make_view(offset, start, size,
|
||||
aligned, cache);
|
||||
pv->lock();
|
||||
return new File_view(*this, pv, pv->data() + (start - pv->start()));
|
||||
return new File_view(*this, pv,
|
||||
(pv->data()
|
||||
+ (offset + start - pv->start() + pv->byteshift())));
|
||||
}
|
||||
|
||||
// Use readv to read COUNT entries from RM starting at START. BASE
|
||||
@ -450,13 +541,15 @@ File_read::read_multiple(off_t base, const Read_multiple& rm)
|
||||
else
|
||||
{
|
||||
File_read::View* view = this->find_view(base + i_off,
|
||||
end_off - i_off);
|
||||
end_off - i_off,
|
||||
-1U, NULL);
|
||||
if (view == NULL)
|
||||
this->do_readv(base, rm, i, j - i);
|
||||
else
|
||||
{
|
||||
const unsigned char* v = (view->data()
|
||||
+ (base + i_off - view->start()));
|
||||
+ (base + i_off - view->start()
|
||||
+ view->byteshift()));
|
||||
for (size_t k = i; k < j; ++k)
|
||||
{
|
||||
const Read_multiple_entry& k_entry(rm[k]);
|
||||
|
@ -116,14 +116,19 @@ class File_read
|
||||
{ return this->size_; }
|
||||
|
||||
// Return a view into the file starting at file offset START for
|
||||
// SIZE bytes. The pointer will remain valid until the File_read is
|
||||
// unlocked. It is an error if we can not read enough data from the
|
||||
// file. The CACHE parameter is a hint as to whether it will be
|
||||
// SIZE bytes. OFFSET is the offset into the input file for the
|
||||
// file we are reading; this is zero for a normal object file,
|
||||
// non-zero for an object file in an archive. ALIGNED is true if
|
||||
// the data must be naturally aligned; this only matters when OFFSET
|
||||
// is not zero. The pointer will remain valid until the File_read
|
||||
// is unlocked. It is an error if we can not read enough data from
|
||||
// the file. The CACHE parameter is a hint as to whether it will be
|
||||
// useful to cache this data for later accesses--i.e., later calls
|
||||
// to get_view, read, or get_lasting_view which retrieve the same
|
||||
// data.
|
||||
const unsigned char*
|
||||
get_view(off_t start, section_size_type size, bool cache);
|
||||
get_view(off_t offset, off_t start, section_size_type size, bool aligned,
|
||||
bool cache);
|
||||
|
||||
// Read data from the file into the buffer P starting at file offset
|
||||
// START for SIZE bytes.
|
||||
@ -134,15 +139,23 @@ class File_read
|
||||
// for SIZE bytes. This is allocated with new, and the caller is
|
||||
// responsible for deleting it when done. The data associated with
|
||||
// this view will remain valid until the view is deleted. It is an
|
||||
// error if we can not read enough data from the file. The CACHE
|
||||
// parameter is as in get_view.
|
||||
// error if we can not read enough data from the file. The OFFSET,
|
||||
// ALIGNED and CACHE parameters are as in get_view.
|
||||
File_view*
|
||||
get_lasting_view(off_t start, section_size_type size, bool cache);
|
||||
get_lasting_view(off_t offset, off_t start, section_size_type size,
|
||||
bool aligned, bool cache);
|
||||
|
||||
// Mark all views as no longer cached.
|
||||
void
|
||||
clear_view_cache_marks();
|
||||
|
||||
// Discard all uncached views. This is normally done by release(),
|
||||
// but not for objects in archives. FIXME: This is a complicated
|
||||
// interface, and it would be nice to have something more automatic.
|
||||
void
|
||||
clear_uncached_views()
|
||||
{ this->clear_views(false); }
|
||||
|
||||
// A struct used to do a multiple read.
|
||||
struct Read_multiple_entry
|
||||
{
|
||||
@ -193,9 +206,9 @@ class File_read
|
||||
{
|
||||
public:
|
||||
View(off_t start, section_size_type size, const unsigned char* data,
|
||||
bool cache, bool mapped)
|
||||
unsigned int byteshift, bool cache, bool mapped)
|
||||
: start_(start), size_(size), data_(data), lock_count_(0),
|
||||
cache_(cache), mapped_(mapped), accessed_(true)
|
||||
byteshift_(byteshift), cache_(cache), mapped_(mapped), accessed_(true)
|
||||
{ }
|
||||
|
||||
~View();
|
||||
@ -221,6 +234,10 @@ class File_read
|
||||
bool
|
||||
is_locked();
|
||||
|
||||
unsigned int
|
||||
byteshift() const
|
||||
{ return this->byteshift_; }
|
||||
|
||||
void
|
||||
set_cache()
|
||||
{ this->cache_ = true; }
|
||||
@ -249,29 +266,58 @@ class File_read
|
||||
View(const View&);
|
||||
View& operator=(const View&);
|
||||
|
||||
// The file offset of the start of the view.
|
||||
off_t start_;
|
||||
// The size of the view.
|
||||
section_size_type size_;
|
||||
// A pointer to the actual bytes.
|
||||
const unsigned char* data_;
|
||||
// The number of locks on this view.
|
||||
int lock_count_;
|
||||
// The number of bytes that the view is shifted relative to the
|
||||
// underlying file. This is used to align data. This is normally
|
||||
// zero, except possibly for an object in an archive.
|
||||
unsigned int byteshift_;
|
||||
// Whether the view is cached.
|
||||
bool cache_;
|
||||
// Whether the view is mapped into memory. If not, data_ points
|
||||
// to memory allocated using new[].
|
||||
bool mapped_;
|
||||
// Whether the view has been accessed recently.
|
||||
bool accessed_;
|
||||
};
|
||||
|
||||
friend class View;
|
||||
friend class File_view;
|
||||
|
||||
// The type of a mapping from page start and byte shift to views.
|
||||
typedef std::map<std::pair<off_t, unsigned int>, View*> Views;
|
||||
|
||||
// A simple list of Views.
|
||||
typedef std::list<View*> Saved_views;
|
||||
|
||||
// Find a view into the file.
|
||||
View*
|
||||
find_view(off_t start, section_size_type size) const;
|
||||
find_view(off_t start, section_size_type size, unsigned int byteshift,
|
||||
View** vshifted) const;
|
||||
|
||||
// Read data from the file into a buffer.
|
||||
void
|
||||
do_read(off_t start, section_size_type size, void* p) const;
|
||||
|
||||
// Add a view.
|
||||
void
|
||||
add_view(View*);
|
||||
|
||||
// Make a view into the file.
|
||||
View*
|
||||
make_view(off_t start, section_size_type size, unsigned int byteshift,
|
||||
bool cache);
|
||||
|
||||
// Find or make a view into the file.
|
||||
View*
|
||||
find_or_make_view(off_t start, section_size_type size, bool cache);
|
||||
find_or_make_view(off_t offset, off_t start, section_size_type size,
|
||||
bool aligned, bool cache);
|
||||
|
||||
// Clear the file views.
|
||||
void
|
||||
@ -290,12 +336,6 @@ class File_read
|
||||
pages(off_t file_size)
|
||||
{ return (file_size + (page_size - 1)) & ~ (page_size - 1); }
|
||||
|
||||
// The type of a mapping from page start to views.
|
||||
typedef std::map<off_t, View*> Views;
|
||||
|
||||
// A simple list of Views.
|
||||
typedef std::list<View*> Saved_views;
|
||||
|
||||
// The maximum number of entries we will pass to ::readv.
|
||||
static const size_t max_readv_entries = 128;
|
||||
|
||||
|
@ -80,7 +80,7 @@ Object::section_contents(unsigned int shndx, section_size_type* plen,
|
||||
{
|
||||
Location loc(this->do_section_contents(shndx));
|
||||
*plen = convert_to_section_size_type(loc.data_size);
|
||||
return this->get_view(loc.file_offset, *plen, cache);
|
||||
return this->get_view(loc.file_offset, *plen, true, cache);
|
||||
}
|
||||
|
||||
// Read the section data into SD. This is code common to Sized_relobj
|
||||
@ -96,7 +96,8 @@ Object::read_section_data(elfcpp::Elf_file<size, big_endian, Object>* elf_file,
|
||||
// Read the section headers.
|
||||
const off_t shoff = elf_file->shoff();
|
||||
const unsigned int shnum = this->shnum();
|
||||
sd->section_headers = this->get_lasting_view(shoff, shnum * shdr_size, true);
|
||||
sd->section_headers = this->get_lasting_view(shoff, shnum * shdr_size,
|
||||
true, true);
|
||||
|
||||
// Read the section names.
|
||||
const unsigned char* pshdrs = sd->section_headers->data();
|
||||
@ -110,7 +111,8 @@ Object::read_section_data(elfcpp::Elf_file<size, big_endian, Object>* elf_file,
|
||||
sd->section_names_size =
|
||||
convert_to_section_size_type(shdrnames.get_sh_size());
|
||||
sd->section_names = this->get_lasting_view(shdrnames.get_sh_offset(),
|
||||
sd->section_names_size, false);
|
||||
sd->section_names_size, false,
|
||||
false);
|
||||
}
|
||||
|
||||
// If NAME is the name of a special .gnu.warning section, arrange for
|
||||
@ -319,7 +321,7 @@ Sized_relobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
|
||||
off_t readoff = this->has_eh_frame_ ? dataoff : extoff;
|
||||
section_size_type readsize = this->has_eh_frame_ ? datasize : extsize;
|
||||
|
||||
File_view* fvsymtab = this->get_lasting_view(readoff, readsize, false);
|
||||
File_view* fvsymtab = this->get_lasting_view(readoff, readsize, true, false);
|
||||
|
||||
// Read the section header for the symbol names.
|
||||
unsigned int strtab_shndx = symtabshdr.get_sh_link();
|
||||
@ -338,7 +340,8 @@ Sized_relobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
|
||||
|
||||
// Read the symbol names.
|
||||
File_view* fvstrtab = this->get_lasting_view(strtabshdr.get_sh_offset(),
|
||||
strtabshdr.get_sh_size(), true);
|
||||
strtabshdr.get_sh_size(),
|
||||
false, true);
|
||||
|
||||
sd->symbols = fvsymtab;
|
||||
sd->symbols_size = readsize;
|
||||
@ -390,7 +393,7 @@ Sized_relobj<size, big_endian>::include_section_group(
|
||||
{
|
||||
// Read the section contents.
|
||||
const unsigned char* pcon = this->get_view(shdr.get_sh_offset(),
|
||||
shdr.get_sh_size(), false);
|
||||
shdr.get_sh_size(), true, false);
|
||||
const elfcpp::Elf_Word* pword =
|
||||
reinterpret_cast<const elfcpp::Elf_Word*>(pcon);
|
||||
|
||||
@ -417,7 +420,8 @@ Sized_relobj<size, big_endian>::include_section_group(
|
||||
return false;
|
||||
}
|
||||
off_t symoff = symshdr.get_sh_offset() + shdr.get_sh_info() * This::sym_size;
|
||||
const unsigned char* psym = this->get_view(symoff, This::sym_size, false);
|
||||
const unsigned char* psym = this->get_view(symoff, This::sym_size, true,
|
||||
false);
|
||||
elfcpp::Sym<size, big_endian> sym(psym);
|
||||
|
||||
// Read the symbol table names.
|
||||
@ -849,7 +853,7 @@ Sized_relobj<size, big_endian>::do_count_local_symbols(Stringpool* pool,
|
||||
gold_assert(loccount == symtabshdr.get_sh_info());
|
||||
off_t locsize = loccount * sym_size;
|
||||
const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(),
|
||||
locsize, true);
|
||||
locsize, true, true);
|
||||
|
||||
// Read the symbol names.
|
||||
const unsigned int strtab_shndx = symtabshdr.get_sh_link();
|
||||
@ -1084,7 +1088,7 @@ Sized_relobj<size, big_endian>::write_local_symbols(
|
||||
const int sym_size = This::sym_size;
|
||||
off_t locsize = loccount * sym_size;
|
||||
const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(),
|
||||
locsize, false);
|
||||
locsize, true, false);
|
||||
|
||||
// Read the symbol names.
|
||||
const unsigned int strtab_shndx = symtabshdr.get_sh_link();
|
||||
|
@ -295,7 +295,7 @@ class Object
|
||||
// Return a View.
|
||||
View
|
||||
view(off_t file_offset, section_size_type data_size)
|
||||
{ return View(this->get_view(file_offset, data_size, true)); }
|
||||
{ return View(this->get_view(file_offset, data_size, true, true)); }
|
||||
|
||||
// Report an error.
|
||||
void
|
||||
@ -314,22 +314,23 @@ class Object
|
||||
|
||||
// Get a View given a Location.
|
||||
View view(Location loc)
|
||||
{ return View(this->get_view(loc.file_offset, loc.data_size, true)); }
|
||||
{ return View(this->get_view(loc.file_offset, loc.data_size, true, true)); }
|
||||
|
||||
// Get a view into the underlying file.
|
||||
const unsigned char*
|
||||
get_view(off_t start, section_size_type size, bool cache)
|
||||
get_view(off_t start, section_size_type size, bool aligned, bool cache)
|
||||
{
|
||||
return this->input_file()->file().get_view(start + this->offset_, size,
|
||||
cache);
|
||||
return this->input_file()->file().get_view(this->offset_, start, size,
|
||||
aligned, cache);
|
||||
}
|
||||
|
||||
// Get a lasting view into the underlying file.
|
||||
File_view*
|
||||
get_lasting_view(off_t start, section_size_type size, bool cache)
|
||||
get_lasting_view(off_t start, section_size_type size, bool aligned,
|
||||
bool cache)
|
||||
{
|
||||
return this->input_file()->file().get_lasting_view(start + this->offset_,
|
||||
size, cache);
|
||||
return this->input_file()->file().get_lasting_view(this->offset_, start,
|
||||
size, aligned, cache);
|
||||
}
|
||||
|
||||
// Read data from the underlying file.
|
||||
|
@ -197,7 +197,7 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
|
||||
|
||||
const unsigned char *pshdrs = this->get_view(this->elf_file_.shoff(),
|
||||
shnum * This::shdr_size,
|
||||
true);
|
||||
true, true);
|
||||
// Skip the first, dummy, section.
|
||||
const unsigned char *ps = pshdrs + This::shdr_size;
|
||||
for (unsigned int i = 1; i < shnum; ++i, ps += This::shdr_size)
|
||||
@ -269,7 +269,7 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
|
||||
sr.reloc_shndx = i;
|
||||
sr.data_shndx = shndx;
|
||||
sr.contents = this->get_lasting_view(shdr.get_sh_offset(), sh_size,
|
||||
true);
|
||||
true, true);
|
||||
sr.sh_type = sh_type;
|
||||
sr.reloc_count = reloc_count;
|
||||
sr.output_section = os;
|
||||
@ -291,7 +291,7 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
|
||||
gold_assert(loccount == symtabshdr.get_sh_info());
|
||||
off_t locsize = loccount * sym_size;
|
||||
rd->local_symbols = this->get_lasting_view(symtabshdr.get_sh_offset(),
|
||||
locsize, true);
|
||||
locsize, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -465,7 +465,7 @@ Sized_relobj<size, big_endian>::do_relocate(const General_options& options,
|
||||
// Read the section headers.
|
||||
const unsigned char* pshdrs = this->get_view(this->elf_file_.shoff(),
|
||||
shnum * This::shdr_size,
|
||||
true);
|
||||
true, true);
|
||||
|
||||
Views views;
|
||||
views.resize(shnum);
|
||||
@ -745,7 +745,7 @@ Sized_relobj<size, big_endian>::relocate_sections(
|
||||
|
||||
off_t sh_size = shdr.get_sh_size();
|
||||
const unsigned char* prelocs = this->get_view(shdr.get_sh_offset(),
|
||||
sh_size, false);
|
||||
sh_size, true, false);
|
||||
|
||||
unsigned int reloc_size;
|
||||
if (sh_type == elfcpp::SHT_REL)
|
||||
|
Loading…
x
Reference in New Issue
Block a user