Add cache parameter to get_view. Discard uncached views on unlock.
Fix bug this exposed in archive armap symbol name handling.
This commit is contained in:
parent
0b058123a0
commit
9eb9fa57c2
10 changed files with 141 additions and 113 deletions
|
@ -101,7 +101,7 @@ Archive::setup()
|
||||||
if (xname == "/")
|
if (xname == "/")
|
||||||
{
|
{
|
||||||
const unsigned char* p = this->get_view(off + sizeof(Archive_header),
|
const unsigned char* p = this->get_view(off + sizeof(Archive_header),
|
||||||
extended_size);
|
extended_size, false);
|
||||||
const char* px = reinterpret_cast<const char*>(p);
|
const char* px = reinterpret_cast<const char*>(p);
|
||||||
this->extended_names_.assign(px, extended_size);
|
this->extended_names_.assign(px, extended_size);
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ void
|
||||||
Archive::read_armap(off_t start, off_t size)
|
Archive::read_armap(off_t start, off_t size)
|
||||||
{
|
{
|
||||||
// Read in the entire armap.
|
// Read in the entire armap.
|
||||||
const unsigned char* p = this->get_view(start, size);
|
const unsigned char* p = this->get_view(start, size, false);
|
||||||
|
|
||||||
// Numbers in the armap are always big-endian.
|
// Numbers in the armap are always big-endian.
|
||||||
const elfcpp::Elf_Word* pword = reinterpret_cast<const elfcpp::Elf_Word*>(p);
|
const elfcpp::Elf_Word* pword = reinterpret_cast<const elfcpp::Elf_Word*>(p);
|
||||||
|
@ -125,14 +125,17 @@ Archive::read_armap(off_t start, off_t size)
|
||||||
|
|
||||||
// Note that the addition is in units of sizeof(elfcpp::Elf_Word).
|
// Note that the addition is in units of sizeof(elfcpp::Elf_Word).
|
||||||
const char* pnames = reinterpret_cast<const char*>(pword + nsyms);
|
const char* pnames = reinterpret_cast<const char*>(pword + nsyms);
|
||||||
|
off_t names_size = reinterpret_cast<const char*>(p) + size - pnames;
|
||||||
|
this->armap_names_.assign(pnames, names_size);
|
||||||
|
|
||||||
this->armap_.resize(nsyms);
|
this->armap_.resize(nsyms);
|
||||||
|
|
||||||
|
off_t name_offset = 0;
|
||||||
for (unsigned int i = 0; i < nsyms; ++i)
|
for (unsigned int i = 0; i < nsyms; ++i)
|
||||||
{
|
{
|
||||||
this->armap_[i].name = pnames;
|
this->armap_[i].name_offset = name_offset;
|
||||||
this->armap_[i].offset = elfcpp::Swap<32, true>::readval(pword);
|
this->armap_[i].file_offset = elfcpp::Swap<32, true>::readval(pword);
|
||||||
pnames += strlen(pnames) + 1;
|
name_offset += strlen(pnames + name_offset) + 1;
|
||||||
++pword;
|
++pword;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +158,7 @@ Archive::read_armap(off_t start, off_t size)
|
||||||
off_t
|
off_t
|
||||||
Archive::read_header(off_t off, std::string* pname)
|
Archive::read_header(off_t off, std::string* pname)
|
||||||
{
|
{
|
||||||
const unsigned char* p = this->get_view(off, sizeof(Archive_header));
|
const unsigned char* p = this->get_view(off, sizeof(Archive_header), false);
|
||||||
const Archive_header* hdr = reinterpret_cast<const Archive_header*>(p);
|
const Archive_header* hdr = reinterpret_cast<const Archive_header*>(p);
|
||||||
return this->interpret_header(hdr, off, pname);
|
return this->interpret_header(hdr, off, pname);
|
||||||
}
|
}
|
||||||
|
@ -283,20 +286,22 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout,
|
||||||
{
|
{
|
||||||
if (this->armap_checked_[i])
|
if (this->armap_checked_[i])
|
||||||
continue;
|
continue;
|
||||||
if (this->armap_[i].offset == last_seen_offset)
|
if (this->armap_[i].file_offset == last_seen_offset)
|
||||||
{
|
{
|
||||||
this->armap_checked_[i] = true;
|
this->armap_checked_[i] = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (this->seen_offsets_.find(this->armap_[i].offset)
|
if (this->seen_offsets_.find(this->armap_[i].file_offset)
|
||||||
!= this->seen_offsets_.end())
|
!= this->seen_offsets_.end())
|
||||||
{
|
{
|
||||||
this->armap_checked_[i] = true;
|
this->armap_checked_[i] = true;
|
||||||
last_seen_offset = this->armap_[i].offset;
|
last_seen_offset = this->armap_[i].file_offset;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol* sym = symtab->lookup(this->armap_[i].name);
|
const char* sym_name = (this->armap_names_.data()
|
||||||
|
+ this->armap_[i].name_offset);
|
||||||
|
Symbol* sym = symtab->lookup(sym_name);
|
||||||
if (sym == NULL)
|
if (sym == NULL)
|
||||||
continue;
|
continue;
|
||||||
else if (!sym->is_undefined())
|
else if (!sym->is_undefined())
|
||||||
|
@ -308,7 +313,7 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// We want to include this object in the link.
|
// We want to include this object in the link.
|
||||||
last_seen_offset = this->armap_[i].offset;
|
last_seen_offset = this->armap_[i].file_offset;
|
||||||
this->seen_offsets_.insert(last_seen_offset);
|
this->seen_offsets_.insert(last_seen_offset);
|
||||||
this->armap_checked_[i] = true;
|
this->armap_checked_[i] = true;
|
||||||
this->include_member(symtab, layout, input_objects,
|
this->include_member(symtab, layout, input_objects,
|
||||||
|
|
|
@ -44,7 +44,8 @@ class Archive
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Archive(const std::string& name, Input_file* input_file)
|
Archive(const std::string& name, Input_file* input_file)
|
||||||
: name_(name), input_file_(input_file), armap_(), extended_names_()
|
: name_(name), input_file_(input_file), armap_(), armap_names_(),
|
||||||
|
extended_names_(), armap_checked_(), seen_offsets_()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
// The length of the magic string at the start of an archive.
|
// The length of the magic string at the start of an archive.
|
||||||
|
@ -98,8 +99,8 @@ class Archive
|
||||||
|
|
||||||
// Get a view into the underlying file.
|
// Get a view into the underlying file.
|
||||||
const unsigned char*
|
const unsigned char*
|
||||||
get_view(off_t start, off_t size)
|
get_view(off_t start, off_t size, bool cache)
|
||||||
{ return this->input_file_->file().get_view(start, size); }
|
{ return this->input_file_->file().get_view(start, size, cache); }
|
||||||
|
|
||||||
// Read the archive symbol map.
|
// Read the archive symbol map.
|
||||||
void
|
void
|
||||||
|
@ -126,10 +127,10 @@ class Archive
|
||||||
// An entry in the archive map of symbols to object files.
|
// An entry in the archive map of symbols to object files.
|
||||||
struct Armap_entry
|
struct Armap_entry
|
||||||
{
|
{
|
||||||
// The symbol name.
|
// The offset to the symbol name in armap_names_.
|
||||||
const char* name;
|
off_t name_offset;
|
||||||
// The offset to the file.
|
// The file offset to the object in the archive.
|
||||||
off_t offset;
|
off_t file_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A simple hash code for off_t values.
|
// A simple hash code for off_t values.
|
||||||
|
@ -146,6 +147,8 @@ class Archive
|
||||||
Input_file* input_file_;
|
Input_file* input_file_;
|
||||||
// The archive map.
|
// The archive map.
|
||||||
std::vector<Armap_entry> armap_;
|
std::vector<Armap_entry> armap_;
|
||||||
|
// The names in the archive map.
|
||||||
|
std::string armap_names_;
|
||||||
// The extended name table.
|
// The extended name table.
|
||||||
std::string extended_names_;
|
std::string extended_names_;
|
||||||
// Track which symbols in the archive map are for elements which are
|
// Track which symbols in the archive map are for elements which are
|
||||||
|
|
|
@ -174,7 +174,8 @@ Sized_dynobj<size, big_endian>::read_dynsym_section(
|
||||||
gold_exit(false);
|
gold_exit(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
*view = this->get_lasting_view(shdr.get_sh_offset(), shdr.get_sh_size());
|
*view = this->get_lasting_view(shdr.get_sh_offset(), shdr.get_sh_size(),
|
||||||
|
false);
|
||||||
*view_size = shdr.get_sh_size();
|
*view_size = shdr.get_sh_size();
|
||||||
*view_info = shdr.get_sh_info();
|
*view_info = shdr.get_sh_info();
|
||||||
}
|
}
|
||||||
|
@ -198,7 +199,7 @@ Sized_dynobj<size, big_endian>::set_soname(const unsigned char* pshdrs,
|
||||||
|
|
||||||
const off_t dynamic_size = dynamicshdr.get_sh_size();
|
const off_t dynamic_size = dynamicshdr.get_sh_size();
|
||||||
const unsigned char* pdynamic = this->get_view(dynamicshdr.get_sh_offset(),
|
const unsigned char* pdynamic = this->get_view(dynamicshdr.get_sh_offset(),
|
||||||
dynamic_size);
|
dynamic_size, false);
|
||||||
|
|
||||||
const unsigned int link = dynamicshdr.get_sh_link();
|
const unsigned int link = dynamicshdr.get_sh_link();
|
||||||
if (link != strtab_shndx)
|
if (link != strtab_shndx)
|
||||||
|
@ -223,7 +224,7 @@ Sized_dynobj<size, big_endian>::set_soname(const unsigned char* pshdrs,
|
||||||
}
|
}
|
||||||
|
|
||||||
strtab_size = strtabshdr.get_sh_size();
|
strtab_size = strtabshdr.get_sh_size();
|
||||||
strtabu = this->get_view(strtabshdr.get_sh_offset(), strtab_size);
|
strtabu = this->get_view(strtabshdr.get_sh_offset(), strtab_size, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const unsigned char* p = pdynamic;
|
for (const unsigned char* p = pdynamic;
|
||||||
|
@ -295,7 +296,7 @@ Sized_dynobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
|
||||||
gold_assert(dynsymshdr.get_sh_type() == elfcpp::SHT_DYNSYM);
|
gold_assert(dynsymshdr.get_sh_type() == elfcpp::SHT_DYNSYM);
|
||||||
|
|
||||||
sd->symbols = this->get_lasting_view(dynsymshdr.get_sh_offset(),
|
sd->symbols = this->get_lasting_view(dynsymshdr.get_sh_offset(),
|
||||||
dynsymshdr.get_sh_size());
|
dynsymshdr.get_sh_size(), false);
|
||||||
sd->symbols_size = dynsymshdr.get_sh_size();
|
sd->symbols_size = dynsymshdr.get_sh_size();
|
||||||
|
|
||||||
// Get the symbol names.
|
// Get the symbol names.
|
||||||
|
@ -319,7 +320,8 @@ Sized_dynobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
|
||||||
}
|
}
|
||||||
|
|
||||||
sd->symbol_names = this->get_lasting_view(strtabshdr.get_sh_offset(),
|
sd->symbol_names = this->get_lasting_view(strtabshdr.get_sh_offset(),
|
||||||
strtabshdr.get_sh_size());
|
strtabshdr.get_sh_size(),
|
||||||
|
true);
|
||||||
sd->symbol_names_size = strtabshdr.get_sh_size();
|
sd->symbol_names_size = strtabshdr.get_sh_size();
|
||||||
|
|
||||||
// Get the version information.
|
// Get the version information.
|
||||||
|
|
|
@ -136,6 +136,8 @@ File_read::unlock()
|
||||||
{
|
{
|
||||||
gold_assert(this->lock_count_ > 0);
|
gold_assert(this->lock_count_ > 0);
|
||||||
--this->lock_count_;
|
--this->lock_count_;
|
||||||
|
if (this->lock_count_ == 0)
|
||||||
|
this->clear_views(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -160,54 +162,44 @@ File_read::find_view(off_t start, off_t size)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read SIZE bytes from the file starting at offset START. Read into
|
// Read SIZE bytes from the file starting at offset START. Read into
|
||||||
// the buffer at P. Return the number of bytes read, which should
|
// the buffer at P.
|
||||||
// always be at least SIZE except at the end of the file.
|
|
||||||
|
|
||||||
off_t
|
void
|
||||||
File_read::do_read(off_t start, off_t size, void* p)
|
File_read::do_read(off_t start, off_t size, void* p)
|
||||||
{
|
{
|
||||||
gold_assert(this->lock_count_ > 0);
|
gold_assert(this->lock_count_ > 0);
|
||||||
|
|
||||||
|
off_t bytes;
|
||||||
if (this->contents_ != NULL)
|
if (this->contents_ != NULL)
|
||||||
{
|
{
|
||||||
off_t bytes = this->size_ - start;
|
bytes = this->size_ - start;
|
||||||
|
if (bytes >= size)
|
||||||
|
{
|
||||||
|
memcpy(p, this->contents_ + start, size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bytes = ::pread(this->descriptor_, p, size, start);
|
||||||
|
if (bytes == size)
|
||||||
|
return;
|
||||||
|
|
||||||
if (bytes < 0)
|
if (bytes < 0)
|
||||||
bytes = 0;
|
{
|
||||||
else if (bytes > size)
|
fprintf(stderr, _("%s: %s: pread failed: %s\n"),
|
||||||
bytes = size;
|
program_name, this->filename().c_str(), strerror(errno));
|
||||||
memcpy(p, this->contents_ + start, bytes);
|
gold_exit(false);
|
||||||
return bytes;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t bytes = ::pread(this->descriptor_, p, size, start);
|
fprintf(stderr,
|
||||||
if (bytes < 0)
|
_("%s: %s: file too short: read only %lld of %lld bytes at %lld\n"),
|
||||||
{
|
program_name, this->filename().c_str(),
|
||||||
fprintf(stderr, _("%s: %s: pread failed: %s\n"),
|
static_cast<long long>(bytes),
|
||||||
program_name, this->filename().c_str(), strerror(errno));
|
static_cast<long long>(size),
|
||||||
gold_exit(false);
|
static_cast<long long>(start));
|
||||||
}
|
gold_exit(false);
|
||||||
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read exactly SIZE bytes from the file starting at offset START.
|
|
||||||
// Read into the buffer at P.
|
|
||||||
|
|
||||||
void
|
|
||||||
File_read::do_read_exact(off_t start, off_t size, void* p)
|
|
||||||
{
|
|
||||||
off_t bytes = this->do_read(start, size, p);
|
|
||||||
if (bytes != size)
|
|
||||||
{
|
|
||||||
fprintf(stderr,
|
|
||||||
_("%s: %s: file too short: read only %lld of %lld "
|
|
||||||
"bytes at %lld\n"),
|
|
||||||
program_name, this->filename().c_str(),
|
|
||||||
static_cast<long long>(bytes),
|
|
||||||
static_cast<long long>(size),
|
|
||||||
static_cast<long long>(start));
|
|
||||||
gold_exit(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read data from the file.
|
// Read data from the file.
|
||||||
|
@ -224,13 +216,13 @@ File_read::read(off_t start, off_t size, void* p)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->do_read_exact(start, size, p);
|
this->do_read(start, size, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find an existing view or make a new one.
|
// Find an existing view or make a new one.
|
||||||
|
|
||||||
File_read::View*
|
File_read::View*
|
||||||
File_read::find_or_make_view(off_t start, off_t size)
|
File_read::find_or_make_view(off_t start, off_t size, bool cache)
|
||||||
{
|
{
|
||||||
gold_assert(this->lock_count_ > 0);
|
gold_assert(this->lock_count_ > 0);
|
||||||
|
|
||||||
|
@ -245,7 +237,11 @@ File_read::find_or_make_view(off_t start, off_t size)
|
||||||
// There was an existing view at this offset.
|
// There was an existing view at this offset.
|
||||||
File_read::View* v = ins.first->second;
|
File_read::View* v = ins.first->second;
|
||||||
if (v->size() - (start - v->start()) >= size)
|
if (v->size() - (start - v->start()) >= size)
|
||||||
return v;
|
{
|
||||||
|
if (cache)
|
||||||
|
v->set_cache();
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
// This view is not large enough.
|
// This view is not large enough.
|
||||||
this->saved_views_.push_back(v);
|
this->saved_views_.push_back(v);
|
||||||
|
@ -264,9 +260,9 @@ File_read::find_or_make_view(off_t start, off_t size)
|
||||||
|
|
||||||
unsigned char* p = new unsigned char[psize];
|
unsigned char* p = new unsigned char[psize];
|
||||||
|
|
||||||
this->do_read_exact(poff, psize, p);
|
this->do_read(poff, psize, p);
|
||||||
|
|
||||||
File_read::View* v = new File_read::View(poff, psize, p);
|
File_read::View* v = new File_read::View(poff, psize, p, cache);
|
||||||
ins.first->second = v;
|
ins.first->second = v;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
@ -276,18 +272,18 @@ File_read::find_or_make_view(off_t start, off_t size)
|
||||||
// mmap.
|
// mmap.
|
||||||
|
|
||||||
const unsigned char*
|
const unsigned char*
|
||||||
File_read::get_view(off_t start, off_t size)
|
File_read::get_view(off_t start, off_t size, bool cache)
|
||||||
{
|
{
|
||||||
gold_assert(this->lock_count_ > 0);
|
gold_assert(this->lock_count_ > 0);
|
||||||
File_read::View* pv = this->find_or_make_view(start, size);
|
File_read::View* pv = this->find_or_make_view(start, size, cache);
|
||||||
return pv->data() + (start - pv->start());
|
return pv->data() + (start - pv->start());
|
||||||
}
|
}
|
||||||
|
|
||||||
File_view*
|
File_view*
|
||||||
File_read::get_lasting_view(off_t start, off_t size)
|
File_read::get_lasting_view(off_t start, off_t size, bool cache)
|
||||||
{
|
{
|
||||||
gold_assert(this->lock_count_ > 0);
|
gold_assert(this->lock_count_ > 0);
|
||||||
File_read::View* pv = this->find_or_make_view(start, size);
|
File_read::View* pv = this->find_or_make_view(start, size, cache);
|
||||||
pv->lock();
|
pv->lock();
|
||||||
return new File_view(*this, pv, pv->data() + (start - pv->start()));
|
return new File_view(*this, pv, pv->data() + (start - pv->start()));
|
||||||
}
|
}
|
||||||
|
@ -301,7 +297,8 @@ File_read::clear_views(bool destroying)
|
||||||
p != this->views_.end();
|
p != this->views_.end();
|
||||||
++p)
|
++p)
|
||||||
{
|
{
|
||||||
if (!p->second->is_locked())
|
if (!p->second->is_locked()
|
||||||
|
&& (destroying || !p->second->should_cache()))
|
||||||
delete p->second;
|
delete p->second;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -314,7 +311,8 @@ File_read::clear_views(bool destroying)
|
||||||
Saved_views::iterator p = this->saved_views_.begin();
|
Saved_views::iterator p = this->saved_views_.begin();
|
||||||
while (p != this->saved_views_.end())
|
while (p != this->saved_views_.end())
|
||||||
{
|
{
|
||||||
if (!(*p)->is_locked())
|
if (!(*p)->is_locked()
|
||||||
|
&& (destroying || !(*p)->should_cache()))
|
||||||
{
|
{
|
||||||
delete *p;
|
delete *p;
|
||||||
p = this->saved_views_.erase(p);
|
p = this->saved_views_.erase(p);
|
||||||
|
|
|
@ -88,9 +88,12 @@ class File_read
|
||||||
// Return a view into the file starting at file offset START for
|
// Return a view into the file starting at file offset START for
|
||||||
// SIZE bytes. The pointer will remain valid until the File_read is
|
// 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
|
// unlocked. It is an error if we can not read enough data from the
|
||||||
// file.
|
// 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*
|
const unsigned char*
|
||||||
get_view(off_t start, off_t size);
|
get_view(off_t start, off_t size, bool cache);
|
||||||
|
|
||||||
// Read data from the file into the buffer P starting at file offset
|
// Read data from the file into the buffer P starting at file offset
|
||||||
// START for SIZE bytes.
|
// START for SIZE bytes.
|
||||||
|
@ -101,9 +104,10 @@ class File_read
|
||||||
// for SIZE bytes. This is allocated with new, and the caller is
|
// for SIZE bytes. This is allocated with new, and the caller is
|
||||||
// responsible for deleting it when done. The data associated with
|
// responsible for deleting it when done. The data associated with
|
||||||
// this view will remain valid until the view is deleted. It is an
|
// this view will remain valid until the view is deleted. It is an
|
||||||
// error if we can not read enough data from the file.
|
// error if we can not read enough data from the file. The CACHE
|
||||||
|
// parameter is as in get_view.
|
||||||
File_view*
|
File_view*
|
||||||
get_lasting_view(off_t start, off_t size);
|
get_lasting_view(off_t start, off_t size, bool cache);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// This class may not be copied.
|
// This class may not be copied.
|
||||||
|
@ -114,8 +118,9 @@ class File_read
|
||||||
class View
|
class View
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
View(off_t start, off_t size, const unsigned char* data)
|
View(off_t start, off_t size, const unsigned char* data, bool cache)
|
||||||
: start_(start), size_(size), data_(data), lock_count_(0)
|
: start_(start), size_(size), data_(data), lock_count_(0),
|
||||||
|
cache_(cache)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
~View();
|
~View();
|
||||||
|
@ -141,6 +146,14 @@ class File_read
|
||||||
bool
|
bool
|
||||||
is_locked();
|
is_locked();
|
||||||
|
|
||||||
|
void
|
||||||
|
set_cache()
|
||||||
|
{ this->cache_ = true; }
|
||||||
|
|
||||||
|
bool
|
||||||
|
should_cache() const
|
||||||
|
{ return this->cache_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
View(const View&);
|
View(const View&);
|
||||||
View& operator=(const View&);
|
View& operator=(const View&);
|
||||||
|
@ -149,6 +162,7 @@ class File_read
|
||||||
off_t size_;
|
off_t size_;
|
||||||
const unsigned char* data_;
|
const unsigned char* data_;
|
||||||
int lock_count_;
|
int lock_count_;
|
||||||
|
bool cache_;
|
||||||
};
|
};
|
||||||
|
|
||||||
friend class File_view;
|
friend class File_view;
|
||||||
|
@ -158,16 +172,12 @@ class File_read
|
||||||
find_view(off_t start, off_t size);
|
find_view(off_t start, off_t size);
|
||||||
|
|
||||||
// Read data from the file into a buffer.
|
// Read data from the file into a buffer.
|
||||||
off_t
|
|
||||||
do_read(off_t start, off_t size, void* p);
|
|
||||||
|
|
||||||
// Read an exact number of bytes into a buffer.
|
|
||||||
void
|
void
|
||||||
do_read_exact(off_t start, off_t size, void* p);
|
do_read(off_t start, off_t size, void* p);
|
||||||
|
|
||||||
// Find or make a view into the file.
|
// Find or make a view into the file.
|
||||||
View*
|
View*
|
||||||
find_or_make_view(off_t start, off_t size);
|
find_or_make_view(off_t start, off_t size, bool cache);
|
||||||
|
|
||||||
// Clear the file views.
|
// Clear the file views.
|
||||||
void
|
void
|
||||||
|
|
|
@ -177,7 +177,7 @@ bool
|
||||||
Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
|
Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
|
||||||
{
|
{
|
||||||
off_t len;
|
off_t len;
|
||||||
const unsigned char* p = object->section_contents(shndx, &len);
|
const unsigned char* p = object->section_contents(shndx, &len, false);
|
||||||
|
|
||||||
uint64_t entsize = this->entsize();
|
uint64_t entsize = this->entsize();
|
||||||
|
|
||||||
|
@ -237,7 +237,7 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
|
||||||
unsigned int shndx)
|
unsigned int shndx)
|
||||||
{
|
{
|
||||||
off_t len;
|
off_t len;
|
||||||
const unsigned char* pdata = object->section_contents(shndx, &len);
|
const unsigned char* pdata = object->section_contents(shndx, &len, false);
|
||||||
|
|
||||||
const Char_type* p = reinterpret_cast<const Char_type*>(pdata);
|
const Char_type* p = reinterpret_cast<const Char_type*>(pdata);
|
||||||
|
|
||||||
|
|
|
@ -73,11 +73,11 @@ Object::error(const char* format, ...)
|
||||||
// Return a view of the contents of a section.
|
// Return a view of the contents of a section.
|
||||||
|
|
||||||
const unsigned char*
|
const unsigned char*
|
||||||
Object::section_contents(unsigned int shndx, off_t* plen)
|
Object::section_contents(unsigned int shndx, off_t* plen, bool cache)
|
||||||
{
|
{
|
||||||
Location loc(this->do_section_contents(shndx));
|
Location loc(this->do_section_contents(shndx));
|
||||||
*plen = loc.data_size;
|
*plen = loc.data_size;
|
||||||
return this->get_view(loc.file_offset, loc.data_size);
|
return this->get_view(loc.file_offset, loc.data_size, cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the section data into SD. This is code common to Sized_relobj
|
// Read the section data into SD. This is code common to Sized_relobj
|
||||||
|
@ -93,7 +93,7 @@ Object::read_section_data(elfcpp::Elf_file<size, big_endian, Object>* elf_file,
|
||||||
// Read the section headers.
|
// Read the section headers.
|
||||||
const off_t shoff = elf_file->shoff();
|
const off_t shoff = elf_file->shoff();
|
||||||
const unsigned int shnum = this->shnum();
|
const unsigned int shnum = this->shnum();
|
||||||
sd->section_headers = this->get_lasting_view(shoff, shnum * shdr_size);
|
sd->section_headers = this->get_lasting_view(shoff, shnum * shdr_size, true);
|
||||||
|
|
||||||
// Read the section names.
|
// Read the section names.
|
||||||
const unsigned char* pshdrs = sd->section_headers->data();
|
const unsigned char* pshdrs = sd->section_headers->data();
|
||||||
|
@ -111,7 +111,7 @@ Object::read_section_data(elfcpp::Elf_file<size, big_endian, Object>* elf_file,
|
||||||
|
|
||||||
sd->section_names_size = shdrnames.get_sh_size();
|
sd->section_names_size = shdrnames.get_sh_size();
|
||||||
sd->section_names = this->get_lasting_view(shdrnames.get_sh_offset(),
|
sd->section_names = this->get_lasting_view(shdrnames.get_sh_offset(),
|
||||||
sd->section_names_size);
|
sd->section_names_size, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If NAME is the name of a special .gnu.warning section, arrange for
|
// If NAME is the name of a special .gnu.warning section, arrange for
|
||||||
|
@ -239,7 +239,7 @@ Sized_relobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
|
||||||
off_t extsize = symtabshdr.get_sh_size() - locsize;
|
off_t extsize = symtabshdr.get_sh_size() - locsize;
|
||||||
|
|
||||||
// Read the symbol table.
|
// Read the symbol table.
|
||||||
File_view* fvsymtab = this->get_lasting_view(extoff, extsize);
|
File_view* fvsymtab = this->get_lasting_view(extoff, extsize, false);
|
||||||
|
|
||||||
// Read the section header for the symbol names.
|
// Read the section header for the symbol names.
|
||||||
unsigned int strtab_shndx = symtabshdr.get_sh_link();
|
unsigned int strtab_shndx = symtabshdr.get_sh_link();
|
||||||
|
@ -261,7 +261,7 @@ Sized_relobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
|
||||||
|
|
||||||
// Read the symbol names.
|
// Read the symbol names.
|
||||||
File_view* fvstrtab = this->get_lasting_view(strtabshdr.get_sh_offset(),
|
File_view* fvstrtab = this->get_lasting_view(strtabshdr.get_sh_offset(),
|
||||||
strtabshdr.get_sh_size());
|
strtabshdr.get_sh_size(), true);
|
||||||
|
|
||||||
sd->symbols = fvsymtab;
|
sd->symbols = fvsymtab;
|
||||||
sd->symbols_size = extsize;
|
sd->symbols_size = extsize;
|
||||||
|
@ -285,7 +285,7 @@ Sized_relobj<size, big_endian>::include_section_group(
|
||||||
{
|
{
|
||||||
// Read the section contents.
|
// Read the section contents.
|
||||||
const unsigned char* pcon = this->get_view(shdr.get_sh_offset(),
|
const unsigned char* pcon = this->get_view(shdr.get_sh_offset(),
|
||||||
shdr.get_sh_size());
|
shdr.get_sh_size(), false);
|
||||||
const elfcpp::Elf_Word* pword =
|
const elfcpp::Elf_Word* pword =
|
||||||
reinterpret_cast<const elfcpp::Elf_Word*>(pcon);
|
reinterpret_cast<const elfcpp::Elf_Word*>(pcon);
|
||||||
|
|
||||||
|
@ -314,13 +314,14 @@ Sized_relobj<size, big_endian>::include_section_group(
|
||||||
gold_exit(false);
|
gold_exit(false);
|
||||||
}
|
}
|
||||||
off_t symoff = symshdr.get_sh_offset() + shdr.get_sh_info() * This::sym_size;
|
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);
|
const unsigned char* psym = this->get_view(symoff, This::sym_size, true);
|
||||||
elfcpp::Sym<size, big_endian> sym(psym);
|
elfcpp::Sym<size, big_endian> sym(psym);
|
||||||
|
|
||||||
// Read the symbol table names.
|
// Read the symbol table names.
|
||||||
off_t symnamelen;
|
off_t symnamelen;
|
||||||
const unsigned char* psymnamesu;
|
const unsigned char* psymnamesu;
|
||||||
psymnamesu = this->section_contents(symshdr.get_sh_link(), &symnamelen);
|
psymnamesu = this->section_contents(symshdr.get_sh_link(), &symnamelen,
|
||||||
|
true);
|
||||||
const char* psymnames = reinterpret_cast<const char*>(psymnamesu);
|
const char* psymnames = reinterpret_cast<const char*>(psymnamesu);
|
||||||
|
|
||||||
// Get the section group signature.
|
// Get the section group signature.
|
||||||
|
@ -557,7 +558,7 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index,
|
||||||
gold_assert(loccount == symtabshdr.get_sh_info());
|
gold_assert(loccount == symtabshdr.get_sh_info());
|
||||||
off_t locsize = loccount * sym_size;
|
off_t locsize = loccount * sym_size;
|
||||||
const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(),
|
const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(),
|
||||||
locsize);
|
locsize, true);
|
||||||
|
|
||||||
this->local_values_.resize(loccount);
|
this->local_values_.resize(loccount);
|
||||||
|
|
||||||
|
@ -565,7 +566,8 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index,
|
||||||
const unsigned int strtab_shndx = symtabshdr.get_sh_link();
|
const unsigned int strtab_shndx = symtabshdr.get_sh_link();
|
||||||
off_t strtab_size;
|
off_t strtab_size;
|
||||||
const unsigned char* pnamesu = this->section_contents(strtab_shndx,
|
const unsigned char* pnamesu = this->section_contents(strtab_shndx,
|
||||||
&strtab_size);
|
&strtab_size,
|
||||||
|
true);
|
||||||
const char* pnames = reinterpret_cast<const char*>(pnamesu);
|
const char* pnames = reinterpret_cast<const char*>(pnamesu);
|
||||||
|
|
||||||
// Loop over the local symbols.
|
// Loop over the local symbols.
|
||||||
|
@ -700,13 +702,14 @@ Sized_relobj<size, big_endian>::write_local_symbols(Output_file* of,
|
||||||
const int sym_size = This::sym_size;
|
const int sym_size = This::sym_size;
|
||||||
off_t locsize = loccount * sym_size;
|
off_t locsize = loccount * sym_size;
|
||||||
const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(),
|
const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(),
|
||||||
locsize);
|
locsize, false);
|
||||||
|
|
||||||
// Read the symbol names.
|
// Read the symbol names.
|
||||||
const unsigned int strtab_shndx = symtabshdr.get_sh_link();
|
const unsigned int strtab_shndx = symtabshdr.get_sh_link();
|
||||||
off_t strtab_size;
|
off_t strtab_size;
|
||||||
const unsigned char* pnamesu = this->section_contents(strtab_shndx,
|
const unsigned char* pnamesu = this->section_contents(strtab_shndx,
|
||||||
&strtab_size);
|
&strtab_size,
|
||||||
|
true);
|
||||||
const char* pnames = reinterpret_cast<const char*>(pnamesu);
|
const char* pnames = reinterpret_cast<const char*>(pnamesu);
|
||||||
|
|
||||||
// Get a view into the output file.
|
// Get a view into the output file.
|
||||||
|
|
|
@ -168,9 +168,9 @@ class Object
|
||||||
{ return this->shnum_; }
|
{ return this->shnum_; }
|
||||||
|
|
||||||
// Return a view of the contents of a section. Set *PLEN to the
|
// Return a view of the contents of a section. Set *PLEN to the
|
||||||
// size.
|
// size. CACHE is a hint as in File_read::get_view.
|
||||||
const unsigned char*
|
const unsigned char*
|
||||||
section_contents(unsigned int shndx, off_t* plen);
|
section_contents(unsigned int shndx, off_t* plen, bool cache);
|
||||||
|
|
||||||
// Return the name of a section given a section index. This is only
|
// Return the name of a section given a section index. This is only
|
||||||
// used for error messages.
|
// used for error messages.
|
||||||
|
@ -224,7 +224,7 @@ class Object
|
||||||
// Return a View.
|
// Return a View.
|
||||||
View
|
View
|
||||||
view(off_t file_offset, off_t data_size)
|
view(off_t file_offset, off_t data_size)
|
||||||
{ return View(this->get_view(file_offset, data_size)); }
|
{ return View(this->get_view(file_offset, data_size, true)); }
|
||||||
|
|
||||||
// Report an error.
|
// Report an error.
|
||||||
void
|
void
|
||||||
|
@ -243,7 +243,7 @@ class Object
|
||||||
|
|
||||||
// Get a View given a Location.
|
// Get a View given a Location.
|
||||||
View view(Location loc)
|
View view(Location loc)
|
||||||
{ return View(this->get_view(loc.file_offset, loc.data_size)); }
|
{ return View(this->get_view(loc.file_offset, loc.data_size, true)); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Read the symbols--implemented by child class.
|
// Read the symbols--implemented by child class.
|
||||||
|
@ -284,15 +284,18 @@ class Object
|
||||||
|
|
||||||
// Get a view into the underlying file.
|
// Get a view into the underlying file.
|
||||||
const unsigned char*
|
const unsigned char*
|
||||||
get_view(off_t start, off_t size)
|
get_view(off_t start, off_t size, bool cache)
|
||||||
{ return this->input_file_->file().get_view(start + this->offset_, size); }
|
{
|
||||||
|
return this->input_file_->file().get_view(start + this->offset_, size,
|
||||||
|
cache);
|
||||||
|
}
|
||||||
|
|
||||||
// Get a lasting view into the underlying file.
|
// Get a lasting view into the underlying file.
|
||||||
File_view*
|
File_view*
|
||||||
get_lasting_view(off_t start, off_t size)
|
get_lasting_view(off_t start, off_t size, bool cache)
|
||||||
{
|
{
|
||||||
return this->input_file_->file().get_lasting_view(start + this->offset_,
|
return this->input_file_->file().get_lasting_view(start + this->offset_,
|
||||||
size);
|
size, cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read data from the underlying file.
|
// Read data from the underlying file.
|
||||||
|
|
|
@ -172,7 +172,8 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
|
||||||
rd->relocs.reserve(shnum / 2);
|
rd->relocs.reserve(shnum / 2);
|
||||||
|
|
||||||
const unsigned char *pshdrs = this->get_view(this->elf_file_.shoff(),
|
const unsigned char *pshdrs = this->get_view(this->elf_file_.shoff(),
|
||||||
shnum * This::shdr_size);
|
shnum * This::shdr_size,
|
||||||
|
true);
|
||||||
// Skip the first, dummy, section.
|
// Skip the first, dummy, section.
|
||||||
const unsigned char *ps = pshdrs + This::shdr_size;
|
const unsigned char *ps = pshdrs + This::shdr_size;
|
||||||
for (unsigned int i = 1; i < shnum; ++i, ps += This::shdr_size)
|
for (unsigned int i = 1; i < shnum; ++i, ps += This::shdr_size)
|
||||||
|
@ -242,7 +243,8 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
|
||||||
Section_relocs& sr(rd->relocs.back());
|
Section_relocs& sr(rd->relocs.back());
|
||||||
sr.reloc_shndx = i;
|
sr.reloc_shndx = i;
|
||||||
sr.data_shndx = shndx;
|
sr.data_shndx = shndx;
|
||||||
sr.contents = this->get_lasting_view(shdr.get_sh_offset(), sh_size);
|
sr.contents = this->get_lasting_view(shdr.get_sh_offset(), sh_size,
|
||||||
|
true);
|
||||||
sr.sh_type = sh_type;
|
sr.sh_type = sh_type;
|
||||||
sr.reloc_count = reloc_count;
|
sr.reloc_count = reloc_count;
|
||||||
}
|
}
|
||||||
|
@ -261,7 +263,7 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
|
||||||
gold_assert(loccount == symtabshdr.get_sh_info());
|
gold_assert(loccount == symtabshdr.get_sh_info());
|
||||||
off_t locsize = loccount * sym_size;
|
off_t locsize = loccount * sym_size;
|
||||||
rd->local_symbols = this->get_lasting_view(symtabshdr.get_sh_offset(),
|
rd->local_symbols = this->get_lasting_view(symtabshdr.get_sh_offset(),
|
||||||
locsize);
|
locsize, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,7 +318,8 @@ Sized_relobj<size, big_endian>::do_relocate(const General_options& options,
|
||||||
|
|
||||||
// Read the section headers.
|
// Read the section headers.
|
||||||
const unsigned char* pshdrs = this->get_view(this->elf_file_.shoff(),
|
const unsigned char* pshdrs = this->get_view(this->elf_file_.shoff(),
|
||||||
shnum * This::shdr_size);
|
shnum * This::shdr_size,
|
||||||
|
true);
|
||||||
|
|
||||||
Views views;
|
Views views;
|
||||||
views.resize(shnum);
|
views.resize(shnum);
|
||||||
|
@ -455,7 +458,7 @@ Sized_relobj<size, big_endian>::relocate_sections(
|
||||||
|
|
||||||
off_t sh_size = shdr.get_sh_size();
|
off_t sh_size = shdr.get_sh_size();
|
||||||
const unsigned char* prelocs = this->get_view(shdr.get_sh_offset(),
|
const unsigned char* prelocs = this->get_view(shdr.get_sh_offset(),
|
||||||
sh_size);
|
sh_size, false);
|
||||||
|
|
||||||
unsigned int reloc_size;
|
unsigned int reloc_size;
|
||||||
if (sh_type == elfcpp::SHT_REL)
|
if (sh_type == elfcpp::SHT_REL)
|
||||||
|
|
|
@ -1550,7 +1550,8 @@ Warnings::note_warnings(Symbol_table* symtab)
|
||||||
Task_locker_obj<Object> tl(*p->second.object);
|
Task_locker_obj<Object> tl(*p->second.object);
|
||||||
const unsigned char* c;
|
const unsigned char* c;
|
||||||
off_t len;
|
off_t len;
|
||||||
c = p->second.object->section_contents(p->second.shndx, &len);
|
c = p->second.object->section_contents(p->second.shndx, &len,
|
||||||
|
false);
|
||||||
p->second.set_text(reinterpret_cast<const char*>(c), len);
|
p->second.set_text(reinterpret_cast<const char*>(c), len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue