From Craig Silverstein: Add support for compressing .debug_str section.

This commit is contained in:
Ian Lance Taylor 2007-11-30 00:35:27 +00:00
parent 71195202df
commit 9a0910c33e
20 changed files with 1666 additions and 444 deletions

View File

@ -30,6 +30,7 @@ noinst_LIBRARIES = libgold.a
CCFILES = \
archive.cc \
common.cc \
compressed_output.cc \
defstd.cc \
dirsearch.cc \
dynobj.cc \
@ -59,6 +60,7 @@ CCFILES = \
HFILES = \
archive.h \
common.h \
compressed_output.h \
defstd.h \
dirsearch.h \
dynobj.h \

View File

@ -70,7 +70,8 @@ AR = ar
ARFLAGS = cru
libgold_a_AR = $(AR) $(ARFLAGS)
libgold_a_LIBADD =
am__objects_1 = archive.$(OBJEXT) common.$(OBJEXT) defstd.$(OBJEXT) \
am__objects_1 = archive.$(OBJEXT) common.$(OBJEXT) \
compressed_output.$(OBJEXT) defstd.$(OBJEXT) \
dirsearch.$(OBJEXT) dynobj.$(OBJEXT) dwarf_reader.$(OBJEXT) \
ehframe.$(OBJEXT) errors.$(OBJEXT) fileread.$(OBJEXT) \
gold.$(OBJEXT) gold-threads.$(OBJEXT) layout.$(OBJEXT) \
@ -152,6 +153,7 @@ CATOBJEXT = @CATOBJEXT@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
@ -285,6 +287,7 @@ noinst_LIBRARIES = libgold.a
CCFILES = \
archive.cc \
common.cc \
compressed_output.cc \
defstd.cc \
dirsearch.cc \
dynobj.cc \
@ -314,6 +317,7 @@ CCFILES = \
HFILES = \
archive.h \
common.h \
compressed_output.h \
defstd.h \
dirsearch.h \
dynobj.h \
@ -465,6 +469,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pread.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/archive.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compressed_output.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/defstd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dirsearch.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_reader.Po@am__quote@

267
gold/compressed_output.cc Normal file
View File

@ -0,0 +1,267 @@
// compressed_output.cc -- manage compressed output sections for gold
// Copyright 2007 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
// MA 02110-1301, USA.
#include "gold.h"
#ifdef HAVE_ZLIB_H
#include <zlib.h>
#endif
#include "compressed_output.h"
#include "parameters.h"
namespace gold
{
// Compress UNCOMPRESSED_DATA of size UNCOMPRESSED_SIZE. Returns true
// if it successfully compressed, false if it failed for any reason
// (including not having zlib support in the library). If it returns
// true, it allocates memory for the compressed data using new, and
// sets *COMPRESSED_DATA and *COMPRESSED_SIZE to appropriate values.
static bool
zlib_compress(const char* uncompressed_data, unsigned long uncompressed_size,
char** compressed_data, unsigned long* compressed_size)
{
#ifndef HAVE_ZLIB_H
return false;
#else
*compressed_size = uncompressed_size + uncompressed_size / 1000 + 128;
*compressed_data = new char[*compressed_size];
int compress_level;
if (parameters->optimization_level() >= 1)
compress_level = 9;
else
compress_level = 1;
int rc = compress2(reinterpret_cast<Bytef*>(*compressed_data),
compressed_size,
reinterpret_cast<const Bytef*>(uncompressed_data),
uncompressed_size,
compress_level);
if (rc == Z_OK)
return true;
else
{
delete[] *compressed_data;
*compressed_data = NULL;
return false;
}
#endif // #ifdef HAVE_ZLIB_H
}
// After compressing an output section, we rename it from foo to
// foo.zlib.nnnn, where nnnn is the uncompressed size of the section.
static std::string
zlib_compressed_suffix(unsigned long uncompressed_size)
{
char size_string[64];
snprintf(size_string, sizeof(size_string), "%lu", uncompressed_size);
return std::string(".zlib.") + size_string;
}
// Class Output_compressed_section_data.
// Add an input section. In this case, we just keep track of the sections.
bool
Output_compressed_section_data::do_add_input_section(Relobj* obj,
unsigned int shndx)
{
this->objects_.push_back(Object_entry(obj, shndx));
return true;
}
// Set the final data size of a compressed section. This is where
// we actually compress the section data.
void
Output_compressed_section_data::set_final_data_size()
{
// FIXME: assert that relocations have already been applied.
off_t uncompressed_size = 0;
for (std::vector<Object_entry>::iterator it = this->objects_.begin();
it != this->objects_.end();
++it)
{
it->contents
= it->object->section_contents(it->shndx, &it->length, false);
uncompressed_size += it->length;
}
// (Try to) compress the data.
unsigned long compressed_size;
char* uncompressed_data = new char[uncompressed_size];
off_t pos = 0;
for (std::vector<Object_entry>::const_iterator it = this->objects_.begin();
it != this->objects_.end();
++it)
{
memcpy(uncompressed_data + pos,
reinterpret_cast<const char*>(it->contents),
it->length);
pos += it->length;
}
bool success = false;
if (options_.zlib_compress_debug_sections())
success = zlib_compress(uncompressed_data, uncompressed_size,
&this->data_, &compressed_size);
if (success)
{
delete[] uncompressed_data;
this->set_data_size(compressed_size);
this->new_section_name_ = zlib_compressed_suffix(uncompressed_size);
}
else
{
gold_warning(_("Not compressing section data: zlib error"));
gold_assert(this->data_ == NULL);
this->data_ = uncompressed_data;
this->set_data_size(uncompressed_size);
}
}
// Change the name of the output section to reflect it's compressed.
// The layout routines call into this right before finalizing the
// shstrtab.
const char*
Output_compressed_section_data::do_modified_output_section_name(
const char* name)
{
// This mean we never compressed the data.
if (this->new_section_name_.empty())
return NULL;
this->new_section_name_ = std::string(name) + this->new_section_name_;
return this->new_section_name_.c_str();
}
// Write out a compressed section. If we couldn't compress, we just
// write it out as normal, uncompressed data.
void
Output_compressed_section_data::do_write(Output_file* of)
{
unsigned char* uview = of->get_output_view(this->offset(),
this->data_size());
char* view = reinterpret_cast<char*>(uview);
memcpy(view, this->data_, this->data_size());
of->write_output_view(this->offset(), this->data_size(), uview);
}
// Class Output_compressed_string.
// Add an input section. We don't do anything special here.
template<typename Char_type>
bool
Output_compressed_string<Char_type>::do_add_input_section(Relobj* object,
unsigned int shndx)
{
return Output_merge_string<Char_type>::do_add_input_section(object, shndx);
}
// Set the final data size of a compressed section. This is where
// we actually compress the section data.
template<typename Char_type>
void
Output_compressed_string<Char_type>::set_final_data_size()
{
// First let the superclass finalize all its data, then write it to
// a buffer.
unsigned long uncompressed_size = this->finalize_merged_data();
char* uncompressed_data = new char[uncompressed_size];
this->stringpool_to_buffer(uncompressed_data, uncompressed_size);
// (Try to) compress the data.
unsigned long compressed_size;
if (options_.zlib_compress_debug_sections()
&& zlib_compress(uncompressed_data, uncompressed_size,
&this->compressed_data_, &compressed_size))
{
this->set_data_size(compressed_size);
// Save some memory.
this->clear_stringpool();
// We will be renaming the section to name.zlib.uncompressed_size.
this->new_section_name_ = zlib_compressed_suffix(uncompressed_size);
}
else
{
this->compressed_data_ = NULL;
this->set_data_size(uncompressed_size);
}
delete[] uncompressed_data;
}
// Change the name of the output section to reflect it's compressed.
// The layout routines call into this right before finalizing the
// shstrtab.
template<typename Char_type>
const char*
Output_compressed_string<Char_type>::do_modified_output_section_name(
const char* name)
{
// This mean we never compressed the data
if (this->new_section_name_.empty())
return NULL;
this->new_section_name_ = std::string(name) + this->new_section_name_;
return this->new_section_name_.c_str();
}
// Write out a compressed string section. If we couldn't compress,
// we just write out the normal string section.
template<typename Char_type>
void
Output_compressed_string<Char_type>::do_write(Output_file* of)
{
if (this->compressed_data_ == NULL)
Output_merge_string<Char_type>::do_write(of);
else
{
unsigned char* uview = of->get_output_view(this->offset(),
this->data_size());
char* view = reinterpret_cast<char*>(uview);
memcpy(view, this->compressed_data_, this->data_size());
of->write_output_view(this->offset(), this->data_size(), uview);
}
}
// Instantiate the templates we need.
template
class Output_compressed_string<char>;
template
class Output_compressed_string<uint16_t>;
template
class Output_compressed_string<uint32_t>;
} // End namespace gold.

