Fully implement the SECTIONS clause.
This commit is contained in:
parent
d16c732117
commit
a445fddf82
24 changed files with 3087 additions and 441 deletions
|
@ -131,6 +131,10 @@ class Elf_file
|
||||||
typename File::Location
|
typename File::Location
|
||||||
section_contents(unsigned int shndx);
|
section_contents(unsigned int shndx);
|
||||||
|
|
||||||
|
// Return the size of section SHNDX.
|
||||||
|
typename Elf_types<size>::Elf_WXword
|
||||||
|
section_size(unsigned int shndx);
|
||||||
|
|
||||||
// Return the flags of section SHNDX.
|
// Return the flags of section SHNDX.
|
||||||
typename Elf_types<size>::Elf_WXword
|
typename Elf_types<size>::Elf_WXword
|
||||||
section_flags(unsigned int shndx);
|
section_flags(unsigned int shndx);
|
||||||
|
@ -147,6 +151,9 @@ class Elf_file
|
||||||
Elf_Word
|
Elf_Word
|
||||||
section_info(unsigned int shndx);
|
section_info(unsigned int shndx);
|
||||||
|
|
||||||
|
// Return the addralign field of section SHNDX.
|
||||||
|
typename Elf_types<size>::Elf_WXword
|
||||||
|
section_addralign(unsigned int shndx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Shared constructor code.
|
// Shared constructor code.
|
||||||
|
@ -296,6 +303,25 @@ Elf_file<size, big_endian, File>::section_contents(unsigned int shndx)
|
||||||
return typename File::Location(shdr.get_sh_offset(), shdr.get_sh_size());
|
return typename File::Location(shdr.get_sh_offset(), shdr.get_sh_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the size of section SHNDX.
|
||||||
|
|
||||||
|
template<int size, bool big_endian, typename File>
|
||||||
|
typename Elf_types<size>::Elf_WXword
|
||||||
|
Elf_file<size, big_endian, File>::section_size(unsigned int shndx)
|
||||||
|
{
|
||||||
|
File* const file = this->file_;
|
||||||
|
|
||||||
|
if (shndx >= this->shnum())
|
||||||
|
file->error(_("section_size: bad shndx %u >= %u"),
|
||||||
|
shndx, this->shnum());
|
||||||
|
|
||||||
|
typename File::View v(file->view(this->section_header_offset(shndx),
|
||||||
|
This::shdr_size));
|
||||||
|
|
||||||
|
Ef_shdr shdr(v.data());
|
||||||
|
return shdr.get_sh_size();
|
||||||
|
}
|
||||||
|
|
||||||
// Return the section flags of section SHNDX.
|
// Return the section flags of section SHNDX.
|
||||||
|
|
||||||
template<int size, bool big_endian, typename File>
|
template<int size, bool big_endian, typename File>
|
||||||
|
@ -372,6 +398,25 @@ Elf_file<size, big_endian, File>::section_info(unsigned int shndx)
|
||||||
return shdr.get_sh_info();
|
return shdr.get_sh_info();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the sh_addralign field of section SHNDX.
|
||||||
|
|
||||||
|
template<int size, bool big_endian, typename File>
|
||||||
|
typename Elf_types<size>::Elf_WXword
|
||||||
|
Elf_file<size, big_endian, File>::section_addralign(unsigned int shndx)
|
||||||
|
{
|
||||||
|
File* const file = this->file_;
|
||||||
|
|
||||||
|
if (shndx >= this->shnum())
|
||||||
|
file->error(_("section_addralign: bad shndx %u >= %u"),
|
||||||
|
shndx, this->shnum());
|
||||||
|
|
||||||
|
typename File::View v(file->view(this->section_header_offset(shndx),
|
||||||
|
This::shdr_size));
|
||||||
|
|
||||||
|
Ef_shdr shdr(v.data());
|
||||||
|
return shdr.get_sh_addralign();
|
||||||
|
}
|
||||||
|
|
||||||
} // End namespace elfcpp.
|
} // End namespace elfcpp.
|
||||||
|
|
||||||
#endif // !defined(ELFCPP_FILE_H)
|
#endif // !defined(ELFCPP_FILE_H)
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "gold.h"
|
#include "gold.h"
|
||||||
|
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
|
#include "layout.h"
|
||||||
#include "defstd.h"
|
#include "defstd.h"
|
||||||
|
|
||||||
// This is a simple file which defines the standard symbols like
|
// This is a simple file which defines the standard symbols like
|
||||||
|
@ -251,8 +252,11 @@ namespace gold
|
||||||
void
|
void
|
||||||
define_standard_symbols(Symbol_table* symtab, const Layout* layout)
|
define_standard_symbols(Symbol_table* symtab, const Layout* layout)
|
||||||
{
|
{
|
||||||
symtab->define_symbols(layout, in_section_count, in_section);
|
bool saw_sections_clause = layout->script_options()->saw_sections_clause();
|
||||||
symtab->define_symbols(layout, in_segment_count, in_segment);
|
symtab->define_symbols(layout, in_section_count, in_section,
|
||||||
|
saw_sections_clause);
|
||||||
|
symtab->define_symbols(layout, in_segment_count, in_segment,
|
||||||
|
saw_sections_clause);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // End namespace gold.
|
} // End namespace gold.
|
||||||
|
|
|
@ -176,6 +176,11 @@ class Sized_dynobj : public Dynobj
|
||||||
void
|
void
|
||||||
do_add_symbols(Symbol_table*, Read_symbols_data*);
|
do_add_symbols(Symbol_table*, Read_symbols_data*);
|
||||||
|
|
||||||
|
// Get the size of a section.
|
||||||
|
uint64_t
|
||||||
|
do_section_size(unsigned int shndx)
|
||||||
|
{ return this->elf_file_.section_size(shndx); }
|
||||||
|
|
||||||
// Get the name of a section.
|
// Get the name of a section.
|
||||||
std::string
|
std::string
|
||||||
do_section_name(unsigned int shndx)
|
do_section_name(unsigned int shndx)
|
||||||
|
@ -207,6 +212,11 @@ class Sized_dynobj : public Dynobj
|
||||||
do_section_info(unsigned int shndx)
|
do_section_info(unsigned int shndx)
|
||||||
{ return this->elf_file_.section_info(shndx); }
|
{ return this->elf_file_.section_info(shndx); }
|
||||||
|
|
||||||
|
// Return the section alignment.
|
||||||
|
uint64_t
|
||||||
|
do_section_addralign(unsigned int shndx)
|
||||||
|
{ return this->elf_file_.section_addralign(shndx); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// For convenience.
|
// For convenience.
|
||||||
typedef Sized_dynobj<size, big_endian> This;
|
typedef Sized_dynobj<size, big_endian> This;
|
||||||
|
|
|
@ -36,24 +36,75 @@ namespace gold
|
||||||
|
|
||||||
// This file holds the code which handles linker expressions.
|
// This file holds the code which handles linker expressions.
|
||||||
|
|
||||||
|
// The dot symbol, which linker scripts refer to simply as ".",
|
||||||
|
// requires special treatment. The dot symbol is set several times,
|
||||||
|
// section addresses will refer to it, output sections will change it,
|
||||||
|
// and it can be set based on the value of other symbols. We simplify
|
||||||
|
// the handling by prohibiting setting the dot symbol to the value of
|
||||||
|
// a non-absolute symbol.
|
||||||
|
|
||||||
// When evaluating the value of an expression, we pass in a pointer to
|
// When evaluating the value of an expression, we pass in a pointer to
|
||||||
// this struct, so that the expression evaluation can find the
|
// this struct, so that the expression evaluation can find the
|
||||||
// information it needs.
|
// information it needs.
|
||||||
|
|
||||||
struct Expression::Expression_eval_info
|
struct Expression::Expression_eval_info
|
||||||
{
|
{
|
||||||
|
// The symbol table.
|
||||||
const Symbol_table* symtab;
|
const Symbol_table* symtab;
|
||||||
|
// The layout--we use this to get section information.
|
||||||
const Layout* layout;
|
const Layout* layout;
|
||||||
|
// Whether expressions can refer to the dot symbol. The dot symbol
|
||||||
|
// is only available within a SECTIONS clause.
|
||||||
|
bool is_dot_available;
|
||||||
|
// Whether the dot symbol currently has a value.
|
||||||
|
bool dot_has_value;
|
||||||
|
// The current value of the dot symbol.
|
||||||
|
uint64_t dot_value;
|
||||||
|
// Points to the IS_ABSOLUTE variable, which is set to false if the
|
||||||
|
// expression uses a value which is not absolute.
|
||||||
|
bool* is_absolute;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Evaluate an expression.
|
// Evaluate an expression.
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
Expression::eval(const Symbol_table* symtab, const Layout* layout)
|
Expression::eval(const Symbol_table* symtab, const Layout* layout)
|
||||||
|
{
|
||||||
|
bool dummy;
|
||||||
|
return this->eval_maybe_dot(symtab, layout, false, false, 0, &dummy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Evaluate an expression which may refer to the dot symbol.
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
Expression::eval_with_dot(const Symbol_table* symtab, const Layout* layout,
|
||||||
|
bool dot_has_value, uint64_t dot_value,
|
||||||
|
bool* is_absolute)
|
||||||
|
{
|
||||||
|
return this->eval_maybe_dot(symtab, layout, true, dot_has_value, dot_value,
|
||||||
|
is_absolute);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Evaluate an expression which may or may not refer to the dot
|
||||||
|
// symbol.
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
Expression::eval_maybe_dot(const Symbol_table* symtab, const Layout* layout,
|
||||||
|
bool is_dot_available, bool dot_has_value,
|
||||||
|
uint64_t dot_value, bool* is_absolute)
|
||||||
{
|
{
|
||||||
Expression_eval_info eei;
|
Expression_eval_info eei;
|
||||||
eei.symtab = symtab;
|
eei.symtab = symtab;
|
||||||
eei.layout = layout;
|
eei.layout = layout;
|
||||||
|
eei.is_dot_available = is_dot_available;
|
||||||
|
eei.dot_has_value = dot_has_value;
|
||||||
|
eei.dot_value = dot_value;
|
||||||
|
|
||||||
|
// We assume the value is absolute, and only set this to false if we
|
||||||
|
// find a section relative reference.
|
||||||
|
*is_absolute = true;
|
||||||
|
eei.is_absolute = is_absolute;
|
||||||
|
|
||||||
return this->value(&eei);
|
return this->value(&eei);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,6 +166,14 @@ Symbol_expression::value(const Expression_eval_info* eei)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this symbol does not have an absolute value, then the whole
|
||||||
|
// expression does not have an absolute value. This is not strictly
|
||||||
|
// accurate: the subtraction of two symbols in the same section is
|
||||||
|
// absolute. This is unlikely to matter in practice, as this value
|
||||||
|
// is only used for error checking.
|
||||||
|
if (!sym->value_is_absolute())
|
||||||
|
*eei->is_absolute = false;
|
||||||
|
|
||||||
if (parameters->get_size() == 32)
|
if (parameters->get_size() == 32)
|
||||||
return eei->symtab->get_sized_symbol<32>(sym)->value();
|
return eei->symtab->get_sized_symbol<32>(sym)->value();
|
||||||
else if (parameters->get_size() == 64)
|
else if (parameters->get_size() == 64)
|
||||||
|
@ -141,10 +200,21 @@ class Dot_expression : public Expression
|
||||||
};
|
};
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
Dot_expression::value(const Expression_eval_info*)
|
Dot_expression::value(const Expression_eval_info* eei)
|
||||||
{
|
{
|
||||||
gold_error("dot symbol unimplemented");
|
if (!eei->is_dot_available)
|
||||||
|
{
|
||||||
|
gold_error(_("invalid reference to dot symbol outside of "
|
||||||
|
"SECTIONS clause"));
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
else if (!eei->dot_has_value)
|
||||||
|
{
|
||||||
|
gold_error(_("invalid reference to dot symbol before "
|
||||||
|
"it has been given a value"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return eei->dot_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A string. This is either the name of a symbol, or ".".
|
// A string. This is either the name of a symbol, or ".".
|
||||||
|
@ -549,6 +619,10 @@ Addr_expression::value(const Expression_eval_info* eei)
|
||||||
section_name);
|
section_name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note that the address of a section is an absolute address, and we
|
||||||
|
// should not clear *EEI->IS_ABSOLUTE here.
|
||||||
|
|
||||||
return os->address();
|
return os->address();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -198,17 +198,16 @@ queue_middle_tasks(const General_options& options,
|
||||||
// handles some cases we want to see before we read the relocs.
|
// handles some cases we want to see before we read the relocs.
|
||||||
layout->create_initial_dynamic_sections(symtab);
|
layout->create_initial_dynamic_sections(symtab);
|
||||||
|
|
||||||
// Predefine standard symbols. This should be fast, so we don't
|
// Define symbols from any linker scripts.
|
||||||
// bother to create a task for it.
|
layout->define_script_symbols(symtab);
|
||||||
|
|
||||||
|
// Predefine standard symbols.
|
||||||
define_standard_symbols(symtab, layout);
|
define_standard_symbols(symtab, layout);
|
||||||
|
|
||||||
// Define __start and __stop symbols for output sections where
|
// Define __start and __stop symbols for output sections where
|
||||||
// appropriate.
|
// appropriate.
|
||||||
layout->define_section_symbols(symtab);
|
layout->define_section_symbols(symtab);
|
||||||
|
|
||||||
// Define symbols from any linker scripts.
|
|
||||||
layout->define_script_symbols(symtab);
|
|
||||||
|
|
||||||
// Read the relocations of the input files. We do this to find
|
// Read the relocations of the input files. We do this to find
|
||||||
// which symbols are used by relocations which require a GOT and/or
|
// which symbols are used by relocations which require a GOT and/or
|
||||||
// a PLT entry, or a COPY reloc. When we implement garbage
|
// a PLT entry, or a COPY reloc. When we implement garbage
|
||||||
|
|
356
gold/layout.cc
356
gold/layout.cc
|
@ -29,6 +29,8 @@
|
||||||
|
|
||||||
#include "parameters.h"
|
#include "parameters.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
#include "script.h"
|
||||||
|
#include "script-sections.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
#include "dynobj.h"
|
#include "dynobj.h"
|
||||||
|
@ -185,11 +187,11 @@ Layout::include_section(Sized_relobj<size, big_endian>*, const char* name,
|
||||||
Output_section*
|
Output_section*
|
||||||
Layout::find_output_section(const char* name) const
|
Layout::find_output_section(const char* name) const
|
||||||
{
|
{
|
||||||
for (Section_name_map::const_iterator p = this->section_name_map_.begin();
|
for (Section_list::const_iterator p = this->section_list_.begin();
|
||||||
p != this->section_name_map_.end();
|
p != this->section_list_.end();
|
||||||
++p)
|
++p)
|
||||||
if (strcmp(p->second->name(), name) == 0)
|
if (strcmp((*p)->name(), name) == 0)
|
||||||
return p->second;
|
return *p;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,19 +213,13 @@ Layout::find_output_segment(elfcpp::PT type, elfcpp::Elf_Word set,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the output section to use for section NAME with type TYPE
|
// Return the output section to use for section NAME with type TYPE
|
||||||
// and section flags FLAGS.
|
// and section flags FLAGS. NAME must be canonicalized in the string
|
||||||
|
// pool, and NAME_KEY is the key.
|
||||||
|
|
||||||
Output_section*
|
Output_section*
|
||||||
Layout::get_output_section(const char* name, Stringpool::Key name_key,
|
Layout::get_output_section(const char* name, Stringpool::Key name_key,
|
||||||
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags)
|
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags)
|
||||||
{
|
{
|
||||||
// We should ignore some flags.
|
|
||||||
flags &= ~ (elfcpp::SHF_INFO_LINK
|
|
||||||
| elfcpp::SHF_LINK_ORDER
|
|
||||||
| elfcpp::SHF_GROUP
|
|
||||||
| elfcpp::SHF_MERGE
|
|
||||||
| elfcpp::SHF_STRINGS);
|
|
||||||
|
|
||||||
const Key key(name_key, std::make_pair(type, flags));
|
const Key key(name_key, std::make_pair(type, flags));
|
||||||
const std::pair<Key, Output_section*> v(key, NULL);
|
const std::pair<Key, Output_section*> v(key, NULL);
|
||||||
std::pair<Section_name_map::iterator, bool> ins(
|
std::pair<Section_name_map::iterator, bool> ins(
|
||||||
|
@ -241,6 +237,80 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pick the output section to use for section NAME, in input file
|
||||||
|
// RELOBJ, with type TYPE and flags FLAGS. RELOBJ may be NULL for a
|
||||||
|
// linker created section. ADJUST_NAME is true if we should apply the
|
||||||
|
// standard name mappings in Layout::output_section_name. This will
|
||||||
|
// return NULL if the input section should be discarded.
|
||||||
|
|
||||||
|
Output_section*
|
||||||
|
Layout::choose_output_section(const Relobj* relobj, const char* name,
|
||||||
|
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
|
||||||
|
bool adjust_name)
|
||||||
|
{
|
||||||
|
// We should ignore some flags. FIXME: This will need some
|
||||||
|
// adjustment for ld -r.
|
||||||
|
flags &= ~ (elfcpp::SHF_INFO_LINK
|
||||||
|
| elfcpp::SHF_LINK_ORDER
|
||||||
|
| elfcpp::SHF_GROUP
|
||||||
|
| elfcpp::SHF_MERGE
|
||||||
|
| elfcpp::SHF_STRINGS);
|
||||||
|
|
||||||
|
if (this->script_options_->saw_sections_clause())
|
||||||
|
{
|
||||||
|
// We are using a SECTIONS clause, so the output section is
|
||||||
|
// chosen based only on the name.
|
||||||
|
|
||||||
|
Script_sections* ss = this->script_options_->script_sections();
|
||||||
|
const char* file_name = relobj == NULL ? NULL : relobj->name().c_str();
|
||||||
|
Output_section** output_section_slot;
|
||||||
|
name = ss->output_section_name(file_name, name, &output_section_slot);
|
||||||
|
if (name == NULL)
|
||||||
|
{
|
||||||
|
// The SECTIONS clause says to discard this input section.
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is an orphan section--one not mentioned in the linker
|
||||||
|
// script--then OUTPUT_SECTION_SLOT will be NULL, and we do the
|
||||||
|
// default processing below.
|
||||||
|
|
||||||
|
if (output_section_slot != NULL)
|
||||||
|
{
|
||||||
|
if (*output_section_slot != NULL)
|
||||||
|
return *output_section_slot;
|
||||||
|
|
||||||
|
// We don't put sections found in the linker script into
|
||||||
|
// SECTION_NAME_MAP_. That keeps us from getting confused
|
||||||
|
// if an orphan section is mapped to a section with the same
|
||||||
|
// name as one in the linker script.
|
||||||
|
|
||||||
|
name = this->namepool_.add(name, false, NULL);
|
||||||
|
|
||||||
|
Output_section* os = this->make_output_section(name, type, flags);
|
||||||
|
os->set_found_in_sections_clause();
|
||||||
|
*output_section_slot = os;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Handle SHF_OS_NONCONFORMING somewhere.
|
||||||
|
|
||||||
|
// Turn NAME from the name of the input section into the name of the
|
||||||
|
// output section.
|
||||||
|
|
||||||
|
size_t len = strlen(name);
|
||||||
|
if (adjust_name && !parameters->output_is_object())
|
||||||
|
name = Layout::output_section_name(name, &len);
|
||||||
|
|
||||||
|
Stringpool::Key name_key;
|
||||||
|
name = this->namepool_.add_with_length(name, len, true, &name_key);
|
||||||
|
|
||||||
|
// Find or make the output section. The output section is selected
|
||||||
|
// based on the section name, type, and flags.
|
||||||
|
return this->get_output_section(name, name_key, type, flags);
|
||||||
|
}
|
||||||
|
|
||||||
// Return the output section to use for input section SHNDX, with name
|
// Return the output section to use for input section SHNDX, with name
|
||||||
// NAME, with header HEADER, from object OBJECT. RELOC_SHNDX is the
|
// NAME, with header HEADER, from object OBJECT. RELOC_SHNDX is the
|
||||||
// index of a relocation section which applies to this section, or 0
|
// index of a relocation section which applies to this section, or 0
|
||||||
|
@ -260,27 +330,18 @@ Layout::layout(Sized_relobj<size, big_endian>* object, unsigned int shndx,
|
||||||
if (!this->include_section(object, name, shdr))
|
if (!this->include_section(object, name, shdr))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// If we are not doing a relocateable link, choose the name to use
|
Output_section* os = this->choose_output_section(object,
|
||||||
// for the output section.
|
name,
|
||||||
size_t len = strlen(name);
|
|
||||||
if (!parameters->output_is_object())
|
|
||||||
name = Layout::output_section_name(name, &len);
|
|
||||||
|
|
||||||
// FIXME: Handle SHF_OS_NONCONFORMING here.
|
|
||||||
|
|
||||||
// Canonicalize the section name.
|
|
||||||
Stringpool::Key name_key;
|
|
||||||
name = this->namepool_.add_with_length(name, len, true, &name_key);
|
|
||||||
|
|
||||||
// Find the output section. The output section is selected based on
|
|
||||||
// the section name, type, and flags.
|
|
||||||
Output_section* os = this->get_output_section(name, name_key,
|
|
||||||
shdr.get_sh_type(),
|
shdr.get_sh_type(),
|
||||||
shdr.get_sh_flags());
|
shdr.get_sh_flags(),
|
||||||
|
true);
|
||||||
|
if (os == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// FIXME: Handle SHF_LINK_ORDER somewhere.
|
// FIXME: Handle SHF_LINK_ORDER somewhere.
|
||||||
|
|
||||||
*off = os->add_input_section(object, shndx, name, shdr, reloc_shndx);
|
*off = os->add_input_section(object, shndx, name, shdr, reloc_shndx,
|
||||||
|
this->script_options_->saw_sections_clause());
|
||||||
|
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
@ -304,12 +365,14 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
|
||||||
gold_assert(shdr.get_sh_type() == elfcpp::SHT_PROGBITS);
|
gold_assert(shdr.get_sh_type() == elfcpp::SHT_PROGBITS);
|
||||||
gold_assert(shdr.get_sh_flags() == elfcpp::SHF_ALLOC);
|
gold_assert(shdr.get_sh_flags() == elfcpp::SHF_ALLOC);
|
||||||
|
|
||||||
Stringpool::Key name_key;
|
const char* const name = ".eh_frame";
|
||||||
const char* name = this->namepool_.add(".eh_frame", false, &name_key);
|
Output_section* os = this->choose_output_section(object,
|
||||||
|
name,
|
||||||
Output_section* os = this->get_output_section(name, name_key,
|
|
||||||
elfcpp::SHT_PROGBITS,
|
elfcpp::SHT_PROGBITS,
|
||||||
elfcpp::SHF_ALLOC);
|
elfcpp::SHF_ALLOC,
|
||||||
|
false);
|
||||||
|
if (os == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (this->eh_frame_section_ == NULL)
|
if (this->eh_frame_section_ == NULL)
|
||||||
{
|
{
|
||||||
|
@ -319,16 +382,17 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
|
||||||
|
|
||||||
if (this->options_.create_eh_frame_hdr())
|
if (this->options_.create_eh_frame_hdr())
|
||||||
{
|
{
|
||||||
Stringpool::Key hdr_name_key;
|
|
||||||
const char* hdr_name = this->namepool_.add(".eh_frame_hdr",
|
|
||||||
false,
|
|
||||||
&hdr_name_key);
|
|
||||||
Output_section* hdr_os =
|
Output_section* hdr_os =
|
||||||
this->get_output_section(hdr_name, hdr_name_key,
|
this->choose_output_section(NULL,
|
||||||
|
".eh_frame_hdr",
|
||||||
elfcpp::SHT_PROGBITS,
|
elfcpp::SHT_PROGBITS,
|
||||||
elfcpp::SHF_ALLOC);
|
elfcpp::SHF_ALLOC,
|
||||||
|
false);
|
||||||
|
|
||||||
Eh_frame_hdr* hdr_posd = new Eh_frame_hdr(os, this->eh_frame_data_);
|
if (hdr_os != NULL)
|
||||||
|
{
|
||||||
|
Eh_frame_hdr* hdr_posd = new Eh_frame_hdr(os,
|
||||||
|
this->eh_frame_data_);
|
||||||
hdr_os->add_output_section_data(hdr_posd);
|
hdr_os->add_output_section_data(hdr_posd);
|
||||||
|
|
||||||
hdr_os->set_after_input_sections();
|
hdr_os->set_after_input_sections();
|
||||||
|
@ -341,6 +405,7 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
|
||||||
this->eh_frame_data_->set_eh_frame_hdr(hdr_posd);
|
this->eh_frame_data_->set_eh_frame_hdr(hdr_posd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gold_assert(this->eh_frame_section_ == os);
|
gold_assert(this->eh_frame_section_ == os);
|
||||||
|
|
||||||
|
@ -357,7 +422,9 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
|
||||||
{
|
{
|
||||||
// We couldn't handle this .eh_frame section for some reason.
|
// We couldn't handle this .eh_frame section for some reason.
|
||||||
// Add it as a normal section.
|
// Add it as a normal section.
|
||||||
*off = os->add_input_section(object, shndx, name, shdr, reloc_shndx);
|
bool saw_sections_clause = this->script_options_->saw_sections_clause();
|
||||||
|
*off = os->add_input_section(object, shndx, name, shdr, reloc_shndx,
|
||||||
|
saw_sections_clause);
|
||||||
}
|
}
|
||||||
|
|
||||||
return os;
|
return os;
|
||||||
|
@ -370,11 +437,9 @@ Layout::add_output_section_data(const char* name, elfcpp::Elf_Word type,
|
||||||
elfcpp::Elf_Xword flags,
|
elfcpp::Elf_Xword flags,
|
||||||
Output_section_data* posd)
|
Output_section_data* posd)
|
||||||
{
|
{
|
||||||
// Canonicalize the name.
|
Output_section* os = this->choose_output_section(NULL, name, type, flags,
|
||||||
Stringpool::Key name_key;
|
false);
|
||||||
name = this->namepool_.add(name, true, &name_key);
|
if (os != NULL)
|
||||||
|
|
||||||
Output_section* os = this->get_output_section(name, name_key, type, flags);
|
|
||||||
os->add_output_section_data(posd);
|
os->add_output_section_data(posd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,6 +493,11 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
|
||||||
this->unattached_section_list_.push_back(os);
|
this->unattached_section_list_.push_back(os);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// If we have a SECTIONS clause, we can't handle the attachment
|
||||||
|
// to segments until after we've seen all the sections.
|
||||||
|
if (this->script_options_->saw_sections_clause())
|
||||||
|
return os;
|
||||||
|
|
||||||
// This output section goes into a PT_LOAD segment.
|
// This output section goes into a PT_LOAD segment.
|
||||||
|
|
||||||
elfcpp::Elf_Word seg_flags = Layout::section_flags_to_segment(flags);
|
elfcpp::Elf_Word seg_flags = Layout::section_flags_to_segment(flags);
|
||||||
|
@ -581,7 +651,7 @@ Layout::define_section_symbols(Symbol_table* symtab)
|
||||||
elfcpp::STV_DEFAULT,
|
elfcpp::STV_DEFAULT,
|
||||||
0, // nonvis
|
0, // nonvis
|
||||||
false, // offset_is_from_end
|
false, // offset_is_from_end
|
||||||
false); // only_if_ref
|
true); // only_if_ref
|
||||||
|
|
||||||
symtab->define_in_output_data(stop_name.c_str(),
|
symtab->define_in_output_data(stop_name.c_str(),
|
||||||
NULL, // version
|
NULL, // version
|
||||||
|
@ -593,7 +663,7 @@ Layout::define_section_symbols(Symbol_table* symtab)
|
||||||
elfcpp::STV_DEFAULT,
|
elfcpp::STV_DEFAULT,
|
||||||
0, // nonvis
|
0, // nonvis
|
||||||
true, // offset_is_from_end
|
true, // offset_is_from_end
|
||||||
false); // only_if_ref
|
true); // only_if_ref
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -664,17 +734,11 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
|
||||||
this->create_gold_note();
|
this->create_gold_note();
|
||||||
this->create_executable_stack_info(target);
|
this->create_executable_stack_info(target);
|
||||||
|
|
||||||
Output_segment* phdr_seg = NULL;
|
if (!parameters->output_is_object() && !parameters->doing_static_link())
|
||||||
if (!parameters->doing_static_link())
|
|
||||||
{
|
{
|
||||||
// There was a dynamic object in the link. We need to create
|
// There was a dynamic object in the link. We need to create
|
||||||
// some information for the dynamic linker.
|
// some information for the dynamic linker.
|
||||||
|
|
||||||
// Create the PT_PHDR segment which will hold the program
|
|
||||||
// headers.
|
|
||||||
phdr_seg = new Output_segment(elfcpp::PT_PHDR, elfcpp::PF_R);
|
|
||||||
this->segment_list_.push_back(phdr_seg);
|
|
||||||
|
|
||||||
// Create the dynamic symbol table, including the hash table.
|
// Create the dynamic symbol table, including the hash table.
|
||||||
Output_section* dynstr;
|
Output_section* dynstr;
|
||||||
std::vector<Symbol*> dynamic_symbols;
|
std::vector<Symbol*> dynamic_symbols;
|
||||||
|
@ -703,15 +767,30 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
|
||||||
dynamic_symbols, dynstr);
|
dynamic_symbols, dynstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Handle PT_GNU_STACK.
|
// If there is a SECTIONS clause, put all the input sections into
|
||||||
|
// the required order.
|
||||||
|
Output_segment* load_seg;
|
||||||
|
if (this->script_options_->saw_sections_clause())
|
||||||
|
load_seg = this->set_section_addresses_from_script(symtab);
|
||||||
|
else
|
||||||
|
load_seg = this->find_first_load_seg();
|
||||||
|
|
||||||
Output_segment* load_seg = this->find_first_load_seg();
|
Output_segment* phdr_seg = NULL;
|
||||||
|
if (load_seg != NULL
|
||||||
|
&& !parameters->output_is_object()
|
||||||
|
&& !parameters->doing_static_link())
|
||||||
|
{
|
||||||
|
// Create the PT_PHDR segment which will hold the program
|
||||||
|
// headers.
|
||||||
|
phdr_seg = new Output_segment(elfcpp::PT_PHDR, elfcpp::PF_R);
|
||||||
|
this->segment_list_.push_back(phdr_seg);
|
||||||
|
}
|
||||||
|
|
||||||
// Lay out the segment headers.
|
// Lay out the segment headers.
|
||||||
Output_segment_headers* segment_headers;
|
Output_segment_headers* segment_headers;
|
||||||
segment_headers = new Output_segment_headers(this->segment_list_);
|
segment_headers = new Output_segment_headers(this->segment_list_);
|
||||||
|
if (load_seg != NULL)
|
||||||
load_seg->add_initial_output_data(segment_headers);
|
load_seg->add_initial_output_data(segment_headers);
|
||||||
this->special_output_list_.push_back(segment_headers);
|
|
||||||
if (phdr_seg != NULL)
|
if (phdr_seg != NULL)
|
||||||
phdr_seg->add_initial_output_data(segment_headers);
|
phdr_seg->add_initial_output_data(segment_headers);
|
||||||
|
|
||||||
|
@ -719,8 +798,11 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
|
||||||
Output_file_header* file_header;
|
Output_file_header* file_header;
|
||||||
file_header = new Output_file_header(target, symtab, segment_headers,
|
file_header = new Output_file_header(target, symtab, segment_headers,
|
||||||
this->script_options_->entry());
|
this->script_options_->entry());
|
||||||
|
if (load_seg != NULL)
|
||||||
load_seg->add_initial_output_data(file_header);
|
load_seg->add_initial_output_data(file_header);
|
||||||
|
|
||||||
this->special_output_list_.push_back(file_header);
|
this->special_output_list_.push_back(file_header);
|
||||||
|
this->special_output_list_.push_back(segment_headers);
|
||||||
|
|
||||||
// We set the output section indexes in set_segment_offsets and
|
// We set the output section indexes in set_segment_offsets and
|
||||||
// set_section_indexes.
|
// set_section_indexes.
|
||||||
|
@ -970,6 +1052,27 @@ Layout::segment_precedes(const Output_segment* seg1,
|
||||||
return flags1 < flags2;
|
return flags1 < flags2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the addresses are set already, sort by load address.
|
||||||
|
if (seg1->are_addresses_set())
|
||||||
|
{
|
||||||
|
if (!seg2->are_addresses_set())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
unsigned int section_count1 = seg1->output_section_count();
|
||||||
|
unsigned int section_count2 = seg2->output_section_count();
|
||||||
|
if (section_count1 == 0 && section_count2 > 0)
|
||||||
|
return true;
|
||||||
|
if (section_count1 > 0 && section_count2 == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint64_t paddr1 = seg1->first_section_load_address();
|
||||||
|
uint64_t paddr2 = seg2->first_section_load_address();
|
||||||
|
if (paddr1 != paddr2)
|
||||||
|
return paddr1 < paddr2;
|
||||||
|
}
|
||||||
|
else if (seg2->are_addresses_set())
|
||||||
|
return false;
|
||||||
|
|
||||||
// We sort PT_LOAD segments based on the flags. Readonly segments
|
// We sort PT_LOAD segments based on the flags. Readonly segments
|
||||||
// come before writable segments. Then executable segments come
|
// come before writable segments. Then executable segments come
|
||||||
// before non-executable segments. Then the unlikely case of a
|
// before non-executable segments. Then the unlikely case of a
|
||||||
|
@ -984,15 +1087,9 @@ Layout::segment_precedes(const Output_segment* seg1,
|
||||||
if ((flags1 & elfcpp::PF_R) != (flags2 & elfcpp::PF_R))
|
if ((flags1 & elfcpp::PF_R) != (flags2 & elfcpp::PF_R))
|
||||||
return (flags1 & elfcpp::PF_R) == 0;
|
return (flags1 & elfcpp::PF_R) == 0;
|
||||||
|
|
||||||
uint64_t vaddr1 = seg1->vaddr();
|
// We shouldn't get here--we shouldn't create segments which we
|
||||||
uint64_t vaddr2 = seg2->vaddr();
|
// can't distinguish.
|
||||||
if (vaddr1 != vaddr2)
|
gold_unreachable();
|
||||||
return vaddr1 < vaddr2;
|
|
||||||
|
|
||||||
uint64_t paddr1 = seg1->paddr();
|
|
||||||
uint64_t paddr2 = seg2->paddr();
|
|
||||||
gold_assert(paddr1 != paddr2);
|
|
||||||
return paddr1 < paddr2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the file offsets of all the segments, and all the sections they
|
// Set the file offsets of all the segments, and all the sections they
|
||||||
|
@ -1010,13 +1107,29 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
|
||||||
// Find the PT_LOAD segments, and set their addresses and offsets
|
// Find the PT_LOAD segments, and set their addresses and offsets
|
||||||
// and their section's addresses and offsets.
|
// and their section's addresses and offsets.
|
||||||
uint64_t addr;
|
uint64_t addr;
|
||||||
if (parameters->output_is_shared())
|
if (this->options_.user_set_text_segment_address())
|
||||||
addr = 0;
|
|
||||||
else if (options_.user_set_text_segment_address())
|
|
||||||
addr = options_.text_segment_address();
|
addr = options_.text_segment_address();
|
||||||
|
else if (parameters->output_is_shared())
|
||||||
|
addr = 0;
|
||||||
else
|
else
|
||||||
addr = target->default_text_segment_address();
|
addr = target->default_text_segment_address();
|
||||||
off_t off = 0;
|
off_t off = 0;
|
||||||
|
|
||||||
|
// If LOAD_SEG is NULL, then the file header and segment headers
|
||||||
|
// will not be loadable. But they still need to be at offset 0 in
|
||||||
|
// the file. Set their offsets now.
|
||||||
|
if (load_seg == NULL)
|
||||||
|
{
|
||||||
|
for (Data_list::iterator p = this->special_output_list_.begin();
|
||||||
|
p != this->special_output_list_.end();
|
||||||
|
++p)
|
||||||
|
{
|
||||||
|
off = align_address(off, (*p)->addralign());
|
||||||
|
(*p)->set_address_and_file_offset(0, off);
|
||||||
|
off += (*p)->data_size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool was_readonly = false;
|
bool was_readonly = false;
|
||||||
for (Segment_list::iterator p = this->segment_list_.begin();
|
for (Segment_list::iterator p = this->segment_list_.begin();
|
||||||
p != this->segment_list_.end();
|
p != this->segment_list_.end();
|
||||||
|
@ -1028,34 +1141,55 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
|
||||||
gold_unreachable();
|
gold_unreachable();
|
||||||
load_seg = NULL;
|
load_seg = NULL;
|
||||||
|
|
||||||
// If the last segment was readonly, and this one is not,
|
|
||||||
// then skip the address forward one page, maintaining the
|
|
||||||
// same position within the page. This lets us store both
|
|
||||||
// segments overlapping on a single page in the file, but
|
|
||||||
// the loader will put them on different pages in memory.
|
|
||||||
|
|
||||||
uint64_t orig_addr = addr;
|
uint64_t orig_addr = addr;
|
||||||
uint64_t orig_off = off;
|
uint64_t orig_off = off;
|
||||||
|
|
||||||
uint64_t aligned_addr = addr;
|
uint64_t aligned_addr = 0;
|
||||||
uint64_t abi_pagesize = target->abi_pagesize();
|
uint64_t abi_pagesize = target->abi_pagesize();
|
||||||
|
|
||||||
// FIXME: This should depend on the -n and -N options.
|
// FIXME: This should depend on the -n and -N options.
|
||||||
(*p)->set_minimum_addralign(target->common_pagesize());
|
(*p)->set_minimum_p_align(target->common_pagesize());
|
||||||
|
|
||||||
|
bool are_addresses_set = (*p)->are_addresses_set();
|
||||||
|
if (are_addresses_set)
|
||||||
|
{
|
||||||
|
// When it comes to setting file offsets, we care about
|
||||||
|
// the physical address.
|
||||||
|
addr = (*p)->paddr();
|
||||||
|
|
||||||
|
// Adjust the file offset to the same address modulo the
|
||||||
|
// page size.
|
||||||
|
uint64_t unsigned_off = off;
|
||||||
|
uint64_t aligned_off = ((unsigned_off & ~(abi_pagesize - 1))
|
||||||
|
| (addr & (abi_pagesize - 1)));
|
||||||
|
if (aligned_off < unsigned_off)
|
||||||
|
aligned_off += abi_pagesize;
|
||||||
|
off = aligned_off;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If the last segment was readonly, and this one is
|
||||||
|
// not, then skip the address forward one page,
|
||||||
|
// maintaining the same position within the page. This
|
||||||
|
// lets us store both segments overlapping on a single
|
||||||
|
// page in the file, but the loader will put them on
|
||||||
|
// different pages in memory.
|
||||||
|
|
||||||
|
addr = align_address(addr, (*p)->maximum_alignment());
|
||||||
|
aligned_addr = addr;
|
||||||
|
|
||||||
if (was_readonly && ((*p)->flags() & elfcpp::PF_W) != 0)
|
if (was_readonly && ((*p)->flags() & elfcpp::PF_W) != 0)
|
||||||
{
|
{
|
||||||
uint64_t align = (*p)->addralign();
|
|
||||||
|
|
||||||
addr = align_address(addr, align);
|
|
||||||
aligned_addr = addr;
|
|
||||||
if ((addr & (abi_pagesize - 1)) != 0)
|
if ((addr & (abi_pagesize - 1)) != 0)
|
||||||
addr = addr + abi_pagesize;
|
addr = addr + abi_pagesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int shndx_hold = *pshndx;
|
|
||||||
off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
|
off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
|
||||||
uint64_t new_addr = (*p)->set_section_addresses(addr, &off, pshndx);
|
}
|
||||||
|
|
||||||
|
unsigned int shndx_hold = *pshndx;
|
||||||
|
uint64_t new_addr = (*p)->set_section_addresses(false, addr, &off,
|
||||||
|
pshndx);
|
||||||
|
|
||||||
// Now that we know the size of this segment, we may be able
|
// Now that we know the size of this segment, we may be able
|
||||||
// to save a page in memory, at the cost of wasting some
|
// to save a page in memory, at the cost of wasting some
|
||||||
|
@ -1063,7 +1197,7 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
|
||||||
// page. Here we use the real machine page size rather than
|
// page. Here we use the real machine page size rather than
|
||||||
// the ABI mandated page size.
|
// the ABI mandated page size.
|
||||||
|
|
||||||
if (aligned_addr != addr)
|
if (!are_addresses_set && aligned_addr != addr)
|
||||||
{
|
{
|
||||||
uint64_t common_pagesize = target->common_pagesize();
|
uint64_t common_pagesize = target->common_pagesize();
|
||||||
uint64_t first_off = (common_pagesize
|
uint64_t first_off = (common_pagesize
|
||||||
|
@ -1078,8 +1212,10 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
|
||||||
{
|
{
|
||||||
*pshndx = shndx_hold;
|
*pshndx = shndx_hold;
|
||||||
addr = align_address(aligned_addr, common_pagesize);
|
addr = align_address(aligned_addr, common_pagesize);
|
||||||
|
addr = align_address(addr, (*p)->maximum_alignment());
|
||||||
off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
|
off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
|
||||||
new_addr = (*p)->set_section_addresses(addr, &off, pshndx);
|
new_addr = (*p)->set_section_addresses(true, addr, &off,
|
||||||
|
pshndx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1172,6 +1308,30 @@ Layout::set_section_indexes(unsigned int shndx)
|
||||||
return shndx;
|
return shndx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the section addresses according to the linker script. This is
|
||||||
|
// only called when we see a SECTIONS clause. This returns the
|
||||||
|
// program segment which should hold the file header and segment
|
||||||
|
// headers, if any. It will return NULL if they should not be in a
|
||||||
|
// segment.
|
||||||
|
|
||||||
|
Output_segment*
|
||||||
|
Layout::set_section_addresses_from_script(Symbol_table* symtab)
|
||||||
|
{
|
||||||
|
Script_sections* ss = this->script_options_->script_sections();
|
||||||
|
gold_assert(ss->saw_sections_clause());
|
||||||
|
|
||||||
|
// Place each orphaned output section in the script.
|
||||||
|
for (Section_list::iterator p = this->section_list_.begin();
|
||||||
|
p != this->section_list_.end();
|
||||||
|
++p)
|
||||||
|
{
|
||||||
|
if (!(*p)->found_in_sections_clause())
|
||||||
|
ss->place_orphan(*p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this->script_options_->set_section_addresses(symtab, this);
|
||||||
|
}
|
||||||
|
|
||||||
// Count the local symbols in the regular symbol table and the dynamic
|
// Count the local symbols in the regular symbol table and the dynamic
|
||||||
// symbol table, and build the respective string pools.
|
// symbol table, and build the respective string pools.
|
||||||
|
|
||||||
|
@ -1963,6 +2123,28 @@ Layout::add_comdat(const char* signature, bool group)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store the allocated sections into the section list.
|
||||||
|
|
||||||
|
void
|
||||||
|
Layout::get_allocated_sections(Section_list* section_list) const
|
||||||
|
{
|
||||||
|
for (Section_list::const_iterator p = this->section_list_.begin();
|
||||||
|
p != this->section_list_.end();
|
||||||
|
++p)
|
||||||
|
if (((*p)->flags() & elfcpp::SHF_ALLOC) != 0)
|
||||||
|
section_list->push_back(*p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an output segment.
|
||||||
|
|
||||||
|
Output_segment*
|
||||||
|
Layout::make_output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
|
||||||
|
{
|
||||||
|
Output_segment* oseg = new Output_segment(type, flags);
|
||||||
|
this->segment_list_.push_back(oseg);
|
||||||
|
return oseg;
|
||||||
|
}
|
||||||
|
|
||||||
// Write out the Output_sections. Most won't have anything to write,
|
// Write out the Output_sections. Most won't have anything to write,
|
||||||
// since most of the data will come from input sections which are
|
// since most of the data will come from input sections which are
|
||||||
// handled elsewhere. But some Output_sections do have Output_data.
|
// handled elsewhere. But some Output_sections do have Output_data.
|
||||||
|
|
|
@ -260,11 +260,11 @@ class Layout
|
||||||
void
|
void
|
||||||
print_stats() const;
|
print_stats() const;
|
||||||
|
|
||||||
// The list of segments.
|
// A list of segments.
|
||||||
|
|
||||||
typedef std::vector<Output_segment*> Segment_list;
|
typedef std::vector<Output_segment*> Segment_list;
|
||||||
|
|
||||||
// The list of sections not attached to a segment.
|
// A list of sections.
|
||||||
|
|
||||||
typedef std::vector<Output_section*> Section_list;
|
typedef std::vector<Output_section*> Section_list;
|
||||||
|
|
||||||
|
@ -272,6 +272,24 @@ class Layout
|
||||||
// either a section or a segment.
|
// either a section or a segment.
|
||||||
typedef std::vector<Output_data*> Data_list;
|
typedef std::vector<Output_data*> Data_list;
|
||||||
|
|
||||||
|
// Store the allocated sections into the section list. This is used
|
||||||
|
// by the linker script code.
|
||||||
|
void
|
||||||
|
get_allocated_sections(Section_list*) const;
|
||||||
|
|
||||||
|
// Make a segment. This is used by the linker script code.
|
||||||
|
Output_segment*
|
||||||
|
make_output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags);
|
||||||
|
|
||||||
|
// Return the number of segments.
|
||||||
|
size_t
|
||||||
|
segment_count() const
|
||||||
|
{ return this->segment_list_.size(); }
|
||||||
|
|
||||||
|
// Map from section flags to segment flags.
|
||||||
|
static elfcpp::Elf_Word
|
||||||
|
section_flags_to_segment(elfcpp::Elf_Xword flags);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Layout(const Layout&);
|
Layout(const Layout&);
|
||||||
Layout& operator=(const Layout&);
|
Layout& operator=(const Layout&);
|
||||||
|
@ -376,6 +394,12 @@ class Layout
|
||||||
get_output_section(const char* name, Stringpool::Key name_key,
|
get_output_section(const char* name, Stringpool::Key name_key,
|
||||||
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags);
|
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags);
|
||||||
|
|
||||||
|
// Choose the output section for NAME in RELOBJ.
|
||||||
|
Output_section*
|
||||||
|
choose_output_section(const Relobj* relobj, const char* name,
|
||||||
|
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
|
||||||
|
bool adjust_name);
|
||||||
|
|
||||||
// Create a new Output_section.
|
// Create a new Output_section.
|
||||||
Output_section*
|
Output_section*
|
||||||
make_output_section(const char* name, elfcpp::Elf_Word type,
|
make_output_section(const char* name, elfcpp::Elf_Word type,
|
||||||
|
@ -405,14 +429,14 @@ class Layout
|
||||||
unsigned int
|
unsigned int
|
||||||
set_section_indexes(unsigned int pshndx);
|
set_section_indexes(unsigned int pshndx);
|
||||||
|
|
||||||
|
// Set the section addresses when using a script.
|
||||||
|
Output_segment*
|
||||||
|
set_section_addresses_from_script(Symbol_table*);
|
||||||
|
|
||||||
// Return whether SEG1 comes before SEG2 in the output file.
|
// Return whether SEG1 comes before SEG2 in the output file.
|
||||||
static bool
|
static bool
|
||||||
segment_precedes(const Output_segment* seg1, const Output_segment* seg2);
|
segment_precedes(const Output_segment* seg1, const Output_segment* seg2);
|
||||||
|
|
||||||
// Map from section flags to segment flags.
|
|
||||||
static elfcpp::Elf_Word
|
|
||||||
section_flags_to_segment(elfcpp::Elf_Xword flags);
|
|
||||||
|
|
||||||
// A mapping used for group signatures.
|
// A mapping used for group signatures.
|
||||||
typedef Unordered_map<std::string, bool> Signatures;
|
typedef Unordered_map<std::string, bool> Signatures;
|
||||||
|
|
||||||
|
|
|
@ -206,8 +206,12 @@ class Object
|
||||||
const unsigned char*
|
const unsigned char*
|
||||||
section_contents(unsigned int shndx, section_size_type* plen, bool cache);
|
section_contents(unsigned int shndx, section_size_type* plen, bool cache);
|
||||||
|
|
||||||
// Return the name of a section given a section index. This is only
|
// Return the size of a section given a section index.
|
||||||
// used for error messages.
|
uint64_t
|
||||||
|
section_size(unsigned int shndx)
|
||||||
|
{ return this->do_section_size(shndx); }
|
||||||
|
|
||||||
|
// Return the name of a section given a section index.
|
||||||
std::string
|
std::string
|
||||||
section_name(unsigned int shndx)
|
section_name(unsigned int shndx)
|
||||||
{ return this->do_section_name(shndx); }
|
{ return this->do_section_name(shndx); }
|
||||||
|
@ -232,6 +236,11 @@ class Object
|
||||||
section_info(unsigned int shndx)
|
section_info(unsigned int shndx)
|
||||||
{ return this->do_section_info(shndx); }
|
{ return this->do_section_info(shndx); }
|
||||||
|
|
||||||
|
// Return the required section alignment given a section index.
|
||||||
|
uint64_t
|
||||||
|
section_addralign(unsigned int shndx)
|
||||||
|
{ return this->do_section_addralign(shndx); }
|
||||||
|
|
||||||
// Read the symbol information.
|
// Read the symbol information.
|
||||||
void
|
void
|
||||||
read_symbols(Read_symbols_data* sd)
|
read_symbols(Read_symbols_data* sd)
|
||||||
|
@ -344,6 +353,10 @@ class Object
|
||||||
virtual Location
|
virtual Location
|
||||||
do_section_contents(unsigned int shndx) = 0;
|
do_section_contents(unsigned int shndx) = 0;
|
||||||
|
|
||||||
|
// Get the size of a section--implemented by child class.
|
||||||
|
virtual uint64_t
|
||||||
|
do_section_size(unsigned int shndx) = 0;
|
||||||
|
|
||||||
// Get the name of a section--implemented by child class.
|
// Get the name of a section--implemented by child class.
|
||||||
virtual std::string
|
virtual std::string
|
||||||
do_section_name(unsigned int shndx) = 0;
|
do_section_name(unsigned int shndx) = 0;
|
||||||
|
@ -364,6 +377,10 @@ class Object
|
||||||
virtual unsigned int
|
virtual unsigned int
|
||||||
do_section_info(unsigned int shndx) = 0;
|
do_section_info(unsigned int shndx) = 0;
|
||||||
|
|
||||||
|
// Get section alignment--implemented by child class.
|
||||||
|
virtual uint64_t
|
||||||
|
do_section_addralign(unsigned int shndx) = 0;
|
||||||
|
|
||||||
// Get the file. We pass on const-ness.
|
// Get the file. We pass on const-ness.
|
||||||
Input_file*
|
Input_file*
|
||||||
input_file()
|
input_file()
|
||||||
|
@ -1136,6 +1153,11 @@ class Sized_relobj : public Relobj
|
||||||
do_relocate(const General_options& options, const Symbol_table* symtab,
|
do_relocate(const General_options& options, const Symbol_table* symtab,
|
||||||
const Layout*, Output_file* of);
|
const Layout*, Output_file* of);
|
||||||
|
|
||||||
|
// Get the size of a section.
|
||||||
|
uint64_t
|
||||||
|
do_section_size(unsigned int shndx)
|
||||||
|
{ return this->elf_file_.section_size(shndx); }
|
||||||
|
|
||||||
// Get the name of a section.
|
// Get the name of a section.
|
||||||
std::string
|
std::string
|
||||||
do_section_name(unsigned int shndx)
|
do_section_name(unsigned int shndx)
|
||||||
|
@ -1166,6 +1188,11 @@ class Sized_relobj : public Relobj
|
||||||
do_section_info(unsigned int shndx)
|
do_section_info(unsigned int shndx)
|
||||||
{ return this->elf_file_.section_info(shndx); }
|
{ return this->elf_file_.section_info(shndx); }
|
||||||
|
|
||||||
|
// Return the section alignment.
|
||||||
|
uint64_t
|
||||||
|
do_section_addralign(unsigned int shndx)
|
||||||
|
{ return this->elf_file_.section_addralign(shndx); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// For convenience.
|
// For convenience.
|
||||||
typedef Sized_relobj<size, big_endian> This;
|
typedef Sized_relobj<size, big_endian> This;
|
||||||
|
|
261
gold/output.cc
261
gold/output.cc
|
@ -275,6 +275,7 @@ Output_segment_headers::do_sized_write(Output_file* of)
|
||||||
{
|
{
|
||||||
const int phdr_size = elfcpp::Elf_sizes<size>::phdr_size;
|
const int phdr_size = elfcpp::Elf_sizes<size>::phdr_size;
|
||||||
off_t all_phdrs_size = this->segment_list_.size() * phdr_size;
|
off_t all_phdrs_size = this->segment_list_.size() * phdr_size;
|
||||||
|
gold_assert(all_phdrs_size == this->data_size());
|
||||||
unsigned char* view = of->get_output_view(this->offset(),
|
unsigned char* view = of->get_output_view(this->offset(),
|
||||||
all_phdrs_size);
|
all_phdrs_size);
|
||||||
unsigned char* v = view;
|
unsigned char* v = view;
|
||||||
|
@ -287,6 +288,8 @@ Output_segment_headers::do_sized_write(Output_file* of)
|
||||||
v += phdr_size;
|
v += phdr_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gold_assert(v - view == all_phdrs_size);
|
||||||
|
|
||||||
of->write_output_view(this->offset(), all_phdrs_size, view);
|
of->write_output_view(this->offset(), all_phdrs_size, view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1371,6 +1374,15 @@ Output_section::Input_section::set_address_and_file_offset(
|
||||||
this->u2_.posd->set_address_and_file_offset(address, file_offset);
|
this->u2_.posd->set_address_and_file_offset(address, file_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset the address and file offset.
|
||||||
|
|
||||||
|
void
|
||||||
|
Output_section::Input_section::reset_address_and_file_offset()
|
||||||
|
{
|
||||||
|
if (!this->is_input_section())
|
||||||
|
this->u2_.posd->reset_address_and_file_offset();
|
||||||
|
}
|
||||||
|
|
||||||
// Finalize the data size.
|
// Finalize the data size.
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1444,6 +1456,7 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
|
||||||
: name_(name),
|
: name_(name),
|
||||||
addralign_(0),
|
addralign_(0),
|
||||||
entsize_(0),
|
entsize_(0),
|
||||||
|
load_address_(0),
|
||||||
link_section_(NULL),
|
link_section_(NULL),
|
||||||
link_(0),
|
link_(0),
|
||||||
info_section_(NULL),
|
info_section_(NULL),
|
||||||
|
@ -1463,6 +1476,8 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
|
||||||
should_link_to_dynsym_(false),
|
should_link_to_dynsym_(false),
|
||||||
after_input_sections_(false),
|
after_input_sections_(false),
|
||||||
requires_postprocessing_(false),
|
requires_postprocessing_(false),
|
||||||
|
found_in_sections_clause_(false),
|
||||||
|
has_load_address_(false),
|
||||||
tls_offset_(0)
|
tls_offset_(0)
|
||||||
{
|
{
|
||||||
// An unallocated section has no address. Forcing this means that
|
// An unallocated section has no address. Forcing this means that
|
||||||
|
@ -1495,7 +1510,9 @@ Output_section::set_entsize(uint64_t v)
|
||||||
// receive special handling. In the normal case we don't always keep
|
// receive special handling. In the normal case we don't always keep
|
||||||
// track of input sections for an Output_section. Instead, each
|
// track of input sections for an Output_section. Instead, each
|
||||||
// Object keeps track of the Output_section for each of its input
|
// Object keeps track of the Output_section for each of its input
|
||||||
// sections.
|
// sections. However, if HAVE_SECTIONS_SCRIPT is true, we do keep
|
||||||
|
// track of input sections here; this is used when SECTIONS appears in
|
||||||
|
// a linker script.
|
||||||
|
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
off_t
|
off_t
|
||||||
|
@ -1503,7 +1520,8 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object,
|
||||||
unsigned int shndx,
|
unsigned int shndx,
|
||||||
const char* secname,
|
const char* secname,
|
||||||
const elfcpp::Shdr<size, big_endian>& shdr,
|
const elfcpp::Shdr<size, big_endian>& shdr,
|
||||||
unsigned int reloc_shndx)
|
unsigned int reloc_shndx,
|
||||||
|
bool have_sections_script)
|
||||||
{
|
{
|
||||||
elfcpp::Elf_Xword addralign = shdr.get_sh_addralign();
|
elfcpp::Elf_Xword addralign = shdr.get_sh_addralign();
|
||||||
if ((addralign & (addralign - 1)) != 0)
|
if ((addralign & (addralign - 1)) != 0)
|
||||||
|
@ -1517,6 +1535,11 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object,
|
||||||
this->addralign_ = addralign;
|
this->addralign_ = addralign;
|
||||||
|
|
||||||
typename elfcpp::Elf_types<size>::Elf_WXword sh_flags = shdr.get_sh_flags();
|
typename elfcpp::Elf_types<size>::Elf_WXword sh_flags = shdr.get_sh_flags();
|
||||||
|
this->flags_ |= (sh_flags
|
||||||
|
& (elfcpp::SHF_WRITE
|
||||||
|
| elfcpp::SHF_ALLOC
|
||||||
|
| elfcpp::SHF_EXECINSTR));
|
||||||
|
|
||||||
uint64_t entsize = shdr.get_sh_entsize();
|
uint64_t entsize = shdr.get_sh_entsize();
|
||||||
|
|
||||||
// .debug_str is a mergeable string section, but is not always so
|
// .debug_str is a mergeable string section, but is not always so
|
||||||
|
@ -1547,6 +1570,7 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object,
|
||||||
addralign);
|
addralign);
|
||||||
|
|
||||||
if (aligned_offset_in_section > offset_in_section
|
if (aligned_offset_in_section > offset_in_section
|
||||||
|
&& !have_sections_script
|
||||||
&& (sh_flags & elfcpp::SHF_EXECINSTR) != 0
|
&& (sh_flags & elfcpp::SHF_EXECINSTR) != 0
|
||||||
&& object->target()->has_code_fill())
|
&& object->target()->has_code_fill())
|
||||||
{
|
{
|
||||||
|
@ -1572,7 +1596,7 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object,
|
||||||
// We need to keep track of this section if we are already keeping
|
// We need to keep track of this section if we are already keeping
|
||||||
// track of sections, or if we are relaxing. FIXME: Add test for
|
// track of sections, or if we are relaxing. FIXME: Add test for
|
||||||
// relaxing.
|
// relaxing.
|
||||||
if (!this->input_sections_.empty())
|
if (have_sections_script || !this->input_sections_.empty())
|
||||||
this->input_sections_.push_back(Input_section(object, shndx,
|
this->input_sections_.push_back(Input_section(object, shndx,
|
||||||
shdr.get_sh_size(),
|
shdr.get_sh_size(),
|
||||||
addralign));
|
addralign));
|
||||||
|
@ -1587,6 +1611,15 @@ Output_section::add_output_section_data(Output_section_data* posd)
|
||||||
{
|
{
|
||||||
Input_section inp(posd);
|
Input_section inp(posd);
|
||||||
this->add_output_section_data(&inp);
|
this->add_output_section_data(&inp);
|
||||||
|
|
||||||
|
if (posd->is_data_size_valid())
|
||||||
|
{
|
||||||
|
off_t offset_in_section = this->current_data_size_for_child();
|
||||||
|
off_t aligned_offset_in_section = align_address(offset_in_section,
|
||||||
|
posd->addralign());
|
||||||
|
this->set_current_data_size_for_child(aligned_offset_in_section
|
||||||
|
+ posd->data_size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add arbitrary data to an output section by Input_section.
|
// Add arbitrary data to an output section by Input_section.
|
||||||
|
@ -1809,6 +1842,17 @@ Output_section::set_final_data_size()
|
||||||
this->set_data_size(off - startoff);
|
this->set_data_size(off - startoff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset the address and file offset.
|
||||||
|
|
||||||
|
void
|
||||||
|
Output_section::do_reset_address_and_file_offset()
|
||||||
|
{
|
||||||
|
for (Input_section_list::iterator p = this->input_sections_.begin();
|
||||||
|
p != this->input_sections_.end();
|
||||||
|
++p)
|
||||||
|
p->reset_address_and_file_offset();
|
||||||
|
}
|
||||||
|
|
||||||
// Set the TLS offset. Called only for SHT_TLS sections.
|
// Set the TLS offset. Called only for SHT_TLS sections.
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1917,7 +1961,8 @@ Output_section::write_to_postprocessing_buffer()
|
||||||
++p)
|
++p)
|
||||||
{
|
{
|
||||||
std::string fill_data(target->code_fill(p->length()));
|
std::string fill_data(target->code_fill(p->length()));
|
||||||
memcpy(buffer + p->section_offset(), fill_data.data(), fill_data.size());
|
memcpy(buffer + p->section_offset(), fill_data.data(),
|
||||||
|
fill_data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t off = this->first_input_offset_;
|
off_t off = this->first_input_offset_;
|
||||||
|
@ -1931,6 +1976,89 @@ Output_section::write_to_postprocessing_buffer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the input sections for linker script processing. We leave
|
||||||
|
// behind the Output_section_data entries. Note that this may be
|
||||||
|
// slightly incorrect for merge sections. We will leave them behind,
|
||||||
|
// but it is possible that the script says that they should follow
|
||||||
|
// some other input sections, as in:
|
||||||
|
// .rodata { *(.rodata) *(.rodata.cst*) }
|
||||||
|
// For that matter, we don't handle this correctly:
|
||||||
|
// .rodata { foo.o(.rodata.cst*) *(.rodata.cst*) }
|
||||||
|
// With luck this will never matter.
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
Output_section::get_input_sections(
|
||||||
|
uint64_t address,
|
||||||
|
const std::string& fill,
|
||||||
|
std::list<std::pair<Relobj*, unsigned int> >* input_sections)
|
||||||
|
{
|
||||||
|
uint64_t orig_address = address;
|
||||||
|
|
||||||
|
address = align_address(address, this->addralign());
|
||||||
|
|
||||||
|
Input_section_list remaining;
|
||||||
|
for (Input_section_list::iterator p = this->input_sections_.begin();
|
||||||
|
p != this->input_sections_.end();
|
||||||
|
++p)
|
||||||
|
{
|
||||||
|
if (p->is_input_section())
|
||||||
|
input_sections->push_back(std::make_pair(p->relobj(), p->shndx()));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint64_t aligned_address = align_address(address, p->addralign());
|
||||||
|
if (aligned_address != address && !fill.empty())
|
||||||
|
{
|
||||||
|
section_size_type length =
|
||||||
|
convert_to_section_size_type(aligned_address - address);
|
||||||
|
std::string this_fill;
|
||||||
|
this_fill.reserve(length);
|
||||||
|
while (this_fill.length() + fill.length() <= length)
|
||||||
|
this_fill += fill;
|
||||||
|
if (this_fill.length() < length)
|
||||||
|
this_fill.append(fill, 0, length - this_fill.length());
|
||||||
|
|
||||||
|
Output_section_data* posd = new Output_data_const(this_fill, 0);
|
||||||
|
remaining.push_back(Input_section(posd));
|
||||||
|
}
|
||||||
|
address = aligned_address;
|
||||||
|
|
||||||
|
remaining.push_back(*p);
|
||||||
|
|
||||||
|
p->finalize_data_size();
|
||||||
|
address += p->data_size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->input_sections_.swap(remaining);
|
||||||
|
this->first_input_offset_ = 0;
|
||||||
|
|
||||||
|
uint64_t data_size = address - orig_address;
|
||||||
|
this->set_current_data_size_for_child(data_size);
|
||||||
|
return data_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add an input section from a script.
|
||||||
|
|
||||||
|
void
|
||||||
|
Output_section::add_input_section_for_script(Relobj* object,
|
||||||
|
unsigned int shndx,
|
||||||
|
off_t data_size,
|
||||||
|
uint64_t addralign)
|
||||||
|
{
|
||||||
|
if (addralign > this->addralign_)
|
||||||
|
this->addralign_ = addralign;
|
||||||
|
|
||||||
|
off_t offset_in_section = this->current_data_size_for_child();
|
||||||
|
off_t aligned_offset_in_section = align_address(offset_in_section,
|
||||||
|
addralign);
|
||||||
|
|
||||||
|
this->set_current_data_size_for_child(aligned_offset_in_section
|
||||||
|
+ data_size);
|
||||||
|
|
||||||
|
this->input_sections_.push_back(Input_section(object, shndx,
|
||||||
|
data_size, addralign));
|
||||||
|
}
|
||||||
|
|
||||||
// Print stats for merge sections to stderr.
|
// Print stats for merge sections to stderr.
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1951,12 +2079,14 @@ Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
|
||||||
vaddr_(0),
|
vaddr_(0),
|
||||||
paddr_(0),
|
paddr_(0),
|
||||||
memsz_(0),
|
memsz_(0),
|
||||||
align_(0),
|
max_align_(0),
|
||||||
|
min_p_align_(0),
|
||||||
offset_(0),
|
offset_(0),
|
||||||
filesz_(0),
|
filesz_(0),
|
||||||
type_(type),
|
type_(type),
|
||||||
flags_(flags),
|
flags_(flags),
|
||||||
is_align_known_(false)
|
is_max_align_known_(false),
|
||||||
|
are_addresses_set_(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1968,7 +2098,7 @@ Output_segment::add_output_section(Output_section* os,
|
||||||
bool front)
|
bool front)
|
||||||
{
|
{
|
||||||
gold_assert((os->flags() & elfcpp::SHF_ALLOC) != 0);
|
gold_assert((os->flags() & elfcpp::SHF_ALLOC) != 0);
|
||||||
gold_assert(!this->is_align_known_);
|
gold_assert(!this->is_max_align_known_);
|
||||||
|
|
||||||
// Update the segment flags.
|
// Update the segment flags.
|
||||||
this->flags_ |= seg_flags;
|
this->flags_ |= seg_flags;
|
||||||
|
@ -2069,38 +2199,37 @@ Output_segment::add_output_section(Output_section* os,
|
||||||
void
|
void
|
||||||
Output_segment::add_initial_output_data(Output_data* od)
|
Output_segment::add_initial_output_data(Output_data* od)
|
||||||
{
|
{
|
||||||
gold_assert(!this->is_align_known_);
|
gold_assert(!this->is_max_align_known_);
|
||||||
this->output_data_.push_front(od);
|
this->output_data_.push_front(od);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the maximum alignment of the Output_data in Output_segment.
|
// Return the maximum alignment of the Output_data in Output_segment.
|
||||||
// Once we compute this, we prohibit new sections from being added.
|
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
Output_segment::addralign()
|
Output_segment::maximum_alignment()
|
||||||
{
|
{
|
||||||
if (!this->is_align_known_)
|
if (!this->is_max_align_known_)
|
||||||
{
|
{
|
||||||
uint64_t addralign;
|
uint64_t addralign;
|
||||||
|
|
||||||
addralign = Output_segment::maximum_alignment(&this->output_data_);
|
addralign = Output_segment::maximum_alignment_list(&this->output_data_);
|
||||||
if (addralign > this->align_)
|
if (addralign > this->max_align_)
|
||||||
this->align_ = addralign;
|
this->max_align_ = addralign;
|
||||||
|
|
||||||
addralign = Output_segment::maximum_alignment(&this->output_bss_);
|
addralign = Output_segment::maximum_alignment_list(&this->output_bss_);
|
||||||
if (addralign > this->align_)
|
if (addralign > this->max_align_)
|
||||||
this->align_ = addralign;
|
this->max_align_ = addralign;
|
||||||
|
|
||||||
this->is_align_known_ = true;
|
this->is_max_align_known_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->align_;
|
return this->max_align_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the maximum alignment of a list of Output_data.
|
// Return the maximum alignment of a list of Output_data.
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
Output_segment::maximum_alignment(const Output_data_list* pdl)
|
Output_segment::maximum_alignment_list(const Output_data_list* pdl)
|
||||||
{
|
{
|
||||||
uint64_t ret = 0;
|
uint64_t ret = 0;
|
||||||
for (Output_data_list::const_iterator p = pdl->begin();
|
for (Output_data_list::const_iterator p = pdl->begin();
|
||||||
|
@ -2136,33 +2265,41 @@ Output_segment::dynamic_reloc_count_list(const Output_data_list* pdl) const
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the section addresses for an Output_segment. ADDR is the
|
// Set the section addresses for an Output_segment. If RESET is true,
|
||||||
// address and *POFF is the file offset. Set the section indexes
|
// reset the addresses first. ADDR is the address and *POFF is the
|
||||||
// starting with *PSHNDX. Return the address of the immediately
|
// file offset. Set the section indexes starting with *PSHNDX.
|
||||||
// following segment. Update *POFF and *PSHNDX.
|
// Return the address of the immediately following segment. Update
|
||||||
|
// *POFF and *PSHNDX.
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
Output_segment::set_section_addresses(uint64_t addr, off_t* poff,
|
Output_segment::set_section_addresses(bool reset, uint64_t addr, off_t* poff,
|
||||||
unsigned int* pshndx)
|
unsigned int* pshndx)
|
||||||
{
|
{
|
||||||
gold_assert(this->type_ == elfcpp::PT_LOAD);
|
gold_assert(this->type_ == elfcpp::PT_LOAD);
|
||||||
|
|
||||||
|
if (!reset && this->are_addresses_set_)
|
||||||
|
{
|
||||||
|
gold_assert(this->paddr_ == addr);
|
||||||
|
addr = this->vaddr_;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
this->vaddr_ = addr;
|
this->vaddr_ = addr;
|
||||||
this->paddr_ = addr;
|
this->paddr_ = addr;
|
||||||
|
this->are_addresses_set_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
off_t orig_off = *poff;
|
off_t orig_off = *poff;
|
||||||
this->offset_ = orig_off;
|
this->offset_ = orig_off;
|
||||||
|
|
||||||
*poff = align_address(*poff, this->addralign());
|
addr = this->set_section_list_addresses(reset, &this->output_data_,
|
||||||
|
addr, poff, pshndx);
|
||||||
addr = this->set_section_list_addresses(&this->output_data_, addr, poff,
|
|
||||||
pshndx);
|
|
||||||
this->filesz_ = *poff - orig_off;
|
this->filesz_ = *poff - orig_off;
|
||||||
|
|
||||||
off_t off = *poff;
|
off_t off = *poff;
|
||||||
|
|
||||||
uint64_t ret = this->set_section_list_addresses(&this->output_bss_, addr,
|
uint64_t ret = this->set_section_list_addresses(reset, &this->output_bss_,
|
||||||
poff, pshndx);
|
addr, poff, pshndx);
|
||||||
this->memsz_ = *poff - orig_off;
|
this->memsz_ = *poff - orig_off;
|
||||||
|
|
||||||
// Ignore the file offset adjustments made by the BSS Output_data
|
// Ignore the file offset adjustments made by the BSS Output_data
|
||||||
|
@ -2176,7 +2313,7 @@ Output_segment::set_section_addresses(uint64_t addr, off_t* poff,
|
||||||
// structures.
|
// structures.
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
Output_segment::set_section_list_addresses(Output_data_list* pdl,
|
Output_segment::set_section_list_addresses(bool reset, Output_data_list* pdl,
|
||||||
uint64_t addr, off_t* poff,
|
uint64_t addr, off_t* poff,
|
||||||
unsigned int* pshndx)
|
unsigned int* pshndx)
|
||||||
{
|
{
|
||||||
|
@ -2188,7 +2325,23 @@ Output_segment::set_section_list_addresses(Output_data_list* pdl,
|
||||||
++p)
|
++p)
|
||||||
{
|
{
|
||||||
off = align_address(off, (*p)->addralign());
|
off = align_address(off, (*p)->addralign());
|
||||||
|
|
||||||
|
if (reset)
|
||||||
|
(*p)->reset_address_and_file_offset();
|
||||||
|
|
||||||
|
// When using a linker script the section will most likely
|
||||||
|
// already have an address.
|
||||||
|
if (!(*p)->is_address_valid())
|
||||||
(*p)->set_address_and_file_offset(addr + (off - startoff), off);
|
(*p)->set_address_and_file_offset(addr + (off - startoff), off);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The script may have inserted a skip forward, but it
|
||||||
|
// better not have moved backward.
|
||||||
|
gold_assert((*p)->address() >= addr);
|
||||||
|
off = startoff + ((*p)->address() - addr);
|
||||||
|
(*p)->set_file_offset(off);
|
||||||
|
(*p)->finalize_data_size();
|
||||||
|
}
|
||||||
|
|
||||||
// Unless this is a PT_TLS segment, we want to ignore the size
|
// Unless this is a PT_TLS segment, we want to ignore the size
|
||||||
// of a SHF_TLS/SHT_NOBITS section. Such a section does not
|
// of a SHF_TLS/SHT_NOBITS section. Such a section does not
|
||||||
|
@ -2217,12 +2370,15 @@ Output_segment::set_offset()
|
||||||
{
|
{
|
||||||
gold_assert(this->type_ != elfcpp::PT_LOAD);
|
gold_assert(this->type_ != elfcpp::PT_LOAD);
|
||||||
|
|
||||||
|
gold_assert(!this->are_addresses_set_);
|
||||||
|
|
||||||
if (this->output_data_.empty() && this->output_bss_.empty())
|
if (this->output_data_.empty() && this->output_bss_.empty())
|
||||||
{
|
{
|
||||||
this->vaddr_ = 0;
|
this->vaddr_ = 0;
|
||||||
this->paddr_ = 0;
|
this->paddr_ = 0;
|
||||||
|
this->are_addresses_set_ = true;
|
||||||
this->memsz_ = 0;
|
this->memsz_ = 0;
|
||||||
this->align_ = 0;
|
this->min_p_align_ = 0;
|
||||||
this->offset_ = 0;
|
this->offset_ = 0;
|
||||||
this->filesz_ = 0;
|
this->filesz_ = 0;
|
||||||
return;
|
return;
|
||||||
|
@ -2234,7 +2390,10 @@ Output_segment::set_offset()
|
||||||
else
|
else
|
||||||
first = this->output_data_.front();
|
first = this->output_data_.front();
|
||||||
this->vaddr_ = first->address();
|
this->vaddr_ = first->address();
|
||||||
this->paddr_ = this->vaddr_;
|
this->paddr_ = (first->has_load_address()
|
||||||
|
? first->load_address()
|
||||||
|
: this->vaddr_);
|
||||||
|
this->are_addresses_set_ = true;
|
||||||
this->offset_ = first->offset();
|
this->offset_ = first->offset();
|
||||||
|
|
||||||
if (this->output_data_.empty())
|
if (this->output_data_.empty())
|
||||||
|
@ -2275,6 +2434,26 @@ Output_segment::set_tls_offsets()
|
||||||
(*p)->set_tls_offset(this->vaddr_);
|
(*p)->set_tls_offset(this->vaddr_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the address of the first section.
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
Output_segment::first_section_load_address() const
|
||||||
|
{
|
||||||
|
for (Output_data_list::const_iterator p = this->output_data_.begin();
|
||||||
|
p != this->output_data_.end();
|
||||||
|
++p)
|
||||||
|
if ((*p)->is_section())
|
||||||
|
return (*p)->has_load_address() ? (*p)->load_address() : (*p)->address();
|
||||||
|
|
||||||
|
for (Output_data_list::const_iterator p = this->output_bss_.begin();
|
||||||
|
p != this->output_bss_.end();
|
||||||
|
++p)
|
||||||
|
if ((*p)->is_section())
|
||||||
|
return (*p)->has_load_address() ? (*p)->load_address() : (*p)->address();
|
||||||
|
|
||||||
|
gold_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
// Return the number of Output_sections in an Output_segment.
|
// Return the number of Output_sections in an Output_segment.
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
|
@ -2313,7 +2492,7 @@ Output_segment::write_header(elfcpp::Phdr_write<size, big_endian>* ophdr)
|
||||||
ophdr->put_p_filesz(this->filesz_);
|
ophdr->put_p_filesz(this->filesz_);
|
||||||
ophdr->put_p_memsz(this->memsz_);
|
ophdr->put_p_memsz(this->memsz_);
|
||||||
ophdr->put_p_flags(this->flags_);
|
ophdr->put_p_flags(this->flags_);
|
||||||
ophdr->put_p_align(this->addralign());
|
ophdr->put_p_align(std::max(this->min_p_align_, this->maximum_alignment()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the section headers into V.
|
// Write the section headers into V.
|
||||||
|
@ -2534,7 +2713,8 @@ Output_section::add_input_section<32, false>(
|
||||||
unsigned int shndx,
|
unsigned int shndx,
|
||||||
const char* secname,
|
const char* secname,
|
||||||
const elfcpp::Shdr<32, false>& shdr,
|
const elfcpp::Shdr<32, false>& shdr,
|
||||||
unsigned int reloc_shndx);
|
unsigned int reloc_shndx,
|
||||||
|
bool have_sections_script);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_TARGET_32_BIG
|
#ifdef HAVE_TARGET_32_BIG
|
||||||
|
@ -2545,7 +2725,8 @@ Output_section::add_input_section<32, true>(
|
||||||
unsigned int shndx,
|
unsigned int shndx,
|
||||||
const char* secname,
|
const char* secname,
|
||||||
const elfcpp::Shdr<32, true>& shdr,
|
const elfcpp::Shdr<32, true>& shdr,
|
||||||
unsigned int reloc_shndx);
|
unsigned int reloc_shndx,
|
||||||
|
bool have_sections_script);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_TARGET_64_LITTLE
|
#ifdef HAVE_TARGET_64_LITTLE
|
||||||
|
@ -2556,7 +2737,8 @@ Output_section::add_input_section<64, false>(
|
||||||
unsigned int shndx,
|
unsigned int shndx,
|
||||||
const char* secname,
|
const char* secname,
|
||||||
const elfcpp::Shdr<64, false>& shdr,
|
const elfcpp::Shdr<64, false>& shdr,
|
||||||
unsigned int reloc_shndx);
|
unsigned int reloc_shndx,
|
||||||
|
bool have_sections_script);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_TARGET_64_BIG
|
#ifdef HAVE_TARGET_64_BIG
|
||||||
|
@ -2567,7 +2749,8 @@ Output_section::add_input_section<64, true>(
|
||||||
unsigned int shndx,
|
unsigned int shndx,
|
||||||
const char* secname,
|
const char* secname,
|
||||||
const elfcpp::Shdr<64, true>& shdr,
|
const elfcpp::Shdr<64, true>& shdr,
|
||||||
unsigned int reloc_shndx);
|
unsigned int reloc_shndx,
|
||||||
|
bool have_sections_script);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_TARGET_32_LITTLE
|
#ifdef HAVE_TARGET_32_LITTLE
|
||||||
|
|
245
gold/output.h
245
gold/output.h
|
@ -88,11 +88,32 @@ class Output_data
|
||||||
return this->offset_;
|
return this->offset_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset the address and file offset. This essentially disables the
|
||||||
|
// sanity testing about duplicate and unknown settings.
|
||||||
|
void
|
||||||
|
reset_address_and_file_offset()
|
||||||
|
{
|
||||||
|
this->is_address_valid_ = false;
|
||||||
|
this->is_offset_valid_ = false;
|
||||||
|
this->is_data_size_valid_ = false;
|
||||||
|
this->do_reset_address_and_file_offset();
|
||||||
|
}
|
||||||
|
|
||||||
// Return the required alignment.
|
// Return the required alignment.
|
||||||
uint64_t
|
uint64_t
|
||||||
addralign() const
|
addralign() const
|
||||||
{ return this->do_addralign(); }
|
{ return this->do_addralign(); }
|
||||||
|
|
||||||
|
// Return whether this has a load address.
|
||||||
|
bool
|
||||||
|
has_load_address() const
|
||||||
|
{ return this->do_has_load_address(); }
|
||||||
|
|
||||||
|
// Return the load address.
|
||||||
|
uint64_t
|
||||||
|
load_address() const
|
||||||
|
{ return this->do_load_address(); }
|
||||||
|
|
||||||
// Return whether this is an Output_section.
|
// Return whether this is an Output_section.
|
||||||
bool
|
bool
|
||||||
is_section() const
|
is_section() const
|
||||||
|
@ -224,6 +245,16 @@ class Output_data
|
||||||
virtual uint64_t
|
virtual uint64_t
|
||||||
do_addralign() const = 0;
|
do_addralign() const = 0;
|
||||||
|
|
||||||
|
// Return whether this has a load address.
|
||||||
|
virtual bool
|
||||||
|
do_has_load_address() const
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
|
// Return the load address.
|
||||||
|
virtual uint64_t
|
||||||
|
do_load_address() const
|
||||||
|
{ gold_unreachable(); }
|
||||||
|
|
||||||
// Return whether this is an Output_section.
|
// Return whether this is an Output_section.
|
||||||
virtual bool
|
virtual bool
|
||||||
do_is_section() const
|
do_is_section() const
|
||||||
|
@ -258,6 +289,11 @@ class Output_data
|
||||||
set_final_data_size()
|
set_final_data_size()
|
||||||
{ gold_unreachable(); }
|
{ gold_unreachable(); }
|
||||||
|
|
||||||
|
// A hook for resetting the address and file offset.
|
||||||
|
virtual void
|
||||||
|
do_reset_address_and_file_offset()
|
||||||
|
{ }
|
||||||
|
|
||||||
// Set the TLS offset. Called only for SHT_TLS sections.
|
// Set the TLS offset. Called only for SHT_TLS sections.
|
||||||
virtual void
|
virtual void
|
||||||
do_set_tls_offset(uint64_t)
|
do_set_tls_offset(uint64_t)
|
||||||
|
@ -1491,13 +1527,16 @@ class Output_section : public Output_data
|
||||||
// Add a new input section SHNDX, named NAME, with header SHDR, from
|
// Add a new input section SHNDX, named NAME, with header SHDR, from
|
||||||
// object OBJECT. RELOC_SHNDX is the index of a relocation section
|
// object OBJECT. RELOC_SHNDX is the index of a relocation section
|
||||||
// which applies to this section, or 0 if none, or -1U if more than
|
// which applies to this section, or 0 if none, or -1U if more than
|
||||||
// one. Return the offset within the output section.
|
// one. HAVE_SECTIONS_SCRIPT is true if we have a SECTIONS clause
|
||||||
|
// in a linker script; in that case we need to keep track of input
|
||||||
|
// sections associated with an output section. Return the offset
|
||||||
|
// within the output section.
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
off_t
|
off_t
|
||||||
add_input_section(Sized_relobj<size, big_endian>* object, unsigned int shndx,
|
add_input_section(Sized_relobj<size, big_endian>* object, unsigned int shndx,
|
||||||
const char *name,
|
const char *name,
|
||||||
const elfcpp::Shdr<size, big_endian>& shdr,
|
const elfcpp::Shdr<size, big_endian>& shdr,
|
||||||
unsigned int reloc_shndx);
|
unsigned int reloc_shndx, bool have_sections_script);
|
||||||
|
|
||||||
// Add generated data POSD to this output section.
|
// Add generated data POSD to this output section.
|
||||||
void
|
void
|
||||||
|
@ -1527,6 +1566,14 @@ class Output_section : public Output_data
|
||||||
void
|
void
|
||||||
set_entsize(uint64_t v);
|
set_entsize(uint64_t v);
|
||||||
|
|
||||||
|
// Set the load address.
|
||||||
|
void
|
||||||
|
set_load_address(uint64_t load_address)
|
||||||
|
{
|
||||||
|
this->load_address_ = load_address;
|
||||||
|
this->has_load_address_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Set the link field to the output section index of a section.
|
// Set the link field to the output section index of a section.
|
||||||
void
|
void
|
||||||
set_link_section(const Output_data* od)
|
set_link_section(const Output_data* od)
|
||||||
|
@ -1709,12 +1756,53 @@ class Output_section : public Output_data
|
||||||
uint64_t
|
uint64_t
|
||||||
starting_output_address(const Relobj* object, unsigned int shndx) const;
|
starting_output_address(const Relobj* object, unsigned int shndx) const;
|
||||||
|
|
||||||
|
// Record that this output section was found in the SECTIONS clause
|
||||||
|
// of a linker script.
|
||||||
|
void
|
||||||
|
set_found_in_sections_clause()
|
||||||
|
{ this->found_in_sections_clause_ = true; }
|
||||||
|
|
||||||
|
// Return whether this output section was found in the SECTIONS
|
||||||
|
// clause of a linker script.
|
||||||
|
bool
|
||||||
|
found_in_sections_clause() const
|
||||||
|
{ return this->found_in_sections_clause_; }
|
||||||
|
|
||||||
// Write the section header into *OPHDR.
|
// Write the section header into *OPHDR.
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
void
|
void
|
||||||
write_header(const Layout*, const Stringpool*,
|
write_header(const Layout*, const Stringpool*,
|
||||||
elfcpp::Shdr_write<size, big_endian>*) const;
|
elfcpp::Shdr_write<size, big_endian>*) const;
|
||||||
|
|
||||||
|
// The next few calls are for linker script support.
|
||||||
|
|
||||||
|
// Store the list of input sections for this Output_section into the
|
||||||
|
// list passed in. This removes the input sections, leaving only
|
||||||
|
// any Output_section_data elements. This returns the size of those
|
||||||
|
// Output_section_data elements. ADDRESS is the address of this
|
||||||
|
// output section. FILL is the fill value to use, in case there are
|
||||||
|
// any spaces between the remaining Output_section_data elements.
|
||||||
|
uint64_t
|
||||||
|
get_input_sections(uint64_t address, const std::string& fill,
|
||||||
|
std::list<std::pair<Relobj*, unsigned int > >*);
|
||||||
|
|
||||||
|
// Add an input section from a script.
|
||||||
|
void
|
||||||
|
add_input_section_for_script(Relobj* object, unsigned int shndx,
|
||||||
|
off_t data_size, uint64_t addralign);
|
||||||
|
|
||||||
|
// Set the current size of the output section.
|
||||||
|
void
|
||||||
|
set_current_data_size(off_t size)
|
||||||
|
{ this->set_current_data_size_for_child(size); }
|
||||||
|
|
||||||
|
// Get the current size of the output section.
|
||||||
|
off_t
|
||||||
|
current_data_size() const
|
||||||
|
{ return this->current_data_size_for_child(); }
|
||||||
|
|
||||||
|
// End of linker script support.
|
||||||
|
|
||||||
// Print merge statistics to stderr.
|
// Print merge statistics to stderr.
|
||||||
void
|
void
|
||||||
print_merge_stats();
|
print_merge_stats();
|
||||||
|
@ -1732,7 +1820,7 @@ class Output_section : public Output_data
|
||||||
void
|
void
|
||||||
do_set_out_shndx(unsigned int shndx)
|
do_set_out_shndx(unsigned int shndx)
|
||||||
{
|
{
|
||||||
gold_assert(this->out_shndx_ == -1U);
|
gold_assert(this->out_shndx_ == -1U || this->out_shndx_ == shndx);
|
||||||
this->out_shndx_ = shndx;
|
this->out_shndx_ = shndx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1743,6 +1831,10 @@ class Output_section : public Output_data
|
||||||
virtual void
|
virtual void
|
||||||
set_final_data_size();
|
set_final_data_size();
|
||||||
|
|
||||||
|
// Reset the address and file offset.
|
||||||
|
void
|
||||||
|
do_reset_address_and_file_offset();
|
||||||
|
|
||||||
// Write the data to the file. For a typical Output_section, this
|
// Write the data to the file. For a typical Output_section, this
|
||||||
// does nothing: the data is written out by calling Object::Relocate
|
// does nothing: the data is written out by calling Object::Relocate
|
||||||
// on each input object. But if there are any Output_section_data
|
// on each input object. But if there are any Output_section_data
|
||||||
|
@ -1755,6 +1847,19 @@ class Output_section : public Output_data
|
||||||
do_addralign() const
|
do_addralign() const
|
||||||
{ return this->addralign_; }
|
{ return this->addralign_; }
|
||||||
|
|
||||||
|
// Return whether there is a load address.
|
||||||
|
bool
|
||||||
|
do_has_load_address() const
|
||||||
|
{ return this->has_load_address_; }
|
||||||
|
|
||||||
|
// Return the load address.
|
||||||
|
uint64_t
|
||||||
|
do_load_address() const
|
||||||
|
{
|
||||||
|
gold_assert(this->has_load_address_);
|
||||||
|
return this->load_address_;
|
||||||
|
}
|
||||||
|
|
||||||
// Return whether this is an Output_section.
|
// Return whether this is an Output_section.
|
||||||
bool
|
bool
|
||||||
do_is_section() const
|
do_is_section() const
|
||||||
|
@ -1877,6 +1982,15 @@ class Output_section : public Output_data
|
||||||
off_t
|
off_t
|
||||||
data_size() const;
|
data_size() const;
|
||||||
|
|
||||||
|
// Whether this is an input section.
|
||||||
|
bool
|
||||||
|
is_input_section() const
|
||||||
|
{
|
||||||
|
return (this->shndx_ != OUTPUT_SECTION_CODE
|
||||||
|
&& this->shndx_ != MERGE_DATA_SECTION_CODE
|
||||||
|
&& this->shndx_ != MERGE_STRING_SECTION_CODE);
|
||||||
|
}
|
||||||
|
|
||||||
// Return whether this is a merge section which matches the
|
// Return whether this is a merge section which matches the
|
||||||
// parameters.
|
// parameters.
|
||||||
bool
|
bool
|
||||||
|
@ -1890,6 +2004,22 @@ class Output_section : public Output_data
|
||||||
&& this->addralign() == addralign);
|
&& this->addralign() == addralign);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the object for an input section.
|
||||||
|
Relobj*
|
||||||
|
relobj() const
|
||||||
|
{
|
||||||
|
gold_assert(this->is_input_section());
|
||||||
|
return this->u2_.object;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the input section index for an input section.
|
||||||
|
unsigned int
|
||||||
|
shndx() const
|
||||||
|
{
|
||||||
|
gold_assert(this->is_input_section());
|
||||||
|
return this->shndx_;
|
||||||
|
}
|
||||||
|
|
||||||
// Set the output section.
|
// Set the output section.
|
||||||
void
|
void
|
||||||
set_output_section(Output_section* os)
|
set_output_section(Output_section* os)
|
||||||
|
@ -1905,6 +2035,10 @@ class Output_section : public Output_data
|
||||||
set_address_and_file_offset(uint64_t address, off_t file_offset,
|
set_address_and_file_offset(uint64_t address, off_t file_offset,
|
||||||
off_t section_file_offset);
|
off_t section_file_offset);
|
||||||
|
|
||||||
|
// Reset the address and file offset.
|
||||||
|
void
|
||||||
|
reset_address_and_file_offset();
|
||||||
|
|
||||||
// Finalize the data size.
|
// Finalize the data size.
|
||||||
void
|
void
|
||||||
finalize_data_size();
|
finalize_data_size();
|
||||||
|
@ -1968,15 +2102,6 @@ class Output_section : public Output_data
|
||||||
MERGE_STRING_SECTION_CODE = -3U
|
MERGE_STRING_SECTION_CODE = -3U
|
||||||
};
|
};
|
||||||
|
|
||||||
// Whether this is an input section.
|
|
||||||
bool
|
|
||||||
is_input_section() const
|
|
||||||
{
|
|
||||||
return (this->shndx_ != OUTPUT_SECTION_CODE
|
|
||||||
&& this->shndx_ != MERGE_DATA_SECTION_CODE
|
|
||||||
&& this->shndx_ != MERGE_STRING_SECTION_CODE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// For an ordinary input section, this is the section index in the
|
// For an ordinary input section, this is the section index in the
|
||||||
// input file. For an Output_section_data, this is
|
// input file. For an Output_section_data, this is
|
||||||
// OUTPUT_SECTION_CODE or MERGE_DATA_SECTION_CODE or
|
// OUTPUT_SECTION_CODE or MERGE_DATA_SECTION_CODE or
|
||||||
|
@ -2007,15 +2132,16 @@ class Output_section : public Output_data
|
||||||
typedef std::vector<Input_section> Input_section_list;
|
typedef std::vector<Input_section> Input_section_list;
|
||||||
|
|
||||||
// Fill data. This is used to fill in data between input sections.
|
// Fill data. This is used to fill in data between input sections.
|
||||||
// When we have to keep track of the input sections, we can use an
|
// It is also used for data statements (BYTE, WORD, etc.) in linker
|
||||||
// Output_data_const, but we don't want to have to keep track of
|
// scripts. When we have to keep track of the input sections, we
|
||||||
// input sections just to implement fills. For a fill we record the
|
// can use an Output_data_const, but we don't want to have to keep
|
||||||
// offset, and the actual data to be written out.
|
// track of input sections just to implement fills.
|
||||||
class Fill
|
class Fill
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Fill(off_t section_offset, off_t length)
|
Fill(off_t section_offset, off_t length)
|
||||||
: section_offset_(section_offset), length_(length)
|
: section_offset_(section_offset),
|
||||||
|
length_(convert_to_section_size_type(length))
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
// Return section offset.
|
// Return section offset.
|
||||||
|
@ -2024,7 +2150,7 @@ class Output_section : public Output_data
|
||||||
{ return this->section_offset_; }
|
{ return this->section_offset_; }
|
||||||
|
|
||||||
// Return fill length.
|
// Return fill length.
|
||||||
off_t
|
section_size_type
|
||||||
length() const
|
length() const
|
||||||
{ return this->length_; }
|
{ return this->length_; }
|
||||||
|
|
||||||
|
@ -2032,7 +2158,7 @@ class Output_section : public Output_data
|
||||||
// The offset within the output section.
|
// The offset within the output section.
|
||||||
off_t section_offset_;
|
off_t section_offset_;
|
||||||
// The length of the space to fill.
|
// The length of the space to fill.
|
||||||
off_t length_;
|
section_size_type length_;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<Fill> Fill_list;
|
typedef std::vector<Fill> Fill_list;
|
||||||
|
@ -2064,6 +2190,10 @@ class Output_section : public Output_data
|
||||||
uint64_t addralign_;
|
uint64_t addralign_;
|
||||||
// The section entry size.
|
// The section entry size.
|
||||||
uint64_t entsize_;
|
uint64_t entsize_;
|
||||||
|
// The load address. This is only used when using a linker script
|
||||||
|
// with a SECTIONS clause. The has_load_address_ field indicates
|
||||||
|
// whether this field is valid.
|
||||||
|
uint64_t load_address_;
|
||||||
// The file offset is in the parent class.
|
// The file offset is in the parent class.
|
||||||
// Set the section link field to the index of this section.
|
// Set the section link field to the index of this section.
|
||||||
const Output_data* link_section_;
|
const Output_data* link_section_;
|
||||||
|
@ -2076,7 +2206,7 @@ class Output_section : public Output_data
|
||||||
// The section type.
|
// The section type.
|
||||||
const elfcpp::Elf_Word type_;
|
const elfcpp::Elf_Word type_;
|
||||||
// The section flags.
|
// The section flags.
|
||||||
const elfcpp::Elf_Xword flags_;
|
elfcpp::Elf_Xword flags_;
|
||||||
// The section index.
|
// The section index.
|
||||||
unsigned int out_shndx_;
|
unsigned int out_shndx_;
|
||||||
// If there is a STT_SECTION for this output section in the normal
|
// If there is a STT_SECTION for this output section in the normal
|
||||||
|
@ -2121,6 +2251,11 @@ class Output_section : public Output_data
|
||||||
// Whether this section requires post processing after all
|
// Whether this section requires post processing after all
|
||||||
// relocations have been applied.
|
// relocations have been applied.
|
||||||
bool requires_postprocessing_ : 1;
|
bool requires_postprocessing_ : 1;
|
||||||
|
// Whether an input section was mapped to this output section
|
||||||
|
// because of a SECTIONS clause in a linker script.
|
||||||
|
bool found_in_sections_clause_ : 1;
|
||||||
|
// Whether this section has an explicitly specified load address.
|
||||||
|
bool has_load_address_ : 1;
|
||||||
// For SHT_TLS sections, the offset of this section relative to the base
|
// For SHT_TLS sections, the offset of this section relative to the base
|
||||||
// of the TLS segment.
|
// of the TLS segment.
|
||||||
uint64_t tls_offset_;
|
uint64_t tls_offset_;
|
||||||
|
@ -2168,7 +2303,7 @@ class Output_segment
|
||||||
|
|
||||||
// Return the maximum alignment of the Output_data.
|
// Return the maximum alignment of the Output_data.
|
||||||
uint64_t
|
uint64_t
|
||||||
addralign();
|
maximum_alignment();
|
||||||
|
|
||||||
// Add an Output_section to this segment.
|
// Add an Output_section to this segment.
|
||||||
void
|
void
|
||||||
|
@ -2189,23 +2324,40 @@ class Output_segment
|
||||||
unsigned int
|
unsigned int
|
||||||
dynamic_reloc_count() const;
|
dynamic_reloc_count() const;
|
||||||
|
|
||||||
// Set the address of the segment to ADDR and the offset to *POFF
|
// Return the address of the first section.
|
||||||
// (aligned if necessary), and set the addresses and offsets of all
|
|
||||||
// contained output sections accordingly. Set the section indexes
|
|
||||||
// of all contained output sections starting with *PSHNDX. Return
|
|
||||||
// the address of the immediately following segment. Update *POFF
|
|
||||||
// and *PSHNDX. This should only be called for a PT_LOAD segment.
|
|
||||||
uint64_t
|
uint64_t
|
||||||
set_section_addresses(uint64_t addr, off_t* poff, unsigned int* pshndx);
|
first_section_load_address() const;
|
||||||
|
|
||||||
|
// Return whether the addresses have been set already.
|
||||||
|
bool
|
||||||
|
are_addresses_set() const
|
||||||
|
{ return this->are_addresses_set_; }
|
||||||
|
|
||||||
|
// Set the addresses.
|
||||||
|
void
|
||||||
|
set_addresses(uint64_t vaddr, uint64_t paddr)
|
||||||
|
{
|
||||||
|
this->vaddr_ = vaddr;
|
||||||
|
this->paddr_ = paddr;
|
||||||
|
this->are_addresses_set_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the address of the segment to ADDR and the offset to *POFF
|
||||||
|
// and set the addresses and offsets of all contained output
|
||||||
|
// sections accordingly. Set the section indexes of all contained
|
||||||
|
// output sections starting with *PSHNDX. If RESET is true, first
|
||||||
|
// reset the addresses of the contained sections. Return the
|
||||||
|
// address of the immediately following segment. Update *POFF and
|
||||||
|
// *PSHNDX. This should only be called for a PT_LOAD segment.
|
||||||
|
uint64_t
|
||||||
|
set_section_addresses(bool reset, uint64_t addr, off_t* poff,
|
||||||
|
unsigned int* pshndx);
|
||||||
|
|
||||||
// Set the minimum alignment of this segment. This may be adjusted
|
// Set the minimum alignment of this segment. This may be adjusted
|
||||||
// upward based on the section alignments.
|
// upward based on the section alignments.
|
||||||
void
|
void
|
||||||
set_minimum_addralign(uint64_t align)
|
set_minimum_p_align(uint64_t align)
|
||||||
{
|
{ this->min_p_align_ = align; }
|
||||||
gold_assert(!this->is_align_known_);
|
|
||||||
this->align_ = align;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the offset of this segment based on the section. This should
|
// Set the offset of this segment based on the section. This should
|
||||||
// only be called for a non-PT_LOAD segment.
|
// only be called for a non-PT_LOAD segment.
|
||||||
|
@ -2244,12 +2396,12 @@ class Output_segment
|
||||||
|
|
||||||
// Find the maximum alignment in an Output_data_list.
|
// Find the maximum alignment in an Output_data_list.
|
||||||
static uint64_t
|
static uint64_t
|
||||||
maximum_alignment(const Output_data_list*);
|
maximum_alignment_list(const Output_data_list*);
|
||||||
|
|
||||||
// Set the section addresses in an Output_data_list.
|
// Set the section addresses in an Output_data_list.
|
||||||
uint64_t
|
uint64_t
|
||||||
set_section_list_addresses(Output_data_list*, uint64_t addr, off_t* poff,
|
set_section_list_addresses(bool reset, Output_data_list*, uint64_t addr,
|
||||||
unsigned int* pshndx);
|
off_t* poff, unsigned int* pshndx);
|
||||||
|
|
||||||
// Return the number of Output_sections in an Output_data_list.
|
// Return the number of Output_sections in an Output_data_list.
|
||||||
unsigned int
|
unsigned int
|
||||||
|
@ -2276,10 +2428,17 @@ class Output_segment
|
||||||
uint64_t paddr_;
|
uint64_t paddr_;
|
||||||
// The size of the segment in memory.
|
// The size of the segment in memory.
|
||||||
uint64_t memsz_;
|
uint64_t memsz_;
|
||||||
// The segment alignment. The is_align_known_ field indicates
|
// The maximum section alignment. The is_max_align_known_ field
|
||||||
// whether this has been finalized. It can be set to a minimum
|
// indicates whether this has been finalized.
|
||||||
// value before it is finalized.
|
uint64_t max_align_;
|
||||||
uint64_t align_;
|
// The required minimum value for the p_align field. This is used
|
||||||
|
// for PT_LOAD segments. Note that this does not mean that
|
||||||
|
// addresses should be aligned to this value; it means the p_paddr
|
||||||
|
// and p_vaddr fields must be congruent modulo this value. For
|
||||||
|
// non-PT_LOAD segments, the dynamic linker works more efficiently
|
||||||
|
// if the p_align field has the more conventional value, although it
|
||||||
|
// can align as needed.
|
||||||
|
uint64_t min_p_align_;
|
||||||
// The offset of the segment data within the file.
|
// The offset of the segment data within the file.
|
||||||
off_t offset_;
|
off_t offset_;
|
||||||
// The size of the segment data in the file.
|
// The size of the segment data in the file.
|
||||||
|
@ -2288,8 +2447,10 @@ class Output_segment
|
||||||
elfcpp::Elf_Word type_;
|
elfcpp::Elf_Word type_;
|
||||||
// The segment flags.
|
// The segment flags.
|
||||||
elfcpp::Elf_Word flags_;
|
elfcpp::Elf_Word flags_;
|
||||||
// Whether we have finalized align_.
|
// Whether we have finalized max_align_.
|
||||||
bool is_align_known_;
|
bool is_max_align_known_ : 1;
|
||||||
|
// Whether vaddr and paddr were set by a linker script.
|
||||||
|
bool are_addresses_set_ : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This class represents the output file.
|
// This class represents the output file.
|
||||||
|
|
|
@ -45,6 +45,8 @@ resolve.cc
|
||||||
script.cc
|
script.cc
|
||||||
script-c.h
|
script-c.h
|
||||||
script.h
|
script.h
|
||||||
|
script-sections.cc
|
||||||
|
script-sections.h
|
||||||
stringpool.cc
|
stringpool.cc
|
||||||
stringpool.h
|
stringpool.h
|
||||||
symtab.cc
|
symtab.cc
|
||||||
|
|
398
gold/po/gold.pot
398
gold/po/gold.pot
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2008-01-09 11:37-0800\n"
|
"POT-Creation-Date: 2008-02-01 22:48-0800\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -61,7 +61,7 @@ msgstr ""
|
||||||
msgid "%s: member at %zu is not an ELF object"
|
msgid "%s: member at %zu is not an ELF object"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: compressed_output.cc:126
|
#: compressed_output.cc:127
|
||||||
msgid "not compressing section data: zlib error"
|
msgid "not compressing section data: zlib error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -70,115 +70,115 @@ msgstr ""
|
||||||
msgid "%s: can not read directory: %s"
|
msgid "%s: can not read directory: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:145
|
#: dynobj.cc:147
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "unexpected duplicate type %u section: %u, %u"
|
msgid "unexpected duplicate type %u section: %u, %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:181
|
#: dynobj.cc:183
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "unexpected link in section %u header: %u != %u"
|
msgid "unexpected link in section %u header: %u != %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:217
|
#: dynobj.cc:219
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "DYNAMIC section %u link out of range: %u"
|
msgid "DYNAMIC section %u link out of range: %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:225
|
#: dynobj.cc:227
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "DYNAMIC section %u link %u is not a strtab"
|
msgid "DYNAMIC section %u link %u is not a strtab"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:253
|
#: dynobj.cc:255
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "DT_SONAME value out of range: %lld >= %lld"
|
msgid "DT_SONAME value out of range: %lld >= %lld"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:265
|
#: dynobj.cc:267
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "DT_NEEDED value out of range: %lld >= %lld"
|
msgid "DT_NEEDED value out of range: %lld >= %lld"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:278
|
#: dynobj.cc:280
|
||||||
msgid "missing DT_NULL in dynamic segment"
|
msgid "missing DT_NULL in dynamic segment"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:323
|
#: dynobj.cc:325
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "invalid dynamic symbol table name index: %u"
|
msgid "invalid dynamic symbol table name index: %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:330
|
#: dynobj.cc:332
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "dynamic symbol table name section has wrong type: %u"
|
msgid "dynamic symbol table name section has wrong type: %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:404 object.cc:251 object.cc:589
|
#: dynobj.cc:406 object.cc:251 object.cc:589
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "bad section name offset for section %u: %lu"
|
msgid "bad section name offset for section %u: %lu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:433
|
#: dynobj.cc:435
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "duplicate definition for version %u"
|
msgid "duplicate definition for version %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:462
|
#: dynobj.cc:464
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "unexpected verdef version %u"
|
msgid "unexpected verdef version %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:478
|
#: dynobj.cc:480
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "verdef vd_cnt field too small: %u"
|
msgid "verdef vd_cnt field too small: %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:486
|
#: dynobj.cc:488
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "verdef vd_aux field out of range: %u"
|
msgid "verdef vd_aux field out of range: %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:497
|
#: dynobj.cc:499
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "verdaux vda_name field out of range: %u"
|
msgid "verdaux vda_name field out of range: %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:507
|
#: dynobj.cc:509
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "verdef vd_next field out of range: %u"
|
msgid "verdef vd_next field out of range: %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:541
|
#: dynobj.cc:543
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "unexpected verneed version %u"
|
msgid "unexpected verneed version %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:550
|
#: dynobj.cc:552
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "verneed vn_aux field out of range: %u"
|
msgid "verneed vn_aux field out of range: %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:564
|
#: dynobj.cc:566
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "vernaux vna_name field out of range: %u"
|
msgid "vernaux vna_name field out of range: %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:575
|
#: dynobj.cc:577
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "verneed vna_next field out of range: %u"
|
msgid "verneed vna_next field out of range: %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:586
|
#: dynobj.cc:588
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "verneed vn_next field out of range: %u"
|
msgid "verneed vn_next field out of range: %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:634
|
#: dynobj.cc:636
|
||||||
msgid "size of dynamic symbols is not multiple of symbol size"
|
msgid "size of dynamic symbols is not multiple of symbol size"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:1316
|
#: dynobj.cc:1355
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "symbol %s has undefined version %s"
|
msgid "symbol %s has undefined version %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -203,64 +203,60 @@ msgstr ""
|
||||||
msgid "%s: "
|
msgid "%s: "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: expression.cc:104
|
#: expression.cc:113
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "undefined symbol '%s' referenced in expression"
|
msgid "undefined symbol '%s' referenced in expression"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: expression.cc:427
|
#: expression.cc:566
|
||||||
msgid "DEFINED not implemented"
|
msgid "DEFINED not implemented"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: expression.cc:433
|
#: expression.cc:572
|
||||||
msgid "SIZEOF_HEADERS not implemented"
|
msgid "SIZEOF_HEADERS not implemented"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: expression.cc:439
|
#: expression.cc:578
|
||||||
msgid "ALIGNOF not implemented"
|
msgid "ALIGNOF not implemented"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: expression.cc:445
|
#: expression.cc:584
|
||||||
msgid "SIZEOF not implemented"
|
msgid "SIZEOF not implemented"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: expression.cc:451
|
#: expression.cc:590
|
||||||
msgid "ADDR not implemented"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: expression.cc:457
|
|
||||||
msgid "LOADADDR not implemented"
|
msgid "LOADADDR not implemented"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: expression.cc:463
|
#: expression.cc:596
|
||||||
msgid "ORIGIN not implemented"
|
msgid "ORIGIN not implemented"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: expression.cc:469
|
#: expression.cc:602
|
||||||
msgid "LENGTH not implemented"
|
msgid "LENGTH not implemented"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: expression.cc:475
|
#: expression.cc:608
|
||||||
msgid "CONSTANT not implemented"
|
msgid "CONSTANT not implemented"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: expression.cc:481
|
#: expression.cc:614
|
||||||
msgid "ABSOLUTE not implemented"
|
msgid "ABSOLUTE not implemented"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: expression.cc:487
|
#: expression.cc:620
|
||||||
msgid "DATA_SEGMENT_ALIGN not implemented"
|
msgid "DATA_SEGMENT_ALIGN not implemented"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: expression.cc:493
|
#: expression.cc:626
|
||||||
msgid "DATA_SEGMENT_RELRO_END not implemented"
|
msgid "DATA_SEGMENT_RELRO_END not implemented"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: expression.cc:499
|
#: expression.cc:632
|
||||||
msgid "DATA_SEGMENT_END not implemented"
|
msgid "DATA_SEGMENT_END not implemented"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: expression.cc:505
|
#: expression.cc:638
|
||||||
msgid "SEGMENT_START not implemented"
|
msgid "SEGMENT_START not implemented"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -319,34 +315,34 @@ msgstr ""
|
||||||
msgid "%s: maximum bytes mapped for read at one time: %llu\n"
|
msgid "%s: maximum bytes mapped for read at one time: %llu\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: fileread.cc:628
|
#: fileread.cc:642
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "cannot find -l%s"
|
msgid "cannot find -l%s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: fileread.cc:655
|
#: fileread.cc:669
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "cannot find %s"
|
msgid "cannot find %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: fileread.cc:666
|
#: fileread.cc:680
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "cannot open %s: %s"
|
msgid "cannot open %s: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: gold.cc:72
|
#: gold.cc:73
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: internal error in %s, at %s:%d\n"
|
msgid "%s: internal error in %s, at %s:%d\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. We had some input files, but we weren't able to open any of
|
#. We had some input files, but we weren't able to open any of
|
||||||
#. them.
|
#. them.
|
||||||
#: gold.cc:118 gold.cc:166
|
#: gold.cc:119 gold.cc:167
|
||||||
msgid "no input files"
|
msgid "no input files"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. We print out just the first .so we see; there may be others.
|
#. We print out just the first .so we see; there may be others.
|
||||||
#: gold.cc:181
|
#: gold.cc:182
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "cannot mix -static with dynamic object %s"
|
msgid "cannot mix -static with dynamic object %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -412,42 +408,42 @@ msgid "pthread_cond_broadcast failed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. FIXME: This needs to specify the location somehow.
|
#. FIXME: This needs to specify the location somehow.
|
||||||
#: i386.cc:160 i386.cc:1484 x86_64.cc:172 x86_64.cc:1373
|
#: i386.cc:160 i386.cc:1490 x86_64.cc:172 x86_64.cc:1375
|
||||||
msgid "missing expected TLS relocation"
|
msgid "missing expected TLS relocation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: i386.cc:810 x86_64.cc:764 x86_64.cc:978
|
#: i386.cc:809 x86_64.cc:764 x86_64.cc:978
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: unsupported reloc %u against local symbol"
|
msgid "%s: unsupported reloc %u against local symbol"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: i386.cc:917 i386.cc:1213 x86_64.cc:889 x86_64.cc:1160
|
#: i386.cc:916 i386.cc:1214 x86_64.cc:889 x86_64.cc:1162
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: unexpected reloc %u in object file"
|
msgid "%s: unexpected reloc %u in object file"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: i386.cc:1056 x86_64.cc:992 x86_64.cc:1256
|
#: i386.cc:1055 x86_64.cc:992 x86_64.cc:1258
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: unsupported reloc %u against global symbol %s"
|
msgid "%s: unsupported reloc %u against global symbol %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: i386.cc:1367
|
#: i386.cc:1368
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: unsupported RELA reloc section"
|
msgid "%s: unsupported RELA reloc section"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: i386.cc:1627 x86_64.cc:1575
|
#: i386.cc:1640 x86_64.cc:1577
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "unexpected reloc %u in object file"
|
msgid "unexpected reloc %u in object file"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: i386.cc:1659 i386.cc:1734 i386.cc:1741 i386.cc:1772 i386.cc:1825
|
#: i386.cc:1672 i386.cc:1747 i386.cc:1754 i386.cc:1785 i386.cc:1838
|
||||||
#: x86_64.cc:1596 x86_64.cc:1676 x86_64.cc:1700
|
#: x86_64.cc:1598 x86_64.cc:1678 x86_64.cc:1702
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "unsupported reloc %u"
|
msgid "unsupported reloc %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: i386.cc:1749
|
#: i386.cc:1762
|
||||||
msgid "both SUN and GNU model TLS relocations"
|
msgid "both SUN and GNU model TLS relocations"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -604,365 +600,378 @@ msgstr ""
|
||||||
msgid "unable to parse script file %s"
|
msgid "unable to parse script file %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:185
|
#: options.cc:174
|
||||||
|
#, c-format
|
||||||
|
msgid "unable to parse version script file %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: options.cc:201
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Usage: %s [options] file...\n"
|
"Usage: %s [options] file...\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:356
|
#: options.cc:372
|
||||||
msgid "Allow unresolved references in shared libraries"
|
msgid "Allow unresolved references in shared libraries"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:360
|
#: options.cc:376
|
||||||
msgid "Do not allow unresolved references in shared libraries"
|
msgid "Do not allow unresolved references in shared libraries"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:364
|
#: options.cc:380
|
||||||
msgid "Only set DT_NEEDED for dynamic libs if used"
|
msgid "Only set DT_NEEDED for dynamic libs if used"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:367
|
#: options.cc:383
|
||||||
msgid "Always DT_NEEDED for dynamic libs (default)"
|
msgid "Always DT_NEEDED for dynamic libs (default)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:370
|
#: options.cc:386
|
||||||
msgid "-l searches for shared libraries"
|
msgid "-l searches for shared libraries"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:374
|
#: options.cc:390
|
||||||
msgid "-l does not search for shared libraries"
|
msgid "-l does not search for shared libraries"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:377
|
#: options.cc:393
|
||||||
msgid "Bind defined symbols locally"
|
msgid "Bind defined symbols locally"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:385
|
#: options.cc:401
|
||||||
msgid "Compress .debug_* sections in the output file (default is none)"
|
msgid "Compress .debug_* sections in the output file (default is none)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:387
|
#: options.cc:403
|
||||||
msgid "--compress-debug-sections=[none"
|
msgid "--compress-debug-sections=[none"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:387
|
#: options.cc:403
|
||||||
msgid "]"
|
msgid "]"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:390
|
#: options.cc:406
|
||||||
msgid "Define a symbol"
|
msgid "Define a symbol"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:391
|
#: options.cc:407
|
||||||
msgid "--defsym SYMBOL=EXPRESSION"
|
msgid "--defsym SYMBOL=EXPRESSION"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:393
|
#: options.cc:409
|
||||||
msgid "Demangle C++ symbols in log messages"
|
msgid "Demangle C++ symbols in log messages"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:396
|
#: options.cc:412
|
||||||
msgid "Do not demangle C++ symbols in log messages"
|
msgid "Do not demangle C++ symbols in log messages"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:399
|
#: options.cc:415
|
||||||
msgid "Try to detect violations of the One Definition Rule"
|
msgid "Try to detect violations of the One Definition Rule"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:401
|
#: options.cc:417
|
||||||
msgid "Set program start address"
|
msgid "Set program start address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:402
|
#: options.cc:418
|
||||||
msgid "-e ADDRESS, --entry ADDRESS"
|
msgid "-e ADDRESS, --entry ADDRESS"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:404
|
#: options.cc:420
|
||||||
msgid "Export all dynamic symbols"
|
msgid "Export all dynamic symbols"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:406
|
#: options.cc:422
|
||||||
msgid "Create exception frame header"
|
msgid "Create exception frame header"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:408
|
#: options.cc:424
|
||||||
msgid "Set shared library name"
|
msgid "Set shared library name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:409
|
#: options.cc:425
|
||||||
msgid "-h FILENAME, -soname FILENAME"
|
msgid "-h FILENAME, -soname FILENAME"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:411
|
#: options.cc:427
|
||||||
msgid "Set dynamic linker path"
|
msgid "Set dynamic linker path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:412
|
#: options.cc:428
|
||||||
msgid "-I PROGRAM, --dynamic-linker PROGRAM"
|
msgid "-I PROGRAM, --dynamic-linker PROGRAM"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:414
|
#: options.cc:430
|
||||||
msgid "Search for library LIBNAME"
|
msgid "Search for library LIBNAME"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:415
|
#: options.cc:431
|
||||||
msgid "-lLIBNAME, --library LIBNAME"
|
msgid "-lLIBNAME, --library LIBNAME"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:417
|
#: options.cc:433
|
||||||
msgid "Add directory to search path"
|
msgid "Add directory to search path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:418
|
#: options.cc:434
|
||||||
msgid "-L DIR, --library-path DIR"
|
msgid "-L DIR, --library-path DIR"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:420
|
#: options.cc:436
|
||||||
msgid "Ignored for compatibility"
|
msgid "Ignored for compatibility"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:422
|
#: options.cc:438
|
||||||
msgid "Set output file name"
|
msgid "Set output file name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:423
|
#: options.cc:439
|
||||||
msgid "-o FILE, --output FILE"
|
msgid "-o FILE, --output FILE"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:425
|
#: options.cc:441
|
||||||
msgid "Optimize output file size"
|
msgid "Optimize output file size"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:426
|
#: options.cc:442
|
||||||
msgid "-O level"
|
msgid "-O level"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:428
|
#: options.cc:444
|
||||||
msgid "Generate relocatable output"
|
msgid "Generate relocatable output"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:430
|
#: options.cc:446
|
||||||
msgid "Add DIR to runtime search path"
|
msgid "Add DIR to runtime search path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:431
|
#: options.cc:447
|
||||||
msgid "-R DIR, -rpath DIR"
|
msgid "-R DIR, -rpath DIR"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:434
|
#: options.cc:450
|
||||||
msgid "Add DIR to link time shared library search path"
|
msgid "Add DIR to link time shared library search path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:435
|
#: options.cc:451
|
||||||
msgid "--rpath-link DIR"
|
msgid "--rpath-link DIR"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:437
|
#: options.cc:453
|
||||||
msgid "Strip all symbols"
|
msgid "Strip all symbols"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:440
|
#: options.cc:456
|
||||||
msgid "Strip debug symbols that are unused by gdb (at least versions <= 6.7)"
|
msgid "Strip debug symbols that are unused by gdb (at least versions <= 6.7)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. This must come after -Sdebug since it's a prefix of it.
|
#. This must come after -Sdebug since it's a prefix of it.
|
||||||
#: options.cc:444
|
#: options.cc:460
|
||||||
msgid "Strip debugging information"
|
msgid "Strip debugging information"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:446
|
#: options.cc:462
|
||||||
msgid "Generate shared library"
|
msgid "Generate shared library"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:448
|
#: options.cc:464
|
||||||
msgid "Do not link against shared libraries"
|
msgid "Do not link against shared libraries"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:450
|
#: options.cc:466
|
||||||
msgid "Print resource usage statistics"
|
msgid "Print resource usage statistics"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:452
|
#: options.cc:468
|
||||||
msgid "Set target system root directory"
|
msgid "Set target system root directory"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:453
|
#: options.cc:469
|
||||||
msgid "--sysroot DIR"
|
msgid "--sysroot DIR"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:454
|
#: options.cc:470
|
||||||
msgid "Set the address of the .text section"
|
msgid "Set the address of the .text section"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:455
|
#: options.cc:471
|
||||||
msgid "-Ttext ADDRESS"
|
msgid "-Ttext ADDRESS"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. This must come after -Ttext since it's a prefix of it.
|
#. This must come after -Ttext since it's a prefix of it.
|
||||||
#: options.cc:458
|
#: options.cc:474
|
||||||
msgid "Read linker script"
|
msgid "Read linker script"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:459
|
#: options.cc:475
|
||||||
msgid "-T FILE, --script FILE"
|
msgid "-T FILE, --script FILE"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:461
|
|
||||||
msgid "Run the linker multi-threaded"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: options.cc:463
|
|
||||||
msgid "Do not run the linker multi-threaded"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: options.cc:465
|
|
||||||
msgid "Number of threads to use"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: options.cc:466
|
|
||||||
msgid "--thread-count COUNT"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: options.cc:469
|
|
||||||
msgid "Number of threads to use in initial pass"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: options.cc:470
|
|
||||||
msgid "--thread-count-initial COUNT"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: options.cc:473
|
|
||||||
msgid "Number of threads to use in middle pass"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: options.cc:474
|
|
||||||
msgid "--thread-count-middle COUNT"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: options.cc:477
|
#: options.cc:477
|
||||||
msgid "Number of threads to use in final pass"
|
msgid "Read version script"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:478
|
#: options.cc:478
|
||||||
msgid "--thread-count-final COUNT"
|
msgid "--version-script FILE"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:481
|
#: options.cc:480
|
||||||
msgid "Include all archive contents"
|
msgid "Run the linker multi-threaded"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: options.cc:482
|
||||||
|
msgid "Do not run the linker multi-threaded"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: options.cc:484
|
||||||
|
msgid "Number of threads to use"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:485
|
#: options.cc:485
|
||||||
|
msgid "--thread-count COUNT"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: options.cc:488
|
||||||
|
msgid "Number of threads to use in initial pass"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: options.cc:489
|
||||||
|
msgid "--thread-count-initial COUNT"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: options.cc:492
|
||||||
|
msgid "Number of threads to use in middle pass"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: options.cc:493
|
||||||
|
msgid "--thread-count-middle COUNT"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: options.cc:496
|
||||||
|
msgid "Number of threads to use in final pass"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: options.cc:497
|
||||||
|
msgid "--thread-count-final COUNT"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: options.cc:500
|
||||||
|
msgid "Include all archive contents"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: options.cc:504
|
||||||
msgid "Include only needed archive contents"
|
msgid "Include only needed archive contents"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:490
|
#: options.cc:509
|
||||||
msgid ""
|
msgid ""
|
||||||
"Subcommands as follows:\n"
|
"Subcommands as follows:\n"
|
||||||
" -z execstack Mark output as requiring executable stack\n"
|
" -z execstack Mark output as requiring executable stack\n"
|
||||||
" -z noexecstack Mark output as not requiring executable stack"
|
" -z noexecstack Mark output as not requiring executable stack"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:493
|
#: options.cc:512
|
||||||
msgid "-z SUBCOMMAND"
|
msgid "-z SUBCOMMAND"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:496
|
#: options.cc:515
|
||||||
msgid "Start a library search group"
|
msgid "Start a library search group"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:498
|
#: options.cc:517
|
||||||
msgid "End a library search group"
|
msgid "End a library search group"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:500
|
#: options.cc:519
|
||||||
msgid "Report usage information"
|
msgid "Report usage information"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:502
|
#: options.cc:521
|
||||||
msgid "Report version information"
|
msgid "Report version information"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:504
|
#: options.cc:523
|
||||||
msgid "Turn on debugging (all,task)"
|
msgid "Turn on debugging (all,task,script)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:505
|
#: options.cc:524
|
||||||
msgid "--debug=TYPE"
|
msgid "--debug=TYPE"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:600
|
#: options.cc:620
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: unrecognized -z subcommand: %s\n"
|
msgid "%s: unrecognized -z subcommand: %s\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:623
|
#: options.cc:643
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: unrecognized --debug subcommand: %s\n"
|
msgid "%s: unrecognized --debug subcommand: %s\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:812
|
#: options.cc:832
|
||||||
msgid "unexpected argument"
|
msgid "unexpected argument"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:819 options.cc:871 options.cc:952
|
#: options.cc:839 options.cc:891 options.cc:972
|
||||||
msgid "missing argument"
|
msgid "missing argument"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:832 options.cc:880
|
#: options.cc:852 options.cc:900
|
||||||
msgid "unknown option"
|
msgid "unknown option"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:898
|
#: options.cc:918
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: missing group end\n"
|
msgid "%s: missing group end\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:1026
|
#: options.cc:1046
|
||||||
msgid "may not nest groups"
|
msgid "may not nest groups"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:1036
|
#: options.cc:1056
|
||||||
msgid "group end without group start"
|
msgid "group end without group start"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:1046
|
#: options.cc:1066
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: use the --help option for usage information\n"
|
msgid "%s: use the --help option for usage information\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:1055
|
#: options.cc:1075
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: %s: %s\n"
|
msgid "%s: %s: %s\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:1064
|
#: options.cc:1084
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: -%c: %s\n"
|
msgid "%s: -%c: %s\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.h:358
|
#: options.h:363
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "invalid optimization level: %s"
|
msgid "invalid optimization level: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.h:404
|
#: options.h:409
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "unsupported argument to --compress-debug-sections: %s"
|
msgid "unsupported argument to --compress-debug-sections: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.h:458
|
#: options.h:463
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "invalid argument to -Ttext: %s"
|
msgid "invalid argument to -Ttext: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.h:467
|
#: options.h:472
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "invalid thread count: %s"
|
msgid "invalid thread count: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.h:475
|
#: options.h:480
|
||||||
msgid "--threads not supported"
|
msgid "--threads not supported"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -971,42 +980,42 @@ msgstr ""
|
||||||
msgid "invalid alignment %lu for section \"%s\""
|
msgid "invalid alignment %lu for section \"%s\""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: output.cc:2418
|
#: output.cc:2416
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: open: %s"
|
msgid "%s: open: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: output.cc:2438
|
#: output.cc:2436
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: mremap: %s"
|
msgid "%s: mremap: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: output.cc:2474
|
#: output.cc:2472
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: lseek: %s"
|
msgid "%s: lseek: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: output.cc:2477 output.cc:2514
|
#: output.cc:2475 output.cc:2512
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: write: %s"
|
msgid "%s: write: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: output.cc:2485
|
#: output.cc:2483
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: mmap: %s"
|
msgid "%s: mmap: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: output.cc:2495
|
#: output.cc:2493
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: munmap: %s"
|
msgid "%s: munmap: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: output.cc:2512
|
#: output.cc:2510
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: write: unexpected 0 return-value"
|
msgid "%s: write: unexpected 0 return-value"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: output.cc:2524
|
#: output.cc:2522
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: close: %s"
|
msgid "%s: close: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1016,13 +1025,8 @@ msgstr ""
|
||||||
msgid "%s: file is empty"
|
msgid "%s: file is empty"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: readsyms.cc:185
|
|
||||||
#, c-format
|
|
||||||
msgid "%s: ordinary object found in input group"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Here we have to handle any other input file types we need.
|
#. Here we have to handle any other input file types we need.
|
||||||
#: readsyms.cc:242
|
#: readsyms.cc:231
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: not an object or archive"
|
msgid "%s: not an object or archive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1075,14 +1079,14 @@ msgstr ""
|
||||||
msgid "%s: previous definition here"
|
msgid "%s: previous definition here"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: script.cc:1413
|
#: script.cc:1890
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s:%d:%d: %s"
|
msgid "%s:%d:%d: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. There are some options that we could handle here--e.g.,
|
#. There are some options that we could handle here--e.g.,
|
||||||
#. -lLIBRARY. Should we bother?
|
#. -lLIBRARY. Should we bother?
|
||||||
#: script.cc:1539
|
#: script.cc:2026
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"%s:%d:%d: ignoring command OPTION; OPTION is only valid for scripts "
|
"%s:%d:%d: ignoring command OPTION; OPTION is only valid for scripts "
|
||||||
|
@ -1104,51 +1108,51 @@ msgstr ""
|
||||||
msgid "%s: %s Stringdata structures: %zu\n"
|
msgid "%s: %s Stringdata structures: %zu\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: symtab.cc:603
|
#: symtab.cc:627
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "bad global symbol name offset %u at %zu"
|
msgid "bad global symbol name offset %u at %zu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: symtab.cc:682
|
#: symtab.cc:730
|
||||||
msgid "too few symbol versions"
|
msgid "too few symbol versions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: symtab.cc:711
|
#: symtab.cc:762
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "bad symbol name offset %u at %zu"
|
msgid "bad symbol name offset %u at %zu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: symtab.cc:765
|
#: symtab.cc:816
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "versym for symbol %zu out of range: %u"
|
msgid "versym for symbol %zu out of range: %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: symtab.cc:773
|
#: symtab.cc:824
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "versym for symbol %zu has no name: %u"
|
msgid "versym for symbol %zu has no name: %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: symtab.cc:1499 symtab.cc:1715
|
#: symtab.cc:1625 symtab.cc:1824
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: unsupported symbol section 0x%x"
|
msgid "%s: unsupported symbol section 0x%x"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: symtab.cc:1839
|
#: symtab.cc:1952
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: undefined reference to '%s'"
|
msgid "%s: undefined reference to '%s'"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: symtab.cc:1924
|
#: symtab.cc:2037
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: symbol table entries: %zu; buckets: %zu\n"
|
msgid "%s: symbol table entries: %zu; buckets: %zu\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: symtab.cc:1927
|
#: symtab.cc:2040
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: symbol table entries: %zu\n"
|
msgid "%s: symbol table entries: %zu\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: symtab.cc:1996
|
#: symtab.cc:2109
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"while linking %s: symbol '%s' defined in multiple places (possible ODR "
|
"while linking %s: symbol '%s' defined in multiple places (possible ODR "
|
||||||
|
@ -1188,12 +1192,12 @@ msgstr ""
|
||||||
msgid "%s failed: %s"
|
msgid "%s failed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: x86_64.cc:1281
|
#: x86_64.cc:1283
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: unsupported REL reloc section"
|
msgid "%s: unsupported REL reloc section"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: x86_64.cc:1748
|
#: x86_64.cc:1750
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "unsupported reloc type %u"
|
msgid "unsupported reloc type %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -37,6 +37,8 @@ struct Input_section_spec;
|
||||||
class Expression;
|
class Expression;
|
||||||
class Sections_element;
|
class Sections_element;
|
||||||
class Output_section_definition;
|
class Output_section_definition;
|
||||||
|
class Output_section;
|
||||||
|
class Output_segment;
|
||||||
|
|
||||||
class Script_sections
|
class Script_sections
|
||||||
{
|
{
|
||||||
|
@ -79,6 +81,11 @@ class Script_sections
|
||||||
void
|
void
|
||||||
add_symbol_assignment(const char* name, size_t length, Expression* value,
|
add_symbol_assignment(const char* name, size_t length, Expression* value,
|
||||||
bool provide, bool hidden);
|
bool provide, bool hidden);
|
||||||
|
|
||||||
|
// Add an assignment to the special dot symbol.
|
||||||
|
void
|
||||||
|
add_dot_assignment(Expression* value);
|
||||||
|
|
||||||
// Add an assertion.
|
// Add an assertion.
|
||||||
void
|
void
|
||||||
add_assertion(Expression* check, const char* message, size_t messagelen);
|
add_assertion(Expression* check, const char* message, size_t messagelen);
|
||||||
|
@ -91,6 +98,42 @@ class Script_sections
|
||||||
void
|
void
|
||||||
add_input_section(const Input_section_spec* spec, bool keep);
|
add_input_section(const Input_section_spec* spec, bool keep);
|
||||||
|
|
||||||
|
// Add any symbols we are defining to the symbol table.
|
||||||
|
void
|
||||||
|
add_symbols_to_table(Symbol_table*);
|
||||||
|
|
||||||
|
// Finalize symbol values and check assertions.
|
||||||
|
void
|
||||||
|
finalize_symbols(Symbol_table* symtab, const Layout* layout);
|
||||||
|
|
||||||
|
// Find the name of the output section to use for an input file name
|
||||||
|
// and section name. This returns a name, and sets
|
||||||
|
// *OUTPUT_SECTION_SLOT to point to the address where the actual
|
||||||
|
// output section may be stored.
|
||||||
|
// 1) If the input section should be discarded, this returns NULL
|
||||||
|
// and sets *OUTPUT_SECTION_SLOT to NULL.
|
||||||
|
// 2) If the input section is mapped by the SECTIONS clause, this
|
||||||
|
// returns the name to use for the output section (in permanent
|
||||||
|
// storage), and sets *OUTPUT_SECTION_SLOT to point to where the
|
||||||
|
// output section should be stored. **OUTPUT_SECTION_SLOT will be
|
||||||
|
// non-NULL if we have seen this output section already.
|
||||||
|
// 3) If the input section is not mapped by the SECTIONS clause,
|
||||||
|
// this returns SECTION_NAME, and sets *OUTPUT_SECTION_SLOT to
|
||||||
|
// NULL.
|
||||||
|
const char*
|
||||||
|
output_section_name(const char* file_name, const char* section_name,
|
||||||
|
Output_section*** output_section_slot);
|
||||||
|
|
||||||
|
// Place a marker for an orphan output section into the SECTIONS
|
||||||
|
// clause.
|
||||||
|
void
|
||||||
|
place_orphan(Output_section* os);
|
||||||
|
|
||||||
|
// Set the addresses of all the output sections. Return the segment
|
||||||
|
// which holds the file header and segment headers, if any.
|
||||||
|
Output_segment*
|
||||||
|
set_section_addresses(Symbol_table*, Layout*);
|
||||||
|
|
||||||
// Print the contents to the FILE. This is for debugging.
|
// Print the contents to the FILE. This is for debugging.
|
||||||
void
|
void
|
||||||
print(FILE*) const;
|
print(FILE*) const;
|
||||||
|
@ -98,6 +141,18 @@ class Script_sections
|
||||||
private:
|
private:
|
||||||
typedef std::vector<Sections_element*> Sections_elements;
|
typedef std::vector<Sections_element*> Sections_elements;
|
||||||
|
|
||||||
|
// Create segments.
|
||||||
|
Output_segment*
|
||||||
|
create_segments(Layout*);
|
||||||
|
|
||||||
|
// Create PT_NOTE and PT_TLS segments.
|
||||||
|
void
|
||||||
|
create_note_and_tls_segments(Layout*, const std::vector<Output_section*>*);
|
||||||
|
|
||||||
|
// Return whether the section is a BSS section.
|
||||||
|
static bool
|
||||||
|
is_bss_section(const Output_section*);
|
||||||
|
|
||||||
// True if we ever saw a SECTIONS clause.
|
// True if we ever saw a SECTIONS clause.
|
||||||
bool saw_sections_clause_;
|
bool saw_sections_clause_;
|
||||||
// True if we are currently processing a SECTIONS clause.
|
// True if we are currently processing a SECTIONS clause.
|
||||||
|
|
122
gold/script.cc
122
gold/script.cc
|
@ -912,6 +912,29 @@ Symbol_assignment::add_to_table(Symbol_table* symtab)
|
||||||
|
|
||||||
void
|
void
|
||||||
Symbol_assignment::finalize(Symbol_table* symtab, const Layout* layout)
|
Symbol_assignment::finalize(Symbol_table* symtab, const Layout* layout)
|
||||||
|
{
|
||||||
|
this->finalize_maybe_dot(symtab, layout, false, false, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finalize a symbol value which can refer to the dot symbol.
|
||||||
|
|
||||||
|
void
|
||||||
|
Symbol_assignment::finalize_with_dot(Symbol_table* symtab,
|
||||||
|
const Layout* layout,
|
||||||
|
bool dot_has_value,
|
||||||
|
uint64_t dot_value)
|
||||||
|
{
|
||||||
|
this->finalize_maybe_dot(symtab, layout, true, dot_has_value, dot_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finalize a symbol value, internal version.
|
||||||
|
|
||||||
|
void
|
||||||
|
Symbol_assignment::finalize_maybe_dot(Symbol_table* symtab,
|
||||||
|
const Layout* layout,
|
||||||
|
bool is_dot_available,
|
||||||
|
bool dot_has_value,
|
||||||
|
uint64_t dot_value)
|
||||||
{
|
{
|
||||||
// If we were only supposed to provide this symbol, the sym_ field
|
// If we were only supposed to provide this symbol, the sym_ field
|
||||||
// will be NULL if the symbol was not referenced.
|
// will be NULL if the symbol was not referenced.
|
||||||
|
@ -924,7 +947,8 @@ Symbol_assignment::finalize(Symbol_table* symtab, const Layout* layout)
|
||||||
if (parameters->get_size() == 32)
|
if (parameters->get_size() == 32)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
|
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
|
||||||
this->sized_finalize<32>(symtab, layout);
|
this->sized_finalize<32>(symtab, layout, is_dot_available, dot_has_value,
|
||||||
|
dot_value);
|
||||||
#else
|
#else
|
||||||
gold_unreachable();
|
gold_unreachable();
|
||||||
#endif
|
#endif
|
||||||
|
@ -932,7 +956,8 @@ Symbol_assignment::finalize(Symbol_table* symtab, const Layout* layout)
|
||||||
else if (parameters->get_size() == 64)
|
else if (parameters->get_size() == 64)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
|
#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
|
||||||
this->sized_finalize<64>(symtab, layout);
|
this->sized_finalize<64>(symtab, layout, is_dot_available, dot_has_value,
|
||||||
|
dot_value);
|
||||||
#else
|
#else
|
||||||
gold_unreachable();
|
gold_unreachable();
|
||||||
#endif
|
#endif
|
||||||
|
@ -943,10 +968,56 @@ Symbol_assignment::finalize(Symbol_table* symtab, const Layout* layout)
|
||||||
|
|
||||||
template<int size>
|
template<int size>
|
||||||
void
|
void
|
||||||
Symbol_assignment::sized_finalize(Symbol_table* symtab, const Layout* layout)
|
Symbol_assignment::sized_finalize(Symbol_table* symtab, const Layout* layout,
|
||||||
|
bool is_dot_available, bool dot_has_value,
|
||||||
|
uint64_t dot_value)
|
||||||
{
|
{
|
||||||
|
bool dummy;
|
||||||
|
uint64_t final_val = this->val_->eval_maybe_dot(symtab, layout,
|
||||||
|
is_dot_available,
|
||||||
|
dot_has_value, dot_value,
|
||||||
|
&dummy);
|
||||||
Sized_symbol<size>* ssym = symtab->get_sized_symbol<size>(this->sym_);
|
Sized_symbol<size>* ssym = symtab->get_sized_symbol<size>(this->sym_);
|
||||||
ssym->set_value(this->val_->eval(symtab, layout));
|
ssym->set_value(final_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the symbol value if the expression yields an absolute value.
|
||||||
|
|
||||||
|
void
|
||||||
|
Symbol_assignment::set_if_absolute(Symbol_table* symtab, const Layout* layout,
|
||||||
|
bool is_dot_available, bool dot_has_value,
|
||||||
|
uint64_t dot_value)
|
||||||
|
{
|
||||||
|
if (this->sym_ == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool is_absolute;
|
||||||
|
uint64_t val = this->val_->eval_maybe_dot(symtab, layout, is_dot_available,
|
||||||
|
dot_has_value, dot_value,
|
||||||
|
&is_absolute);
|
||||||
|
if (!is_absolute)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (parameters->get_size() == 32)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
|
||||||
|
Sized_symbol<32>* ssym = symtab->get_sized_symbol<32>(this->sym_);
|
||||||
|
ssym->set_value(val);
|
||||||
|
#else
|
||||||
|
gold_unreachable();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (parameters->get_size() == 64)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
|
||||||
|
Sized_symbol<64>* ssym = symtab->get_sized_symbol<64>(this->sym_);
|
||||||
|
ssym->set_value(val);
|
||||||
|
#else
|
||||||
|
gold_unreachable();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gold_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print for debugging.
|
// Print for debugging.
|
||||||
|
@ -1006,6 +1077,8 @@ Script_options::add_symbol_assignment(const char* name, size_t length,
|
||||||
Expression* value, bool provide,
|
Expression* value, bool provide,
|
||||||
bool hidden)
|
bool hidden)
|
||||||
{
|
{
|
||||||
|
if (length != 1 || name[0] != '.')
|
||||||
|
{
|
||||||
if (this->script_sections_.in_sections_clause())
|
if (this->script_sections_.in_sections_clause())
|
||||||
this->script_sections_.add_symbol_assignment(name, length, value,
|
this->script_sections_.add_symbol_assignment(name, length, value,
|
||||||
provide, hidden);
|
provide, hidden);
|
||||||
|
@ -1015,6 +1088,16 @@ Script_options::add_symbol_assignment(const char* name, size_t length,
|
||||||
provide, hidden);
|
provide, hidden);
|
||||||
this->symbol_assignments_.push_back(p);
|
this->symbol_assignments_.push_back(p);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (provide || hidden)
|
||||||
|
gold_error(_("invalid use of PROVIDE for dot symbol"));
|
||||||
|
if (!this->script_sections_.in_sections_clause())
|
||||||
|
gold_error(_("invalid assignment to dot outside of SECTIONS"));
|
||||||
|
else
|
||||||
|
this->script_sections_.add_dot_assignment(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add an assertion.
|
// Add an assertion.
|
||||||
|
@ -1041,9 +1124,10 @@ Script_options::add_symbols_to_table(Symbol_table* symtab)
|
||||||
p != this->symbol_assignments_.end();
|
p != this->symbol_assignments_.end();
|
||||||
++p)
|
++p)
|
||||||
(*p)->add_to_table(symtab);
|
(*p)->add_to_table(symtab);
|
||||||
|
this->script_sections_.add_symbols_to_table(symtab);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finalize symbol values.
|
// Finalize symbol values. Also check assertions.
|
||||||
|
|
||||||
void
|
void
|
||||||
Script_options::finalize_symbols(Symbol_table* symtab, const Layout* layout)
|
Script_options::finalize_symbols(Symbol_table* symtab, const Layout* layout)
|
||||||
|
@ -1052,6 +1136,29 @@ Script_options::finalize_symbols(Symbol_table* symtab, const Layout* layout)
|
||||||
p != this->symbol_assignments_.end();
|
p != this->symbol_assignments_.end();
|
||||||
++p)
|
++p)
|
||||||
(*p)->finalize(symtab, layout);
|
(*p)->finalize(symtab, layout);
|
||||||
|
|
||||||
|
for (Assertions::iterator p = this->assertions_.begin();
|
||||||
|
p != this->assertions_.end();
|
||||||
|
++p)
|
||||||
|
(*p)->check(symtab, layout);
|
||||||
|
|
||||||
|
this->script_sections_.finalize_symbols(symtab, layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set section addresses. We set all the symbols which have absolute
|
||||||
|
// values. Then we let the SECTIONS clause do its thing. This
|
||||||
|
// returns the segment which holds the file header and segment
|
||||||
|
// headers, if any.
|
||||||
|
|
||||||
|
Output_segment*
|
||||||
|
Script_options::set_section_addresses(Symbol_table* symtab, Layout* layout)
|
||||||
|
{
|
||||||
|
for (Symbol_assignments::iterator p = this->symbol_assignments_.begin();
|
||||||
|
p != this->symbol_assignments_.end();
|
||||||
|
++p)
|
||||||
|
(*p)->set_if_absolute(symtab, layout, false, false, 0);
|
||||||
|
|
||||||
|
return this->script_sections_.set_section_addresses(symtab, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This class holds data passed through the parser to the lexer and to
|
// This class holds data passed through the parser to the lexer and to
|
||||||
|
@ -2279,8 +2386,13 @@ extern "C" String_sort_list_ptr
|
||||||
script_string_sort_list_add(String_sort_list_ptr pv,
|
script_string_sort_list_add(String_sort_list_ptr pv,
|
||||||
const struct Wildcard_section* string_sort)
|
const struct Wildcard_section* string_sort)
|
||||||
{
|
{
|
||||||
|
if (pv == NULL)
|
||||||
|
return script_new_string_sort_list(string_sort);
|
||||||
|
else
|
||||||
|
{
|
||||||
pv->push_back(*string_sort);
|
pv->push_back(*string_sort);
|
||||||
return pv;
|
return pv;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new list of strings.
|
// Create a new list of strings.
|
||||||
|
|
|
@ -46,6 +46,7 @@ class Input_argument;
|
||||||
class Input_objects;
|
class Input_objects;
|
||||||
class Input_group;
|
class Input_group;
|
||||||
class Input_file;
|
class Input_file;
|
||||||
|
class Output_segment;
|
||||||
class Task_token;
|
class Task_token;
|
||||||
class Workqueue;
|
class Workqueue;
|
||||||
struct Version_dependency_list;
|
struct Version_dependency_list;
|
||||||
|
@ -65,10 +66,27 @@ class Expression
|
||||||
virtual ~Expression()
|
virtual ~Expression()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
// Return the value of the expression.
|
// Return the value of the expression which is not permitted to
|
||||||
|
// refer to the dot symbol.
|
||||||
uint64_t
|
uint64_t
|
||||||
eval(const Symbol_table*, const Layout*);
|
eval(const Symbol_table*, const Layout*);
|
||||||
|
|
||||||
|
// Return the value of an expression which is permitted to refer to
|
||||||
|
// the dot symbol. This sets *IS_ABSOLUTE to indicate whether this
|
||||||
|
// is an absolute value; it will be false if a non-absolute symbol
|
||||||
|
// was referenced in the expression; this is used to detect invalid
|
||||||
|
// uses when setting a section address.
|
||||||
|
uint64_t
|
||||||
|
eval_with_dot(const Symbol_table*, const Layout*, bool dot_has_value,
|
||||||
|
uint64_t dot_value, bool* is_absolute);
|
||||||
|
|
||||||
|
// Return the value of an expression which may or may not be
|
||||||
|
// permitted to refer to the dot symbol, depending on
|
||||||
|
// is_dot_available.
|
||||||
|
uint64_t
|
||||||
|
eval_maybe_dot(const Symbol_table*, const Layout*, bool is_dot_available,
|
||||||
|
bool dot_has_value, uint64_t dot_value, bool* is_absolute);
|
||||||
|
|
||||||
// Print the expression to the FILE. This is for debugging.
|
// Print the expression to the FILE. This is for debugging.
|
||||||
virtual void
|
virtual void
|
||||||
print(FILE*) const = 0;
|
print(FILE*) const = 0;
|
||||||
|
@ -181,17 +199,35 @@ class Symbol_assignment
|
||||||
add_to_table(Symbol_table*);
|
add_to_table(Symbol_table*);
|
||||||
|
|
||||||
// Finalize the symbol value.
|
// Finalize the symbol value.
|
||||||
void finalize(Symbol_table*, const Layout*);
|
void
|
||||||
|
finalize(Symbol_table*, const Layout*);
|
||||||
|
|
||||||
|
// Finalize the symbol value when it can refer to the dot symbol.
|
||||||
|
void
|
||||||
|
finalize_with_dot(Symbol_table*, const Layout*, bool dot_has_value,
|
||||||
|
uint64_t dot_value);
|
||||||
|
|
||||||
|
// Set the symbol value, but only if the value is absolute. This is
|
||||||
|
// used while processing a SECTIONS clause.
|
||||||
|
void
|
||||||
|
set_if_absolute(Symbol_table*, const Layout*, bool is_dot_available,
|
||||||
|
bool dot_has_value, uint64_t dot_value);
|
||||||
|
|
||||||
// Print the assignment to the FILE. This is for debugging.
|
// Print the assignment to the FILE. This is for debugging.
|
||||||
void
|
void
|
||||||
print(FILE*) const;
|
print(FILE*) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Shared by finalize and finalize_with_dot.
|
||||||
|
void
|
||||||
|
finalize_maybe_dot(Symbol_table*, const Layout*, bool is_dot_available,
|
||||||
|
bool dot_has_value, uint64_t dot_value);
|
||||||
|
|
||||||
// Sized version of finalize.
|
// Sized version of finalize.
|
||||||
template<int size>
|
template<int size>
|
||||||
void
|
void
|
||||||
sized_finalize(Symbol_table*, const Layout*);
|
sized_finalize(Symbol_table*, const Layout*, bool is_dot_available,
|
||||||
|
bool dot_has_value, uint64_t dot_value);
|
||||||
|
|
||||||
// Symbol name.
|
// Symbol name.
|
||||||
std::string name_;
|
std::string name_;
|
||||||
|
@ -274,7 +310,7 @@ class Script_options
|
||||||
void
|
void
|
||||||
add_symbols_to_table(Symbol_table*);
|
add_symbols_to_table(Symbol_table*);
|
||||||
|
|
||||||
// Finalize the symbol values.
|
// Finalize the symbol values. Also check assertions.
|
||||||
void
|
void
|
||||||
finalize_symbols(Symbol_table*, const Layout*);
|
finalize_symbols(Symbol_table*, const Layout*);
|
||||||
|
|
||||||
|
@ -290,6 +326,18 @@ class Script_options
|
||||||
script_sections()
|
script_sections()
|
||||||
{ return &this->script_sections_; }
|
{ return &this->script_sections_; }
|
||||||
|
|
||||||
|
// Whether we saw a SECTIONS clause.
|
||||||
|
bool
|
||||||
|
saw_sections_clause() const
|
||||||
|
{ return this->script_sections_.saw_sections_clause(); }
|
||||||
|
|
||||||
|
// Set section addresses using a SECTIONS clause. Return the
|
||||||
|
// segment which should hold the file header and segment headers;
|
||||||
|
// this may return NULL, in which case the headers are not in a
|
||||||
|
// loadable segment.
|
||||||
|
Output_segment*
|
||||||
|
set_section_addresses(Symbol_table*, Layout*);
|
||||||
|
|
||||||
// Print the script to the FILE. This is for debugging.
|
// Print the script to the FILE. This is for debugging.
|
||||||
void
|
void
|
||||||
print(FILE*) const;
|
print(FILE*) const;
|
||||||
|
|
|
@ -298,6 +298,25 @@ Symbol::final_value_is_known() const
|
||||||
return parameters->doing_static_link();
|
return parameters->doing_static_link();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return whether the symbol has an absolute value.
|
||||||
|
|
||||||
|
bool
|
||||||
|
Symbol::value_is_absolute() const
|
||||||
|
{
|
||||||
|
switch (this->source_)
|
||||||
|
{
|
||||||
|
case FROM_OBJECT:
|
||||||
|
return this->u_.from_object.shndx == elfcpp::SHN_ABS;
|
||||||
|
case IN_OUTPUT_DATA:
|
||||||
|
case IN_OUTPUT_SEGMENT:
|
||||||
|
return false;
|
||||||
|
case CONSTANT:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
gold_unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Class Symbol_table.
|
// Class Symbol_table.
|
||||||
|
|
||||||
Symbol_table::Symbol_table(unsigned int count,
|
Symbol_table::Symbol_table(unsigned int count,
|
||||||
|
@ -1336,7 +1355,8 @@ Symbol_table::do_define_as_constant(
|
||||||
|
|
||||||
void
|
void
|
||||||
Symbol_table::define_symbols(const Layout* layout, int count,
|
Symbol_table::define_symbols(const Layout* layout, int count,
|
||||||
const Define_symbol_in_section* p)
|
const Define_symbol_in_section* p,
|
||||||
|
bool only_if_ref)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count; ++i, ++p)
|
for (int i = 0; i < count; ++i, ++p)
|
||||||
{
|
{
|
||||||
|
@ -1345,11 +1365,12 @@ Symbol_table::define_symbols(const Layout* layout, int count,
|
||||||
this->define_in_output_data(p->name, NULL, os, p->value,
|
this->define_in_output_data(p->name, NULL, os, p->value,
|
||||||
p->size, p->type, p->binding,
|
p->size, p->type, p->binding,
|
||||||
p->visibility, p->nonvis,
|
p->visibility, p->nonvis,
|
||||||
p->offset_is_from_end, p->only_if_ref);
|
p->offset_is_from_end,
|
||||||
|
only_if_ref || p->only_if_ref);
|
||||||
else
|
else
|
||||||
this->define_as_constant(p->name, NULL, 0, p->size, p->type,
|
this->define_as_constant(p->name, NULL, 0, p->size, p->type,
|
||||||
p->binding, p->visibility, p->nonvis,
|
p->binding, p->visibility, p->nonvis,
|
||||||
p->only_if_ref);
|
only_if_ref || p->only_if_ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1357,7 +1378,8 @@ Symbol_table::define_symbols(const Layout* layout, int count,
|
||||||
|
|
||||||
void
|
void
|
||||||
Symbol_table::define_symbols(const Layout* layout, int count,
|
Symbol_table::define_symbols(const Layout* layout, int count,
|
||||||
const Define_symbol_in_segment* p)
|
const Define_symbol_in_segment* p,
|
||||||
|
bool only_if_ref)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count; ++i, ++p)
|
for (int i = 0; i < count; ++i, ++p)
|
||||||
{
|
{
|
||||||
|
@ -1368,11 +1390,12 @@ Symbol_table::define_symbols(const Layout* layout, int count,
|
||||||
this->define_in_output_segment(p->name, NULL, os, p->value,
|
this->define_in_output_segment(p->name, NULL, os, p->value,
|
||||||
p->size, p->type, p->binding,
|
p->size, p->type, p->binding,
|
||||||
p->visibility, p->nonvis,
|
p->visibility, p->nonvis,
|
||||||
p->offset_base, p->only_if_ref);
|
p->offset_base,
|
||||||
|
only_if_ref || p->only_if_ref);
|
||||||
else
|
else
|
||||||
this->define_as_constant(p->name, NULL, 0, p->size, p->type,
|
this->define_as_constant(p->name, NULL, 0, p->size, p->type,
|
||||||
p->binding, p->visibility, p->nonvis,
|
p->binding, p->visibility, p->nonvis,
|
||||||
p->only_if_ref);
|
only_if_ref || p->only_if_ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -552,6 +552,10 @@ class Symbol
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return whether this symbol currently has an absolute value.
|
||||||
|
bool
|
||||||
|
value_is_absolute() const;
|
||||||
|
|
||||||
// Return whether there should be a warning for references to this
|
// Return whether there should be a warning for references to this
|
||||||
// symbol.
|
// symbol.
|
||||||
bool
|
bool
|
||||||
|
@ -1053,13 +1057,17 @@ class Symbol_table
|
||||||
elfcpp::STB binding, elfcpp::STV visibility,
|
elfcpp::STB binding, elfcpp::STV visibility,
|
||||||
unsigned char nonvis, bool only_if_ref);
|
unsigned char nonvis, bool only_if_ref);
|
||||||
|
|
||||||
// Define a set of symbols in output sections.
|
// Define a set of symbols in output sections. If ONLY_IF_REF is
|
||||||
|
// true, only define them if they are referenced.
|
||||||
void
|
void
|
||||||
define_symbols(const Layout*, int count, const Define_symbol_in_section*);
|
define_symbols(const Layout*, int count, const Define_symbol_in_section*,
|
||||||
|
bool only_if_ref);
|
||||||
|
|
||||||
// Define a set of symbols in output segments.
|
// Define a set of symbols in output segments. If ONLY_IF_REF is
|
||||||
|
// true, only defined them if they are referenced.
|
||||||
void
|
void
|
||||||
define_symbols(const Layout*, int count, const Define_symbol_in_segment*);
|
define_symbols(const Layout*, int count, const Define_symbol_in_segment*,
|
||||||
|
bool only_if_ref);
|
||||||
|
|
||||||
// Define SYM using a COPY reloc. POSD is the Output_data where the
|
// Define SYM using a COPY reloc. POSD is the Output_data where the
|
||||||
// symbol should be defined--typically a .dyn.bss section. VALUE is
|
// symbol should be defined--typically a .dyn.bss section. VALUE is
|
||||||
|
|
|
@ -527,6 +527,11 @@ script_test_1_SOURCES = script_test_1.cc
|
||||||
script_test_1_DEPENDENCIES = gcctestdir/ld script_test_1.t
|
script_test_1_DEPENDENCIES = gcctestdir/ld script_test_1.t
|
||||||
script_test_1_LDFLAGS = -Bgcctestdir/ -Wl,-R,. -T $(srcdir)/script_test_1.t
|
script_test_1_LDFLAGS = -Bgcctestdir/ -Wl,-R,. -T $(srcdir)/script_test_1.t
|
||||||
|
|
||||||
|
check_PROGRAMS += script_test_2
|
||||||
|
script_test_2_SOURCES = script_test_2.cc script_test_2a.cc script_test_2b.cc
|
||||||
|
script_test_2_DEPENDENCIES = gcctestdir/ld script_test_2.t
|
||||||
|
script_test_2_LDFLAGS = -Bgcctestdir/ -Wl,-R,. -T $(srcdir)/script_test_2.t
|
||||||
|
|
||||||
if OBJDUMP_AND_CPPFILT
|
if OBJDUMP_AND_CPPFILT
|
||||||
check_SCRIPTS += ver_matching_test.sh
|
check_SCRIPTS += ver_matching_test.sh
|
||||||
check_DATA += ver_matching_test.stdout
|
check_DATA += ver_matching_test.stdout
|
||||||
|
|
69
gold/testsuite/script_test_2.cc
Normal file
69
gold/testsuite/script_test_2.cc
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
// script_test_2.cc -- linker script test 2 for gold -*- C++ -*-
|
||||||
|
|
||||||
|
// Copyright 2008 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.
|
||||||
|
|
||||||
|
// A test of some uses of the SECTIONS clause. Look at
|
||||||
|
// script_test_2.t to make sense of this test.
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstring>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
extern char start_test_area[];
|
||||||
|
extern char start_test_area_1[];
|
||||||
|
extern char start_data[];
|
||||||
|
extern char end_data[];
|
||||||
|
extern char start_fill[];
|
||||||
|
extern char end_fill[];
|
||||||
|
extern char end_test_area[];
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int, char**)
|
||||||
|
{
|
||||||
|
assert(reinterpret_cast<uintptr_t>(start_test_area) == 0x20000001);
|
||||||
|
assert(reinterpret_cast<uintptr_t>(start_test_area_1) == 0x20000010);
|
||||||
|
|
||||||
|
// We should see the string from script_test_2b.o next. The
|
||||||
|
// subalign should move it up to 0x20000020.
|
||||||
|
for (int i = 0; i < 16; ++i)
|
||||||
|
assert(start_test_area_1[i] == 0);
|
||||||
|
assert(strcmp(start_test_area_1 + 16, "test b") == 0);
|
||||||
|
|
||||||
|
// Next the string from script_test_2a.o, after the subalign.
|
||||||
|
for (int i = 16 + 7; i < 48; ++i)
|
||||||
|
assert(start_test_area_1[i] == 0);
|
||||||
|
assert(strcmp(start_test_area_1 + 48, "test a") == 0);
|
||||||
|
|
||||||
|
// Move four bytes forward to start_data.
|
||||||
|
assert(reinterpret_cast<uintptr_t>(start_test_area_1 + 48 + 7 + 4)
|
||||||
|
== reinterpret_cast<uintptr_t>(start_data));
|
||||||
|
assert(memcmp(start_data, "\1\2\0\4\0\0\0\010\0\0\0\0\0\0\0", 15) == 0
|
||||||
|
|| memcmp(start_data, "\1\0\2\0\0\0\4\0\0\0\0\0\0\0\010", 15) == 0);
|
||||||
|
assert(end_data == start_data + 15);
|
||||||
|
|
||||||
|
// Check that FILL works as expected.
|
||||||
|
assert(start_fill == end_data);
|
||||||
|
assert(memcmp(start_fill, "\x12\x34\x56\x78\x12\x34\x56\0", 8) == 0);
|
||||||
|
assert(end_fill == start_fill + 8);
|
||||||
|
|
||||||
|
assert(end_test_area == end_fill);
|
||||||
|
}
|
63
gold/testsuite/script_test_2.t
Normal file
63
gold/testsuite/script_test_2.t
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/* script_test_2.t -- linker script test 2 for gold
|
||||||
|
|
||||||
|
Copyright 2008 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. */
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* With luck this will work everywhere. */
|
||||||
|
. = 0x10000000;
|
||||||
|
|
||||||
|
/* With luck this will be enough to get the program working. */
|
||||||
|
.text : { *(.text) }
|
||||||
|
.data : { *(.data) }
|
||||||
|
.bss : { *(.bss) }
|
||||||
|
|
||||||
|
/* Now the real test. */
|
||||||
|
. = 0x20000001;
|
||||||
|
start_test_area = .;
|
||||||
|
.gold_test ALIGN(16) : SUBALIGN(32) {
|
||||||
|
start_test_area_1 = .;
|
||||||
|
|
||||||
|
/* No sections should wind up here, because of the EXCLUDE_FILE. */
|
||||||
|
*( EXCLUDE_FILE(script_test*) .gold_test)
|
||||||
|
|
||||||
|
/* This should match only script_test_2b.o. */
|
||||||
|
script_test_2b.o(.gold_test)
|
||||||
|
|
||||||
|
/* This should match the remaining sections. */
|
||||||
|
*(.gold_test)
|
||||||
|
|
||||||
|
. = . + 4;
|
||||||
|
start_data = .;
|
||||||
|
BYTE(1)
|
||||||
|
SHORT(2)
|
||||||
|
LONG(4)
|
||||||
|
QUAD(8)
|
||||||
|
end_data = .;
|
||||||
|
|
||||||
|
start_fill = .;
|
||||||
|
FILL(0x12345678);
|
||||||
|
. = . + 7;
|
||||||
|
BYTE(0)
|
||||||
|
end_fill = .;
|
||||||
|
}
|
||||||
|
end_test_area = .;
|
||||||
|
}
|
24
gold/testsuite/script_test_2a.cc
Normal file
24
gold/testsuite/script_test_2a.cc
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
// script_test_2a.cc -- linker script test 2, file 1 -*- C++ -*-
|
||||||
|
|
||||||
|
// Copyright 2008 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.
|
||||||
|
|
||||||
|
char script_test_string_a[] __attribute__ ((section(".gold_test"))) =
|
||||||
|
"test a";
|
24
gold/testsuite/script_test_2b.cc
Normal file
24
gold/testsuite/script_test_2b.cc
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
// script_test_2a.cc -- linker script test 2, file 2 -*- C++ -*-
|
||||||
|
|
||||||
|
// Copyright 2008 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.
|
||||||
|
|
||||||
|
char script_test_string_b[] __attribute__ ((section(".gold_test"))) =
|
||||||
|
"test b";
|
|
@ -371,7 +371,8 @@ opt_phdr:
|
||||||
| /* empty */
|
| /* empty */
|
||||||
;
|
;
|
||||||
|
|
||||||
/* The value to use to fill an output section. */
|
/* The value to use to fill an output section. FIXME: This does not
|
||||||
|
handle a string of arbitrary length. */
|
||||||
opt_fill:
|
opt_fill:
|
||||||
'=' exp
|
'=' exp
|
||||||
{ $$ = $2; }
|
{ $$ = $2; }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue