// layout.h -- lay out output file sections for gold -*- C++ -*-
-// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
class General_options;
class Incremental_inputs;
+class Incremental_binary;
class Input_objects;
class Mapfile;
class Symbol_table;
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:
+ 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),
+ 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:
+ 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_;
+
+ // 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;
+ // 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.
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);
+ bool
+ is_section_ordering_specified()
+ { return this->section_ordering_specified_; }
+
+ void
+ set_section_ordering_specified()
+ { this->section_ordering_specified_ = true; }
+
+ // 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&);
+ // Read the sequence of input sections from the file specified with
+ // linker option --section-ordering-file.
void
read_layout_from_file();
// 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,
unsigned int reloc_shndx, unsigned int reloc_type,
off_t* offset);
+ // 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);
+
// 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
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*
|| strncmp(name, ".stab", sizeof(".stab") - 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
return this->symtab_section_;
}
+ // Return the file offset of the normal symbol table.
+ 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
// 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
// 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
void
attach_allocated_section_to_segment(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
set_segment_offsets(const Target*, Output_segment*, unsigned int* pshndx);
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.
// 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;
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 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_;
// In incremental build, holds information check the inputs and build the
// .gnu_incremental_inputs section.
Incremental_inputs* incremental_inputs_;
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