137
gold/compressed_output.h Normal file
View File

@ -0,0 +1,137 @@
// compressed_output.h -- compressed output sections for gold -*- C++ -*-
// Copyright 2007 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
// MA 02110-1301, USA.
// We support compressing .debug_* sections on output. (And,
// potentially one day, other sections.) This is a form of
// relaxation. This file adds support for merging and emitting the
// compressed sections.
#ifndef GOLD_COMPRESSED_OUTPUT_H
#define GOLD_COMPRESSED_OUTPUT_H
#include <string>
#include <vector>
#include "output.h"
#include "merge.h"
namespace gold
{
class General_options;
// This is used for compressing a section before emitting it in the
// output file. This only works for unloaded sections, since it
// assumes the final section contents are available at
// set_final_data_size() time. For loaded sections (those that end up
// in segments), this is not true; relocations are applied after
// set_final_data_size() is called. However, for unloaded sections,
// we can -- and do -- postpone calling finalize_data_size() until
// after relocations are applies.
class Output_compressed_section_data : public Output_section_data
{
public:
Output_compressed_section_data(uint64_t addralign,
const General_options& options)
: Output_section_data(addralign), options_(options), data_(NULL)
{ }
protected:
// Add an input section.
bool
do_add_input_section(Relobj* object, unsigned int shndx);
// Set the final data size.
void
set_final_data_size();
// Change the name of the output section to reflect it's compressed.
const char*
do_modified_output_section_name(const char* name);
// Write the data to the file.
void
do_write(Output_file*);
private:
struct Object_entry
{
Relobj* object;
unsigned int shndx;
const unsigned char* contents;
off_t length;
Object_entry(Relobj* o, unsigned int s)
: object(o), shndx(s), contents(NULL), length(0)
{ }
};
const General_options& options_;
std::vector<Object_entry> objects_;
char* data_;
std::string new_section_name_;
};
// This is a special case for when the output section is a string
// section and does not have any relocations to apply to it.
template<typename Char_type>
class Output_compressed_string : public Output_merge_string<Char_type>
{
public:
Output_compressed_string(uint64_t addralign,
const General_options& options)
: Output_merge_string<Char_type>(addralign),
options_(options), compressed_data_(NULL)
{ }
~Output_compressed_string()
{ delete[] compressed_data_; }
protected:
// Add an input section.
bool
do_add_input_section(Relobj* object, unsigned int shndx);
// Set the final data size. Also compresses the buffer.
void
set_final_data_size();
// Change the name of the output section to reflect it's compressed.
const char*
do_modified_output_section_name(const char* name);
// Write the data to the file.
void
do_write(Output_file*);
private:
const General_options& options_;
char* compressed_data_;
// This is just a buffer to store the section name in "permanent" storage.
std::string new_section_name_;
};
} // End namespace gold.
#endif // !defined(GOLD_COMPRESSED_OUTPUT_H)

View File

@ -67,6 +67,9 @@
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the <zlib.h> header file. */
#undef HAVE_ZLIB_H
/* Name of package */
#undef PACKAGE

1028
gold/configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -202,6 +202,9 @@ AC_SUBST(LFS_CXXFLAGS)
AC_REPLACE_FUNCS(pread)
# Link in zlib if we can. This allows us to write compressed sections.
AC_SEARCH_LIBS(zlibVersion, z, [AC_CHECK_HEADERS(zlib.h)])
AC_LANG_PUSH(C++)
AC_CHECK_HEADERS(tr1/unordered_set tr1/unordered_map)

