// output.h -- manage the output file for gold -*- C++ -*-
-// Copyright (C) 2006-2015 Free Software Foundation, Inc.
+// Copyright (C) 2006-2016 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
section_offset_type* poutput) const
{ return this->do_output_offset(object, shndx, offset, poutput); }
- // Return whether this is the merge section for the input section
- // SHNDX in OBJECT. This should return true when output_offset
- // would return true for some values of OFFSET.
- bool
- is_merge_section_for(const Relobj* object, unsigned int shndx) const
- { return this->do_is_merge_section_for(object, shndx); }
-
// Write the contents to a buffer. This is used for sections which
// require postprocessing, such as compression.
void
section_offset_type*) const
{ return false; }
- // The child class may implement is_merge_section_for.
- virtual bool
- do_is_merge_section_for(const Relobj*, unsigned int) const
- { return false; }
-
// The child class may implement write_to_buffer. Most child
// classes can not appear in a compressed section, and they do not
// implement this.
bool
add_local(Relobj* object, unsigned int sym_index, unsigned int got_type);
+ // Add an entry for a local symbol plus ADDEND to the GOT. This returns
+ // true if this is a new GOT entry, false if the symbol already has a GOT
+ // entry.
+ bool
+ add_local(Relobj* object, unsigned int sym_index, unsigned int got_type,
+ uint64_t addend);
+
// Like add_local, but use the PLT offset of the local symbol if it
// has one.
bool
unsigned int got_type, Output_data_reloc_generic* rel_dyn,
unsigned int r_type);
+ // Add an entry for a local symbol plus ADDEND to the GOT, and add a dynamic
+ // relocation of type R_TYPE for the GOT entry.
+ void
+ add_local_with_rel(Relobj* object, unsigned int sym_index,
+ unsigned int got_type, Output_data_reloc_generic* rel_dyn,
+ unsigned int r_type, uint64_t addend);
+
// Add a pair of entries for a local symbol to the GOT, and add
// a dynamic relocation of type R_TYPE using the section symbol of
// the output section to which input section SHNDX maps, on the first.
Output_data_reloc_generic* rel_dyn,
unsigned int r_type);
+ // Add a pair of entries for a local symbol plus ADDEND to the GOT, and add
+ // a dynamic relocation of type R_TYPE using the section symbol of
+ // the output section to which input section SHNDX maps, on the first.
+ // The first got entry will have a value of zero, the second the
+ // value of the local symbol.
+ void
+ add_local_pair_with_rel(Relobj* object, unsigned int sym_index,
+ unsigned int shndx, unsigned int got_type,
+ Output_data_reloc_generic* rel_dyn,
+ unsigned int r_type, uint64_t addend);
+
// Add a pair of entries for a local symbol to the GOT, and add
// a dynamic relocation of type R_TYPE using STN_UNDEF on the first.
// The first got entry will have a value of zero, the second the
public:
// Create a zero entry.
Got_entry()
- : local_sym_index_(RESERVED_CODE), use_plt_or_tls_offset_(false)
+ : local_sym_index_(RESERVED_CODE), use_plt_or_tls_offset_(false),
+ addend_(0)
{ this->u_.constant = 0; }
// Create a global symbol entry.
Got_entry(Symbol* gsym, bool use_plt_or_tls_offset)
: local_sym_index_(GSYM_CODE),
- use_plt_or_tls_offset_(use_plt_or_tls_offset)
+ use_plt_or_tls_offset_(use_plt_or_tls_offset), addend_(0)
{ this->u_.gsym = gsym; }
// Create a local symbol entry.
Got_entry(Relobj* object, unsigned int local_sym_index,
bool use_plt_or_tls_offset)
: local_sym_index_(local_sym_index),
- use_plt_or_tls_offset_(use_plt_or_tls_offset)
+ use_plt_or_tls_offset_(use_plt_or_tls_offset), addend_(0)
{
gold_assert(local_sym_index != GSYM_CODE
&& local_sym_index != CONSTANT_CODE
this->u_.object = object;
}
+ // Create a local symbol entry plus addend.
+ Got_entry(Relobj* object, unsigned int local_sym_index,
+ bool use_plt_or_tls_offset, uint64_t addend)
+ : local_sym_index_(local_sym_index),
+ use_plt_or_tls_offset_(use_plt_or_tls_offset), addend_(addend)
+ {
+ gold_assert(local_sym_index != GSYM_CODE
+ && local_sym_index != CONSTANT_CODE
+ && local_sym_index != RESERVED_CODE
+ && local_sym_index == this->local_sym_index_);
+ this->u_.object = object;
+ }
+
// Create a constant entry. The constant is a host value--it will
// be swapped, if necessary, when it is written out.
explicit Got_entry(Valtype constant)
// Whether to use the PLT offset of the symbol if it has one.
// For TLS symbols, whether to offset the symbol value.
bool use_plt_or_tls_offset_ : 1;
+ // The addend.
+ uint64_t addend_;
};
typedef std::vector<Got_entry> Got_entries;
public:
Output_section_lookup_maps()
: is_valid_(true), merge_sections_by_properties_(),
- merge_sections_by_id_(), relaxed_input_sections_by_id_()
+ relaxed_input_sections_by_id_()
{ }
// Whether the maps are valid.
clear()
{
this->merge_sections_by_properties_.clear();
- this->merge_sections_by_id_.clear();
this->relaxed_input_sections_by_id_.clear();
// A cleared map is valid.
this->is_valid_ = true;
return p != this->merge_sections_by_properties_.end() ? p->second : NULL;
}
- // Find a merge section by section ID of a merge input section. Return NULL
- // if none is found.
- Output_merge_base*
- find_merge_section(const Object* object, unsigned int shndx) const
- {
- gold_assert(this->is_valid_);
- Merge_sections_by_id::const_iterator p =
- this->merge_sections_by_id_.find(Const_section_id(object, shndx));
- return p != this->merge_sections_by_id_.end() ? p->second : NULL;
- }
-
// Add a merge section pointed by POMB with properties MSP.
void
add_merge_section(const Merge_section_properties& msp,
gold_assert(result.second);
}
- // Add a mapping from a merged input section in OBJECT with index SHNDX
- // to a merge output section pointed by POMB.
- void
- add_merge_input_section(const Object* object, unsigned int shndx,
- Output_merge_base* pomb)
- {
- Const_section_id csid(object, shndx);
- std::pair<Const_section_id, Output_merge_base*> value(csid, pomb);
- std::pair<Merge_sections_by_id::iterator, bool> result =
- this->merge_sections_by_id_.insert(value);
- gold_assert(result.second);
- }
-
// Find a relaxed input section of OBJECT with index SHNDX.
Output_relaxed_input_section*
- find_relaxed_input_section(const Object* object, unsigned int shndx) const
+ find_relaxed_input_section(const Relobj* object, unsigned int shndx) const
{
gold_assert(this->is_valid_);
Relaxed_input_sections_by_id::const_iterator p =
}
private:
- typedef Unordered_map<Const_section_id, Output_merge_base*,
- Const_section_id_hash>
- Merge_sections_by_id;
-
typedef Unordered_map<Merge_section_properties, Output_merge_base*,
Merge_section_properties::hash,
Merge_section_properties::equal_to>
bool is_valid_;
// Merge sections by merge section properties.
Merge_sections_by_properties merge_sections_by_properties_;
- // Merge sections by section IDs.
- Merge_sections_by_id merge_sections_by_id_;
// Relaxed sections by section IDs.
Relaxed_input_sections_by_id relaxed_input_sections_by_id_;
};
void
update_flags_for_input_section(elfcpp::Elf_Xword flags);
+ // Set the output section flags.
+ void
+ set_flags(elfcpp::Elf_Xword flags)
+ { this->flags_ = flags; }
+
// Return the entsize field.
uint64_t
entsize() const
section_offset_type offset,
section_offset_type* poutput) const;
- // Return whether this is the merge section for the input section
- // SHNDX in OBJECT.
- bool
- is_merge_section_for(const Relobj* object, unsigned int shndx) const;
-
// Write out the data. This does nothing for an input section.
void
write(Output_file*);
// Find the merge section into which an input section with index SHNDX in
// OBJECT has been added. Return NULL if none found.
- Output_section_data*
+ const Output_section_data*
find_merge_section(const Relobj* object, unsigned int shndx) const;
// Build a relaxation map.