+ // Set the output section.
+ void
+ set_output_section(Output_section* os)
+ {
+ gold_assert(!this->is_input_section());
+ Output_section_data* posd =
+ this->is_relaxed_input_section() ? this->u2_.poris : this->u2_.posd;
+ posd->set_output_section(os);
+ }
+
+ // Set the address and file offset. This is called during
+ // Layout::finalize. SECTION_FILE_OFFSET is the file offset of
+ // the enclosing section.
+ void
+ set_address_and_file_offset(uint64_t address, off_t file_offset,
+ off_t section_file_offset);
+
+ // Reset the address and file offset.
+ void
+ reset_address_and_file_offset();
+
+ // Finalize the data size.
+ void
+ finalize_data_size();
+
+ // Add an input section, for SHF_MERGE sections.
+ bool
+ add_input_section(Relobj* object, unsigned int shndx)
+ {
+ gold_assert(this->shndx_ == MERGE_DATA_SECTION_CODE
+ || this->shndx_ == MERGE_STRING_SECTION_CODE);
+ return this->u2_.posd->add_input_section(object, shndx);
+ }
+
+ // Given an input OBJECT, an input section index SHNDX within that
+ // object, and an OFFSET relative to the start of that input
+ // section, return whether or not the output offset is known. If
+ // this function returns true, it sets *POUTPUT to the offset in
+ // the output section, relative to the start of the input section
+ // in the output section. *POUTPUT may be different from OFFSET
+ // for a merged section.
+ bool
+ output_offset(const Relobj* object, unsigned int shndx,
+ section_offset_type offset,
+ section_offset_type* poutput) const;
+
+ // Write out the data. This does nothing for an input section.
+ void
+ write(Output_file*);
+
+ // Write the data to a buffer. This does nothing for an input
+ // section.
+ void
+ write_to_buffer(unsigned char*);
+
+ // Print to a map file.
+ void
+ print_to_mapfile(Mapfile*) const;
+
+ // Print statistics about merge sections to stderr.
+ void
+ print_merge_stats(const char* section_name)
+ {
+ if (this->shndx_ == MERGE_DATA_SECTION_CODE
+ || this->shndx_ == MERGE_STRING_SECTION_CODE)
+ this->u2_.posd->print_merge_stats(section_name);
+ }
+
+ private:
+ // Code values which appear in shndx_. If the value is not one of
+ // these codes, it is the input section index in the object file.
+ enum
+ {
+ // An Output_section_data.
+ OUTPUT_SECTION_CODE = -1U,
+ // An Output_section_data for an SHF_MERGE section with
+ // SHF_STRINGS not set.
+ MERGE_DATA_SECTION_CODE = -2U,
+ // An Output_section_data for an SHF_MERGE section with
+ // SHF_STRINGS set.
+ MERGE_STRING_SECTION_CODE = -3U,
+ // An Output_section_data for a relaxed input section.
+ RELAXED_INPUT_SECTION_CODE = -4U
+ };
+
+ // For an ordinary input section, this is the section index in the
+ // input file. For an Output_section_data, this is
+ // OUTPUT_SECTION_CODE or MERGE_DATA_SECTION_CODE or
+ // MERGE_STRING_SECTION_CODE.
+ unsigned int shndx_;
+ // The required alignment, stored as a power of 2.
+ unsigned int p2align_;
+ union
+ {
+ // For an ordinary input section, the section size.
+ off_t data_size;
+ // For OUTPUT_SECTION_CODE or RELAXED_INPUT_SECTION_CODE, this is not
+ // used. For MERGE_DATA_SECTION_CODE or MERGE_STRING_SECTION_CODE, the
+ // entity size.
+ uint64_t entsize;
+ } u1_;
+ union
+ {
+ // For an ordinary input section, the object which holds the
+ // input section.
+ Relobj* object;
+ // For OUTPUT_SECTION_CODE or MERGE_DATA_SECTION_CODE or
+ // MERGE_STRING_SECTION_CODE, the data.
+ Output_section_data* posd;
+ Output_merge_base* pomb;
+ // For RELAXED_INPUT_SECTION_CODE, the data.
+ Output_relaxed_input_section* poris;
+ } u2_;
+ // The line number of the pattern it matches in the --section-ordering-file
+ // file. It is 0 if does not match any pattern.
+ unsigned int section_order_index_;
+ };
+
+ // Store the list of input sections for this Output_section into the
+ // list passed in. This removes the input sections, leaving only
+ // any Output_section_data elements. This returns the size of those
+ // Output_section_data elements. ADDRESS is the address of this
+ // output section. FILL is the fill value to use, in case there are
+ // any spaces between the remaining Output_section_data elements.
+ uint64_t
+ get_input_sections(uint64_t address, const std::string& fill,
+ std::list<Input_section>*);
+
+ // Add a script input section. A script input section can either be
+ // a plain input section or a sub-class of Output_section_data.
+ void
+ add_script_input_section(const Input_section& input_section);
+
+ // Set the current size of the output section.
+ void
+ set_current_data_size(off_t size)
+ { this->set_current_data_size_for_child(size); }
+
+ // End of linker script support.
+
+ // Save states before doing section layout.
+ // This is used for relaxation.
+ void
+ save_states();
+
+ // Restore states prior to section layout.
+ void
+ restore_states();
+
+ // Discard states.
+ void
+ discard_states();
+
+ // Convert existing input sections to relaxed input sections.
+ void
+ convert_input_sections_to_relaxed_sections(
+ const std::vector<Output_relaxed_input_section*>& sections);
+
+ // Find a relaxed input section to an input section in OBJECT
+ // with index SHNDX. Return NULL if none is found.
+ const Output_relaxed_input_section*
+ find_relaxed_input_section(const Relobj* object, unsigned int shndx) const;
+
+ // Whether section offsets need adjustment due to relaxation.
+ bool
+ section_offsets_need_adjustment() const
+ { return this->section_offsets_need_adjustment_; }
+
+ // Set section_offsets_need_adjustment to be true.
+ void
+ set_section_offsets_need_adjustment()
+ { this->section_offsets_need_adjustment_ = true; }
+
+ // Set section_offsets_need_adjustment to be false.
+ void
+ clear_section_offsets_need_adjustment()
+ { this->section_offsets_need_adjustment_ = false; }
+
+ // Adjust section offsets of input sections in this. This is
+ // requires if relaxation caused some input sections to change sizes.
+ void
+ adjust_section_offsets();
+
+ // Whether this is a NOLOAD section.
+ bool
+ is_noload() const
+ { return this->is_noload_; }
+
+ // Set NOLOAD flag.
+ void
+ set_is_noload()
+ { this->is_noload_ = true; }
+
+ // Print merge statistics to stderr.
+ void
+ print_merge_stats();
+
+ // Set a fixed layout for the section. Used for incremental update links.
+ void
+ set_fixed_layout(uint64_t sh_addr, off_t sh_offset, off_t sh_size,
+ uint64_t sh_addralign);
+
+ // Return TRUE if the section has a fixed layout.
+ bool
+ has_fixed_layout() const
+ { return this->has_fixed_layout_; }
+
+ // Set flag to allow patch space for this section. Used for full
+ // incremental links.
+ void
+ set_is_patch_space_allowed()
+ { this->is_patch_space_allowed_ = true; }
+
+ // Set a fill method to use for free space left in the output section
+ // during incremental links.
+ void
+ set_free_space_fill(Output_fill* free_space_fill)
+ {
+ this->free_space_fill_ = free_space_fill;
+ this->free_list_.set_min_hole_size(free_space_fill->minimum_hole_size());
+ }
+
+ // Reserve space within the fixed layout for the section. Used for
+ // incremental update links.
+ void
+ reserve(uint64_t sh_offset, uint64_t sh_size);
+
+ // Allocate space from the free list for the section. Used for
+ // incremental update links.
+ off_t
+ allocate(off_t len, uint64_t addralign);
+
+ typedef std::vector<Input_section> Input_section_list;
+
+ // Allow access to the input sections.
+ const Input_section_list&
+ input_sections() const
+ { return this->input_sections_; }
+
+ Input_section_list&
+ input_sections()
+ { return this->input_sections_; }
+
+ protected:
+ // Return the output section--i.e., the object itself.
+ Output_section*
+ do_output_section()
+ { return this; }
+
+ const Output_section*
+ do_output_section() const
+ { return this; }
+
+ // Return the section index in the output file.
+ unsigned int
+ do_out_shndx() const
+ {
+ gold_assert(this->out_shndx_ != -1U);
+ return this->out_shndx_;
+ }
+
+ // Set the output section index.
+ void
+ do_set_out_shndx(unsigned int shndx)
+ {
+ gold_assert(this->out_shndx_ == -1U || this->out_shndx_ == shndx);
+ this->out_shndx_ = shndx;
+ }
+
+ // Update the data size of the Output_section. For a typical
+ // Output_section, there is nothing to do, but if there are any
+ // Output_section_data objects we need to do a trial layout
+ // here.
+ virtual void
+ update_data_size();
+
+ // Set the final data size of the Output_section. For a typical
+ // Output_section, there is nothing to do, but if there are any
+ // Output_section_data objects we need to set their final addresses
+ // here.
+ virtual void
+ set_final_data_size();
+
+ // Reset the address and file offset.
+ void
+ do_reset_address_and_file_offset();
+
+ // Return true if address and file offset already have reset values. In
+ // other words, calling reset_address_and_file_offset will not change them.
+ bool
+ do_address_and_file_offset_have_reset_values() const;