View File

@ -393,7 +393,7 @@ Output_section*
Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
elfcpp::Elf_Xword flags)
{
Output_section* os = new Output_section(name, type, flags);
Output_section* os = new Output_section(this->options_, name, type, flags);
this->section_list_.push_back(os);
if ((flags & elfcpp::SHF_ALLOC) == 0)
@ -710,7 +710,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab)
// Set the file offsets of all the non-data sections which don't
// have to wait for the input sections.
off = this->set_section_offsets(off, false);
off = this->set_section_offsets(off, BEFORE_INPUT_SECTIONS_PASS);
// Now that all sections have been created, set the section indexes.
shndx = this->set_section_indexes(shndx);
@ -1059,7 +1059,7 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
// segment.
off_t
Layout::set_section_offsets(off_t off, bool after_input_sections)
Layout::set_section_offsets(off_t off, Layout::Section_offset_pass pass)
{
for (Section_list::iterator p = this->unattached_section_list_.begin();
p != this->unattached_section_list_.end();
@ -1069,8 +1069,17 @@ Layout::set_section_offsets(off_t off, bool after_input_sections)
if (*p == this->symtab_section_)
continue;
if ((*p)->after_input_sections() != after_input_sections)
continue;
if (pass == BEFORE_INPUT_SECTIONS_PASS
&& (*p)->after_input_sections())
continue;
else if (pass == AFTER_INPUT_SECTIONS_PASS
&& (!(*p)->after_input_sections()
|| (*p)->type() == elfcpp::SHT_STRTAB))
continue;
else if (pass == STRTAB_AFTER_INPUT_SECTIONS_PASS
&& (!(*p)->after_input_sections()
|| (*p)->type() != elfcpp::SHT_STRTAB))
continue;
off = align_address(off, (*p)->addralign());
(*p)->set_file_offset(off);
@ -1080,6 +1089,19 @@ Layout::set_section_offsets(off_t off, bool after_input_sections)
return off;
}
// Allow any section not associated with a segment to change its
// output section name at the last minute.
void
Layout::modify_section_names()
{
for (Section_list::iterator p = this->unattached_section_list_.begin();
p != this->unattached_section_list_.end();
++p)
if ((*p)->maybe_modify_output_section_name())
this->namepool_.add((*p)->name(), true, NULL);
}
// Set the section indexes of all the sections not associated with a
// segment.
@ -1883,9 +1905,19 @@ void
Layout::write_sections_after_input_sections(Output_file* of)
{
// Determine the final section offsets, and thus the final output
// file size.
// file size. Note we finalize the .shstrab last, to allow the
// after_input_section sections to modify their section-names before
// writing.
off_t off = this->output_file_size_;
off = this->set_section_offsets(off, true);
off = this->set_section_offsets(off, AFTER_INPUT_SECTIONS_PASS);
// Determine the final section names as well (at least, for sections
// that we haven't written yet).
this->modify_section_names();
// Now that we've finalized the names, we can finalize the shstrab.
off = this->set_section_offsets(off, STRTAB_AFTER_INPUT_SECTIONS_PASS);
if (off > this->output_file_size_)
{
of->resize(off);

View File

@ -342,9 +342,25 @@ class Layout
set_segment_offsets(const Target*, Output_segment*, unsigned int* pshndx);
// Set the final file offsets of all the sections not associated
// with a segment.
// with a segment. We set section offsets in three passes: the
// first handles all allocated sections, the second sections that
// can be handled after input-sections are processed, and the last
// the late-bound STRTAB sections (probably only shstrtab, which is
// the one we care about because it holds section names).
enum Section_offset_pass
{
BEFORE_INPUT_SECTIONS_PASS,
AFTER_INPUT_SECTIONS_PASS,
STRTAB_AFTER_INPUT_SECTIONS_PASS
};
off_t
set_section_offsets(off_t, bool after_input_sections);
set_section_offsets(off_t, Section_offset_pass pass);
// We also allow any section not associated with a segment to change
// its output section name at the last minute. Compressed sections
// use this to embed compression info in their name.
void
modify_section_names();
// Set the final section indexes of all the sections not associated
// with a segment. Returns the next unused index.

View File

@ -496,13 +496,12 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
return true;
}
// Set the final data size of a merged string section. This is where
// we finalize the mappings from the input sections to the output
// section.
// Finalize the mappings from the input sections to the output
// section, and return the final data size.
template<typename Char_type>
void
Output_merge_string<Char_type>::set_final_data_size()
off_t
Output_merge_string<Char_type>::finalize_merged_data()
{
this->stringpool_.set_string_offsets();
@ -513,10 +512,18 @@ Output_merge_string<Char_type>::set_final_data_size()
this->add_mapping(p->object, p->shndx, p->offset, p->length,
this->stringpool_.get_offset(p->string));
this->set_data_size(this->stringpool_.get_strtab_size());
// Save some memory.
this->merged_strings_.clear();
return this->stringpool_.get_strtab_size();
}
template<typename Char_type>
void
Output_merge_string<Char_type>::set_final_data_size()
{
const off_t final_data_size = this->finalize_merged_data();
this->set_data_size(final_data_size);
}
// Write out a merged string section.

View File

@ -209,10 +209,16 @@ class Output_merge_string : public Output_merge_base
this->stringpool_.set_no_zero_null();
}
protected:
// Add an input section.
bool
do_add_input_section(Relobj* object, unsigned int shndx);
// Do all the final processing after the input sections are read in.
// Returns the final data size.
off_t
finalize_merged_data();
// Set the final data size.
void
set_final_data_size();
@ -221,6 +227,16 @@ class Output_merge_string : public Output_merge_base
void
do_write(Output_file*);
// Writes the stringpool to a buffer.
void
stringpool_to_buffer(char* buffer, size_t buffer_size)
{ this->stringpool_.write_to_buffer(buffer, buffer_size); }
// Clears all the data in the stringpool, to save on memory.
void
clear_stringpool()
{ stringpool_.clear(); }
private:
// As we see input sections, we build a mapping from object, section
// index and offset to strings.

View File

@ -376,6 +376,17 @@ options::Command_line_options::options[] =
&Position_dependent_options::set_static_search),
GENERAL_NOARG('\0', "Bsymbolic", N_("Bind defined symbols locally"),
NULL, ONE_DASH, &General_options::set_symbolic),
#ifdef HAVE_ZLIB_H
# define ZLIB_STR ",zlib"
#else
# define ZLIB_STR ""
#endif
GENERAL_ARG('\0', "compress-debug-sections",
N_("Compress .debug_* sections in the output file "
"(default is none)"),
N_("--compress-debug-sections=[none" ZLIB_STR "]"),
TWO_DASHES,
&General_options::set_compress_debug_symbols),
GENERAL_NOARG('\0', "demangle", N_("Demangle C++ symbols in log messages"),
NULL, TWO_DASHES, &General_options::set_demangle),
GENERAL_NOARG('\0', "no-demangle",
@ -525,6 +536,7 @@ General_options::General_options()
strip_(STRIP_NONE),
allow_shlib_undefined_(false),
symbolic_(false),
compress_debug_sections_(NO_COMPRESSION),
detect_odr_violations_(false),
create_eh_frame_hdr_(false),
rpath_(),

View File

@ -150,8 +150,8 @@ class General_options
strip_debug() const
{ return this->strip_ == STRIP_ALL || this->strip_ == STRIP_DEBUG; }
// -Sgdb: strip only debugging information that's not used by
// gdb (at least, for gdb versions <= 6.7).
// --strip-debug-gdb: strip only debugging information that's not
// used by gdb (at least, for gdb versions <= 6.7).
bool
strip_debug_gdb() const
{ return this->strip_debug() || this->strip_ == STRIP_DEBUG_UNUSED_BY_GDB; }
@ -167,6 +167,17 @@ class General_options
symbolic() const
{ return this->symbolic_; }
// --compress-debug-sections: compress .debug_* sections in the
// output file using the given compression method. This is useful
// when the tools (such as gdb) support compressed sections.
bool
compress_debug_sections() const
{ return this->compress_debug_sections_ != NO_COMPRESSION; }
bool
zlib_compress_debug_sections() const
{ return this->compress_debug_sections_ == ZLIB_COMPRESSION; }
// --demangle: demangle C++ symbols in our log messages.
bool
demangle() const
@ -288,6 +299,13 @@ class General_options
EXECSTACK_NO
};
// What compression method to use
enum CompressionMethod
{
NO_COMPRESSION,
ZLIB_COMPRESSION,
};
void
set_export_dynamic()
{ this->export_dynamic_ = true; }
@ -342,6 +360,19 @@ class General_options
set_symbolic()
{ this->symbolic_ = true; }
void set_compress_debug_symbols(const char* arg)
{
if (strcmp(arg, "none") == 0)
this->compress_debug_sections_ = NO_COMPRESSION;
#ifdef HAVE_ZLIB_H
else if (strcmp(arg, "zlib") == 0)
this->compress_debug_sections_ = ZLIB_COMPRESSION;
#endif
else
gold_fatal(_("Unsupported argument to --compress-debug-symbols: %s"),
arg);
}
void
set_demangle()
{ this->demangle_ = true; }
@ -476,6 +507,7 @@ class General_options
Strip strip_;
bool allow_shlib_undefined_;
bool symbolic_;
CompressionMethod compress_debug_sections_;
bool demangle_;
bool detect_odr_violations_;
bool create_eh_frame_hdr_;

