#include <cstring>
#include <list>
+#include <map>
#include <string>
#include <utility>
#include <vector>
{
class General_options;
+class Incremental_inputs;
class Input_objects;
class Mapfile;
class Symbol_table;
class Output_section_data;
class Output_section;
class Output_section_headers;
+class Output_segment_headers;
+class Output_file_header;
class Output_segment;
class Output_data;
+class Output_data_reloc_generic;
class Output_data_dynamic;
class Output_symtab_xindex;
class Output_reduced_debug_abbrev_section;
class Eh_frame;
class Target;
+// Return TRUE if SECNAME is the name of a compressed debug section.
+extern bool
+is_compressed_debug_section(const char* secname);
+
// This task function handles mapping the input sections to output
// sections and laying them out in memory.
Mapfile* mapfile_;
};
-// This struct holds information about the comdat or .gnu.linkonce
-// that will be kept.
+// This class holds information about the comdat group or
+// .gnu.linkonce section that will be kept for a given signature.
-struct Kept_section
+class Kept_section
{
+ private:
+ // For a comdat group, we build a mapping from the name of each
+ // section in the group to the section index and the size in object.
+ // When we discard a group in some other object file, we use this
+ // map to figure out which kept section the discarded section is
+ // associated with. We then use that mapping when processing relocs
+ // against discarded sections.
+ struct Comdat_section_info
+ {
+ // The section index.
+ unsigned int shndx;
+ // The section size.
+ uint64_t size;
+
+ Comdat_section_info(unsigned int a_shndx, uint64_t a_size)
+ : shndx(a_shndx), size(a_size)
+ { }
+ };
+
+ // Most comdat groups have only one or two sections, so we use a
+ // std::map rather than an Unordered_map to optimize for that case
+ // without paying too heavily for groups with more sections.
+ typedef std::map<std::string, Comdat_section_info> Comdat_group;
+
+ public:
Kept_section()
- : object(NULL), shndx(0), is_group(false), group_sections(NULL)
- { }
- Kept_section(Relobj* a_object, unsigned int a_shndx, bool a_is_group)
- : object(a_object), shndx(a_shndx), is_group(a_is_group),
- group_sections(NULL)
- { }
+ : object_(NULL), shndx_(0), is_comdat_(false), is_group_name_(false)
+ { this->u_.linkonce_size = 0; }
+
+ // We need to support copies for the signature map in the Layout
+ // object, but we should never copy an object after it has been
+ // marked as a comdat section.
+ Kept_section(const Kept_section& k)
+ : object_(k.object_), shndx_(k.shndx_), is_comdat_(false),
+ is_group_name_(k.is_group_name_)
+ {
+ gold_assert(!k.is_comdat_);
+ this->u_.linkonce_size = 0;
+ }
+
+ ~Kept_section()
+ {
+ if (this->is_comdat_)
+ delete this->u_.group_sections;
+ }
+
+ // The object where this section lives.
+ Relobj*
+ object() const
+ { return this->object_; }
+
+ // Set the object.
+ void
+ set_object(Relobj* object)
+ {
+ gold_assert(this->object_ == NULL);
+ this->object_ = object;
+ }
+
+ // The section index.
+ unsigned int
+ shndx() const
+ { return this->shndx_; }
+
+ // Set the section index.
+ void
+ set_shndx(unsigned int shndx)
+ {
+ gold_assert(this->shndx_ == 0);
+ this->shndx_ = shndx;
+ }
+
+ // Whether this is a comdat group.
+ bool
+ is_comdat() const
+ { return this->is_comdat_; }
+
+ // Set that this is a comdat group.
+ void
+ set_is_comdat()
+ {
+ gold_assert(!this->is_comdat_);
+ this->is_comdat_ = true;
+ this->u_.group_sections = new Comdat_group();
+ }
+
+ // Whether this is associated with the name of a group or section
+ // rather than the symbol name derived from a linkonce section.
+ bool
+ is_group_name() const
+ { return this->is_group_name_; }
+
+ // Note that this represents a comdat group rather than a single
+ // linkonce section.
+ void
+ set_is_group_name()
+ { this->is_group_name_ = true; }
+
+ // Add a section to the group list.
+ void
+ add_comdat_section(const std::string& name, unsigned int shndx,
+ uint64_t size)
+ {
+ gold_assert(this->is_comdat_);
+ Comdat_section_info sinfo(shndx, size);
+ this->u_.group_sections->insert(std::make_pair(name, sinfo));
+ }
+
+ // Look for a section name in the group list, and return whether it
+ // was found. If found, returns the section index and size.
+ bool
+ find_comdat_section(const std::string& name, unsigned int *pshndx,
+ uint64_t *psize) const
+ {
+ gold_assert(this->is_comdat_);
+ Comdat_group::const_iterator p = this->u_.group_sections->find(name);
+ if (p == this->u_.group_sections->end())
+ return false;
+ *pshndx = p->second.shndx;
+ *psize = p->second.size;
+ return true;
+ }
+
+ // If there is only one section in the group list, return true, and
+ // return the section index and size.
+ bool
+ find_single_comdat_section(unsigned int *pshndx, uint64_t *psize) const
+ {
+ gold_assert(this->is_comdat_);
+ if (this->u_.group_sections->size() != 1)
+ return false;
+ Comdat_group::const_iterator p = this->u_.group_sections->begin();
+ *pshndx = p->second.shndx;
+ *psize = p->second.size;
+ return true;
+ }
+
+ // Return the size of a linkonce section.
+ uint64_t
+ linkonce_size() const
+ {
+ gold_assert(!this->is_comdat_);
+ return this->u_.linkonce_size;
+ }
+
+ // Set the size of a linkonce section.
+ void
+ set_linkonce_size(uint64_t size)
+ {
+ gold_assert(!this->is_comdat_);
+ this->u_.linkonce_size = size;
+ }
- typedef Unordered_map<std::string, unsigned int> Comdat_group;
+ private:
+ // No assignment.
+ Kept_section& operator=(const Kept_section&);
- // The object containing the comdat or .gnu.linkonce.
- Relobj* object;
- // Index to the group section for comdats and the section itself for
+ // The object containing the comdat group or .gnu.linkonce section.
+ Relobj* object_;
+ // Index of the group section for comdats and the section itself for
// .gnu.linkonce.
- unsigned int shndx;
+ unsigned int shndx_;
+ // True if this is for a comdat group rather than a .gnu.linkonce
+ // section.
+ bool is_comdat_;
// The Kept_sections are values of a mapping, that maps names to
// them. This field is true if this struct is associated with the
// name of a comdat or .gnu.linkonce, false if it is associated with
// the name of a symbol obtained from the .gnu.linkonce.* name
// through some heuristics.
- bool is_group;
- // For comdats, a map from names of the sections in the group to
- // indexes in OBJECT_. NULL for .gnu.linkonce.
- Comdat_group* group_sections;
+ bool is_group_name_;
+ union
+ {
+ // If the is_comdat_ field is true, this holds a map from names of
+ // the sections in the group to section indexes in object_ and to
+ // section sizes.
+ Comdat_group* group_sections;
+ // If the is_comdat_ field is false, this holds the size of the
+ // single section.
+ uint64_t linkonce_size;
+ } u_;
};
// This class handles the details of laying out input sections.
public:
Layout(int number_of_input_files, Script_options*);
+ ~Layout()
+ {
+ delete this->relaxation_debug_check_;
+ delete this->segment_states_;
+ }
+
// Given an input section SHNDX, named NAME, with data in SHDR, from
// the object file OBJECT, return the output section where this
// input section should go. RELOC_SHNDX is the index of a
const char* name, const elfcpp::Shdr<size, big_endian>& shdr,
unsigned int reloc_shndx, unsigned int reloc_type, off_t* offset);
+ unsigned int
+ find_section_order_index(const std::string&);
+
+ void
+ read_layout_from_file();
+
// Layout an input reloc section when doing a relocatable link. The
// section is RELOC_SHNDX in OBJECT, with data in SHDR.
// DATA_SECTION is the reloc section to which it refers. RR is the
layout_gnu_stack(bool seen_gnu_stack, uint64_t gnu_stack_flags);
// Add an Output_section_data to the layout. This is used for
- // special sections like the GOT section.
+ // special sections like the GOT section. IS_DYNAMIC_LINKER_SECTION
+ // is true for sections which are used by the dynamic linker, such
+ // as dynamic reloc sections. IS_RELRO is true for relro sections.
+ // IS_LAST_RELRO is true for the last relro section.
+ // IS_FIRST_NON_RELRO is true for the first section after the relro
+ // sections.
Output_section*
add_output_section_data(const char* name, elfcpp::Elf_Word type,
elfcpp::Elf_Xword flags,
- Output_section_data*);
+ Output_section_data*, bool is_dynamic_linker_section,
+ bool is_relro, bool is_last_relro,
+ bool is_first_non_relro);
+
+ // Increase the size of the relro segment by this much.
+ void
+ increase_relro(unsigned int s)
+ { this->increase_relro_ += s; }
// Create dynamic sections if necessary.
void
void
define_section_symbols(Symbol_table*);
+ // Create automatic note sections.
+ void
+ create_notes();
+
// Create sections for linker scripts.
void
create_script_sections()
is_linkonce(const char* name)
{ return strncmp(name, ".gnu.linkonce", sizeof(".gnu.linkonce") - 1) == 0; }
+ // Whether we have added an input section.
+ bool
+ have_added_input_section() const
+ { return this->have_added_input_section_; }
+
// Return true if a section is a debugging section.
static inline bool
is_debug_info_section(const char* name)
{
// Debugging sections can only be recognized by name.
return (strncmp(name, ".debug", sizeof(".debug") - 1) == 0
+ || strncmp(name, ".zdebug", sizeof(".zdebug") - 1) == 0
|| strncmp(name, ".gnu.linkonce.wi.",
sizeof(".gnu.linkonce.wi.") - 1) == 0
|| strncmp(name, ".line", sizeof(".line") - 1) == 0
// Check if a comdat group or .gnu.linkonce section with the given
// NAME is selected for the link. If there is already a section,
// *KEPT_SECTION is set to point to the signature and the function
- // returns false. Otherwise, the CANDIDATE signature is recorded
- // for this NAME in the layout object, *KEPT_SECTION is set to the
- // internal copy and the function return false. In some cases, with
- // CANDIDATE->GROUP_ being false, KEPT_SECTION can point back to
- // CANDIDATE.
+ // returns false. Otherwise, OBJECT, SHNDX,IS_COMDAT, and
+ // IS_GROUP_NAME are recorded for this NAME in the layout object,
+ // *KEPT_SECTION is set to the internal copy and the function return
+ // false.
bool
- find_or_add_kept_section(const std::string& name,
- Kept_section* candidate,
- Kept_section** kept_section);
-
- // Find the given comdat signature, and return the object and section
- // index of the kept group.
- Relobj*
- find_kept_object(const std::string&, unsigned int*) const;
+ find_or_add_kept_section(const std::string& name, Relobj* object,
+ unsigned int shndx, bool is_comdat,
+ bool is_group_name, Kept_section** kept_section);
// Finalize the layout after all the input sections have been added.
off_t
script_options() const
{ return this->script_options_; }
+ // Return the object managing inputs in incremental build. NULL in
+ // non-incremental builds.
+ Incremental_inputs*
+ incremental_inputs()
+ { return this->incremental_inputs_; }
+
+ // For the target-specific code to add dynamic tags which are common
+ // to most targets.
+ void
+ add_target_dynamic_tags(bool use_rel, const Output_data* plt_got,
+ const Output_data* plt_rel,
+ const Output_data_reloc_generic* dyn_rel,
+ bool add_debug, bool dynrel_includes_plt);
+
// Compute and write out the build ID if needed.
void
write_build_id(Output_file*) const;
// Make a section for a linker script to hold data.
Output_section*
- make_output_section_for_script(const char* name);
+ make_output_section_for_script(const char* name,
+ Script_sections::Section_type section_type);
// Make a segment. This is used by the linker script code.
Output_segment*
void
attach_sections_to_segments();
+ // For relaxation clean up, we need to know output section data created
+ // from a linker script.
+ void
+ new_output_section_data_from_script(Output_section_data* posd)
+ {
+ if (this->record_output_section_data_from_script_)
+ this->script_output_section_data_list_.push_back(posd);
+ }
+
+ // Return section list.
+ const Section_list&
+ section_list() const
+ { return this->section_list_; }
+
private:
Layout(const Layout&);
Layout& operator=(const Layout&);
- // Mapping from .gnu.linkonce section names to output section names.
- struct Linkonce_mapping
+ // Mapping from input section names to output section names.
+ struct Section_name_mapping
{
const char* from;
int fromlen;
const char* to;
int tolen;
};
- static const Linkonce_mapping linkonce_mapping[];
- static const int linkonce_mapping_count;
+ static const Section_name_mapping section_name_mapping[];
+ static const int section_name_mapping_count;
// During a relocatable link, a list of group sections and
// signatures.
// Record whether the stack must be executable.
void
- create_executable_stack_info(const Target*);
+ create_executable_stack_info();
// Create a build ID note if needed.
void
create_build_id();
+ // Link .stab and .stabstr sections.
+ void
+ link_stabs_sections();
+
+ // Create .gnu_incremental_inputs and .gnu_incremental_strtab sections needed
+ // for the next run of incremental linking to check what has changed.
+ void
+ create_incremental_info_sections();
+
// Find the first read-only PT_LOAD segment, creating one if
// necessary.
Output_segment*
void
finish_dynamic_section(const Input_objects*, const Symbol_table*);
+ // Set the size of the _DYNAMIC symbol.
+ void
+ set_dynamic_symbol_size(const Symbol_table*);
+
// Create the .interp section and PT_INTERP segment.
void
create_interp(const Target* target);
static const char*
output_section_name(const char* name, size_t* plen);
- // Return the output section name to use for a linkonce section
- // name. PLEN is as for output_section_name.
- static const char*
- linkonce_output_name(const char* name, size_t* plen);
-
// Return the number of allocated output sections.
size_t
allocated_output_section_count() const;
// Return the output section for NAME, TYPE and FLAGS.
Output_section*
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,
+ bool is_interp, bool is_dynamic_linker_section,
+ bool is_relro, bool is_last_relro,
+ bool is_first_non_relro);
// 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 is_input_section);
+ bool is_input_section, bool is_interp,
+ bool is_dynamic_linker_section, bool is_relro,
+ bool is_last_relro, bool is_first_non_relro);
// Create a new Output_section.
Output_section*
make_output_section(const char* name, elfcpp::Elf_Word type,
- elfcpp::Elf_Xword flags);
+ elfcpp::Elf_Xword flags, bool is_interp,
+ bool is_dynamic_linker_section, bool is_relro,
+ bool is_last_relro, bool is_first_non_relro);
// Attach a section to a segment.
void
Output_segment*
set_section_addresses_from_script(Symbol_table*);
+ // Find appropriate places or orphan sections in a script.
+ void
+ place_orphan_sections_in_script();
+
// Return whether SEG1 comes before SEG2 in the output file.
static bool
segment_precedes(const Output_segment* seg1, const Output_segment* seg2);
+ // Use to save and restore segments during relaxation.
+ typedef Unordered_map<const Output_segment*, const Output_segment*>
+ Segment_states;
+
+ // Save states of current output segments.
+ void
+ save_segments(Segment_states*);
+
+ // Restore output segment states.
+ void
+ restore_segments(const Segment_states*);
+
+ // Clean up after relaxation so that it is possible to lay out the
+ // sections and segments again.
+ void
+ clean_up_after_relaxation();
+
+ // Doing preparation work for relaxation. This is factored out to make
+ // Layout::finalized a bit smaller and easier to read.
+ void
+ prepare_for_relaxation();
+
+ // Main body of the relaxation loop, which lays out the section.
+ off_t
+ relaxation_loop_body(int, Target*, Symbol_table*, Output_segment**,
+ Output_segment*, Output_segment_headers*,
+ Output_file_header*, unsigned int*);
+
// A mapping used for kept comdats/.gnu.linkonce group signatures.
typedef Unordered_map<std::string, Kept_section> Signatures;
{ return Layout::segment_precedes(seg1, seg2); }
};
+ typedef std::vector<Output_section_data*> Output_section_data_list;
+
+ // Debug checker class.
+ class Relaxation_debug_check
+ {
+ public:
+ Relaxation_debug_check()
+ : section_infos_()
+ { }
+
+ // Check that sections and special data are in reset states.
+ void
+ check_output_data_for_reset_values(const Layout::Section_list&,
+ const Layout::Data_list&);
+
+ // Record information of a section list.
+ void
+ read_sections(const Layout::Section_list&);
+
+ // Verify a section list with recorded information.
+ void
+ verify_sections(const Layout::Section_list&);
+
+ private:
+ // Information we care about a section.
+ struct Section_info
+ {
+ // Output section described by this.
+ Output_section* output_section;
+ // Load address.
+ uint64_t address;
+ // Data size.
+ off_t data_size;
+ // File offset.
+ off_t offset;
+ };
+
+ // Section information.
+ std::vector<Section_info> section_infos_;
+ };
+
// The number of input files, for sizing tables.
int number_of_input_files_;
// Information set by scripts or by command line options.
Output_segment* tls_segment_;
// A pointer to the PT_GNU_RELRO segment if there is one.
Output_segment* relro_segment_;
+ // A backend may increase the size of the PT_GNU_RELRO segment if
+ // there is one. This is the amount to increase it by.
+ unsigned int increase_relro_;
// The SHT_SYMTAB output section.
Output_section* symtab_section_;
// The SHT_SYMTAB_SHNDX for the regular symbol table if there is one.
Output_symtab_xindex* dynsym_xindex_;
// The SHT_DYNAMIC output section if there is one.
Output_section* dynamic_section_;
+ // The _DYNAMIC symbol if there is one.
+ Symbol* dynamic_symbol_;
// The dynamic data which goes into dynamic_section_.
Output_data_dynamic* dynamic_data_;
// The exception frame output section if there is one.
Group_signatures group_signatures_;
// The size of the output file.
off_t output_file_size_;
+ // Whether we have added an input section to an output section.
+ bool have_added_input_section_;
// Whether we have attached the sections to the segments.
bool sections_are_attached_;
// Whether we have seen an object file marked to require an
bool any_postprocessing_sections_;
// Whether we have resized the signatures_ hash table.
bool resized_signatures_;
+ // Whether we have created a .stab*str output section.
+ bool have_stabstr_section_;
+ // In incremental build, holds information check the inputs and build the
+ // .gnu_incremental_inputs section.
+ Incremental_inputs* incremental_inputs_;
+ // Whether we record output section data created in script
+ bool record_output_section_data_from_script_;
+ // List of output data that needs to be removed at relexation clean up.
+ Output_section_data_list script_output_section_data_list_;
+ // Structure to save segment states before entering the relaxation loop.
+ Segment_states* segment_states_;
+ // A relaxation debug checker. We only create one when in debugging mode.
+ Relaxation_debug_check* relaxation_debug_check_;
+ // Hash a pattern to its position in the section ordering file.
+ Unordered_map<std::string, unsigned int> input_section_position_;
+ // Vector of glob only patterns in the section_ordering file.
+ std::vector<std::string> input_section_glob_;
};
// This task handles writing out data in output sections which is not