// layout.h -- lay out output file sections for gold -*- C++ -*-
-// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
// This file is part of gold.
class General_options;
class Incremental_inputs;
+class Incremental_binary;
class Input_objects;
class Mapfile;
class Symbol_table;
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 Output_reduced_debug_info_section;
class Eh_frame;
class Target;
+struct Timespec;
+
+// Return TRUE if SECNAME is the name of a compressed debug section.
+extern bool
+is_compressed_debug_section(const char* secname);
+
+// Maintain a list of free space within a section, segment, or file.
+// Used for incremental update links.
+
+class Free_list
+{
+ public:
+ Free_list()
+ : list_(), last_remove_(list_.begin()), extend_(false), length_(0)
+ { }
+
+ void
+ init(off_t len, bool extend);
+
+ void
+ remove(off_t start, off_t end);
+
+ off_t
+ allocate(off_t len, uint64_t align, off_t minoff);
+
+ void
+ dump();
+
+ static void
+ print_stats();
+
+ private:
+ struct Free_list_node
+ {
+ Free_list_node(off_t start, off_t end)
+ : start_(start), end_(end)
+ { }
+ off_t start_;
+ off_t end_;
+ };
+ typedef std::list<Free_list_node>::iterator Iterator;
+
+ // The free list.
+ std::list<Free_list_node> list_;
+
+ // The last node visited during a remove operation.
+ Iterator last_remove_;
+
+ // Whether we can extend past the original length.
+ bool extend_;
+
+ // The total length of the section, segment, or file.
+ off_t length_;
+
+ // Statistics:
+ // The total number of free lists used.
+ static unsigned int num_lists;
+ // The total number of free list nodes used.
+ static unsigned int num_nodes;
+ // The total number of calls to Free_list::remove.
+ static unsigned int num_removes;
+ // The total number of nodes visited during calls to Free_list::remove.
+ static unsigned int num_remove_visits;
+ // The total number of calls to Free_list::allocate.
+ static unsigned int num_allocates;
+ // The total number of nodes visited during calls to Free_list::allocate.
+ static unsigned int num_allocate_visits;
+};
// This task function handles mapping the input sections to output
// sections and laying them out in memory.
// 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
+ 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 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
+ find_single_comdat_section(unsigned int* pshndx, uint64_t* psize) const
{
gold_assert(this->is_comdat_);
if (this->u_.group_sections->size() != 1)
} u_;
};
+// The ordering for output sections. This controls how output
+// sections are ordered within a PT_LOAD output segment.
+
+enum Output_section_order
+{
+ // Unspecified. Used for non-load segments. Also used for the file
+ // and segment headers.
+ ORDER_INVALID,
+
+ // The PT_INTERP section should come first, so that the dynamic
+ // linker can pick it up quickly.
+ ORDER_INTERP,
+
+ // Loadable read-only note sections come next so that the PT_NOTE
+ // segment is on the first page of the executable.
+ ORDER_RO_NOTE,
+
+ // Put read-only sections used by the dynamic linker early in the
+ // executable to minimize paging.
+ ORDER_DYNAMIC_LINKER,
+
+ // Put reloc sections used by the dynamic linker after other
+ // sections used by the dynamic linker; otherwise, objcopy and strip
+ // get confused.
+ ORDER_DYNAMIC_RELOCS,
+
+ // Put the PLT reloc section after the other dynamic relocs;
+ // otherwise, prelink gets confused.
+ ORDER_DYNAMIC_PLT_RELOCS,
+
+ // The .init section.
+ ORDER_INIT,
+
+ // The PLT.
+ ORDER_PLT,
+
+ // The regular text sections.
+ ORDER_TEXT,
+
+ // The .fini section.
+ ORDER_FINI,
+
+ // The read-only sections.
+ ORDER_READONLY,
+
+ // The exception frame sections.
+ ORDER_EHFRAME,
+
+ // The TLS sections come first in the data section.
+ ORDER_TLS_DATA,
+ ORDER_TLS_BSS,
+
+ // Local RELRO (read-only after relocation) sections come before
+ // non-local RELRO sections. This data will be fully resolved by
+ // the prelinker.
+ ORDER_RELRO_LOCAL,
+
+ // Non-local RELRO sections are grouped together after local RELRO
+ // sections. All RELRO sections must be adjacent so that they can
+ // all be put into a PT_GNU_RELRO segment.
+ ORDER_RELRO,
+
+ // We permit marking exactly one output section as the last RELRO
+ // section. We do this so that the read-only GOT can be adjacent to
+ // the writable GOT.
+ ORDER_RELRO_LAST,
+
+ // Similarly, we permit marking exactly one output section as the
+ // first non-RELRO section.
+ ORDER_NON_RELRO_FIRST,
+
+ // The regular data sections come after the RELRO sections.
+ ORDER_DATA,
+
+ // Large data sections normally go in large data segments.
+ ORDER_LARGE_DATA,
+
+ // Group writable notes so that we can have a single PT_NOTE
+ // segment.
+ ORDER_RW_NOTE,
+
+ // The small data sections must be at the end of the data sections,
+ // so that they can be adjacent to the small BSS sections.
+ ORDER_SMALL_DATA,
+
+ // The BSS sections start here.
+
+ // The small BSS sections must be at the start of the BSS sections,
+ // so that they can be adjacent to the small data sections.
+ ORDER_SMALL_BSS,
+
+ // The regular BSS sections.
+ ORDER_BSS,
+
+ // The large BSS sections come after the other BSS sections.
+ ORDER_LARGE_BSS,
+
+ // Maximum value.
+ ORDER_MAX
+};
+
// This class handles the details of laying out input sections.
class Layout
delete this->segment_states_;
}
+ // For incremental links, record the base file to be modified.
+ void
+ set_incremental_base(Incremental_binary* base);
+
+ Incremental_binary*
+ incremental_base()
+ { return this->incremental_base_; }
+
+ // For incremental links, record the initial fixed layout of a section
+ // from the base file, and return a pointer to the Output_section.
+ template<int size, bool big_endian>
+ Output_section*
+ init_fixed_output_section(const char*, elfcpp::Shdr<size, big_endian>&);
+
// 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
// within the output section.
template<int size, bool big_endian>
Output_section*
- layout(Sized_relobj<size, big_endian> *object, unsigned int shndx,
+ layout(Sized_relobj_file<size, big_endian> *object, unsigned int shndx,
const char* name, const elfcpp::Shdr<size, big_endian>& shdr,
unsigned int reloc_shndx, unsigned int reloc_type, off_t* offset);
+ // For incremental updates, allocate a block of memory from the
+ // free list. Find a block starting at or after MINOFF.
+ off_t
+ allocate(off_t len, uint64_t align, off_t minoff)
+ { return this->free_list_.allocate(len, align, minoff); }
+
+ 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
// relocatable information.
template<int size, bool big_endian>
Output_section*
- layout_reloc(Sized_relobj<size, big_endian>* object,
+ layout_reloc(Sized_relobj_file<size, big_endian>* object,
unsigned int reloc_shndx,
const elfcpp::Shdr<size, big_endian>& shdr,
Output_section* data_section,
template<int size, bool big_endian>
void
layout_group(Symbol_table* symtab,
- Sized_relobj<size, big_endian>* object,
+ Sized_relobj_file<size, big_endian>* object,
unsigned int group_shndx,
const char* group_section_name,
const char* signature,
// returns the output section, and sets *OFFSET to the offset.
template<int size, bool big_endian>
Output_section*
- layout_eh_frame(Sized_relobj<size, big_endian>* object,
+ layout_eh_frame(Sized_relobj_file<size, big_endian>* object,
const unsigned char* symbols,
off_t symbols_size,
const unsigned char* symbol_names,
// .note.GNU-stack section. GNU_STACK_FLAGS is the section flags
// from that section if there was one.
void
- layout_gnu_stack(bool seen_gnu_stack, uint64_t gnu_stack_flags);
+ layout_gnu_stack(bool seen_gnu_stack, uint64_t gnu_stack_flags,
+ const Object*);
// Add an Output_section_data to the layout. This is used for
- // 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.
+ // special sections like the GOT section. ORDER is where the
+ // section should wind up in the output segment. IS_RELRO is true
+ // for relro sections.
Output_section*
add_output_section_data(const char* name, elfcpp::Elf_Word type,
elfcpp::Elf_Xword flags,
- Output_section_data*, bool is_dynamic_linker_section);
+ Output_section_data*, Output_section_order order,
+ bool is_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
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
return this->symtab_section_;
}
+ // Return the file offset of the normal symbol table.
+ off_t
+ symtab_section_offset() const;
+
// Return the dynamic symbol table.
Output_section*
dynsym_section() const
// Return the object managing inputs in incremental build. NULL in
// non-incremental builds.
Incremental_inputs*
- incremental_inputs()
+ incremental_inputs() const
{ 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*
// Create a note section, filling in the header.
Output_section*
- create_note(const char* name, int note_type, const char *section_name,
+ create_note(const char* name, int note_type, const char* section_name,
size_t descsz, bool allocate, size_t* trailing_padding);
// Create a note section for gold version.
// 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();
+ create_incremental_info_sections(Symbol_table*);
// Find the first read-only PT_LOAD segment, creating one if
// necessary.
// Return whether to include this section in the link.
template<int size, bool big_endian>
bool
- include_section(Sized_relobj<size, big_endian>* object, const char* name,
+ include_section(Sized_relobj_file<size, big_endian>* object, const char* name,
const elfcpp::Shdr<size, big_endian>&);
// Return the output section name to use given an input section
Output_section*
get_output_section(const char* name, Stringpool::Key name_key,
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
- bool is_interp, bool is_dynamic_linker_section);
+ Output_section_order order, bool is_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_interp,
- bool is_dynamic_linker_section);
+ bool is_input_section, Output_section_order order,
+ bool is_relro);
// Create a new Output_section.
Output_section*
make_output_section(const char* name, elfcpp::Elf_Word type,
- elfcpp::Elf_Xword flags, bool is_interp,
- bool is_dynamic_linker_section);
+ elfcpp::Elf_Xword flags, Output_section_order order,
+ bool is_relro);
// Attach a section to a segment.
void
attach_section_to_segment(Output_section*);
+ // Get section order.
+ Output_section_order
+ default_section_order(Output_section*, bool is_relro_local);
+
// Attach an allocated section to a segment.
void
attach_allocated_section_to_segment(Output_section*);
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.
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
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.
+ // List of output data that needs to be removed at relaxation 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_;
+ // For incremental links, the base file to be modified.
+ Incremental_binary* incremental_base_;
+ // For incremental links, a list of free space within the file.
+ Free_list free_list_;
};
// This task handles writing out data in output sections which is not