// output.h -- manage the output file for gold -*- C++ -*-
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright (C) 2006-2015 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
class Output_file_header : public Output_data
{
public:
- Output_file_header(const Target*,
+ Output_file_header(Target*,
const Symbol_table*,
const Output_segment_headers*);
off_t
do_size() const;
- const Target* target_;
+ Target* target_;
const Symbol_table* symtab_;
const Output_segment_headers* segment_header_;
const Output_section_headers* section_header_;
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.
address, true, true, false, false));
}
+ void
+ add_local_relative(Sized_relobj<size, big_endian>* relobj,
+ unsigned int local_sym_index, unsigned int type,
+ Output_data* od, unsigned int shndx, Address address,
+ bool use_plt_offset)
+ {
+ this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
+ address, true, true, false,
+ use_plt_offset));
+ }
+
// Add a local relocation which does not use a symbol for the relocation,
// but which gets its addend from a symbol.
// entry from the start of the GOT.
unsigned int
add_constant(Valtype constant)
- {
- unsigned int got_offset = this->add_got_entry(Got_entry(constant));
- return got_offset;
- }
+ { return this->add_got_entry(Got_entry(constant)); }
+
+ // Add a pair of constants to the GOT. This returns the offset of
+ // the new entry from the start of the GOT.
+ unsigned int
+ add_constant_pair(Valtype c1, Valtype c2)
+ { return this->add_got_entry_pair(Got_entry(c1), Got_entry(c2)); }
// Replace GOT entry I with a new constant.
void
add_string(elfcpp::DT tag, const std::string& str)
{ this->add_string(tag, str.c_str()); }
+ // Add a new dynamic entry with custom value.
+ void
+ add_custom(elfcpp::DT tag)
+ { this->add_entry(Dynamic_entry(tag)); }
+
protected:
// Adjust the output section to set the entry size.
void
: tag_(tag), offset_(DYNAMIC_STRING)
{ this->u_.str = str; }
+ // Create an entry with a custom value.
+ Dynamic_entry(elfcpp::DT tag)
+ : tag_(tag), offset_(DYNAMIC_CUSTOM)
+ { }
+
// Return the tag of this entry.
elfcpp::DT
tag() const
// Symbol adress.
DYNAMIC_SYMBOL = -3U,
// String.
- DYNAMIC_STRING = -4U
+ DYNAMIC_STRING = -4U,
+ // Custom value.
+ DYNAMIC_CUSTOM = -5U
// Any other value indicates a section address plus OFFSET.
};
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
}
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_;
};
this->dynsym_index_ = index;
}
+ // Sort the attached input sections.
+ void
+ sort_attached_input_sections();
+
// Return whether the input sections sections attachd to this output
// section may require sorting. This is used to handle constructor
// priorities compatibly with GNU ld.
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*);
const Input_section_sort_entry&) const;
};
+ // This is the sort comparison function for .text to sort sections with
+ // prefixes .text.{unlikely,exit,startup,hot} before other sections.
+ struct Input_section_sort_section_prefix_special_ordering_compare
+ {
+ bool
+ operator()(const Input_section_sort_entry&,
+ const Input_section_sort_entry&) const;
+ };
+
+ // This is the sort comparison function for sorting sections by name.
+ struct Input_section_sort_section_name_compare
+ {
+ bool
+ operator()(const Input_section_sort_entry&,
+ const Input_section_sort_entry&) const;
+ };
+
// Fill data. This is used to fill in data between input sections.
// It is also used for data statements (BYTE, WORD, etc.) in linker
// scripts. When we have to keep track of the input sections, we
add_output_merge_section(Output_section_data* posd, bool is_string,
uint64_t entsize);
- // Sort the attached input sections.
- void
- sort_attached_input_sections();
-
// 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.
// address of the immediately following segment. Update *POFF and
// *PSHNDX. This should only be called for a PT_LOAD segment.
uint64_t
- set_section_addresses(Layout*, bool reset, uint64_t addr,
+ set_section_addresses(const Target*, Layout*, bool reset, uint64_t addr,
unsigned int* increase_relro, bool* has_relro,
off_t* poff, unsigned int* pshndx);