mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 03:54:41 +08:00
From Craig Silverstein: Add support for compressing .debug_str section.
This commit is contained in:
parent
71195202df
commit
9a0910c33e
@ -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 \
|
||||
|
@ -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
267
gold/compressed_output.cc
Normal 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
137
gold/compressed_output.h
Normal 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)
|
@ -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
1028
gold/configure
vendored
File diff suppressed because it is too large
Load Diff
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
16
gold/merge.h
16
gold/merge.h
@ -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.
|
||||
|
@ -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_(),
|
||||
|
@ -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_;
|
||||
|
112
gold/output.cc
112
gold/output.cc
@ -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>
|
||||
|
@ -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_;
|
||||
|
@ -2,6 +2,8 @@ archive.cc
|
||||
archive.h
|
||||
common.cc
|
||||
common.h
|
||||
compressed_output.cc
|
||||
compressed_output.h
|
||||
defstd.cc
|
||||
defstd.h
|
||||
dirsearch.cc
|
||||
|
296
gold/po/gold.pot
296
gold/po/gold.pot
@ -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 ""
|
||||
|
@ -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.
|
||||
|
@ -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&);
|
||||
|
@ -445,6 +445,7 @@ CATOBJEXT = @CATOBJEXT@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
|
Loading…
Reference in New Issue
Block a user