View File

@ -32,6 +32,7 @@
#include "libiberty.h" // for unlink_if_ordinary()
#include "parameters.h"
#include "compressed_output.h"
#include "object.h"
#include "symtab.h"
#include "reloc.h"
@ -1033,9 +1034,11 @@ Output_section::Input_section::write(Output_file* of)
// Construct an Output_section. NAME will point into a Stringpool.
Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
Output_section::Output_section(const General_options& options,
const char* name, elfcpp::Elf_Word type,
elfcpp::Elf_Xword flags)
: name_(name),
: options_(options),
name_(name),
addralign_(0),
entsize_(0),
link_section_(NULL),
@ -1079,6 +1082,22 @@ Output_section::set_entsize(uint64_t v)
gold_assert(this->entsize_ == v);
}
// Sometimes we compress sections. This is typically done for
// sections that are not part of normal program execution (such as
// .debug_* sections), and where the readers of these sections know
// how to deal with compressed sections. (To make it easier for them,
// we will rename the ouput section in such cases from .foo to
// .foo.zlib.nnnn, where nnnn is the uncompressed size.) This routine
// doesn't say for certain whether we'll compress -- it depends on
// commandline options as well -- just whether this section is a
// candidate for compression.
static bool
is_compressible_section(const char* secname)
{
return (strncmp(secname, ".debug", sizeof(".debug") - 1) == 0);
}
// Add the input section SHNDX, with header SHDR, named SECNAME, in
// OBJECT, to the Output_section. RELOC_SHNDX is the index of a
// relocation section which applies to this section, or 0 if none, or
@ -1126,7 +1145,8 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object,
&& reloc_shndx == 0)
{
if (this->add_merge_input_section(object, shndx, sh_flags,
entsize, addralign))
entsize, addralign,
is_compressible_section(secname)))
{
// Tell the relocation routines that they need to call the
// output_offset method to determine the final address.
@ -1213,7 +1233,8 @@ Output_section::add_output_merge_section(Output_section_data* posd,
bool
Output_section::add_merge_input_section(Relobj* object, unsigned int shndx,
uint64_t flags, uint64_t entsize,
uint64_t addralign)
uint64_t addralign,
bool is_compressible_section)
{
bool is_string = (flags & elfcpp::SHF_STRINGS) != 0;
@ -1227,30 +1248,56 @@ Output_section::add_merge_input_section(Relobj* object, unsigned int shndx,
p != this->input_sections_.end();
++p)
if (p->is_merge_section(is_string, entsize, addralign))
break;
{
p->add_input_section(object, shndx);
return true;
}
// We handle the actual constant merging in Output_merge_data or
// Output_merge_string_data.
if (p != this->input_sections_.end())
p->add_input_section(object, shndx);
Output_section_data* posd;
if (!is_string)
posd = new Output_merge_data(entsize, addralign);
else if (is_compressible_section && options_.compress_debug_sections())
{
switch (entsize)
{
case 1:
posd = new Output_compressed_string<char>(addralign, this->options_);
break;
case 2:
posd = new Output_compressed_string<uint16_t>(addralign,
this->options_);
break;
case 4:
posd = new Output_compressed_string<uint32_t>(addralign,
this->options_);
break;
default:
return false;
}
}
else
{
Output_section_data* posd;
if (!is_string)
posd = new Output_merge_data(entsize, addralign);
else if (entsize == 1)
posd = new Output_merge_string<char>(addralign);
else if (entsize == 2)
posd = new Output_merge_string<uint16_t>(addralign);
else if (entsize == 4)
posd = new Output_merge_string<uint32_t>(addralign);
else
return false;
this->add_output_merge_section(posd, is_string, entsize);
posd->add_input_section(object, shndx);
switch (entsize)
{
case 1:
posd = new Output_merge_string<char>(addralign);
break;
case 2:
posd = new Output_merge_string<uint16_t>(addralign);
break;
case 4:
posd = new Output_merge_string<uint32_t>(addralign);
break;
default:
return false;
}
}
this->add_output_merge_section(posd, is_string, entsize);
posd->add_input_section(object, shndx);
return true;
}
@ -1367,6 +1414,29 @@ Output_section::set_final_data_size()
this->set_data_size(off - startoff);
}
// Ask each output_section_data member if it wants to change the name
// of the output section. If any of them says yes, use this to set
// the new name. This should be called after all processing of this
// output section is done, but before the name is finally committed to
// the output-section's header.
bool
Output_section::maybe_modify_output_section_name()
{
for (Input_section_list::const_iterator it = input_sections_.begin();
it != input_sections_.end();
++it)
{
const char* newname = it->modified_output_section_name(this->name());
if (newname != NULL)
{
this->set_name(newname);
return true;
}
}
return false;
}
// Write the section header to *OSHDR.
template<int size, bool big_endian>

