// layout.h -- lay out output file sections for gold -*- C++ -*-
-// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright (C) 2006-2019 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
class Output_reduced_debug_abbrev_section;
class Output_reduced_debug_info_section;
class Eh_frame;
+class Gdb_index;
class Target;
struct Timespec;
extern bool
is_compressed_debug_section(const char* secname);
+// Return the name of the corresponding uncompressed debug section.
+extern std::string
+corresponding_uncompressed_section_name(std::string secname);
+
// Maintain a list of free space within a section, segment, or file.
// Used for incremental update links.
class Free_list
{
public:
+ 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>::const_iterator Const_iterator;
+
Free_list()
- : list_(), last_remove_(list_.begin()), extend_(false), length_(0)
+ : list_(), last_remove_(list_.begin()), extend_(false), length_(0),
+ min_hole_(0)
{ }
+ // Initialize the free list for a section of length LEN.
+ // If EXTEND is true, free space may be allocated past the end.
void
init(off_t len, bool extend);
+ // Set the minimum hole size that is allowed when allocating
+ // from the free list.
+ void
+ set_min_hole_size(off_t min_hole)
+ { this->min_hole_ = min_hole; }
+
+ // Remove a chunk from the free list.
void
remove(off_t start, off_t end);
+ // Allocate a chunk of space from the free list of length LEN,
+ // with alignment ALIGN, and minimum offset MINOFF.
off_t
allocate(off_t len, uint64_t align, off_t minoff);
+ // Return an iterator for the beginning of the free list.
+ Const_iterator
+ begin() const
+ { return this->list_.begin(); }
+
+ // Return an iterator for the end of the free list.
+ Const_iterator
+ end() const
+ { return this->list_.end(); }
+
+ // Dump the free list (for debugging).
void
dump();
+ // Print usage statistics.
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.
// The total length of the section, segment, or file.
off_t length_;
+ // The minimum hole size allowed. When allocating from the free list,
+ // we must not leave a hole smaller than this.
+ off_t min_hole_;
+
// Statistics:
// The total number of free lists used.
static unsigned int num_lists;
Layout_task_runner(const General_options& options,
const Input_objects* input_objects,
Symbol_table* symtab,
- Target* target,
+ Target* target,
Layout* layout,
Mapfile* mapfile)
: options_(options), input_objects_(input_objects), symtab_(symtab),
// The PLT.
ORDER_PLT,
+ // The hot text sections, prefixed by .text.hot.
+ ORDER_TEXT_HOT,
+
// The regular text sections.
ORDER_TEXT,
+ // The startup text sections, prefixed by .text.startup.
+ ORDER_TEXT_STARTUP,
+
+ // The startup text sections, prefixed by .text.startup.
+ ORDER_TEXT_EXIT,
+
+ // The unlikely text sections, prefixed by .text.unlikely.
+ ORDER_TEXT_UNLIKELY,
+
// The .fini section.
ORDER_FINI,
Output_section*
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);
+ unsigned int sh_type, unsigned int reloc_shndx,
+ unsigned int reloc_type, off_t* offset);
+
+ std::map<Section_id, unsigned int>*
+ get_section_order_map()
+ { return &this->section_order_map_; }
+
+ // Struct to store segment info when mapping some input sections to
+ // unique segments using linker plugins. Mapping an input section to
+ // a unique segment is done by first placing such input sections in
+ // unique output sections and then mapping the output section to a
+ // unique segment. NAME is the name of the output section. FLAGS
+ // and ALIGN are the extra flags and alignment of the segment.
+ struct Unique_segment_info
+ {
+ // Identifier for the segment. ELF segments don't have names. This
+ // is used as the name of the output section mapped to the segment.
+ const char* name;
+ // Additional segment flags.
+ uint64_t flags;
+ // Segment alignment.
+ uint64_t align;
+ };
+
+ // Mapping from input section to segment.
+ typedef std::map<Const_section_id, Unique_segment_info*>
+ Section_segment_map;
+
+ // Maps section SECN to SEGMENT s.
+ void
+ insert_section_segment_map(Const_section_id secn, Unique_segment_info *s);
+
+ // Some input sections require special ordering, for compatibility
+ // with GNU ld. Given the name of an input section, return -1 if it
+ // does not require special ordering. Otherwise, return the index
+ // by which it should be ordered compared to other input sections
+ // that require special ordering.
+ static int
+ special_ordering_of_input_section(const char* name);
+
+ bool
+ is_section_ordering_specified()
+ { return this->section_ordering_specified_; }
+
+ void
+ set_section_ordering_specified()
+ { this->section_ordering_specified_ = true; }
+
+ bool
+ is_unique_segment_for_sections_specified() const
+ { return this->unique_segment_for_sections_specified_; }
+
+ void
+ set_unique_segment_for_sections_specified()
+ { this->unique_segment_for_sections_specified_ = true; }
+
+ bool
+ is_lto_slim_object () const
+ { return this->lto_slim_object_; }
+
+ void
+ set_lto_slim_object ()
+ { this->lto_slim_object_ = true; }
// For incremental updates, allocate a block of memory from the
// free list. Find a block starting at or after MINOFF.
unsigned int
find_section_order_index(const std::string&);
+ // Read the sequence of input sections from the file specified with
+ // linker option --section-ordering-file.
void
read_layout_from_file();
unsigned int reloc_shndx, unsigned int reloc_type,
off_t* offset);
+ // After processing all input files, we call this to make sure that
+ // the optimized .eh_frame sections have been added to the output
+ // section.
+ void
+ finalize_eh_frame_section();
+
+ // Add .eh_frame information for a PLT. The FDE must start with a
+ // 4-byte PC-relative reference to the start of the PLT, followed by
+ // a 4-byte size of PLT.
+ void
+ add_eh_frame_for_plt(Output_data* plt, const unsigned char* cie_data,
+ size_t cie_length, const unsigned char* fde_data,
+ size_t fde_length);
+
+ // Remove all post-map .eh_frame information for a PLT.
+ void
+ remove_eh_frame_for_plt(Output_data* plt, const unsigned char* cie_data,
+ size_t cie_length);
+
+ // Scan a .debug_info or .debug_types section, and add summary
+ // information to the .gdb_index section.
+ template<int size, bool big_endian>
+ void
+ add_to_gdb_index(bool is_type_unit,
+ Sized_relobj<size, big_endian>* object,
+ const unsigned char* symbols,
+ off_t symbols_size,
+ unsigned int shndx,
+ unsigned int reloc_shndx,
+ unsigned int reloc_type);
+
// Handle a GNU stack note. This is called once per input object
// file. SEEN_GNU_STACK is true if the object file has a
// .note.GNU-stack section. GNU_STACK_FLAGS is the section flags
layout_gnu_stack(bool seen_gnu_stack, uint64_t gnu_stack_flags,
const Object*);
+ // Layout a .note.gnu.property section.
+ void
+ layout_gnu_property(unsigned int note_type,
+ unsigned int pr_type,
+ size_t pr_datasz,
+ const unsigned char* pr_data,
+ const Object* object);
+
+ // Merge per-object properties with program properties.
+ void
+ merge_gnu_properties(const Object* object);
+
+ // Add a target-specific property for the output .note.gnu.property section.
+ void
+ add_gnu_property(unsigned int note_type,
+ unsigned int pr_type,
+ size_t pr_datasz,
+ const unsigned char* pr_data);
+
// Add an Output_section_data to the layout. This is used for
// special sections like the GOT section. ORDER is where the
// section should wind up in the output segment. IS_RELRO is true
dynpool() const
{ return &this->dynpool_; }
+ // Return the .dynamic output section. This is only valid after the
+ // layout has been finalized.
+ Output_section*
+ dynamic_section() const
+ { return this->dynamic_section_; }
+
// Return the symtab_xindex section used to hold large section
// indexes for the normal symbol table.
Output_symtab_xindex*
{
// 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
- || strncmp(name, ".stab", sizeof(".stab") - 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
+ || strncmp(name, ".stab", sizeof(".stab") - 1) == 0
+ || strncmp(name, ".pdr", sizeof(".pdr") - 1) == 0);
}
+ // Return true if RELOBJ is an input file whose base name matches
+ // FILE_NAME. The base name must have an extension of ".o", and
+ // must be exactly FILE_NAME.o or FILE_NAME, one character, ".o".
+ static bool
+ match_file_name(const Relobj* relobj, const char* file_name);
+
+ // Return whether section SHNDX in RELOBJ is a .ctors/.dtors section
+ // with more than one word being mapped to a .init_array/.fini_array
+ // section.
+ bool
+ is_ctors_in_init_array(Relobj* relobj, unsigned int shndx) const;
+
// 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
// *KEPT_SECTION is set to the internal copy and the function return
// false.
bool
- find_or_add_kept_section(const std::string& name, Relobj* object,
+ 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);
off_t
symtab_section_offset() const;
+ // Return the section index of the normal symbol tabl.e
+ unsigned int
+ symtab_section_shndx() const;
+
// Return the dynamic symbol table.
Output_section*
dynsym_section() const
const Output_data_reloc_generic* dyn_rel,
bool add_debug, bool dynrel_includes_plt);
+ // Add a target-specific dynamic tag with constant value.
+ void
+ add_target_specific_dynamic_tag(elfcpp::DT tag, unsigned int val);
+
// Compute and write out the build ID if needed.
void
- write_build_id(Output_file*) const;
+ write_build_id(Output_file*, unsigned char*, size_t) const;
// Rewrite output file in binary format.
void
void
get_allocated_sections(Section_list*) const;
+ // Store the executable sections into the section list.
+ void
+ get_executable_sections(Section_list*) const;
+
// Make a section for a linker script to hold data.
Output_section*
make_output_section_for_script(const char* name,
// Attach sections to segments.
void
- attach_sections_to_segments();
+ attach_sections_to_segments(const Target*);
// For relaxation clean up, we need to know output section data created
// from a linker script.
section_list() const
{ return this->section_list_; }
+ // Returns TRUE iff NAME (an input section from RELOBJ) will
+ // be mapped to an output section that should be KEPT.
+ bool
+ keep_input_section(const Relobj*, const char*);
+
+ // Add a special output object that will be recreated afresh
+ // if there is another relaxation iteration.
+ void
+ add_relax_output(Output_data* data)
+ { this->relax_output_list_.push_back(data); }
+
+ // Clear out (and free) everything added by add_relax_output.
+ void
+ reset_relax_output();
+
private:
Layout(const Layout&);
Layout& operator=(const Layout&);
};
static const Section_name_mapping section_name_mapping[];
static const int section_name_mapping_count;
+ static const Section_name_mapping text_section_name_mapping[];
+ static const int text_section_name_mapping_count;
+
+ // Find section name NAME in map and return the mapped name if found
+ // with the length set in PLEN.
+ static const char* match_section_name(const Section_name_mapping* map,
+ const int count, const char* name,
+ size_t* plen);
// During a relocatable link, a list of group sections and
// signatures.
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 gnu program properties.
+ void
+ create_gnu_properties_note();
+
// Create a note section for gold version.
void
create_gold_note();
- // Record whether the stack must be executable.
+ // Record whether the stack must be executable, and a user-supplied size.
void
- create_executable_stack_info();
+ create_stack_segment();
// Create a build ID note if needed.
void
// Find the first read-only PT_LOAD segment, creating one if
// necessary.
Output_segment*
- find_first_load_seg();
+ find_first_load_seg(const Target*);
// Count the local symbols in the regular symbol table and the dynamic
// symbol table, and build the respective string pools.
// Create the output sections for the symbol table.
void
create_symtab_sections(const Input_objects*, Symbol_table*,
- unsigned int, off_t*);
+ unsigned int, off_t*, unsigned int);
// Create the .shstrtab section.
Output_section*
create_dynamic_symtab(const Input_objects*, Symbol_table*,
Output_section** pdynstr,
unsigned int* plocal_dynamic_count,
+ unsigned int* pforced_local_dynamic_count,
std::vector<Symbol*>* pdynamic_symbols,
Versions* versions);
// name. Set *PLEN to the length of the name. *PLEN must be
// initialized to the length of NAME.
static const char*
- output_section_name(const char* name, size_t* plen);
+ output_section_name(const Relobj*, const char* name, size_t* plen);
// Return the number of allocated output sections.
size_t
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
Output_section_order order, bool is_relro);
+ // Clear the input section flags that should not be copied to the
+ // output section.
+ elfcpp::Elf_Xword
+ get_output_section_flags (elfcpp::Elf_Xword input_section_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 is_input_section, Output_section_order order,
- bool is_relro);
+ bool is_relro, bool is_reloc, bool match_input_spec);
// Create a new Output_section.
Output_section*
// Attach a section to a segment.
void
- attach_section_to_segment(Output_section*);
+ attach_section_to_segment(const Target*, Output_section*);
// Get section order.
Output_section_order
// Attach an allocated section to a segment.
void
- attach_allocated_section_to_segment(Output_section*);
+ attach_allocated_section_to_segment(const Target*, Output_section*);
+
+ // Make the .eh_frame section.
+ Output_section*
+ make_eh_frame_section(const Relobj*);
// Set the final file offsets of all the segments.
off_t
place_orphan_sections_in_script();
// Return whether SEG1 comes before SEG2 in the output file.
- static bool
+ bool
segment_precedes(const Output_segment* seg1, const Output_segment* seg2);
- // Use to save and restore segments during relaxation.
+ // Use to save and restore segments during relaxation.
typedef Unordered_map<const Output_segment*, const Output_segment*>
Segment_states;
// A comparison class for segments.
- struct Compare_segments
+ class Compare_segments
{
+ public:
+ Compare_segments(Layout* layout)
+ : layout_(layout)
+ { }
+
bool
operator()(const Output_segment* seg1, const Output_segment* seg2)
- { return Layout::segment_precedes(seg1, seg2); }
+ { return this->layout_->segment_precedes(seg1, seg2); }
+
+ private:
+ Layout* layout_;
};
typedef std::vector<Output_section_data*> Output_section_data_list;
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&);
-
+ const Layout::Data_list& special_outputs,
+ const Layout::Data_list& relax_outputs);
+
// 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
std::vector<Section_info> section_infos_;
};
+ // Program properties from .note.gnu.property sections.
+ struct Gnu_property
+ {
+ size_t pr_datasz;
+ unsigned char* pr_data;
+ };
+ typedef std::map<unsigned int, Gnu_property> Gnu_properties;
+
// The number of input files, for sizing tables.
int number_of_input_files_;
// Information set by scripts or by command line options.
// The list of unattached Output_data objects which require special
// handling because they are not Output_sections.
Data_list special_output_list_;
+ // Like special_output_list_, but cleared and recreated on each
+ // iteration of relaxation.
+ Data_list relax_output_list_;
// The section headers.
Output_section_headers* section_headers_;
// A pointer to the PT_TLS segment if there is one.
Output_segment* tls_segment_;
// A pointer to the PT_GNU_RELRO segment if there is one.
Output_segment* relro_segment_;
+ // A pointer to the PT_INTERP segment if there is one.
+ Output_segment* interp_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_;
bool added_eh_frame_data_;
// The exception frame header output section if there is one.
Output_section* eh_frame_hdr_section_;
+ // The data for the .gdb_index section.
+ Gdb_index* gdb_index_data_;
// The space for the build ID checksum if there is one.
Output_section_data* build_id_note_;
// The output section containing dwarf abbreviations
bool resized_signatures_;
// Whether we have created a .stab*str output section.
bool have_stabstr_section_;
+ // True if the input sections in the output sections should be sorted
+ // as specified in a section ordering file.
+ bool section_ordering_specified_;
+ // True if some input sections need to be mapped to a unique segment,
+ // after being mapped to a unique Output_section.
+ bool unique_segment_for_sections_specified_;
// 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_;
+ // Set if this is a slim LTO object not loaded with a compiler plugin
+ bool lto_slim_object_;
// 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_;
+ // Plugins specify section_ordering using this map. This is set in
+ // update_section_order in plugin.cc
+ std::map<Section_id, unsigned int> section_order_map_;
+ // This maps an input section to a unique segment. This is done by first
+ // placing such input sections in unique output sections and then mapping
+ // the output section to a unique segment. Unique_segment_info stores
+ // any additional flags and alignment of the new segment.
+ Section_segment_map section_segment_map_;
// 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.
Incremental_binary* incremental_base_;
// For incremental links, a list of free space within the file.
Free_list free_list_;
+ // Program properties.
+ Gnu_properties gnu_properties_;
};
// This task handles writing out data in output sections which is not
public:
Write_sections_task(const Layout* layout, Output_file* of,
Task_token* output_sections_blocker,
+ Task_token* input_sections_blocker,
Task_token* final_blocker)
: layout_(layout), of_(of),
output_sections_blocker_(output_sections_blocker),
+ input_sections_blocker_(input_sections_blocker),
final_blocker_(final_blocker)
{ }
const Layout* layout_;
Output_file* of_;
Task_token* output_sections_blocker_;
+ Task_token* input_sections_blocker_;
Task_token* final_blocker_;
};
{
public:
Write_symbols_task(const Layout* layout, const Symbol_table* symtab,
- const Input_objects* input_objects,
+ const Input_objects* /*input_objects*/,
const Stringpool* sympool, const Stringpool* dynpool,
Output_file* of, Task_token* final_blocker)
- : layout_(layout), symtab_(symtab), input_objects_(input_objects),
+ : layout_(layout), symtab_(symtab),
sympool_(sympool), dynpool_(dynpool), of_(of),
final_blocker_(final_blocker)
{ }
private:
const Layout* layout_;
const Symbol_table* symtab_;
- const Input_objects* input_objects_;
const Stringpool* sympool_;
const Stringpool* dynpool_;
Output_file* of_;
Task_token* final_blocker_;
};
+// This task function handles computation of the build id.
+// When using --build-id=tree, it schedules the tasks that
+// compute the hashes for each chunk of the file. This task
+// cannot run until we have finalized the size of the output
+// file, after the completion of Write_after_input_sections_task.
+
+class Build_id_task_runner : public Task_function_runner
+{
+ public:
+ Build_id_task_runner(const General_options* options, const Layout* layout,
+ Output_file* of)
+ : options_(options), layout_(layout), of_(of)
+ { }
+
+ // Run the operation.
+ void
+ run(Workqueue*, const Task*);
+
+ private:
+ const General_options* options_;
+ const Layout* layout_;
+ Output_file* of_;
+};
+
// This task function handles closing the file.
class Close_task_runner : public Task_function_runner
{
public:
Close_task_runner(const General_options* options, const Layout* layout,
- Output_file* of)
- : options_(options), layout_(layout), of_(of)
+ Output_file* of, unsigned char* array_of_hashes,
+ size_t size_of_hashes)
+ : options_(options), layout_(layout), of_(of),
+ array_of_hashes_(array_of_hashes), size_of_hashes_(size_of_hashes)
{ }
// Run the operation.
const General_options* options_;
const Layout* layout_;
Output_file* of_;
+ unsigned char* const array_of_hashes_;
+ const size_t size_of_hashes_;
};
// A small helper function to align an address.