X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gold%2Foutput.h;h=77b6697e06724d34f0371b3530c0c894d2e64fb4;hb=9a6c68caa9543e09b064b7ac7c2b658f277bc19c;hp=9b0f87f47c51fdf62698f34ecd43444902c61e32;hpb=cf43a2fe99107aae4bfdf9bae8380729fb2c7b64;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/output.h b/gold/output.h index 9b0f87f47c..77b6697e06 100644 --- a/gold/output.h +++ b/gold/output.h @@ -1,6 +1,6 @@ // output.h -- manage the output file for gold -*- C++ -*- -// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. +// Copyright (C) 2006-2020 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -23,6 +23,7 @@ #ifndef GOLD_OUTPUT_H #define GOLD_OUTPUT_H +#include #include #include @@ -37,7 +38,6 @@ namespace gold class General_options; class Object; class Symbol; -class Output_file; class Output_merge_base; class Output_section; class Relocatable_relocs; @@ -49,6 +49,131 @@ class Sized_relobj; template class Sized_relobj_file; +// This class represents the output file. + +class Output_file +{ + public: + Output_file(const char* name); + + // Indicate that this is a temporary file which should not be + // output. + void + set_is_temporary() + { this->is_temporary_ = true; } + + // Try to open an existing file. Returns false if the file doesn't + // exist, has a size of 0 or can't be mmaped. This method is + // thread-unsafe. If BASE_NAME is not NULL, use the contents of + // that file as the base for incremental linking. + bool + open_base_file(const char* base_name, bool writable); + + // Open the output file. FILE_SIZE is the final size of the file. + // If the file already exists, it is deleted/truncated. This method + // is thread-unsafe. + void + open(off_t file_size); + + // Resize the output file. This method is thread-unsafe. + void + resize(off_t file_size); + + // Close the output file (flushing all buffered data) and make sure + // there are no errors. This method is thread-unsafe. + void + close(); + + // Return the size of this file. + off_t + filesize() + { return this->file_size_; } + + // Return the name of this file. + const char* + filename() + { return this->name_; } + + // We currently always use mmap which makes the view handling quite + // simple. In the future we may support other approaches. + + // Write data to the output file. + void + write(off_t offset, const void* data, size_t len) + { memcpy(this->base_ + offset, data, len); } + + // Get a buffer to use to write to the file, given the offset into + // the file and the size. + unsigned char* + get_output_view(off_t start, size_t size) + { + gold_assert(start >= 0 + && start + static_cast(size) <= this->file_size_); + return this->base_ + start; + } + + // VIEW must have been returned by get_output_view. Write the + // buffer to the file, passing in the offset and the size. + void + write_output_view(off_t, size_t, unsigned char*) + { } + + // Get a read/write buffer. This is used when we want to write part + // of the file, read it in, and write it again. + unsigned char* + get_input_output_view(off_t start, size_t size) + { return this->get_output_view(start, size); } + + // Write a read/write buffer back to the file. + void + write_input_output_view(off_t, size_t, unsigned char*) + { } + + // Get a read buffer. This is used when we just want to read part + // of the file back it in. + const unsigned char* + get_input_view(off_t start, size_t size) + { return this->get_output_view(start, size); } + + // Release a read bfufer. + void + free_input_view(off_t, size_t, const unsigned char*) + { } + + private: + // Map the file into memory or, if that fails, allocate anonymous + // memory. + void + map(); + + // Allocate anonymous memory for the file. + bool + map_anonymous(); + + // Map the file into memory. + bool + map_no_anonymous(bool); + + // Unmap the file from memory (and flush to disk buffers). + void + unmap(); + + // File name. + const char* name_; + // File descriptor. + int o_; + // File size. + off_t file_size_; + // Base of file mapped into memory. + unsigned char* base_; + // True iff base_ points to a memory buffer rather than an output file. + bool map_is_anonymous_; + // True if base_ was allocated using new rather than mmap. + bool map_is_allocated_; + // True if this is a temporary file which should not be output. + bool is_temporary_; +}; + // An abtract class for data which has to go into the output file. class Output_data @@ -92,7 +217,7 @@ class Output_data bool is_data_size_fixed() const { return this->is_data_size_fixed_; } - + // Return the file offset. This is only valid after // Layout::finalize is finished. For some non-allocated sections, // it may not be valid until near the end of the link. @@ -103,8 +228,8 @@ class Output_data return this->offset_; } - // Reset the address and file offset. This essentially disables the - // sanity testing about duplicate and unknown settings. + // Reset the address, file offset and data size. This essentially + // disables the sanity testing about duplicate and unknown settings. void reset_address_and_file_offset() { @@ -115,6 +240,14 @@ class Output_data this->do_reset_address_and_file_offset(); } + // As above, but just for data size. + void + reset_data_size() + { + if (!this->is_data_size_fixed_) + this->is_data_size_valid_ = false; + } + // 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 @@ -406,7 +539,7 @@ class Output_data } // Fix the data size. Once it is fixed, it cannot be changed - // and the data size remains always valid. + // and the data size remains always valid. void fix_data_size() { @@ -564,7 +697,7 @@ class Output_segment_headers : public Output_data class Output_file_header : public Output_data { public: - Output_file_header(const Target*, + Output_file_header(Target*, const Symbol_table*, const Output_segment_headers*); @@ -608,7 +741,7 @@ class Output_file_header : public Output_data 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_; @@ -667,13 +800,6 @@ class Output_section_data : public Output_data 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 @@ -707,11 +833,6 @@ class Output_section_data : public Output_data 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. @@ -1025,7 +1146,7 @@ class Output_reloc bool use_plt_offset); Output_reloc(Symbol* gsym, unsigned int type, - Sized_relobj* relobj, + Sized_relobj* relobj, unsigned int shndx, Address address, bool is_relative, bool is_symbolless, bool use_plt_offset); @@ -1034,30 +1155,31 @@ class Output_reloc Output_reloc(Sized_relobj* relobj, unsigned int local_sym_index, unsigned int type, Output_data* od, Address address, bool is_relative, - bool is_symbolless, bool is_section_symbol, - bool use_plt_offset); + bool is_symbolless, bool is_section_symbol, + bool use_plt_offset); Output_reloc(Sized_relobj* relobj, unsigned int local_sym_index, unsigned int type, unsigned int shndx, Address address, bool is_relative, - bool is_symbolless, bool is_section_symbol, - bool use_plt_offset); + bool is_symbolless, bool is_section_symbol, + bool use_plt_offset); // A reloc against the STT_SECTION symbol of an output section. Output_reloc(Output_section* os, unsigned int type, Output_data* od, - Address address); + Address address, bool is_relative); Output_reloc(Output_section* os, unsigned int type, - Sized_relobj* relobj, - unsigned int shndx, Address address); + Sized_relobj* relobj, unsigned int shndx, + Address address, bool is_relative); - // An absolute relocation with no symbol. + // An absolute or relative relocation with no symbol. - Output_reloc(unsigned int type, Output_data* od, Address address); + Output_reloc(unsigned int type, Output_data* od, Address address, + bool is_relative); Output_reloc(unsigned int type, Sized_relobj* relobj, - unsigned int shndx, Address address); + unsigned int shndx, Address address, bool is_relative); // A target specific relocation. The target will be called to get // the symbol index, passing ARG. The type and offset will be set @@ -1091,10 +1213,10 @@ class Output_reloc is_local_section_symbol() const { return (this->local_sym_index_ != GSYM_CODE - && this->local_sym_index_ != SECTION_CODE - && this->local_sym_index_ != INVALID_CODE + && this->local_sym_index_ != SECTION_CODE + && this->local_sym_index_ != INVALID_CODE && this->local_sym_index_ != TARGET_CODE - && this->is_section_symbol_); + && this->is_section_symbol_); } // Return whether this is a target specific relocation. @@ -1153,11 +1275,6 @@ class Output_reloc r2) const { return this->compare(r2) < 0; } - private: - // Record that we need a dynamic symbol index. - void - set_needs_dynsym_index(); - // Return the symbol index. unsigned int get_symbol_index() const; @@ -1166,6 +1283,11 @@ class Output_reloc Address get_address() const; + private: + // Record that we need a dynamic symbol index. + void + set_needs_dynsym_index(); + // Codes for local_sym_index_. enum { @@ -1262,7 +1384,7 @@ class Output_reloc { } Output_reloc(Symbol* gsym, unsigned int type, - Sized_relobj* relobj, + Sized_relobj* relobj, unsigned int shndx, Address address, Addend addend, bool is_relative, bool is_symbolless, bool use_plt_offset) : rel_(gsym, type, relobj, shndx, address, is_relative, @@ -1278,7 +1400,7 @@ class Output_reloc bool is_symbolless, bool is_section_symbol, bool use_plt_offset) : rel_(relobj, local_sym_index, type, od, address, is_relative, - is_symbolless, is_section_symbol, use_plt_offset), + is_symbolless, is_section_symbol, use_plt_offset), addend_(addend) { } @@ -1289,33 +1411,35 @@ class Output_reloc bool is_symbolless, bool is_section_symbol, bool use_plt_offset) : rel_(relobj, local_sym_index, type, shndx, address, is_relative, - is_symbolless, is_section_symbol, use_plt_offset), + is_symbolless, is_section_symbol, use_plt_offset), addend_(addend) { } // A reloc against the STT_SECTION symbol of an output section. Output_reloc(Output_section* os, unsigned int type, Output_data* od, - Address address, Addend addend) - : rel_(os, type, od, address), addend_(addend) + Address address, Addend addend, bool is_relative) + : rel_(os, type, od, address, is_relative), addend_(addend) { } Output_reloc(Output_section* os, unsigned int type, - Sized_relobj* relobj, - unsigned int shndx, Address address, Addend addend) - : rel_(os, type, relobj, shndx, address), addend_(addend) + Sized_relobj* relobj, + unsigned int shndx, Address address, Addend addend, + bool is_relative) + : rel_(os, type, relobj, shndx, address, is_relative), addend_(addend) { } - // An absolute relocation with no symbol. + // An absolute or relative relocation with no symbol. Output_reloc(unsigned int type, Output_data* od, Address address, - Addend addend) - : rel_(type, od, address), addend_(addend) + Addend addend, bool is_relative) + : rel_(type, od, address, is_relative), addend_(addend) { } Output_reloc(unsigned int type, Sized_relobj* relobj, - unsigned int shndx, Address address, Addend addend) - : rel_(type, relobj, shndx, address), addend_(addend) + unsigned int shndx, Address address, Addend addend, + bool is_relative) + : rel_(type, relobj, shndx, address, is_relative), addend_(addend) { } // A target specific relocation. The target will be called to get @@ -1488,6 +1612,40 @@ class Output_data_reloc_base : public Output_data_reloc_generic void do_write(Output_file*); + // Generic implementation of do_write, allowing a customized + // class for writing the output relocation (e.g., for MIPS-64). + template + void + do_write_generic(Output_file* of) + { + const off_t off = this->offset(); + const off_t oview_size = this->data_size(); + unsigned char* const oview = of->get_output_view(off, oview_size); + + if (this->sort_relocs()) + { + gold_assert(dynamic); + std::sort(this->relocs_.begin(), this->relocs_.end(), + Sort_relocs_comparison()); + } + + unsigned char* pov = oview; + for (typename Relocs::const_iterator p = this->relocs_.begin(); + p != this->relocs_.end(); + ++p) + { + Output_reloc_writer::write(p, pov); + pov += reloc_size; + } + + gold_assert(pov - oview == oview_size); + + of->write_output_view(off, oview_size, oview); + + // We no longer need the relocation entries. + this->relocs_.clear(); + } + // Set the entry size and the link. void do_adjust_output_section(Output_section* os); @@ -1559,14 +1717,19 @@ class Output_data_reloc void add_global(Symbol* gsym, unsigned int type, Output_data* od, Address address) - { this->add(od, Output_reloc_type(gsym, type, od, address, false, false, false)); } + { + this->add(od, Output_reloc_type(gsym, type, od, address, + false, false, false)); + } void add_global(Symbol* gsym, unsigned int type, Output_data* od, - Sized_relobj* relobj, + Sized_relobj* relobj, unsigned int shndx, Address address) - { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, - false, false, false)); } + { + this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, + false, false, false)); + } void add_global_generic(Symbol* gsym, unsigned int type, Output_data* od, @@ -1596,17 +1759,19 @@ class Output_data_reloc void add_global_relative(Symbol* gsym, unsigned int type, Output_data* od, - Address address) - { this->add(od, Output_reloc_type(gsym, type, od, address, true, true, - false)); } + Address address) + { + this->add(od, Output_reloc_type(gsym, type, od, address, true, true, + false)); + } void add_global_relative(Symbol* gsym, unsigned int type, Output_data* od, - Sized_relobj* relobj, - unsigned int shndx, Address address) + Sized_relobj* relobj, + unsigned int shndx, Address address) { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, - true, true, false)); + true, true, false)); } // Add a global relocation which does not use a symbol for the relocation, @@ -1615,8 +1780,10 @@ class Output_data_reloc void add_symbolless_global_addend(Symbol* gsym, unsigned int type, Output_data* od, Address address) - { this->add(od, Output_reloc_type(gsym, type, od, address, false, true, - false)); } + { + this->add(od, Output_reloc_type(gsym, type, od, address, false, true, + false)); + } void add_symbolless_global_addend(Symbol* gsym, unsigned int type, @@ -1625,7 +1792,7 @@ class Output_data_reloc unsigned int shndx, Address address) { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, - false, true, false)); + false, true, false)); } // Add a reloc against a local symbol. @@ -1636,7 +1803,7 @@ class Output_data_reloc Output_data* od, Address address) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, - address, false, false, false, false)); + address, false, false, false, false)); } void @@ -1678,22 +1845,33 @@ class Output_data_reloc void add_local_relative(Sized_relobj* relobj, - unsigned int local_sym_index, unsigned int type, - Output_data* od, Address address) + unsigned int local_sym_index, unsigned int type, + Output_data* od, Address address) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, - address, true, true, false, false)); + address, true, true, false, false)); } void add_local_relative(Sized_relobj* relobj, - unsigned int local_sym_index, unsigned int type, - Output_data* od, unsigned int shndx, Address address) + unsigned int local_sym_index, unsigned int type, + Output_data* od, unsigned int shndx, Address address) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx, address, true, true, false, false)); } + void + add_local_relative(Sized_relobj* 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. @@ -1703,7 +1881,7 @@ class Output_data_reloc Output_data* od, Address address) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, - address, false, true, false, false)); + address, false, true, false, false)); } void @@ -1722,20 +1900,20 @@ class Output_data_reloc void add_local_section(Sized_relobj* relobj, - unsigned int input_shndx, unsigned int type, - Output_data* od, Address address) + unsigned int input_shndx, unsigned int type, + Output_data* od, Address address) { this->add(od, Output_reloc_type(relobj, input_shndx, type, od, - address, false, false, true, false)); + address, false, false, true, false)); } void add_local_section(Sized_relobj* relobj, - unsigned int input_shndx, unsigned int type, - Output_data* od, unsigned int shndx, Address address) + unsigned int input_shndx, unsigned int type, + Output_data* od, unsigned int shndx, Address address) { this->add(od, Output_reloc_type(relobj, input_shndx, type, shndx, - address, false, false, true, false)); + address, false, false, true, false)); } // A reloc against the STT_SECTION symbol of an output section. @@ -1745,13 +1923,13 @@ class Output_data_reloc void add_output_section(Output_section* os, unsigned int type, Output_data* od, Address address) - { this->add(od, Output_reloc_type(os, type, od, address)); } + { this->add(od, Output_reloc_type(os, type, od, address, false)); } void add_output_section(Output_section* os, unsigned int type, Output_data* od, Sized_relobj* relobj, - unsigned int shndx, Address address) - { this->add(od, Output_reloc_type(os, type, relobj, shndx, address)); } + unsigned int shndx, Address address) + { this->add(od, Output_reloc_type(os, type, relobj, shndx, address, false)); } void add_output_section_generic(Output_section* os, unsigned int type, @@ -1760,7 +1938,8 @@ class Output_data_reloc { gold_assert(addend == 0); this->add(od, Output_reloc_type(os, type, od, - convert_types(address))); + convert_types(address), + false)); } void @@ -1773,20 +1952,47 @@ class Output_data_reloc Sized_relobj* sized_relobj = static_cast*>(relobj); this->add(od, Output_reloc_type(os, type, sized_relobj, shndx, - convert_types(address))); + convert_types(address), + false)); } + // As above, but the reloc TYPE is relative + + void + add_output_section_relative(Output_section* os, unsigned int type, + Output_data* od, Address address) + { this->add(od, Output_reloc_type(os, type, od, address, true)); } + + void + add_output_section_relative(Output_section* os, unsigned int type, + Output_data* od, + Sized_relobj* relobj, + unsigned int shndx, Address address) + { this->add(od, Output_reloc_type(os, type, relobj, shndx, address, true)); } + // Add an absolute relocation. void add_absolute(unsigned int type, Output_data* od, Address address) - { this->add(od, Output_reloc_type(type, od, address)); } + { this->add(od, Output_reloc_type(type, od, address, false)); } void add_absolute(unsigned int type, Output_data* od, Sized_relobj* relobj, unsigned int shndx, Address address) - { this->add(od, Output_reloc_type(type, relobj, shndx, address)); } + { this->add(od, Output_reloc_type(type, relobj, shndx, address, false)); } + + // Add a relative relocation + + void + add_relative(unsigned int type, Output_data* od, Address address) + { this->add(od, Output_reloc_type(type, od, address, true)); } + + void + add_relative(unsigned int type, Output_data* od, + Sized_relobj* relobj, + unsigned int shndx, Address address) + { this->add(od, Output_reloc_type(type, relobj, shndx, address, true)); } // Add a target specific relocation. A target which calls this must // define the reloc_symbol_index and reloc_addend virtual functions. @@ -1827,16 +2033,20 @@ class Output_data_reloc void add_global(Symbol* gsym, unsigned int type, Output_data* od, Address address, Addend addend) - { this->add(od, Output_reloc_type(gsym, type, od, address, addend, - false, false, false)); } + { + this->add(od, Output_reloc_type(gsym, type, od, address, addend, + false, false, false)); + } void add_global(Symbol* gsym, unsigned int type, Output_data* od, - Sized_relobj* relobj, + Sized_relobj* relobj, unsigned int shndx, Address address, Addend addend) - { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, - addend, false, false, false)); } + { + this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, + addend, false, false, false)); + } void add_global_generic(Symbol* gsym, unsigned int type, Output_data* od, @@ -1868,17 +2078,21 @@ class Output_data_reloc void add_global_relative(Symbol* gsym, unsigned int type, Output_data* od, - Address address, Addend addend, bool use_plt_offset) - { this->add(od, Output_reloc_type(gsym, type, od, address, addend, true, - true, use_plt_offset)); } + Address address, Addend addend, bool use_plt_offset) + { + this->add(od, Output_reloc_type(gsym, type, od, address, addend, true, + true, use_plt_offset)); + } void add_global_relative(Symbol* gsym, unsigned int type, Output_data* od, - Sized_relobj* relobj, - unsigned int shndx, Address address, Addend addend, + Sized_relobj* relobj, + unsigned int shndx, Address address, Addend addend, bool use_plt_offset) - { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, - addend, true, true, use_plt_offset)); } + { + this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, + addend, true, true, use_plt_offset)); + } // Add a global relocation which does not use a symbol for the relocation, // but which gets its addend from a symbol. @@ -1886,16 +2100,21 @@ class Output_data_reloc void add_symbolless_global_addend(Symbol* gsym, unsigned int type, Output_data* od, Address address, Addend addend) - { this->add(od, Output_reloc_type(gsym, type, od, address, addend, - false, true, false)); } + { + this->add(od, Output_reloc_type(gsym, type, od, address, addend, + false, true, false)); + } void add_symbolless_global_addend(Symbol* gsym, unsigned int type, Output_data* od, Sized_relobj* relobj, - unsigned int shndx, Address address, Addend addend) - { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, - addend, false, true, false)); } + unsigned int shndx, Address address, + Addend addend) + { + this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, + addend, false, true, false)); + } // Add a reloc against a local symbol. @@ -1915,8 +2134,8 @@ class Output_data_reloc Addend addend) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx, - address, addend, false, false, false, - false)); + address, addend, false, false, false, + false)); } void @@ -1949,9 +2168,9 @@ class Output_data_reloc void add_local_relative(Sized_relobj* relobj, - unsigned int local_sym_index, unsigned int type, - Output_data* od, Address address, Addend addend, - bool use_plt_offset) + unsigned int local_sym_index, unsigned int type, + Output_data* od, Address address, Addend addend, + bool use_plt_offset) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, address, addend, true, true, false, @@ -1960,13 +2179,13 @@ class Output_data_reloc void add_local_relative(Sized_relobj* relobj, - unsigned int local_sym_index, unsigned int type, - Output_data* od, unsigned int shndx, Address address, - Addend addend, bool use_plt_offset) + unsigned int local_sym_index, unsigned int type, + Output_data* od, unsigned int shndx, Address address, + Addend addend, bool use_plt_offset) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx, - address, addend, true, true, false, - use_plt_offset)); + address, addend, true, true, false, + use_plt_offset)); } // Add a local relocation which does not use a symbol for the relocation, @@ -1988,8 +2207,8 @@ class Output_data_reloc Address address, Addend addend) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx, - address, addend, false, true, false, - false)); + address, addend, false, true, false, + false)); } // Add a reloc against a local section symbol. This will be @@ -1998,8 +2217,8 @@ class Output_data_reloc void add_local_section(Sized_relobj* relobj, - unsigned int input_shndx, unsigned int type, - Output_data* od, Address address, Addend addend) + unsigned int input_shndx, unsigned int type, + Output_data* od, Address address, Addend addend) { this->add(od, Output_reloc_type(relobj, input_shndx, type, od, address, addend, false, false, true, false)); @@ -2012,8 +2231,8 @@ class Output_data_reloc Addend addend) { this->add(od, Output_reloc_type(relobj, input_shndx, type, shndx, - address, addend, false, false, true, - false)); + address, addend, false, false, true, + false)); } // A reloc against the STT_SECTION symbol of an output section. @@ -2021,14 +2240,16 @@ class Output_data_reloc void add_output_section(Output_section* os, unsigned int type, Output_data* od, Address address, Addend addend) - { this->add(od, Output_reloc_type(os, type, od, address, addend)); } + { this->add(od, Output_reloc_type(os, type, od, address, addend, false)); } void add_output_section(Output_section* os, unsigned int type, Output_data* od, - Sized_relobj* relobj, + Sized_relobj* relobj, unsigned int shndx, Address address, Addend addend) - { this->add(od, Output_reloc_type(os, type, relobj, shndx, address, - addend)); } + { + this->add(od, Output_reloc_type(os, type, relobj, shndx, address, + addend, false)); + } void add_output_section_generic(Output_section* os, unsigned int type, @@ -2037,7 +2258,8 @@ class Output_data_reloc { this->add(od, Output_reloc_type(os, type, od, convert_types(address), - convert_types(addend))); + convert_types(addend), + false)); } void @@ -2050,7 +2272,26 @@ class Output_data_reloc static_cast*>(relobj); this->add(od, Output_reloc_type(os, type, sized_relobj, shndx, convert_types(address), - convert_types(addend))); + convert_types(addend), + false)); + } + + // As above, but the reloc TYPE is relative + + void + add_output_section_relative(Output_section* os, unsigned int type, + Output_data* od, Address address, Addend addend) + { this->add(od, Output_reloc_type(os, type, od, address, addend, true)); } + + void + add_output_section_relative(Output_section* os, unsigned int type, + Output_data* od, + Sized_relobj* relobj, + unsigned int shndx, Address address, + Addend addend) + { + this->add(od, Output_reloc_type(os, type, relobj, shndx, + address, addend, true)); } // Add an absolute relocation. @@ -2058,13 +2299,32 @@ class Output_data_reloc void add_absolute(unsigned int type, Output_data* od, Address address, Addend addend) - { this->add(od, Output_reloc_type(type, od, address, addend)); } + { this->add(od, Output_reloc_type(type, od, address, addend, false)); } void add_absolute(unsigned int type, Output_data* od, Sized_relobj* relobj, unsigned int shndx, Address address, Addend addend) - { this->add(od, Output_reloc_type(type, relobj, shndx, address, addend)); } + { + this->add(od, Output_reloc_type(type, relobj, shndx, address, addend, + false)); + } + + // Add a relative relocation + + void + add_relative(unsigned int type, Output_data* od, Address address, + Addend addend) + { this->add(od, Output_reloc_type(type, od, address, addend, true)); } + + void + add_relative(unsigned int type, Output_data* od, + Sized_relobj* relobj, + unsigned int shndx, Address address, Addend addend) + { + this->add(od, Output_reloc_type(type, relobj, shndx, address, addend, + true)); + } // Add a target specific relocation. A target which calls this must // define the reloc_symbol_index and reloc_addend virtual functions. @@ -2086,7 +2346,7 @@ class Output_data_reloc // Output_relocatable_relocs represents a relocation section in a // relocatable link. The actual data is written out in the target -// hook relocate_for_relocatable. This just saves space for it. +// hook relocate_relocs. This just saves space for it. template class Output_relocatable_relocs : public Output_section_data @@ -2209,30 +2469,49 @@ class Output_data_got : public Output_data_got_base bool add_global_plt(Symbol* gsym, unsigned int got_type); + // Like add_global, but for a TLS symbol where the value will be + // offset using Target::tls_offset_for_global. + bool + add_global_tls(Symbol* gsym, unsigned int got_type) + { return add_global_plt(gsym, got_type); } + // Add an entry for a global symbol to the GOT, and add a dynamic // relocation of type R_TYPE for the GOT entry. void add_global_with_rel(Symbol* gsym, unsigned int got_type, - Output_data_reloc_generic* rel_dyn, unsigned int r_type); + Output_data_reloc_generic* rel_dyn, unsigned int r_type); // Add a pair of entries for a global symbol to the GOT, and add // dynamic relocations of type R_TYPE_1 and R_TYPE_2, respectively. void add_global_pair_with_rel(Symbol* gsym, unsigned int got_type, - Output_data_reloc_generic* rel_dyn, + Output_data_reloc_generic* rel_dyn, unsigned int r_type_1, unsigned int r_type_2); // Add an entry for a local symbol to the GOT. This returns true if // this is a new GOT entry, false if the symbol already has a GOT // entry. bool - add_local(Relobj* object, unsigned int sym_index, unsigned int got_type); + add_local(Relobj* object, unsigned int sym_index, unsigned int got_type); + + // Add an entry for a local symbol plus ADDEND to the GOT. This returns + // true if this is a new GOT entry, false if the symbol already has a GOT + // entry. + bool + add_local(Relobj* object, unsigned int sym_index, unsigned int got_type, + uint64_t addend); // Like add_local, but use the PLT offset of the local symbol if it // has one. bool add_local_plt(Relobj* object, unsigned int sym_index, unsigned int got_type); + // Like add_local, but for a TLS symbol where the value will be + // offset using Target::tls_offset_for_local. + bool + add_local_tls(Relobj* object, unsigned int sym_index, unsigned int got_type) + { return add_local_plt(object, sym_index, got_type); } + // Add an entry for a local symbol to the GOT, and add a dynamic // relocation of type R_TYPE for the GOT entry. void @@ -2240,22 +2519,56 @@ class Output_data_got : public Output_data_got_base unsigned int got_type, Output_data_reloc_generic* rel_dyn, unsigned int r_type); + // Add an entry for a local symbol plus ADDEND to the GOT, and add a dynamic + // relocation of type R_TYPE for the GOT entry. + void + add_local_with_rel(Relobj* object, unsigned int sym_index, + unsigned int got_type, Output_data_reloc_generic* rel_dyn, + unsigned int r_type, uint64_t addend); + // Add a pair of entries for a local symbol to the GOT, and add - // dynamic relocations of type R_TYPE_1 and R_TYPE_2, respectively. + // a dynamic relocation of type R_TYPE using the section symbol of + // the output section to which input section SHNDX maps, on the first. + // The first got entry will have a value of zero, the second the + // value of the local symbol. + void + add_local_pair_with_rel(Relobj* object, unsigned int sym_index, + unsigned int shndx, unsigned int got_type, + Output_data_reloc_generic* rel_dyn, + unsigned int r_type); + + // Add a pair of entries for a local symbol plus ADDEND to the GOT, and add + // a dynamic relocation of type R_TYPE using the section symbol of + // the output section to which input section SHNDX maps, on the first. + // The first got entry will have a value of zero, the second the + // value of the local symbol. void add_local_pair_with_rel(Relobj* object, unsigned int sym_index, unsigned int shndx, unsigned int got_type, Output_data_reloc_generic* rel_dyn, - unsigned int r_type_1, unsigned int r_type_2); + unsigned int r_type, uint64_t addend); + + // Add a pair of entries for a local symbol to the GOT, and add + // a dynamic relocation of type R_TYPE using STN_UNDEF on the first. + // The first got entry will have a value of zero, the second the + // value of the local symbol offset by Target::tls_offset_for_local. + void + add_local_tls_pair(Relobj* object, unsigned int sym_index, + unsigned int got_type, + Output_data_reloc_generic* rel_dyn, + unsigned int r_type); // Add a constant to the GOT. This returns the offset of the new // 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 @@ -2305,18 +2618,21 @@ class Output_data_got : public Output_data_got_base public: // Create a zero entry. Got_entry() - : local_sym_index_(RESERVED_CODE), use_plt_offset_(false) + : local_sym_index_(RESERVED_CODE), use_plt_or_tls_offset_(false), + addend_(0) { this->u_.constant = 0; } // Create a global symbol entry. - Got_entry(Symbol* gsym, bool use_plt_offset) - : local_sym_index_(GSYM_CODE), use_plt_offset_(use_plt_offset) + Got_entry(Symbol* gsym, bool use_plt_or_tls_offset) + : local_sym_index_(GSYM_CODE), + use_plt_or_tls_offset_(use_plt_or_tls_offset), addend_(0) { this->u_.gsym = gsym; } // Create a local symbol entry. Got_entry(Relobj* object, unsigned int local_sym_index, - bool use_plt_offset) - : local_sym_index_(local_sym_index), use_plt_offset_(use_plt_offset) + bool use_plt_or_tls_offset) + : local_sym_index_(local_sym_index), + use_plt_or_tls_offset_(use_plt_or_tls_offset), addend_(0) { gold_assert(local_sym_index != GSYM_CODE && local_sym_index != CONSTANT_CODE @@ -2325,15 +2641,28 @@ class Output_data_got : public Output_data_got_base this->u_.object = object; } + // Create a local symbol entry plus addend. + Got_entry(Relobj* object, unsigned int local_sym_index, + bool use_plt_or_tls_offset, uint64_t addend) + : local_sym_index_(local_sym_index), + use_plt_or_tls_offset_(use_plt_or_tls_offset), addend_(addend) + { + gold_assert(local_sym_index != GSYM_CODE + && local_sym_index != CONSTANT_CODE + && local_sym_index != RESERVED_CODE + && local_sym_index == this->local_sym_index_); + this->u_.object = object; + } + // Create a constant entry. The constant is a host value--it will // be swapped, if necessary, when it is written out. explicit Got_entry(Valtype constant) - : local_sym_index_(CONSTANT_CODE), use_plt_offset_(false) + : local_sym_index_(CONSTANT_CODE), use_plt_or_tls_offset_(false) { this->u_.constant = constant; } // Write the GOT entry to an output view. void - write(unsigned char* pov) const; + write(unsigned int got_indx, unsigned char* pov) const; private: enum @@ -2356,7 +2685,10 @@ class Output_data_got : public Output_data_got_base // for a global symbol, or CONSTANT_CODE for a constant. unsigned int local_sym_index_ : 31; // Whether to use the PLT offset of the symbol if it has one. - bool use_plt_offset_ : 1; + // For TLS symbols, whether to offset the symbol value. + bool use_plt_or_tls_offset_ : 1; + // The addend. + uint64_t addend_; }; typedef std::vector Got_entries; @@ -2416,7 +2748,7 @@ class Output_data_dynamic : public Output_section_data // plus a constant offset. void add_section_plus_offset(elfcpp::DT tag, const Output_data* od, - unsigned int offset) + unsigned int offset) { this->add_entry(Dynamic_entry(tag, od, offset)); } // Add a new dynamic entry with the size of output data. @@ -2444,6 +2776,15 @@ class Output_data_dynamic : public Output_section_data 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)); } + + // Get a dynamic entry offset. + unsigned int + get_entry_offset(elfcpp::DT tag) const; + protected: // Adjust the output section to set the entry size. void @@ -2508,6 +2849,11 @@ class Output_data_dynamic : public Output_section_data : 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 @@ -2528,10 +2874,12 @@ class Output_data_dynamic : public Output_section_data DYNAMIC_NUMBER = -1U, // Section size. DYNAMIC_SECTION_SIZE = -2U, - // Symbol adress. + // Symbol address. DYNAMIC_SYMBOL = -3U, // String. - DYNAMIC_STRING = -4U + DYNAMIC_STRING = -4U, + // Custom value. + DYNAMIC_CUSTOM = -5U // Any other value indicates a section address plus OFFSET. }; @@ -2624,17 +2972,26 @@ class Output_relaxed_input_section : public Output_section_data_build uint64_t addralign) : Output_section_data_build(addralign), relobj_(relobj), shndx_(shndx) { } - + // Return the Relobj of this relaxed input section. Relobj* relobj() const { return this->relobj_; } - + // Return the section index of this relaxed input section. unsigned int shndx() const { return this->shndx_; } + protected: + void + set_relobj(Relobj* relobj) + { this->relobj_ = relobj; } + + void + set_shndx(unsigned int shndx) + { this->shndx_ = shndx; } + private: Relobj* relobj_; unsigned int shndx_; @@ -2670,7 +3027,7 @@ class Merge_section_properties h = (h ^ static_cast(this->addralign_)) * prime; return h; } - + // Functors for associative containers. struct equal_to { @@ -2704,7 +3061,7 @@ class Output_section_lookup_maps 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. @@ -2722,12 +3079,11 @@ class Output_section_lookup_maps 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; } - + // Find a merge section by merge section properties. Return NULL if none // is found. Output_merge_base* @@ -2739,17 +3095,6 @@ class Output_section_lookup_maps 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, @@ -2760,23 +3105,10 @@ class Output_section_lookup_maps this->merge_sections_by_properties_.insert(value); 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 value(csid, pomb); - std::pair 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 + find_relaxed_input_section(const Relobj* object, unsigned int shndx) const { gold_assert(this->is_valid_); Relaxed_input_sections_by_id::const_iterator p = @@ -2799,10 +3131,6 @@ class Output_section_lookup_maps } private: - typedef Unordered_map - Merge_sections_by_id; - typedef Unordered_map @@ -2816,8 +3144,6 @@ class Output_section_lookup_maps 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_; }; @@ -2939,7 +3265,7 @@ class Output_section : public Output_data template off_t add_input_section(Layout* layout, Sized_relobj_file* object, - unsigned int shndx, const char* name, + unsigned int shndx, const char* name, const elfcpp::Shdr& shdr, unsigned int reloc_shndx, bool have_sections_script); @@ -2978,6 +3304,11 @@ class Output_section : public Output_data 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 @@ -3097,6 +3428,13 @@ class Output_section : public Output_data set_addralign(uint64_t v) { this->addralign_ = v; } + void + checkpoint_set_addralign(uint64_t val) + { + if (this->checkpoint_ != NULL) + this->checkpoint_->set_addralign(val); + } + // Whether the output section index has been set. bool has_out_shndx() const @@ -3154,6 +3492,10 @@ class Output_section : public Output_data 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. @@ -3265,6 +3607,28 @@ class Output_section : public Output_data requires_postprocessing() const { return this->requires_postprocessing_; } + bool + is_unique_segment() const + { return this->is_unique_segment_; } + + void + set_is_unique_segment() + { this->is_unique_segment_ = true; } + + uint64_t extra_segment_flags() const + { return this->extra_segment_flags_; } + + void + set_extra_segment_flags(uint64_t flags) + { this->extra_segment_flags_ = flags; } + + uint64_t segment_alignment() const + { return this->segment_alignment_; } + + void + set_segment_alignment(uint64_t align) + { this->segment_alignment_ = align; } + // If a section requires postprocessing, return the buffer to use. unsigned char* postprocessing_buffer() const @@ -3444,7 +3808,7 @@ class Output_section : public Output_data this->p2align_ = ffsll(static_cast(addralign)); } } - + // Return the current required size, without finalization. off_t current_data_size() const; @@ -3467,13 +3831,13 @@ class Output_section : public Output_data // parameters. bool is_merge_section(bool is_string, uint64_t entsize, - uint64_t addralign) const + uint64_t addralign) const { return (this->shndx_ == (is_string ? MERGE_STRING_SECTION_CODE : MERGE_DATA_SECTION_CODE) && this->u1_.entsize == entsize - && this->addralign() == addralign); + && this->addralign() == addralign); } // Return whether this is a merge section for some input section. @@ -3512,7 +3876,7 @@ class Output_section : public Output_data gold_assert(!this->is_input_section()); return this->u2_.posd; } - + // For a merge section, return the Output_merge_base pointer. Output_merge_base* output_merge_base() const @@ -3534,8 +3898,8 @@ class Output_section : public Output_data 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; + Output_section_data* posd = + this->is_relaxed_input_section() ? this->u2_.poris : this->u2_.posd; posd->set_output_section(os); } @@ -3575,11 +3939,6 @@ class Output_section : public Output_data 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*); @@ -3696,7 +4055,7 @@ class Output_section : public Output_data // 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 @@ -3707,6 +4066,11 @@ class Output_section : public Output_data 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 @@ -3761,6 +4125,27 @@ class Output_section : public Output_data off_t allocate(off_t len, uint64_t addralign); + typedef std::vector 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_; } + + // For -r and --emit-relocs, we need to keep track of the associated + // relocation section. + Output_section* + reloc_section() const + { return this->reloc_section_; } + + void + set_reloc_section(Output_section* os) + { this->reloc_section_ = os; } + protected: // Return the output section--i.e., the object itself. Output_section* @@ -3883,13 +4268,6 @@ class Output_section : public Output_data void write_to_postprocessing_buffer(); - typedef std::vector Input_section_list; - - // Allow a child class to access the input sections. - const Input_section_list& - input_sections() const - { return this->input_sections_; } - // Whether this always keeps an input section list bool always_keeps_input_sections() const @@ -3928,6 +4306,10 @@ class Output_section : public Output_data addralign() const { return this->addralign_; } + void + set_addralign(uint64_t val) + { this->addralign_ = val; } + // Return the section flags. elfcpp::Elf_Xword flags() const @@ -4015,6 +4397,23 @@ class Output_section : public Output_data 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 @@ -4072,13 +4471,9 @@ class Output_section : public Output_data 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. @@ -4216,9 +4611,17 @@ class Output_section : public Output_data bool has_fixed_layout_ : 1; // True if we can add patch space to this section. bool is_patch_space_allowed_ : 1; + // True if this output section goes into a unique segment. + bool is_unique_segment_ : 1; // For SHT_TLS sections, the offset of this section relative to the base // of the TLS segment. uint64_t tls_offset_; + // Additional segment flags, specified via linker plugin, when mapping some + // input sections to unique segments. + uint64_t extra_segment_flags_; + // Segment alignment specified via linker plugin, when mapping some + // input sections to unique segments. + uint64_t segment_alignment_; // Saved checkpoint. Checkpoint_output_section* checkpoint_; // Fast lookup maps for merged and relaxed input sections. @@ -4230,6 +4633,8 @@ class Output_section : public Output_data Output_fill* free_space_fill_; // Amount added as patch space for incremental linking. off_t patch_space_; + // Associated relocation section, when emitting relocations. + Output_section* reloc_section_; }; // An output segment. PT_LOAD segments are built from collections of @@ -4294,6 +4699,16 @@ class Output_segment set_is_large_data_segment() { this->is_large_data_segment_ = true; } + bool + is_unique_segment() const + { return this->is_unique_segment_; } + + // Mark segment as unique, happens when linker plugins request that + // certain input sections be mapped to unique segments. + void + set_is_unique_segment() + { this->is_unique_segment_ = true; } + // Return the maximum alignment of the Output_data. uint64_t maximum_alignment(); @@ -4329,9 +4744,18 @@ class Output_segment bool has_dynamic_reloc() const; + // Return the first section. + Output_section* + first_section() const; + // Return the address of the first section. uint64_t - first_section_load_address() const; + first_section_load_address() const + { + const Output_section* os = this->first_section(); + gold_assert(os != NULL); + return os->has_load_address() ? os->load_address() : os->address(); + } // Return whether the addresses have been set already. bool @@ -4372,7 +4796,7 @@ class Output_segment // 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); @@ -4385,6 +4809,13 @@ class Output_segment this->min_p_align_ = align; } + // Set the memory size of this segment. + void + set_size(uint64_t size) + { + this->memsz_ = size; + } + // Set the offset of this segment based on the section. This should // only be called for a non-PT_LOAD segment. void @@ -4433,8 +4864,8 @@ class Output_segment // Set the section addresses in an Output_data_list. uint64_t set_section_list_addresses(Layout*, bool reset, Output_data_list*, - uint64_t addr, off_t* poff, unsigned int* pshndx, - bool* in_tls); + uint64_t addr, off_t* poff, off_t* fpoff, + unsigned int* pshndx, bool* in_tls); // Return the number of Output_sections in an Output_data_list. unsigned int @@ -4470,7 +4901,7 @@ class Output_segment // NOTE: We want to use the copy constructor. Currently, shallow copy // works for us so we do not need to write our own copy constructor. - + // The list of output data attached to this segment. Output_data_list output_lists_[ORDER_MAX]; // The segment virtual address. @@ -4504,131 +4935,8 @@ class Output_segment bool are_addresses_set_ : 1; // Whether this segment holds large data sections. bool is_large_data_segment_ : 1; -}; - -// This class represents the output file. - -class Output_file -{ - public: - Output_file(const char* name); - - // Indicate that this is a temporary file which should not be - // output. - void - set_is_temporary() - { this->is_temporary_ = true; } - - // Try to open an existing file. Returns false if the file doesn't - // exist, has a size of 0 or can't be mmaped. This method is - // thread-unsafe. If BASE_NAME is not NULL, use the contents of - // that file as the base for incremental linking. - bool - open_base_file(const char* base_name, bool writable); - - // Open the output file. FILE_SIZE is the final size of the file. - // If the file already exists, it is deleted/truncated. This method - // is thread-unsafe. - void - open(off_t file_size); - - // Resize the output file. This method is thread-unsafe. - void - resize(off_t file_size); - - // Close the output file (flushing all buffered data) and make sure - // there are no errors. This method is thread-unsafe. - void - close(); - - // Return the size of this file. - off_t - filesize() - { return this->file_size_; } - - // Return the name of this file. - const char* - filename() - { return this->name_; } - - // We currently always use mmap which makes the view handling quite - // simple. In the future we may support other approaches. - - // Write data to the output file. - void - write(off_t offset, const void* data, size_t len) - { memcpy(this->base_ + offset, data, len); } - - // Get a buffer to use to write to the file, given the offset into - // the file and the size. - unsigned char* - get_output_view(off_t start, size_t size) - { - gold_assert(start >= 0 - && start + static_cast(size) <= this->file_size_); - return this->base_ + start; - } - - // VIEW must have been returned by get_output_view. Write the - // buffer to the file, passing in the offset and the size. - void - write_output_view(off_t, size_t, unsigned char*) - { } - - // Get a read/write buffer. This is used when we want to write part - // of the file, read it in, and write it again. - unsigned char* - get_input_output_view(off_t start, size_t size) - { return this->get_output_view(start, size); } - - // Write a read/write buffer back to the file. - void - write_input_output_view(off_t, size_t, unsigned char*) - { } - - // Get a read buffer. This is used when we just want to read part - // of the file back it in. - const unsigned char* - get_input_view(off_t start, size_t size) - { return this->get_output_view(start, size); } - - // Release a read bfufer. - void - free_input_view(off_t, size_t, const unsigned char*) - { } - - private: - // Map the file into memory or, if that fails, allocate anonymous - // memory. - void - map(); - - // Allocate anonymous memory for the file. - bool - map_anonymous(); - - // Map the file into memory. - bool - map_no_anonymous(bool); - - // Unmap the file from memory (and flush to disk buffers). - void - unmap(); - - // File name. - const char* name_; - // File descriptor. - int o_; - // File size. - off_t file_size_; - // Base of file mapped into memory. - unsigned char* base_; - // True iff base_ points to a memory buffer rather than an output file. - bool map_is_anonymous_; - // True if base_ was allocated using new rather than mmap. - bool map_is_allocated_; - // True if this is a temporary file which should not be output. - bool is_temporary_; + // Whether this was marked as a unique segment via a linker plugin. + bool is_unique_segment_ : 1; }; } // End namespace gold.