* dwarf_reader.cc (Sized_dwarf_line_info::Sized_dwarf_line_info):
Call Object::decompressed_section_contents. * dwarf_reader.h (Sized_dwarf_line_info::~Sized_dwarf_line_info): New dtor. (Sized_dwarf_line_info::buffer_start_): New data member. * merge.cc (Output_merge_data::do_add_input_section): Call Object::decompressed_section_contents. (Output_merge_string::do_add_input_section): Likewise. * object.cc (need_decompressed_section): New function. (build_compressed_section_map): Decompress sections needed later. (Sized_relobj_file::do_decompressed_section_contents): New function. (Sized_relobj_file::do_discard_decompressed_sections): New function. * object.h (Object::decompressed_section_contents): New function. (Object::discard_decompressed_sections): New function. (Object::do_decompressed_section_contents): New function. (Object::do_discard_decompressed_sections): New function. (Compressed_section_info): New type. (Compressed_section_map): Include decompressed section contents. (Sized_relobj_file::do_decompressed_section_contents): New function. (Sized_relobj_file::do_discard_decompressed_sections): New function.
This commit is contained in:
parent
718cb7da5d
commit
5dd8762ad1
@ -1,3 +1,26 @@
|
||||
2012-02-29 Cary Coutant <ccoutant@google.com>
|
||||
|
||||
* dwarf_reader.cc (Sized_dwarf_line_info::Sized_dwarf_line_info):
|
||||
Call Object::decompressed_section_contents.
|
||||
* dwarf_reader.h (Sized_dwarf_line_info::~Sized_dwarf_line_info):
|
||||
New dtor.
|
||||
(Sized_dwarf_line_info::buffer_start_): New data member.
|
||||
* merge.cc (Output_merge_data::do_add_input_section): Call
|
||||
Object::decompressed_section_contents.
|
||||
(Output_merge_string::do_add_input_section): Likewise.
|
||||
* object.cc (need_decompressed_section): New function.
|
||||
(build_compressed_section_map): Decompress sections needed later.
|
||||
(Sized_relobj_file::do_decompressed_section_contents): New function.
|
||||
(Sized_relobj_file::do_discard_decompressed_sections): New function.
|
||||
* object.h (Object::decompressed_section_contents): New function.
|
||||
(Object::discard_decompressed_sections): New function.
|
||||
(Object::do_decompressed_section_contents): New function.
|
||||
(Object::do_discard_decompressed_sections): New function.
|
||||
(Compressed_section_info): New type.
|
||||
(Compressed_section_map): Include decompressed section contents.
|
||||
(Sized_relobj_file::do_decompressed_section_contents): New function.
|
||||
(Sized_relobj_file::do_discard_decompressed_sections): New function.
|
||||
|
||||
2012-02-16 Cary Coutant <ccoutant@google.com>
|
||||
|
||||
* testsuite/Makefile.am (initpri2): Add --ctors-in-init-array option.
|
||||
|
@ -62,12 +62,14 @@ ResetLineStateMachine(struct LineStateMachine* lsm, bool default_is_stmt)
|
||||
}
|
||||
|
||||
template<int size, bool big_endian>
|
||||
Sized_dwarf_line_info<size, big_endian>::Sized_dwarf_line_info(Object* object,
|
||||
unsigned int read_shndx)
|
||||
: data_valid_(false), buffer_(NULL), symtab_buffer_(NULL),
|
||||
directories_(), files_(), current_header_index_(-1)
|
||||
Sized_dwarf_line_info<size, big_endian>::Sized_dwarf_line_info(
|
||||
Object* object,
|
||||
unsigned int read_shndx)
|
||||
: data_valid_(false), buffer_(NULL), buffer_start_(NULL),
|
||||
symtab_buffer_(NULL), directories_(), files_(), current_header_index_(-1)
|
||||
{
|
||||
unsigned int debug_shndx;
|
||||
|
||||
for (debug_shndx = 1; debug_shndx < object->shnum(); ++debug_shndx)
|
||||
{
|
||||
// FIXME: do this more efficiently: section_name() isn't super-fast
|
||||
@ -75,8 +77,12 @@ Sized_dwarf_line_info<size, big_endian>::Sized_dwarf_line_info(Object* object,
|
||||
if (name == ".debug_line" || name == ".zdebug_line")
|
||||
{
|
||||
section_size_type buffer_size;
|
||||
this->buffer_ = object->section_contents(debug_shndx, &buffer_size,
|
||||
false);
|
||||
bool is_new = false;
|
||||
this->buffer_ = object->decompressed_section_contents(debug_shndx,
|
||||
&buffer_size,
|
||||
&is_new);
|
||||
if (is_new)
|
||||
this->buffer_start_ = this->buffer_;
|
||||
this->buffer_end_ = this->buffer_ + buffer_size;
|
||||
break;
|
||||
}
|
||||
@ -84,21 +90,6 @@ Sized_dwarf_line_info<size, big_endian>::Sized_dwarf_line_info(Object* object,
|
||||
if (this->buffer_ == NULL)
|
||||
return;
|
||||
|
||||
section_size_type uncompressed_size = 0;
|
||||
unsigned char* uncompressed_data = NULL;
|
||||
if (object->section_is_compressed(debug_shndx, &uncompressed_size))
|
||||
{
|
||||
uncompressed_data = new unsigned char[uncompressed_size];
|
||||
if (!decompress_input_section(this->buffer_,
|
||||
this->buffer_end_ - this->buffer_,
|
||||
uncompressed_data,
|
||||
uncompressed_size))
|
||||
object->error(_("could not decompress section %s"),
|
||||
object->section_name(debug_shndx).c_str());
|
||||
this->buffer_ = uncompressed_data;
|
||||
this->buffer_end_ = this->buffer_ + uncompressed_size;
|
||||
}
|
||||
|
||||
// Find the relocation section for ".debug_line".
|
||||
// We expect these for relobjs (.o's) but not dynobjs (.so's).
|
||||
bool got_relocs = false;
|
||||
|
@ -120,6 +120,13 @@ class Sized_dwarf_line_info : public Dwarf_line_info
|
||||
// information that pertains to the specified section.
|
||||
Sized_dwarf_line_info(Object* object, unsigned int read_shndx = -1U);
|
||||
|
||||
virtual
|
||||
~Sized_dwarf_line_info()
|
||||
{
|
||||
if (this->buffer_start_ != NULL)
|
||||
delete[] this->buffer_start_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string
|
||||
do_addr2line(unsigned int shndx, off_t offset,
|
||||
@ -199,6 +206,10 @@ class Sized_dwarf_line_info : public Dwarf_line_info
|
||||
// the line info to read is.
|
||||
const unsigned char* buffer_;
|
||||
const unsigned char* buffer_end_;
|
||||
// If the buffer was allocated temporarily, and therefore must be
|
||||
// deallocated in the dtor, this contains a pointer to the start
|
||||
// of the buffer.
|
||||
const unsigned char* buffer_start_;
|
||||
|
||||
// This has relocations that point into buffer.
|
||||
Track_relocs<size, big_endian> track_relocs_;
|
||||
|
@ -406,27 +406,16 @@ bool
|
||||
Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
|
||||
{
|
||||
section_size_type len;
|
||||
section_size_type uncompressed_size = 0;
|
||||
unsigned char* uncompressed_data = NULL;
|
||||
const unsigned char* p = object->section_contents(shndx, &len, false);
|
||||
|
||||
if (object->section_is_compressed(shndx, &uncompressed_size))
|
||||
{
|
||||
uncompressed_data = new unsigned char[uncompressed_size];
|
||||
if (!decompress_input_section(p, len, uncompressed_data,
|
||||
uncompressed_size))
|
||||
object->error(_("could not decompress section %s"),
|
||||
object->section_name(shndx).c_str());
|
||||
p = uncompressed_data;
|
||||
len = uncompressed_size;
|
||||
}
|
||||
bool is_new;
|
||||
const unsigned char* p = object->decompressed_section_contents(shndx, &len,
|
||||
&is_new);
|
||||
|
||||
section_size_type entsize = convert_to_section_size_type(this->entsize());
|
||||
|
||||
if (len % entsize != 0)
|
||||
{
|
||||
if (uncompressed_data != NULL)
|
||||
delete[] uncompressed_data;
|
||||
if (is_new)
|
||||
delete[] p;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -457,8 +446,8 @@ Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
|
||||
if (this->keeps_input_sections())
|
||||
record_input_section(object, shndx);
|
||||
|
||||
if (uncompressed_data != NULL)
|
||||
delete[] uncompressed_data;
|
||||
if (is_new)
|
||||
delete[] p;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -517,20 +506,10 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
|
||||
unsigned int shndx)
|
||||
{
|
||||
section_size_type len;
|
||||
section_size_type uncompressed_size = 0;
|
||||
unsigned char* uncompressed_data = NULL;
|
||||
const unsigned char* pdata = object->section_contents(shndx, &len, false);
|
||||
|
||||
if (object->section_is_compressed(shndx, &uncompressed_size))
|
||||
{
|
||||
uncompressed_data = new unsigned char[uncompressed_size];
|
||||
if (!decompress_input_section(pdata, len, uncompressed_data,
|
||||
uncompressed_size))
|
||||
object->error(_("could not decompress section %s"),
|
||||
object->section_name(shndx).c_str());
|
||||
pdata = uncompressed_data;
|
||||
len = uncompressed_size;
|
||||
}
|
||||
bool is_new;
|
||||
const unsigned char* pdata = object->decompressed_section_contents(shndx,
|
||||
&len,
|
||||
&is_new);
|
||||
|
||||
const Char_type* p = reinterpret_cast<const Char_type*>(pdata);
|
||||
const Char_type* pend = p + len / sizeof(Char_type);
|
||||
@ -540,8 +519,8 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
|
||||
{
|
||||
object->error(_("mergeable string section length not multiple of "
|
||||
"character size"));
|
||||
if (uncompressed_data != NULL)
|
||||
delete[] uncompressed_data;
|
||||
if (is_new)
|
||||
delete[] pdata;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -606,8 +585,8 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
|
||||
if (this->keeps_input_sections())
|
||||
record_input_section(object, shndx);
|
||||
|
||||
if (uncompressed_data != NULL)
|
||||
delete[] uncompressed_data;
|
||||
if (is_new)
|
||||
delete[] pdata;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
130
gold/object.cc
130
gold/object.cc
@ -550,8 +550,22 @@ Sized_relobj_file<size, big_endian>::find_eh_frame(
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return TRUE if this is a section whose contents will be needed in the
|
||||
// Add_symbols task.
|
||||
|
||||
static bool
|
||||
need_decompressed_section(const char* name)
|
||||
{
|
||||
// We will need .zdebug_str if this is not an incremental link
|
||||
// (i.e., we are processing string merge sections).
|
||||
if (!parameters->incremental() && strcmp(name, ".zdebug_str") == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Build a table for any compressed debug sections, mapping each section index
|
||||
// to the uncompressed size.
|
||||
// to the uncompressed size and (if needed) the decompressed contents.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
Compressed_section_map*
|
||||
@ -562,9 +576,10 @@ build_compressed_section_map(
|
||||
section_size_type names_size,
|
||||
Sized_relobj_file<size, big_endian>* obj)
|
||||
{
|
||||
Compressed_section_map* uncompressed_sizes = new Compressed_section_map();
|
||||
Compressed_section_map* uncompressed_map = new Compressed_section_map();
|
||||
const unsigned int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
|
||||
const unsigned char* p = pshdrs + shdr_size;
|
||||
|
||||
for (unsigned int i = 1; i < shnum; ++i, p += shdr_size)
|
||||
{
|
||||
typename elfcpp::Shdr<size, big_endian> shdr(p);
|
||||
@ -586,12 +601,38 @@ build_compressed_section_map(
|
||||
obj->section_contents(i, &len, false);
|
||||
uint64_t uncompressed_size = get_uncompressed_size(contents, len);
|
||||
if (uncompressed_size != -1ULL)
|
||||
(*uncompressed_sizes)[i] =
|
||||
convert_to_section_size_type(uncompressed_size);
|
||||
{
|
||||
Compressed_section_info info;
|
||||
info.size = convert_to_section_size_type(uncompressed_size);
|
||||
info.contents = NULL;
|
||||
|
||||
#ifdef ENABLE_THREADS
|
||||
// If we're multi-threaded, it will help to decompress
|
||||
// any sections that will be needed during the Add_symbols
|
||||
// task, so that several decompressions can run in
|
||||
// parallel.
|
||||
if (parameters->options().threads())
|
||||
{
|
||||
unsigned char* uncompressed_data = NULL;
|
||||
if (need_decompressed_section(name))
|
||||
{
|
||||
uncompressed_data = new unsigned char[uncompressed_size];
|
||||
if (decompress_input_section(contents, len,
|
||||
uncompressed_data,
|
||||
uncompressed_size))
|
||||
info.contents = uncompressed_data;
|
||||
else
|
||||
delete[] uncompressed_data;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
(*uncompressed_map)[i] = info;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return uncompressed_sizes;
|
||||
return uncompressed_map;
|
||||
}
|
||||
|
||||
// Read the sections and symbols from an object file.
|
||||
@ -2557,6 +2598,85 @@ Sized_relobj_file<size, big_endian>::do_get_global_symbol_counts(
|
||||
*used = count;
|
||||
}
|
||||
|
||||
// Return a view of the decompressed contents of a section. Set *PLEN
|
||||
// to the size. Set *IS_NEW to true if the contents need to be freed
|
||||
// by the caller.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
const unsigned char*
|
||||
Sized_relobj_file<size, big_endian>::do_decompressed_section_contents(
|
||||
unsigned int shndx,
|
||||
section_size_type* plen,
|
||||
bool* is_new)
|
||||
{
|
||||
section_size_type buffer_size;
|
||||
const unsigned char* buffer = this->section_contents(shndx, &buffer_size,
|
||||
false);
|
||||
|
||||
if (this->compressed_sections_ == NULL)
|
||||
{
|
||||
*plen = buffer_size;
|
||||
*is_new = false;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
Compressed_section_map::const_iterator p =
|
||||
this->compressed_sections_->find(shndx);
|
||||
if (p == this->compressed_sections_->end())
|
||||
{
|
||||
*plen = buffer_size;
|
||||
*is_new = false;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
section_size_type uncompressed_size = p->second.size;
|
||||
if (p->second.contents != NULL)
|
||||
{
|
||||
*plen = uncompressed_size;
|
||||
*is_new = false;
|
||||
return p->second.contents;
|
||||
}
|
||||
|
||||
unsigned char* uncompressed_data = new unsigned char[uncompressed_size];
|
||||
if (!decompress_input_section(buffer,
|
||||
buffer_size,
|
||||
uncompressed_data,
|
||||
uncompressed_size))
|
||||
this->error(_("could not decompress section %s"),
|
||||
this->do_section_name(shndx).c_str());
|
||||
|
||||
// We could cache the results in p->second.contents and store
|
||||
// false in *IS_NEW, but build_compressed_section_map() would
|
||||
// have done so if it had expected it to be profitable. If
|
||||
// we reach this point, we expect to need the contents only
|
||||
// once in this pass.
|
||||
*plen = uncompressed_size;
|
||||
*is_new = true;
|
||||
return uncompressed_data;
|
||||
}
|
||||
|
||||
// Discard any buffers of uncompressed sections. This is done
|
||||
// at the end of the Add_symbols task.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_relobj_file<size, big_endian>::do_discard_decompressed_sections()
|
||||
{
|
||||
if (this->compressed_sections_ == NULL)
|
||||
return;
|
||||
|
||||
for (Compressed_section_map::iterator p = this->compressed_sections_->begin();
|
||||
p != this->compressed_sections_->end();
|
||||
++p)
|
||||
{
|
||||
if (p->second.contents != NULL)
|
||||
{
|
||||
delete[] p->second.contents;
|
||||
p->second.contents = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Input_objects methods.
|
||||
|
||||
// Add a regular relocatable object to the list. Return false if this
|
||||
|
@ -725,6 +725,20 @@ class Object
|
||||
section_size_type* uncompressed_size) const
|
||||
{ return this->do_section_is_compressed(shndx, uncompressed_size); }
|
||||
|
||||
// Return a view of the uncompressed contents of a section. Set *PLEN
|
||||
// to the size. Set *IS_NEW to true if the contents need to be freed
|
||||
// by the caller.
|
||||
const unsigned char*
|
||||
decompressed_section_contents(unsigned int shndx, section_size_type* plen,
|
||||
bool* is_cached)
|
||||
{ return this->do_decompressed_section_contents(shndx, plen, is_cached); }
|
||||
|
||||
// Discard any buffers of decompressed sections. This is done
|
||||
// at the end of the Add_symbols task.
|
||||
void
|
||||
discard_decompressed_sections()
|
||||
{ this->do_discard_decompressed_sections(); }
|
||||
|
||||
// Return the index of the first incremental relocation for symbol SYMNDX.
|
||||
unsigned int
|
||||
get_incremental_reloc_base(unsigned int symndx) const
|
||||
@ -892,6 +906,27 @@ class Object
|
||||
do_section_is_compressed(unsigned int, section_size_type*) const
|
||||
{ return false; }
|
||||
|
||||
// Return a view of the decompressed contents of a section. Set *PLEN
|
||||
// to the size. This default implementation simply returns the
|
||||
// raw section contents and sets *IS_NEW to false to indicate
|
||||
// that the contents do not need to be freed by the caller.
|
||||
// This function must be overridden for any types of object files
|
||||
// that might contain compressed sections.
|
||||
virtual const unsigned char*
|
||||
do_decompressed_section_contents(unsigned int shndx,
|
||||
section_size_type* plen,
|
||||
bool* is_new)
|
||||
{
|
||||
*is_new = false;
|
||||
return this->section_contents(shndx, plen, false);
|
||||
}
|
||||
|
||||
// Discard any buffers of decompressed sections. This is done
|
||||
// at the end of the Add_symbols task.
|
||||
virtual void
|
||||
do_discard_decompressed_sections()
|
||||
{ }
|
||||
|
||||
// Return the index of the first incremental relocation for symbol SYMNDX--
|
||||
// implemented by child class.
|
||||
virtual unsigned int
|
||||
@ -1775,9 +1810,14 @@ class Reloc_symbol_changes
|
||||
std::vector<Symbol*> vec_;
|
||||
};
|
||||
|
||||
// Type for mapping section index to uncompressed size.
|
||||
// Type for mapping section index to uncompressed size and contents.
|
||||
|
||||
typedef std::map<unsigned int, section_size_type> Compressed_section_map;
|
||||
struct Compressed_section_info
|
||||
{
|
||||
section_size_type size;
|
||||
const unsigned char* contents;
|
||||
};
|
||||
typedef std::map<unsigned int, Compressed_section_info> Compressed_section_map;
|
||||
|
||||
// Abstract base class for a regular object file, either a real object file
|
||||
// or an incremental (unchanged) object. This is size and endian specific.
|
||||
@ -2319,12 +2359,25 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
|
||||
if (p != this->compressed_sections_->end())
|
||||
{
|
||||
if (uncompressed_size != NULL)
|
||||
*uncompressed_size = p->second;
|
||||
*uncompressed_size = p->second.size;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return a view of the uncompressed contents of a section. Set *PLEN
|
||||
// to the size. Set *IS_NEW to true if the contents need to be deleted
|
||||
// by the caller.
|
||||
const unsigned char*
|
||||
do_decompressed_section_contents(unsigned int shndx,
|
||||
section_size_type* plen,
|
||||
bool* is_new);
|
||||
|
||||
// Discard any buffers of uncompressed sections. This is done
|
||||
// at the end of the Add_symbols task.
|
||||
void
|
||||
do_discard_decompressed_sections();
|
||||
|
||||
private:
|
||||
// For convenience.
|
||||
typedef Sized_relobj_file<size, big_endian> This;
|
||||
@ -2609,7 +2662,8 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
|
||||
std::vector<Deferred_layout> deferred_layout_;
|
||||
// The list of relocation sections whose layout was deferred.
|
||||
std::vector<Deferred_layout> deferred_layout_relocs_;
|
||||
// For compressed debug sections, map section index to uncompressed size.
|
||||
// For compressed debug sections, map section index to uncompressed size
|
||||
// and contents.
|
||||
Compressed_section_map* compressed_sections_;
|
||||
};
|
||||
|
||||
|
@ -602,6 +602,7 @@ Add_symbols::run(Workqueue*)
|
||||
|
||||
if (!this->input_objects_->add_object(this->object_))
|
||||
{
|
||||
this->object_->discard_decompressed_sections();
|
||||
gold_assert(this->sd_ != NULL);
|
||||
delete this->sd_;
|
||||
this->sd_ = NULL;
|
||||
@ -632,6 +633,7 @@ Add_symbols::run(Workqueue*)
|
||||
}
|
||||
this->object_->layout(this->symtab_, this->layout_, this->sd_);
|
||||
this->object_->add_symbols(this->symtab_, this->sd_, this->layout_);
|
||||
this->object_->discard_decompressed_sections();
|
||||
delete this->sd_;
|
||||
this->sd_ = NULL;
|
||||
this->object_->release();
|
||||
|
Loading…
Reference in New Issue
Block a user