+2008-07-10 Ian Lance Taylor <iant@google.com>
+
+ Handle output sections with more than 0x7fffffff bytes.
+ * object.h (class Relobj): Change map_to_output_ to
+ output_sections_, and just keep a section pointer. Change all
+ uses. Move comdat group support to Sized_relobj.
+ (Relobj::is_section_specially_mapped): Remove.
+ (Relobj::output_section): Remove poff parameter. Change all
+ callers.
+ (Relobj::output_section_offset): New function.
+ (Relobj::set_section_offset): Rewrite.
+ (Relobj::map_to_output): Remove.
+ (Relobj::output_sections): New function.
+ (Relobj::do_output_section_offset): New pure virtual function.
+ (Relobj::do_set_section_offset): Likewise.
+ (class Sized_relobj): Add section_offsets_ field. Add comdat
+ group support from Relobj. Update declarations.
+ (Sized_relobj::get_output_section_offset): New function.
+ (Sized_relobj::do_output_section_offset): New function.
+ (Sized_relobj::do_set_section_offset): New function.
+ * object.cc (Relobj::output_section_address): Remove.
+ (Sized_relobj::Sized_relobj): Initialize new fields.
+ (Sized_relobj::include_section_group): Cast find_kept_object to
+ Sized_relobj.
+ (Sized_relobj::include_linkonce_section): Likewise.
+ (Sized_relobj::do_layout): Use separate arrays for output section
+ and output offset.
+ (Sized_relobj::do_count_local_symbols): Change map_to_output to
+ output_sections.
+ (Sized_relobj::do_finalize_local_symbols): Change map_to_output to
+ output_sections and section_offsets.
+ (Sized_relobj::write_local_symbols): Likewise.
+ (map_to_kept_section): Compute output address directly.
+ * reloc.cc (Sized_relobj::do_read_relocs): Change map_to_output to
+ output_sections and section_offsets.
+ (Sized_relobj::write_sections): Likewise.
+ (Sized_relobj::relocate_sections): Likewise.
+ * symtab.cc (sized_finalize_symbol): Use output_section_offset.
+ * output.h (class Output_reloc): Update declarations. Change
+ u2_.relobj to Sized_relobj*.
+ (class Output_data_reloc): Change add functions to use
+ Sized_relobj*.
+ * output.cc (Output_reloc::Output_reloc): Change relobj to
+ Sized_relobj*.
+ (Output_reloc::local_section_offset): Change return type to
+ Elf_Addr. Use get_output_section_offset.
+ (Output_reloc::get_address): Likewise.
+ (Output_section::is_input_address_mapped): Don't call
+ is_section_specially_mapped.
+ (Output_section::output_offset): Likewise.
+ (Output_section::output_address): Likewise.
+ (Output_section::starting_output_address): Likewise.
+ * copy-relocs.cc (Copy_relocs::copy_reloc): Change object
+ parameter to Sized_relobj*.
+ (Copy_relocs::need_copy_reloc): Likewise.
+ (Copy_relocs::save): Likewise.
+ * copy-relocs.h (class Copy_relocs): Update declarations.
+ (class Copy_relocs::Copy_reloc_entry): Change constructor to use
+ Sized_relobj*. Change relobj_ field to Sized_relobj*.
+ * target-reloc.h (relocate_for_relocatable): Change
+ offset_in_output_section type to Elf_Addr. Change code that uses
+ it as well.
+ * layout.cc (Layout::layout): Always set *off.
+ * mapfile.cc (Mapfile::print_input_section): Use
+ output_section_offset.
+ * i386.cc (Target_i386::copy_reloc): Change object parameter to
+ Sized_relobj*.
+ * powerpc.cc (Target_powerpc::copy_reloc): Likewise.
+ * sparc.cc (Target_sparc::copy_reloc): Likewise.
+ * x86_64.cc (Target_x86_64::copy_reloc): Likewise.
+
2008-07-03 Ian Lance Taylor <iant@google.com>
* layout.cc (Layout::include_section): Do not discard unrecognized
Symbol_table* symtab,
Layout* layout,
Sized_symbol<size>* sym,
- Relobj* object,
+ Sized_relobj<size, big_endian>* object,
unsigned int shndx,
Output_section *output_section,
const Reloc& rel,
bool
Copy_relocs<sh_type, size, big_endian>::need_copy_reloc(
Sized_symbol<size>* sym,
- Relobj* object,
+ Sized_relobj<size, big_endian>* object,
unsigned int shndx) const
{
// FIXME: Handle -z nocopyrelocs.
template<int sh_type, int size, bool big_endian>
void
-Copy_relocs<sh_type, size, big_endian>::save(Symbol* sym, Relobj* object,
- unsigned int shndx,
- Output_section* output_section,
- const Reloc& rel)
+Copy_relocs<sh_type, size, big_endian>::save(
+ Symbol* sym,
+ Sized_relobj<size, big_endian>* object,
+ unsigned int shndx,
+ Output_section* output_section,
+ const Reloc& rel)
{
unsigned int reloc_type = elfcpp::elf_r_type<size>(rel.get_r_info());
typename elfcpp::Elf_types<size>::Elf_Addr addend =
// will wind up. REL is the reloc itself. The Output_data_reloc
// section is where the dynamic relocs are put.
void
- copy_reloc(Symbol_table*, Layout*, Sized_symbol<size>* sym, Relobj* object,
+ copy_reloc(Symbol_table*, Layout*, Sized_symbol<size>* sym,
+ Sized_relobj<size, big_endian>* object,
unsigned int shndx, Output_section* output_section,
const Reloc& rel,
Output_data_reloc<sh_type, true, size, big_endian>*);
{
public:
Copy_reloc_entry(Symbol* sym, unsigned int reloc_type,
- Relobj* relobj, unsigned int shndx,
+ Sized_relobj<size, big_endian>* relobj,
+ unsigned int shndx,
Output_section* output_section,
Address address, Addend addend)
: sym_(sym), reloc_type_(reloc_type), relobj_(relobj),
private:
Symbol* sym_;
unsigned int reloc_type_;
- Relobj* relobj_;
+ Sized_relobj<size, big_endian>* relobj_;
unsigned int shndx_;
Output_section* output_section_;
Address address_;
// Return whether we need a COPY reloc.
bool
- need_copy_reloc(Sized_symbol<size>* gsym, Relobj* object,
+ need_copy_reloc(Sized_symbol<size>* gsym,
+ Sized_relobj<size, big_endian>* object,
unsigned int shndx) const;
// Emit a COPY reloc.
// Save a reloc against SYM for possible emission later.
void
- save(Symbol*, Relobj*, unsigned int shndx, Output_section*,
- const Reloc& rel);
+ save(Symbol*, Sized_relobj<size, big_endian>*, unsigned int shndx,
+ Output_section*, const Reloc& rel);
// The target specific relocation type of the COPY relocation.
const unsigned int copy_reloc_type_;
// Add a potential copy relocation.
void
- copy_reloc(Symbol_table* symtab, Layout* layout, Relobj* object,
+ copy_reloc(Symbol_table* symtab, Layout* layout,
+ Sized_relobj<32, false>* object,
unsigned int shndx, Output_section* output_section,
Symbol* sym, const elfcpp::Rel<32, false>& reloc)
{
const char* name, const elfcpp::Shdr<size, big_endian>& shdr,
unsigned int reloc_shndx, unsigned int, off_t* off)
{
+ *off = 0;
+
if (!this->include_section(object, name, shdr))
return NULL;
}
else
{
- section_offset_type offset;
- os = relobj->output_section(shndx, &offset);
- if (offset == -1)
- addr = ~0ULL;
- else
- addr = os->address() + offset;
+ os = relobj->output_section(shndx);
+ addr = relobj->output_section_offset(shndx);
+ if (addr != -1U)
+ addr += os->address();
}
char sizebuf[50];
// For each object with merge sections, we store an Object_merge_map.
// This is used to map locations in input sections to a merged output
// section. The output section itself is not recorded here--it can be
-// found in the map_to_output_ field of the Object.
+// found in the output_sections_ field of the Object.
class Object_merge_map
{
return false;
}
-// Class Relobj.
-
-// Return the output address of the input section SHNDX.
-uint64_t
-Relobj::output_section_address(unsigned int shndx) const
-{
- section_offset_type offset;
- Output_section* os = this->output_section(shndx, &offset);
- gold_assert(os != NULL && offset != -1);
- return os->address() + offset;
-}
-
// Class Sized_relobj.
template<int size, bool big_endian>
local_dynsym_offset_(0),
local_values_(),
local_got_offsets_(),
+ kept_comdat_sections_(),
+ comdat_groups_(),
has_eh_frame_(false)
{
}
bool include_group = ((flags & elfcpp::GRP_COMDAT) == 0
|| layout->add_comdat(this, index, signature, true));
- Relobj* kept_object = NULL;
+ Sized_relobj<size, big_endian>* kept_object = NULL;
Comdat_group* kept_group = NULL;
if (!include_group)
// This group is being discarded. Find the object and group
// that was kept in its place.
unsigned int kept_group_index = 0;
- kept_object = layout->find_kept_object(signature, &kept_group_index);
+ Relobj* kept_relobj = layout->find_kept_object(signature,
+ &kept_group_index);
+ kept_object = static_cast<Sized_relobj<size, big_endian>*>(kept_relobj);
if (kept_object != NULL)
kept_group = kept_object->find_comdat_group(kept_group_index);
}
// In this case, the section index stored with the layout object
// is the linkonce section that was kept.
unsigned int kept_group_index = 0;
- Relobj* kept_object = layout->find_kept_object(sig2, &kept_group_index);
- if (kept_object != NULL)
+ Relobj* kept_relobj = layout->find_kept_object(sig2, &kept_group_index);
+ if (kept_relobj != NULL)
{
+ Sized_relobj<size, big_endian>* kept_object
+ = static_cast<Sized_relobj<size, big_endian>*>(kept_relobj);
Kept_comdat_section* kept =
new Kept_comdat_section(kept_object, kept_group_index);
this->set_kept_comdat_section(index, kept);
// the group has only one member section. Otherwise, it's not
// worth the effort.
unsigned int kept_group_index = 0;
- Relobj* kept_object = layout->find_kept_object(sig1, &kept_group_index);
- if (kept_object != NULL)
+ Relobj* kept_relobj = layout->find_kept_object(sig1, &kept_group_index);
+ if (kept_relobj != NULL)
{
+ Sized_relobj<size, big_endian>* kept_object =
+ static_cast<Sized_relobj<size, big_endian>*>(kept_relobj);
Comdat_group* kept_group =
kept_object->find_comdat_group(kept_group_index);
if (kept_group != NULL && kept_group->size() == 1)
}
}
- std::vector<Map_to_output>& map_sections(this->map_to_output());
- map_sections.resize(shnum);
+ Output_sections& out_sections(this->output_sections());
+ std::vector<Address>& out_section_offsets(this->section_offsets_);
+
+ out_sections.resize(shnum);
+ out_section_offsets.resize(shnum);
// If we are only linking for symbols, then there is nothing else to
// do here.
if (discard)
{
// Do not include this section in the link.
- map_sections[i].output_section = NULL;
+ out_sections[i] = NULL;
+ out_section_offsets[i] = -1U;
continue;
}
reloc_shndx[i], reloc_type[i],
&offset);
- map_sections[i].output_section = os;
- map_sections[i].offset = offset;
+ out_sections[i] = os;
+ if (offset == -1)
+ out_section_offsets[i] = -1U;
+ else
+ out_section_offsets[i] = convert_types<Address, off_t>(offset);
// If this section requires special handling, and if there are
// relocs that apply to it, then we must do the special handling
continue;
}
- Output_section* data_section = map_sections[data_shndx].output_section;
+ Output_section* data_section = out_sections[data_shndx];
if (data_section == NULL)
{
- map_sections[i].output_section = NULL;
+ out_sections[i] = NULL;
+ out_section_offsets[i] = -1U;
continue;
}
Output_section* os = layout->layout_reloc(this, i, shdr, data_section,
rr);
- map_sections[i].output_section = os;
- map_sections[i].offset = -1;
+ out_sections[i] = os;
+ out_section_offsets[i] = -1U;
}
// Handle the .eh_frame sections at the end.
reloc_shndx[i],
reloc_type[i],
&offset);
- map_sections[i].output_section = os;
- map_sections[i].offset = offset;
+ out_sections[i] = os;
+ if (offset == -1)
+ out_section_offsets[i] = -1U;
+ else
+ out_section_offsets[i] = convert_types<Address, off_t>(offset);
// If this section requires special handling, and if there are
// relocs that apply to it, then we must do the special handling
// Loop over the local symbols.
- const std::vector<Map_to_output>& mo(this->map_to_output());
+ const Output_sections& out_sections(this->output_sections());
unsigned int shnum = this->shnum();
unsigned int count = 0;
unsigned int dyncount = 0;
// Decide whether this symbol should go into the output file.
- if (shndx < shnum && mo[shndx].output_section == NULL)
+ if (shndx < shnum && out_sections[shndx] == NULL)
{
lv.set_no_output_symtab_entry();
gold_assert(!lv.needs_output_dynsym_entry());
const unsigned int loccount = this->local_symbol_count_;
this->local_symbol_offset_ = off;
- const std::vector<Map_to_output>& mo(this->map_to_output());
+ const Output_sections& out_sections(this->output_sections());
+ const std::vector<Address>& out_offsets(this->section_offsets_);
unsigned int shnum = this->shnum();
for (unsigned int i = 1; i < loccount; ++i)
unsigned int shndx = lv.input_shndx(&is_ordinary);
// Set the output symbol value.
-
+
if (!is_ordinary)
{
if (shndx == elfcpp::SHN_ABS || shndx == elfcpp::SHN_COMMON)
shndx = 0;
}
- Output_section* os = mo[shndx].output_section;
+ Output_section* os = out_sections[shndx];
if (os == NULL)
{
// so we leave the input value unchanged here.
continue;
}
- else if (mo[shndx].offset == -1)
+ else if (out_offsets[shndx] == -1U)
{
// This is a SHF_MERGE section or one which otherwise
// requires special handling. We get the output address
}
else if (lv.is_tls_symbol())
lv.set_output_value(os->tls_offset()
- + mo[shndx].offset
+ + out_offsets[shndx]
+ lv.input_value());
else
lv.set_output_value(os->address()
- + mo[shndx].offset
+ + out_offsets[shndx]
+ lv.input_value());
}
dyn_oview = of->get_output_view(this->local_dynsym_offset_,
dyn_output_size);
- const std::vector<Map_to_output>& mo(this->map_to_output());
+ const Output_sections out_sections(this->output_sections());
gold_assert(this->local_values_.size() == loccount);
&is_ordinary);
if (is_ordinary)
{
- gold_assert(st_shndx < mo.size());
- if (mo[st_shndx].output_section == NULL)
+ gold_assert(st_shndx < out_sections.size());
+ if (out_sections[st_shndx] == NULL)
continue;
- st_shndx = mo[st_shndx].output_section->out_shndx();
+ st_shndx = out_sections[st_shndx]->out_shndx();
if (st_shndx >= elfcpp::SHN_LORESERVE)
{
if (lv.needs_output_symtab_entry())
{
gold_assert(kept->object_ != NULL);
*found = true;
- return (static_cast<Address>
- (kept->object_->output_section_address(kept->shndx_)));
+ Output_section* os = kept->object_->output_section(kept->shndx_);
+ Address offset = kept->object_->get_output_section_offset(kept->shndx_);
+ gold_assert(os != NULL && offset != -1U);
+ return os->address() + offset;
}
*found = false;
return 0;
public:
Relobj(const std::string& name, Input_file* input_file, off_t offset = 0)
: Object(name, input_file, false, offset),
- map_to_output_(),
- comdat_groups_(),
- kept_comdat_sections_(),
+ output_sections_(),
map_to_relocatable_relocs_(NULL),
object_merge_map_(NULL),
relocs_must_follow_section_writes_(false)
bool
is_section_included(unsigned int shndx) const
{
- gold_assert(shndx < this->map_to_output_.size());
- return this->map_to_output_[shndx].output_section != NULL;
+ gold_assert(shndx < this->output_sections_.size());
+ return this->output_sections_[shndx] != NULL;
}
- // Return whether an input section requires special
- // handling--whether it is not simply mapped from the input file to
- // the output file.
- bool
- is_section_specially_mapped(unsigned int shndx) const
+ // Given a section index, return the corresponding Output_section.
+ // The return value will be NULL if the section is not included in
+ // the link.
+ Output_section*
+ output_section(unsigned int shndx) const
{
- gold_assert(shndx < this->map_to_output_.size());
- return (this->map_to_output_[shndx].output_section != NULL
- && this->map_to_output_[shndx].offset == -1);
+ gold_assert(shndx < this->output_sections_.size());
+ return this->output_sections_[shndx];
}
- // Given a section index, return the corresponding Output_section
- // (which will be NULL if the section is not included in the link)
- // and set *POFF to the offset within that section. *POFF will be
- // set to -1 if the section requires special handling.
- inline Output_section*
- output_section(unsigned int shndx, section_offset_type* poff) const;
+ // Given a section index, return the offset in the Output_section.
+ // The return value will be -1U if the section is specially mapped,
+ // such as a merge section.
+ uint64_t
+ output_section_offset(unsigned int shndx) const
+ { return this->do_output_section_offset(shndx); }
// Set the offset of an input section within its output section.
- void
- set_section_offset(unsigned int shndx, section_offset_type off)
- {
- gold_assert(shndx < this->map_to_output_.size());
- this->map_to_output_[shndx].offset = off;
- }
-
- // Return the output address of the input section SHNDX.
- uint64_t
- output_section_address(unsigned int shndx) const;
+ virtual void
+ set_section_offset(unsigned int shndx, uint64_t off)
+ { this->do_set_section_offset(shndx, off); }
// Return true if we need to wait for output sections to be written
// before we can apply relocations. This is true if the object has
return (*this->map_to_relocatable_relocs_)[reloc_shndx];
}
- // Information needed to keep track of kept comdat groups. This is
- // simply a map from the section name to its section index. This may
- // not be a one-to-one mapping, but we ignore that possibility since
- // this is used only to attempt to handle stray relocations from
- // non-comdat debug sections that refer to comdat loadable sections.
- typedef Unordered_map<std::string, unsigned int> Comdat_group;
-
- // Find a comdat group table given its group section SHNDX.
- Comdat_group*
- find_comdat_group(unsigned int shndx) const
- {
- Comdat_group_table::const_iterator p =
- this->comdat_groups_.find(shndx);
- if (p != this->comdat_groups_.end())
- return p->second;
- return NULL;
- }
-
protected:
- // What we need to know to map an input section to an output
- // section. We keep an array of these, one for each input section,
- // indexed by the input section number.
- struct Map_to_output
- {
- // The output section. This is NULL if the input section is to be
- // discarded.
- Output_section* output_section;
- // The offset within the output section. This is -1 if the
- // section requires special handling.
- section_offset_type offset;
- };
-
- // A map from group section index to the table of group members.
- typedef std::map<unsigned int, Comdat_group*> Comdat_group_table;
-
- // To keep track of discarded comdat sections, we need to map a member
- // section index to the object and section index of the corresponding
- // kept section.
- struct Kept_comdat_section
- {
- Kept_comdat_section(Relobj* object, unsigned int shndx)
- : object_(object), shndx_(shndx)
- { }
- Relobj* object_;
- unsigned int shndx_;
- };
- typedef std::map<unsigned int, Kept_comdat_section*>
- Kept_comdat_section_table;
+ // The output section to be used for each input section, indexed by
+ // the input section number. The output section is NULL if the
+ // input section is to be discarded.
+ typedef std::vector<Output_section*> Output_sections;
// Read the relocs--implemented by child class.
virtual void
do_relocate(const General_options& options, const Symbol_table* symtab,
const Layout*, Output_file* of) = 0;
- // Return the vector mapping input sections to output sections.
- std::vector<Map_to_output>&
- map_to_output()
- { return this->map_to_output_; }
-
- const std::vector<Map_to_output>&
- map_to_output() const
- { return this->map_to_output_; }
+ // Get the offset of a section--implemented by child class.
+ virtual uint64_t
+ do_output_section_offset(unsigned int shndx) const = 0;
- // Record a new comdat group whose group section index is SHNDX.
- void
- add_comdat_group(unsigned int shndx, Comdat_group* group)
- { this->comdat_groups_[shndx] = group; }
+ // Set the offset of a section--implemented by child class.
+ virtual void
+ do_set_section_offset(unsigned int shndx, uint64_t off) = 0;
- // Record a mapping from discarded section SHNDX to the corresponding
- // kept section.
- void
- set_kept_comdat_section(unsigned int shndx, Kept_comdat_section* kept)
- {
- this->kept_comdat_sections_[shndx] = kept;
- }
+ // Return the vector mapping input sections to output sections.
+ Output_sections&
+ output_sections()
+ { return this->output_sections_; }
- // Find the kept section corresponding to the discarded section SHNDX.
- Kept_comdat_section*
- get_kept_comdat_section(unsigned int shndx) const
- {
- Kept_comdat_section_table::const_iterator p =
- this->kept_comdat_sections_.find(shndx);
- if (p == this->kept_comdat_sections_.end())
- return NULL;
- return p->second;
- }
+ const Output_sections&
+ output_sections() const
+ { return this->output_sections_; }
// Set the size of the relocatable relocs array.
void
private:
// Mapping from input sections to output section.
- std::vector<Map_to_output> map_to_output_;
- // Table of kept comdat groups.
- Comdat_group_table comdat_groups_;
- // Table mapping discarded comdat sections to corresponding kept sections.
- Kept_comdat_section_table kept_comdat_sections_;
+ Output_sections output_sections_;
// Mapping from input section index to the information recorded for
// the relocations. This is only used for a relocatable link.
std::vector<Relocatable_relocs*>* map_to_relocatable_relocs_;
bool relocs_must_follow_section_writes_;
};
-// Implement Object::output_section inline for efficiency.
-inline Output_section*
-Relobj::output_section(unsigned int shndx, section_offset_type* poff) const
-{
- gold_assert(shndx < this->map_to_output_.size());
- const Map_to_output& mo(this->map_to_output_[shndx]);
- *poff = mo.offset;
- return mo.output_section;
-}
-
// This class is used to handle relocations against a section symbol
// in an SHF_MERGE section. For such a symbol, we need to know the
// addend of the relocation before we can determine the final value.
}
}
+ // Get the offset of input section SHNDX within its output section.
+ // This is -1 if the input section requires a special mapping, such
+ // as a merge section. The output section can be found in the
+ // output_sections_ field of the parent class Relobj.
+ Address
+ get_output_section_offset(unsigned int shndx) const
+ {
+ gold_assert(shndx < this->section_offsets_.size());
+ return this->section_offsets_[shndx];
+ }
+
// Return the name of the symbol that spans the given offset in the
// specified section in this object. This is used only for error
// messages and is not particularly efficient.
Xindex*
do_initialize_xindex();
+ // Get the offset of a section.
+ uint64_t
+ do_output_section_offset(unsigned int shndx) const
+ { return this->get_output_section_offset(shndx); }
+
+ // Set the offset of a section.
+ void
+ do_set_section_offset(unsigned int shndx, uint64_t off)
+ {
+ gold_assert(shndx < this->section_offsets_.size());
+ this->section_offsets_[shndx] = convert_types<Address, uint64_t>(off);
+ }
+
private:
// For convenience.
typedef Sized_relobj<size, big_endian> This;
static const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
typedef elfcpp::Shdr<size, big_endian> Shdr;
+ // To keep track of discarded comdat sections, we need to map a member
+ // section index to the object and section index of the corresponding
+ // kept section.
+ struct Kept_comdat_section
+ {
+ Kept_comdat_section(Sized_relobj<size, big_endian>* object,
+ unsigned int shndx)
+ : object_(object), shndx_(shndx)
+ { }
+ Sized_relobj<size, big_endian>* object_;
+ unsigned int shndx_;
+ };
+ typedef std::map<unsigned int, Kept_comdat_section*>
+ Kept_comdat_section_table;
+
+ // Information needed to keep track of kept comdat groups. This is
+ // simply a map from the section name to its section index. This may
+ // not be a one-to-one mapping, but we ignore that possibility since
+ // this is used only to attempt to handle stray relocations from
+ // non-comdat debug sections that refer to comdat loadable sections.
+ typedef Unordered_map<std::string, unsigned int> Comdat_group;
+
+ // A map from group section index to the table of group members.
+ typedef std::map<unsigned int, Comdat_group*> Comdat_group_table;
+
+ // Find a comdat group table given its group section SHNDX.
+ Comdat_group*
+ find_comdat_group(unsigned int shndx) const
+ {
+ Comdat_group_table::const_iterator p =
+ this->comdat_groups_.find(shndx);
+ if (p != this->comdat_groups_.end())
+ return p->second;
+ return NULL;
+ }
+
+ // Record a new comdat group whose group section index is SHNDX.
+ void
+ add_comdat_group(unsigned int shndx, Comdat_group* group)
+ { this->comdat_groups_[shndx] = group; }
+
// Adjust a section index if necessary.
unsigned int
adjust_shndx(unsigned int shndx)
void
emit_relocs(const Relocate_info<size, big_endian>*, unsigned int,
unsigned int sh_type, const unsigned char* prelocs,
- size_t reloc_count, Output_section*, off_t output_offset,
+ size_t reloc_count, Output_section*, Address output_offset,
unsigned char* view, Address address,
section_size_type view_size,
unsigned char* reloc_view, section_size_type reloc_view_size);
void
emit_relocs_reltype(const Relocate_info<size, big_endian>*, unsigned int,
const unsigned char* prelocs, size_t reloc_count,
- Output_section*, off_t output_offset,
+ Output_section*, Address output_offset,
unsigned char* view, Address address,
section_size_type view_size,
unsigned char* reloc_view,
this->local_got_offsets_.clear();
}
+ // Record a mapping from discarded section SHNDX to the corresponding
+ // kept section.
+ void
+ set_kept_comdat_section(unsigned int shndx, Kept_comdat_section* kept)
+ {
+ this->kept_comdat_sections_[shndx] = kept;
+ }
+
+ // Find the kept section corresponding to the discarded section SHNDX.
+ Kept_comdat_section*
+ get_kept_comdat_section(unsigned int shndx) const
+ {
+ typename Kept_comdat_section_table::const_iterator p =
+ this->kept_comdat_sections_.find(shndx);
+ if (p == this->kept_comdat_sections_.end())
+ return NULL;
+ return p->second;
+ }
+
// The GOT offsets of local symbols. This map also stores GOT offsets
// for tp-relative offsets for TLS symbols.
typedef Unordered_map<unsigned int, Got_offset_list*> Local_got_offsets;
// GOT offsets for local non-TLS symbols, and tp-relative offsets
// for TLS symbols, indexed by symbol number.
Local_got_offsets local_got_offsets_;
+ // For each input section, the offset of the input section in its
+ // output section. This is -1U if the input section requires a
+ // special mapping.
+ std::vector<Address> section_offsets_;
+ // Table mapping discarded comdat sections to corresponding kept sections.
+ Kept_comdat_section_table kept_comdat_sections_;
+ // Table of kept comdat groups.
+ Comdat_group_table comdat_groups_;
// Whether this object has a GNU style .eh_frame section.
bool has_eh_frame_;
};
Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
Symbol* gsym,
unsigned int type,
- Relobj* relobj,
+ Sized_relobj<size, big_endian>* relobj,
unsigned int shndx,
Address address,
bool is_relative)
Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
Output_section* os,
unsigned int type,
- Relobj* relobj,
+ Sized_relobj<size, big_endian>* relobj,
unsigned int shndx,
Address address)
: address_(address), local_sym_index_(SECTION_CODE), type_(type),
if (!this->is_section_symbol_)
this->u1_.relobj->set_needs_output_dynsym_entry(lsi);
else
- {
- section_offset_type dummy;
- Output_section* os = this->u1_.relobj->output_section(lsi, &dummy);
- gold_assert(os != NULL);
- os->set_needs_dynsym_index();
- }
+ this->u1_.relobj->output_section(lsi)->set_needs_dynsym_index();
}
break;
}
}
else
{
- section_offset_type dummy;
- Output_section* os = this->u1_.relobj->output_section(lsi, &dummy);
+ Output_section* os = this->u1_.relobj->output_section(lsi);
gold_assert(os != NULL);
if (dynamic)
index = os->dynsym_index();
// within the input section.
template<bool dynamic, int size, bool big_endian>
-section_offset_type
+typename elfcpp::Elf_types<size>::Elf_Addr
Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::
local_section_offset(Addend addend) const
{
&& this->local_sym_index_ != INVALID_CODE
&& this->is_section_symbol_);
const unsigned int lsi = this->local_sym_index_;
- section_offset_type offset;
- Output_section* os = this->u1_.relobj->output_section(lsi, &offset);
+ Output_section* os = this->u1_.relobj->output_section(lsi);
gold_assert(os != NULL);
- if (offset != -1)
+ Address offset = this->u1_.relobj->get_output_section_offset(lsi);
+ if (offset != -1U)
return offset + addend;
// This is a merge section.
offset = os->output_address(this->u1_.relobj, lsi, addend);
- gold_assert(offset != -1);
+ gold_assert(offset != -1U);
return offset;
}
Address address = this->address_;
if (this->shndx_ != INVALID_CODE)
{
- section_offset_type off;
- Output_section* os = this->u2_.relobj->output_section(this->shndx_,
- &off);
+ Output_section* os = this->u2_.relobj->output_section(this->shndx_);
gold_assert(os != NULL);
- if (off != -1)
+ Address off = this->u2_.relobj->get_output_section_offset(this->shndx_);
+ if (off != -1U)
address += os->address() + off;
else
{
p != this->input_shndxes_.end();
++p, ++contents)
{
- section_offset_type dummy;
- Output_section* os = this->relobj_->output_section(*p, &dummy);
+ Output_section* os = this->relobj_->output_section(*p);
unsigned int output_shndx;
if (os != NULL)
this->entries_.push_back(Got_entry());
unsigned int got_offset = this->last_got_offset();
object->set_local_got_offset(symndx, got_type, got_offset);
- section_offset_type off;
- Output_section* os = object->output_section(shndx, &off);
+ Output_section* os = object->output_section(shndx);
rel_dyn->add_output_section(os, r_type_1, this, got_offset);
this->entries_.push_back(Got_entry(object, symndx));
this->entries_.push_back(Got_entry());
unsigned int got_offset = this->last_got_offset();
object->set_local_got_offset(symndx, got_type, got_offset);
- section_offset_type off;
- Output_section* os = object->output_section(shndx, &off);
+ Output_section* os = object->output_section(shndx);
rela_dyn->add_output_section(os, r_type_1, this, got_offset, 0);
this->entries_.push_back(Got_entry(object, symndx));
unsigned int shndx,
off_t offset) const
{
- gold_assert(object->is_section_specially_mapped(shndx));
-
for (Input_section_list::const_iterator p = this->input_sections_.begin();
p != this->input_sections_.end();
++p)
Output_section::output_offset(const Relobj* object, unsigned int shndx,
section_offset_type offset) const
{
- gold_assert(object->is_section_specially_mapped(shndx));
// This can only be called meaningfully when layout is complete.
gold_assert(Output_data::is_layout_complete());
Output_section::output_address(const Relobj* object, unsigned int shndx,
off_t offset) const
{
- gold_assert(object->is_section_specially_mapped(shndx));
-
uint64_t addr = this->address() + this->first_input_offset_;
for (Input_section_list::const_iterator p = this->input_sections_.begin();
p != this->input_sections_.end();
Output_section::starting_output_address(const Relobj* object,
unsigned int shndx) const
{
- gold_assert(object->is_section_specially_mapped(shndx));
-
uint64_t addr = this->address() + this->first_input_offset_;
for (Input_section_list::const_iterator p = this->input_sections_.begin();
p != this->input_sections_.end();
Output_reloc(Symbol* gsym, unsigned int type, Output_data* od,
Address address, bool is_relative);
- Output_reloc(Symbol* gsym, unsigned int type, Relobj* relobj,
+ Output_reloc(Symbol* gsym, unsigned int type,
+ Sized_relobj<size, big_endian>* relobj,
unsigned int shndx, Address address, bool is_relative);
// A reloc against a local symbol or local section symbol.
Output_reloc(Output_section* os, unsigned int type, Output_data* od,
Address address);
- Output_reloc(Output_section* os, unsigned int type, Relobj* relobj,
+ Output_reloc(Output_section* os, unsigned int type,
+ Sized_relobj<size, big_endian>* relobj,
unsigned int shndx, Address address);
// Return TRUE if this is a RELATIVE relocation.
// For a local section symbol, return the offset of the input
// section within the output section. ADDEND is the addend being
// applied to the input section.
- section_offset_type
+ Address
local_section_offset(Addend addend) const;
// Get the value of the symbol referred to by a Rel relocation when
{
// If this->shndx_ is not INVALID CODE, the object which holds the
// input section being used to specify the reloc address.
- Relobj* relobj;
+ Sized_relobj<size, big_endian>* relobj;
// If this->shndx_ is INVALID_CODE, the output data being used to
// specify the reloc address. This may be NULL if the reloc
// address is absolute.
: rel_(gsym, type, od, address, is_relative), addend_(addend)
{ }
- Output_reloc(Symbol* gsym, unsigned int type, Relobj* relobj,
+ Output_reloc(Symbol* gsym, unsigned int type,
+ Sized_relobj<size, big_endian>* relobj,
unsigned int shndx, Address address, Addend addend,
bool is_relative)
: rel_(gsym, type, relobj, shndx, address, is_relative), addend_(addend)
: rel_(os, type, od, address), addend_(addend)
{ }
- Output_reloc(Output_section* os, unsigned int type, Relobj* relobj,
+ Output_reloc(Output_section* os, unsigned int type,
+ Sized_relobj<size, big_endian>* relobj,
unsigned int shndx, Address address, Addend addend)
: rel_(os, type, relobj, shndx, address), addend_(addend)
{ }
{ this->add(od, Output_reloc_type(gsym, type, od, address, false)); }
void
- add_global(Symbol* gsym, unsigned int type, Output_data* od, Relobj* relobj,
+ add_global(Symbol* gsym, unsigned int type, Output_data* od,
+ Sized_relobj<size, big_endian>* relobj,
unsigned int shndx, Address address)
{ this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
false)); }
}
void
- add_global(Symbol* gsym, unsigned int type, Output_data* od, Relobj* relobj,
+ add_global(Symbol* gsym, unsigned int type, Output_data* od,
+ Sized_relobj<size, big_endian>* relobj,
unsigned int shndx, Address address, Address addend)
{
gold_assert(addend == 0);
void
add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
- Relobj* relobj, unsigned int shndx, Address address)
+ Sized_relobj<size, big_endian>* relobj,
+ unsigned int shndx, Address address)
{
this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
true));
void
add_output_section(Output_section* os, unsigned int type, Output_data* od,
- Relobj* relobj, unsigned int shndx, Address address)
+ Sized_relobj<size, big_endian>* relobj,
+ unsigned int shndx, Address address)
{ this->add(od, Output_reloc_type(os, type, relobj, shndx, address)); }
};
false)); }
void
- add_global(Symbol* gsym, unsigned int type, Output_data* od, Relobj* relobj,
+ add_global(Symbol* gsym, unsigned int type, Output_data* od,
+ Sized_relobj<size, big_endian>* relobj,
unsigned int shndx, Address address,
Addend addend)
{ this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
void
add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
- Relobj* relobj, unsigned int shndx, Address address,
- Addend addend)
+ Sized_relobj<size, big_endian>* relobj,
+ unsigned int shndx, Address address, Addend addend)
{ this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
addend, true)); }
{ this->add(os, Output_reloc_type(os, type, od, address, addend)); }
void
- add_output_section(Output_section* os, unsigned int type, Relobj* relobj,
+ add_output_section(Output_section* os, unsigned int type,
+ Sized_relobj<size, big_endian>* relobj,
unsigned int shndx, Address address, Addend addend)
{ this->add(os, Output_reloc_type(os, type, relobj, shndx, address,
addend)); }
// Copy a relocation against a global symbol.
void
- copy_reloc(Symbol_table* symtab, Layout* layout, Relobj* object,
+ copy_reloc(Symbol_table* symtab, Layout* layout,
+ Sized_relobj<size, big_endian>* object,
unsigned int shndx, Output_section* output_section,
Symbol* sym, const elfcpp::Rela<size, big_endian>& reloc)
{
rd->relocs.reserve(shnum / 2);
- std::vector<Map_to_output>& map_sections(this->map_to_output());
+ const Output_sections& out_sections(this->output_sections());
+ const std::vector<Address>& out_offsets(this->section_offsets_);
const unsigned char *pshdrs = this->get_view(this->elf_file_.shoff(),
shnum * This::shdr_size,
continue;
}
- Output_section* os = map_sections[shndx].output_section;
+ Output_section* os = out_sections[shndx];
if (os == NULL)
continue;
sr.sh_type = sh_type;
sr.reloc_count = reloc_count;
sr.output_section = os;
- sr.needs_special_offset_handling = map_sections[shndx].offset == -1;
+ sr.needs_special_offset_handling = out_offsets[shndx] == -1U;
sr.is_data_section_allocated = is_section_allocated;
}
Views* pviews)
{
unsigned int shnum = this->shnum();
- const std::vector<Map_to_output>& map_sections(this->map_to_output());
+ const Output_sections& out_sections(this->output_sections());
+ const std::vector<Address>& out_offsets(this->section_offsets_);
File_read::Read_multiple rm;
bool is_sorted = true;
pvs->view = NULL;
- const Output_section* os = map_sections[i].output_section;
+ const Output_section* os = out_sections[i];
if (os == NULL)
continue;
- off_t output_offset = map_sections[i].offset;
+ Address output_offset = out_offsets[i];
typename This::Shdr shdr(p);
// In the normal case, this input section is simply mapped to
// the output section at offset OUTPUT_OFFSET.
- // However, if OUTPUT_OFFSET == -1, then input data is handled
+ // However, if OUTPUT_OFFSET == -1U, then input data is handled
// specially--e.g., a .eh_frame section. The relocation
// routines need to check for each reloc where it should be
// applied. For this case, we need an input/output view for the
// final data to the output file.
off_t output_section_offset;
- off_t output_section_size;
+ Address output_section_size;
if (!os->requires_postprocessing())
{
output_section_offset = os->offset();
- output_section_size = os->data_size();
+ output_section_size = convert_types<Address, off_t>(os->data_size());
}
else
{
output_section_offset = 0;
- output_section_size = os->postprocessing_buffer_size();
+ output_section_size =
+ convert_types<Address, off_t>(os->postprocessing_buffer_size());
}
off_t view_start;
section_size_type view_size;
- if (output_offset != -1)
+ if (output_offset != -1U)
{
view_start = output_section_offset + output_offset;
view_size = convert_to_section_size_type(shdr.get_sh_size());
if (view_size == 0)
continue;
- gold_assert(output_offset == -1
- || (output_offset >= 0
- && (output_offset + static_cast<off_t>(view_size)
- <= output_section_size)));
+ gold_assert(output_offset == -1U
+ || output_offset + view_size <= output_section_size);
unsigned char* view;
if (os->requires_postprocessing())
{
unsigned char* buffer = os->postprocessing_buffer();
view = buffer + view_start;
- if (output_offset != -1)
+ if (output_offset != -1U)
{
off_t sh_offset = shdr.get_sh_offset();
if (!rm.empty() && rm.back().file_offset > sh_offset)
}
else
{
- if (output_offset == -1)
+ if (output_offset == -1U)
view = of->get_input_output_view(view_start, view_size);
else
{
pvs->view = view;
pvs->address = os->address();
- if (output_offset != -1)
+ if (output_offset != -1U)
pvs->address += output_offset;
pvs->offset = view_start;
pvs->view_size = view_size;
- pvs->is_input_output_view = output_offset == -1;
+ pvs->is_input_output_view = output_offset == -1U;
pvs->is_postprocessing_view = os->requires_postprocessing();
}
unsigned int shnum = this->shnum();
Sized_target<size, big_endian>* target = this->sized_target();
- const std::vector<Map_to_output>& map_sections(this->map_to_output());
+ const Output_sections& out_sections(this->output_sections());
+ const std::vector<Address>& out_offsets(this->section_offsets_);
Relocate_info<size, big_endian> relinfo;
relinfo.options = &options;
continue;
}
- Output_section* os = map_sections[index].output_section;
+ Output_section* os = out_sections[index];
if (os == NULL)
{
// This relocation section is against a section which we
// discarded.
continue;
}
- off_t output_offset = map_sections[index].offset;
+ Address output_offset = out_offsets[index];
gold_assert((*pviews)[index].view != NULL);
if (parameters->options().relocatable())
continue;
}
- gold_assert(output_offset != -1
+ gold_assert(output_offset != -1U
|| this->relocs_must_follow_section_writes());
relinfo.reloc_shndx = i;
prelocs,
reloc_count,
os,
- output_offset == -1,
+ output_offset == -1U,
(*pviews)[index].view,
(*pviews)[index].address,
(*pviews)[index].view_size);
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
- off_t offset_in_output_section,
+ typename elfcpp::Elf_types<size>::Elf_Addr offset_in_output_section,
unsigned char* view,
typename elfcpp::Elf_types<size>::Elf_Addr address,
section_size_type view_size,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
- off_t offset_in_output_section,
+ typename elfcpp::Elf_types<size>::Elf_Addr offset_in_output_section,
unsigned char* view,
typename elfcpp::Elf_types<size>::Elf_Addr address,
section_size_type view_size,
// Copy a relocation against a global symbol.
void
- copy_reloc(Symbol_table* symtab, Layout* layout, Relobj* object,
+ copy_reloc(Symbol_table* symtab, Layout* layout,
+ Sized_relobj<size, big_endian>* object,
unsigned int shndx, Output_section* output_section,
Symbol* sym, const elfcpp::Rela<size, big_endian>& reloc)
{
{
gold_assert(!this->u_.from_object.object->is_dynamic());
Relobj* relobj = static_cast<Relobj*>(this->u_.from_object.object);
- section_offset_type dummy;
- return relobj->output_section(shndx, &dummy);
+ return relobj->output_section(shndx);
}
return NULL;
}
bool
Symbol_table::sized_finalize_symbol(Symbol* unsized_sym)
{
+ typedef typename Sized_symbol<size>::Value_type Value_type;
+
Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(unsized_sym);
// The default version of a symbol may appear twice in the symbol
return false;
}
- typename Sized_symbol<size>::Value_type value;
+ Value_type value;
switch (sym->source())
{
else
{
Relobj* relobj = static_cast<Relobj*>(symobj);
- section_offset_type secoff;
- Output_section* os = relobj->output_section(shndx, &secoff);
+ Output_section* os = relobj->output_section(shndx);
if (os == NULL)
{
return false;
}
+ uint64_t secoff64 = relobj->output_section_offset(shndx);
+ Value_type secoff = convert_types<Value_type, uint64_t>(secoff64);
if (sym->type() == elfcpp::STT_TLS)
value = sym->value() + os->tls_offset() + secoff;
else
else
{
Relobj* relobj = static_cast<Relobj*>(symobj);
- section_offset_type secoff;
- Output_section* os = relobj->output_section(in_shndx,
- &secoff);
+ Output_section* os = relobj->output_section(in_shndx);
gold_assert(os != NULL);
shndx = os->out_shndx();
{
strategy = scan.local_section_strategy(r_type, object);
if (strategy != Relocatable_relocs::RELOC_DISCARD)
- {
- section_offset_type dummy;
- Output_section* os = object->output_section(shndx,
- &dummy);
- os->set_needs_symtab_index();
- }
+ object->output_section(shndx)->set_needs_symtab_index();
}
}
}
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
- off_t offset_in_output_section,
+ typename elfcpp::Elf_types<size>::Elf_Addr offset_in_output_section,
const Relocatable_relocs* rr,
unsigned char* view,
typename elfcpp::Elf_types<size>::Elf_Addr view_address,
unsigned char* reloc_view,
section_size_type reloc_view_size)
{
+ typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
typedef typename Reloc_types<sh_type, size, big_endian>::Reloc_write
Reltype_write;
unsigned int shndx =
object->local_symbol_input_shndx(r_sym, &is_ordinary);
gold_assert(is_ordinary);
- section_offset_type dummy;
- Output_section* os = object->output_section(shndx, &dummy);
+ Output_section* os = object->output_section(shndx);
gold_assert(os != NULL);
gold_assert(os->needs_symtab_index());
new_symndx = os->symtab_index();
// Get the new offset--the location in the output section where
// this relocation should be applied.
- off_t offset = reloc.get_r_offset();
- off_t new_offset;
- if (offset_in_output_section != -1)
+ Address offset = reloc.get_r_offset();
+ Address new_offset;
+ if (offset_in_output_section != -1U)
new_offset = offset + offset_in_output_section;
else
{
- new_offset = output_section->output_offset(object,
- relinfo->data_shndx,
- offset);
- gold_assert(new_offset != -1);
+ section_offset_type sot_offset =
+ convert_types<section_offset_type, Address>(offset);
+ section_offset_type new_sot_offset =
+ output_section->output_offset(object, relinfo->data_shndx,
+ sot_offset);
+ gold_assert(new_sot_offset != -1);
+ new_offset = new_sot_offset;
}
// In an object file, r_offset is an offset within the section.
if (!parameters->options().relocatable())
{
new_offset += view_address;
- if (offset_in_output_section != -1)
+ if (offset_in_output_section != -1U)
new_offset -= offset_in_output_section;
}
// Add a potential copy relocation.
void
- copy_reloc(Symbol_table* symtab, Layout* layout, Relobj* object,
+ copy_reloc(Symbol_table* symtab, Layout* layout,
+ Sized_relobj<64, false>* object,
unsigned int shndx, Output_section* output_section,
Symbol* sym, const elfcpp::Rela<64, false>& reloc)
{