View File

@ -432,6 +432,15 @@ class Output_section_data : public Output_data
add_input_section(Relobj* object, unsigned int shndx)
{ return this->do_add_input_section(object, shndx); }
// This class may change the output section name. This is called
// right before shstrtab is written, so after all input-section
// layout processing is done. The input is the old name, and the
// output should be a new name (which will be copied into permanent
// storage) to change the name, or NULL to keep the name as-is.
virtual const char*
do_modified_output_section_name(const char*)
{ return NULL; }
// Given an input OBJECT, an input section index SHNDX within that
// object, and an OFFSET relative to the start of that input
// section, return whether or not the corresponding offset within
@ -1308,7 +1317,8 @@ class Output_section : public Output_data
{
public:
// Create an output section, giving the name, type, and flags.
Output_section(const char* name, elfcpp::Elf_Word, elfcpp::Elf_Xword);
Output_section(const General_options& options,
const char* name, elfcpp::Elf_Word, elfcpp::Elf_Xword);
virtual ~Output_section();
// Add a new input section SHNDX, named NAME, with header SHDR, from
@ -1331,6 +1341,13 @@ class Output_section : public Output_data
name() const
{ return this->name_; }
// Modify the section name. This should be called only after this
// section is done being constructed. The input should be a pointer
// into layout's namepool_.
void
set_name(const char* newname)
{ this->name_ = newname; }
// Return the section type.
elfcpp::Elf_Word
type() const
@ -1518,6 +1535,16 @@ class Output_section : public Output_data
write_header(const Layout*, const Stringpool*,
elfcpp::Shdr_write<size, big_endian>*) const;
// This class may change the output section name. This is called
// right before shstrtab is written, so after all input-section
// layout processing is done. This calls
// do_modified_output_section_name() on all its output_section_data
// members, and changes the name if any member so suggests. If
// several members would suggest, this takes the first, arbitrarily.
// Return true if the name was modified, false else.
bool
maybe_modify_output_section_name();
protected:
// Return the section index in the output file.
unsigned int
@ -1663,6 +1690,15 @@ class Output_section : public Output_data
void
set_address(uint64_t addr, off_t off, off_t secoff);
// Call modified_output_section_name on the output-section-data object.
const char*
modified_output_section_name(const char* name) const
{
if (this->is_input_section())
return NULL;
return this->u2_.posd->do_modified_output_section_name(name);
}
// Add an input section, for SHF_MERGE sections.
bool
add_input_section(Relobj* object, unsigned int shndx)
@ -1777,7 +1813,8 @@ class Output_section : public Output_data
// handled.
bool
add_merge_input_section(Relobj* object, unsigned int shndx, uint64_t flags,
uint64_t entsize, uint64_t addralign);
uint64_t entsize, uint64_t addralign,
bool can_compress_section);
// Add an output SHF_MERGE section POSD to this output section.
// IS_STRING indicates whether it is a SHF_STRINGS section, and
@ -1789,8 +1826,10 @@ class Output_section : public Output_data
// Most of these fields are only valid after layout.
// General options.
const General_options& options_;
// The name of the section. This will point into a Stringpool.
const char* const name_;
const char* name_;
// The section address is in the parent class.
// The section alignment.
uint64_t addralign_;

View File

