# define MREMAP_MAYMOVE 1
#endif
-#ifndef HAVE_POSIX_FALLOCATE
-// A dummy, non general, version of posix_fallocate. Here we just set
-// the file size and hope that there is enough disk space. FIXME: We
-// could allocate disk space by walking block by block and writing a
-// zero byte into each block.
-static int
-posix_fallocate(int o, off_t offset, off_t len)
-{
- return ftruncate(o, offset + len);
-}
-#endif // !defined(HAVE_POSIX_FALLOCATE)
-
// Mingw does not have S_ISLNK.
#ifndef S_ISLNK
# define S_ISLNK(mode) 0
namespace gold
{
+// A wrapper around posix_fallocate. If we don't have posix_fallocate,
+// or the --no-posix-fallocate option is set, we try the fallocate
+// system call directly. If that fails, we use ftruncate to set
+// the file size and hope that there is enough disk space.
+
+static int
+gold_fallocate(int o, off_t offset, off_t len)
+{
+#ifdef HAVE_POSIX_FALLOCATE
+ if (parameters->options().posix_fallocate())
+ return ::posix_fallocate(o, offset, len);
+#endif // defined(HAVE_POSIX_FALLOCATE)
+#ifdef HAVE_FALLOCATE
+ if (::fallocate(o, 0, offset, len) == 0)
+ return 0;
+#endif // defined(HAVE_FALLOCATE)
+ if (::ftruncate(o, offset + len) < 0)
+ return errno;
+ return 0;
+}
+
// Output_data variables.
bool Output_data::allocated_sizes_are_fixed;
Output_data* od,
Address address,
bool is_relative,
- bool is_symbolless)
+ bool is_symbolless,
+ bool use_plt_offset)
: address_(address), local_sym_index_(GSYM_CODE), type_(type),
is_relative_(is_relative), is_symbolless_(is_symbolless),
- is_section_symbol_(false), use_plt_offset_(false), shndx_(INVALID_CODE)
+ is_section_symbol_(false), use_plt_offset_(use_plt_offset), shndx_(INVALID_CODE)
{
// this->type_ is a bitfield; make sure TYPE fits.
gold_assert(this->type_ == type);
unsigned int shndx,
Address address,
bool is_relative,
- bool is_symbolless)
+ bool is_symbolless,
+ bool use_plt_offset)
: address_(address), local_sym_index_(GSYM_CODE), type_(type),
is_relative_(is_relative), is_symbolless_(is_symbolless),
- is_section_symbol_(false), use_plt_offset_(false), shndx_(shndx)
+ is_section_symbol_(false), use_plt_offset_(use_plt_offset), shndx_(shndx)
{
gold_assert(shndx != INVALID_CODE);
// this->type_ is a bitfield; make sure TYPE fits.
Output_section* os,
unsigned int type,
Output_data* od,
- Address address)
+ Address address,
+ bool is_relative)
: address_(address), local_sym_index_(SECTION_CODE), type_(type),
- is_relative_(false), is_symbolless_(false),
+ is_relative_(is_relative), is_symbolless_(is_relative),
is_section_symbol_(true), use_plt_offset_(false), shndx_(INVALID_CODE)
{
// this->type_ is a bitfield; make sure TYPE fits.
unsigned int type,
Sized_relobj<size, big_endian>* relobj,
unsigned int shndx,
- Address address)
+ Address address,
+ bool is_relative)
: address_(address), local_sym_index_(SECTION_CODE), type_(type),
- is_relative_(false), is_symbolless_(false),
+ is_relative_(is_relative), is_symbolless_(is_relative),
is_section_symbol_(true), use_plt_offset_(false), shndx_(shndx)
{
gold_assert(shndx != INVALID_CODE);
{
const Sized_symbol<size>* sym;
sym = static_cast<const Sized_symbol<size>*>(this->u1_.gsym);
- return sym->value() + addend;
+ if (this->use_plt_offset_ && sym->has_plt_offset())
+ {
+ uint64_t plt_address =
+ parameters->target().plt_address_for_global(sym);
+ return plt_address + sym->plt_offset();
+ }
+ else
+ return sym->value() + addend;
}
- gold_assert(this->local_sym_index_ != SECTION_CODE
- && this->local_sym_index_ != TARGET_CODE
+ if (this->local_sym_index_ == SECTION_CODE)
+ {
+ gold_assert(!this->use_plt_offset_);
+ return this->u1_.os->address() + addend;
+ }
+ gold_assert(this->local_sym_index_ != TARGET_CODE
&& this->local_sym_index_ != INVALID_CODE
&& this->local_sym_index_ != 0
&& !this->is_section_symbol_);
default:
{
- const Sized_relobj_file<size, big_endian>* object = this->u_.object;
+ const Relobj* object = this->u_.object;
const unsigned int lsi = this->local_sym_index_;
- const Symbol_value<size>* symval = object->local_symbol(lsi);
if (!this->use_plt_offset_)
- val = symval->value(this->u_.object, 0);
+ {
+ uint64_t lval = object->local_symbol_value(lsi, 0);
+ val = convert_types<Valtype, uint64_t>(lval);
+ }
else
{
uint64_t plt_address =
Output_data_got<size, big_endian>::add_global_with_rel(
Symbol* gsym,
unsigned int got_type,
- Rel_dyn* rel_dyn,
- unsigned int r_type)
-{
- if (gsym->has_got_offset(got_type))
- return;
-
- unsigned int got_offset = this->add_got_entry(Got_entry());
- gsym->set_got_offset(got_type, got_offset);
- rel_dyn->add_global(gsym, r_type, this, got_offset);
-}
-
-template<int size, bool big_endian>
-void
-Output_data_got<size, big_endian>::add_global_with_rela(
- Symbol* gsym,
- unsigned int got_type,
- Rela_dyn* rela_dyn,
+ Output_data_reloc_generic* rel_dyn,
unsigned int r_type)
{
if (gsym->has_got_offset(got_type))
unsigned int got_offset = this->add_got_entry(Got_entry());
gsym->set_got_offset(got_type, got_offset);
- rela_dyn->add_global(gsym, r_type, this, got_offset, 0);
+ rel_dyn->add_global_generic(gsym, r_type, this, got_offset, 0);
}
// Add a pair of entries for a global symbol to the GOT, and add
Output_data_got<size, big_endian>::add_global_pair_with_rel(
Symbol* gsym,
unsigned int got_type,
- Rel_dyn* rel_dyn,
- unsigned int r_type_1,
- unsigned int r_type_2)
-{
- if (gsym->has_got_offset(got_type))
- return;
-
- unsigned int got_offset = this->add_got_entry_pair(Got_entry(), Got_entry());
- gsym->set_got_offset(got_type, got_offset);
- rel_dyn->add_global(gsym, r_type_1, this, got_offset);
-
- if (r_type_2 != 0)
- rel_dyn->add_global(gsym, r_type_2, this, got_offset + size / 8);
-}
-
-template<int size, bool big_endian>
-void
-Output_data_got<size, big_endian>::add_global_pair_with_rela(
- Symbol* gsym,
- unsigned int got_type,
- Rela_dyn* rela_dyn,
+ Output_data_reloc_generic* rel_dyn,
unsigned int r_type_1,
unsigned int r_type_2)
{
unsigned int got_offset = this->add_got_entry_pair(Got_entry(), Got_entry());
gsym->set_got_offset(got_type, got_offset);
- rela_dyn->add_global(gsym, r_type_1, this, got_offset, 0);
+ rel_dyn->add_global_generic(gsym, r_type_1, this, got_offset, 0);
if (r_type_2 != 0)
- rela_dyn->add_global(gsym, r_type_2, this, got_offset + size / 8, 0);
+ rel_dyn->add_global_generic(gsym, r_type_2, this,
+ got_offset + size / 8, 0);
}
// Add an entry for a local symbol to the GOT. This returns true if
template<int size, bool big_endian>
bool
Output_data_got<size, big_endian>::add_local(
- Sized_relobj_file<size, big_endian>* object,
+ Relobj* object,
unsigned int symndx,
unsigned int got_type)
{
template<int size, bool big_endian>
bool
Output_data_got<size, big_endian>::add_local_plt(
- Sized_relobj_file<size, big_endian>* object,
+ Relobj* object,
unsigned int symndx,
unsigned int got_type)
{
template<int size, bool big_endian>
void
Output_data_got<size, big_endian>::add_local_with_rel(
- Sized_relobj_file<size, big_endian>* object,
- unsigned int symndx,
- unsigned int got_type,
- Rel_dyn* rel_dyn,
- unsigned int r_type)
-{
- if (object->local_has_got_offset(symndx, got_type))
- return;
-
- unsigned int got_offset = this->add_got_entry(Got_entry());
- object->set_local_got_offset(symndx, got_type, got_offset);
- rel_dyn->add_local(object, symndx, r_type, this, got_offset);
-}
-
-template<int size, bool big_endian>
-void
-Output_data_got<size, big_endian>::add_local_with_rela(
- Sized_relobj_file<size, big_endian>* object,
+ Relobj* object,
unsigned int symndx,
unsigned int got_type,
- Rela_dyn* rela_dyn,
+ Output_data_reloc_generic* rel_dyn,
unsigned int r_type)
{
if (object->local_has_got_offset(symndx, got_type))
unsigned int got_offset = this->add_got_entry(Got_entry());
object->set_local_got_offset(symndx, got_type, got_offset);
- rela_dyn->add_local(object, symndx, r_type, this, got_offset, 0);
+ rel_dyn->add_local_generic(object, symndx, r_type, this, got_offset, 0);
}
// Add a pair of entries for a local symbol to the GOT, and add
template<int size, bool big_endian>
void
Output_data_got<size, big_endian>::add_local_pair_with_rel(
- Sized_relobj_file<size, big_endian>* object,
- unsigned int symndx,
- unsigned int shndx,
- unsigned int got_type,
- Rel_dyn* rel_dyn,
- unsigned int r_type_1,
- unsigned int r_type_2)
-{
- if (object->local_has_got_offset(symndx, got_type))
- return;
-
- unsigned int got_offset =
- this->add_got_entry_pair(Got_entry(),
- Got_entry(object, symndx, false));
- object->set_local_got_offset(symndx, got_type, got_offset);
- Output_section* os = object->output_section(shndx);
- rel_dyn->add_output_section(os, r_type_1, this, got_offset);
-
- if (r_type_2 != 0)
- rel_dyn->add_output_section(os, r_type_2, this, got_offset + size / 8);
-}
-
-template<int size, bool big_endian>
-void
-Output_data_got<size, big_endian>::add_local_pair_with_rela(
- Sized_relobj_file<size, big_endian>* object,
+ Relobj* object,
unsigned int symndx,
unsigned int shndx,
unsigned int got_type,
- Rela_dyn* rela_dyn,
+ Output_data_reloc_generic* rel_dyn,
unsigned int r_type_1,
unsigned int r_type_2)
{
Got_entry(object, symndx, false));
object->set_local_got_offset(symndx, got_type, got_offset);
Output_section* os = object->output_section(shndx);
- rela_dyn->add_output_section(os, r_type_1, this, got_offset, 0);
+ rel_dyn->add_output_section_generic(os, r_type_1, this, got_offset, 0);
if (r_type_2 != 0)
- rela_dyn->add_output_section(os, r_type_2, this, got_offset + size / 8, 0);
+ rel_dyn->add_output_section_generic(os, r_type_2, this,
+ got_offset + size / 8, 0);
}
// Reserve a slot in the GOT for a local symbol or the second slot of a pair.
void
Output_data_got<size, big_endian>::reserve_local(
unsigned int i,
- Sized_relobj<size, big_endian>* object,
+ Relobj* object,
unsigned int sym_index,
unsigned int got_type)
{
- this->reserve_slot(i);
+ this->do_reserve_slot(i);
object->set_local_got_offset(sym_index, got_type, this->got_offset(i));
}
Symbol* gsym,
unsigned int got_type)
{
- this->reserve_slot(i);
+ this->do_reserve_slot(i);
gsym->set_got_offset(got_type, this->got_offset(i));
}
}
}
+// Replace GOT entry I with a new value.
+
+template<int size, bool big_endian>
+void
+Output_data_got<size, big_endian>::replace_got_entry(
+ unsigned int i,
+ Got_entry got_entry)
+{
+ gold_assert(i < this->entries_.size());
+ this->entries_[i] = got_entry;
+}
+
// Output_data_dynamic::Dynamic_entry methods.
// Write out the entry.
always_keeps_input_sections_(false),
has_fixed_layout_(false),
is_patch_space_allowed_(false),
+ is_unique_segment_(false),
tls_offset_(0),
+ extra_segment_flags_(0),
+ segment_alignment_(0),
checkpoint_(NULL),
lookup_maps_(new Output_section_lookup_maps),
free_list_(),
flags_(flags),
is_max_align_known_(false),
are_addresses_set_(false),
- is_large_data_segment_(false)
+ is_large_data_segment_(false),
+ is_unique_segment_(false)
{
// The ELF ABI specifies that a PT_TLS segment always has PF_R as
// the flags.
(*p)->set_tls_offset(this->vaddr_);
}
-// Return the load address of the first section.
+// Return the first section.
-uint64_t
-Output_segment::first_section_load_address() const
+Output_section*
+Output_segment::first_section() const
{
for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
{
++p)
{
if ((*p)->is_section())
- return ((*p)->has_load_address()
- ? (*p)->load_address()
- : (*p)->address());
+ return (*p)->output_section();
}
}
gold_unreachable();
// output file will wind up incomplete, but we will have already
// exited. The alternative to fallocate would be to use fdatasync,
// but that would be a more significant performance hit.
- if (writable && ::posix_fallocate(o, 0, this->file_size_) < 0)
- gold_fatal(_("%s: %s"), this->name_, strerror(errno));
+ if (writable)
+ {
+ int err = gold_fallocate(o, 0, this->file_size_);
+ if (err != 0)
+ gold_fatal(_("%s: %s"), this->name_, strerror(err));
+ }
// Map the file into memory.
int prot = PROT_READ;
void
Output_file::map()
{
- if (this->map_no_anonymous(true))
+ if (parameters->options().mmap_output_file()
+ && this->map_no_anonymous(true))
return;
// The mmap call might fail because of file system issues: the file