+ size_t
+ operator()(const Merge_section_properties& msp) const
+ { return msp.hash_value(); }
+ };
+
+ private:
+ // Whether this merge data section is for strings.
+ bool is_string_;
+ // Entsize of this merge data section.
+ uint64_t entsize_;
+ // Address alignment.
+ uint64_t addralign_;
+};
+
+// This class is used to speed up look up of special input sections in an
+// Output_section.
+
+class Output_section_lookup_maps
+{
+ public:
+ Output_section_lookup_maps()
+ : is_valid_(true), merge_sections_by_properties_(),
+ relaxed_input_sections_by_id_()
+ { }
+
+ // Whether the maps are valid.
+ bool
+ is_valid() const
+ { return this->is_valid_; }
+
+ // Invalidate the maps.
+ void
+ invalidate()
+ { this->is_valid_ = false; }
+
+ // Clear the maps.
+ void
+ clear()
+ {
+ this->merge_sections_by_properties_.clear();
+ this->relaxed_input_sections_by_id_.clear();
+ // A cleared map is valid.
+ this->is_valid_ = true;
+ }
+
+ // Find a merge section by merge section properties. Return NULL if none
+ // is found.
+ Output_merge_base*
+ find_merge_section(const Merge_section_properties& msp) const
+ {
+ gold_assert(this->is_valid_);
+ Merge_sections_by_properties::const_iterator p =
+ this->merge_sections_by_properties_.find(msp);
+ return p != this->merge_sections_by_properties_.end() ? p->second : NULL;
+ }
+
+ // Add a merge section pointed by POMB with properties MSP.
+ void
+ add_merge_section(const Merge_section_properties& msp,
+ Output_merge_base* pomb)
+ {
+ std::pair<Merge_section_properties, Output_merge_base*> value(msp, pomb);
+ std::pair<Merge_sections_by_properties::iterator, bool> result =
+ this->merge_sections_by_properties_.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 Relobj* object, unsigned int shndx) const
+ {
+ gold_assert(this->is_valid_);
+ Relaxed_input_sections_by_id::const_iterator p =
+ this->relaxed_input_sections_by_id_.find(Const_section_id(object, shndx));
+ return p != this->relaxed_input_sections_by_id_.end() ? p->second : NULL;
+ }
+
+ // Add a relaxed input section pointed by POMB and whose original input
+ // section is in OBJECT with index SHNDX.
+ void
+ add_relaxed_input_section(const Relobj* relobj, unsigned int shndx,
+ Output_relaxed_input_section* poris)
+ {
+ Const_section_id csid(relobj, shndx);
+ std::pair<Const_section_id, Output_relaxed_input_section*>
+ value(csid, poris);
+ std::pair<Relaxed_input_sections_by_id::iterator, bool> result =
+ this->relaxed_input_sections_by_id_.insert(value);
+ gold_assert(result.second);
+ }
+
+ private:
+ typedef Unordered_map<Merge_section_properties, Output_merge_base*,
+ Merge_section_properties::hash,
+ Merge_section_properties::equal_to>
+ Merge_sections_by_properties;
+
+ typedef Unordered_map<Const_section_id, Output_relaxed_input_section*,
+ Const_section_id_hash>
+ Relaxed_input_sections_by_id;
+
+ // Whether this is valid
+ bool is_valid_;
+ // Merge sections by merge section properties.
+ Merge_sections_by_properties merge_sections_by_properties_;
+ // Relaxed sections by section IDs.
+ Relaxed_input_sections_by_id relaxed_input_sections_by_id_;
+};
+
+// This abstract base class defines the interface for the
+// types of methods used to fill free space left in an output
+// section during an incremental link. These methods are used
+// to insert dummy compilation units into debug info so that
+// debug info consumers can scan the debug info serially.
+
+class Output_fill
+{
+ public:
+ Output_fill()
+ : is_big_endian_(parameters->target().is_big_endian())
+ { }
+
+ virtual
+ ~Output_fill()
+ { }
+
+ // Return the smallest size chunk of free space that can be
+ // filled with a dummy compilation unit.
+ size_t
+ minimum_hole_size() const
+ { return this->do_minimum_hole_size(); }
+
+ // Write a fill pattern of length LEN at offset OFF in the file.
+ void
+ write(Output_file* of, off_t off, size_t len) const
+ { this->do_write(of, off, len); }
+
+ protected:
+ virtual size_t
+ do_minimum_hole_size() const = 0;
+
+ virtual void
+ do_write(Output_file* of, off_t off, size_t len) const = 0;
+
+ bool
+ is_big_endian() const
+ { return this->is_big_endian_; }
+
+ private:
+ bool is_big_endian_;
+};
+
+// Fill method that introduces a dummy compilation unit in
+// a .debug_info or .debug_types section.
+
+class Output_fill_debug_info : public Output_fill
+{
+ public:
+ Output_fill_debug_info(bool is_debug_types)
+ : is_debug_types_(is_debug_types)
+ { }
+
+ protected:
+ virtual size_t
+ do_minimum_hole_size() const;
+
+ virtual void
+ do_write(Output_file* of, off_t off, size_t len) const;
+
+ private:
+ // Version of the header.
+ static const int version = 4;
+ // True if this is a .debug_types section.
+ bool is_debug_types_;
+};
+
+// Fill method that introduces a dummy compilation unit in
+// a .debug_line section.
+
+class Output_fill_debug_line : public Output_fill
+{
+ public:
+ Output_fill_debug_line()
+ { }
+
+ protected:
+ virtual size_t
+ do_minimum_hole_size() const;
+
+ virtual void
+ do_write(Output_file* of, off_t off, size_t len) const;
+
+ private:
+ // Version of the header. We write a DWARF-3 header because it's smaller
+ // and many tools have not yet been updated to understand the DWARF-4 header.
+ static const int version = 3;
+ // Length of the portion of the header that follows the header_length
+ // field. This includes the following fields:
+ // minimum_instruction_length, default_is_stmt, line_base, line_range,
+ // opcode_base, standard_opcode_lengths[], include_directories, filenames.
+ // The standard_opcode_lengths array is 12 bytes long, and the
+ // include_directories and filenames fields each contain only a single
+ // null byte.
+ static const size_t header_length = 19;
+};
+
+// An output section. We don't expect to have too many output
+// sections, so we don't bother to do a template on the size.
+
+class Output_section : public Output_data
+{
+ public:
+ // Create an output section, giving the name, type, and flags.
+ Output_section(const char* name, elfcpp::Elf_Word, elfcpp::Elf_Xword);
+ virtual ~Output_section();
+
+ // Add a new input section SHNDX, named NAME, with header SHDR, from
+ // object OBJECT. RELOC_SHNDX is the index of a relocation section
+ // which applies to this section, or 0 if none, or -1 if more than
+ // one. HAVE_SECTIONS_SCRIPT is true if we have a SECTIONS clause
+ // in a linker script; in that case we need to keep track of input
+ // sections associated with an output section. Return the offset
+ // within the output section.
+ template<int size, bool big_endian>
+ off_t
+ add_input_section(Layout* 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, bool have_sections_script);
+
+ // Add generated data POSD to this output section.
+ void
+ add_output_section_data(Output_section_data* posd);
+
+ // Add a relaxed input section PORIS called NAME to this output section
+ // with LAYOUT.
+ void
+ add_relaxed_input_section(Layout* layout,
+ Output_relaxed_input_section* poris,
+ const std::string& name);
+
+ // Return the section name.
+ const char*
+ name() const
+ { return this->name_; }
+
+ // Return the section type.
+ elfcpp::Elf_Word
+ type() const
+ { return this->type_; }
+
+ // Return the section flags.
+ elfcpp::Elf_Xword
+ flags() const
+ { return this->flags_; }
+
+ typedef std::map<Section_id, unsigned int> Section_layout_order;
+
+ void
+ update_section_layout(const Section_layout_order* order_map);
+
+ // Update the output section flags based on input section flags.
+ void
+ update_flags_for_input_section(elfcpp::Elf_Xword flags);
+
+ // Set the output section flags.
+ void
+ set_flags(elfcpp::Elf_Xword flags)
+ { this->flags_ = flags; }
+
+ // Return the entsize field.
+ uint64_t
+ entsize() const
+ { return this->entsize_; }
+
+ // Set the entsize field.
+ void
+ set_entsize(uint64_t v);
+
+ // Set the load address.
+ void
+ set_load_address(uint64_t load_address)
+ {
+ this->load_address_ = load_address;
+ this->has_load_address_ = true;
+ }
+
+ // Set the link field to the output section index of a section.
+ void
+ set_link_section(const Output_data* od)
+ {
+ gold_assert(this->link_ == 0
+ && !this->should_link_to_symtab_
+ && !this->should_link_to_dynsym_);
+ this->link_section_ = od;
+ }
+
+ // Set the link field to a constant.
+ void
+ set_link(unsigned int v)
+ {
+ gold_assert(this->link_section_ == NULL
+ && !this->should_link_to_symtab_
+ && !this->should_link_to_dynsym_);
+ this->link_ = v;
+ }
+
+ // Record that this section should link to the normal symbol table.
+ void
+ set_should_link_to_symtab()
+ {
+ gold_assert(this->link_section_ == NULL
+ && this->link_ == 0
+ && !this->should_link_to_dynsym_);
+ this->should_link_to_symtab_ = true;
+ }