@ -2,6 +2,8 @@ archive.cc
archive.h
common.cc
common.h
compressed_output.cc
compressed_output.h
defstd.cc
defstd.h
dirsearch.cc

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-11-20 16:37-0800\n"
"POT-Creation-Date: 2007-11-29 16:33-0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -61,6 +61,10 @@ msgstr ""
msgid "%s: member at %zu is not an ELF object"
msgstr ""
#: compressed_output.cc:140
msgid "Not compressing section data: zlib error"
msgstr ""
#: dirsearch.cc:68
#, c-format
msgid "%s: can not read directory: %s"
@ -179,22 +183,22 @@ msgstr ""
msgid "symbol %s has undefined version %s"
msgstr ""
#: errors.cc:77
#: errors.cc:88
#, c-format
msgid "%s: warning: "
msgstr ""
#: errors.cc:112
#: errors.cc:127
#, c-format
msgid "%s: %s: warning: "
msgstr ""
#: errors.cc:136
#: errors.cc:154
#, c-format
msgid "%s: %s: undefined reference to '%s'\n"
msgstr ""
#: errors.cc:146
#: errors.cc:164
#, c-format
msgid "%s: "
msgstr ""
@ -271,62 +275,62 @@ msgstr ""
msgid "cannot mix -static with dynamic object %s"
msgstr ""
#: gold-threads.cc:69
#: gold-threads.cc:102
#, c-format
msgid "pthead_mutextattr_init failed: %s"
msgstr ""
#: gold-threads.cc:73
#: gold-threads.cc:106
#, c-format
msgid "pthread_mutextattr_settype failed: %s"
msgstr ""
#: gold-threads.cc:78
#: gold-threads.cc:111
#, c-format
msgid "pthread_mutex_init failed: %s"
msgstr ""
#: gold-threads.cc:82
#: gold-threads.cc:115
#, c-format
msgid "pthread_mutexattr_destroy failed: %s"
msgstr ""
#: gold-threads.cc:89
#: gold-threads.cc:122
#, c-format
msgid "pthread_mutex_destroy failed: %s"
msgstr ""
#: gold-threads.cc:97
#: gold-threads.cc:130
#, c-format
msgid "pthread_mutex_lock failed: %s"
msgstr ""
#: gold-threads.cc:105
#: gold-threads.cc:138
#, c-format
msgid "pthread_mutex_unlock failed: %s"
msgstr ""
#: gold-threads.cc:193
#: gold-threads.cc:219
#, c-format
msgid "pthread_cond_init failed: %s"
msgstr ""
#: gold-threads.cc:200
#: gold-threads.cc:226
#, c-format
msgid "pthread_cond_destroy failed: %s"
msgstr ""
#: gold-threads.cc:208
#: gold-threads.cc:235
#, c-format
msgid "pthread_cond_wait failed: %s"
msgstr ""
#: gold-threads.cc:216
#: gold-threads.cc:243
#, c-format
msgid "pthread_cond_signal failed: %s"
msgstr ""
#: gold-threads.cc:224
#: gold-threads.cc:251
#, c-format
msgid "pthread_cond_broadcast failed: %s"
msgstr ""
@ -371,11 +375,11 @@ msgstr ""
msgid "both SUN and GNU model TLS relocations"
msgstr ""
#: merge.cc:283
#: merge.cc:464
msgid "mergeable string section length not multiple of character size"
msgstr ""
#: merge.cc:299
#: merge.cc:480
msgid "entry in mergeable string section not null terminated"
msgstr ""
@ -419,7 +423,7 @@ msgstr ""
msgid "section %u in section group %u out of range"
msgstr ""
#: object.cc:534 reloc.cc:226 reloc.cc:493
#: object.cc:534 reloc.cc:229 reloc.cc:496
#, c-format
msgid "relocation section %u has bad info %u"
msgstr ""
@ -549,314 +553,331 @@ msgstr ""
msgid "Bind defined symbols locally"
msgstr ""
#: options.cc:379
msgid "Demangle C++ symbols in log messages"
msgstr ""
#: options.cc:382
msgid "Do not demangle C++ symbols in log messages"
msgstr ""
#: options.cc:385
msgid "Try to detect violations of the One Definition Rule"
msgid "Compress .debug_* sections in the output file (default is none)"
msgstr ""
#: options.cc:387
msgid "Export all dynamic symbols"
msgid "--compress-debug-sections=[none"
msgstr ""
#: options.cc:389
msgid "Create exception frame header"
#: options.cc:387
msgid "]"
msgstr ""
#: options.cc:391
msgid "Set dynamic linker path"
#: options.cc:390
msgid "Demangle C++ symbols in log messages"
msgstr ""
#: options.cc:392
msgid "-I PROGRAM, --dynamic-linker PROGRAM"
#: options.cc:393
msgid "Do not demangle C++ symbols in log messages"
msgstr ""
#: options.cc:394
msgid "Search for library LIBNAME"
msgstr ""
#: options.cc:395
msgid "-lLIBNAME, --library LIBNAME"
msgstr ""
#: options.cc:397
msgid "Add directory to search path"
#: options.cc:396
msgid "Try to detect violations of the One Definition Rule"
msgstr ""
#: options.cc:398
msgid "-L DIR, --library-path DIR"
msgid "Export all dynamic symbols"
msgstr ""
#: options.cc:400
msgid "Ignored for compatibility"
msgid "Create exception frame header"
msgstr ""
#: options.cc:402
msgid "Set output file name"
msgid "Set dynamic linker path"
msgstr ""
#: options.cc:403
msgid "-o FILE, --output FILE"
msgid "-I PROGRAM, --dynamic-linker PROGRAM"
msgstr ""
#: options.cc:405
msgid "Optimize output file size"
msgid "Search for library LIBNAME"
msgstr ""
#: options.cc:406
msgid "-O level"
msgid "-lLIBNAME, --library LIBNAME"
msgstr ""
#: options.cc:408
msgid "Generate relocatable output"
msgid "Add directory to search path"
msgstr ""
#: options.cc:410
msgid "Add DIR to runtime search path"
#: options.cc:409
msgid "-L DIR, --library-path DIR"
msgstr ""
#: options.cc:411
msgid "-R DIR, -rpath DIR"
msgid "Ignored for compatibility"
msgstr ""
#: options.cc:413
msgid "Set output file name"
msgstr ""
#: options.cc:414
msgid "Add DIR to link time shared library search path"
msgid "-o FILE, --output FILE"
msgstr ""
#: options.cc:415
msgid "--rpath-link DIR"
#: options.cc:416
msgid "Optimize output file size"
msgstr ""
#: options.cc:417
msgid "-O level"
msgstr ""
#: options.cc:419
msgid "Generate relocatable output"
msgstr ""
#: options.cc:421
msgid "Add DIR to runtime search path"
msgstr ""
#: options.cc:422
msgid "-R DIR, -rpath DIR"
msgstr ""
#: options.cc:425
msgid "Add DIR to link time shared library search path"
msgstr ""
#: options.cc:426
msgid "--rpath-link DIR"
msgstr ""
#: options.cc:428
msgid "Strip all symbols"
msgstr ""
#: options.cc:420
#: options.cc:431
msgid "Strip debug symbols that are unused by gdb (at least versions <= 6.7)"
msgstr ""
#. This must come after -Sdebug since it's a prefix of it.
#: options.cc:424
#: options.cc:435
msgid "Strip debugging information"
msgstr ""
#: options.cc:426
#: options.cc:437
msgid "Generate shared library"
msgstr ""
#: options.cc:428
#: options.cc:439
msgid "Do not link against shared libraries"
msgstr ""
#: options.cc:430
#: options.cc:441
msgid "Print resource usage statistics"
msgstr ""
#: options.cc:432
#: options.cc:443
msgid "Set target system root directory"
msgstr ""
#: options.cc:433
#: options.cc:444
msgid "--sysroot DIR"
msgstr ""
#: options.cc:434
#: options.cc:445
msgid "Set the address of the .text section"
msgstr ""
#: options.cc:435
#: options.cc:446
msgid "-Ttext ADDRESS"
msgstr ""
#. This must come after -Ttext since it's a prefix of it.
#: options.cc:438
#: options.cc:449
msgid "Read linker script"
msgstr ""
#: options.cc:439
#: options.cc:450
msgid "-T FILE, --script FILE"
msgstr ""
#: options.cc:441
#: options.cc:452
msgid "Run the linker multi-threaded"
msgstr ""
#: options.cc:443
#: options.cc:454
msgid "Do not run the linker multi-threaded"
msgstr ""
#: options.cc:445
#: options.cc:456
msgid "Number of threads to use"
msgstr ""
#: options.cc:446
#: options.cc:457
msgid "--thread-count COUNT"
msgstr ""
#: options.cc:449
#: options.cc:460
msgid "Number of threads to use in initial pass"
msgstr ""
#: options.cc:450
#: options.cc:461
msgid "--thread-count-initial COUNT"
msgstr ""
#: options.cc:453
#: options.cc:464
msgid "Number of threads to use in middle pass"
msgstr ""
#: options.cc:454
#: options.cc:465
msgid "--thread-count-middle COUNT"
msgstr ""
#: options.cc:457
#: options.cc:468
msgid "Number of threads to use in final pass"
msgstr ""
#: options.cc:458
#: options.cc:469
msgid "--thread-count-final COUNT"
msgstr ""
#: options.cc:461
#: options.cc:472
msgid "Include all archive contents"
msgstr ""
#: options.cc:465
#: options.cc:476
msgid "Include only needed archive contents"
msgstr ""
#: options.cc:470
#: options.cc:481
msgid ""
"Subcommands as follows:\n"
" -z execstack Mark output as requiring executable stack\n"
" -z noexecstack Mark output as not requiring executable stack"
msgstr ""
#: options.cc:473
#: options.cc:484
msgid "-z SUBCOMMAND"
msgstr ""
#: options.cc:476
#: options.cc:487
msgid "Start a library search group"
msgstr ""
#: options.cc:478
#: options.cc:489
msgid "End a library search group"
msgstr ""
#: options.cc:480
#: options.cc:491
msgid "Report usage information"
msgstr ""
#: options.cc:482
#: options.cc:493
msgid "Report version information"
msgstr ""
#: options.cc:484
#: options.cc:495
msgid "Turn on debugging (all,task)"
msgstr ""
#: options.cc:485
#: options.cc:496
msgid "--debug=TYPE"
msgstr ""
#: options.cc:578
#: options.cc:590
#, c-format
msgid "%s: unrecognized -z subcommand: %s\n"
msgstr ""
#: options.cc:601
#: options.cc:613
#, c-format
msgid "%s: unrecognized --debug subcommand: %s\n"
msgstr ""
#: options.cc:781
#: options.cc:793
msgid "unexpected argument"
msgstr ""
#: options.cc:788 options.cc:840 options.cc:921
#: options.cc:800 options.cc:852 options.cc:933
msgid "missing argument"
msgstr ""
#: options.cc:801 options.cc:849
#: options.cc:813 options.cc:861
msgid "unknown option"
msgstr ""
#: options.cc:867
#: options.cc:879
#, c-format
msgid "%s: missing group end\n"
msgstr ""
#: options.cc:995
#: options.cc:1007
msgid "may not nest groups"
msgstr ""
#: options.cc:1005
#: options.cc:1017
msgid "group end without group start"
msgstr ""
#: options.cc:1015
#: options.cc:1027
#, c-format
msgid "%s: use the --help option for usage information\n"
msgstr ""
#: options.cc:1024
#: options.cc:1036
#, c-format
msgid "%s: %s: %s\n"
msgstr ""
#: options.cc:1033
#: options.cc:1045
#, c-format
msgid "%s: -%c: %s\n"
msgstr ""
#: options.h:393
#: options.h:372
#, c-format
msgid "Unsupported argument to --compress-debug-symbols: %s"
msgstr ""
#: options.h:424
#, c-format
msgid "%s: invalid argument to -Ttext: %s\n"
msgstr ""
#: options.h:406
#: options.h:437
#, c-format
msgid "%s: invalid thread count: %s\n"
msgstr ""
#: output.cc:1108
#: output.cc:1122
#, c-format
msgid "invalid alignment %lu for section \"%s\""
msgstr ""
#: output.cc:1870
#: output.cc:1941
#, c-format
msgid "%s: open: %s"
msgstr ""
#: output.cc:1875
#, c-format
msgid "%s: lseek: %s"
msgstr ""
#: output.cc:1878
#, c-format
msgid "%s: write: %s"
msgstr ""
#: output.cc:1884
#, c-format
msgid "%s: mmap: %s"
msgstr ""
#: output.cc:1894
#: output.cc:1953 output.cc:1986
#, c-format
msgid "%s: munmap: %s"
msgstr ""
#: output.cc:1898
#: output.cc:1967
#, c-format
msgid "%s: lseek: %s"
msgstr ""
#: output.cc:1970
#, c-format
msgid "%s: write: %s"
msgstr ""
#: output.cc:1976
#, c-format
msgid "%s: mmap: %s"
msgstr ""
#: output.cc:1990
#, c-format
msgid "%s: close: %s"
msgstr ""
@ -877,22 +898,22 @@ msgstr ""
msgid "%s: not an object or archive"
msgstr ""
#: reloc.cc:245 reloc.cc:511
#: reloc.cc:248 reloc.cc:514
#, c-format
msgid "relocation section %u uses unexpected symbol table %u"
msgstr ""
#: reloc.cc:260 reloc.cc:529
#: reloc.cc:263 reloc.cc:532
#, c-format
msgid "unexpected entsize for reloc section %u: %lu != %u"
msgstr ""
#: reloc.cc:269 reloc.cc:538
#: reloc.cc:272 reloc.cc:541
#, c-format
msgid "reloc section %u size %lu uneven"
msgstr ""
#: reloc.cc:729
#: reloc.cc:732
#, c-format
msgid "reloc section size %zu is not a multiple of reloc size %d\n"
msgstr ""
@ -934,41 +955,41 @@ msgid ""
"T"
msgstr ""
#: symtab.cc:576
#: symtab.cc:597
#, c-format
msgid "bad global symbol name offset %u at %zu"
msgstr ""
#: symtab.cc:654
#: symtab.cc:675
msgid "too few symbol versions"
msgstr ""
#: symtab.cc:683
#: symtab.cc:704
#, c-format
msgid "bad symbol name offset %u at %zu"
msgstr ""
#: symtab.cc:737
#: symtab.cc:758
#, c-format
msgid "versym for symbol %zu out of range: %u"
msgstr ""
#: symtab.cc:745
#: symtab.cc:766
#, c-format
msgid "versym for symbol %zu has no name: %u"
msgstr ""
#: symtab.cc:1463 symtab.cc:1676
#: symtab.cc:1484 symtab.cc:1697
#, c-format
msgid "%s: unsupported symbol section 0x%x"
msgstr ""
#: symtab.cc:1800
#: symtab.cc:1821
#, c-format
msgid "%s: undefined reference to '%s'"
msgstr ""
#: symtab.cc:1941
#: symtab.cc:1962
#, c-format
msgid ""
"while linking %s: symbol '%s' defined in multiple places (possible ODR "
@ -1003,7 +1024,12 @@ msgid ""
"This program has absolutely no warranty.\n"
msgstr ""
#: workqueue-threads.cc:106
#: workqueue.cc:484
#, c-format
msgid "gold task queue:\n"
msgstr ""
#: workqueue-threads.cc:107
#, c-format
msgid "%s failed: %s"
msgstr ""

View File

@ -41,12 +41,21 @@ Stringpool_template<Stringpool_char>::Stringpool_template()
}
template<typename Stringpool_char>
Stringpool_template<Stringpool_char>::~Stringpool_template()
void
Stringpool_template<Stringpool_char>::clear()
{
for (typename std::list<Stringdata*>::iterator p = this->strings_.begin();
p != this->strings_.end();
++p)
delete[] reinterpret_cast<char*>(*p);
this->strings_.clear();
this->string_set_.clear();
}
template<typename Stringpool_char>
Stringpool_template<Stringpool_char>::~Stringpool_template()
{
this->clear();
}
// Return the length of a string of arbitrary character type.
@ -413,6 +422,28 @@ Stringpool_template<Stringpool_char>::get_offset(const Stringpool_char* s)
gold_unreachable();
}
// Write the ELF strtab into the buffer.
template<typename Stringpool_char>
void
Stringpool_template<Stringpool_char>::write_to_buffer(char* buffer,
size_t bufsize)
{
gold_assert(this->strtab_size_ != 0);
if (bufsize < this->strtab_size_) // Quiet the compiler in opt mode.
gold_assert(bufsize >= this->strtab_size_);
if (this->zero_null_)
buffer[0] = '\0';
for (typename String_set_type::const_iterator p = this->string_set_.begin();
p != this->string_set_.end();
++p)
{
const int len = (string_length(p->first) + 1) * sizeof(Stringpool_char);
gold_assert(p->second.second + len <= this->strtab_size_);
memcpy(buffer + p->second.second, p->first, len);
}
}
// Write the ELF strtab into the output file at the specified offset.
template<typename Stringpool_char>
@ -420,16 +451,9 @@ void
Stringpool_template<Stringpool_char>::write(Output_file* of, off_t offset)
{
gold_assert(this->strtab_size_ != 0);
unsigned char* viewu = of->get_output_view(offset, this->strtab_size_);
char* view = reinterpret_cast<char*>(viewu);
if (this->zero_null_)
view[0] = '\0';
for (typename String_set_type::const_iterator p = this->string_set_.begin();
p != this->string_set_.end();
++p)
memcpy(view + p->second.second, p->first,
(string_length(p->first) + 1) * sizeof(Stringpool_char));
of->write_output_view(offset, this->strtab_size_, viewu);
unsigned char* view = of->get_output_view(offset, this->strtab_size_);
this->write_to_buffer(reinterpret_cast<char*>(view), this->strtab_size_);
of->write_output_view(offset, this->strtab_size_, view);
}
// Instantiate the templates we need.

View File

@ -84,6 +84,10 @@ class Stringpool_template
~Stringpool_template();
// Clear all the data from the stringpool.
void
clear();
// Indicate that we should not reserve offset 0 to hold the empty
// string when converting the stringpool to a string table. This
// should not be called for a proper ELF SHT_STRTAB section.
@ -139,6 +143,12 @@ class Stringpool_template
void
write(Output_file*, off_t offset);
// Write the string table into the specified buffer, of the
// specified size. buffer_size should be at least
// get_strtab_size().
void
write_to_buffer(char* buffer, size_t buffer_size);
private:
Stringpool_template(const Stringpool_template&);
Stringpool_template& operator=(const Stringpool_template&);

View File

@ -445,6 +445,7 @@ CATOBJEXT = @CATOBJEXT@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@