Line 117... |
Line 117... |
// could allocate disk space by walking block by block and writing a
|
// could allocate disk space by walking block by block and writing a
|
// zero byte into each block.
|
// zero byte into each block.
|
static int
|
static int
|
posix_fallocate(int o, off_t offset, off_t len)
|
posix_fallocate(int o, off_t offset, off_t len)
|
{
|
{
|
return ftruncate(o, offset + len);
|
if (ftruncate(o, offset + len) < 0)
|
|
return errno;
|
|
return 0;
|
}
|
}
|
#endif // !defined(HAVE_POSIX_FALLOCATE)
|
#endif // !defined(HAVE_POSIX_FALLOCATE)
|
|
|
// Mingw does not have S_ISLNK.
|
// Mingw does not have S_ISLNK.
|
#ifndef S_ISLNK
|
#ifndef S_ISLNK
|
Line 704... |
Line 706... |
Address address,
|
Address address,
|
bool is_relative,
|
bool is_relative,
|
bool is_symbolless)
|
bool is_symbolless)
|
: address_(address), local_sym_index_(GSYM_CODE), type_(type),
|
: address_(address), local_sym_index_(GSYM_CODE), type_(type),
|
is_relative_(is_relative), is_symbolless_(is_symbolless),
|
is_relative_(is_relative), is_symbolless_(is_symbolless),
|
is_section_symbol_(false), shndx_(INVALID_CODE)
|
is_section_symbol_(false), use_plt_offset_(false), shndx_(INVALID_CODE)
|
{
|
{
|
// this->type_ is a bitfield; make sure TYPE fits.
|
// this->type_ is a bitfield; make sure TYPE fits.
|
gold_assert(this->type_ == type);
|
gold_assert(this->type_ == type);
|
this->u1_.gsym = gsym;
|
this->u1_.gsym = gsym;
|
this->u2_.od = od;
|
this->u2_.od = od;
|
Line 725... |
Line 727... |
Address address,
|
Address address,
|
bool is_relative,
|
bool is_relative,
|
bool is_symbolless)
|
bool is_symbolless)
|
: address_(address), local_sym_index_(GSYM_CODE), type_(type),
|
: address_(address), local_sym_index_(GSYM_CODE), type_(type),
|
is_relative_(is_relative), is_symbolless_(is_symbolless),
|
is_relative_(is_relative), is_symbolless_(is_symbolless),
|
is_section_symbol_(false), shndx_(shndx)
|
is_section_symbol_(false), use_plt_offset_(false), shndx_(shndx)
|
{
|
{
|
gold_assert(shndx != INVALID_CODE);
|
gold_assert(shndx != INVALID_CODE);
|
// this->type_ is a bitfield; make sure TYPE fits.
|
// this->type_ is a bitfield; make sure TYPE fits.
|
gold_assert(this->type_ == type);
|
gold_assert(this->type_ == type);
|
this->u1_.gsym = gsym;
|
this->u1_.gsym = gsym;
|
Line 747... |
Line 749... |
unsigned int type,
|
unsigned int type,
|
Output_data* od,
|
Output_data* od,
|
Address address,
|
Address address,
|
bool is_relative,
|
bool is_relative,
|
bool is_symbolless,
|
bool is_symbolless,
|
bool is_section_symbol)
|
bool is_section_symbol,
|
|
bool use_plt_offset)
|
: address_(address), local_sym_index_(local_sym_index), type_(type),
|
: address_(address), local_sym_index_(local_sym_index), type_(type),
|
is_relative_(is_relative), is_symbolless_(is_symbolless),
|
is_relative_(is_relative), is_symbolless_(is_symbolless),
|
is_section_symbol_(is_section_symbol), shndx_(INVALID_CODE)
|
is_section_symbol_(is_section_symbol), use_plt_offset_(use_plt_offset),
|
|
shndx_(INVALID_CODE)
|
{
|
{
|
gold_assert(local_sym_index != GSYM_CODE
|
gold_assert(local_sym_index != GSYM_CODE
|
&& local_sym_index != INVALID_CODE);
|
&& local_sym_index != INVALID_CODE);
|
// this->type_ is a bitfield; make sure TYPE fits.
|
// this->type_ is a bitfield; make sure TYPE fits.
|
gold_assert(this->type_ == type);
|
gold_assert(this->type_ == type);
|
Line 771... |
Line 775... |
unsigned int type,
|
unsigned int type,
|
unsigned int shndx,
|
unsigned int shndx,
|
Address address,
|
Address address,
|
bool is_relative,
|
bool is_relative,
|
bool is_symbolless,
|
bool is_symbolless,
|
bool is_section_symbol)
|
bool is_section_symbol,
|
|
bool use_plt_offset)
|
: address_(address), local_sym_index_(local_sym_index), type_(type),
|
: address_(address), local_sym_index_(local_sym_index), type_(type),
|
is_relative_(is_relative), is_symbolless_(is_symbolless),
|
is_relative_(is_relative), is_symbolless_(is_symbolless),
|
is_section_symbol_(is_section_symbol), shndx_(shndx)
|
is_section_symbol_(is_section_symbol), use_plt_offset_(use_plt_offset),
|
|
shndx_(shndx)
|
{
|
{
|
gold_assert(local_sym_index != GSYM_CODE
|
gold_assert(local_sym_index != GSYM_CODE
|
&& local_sym_index != INVALID_CODE);
|
&& local_sym_index != INVALID_CODE);
|
gold_assert(shndx != INVALID_CODE);
|
gold_assert(shndx != INVALID_CODE);
|
// this->type_ is a bitfield; make sure TYPE fits.
|
// this->type_ is a bitfield; make sure TYPE fits.
|
Line 797... |
Line 803... |
unsigned int type,
|
unsigned int type,
|
Output_data* od,
|
Output_data* od,
|
Address address)
|
Address address)
|
: address_(address), local_sym_index_(SECTION_CODE), type_(type),
|
: address_(address), local_sym_index_(SECTION_CODE), type_(type),
|
is_relative_(false), is_symbolless_(false),
|
is_relative_(false), is_symbolless_(false),
|
is_section_symbol_(true), shndx_(INVALID_CODE)
|
is_section_symbol_(true), use_plt_offset_(false), shndx_(INVALID_CODE)
|
{
|
{
|
// this->type_ is a bitfield; make sure TYPE fits.
|
// this->type_ is a bitfield; make sure TYPE fits.
|
gold_assert(this->type_ == type);
|
gold_assert(this->type_ == type);
|
this->u1_.os = os;
|
this->u1_.os = os;
|
this->u2_.od = od;
|
this->u2_.od = od;
|
Line 818... |
Line 824... |
Sized_relobj<size, big_endian>* relobj,
|
Sized_relobj<size, big_endian>* relobj,
|
unsigned int shndx,
|
unsigned int shndx,
|
Address address)
|
Address address)
|
: address_(address), local_sym_index_(SECTION_CODE), type_(type),
|
: address_(address), local_sym_index_(SECTION_CODE), type_(type),
|
is_relative_(false), is_symbolless_(false),
|
is_relative_(false), is_symbolless_(false),
|
is_section_symbol_(true), shndx_(shndx)
|
is_section_symbol_(true), use_plt_offset_(false), shndx_(shndx)
|
{
|
{
|
gold_assert(shndx != INVALID_CODE);
|
gold_assert(shndx != INVALID_CODE);
|
// this->type_ is a bitfield; make sure TYPE fits.
|
// this->type_ is a bitfield; make sure TYPE fits.
|
gold_assert(this->type_ == type);
|
gold_assert(this->type_ == type);
|
this->u1_.os = os;
|
this->u1_.os = os;
|
Line 840... |
Line 846... |
unsigned int type,
|
unsigned int type,
|
Output_data* od,
|
Output_data* od,
|
Address address)
|
Address address)
|
: address_(address), local_sym_index_(0), type_(type),
|
: address_(address), local_sym_index_(0), type_(type),
|
is_relative_(false), is_symbolless_(false),
|
is_relative_(false), is_symbolless_(false),
|
is_section_symbol_(false), shndx_(INVALID_CODE)
|
is_section_symbol_(false), use_plt_offset_(false), shndx_(INVALID_CODE)
|
{
|
{
|
// this->type_ is a bitfield; make sure TYPE fits.
|
// this->type_ is a bitfield; make sure TYPE fits.
|
gold_assert(this->type_ == type);
|
gold_assert(this->type_ == type);
|
this->u1_.relobj = NULL;
|
this->u1_.relobj = NULL;
|
this->u2_.od = od;
|
this->u2_.od = od;
|
Line 856... |
Line 862... |
Sized_relobj<size, big_endian>* relobj,
|
Sized_relobj<size, big_endian>* relobj,
|
unsigned int shndx,
|
unsigned int shndx,
|
Address address)
|
Address address)
|
: address_(address), local_sym_index_(0), type_(type),
|
: address_(address), local_sym_index_(0), type_(type),
|
is_relative_(false), is_symbolless_(false),
|
is_relative_(false), is_symbolless_(false),
|
is_section_symbol_(false), shndx_(shndx)
|
is_section_symbol_(false), use_plt_offset_(false), shndx_(shndx)
|
{
|
{
|
gold_assert(shndx != INVALID_CODE);
|
gold_assert(shndx != INVALID_CODE);
|
// this->type_ is a bitfield; make sure TYPE fits.
|
// this->type_ is a bitfield; make sure TYPE fits.
|
gold_assert(this->type_ == type);
|
gold_assert(this->type_ == type);
|
this->u1_.relobj = NULL;
|
this->u1_.relobj = NULL;
|
Line 875... |
Line 881... |
void* arg,
|
void* arg,
|
Output_data* od,
|
Output_data* od,
|
Address address)
|
Address address)
|
: address_(address), local_sym_index_(TARGET_CODE), type_(type),
|
: address_(address), local_sym_index_(TARGET_CODE), type_(type),
|
is_relative_(false), is_symbolless_(false),
|
is_relative_(false), is_symbolless_(false),
|
is_section_symbol_(false), shndx_(INVALID_CODE)
|
is_section_symbol_(false), use_plt_offset_(false), shndx_(INVALID_CODE)
|
{
|
{
|
// this->type_ is a bitfield; make sure TYPE fits.
|
// this->type_ is a bitfield; make sure TYPE fits.
|
gold_assert(this->type_ == type);
|
gold_assert(this->type_ == type);
|
this->u1_.arg = arg;
|
this->u1_.arg = arg;
|
this->u2_.od = od;
|
this->u2_.od = od;
|
Line 892... |
Line 898... |
Sized_relobj<size, big_endian>* relobj,
|
Sized_relobj<size, big_endian>* relobj,
|
unsigned int shndx,
|
unsigned int shndx,
|
Address address)
|
Address address)
|
: address_(address), local_sym_index_(TARGET_CODE), type_(type),
|
: address_(address), local_sym_index_(TARGET_CODE), type_(type),
|
is_relative_(false), is_symbolless_(false),
|
is_relative_(false), is_symbolless_(false),
|
is_section_symbol_(false), shndx_(shndx)
|
is_section_symbol_(false), use_plt_offset_(false), shndx_(shndx)
|
{
|
{
|
gold_assert(shndx != INVALID_CODE);
|
gold_assert(shndx != INVALID_CODE);
|
// this->type_ is a bitfield; make sure TYPE fits.
|
// this->type_ is a bitfield; make sure TYPE fits.
|
gold_assert(this->type_ == type);
|
gold_assert(this->type_ == type);
|
this->u1_.arg = arg;
|
this->u1_.arg = arg;
|
Line 1119... |
Line 1125... |
&& !this->is_section_symbol_);
|
&& !this->is_section_symbol_);
|
const unsigned int lsi = this->local_sym_index_;
|
const unsigned int lsi = this->local_sym_index_;
|
Sized_relobj_file<size, big_endian>* relobj =
|
Sized_relobj_file<size, big_endian>* relobj =
|
this->u1_.relobj->sized_relobj();
|
this->u1_.relobj->sized_relobj();
|
gold_assert(relobj != NULL);
|
gold_assert(relobj != NULL);
|
|
if (this->use_plt_offset_)
|
|
{
|
|
uint64_t plt_address =
|
|
parameters->target().plt_address_for_local(relobj, lsi);
|
|
return plt_address + relobj->local_plt_offset(lsi);
|
|
}
|
const Symbol_value<size>* symval = relobj->local_symbol(lsi);
|
const Symbol_value<size>* symval = relobj->local_symbol(lsi);
|
return symval->value(relobj, addend);
|
return symval->value(relobj, addend);
|
}
|
}
|
|
|
// Reloc comparison. This function sorts the dynamic relocs for the
|
// Reloc comparison. This function sorts the dynamic relocs for the
|
Line 1947... |
Line 1959... |
// .debug_info or .debug_types section.
|
// .debug_info or .debug_types section.
|
|
|
void
|
void
|
Output_fill_debug_info::do_write(Output_file* of, off_t off, size_t len) const
|
Output_fill_debug_info::do_write(Output_file* of, off_t off, size_t len) const
|
{
|
{
|
gold_debug(DEBUG_INCREMENTAL, "fill_debug_info(%08lx, %08lx)", off, len);
|
gold_debug(DEBUG_INCREMENTAL, "fill_debug_info(%08lx, %08lx)",
|
|
static_cast<long>(off), static_cast<long>(len));
|
|
|
gold_assert(len >= this->do_minimum_hole_size());
|
gold_assert(len >= this->do_minimum_hole_size());
|
|
|
unsigned char* const oview = of->get_output_view(off, len);
|
unsigned char* const oview = of->get_output_view(off, len);
|
unsigned char* pov = oview;
|
unsigned char* pov = oview;
|
|
|
// Write header fields: unit_length, version, debug_abbrev_offset,
|
// Write header fields: unit_length, version, debug_abbrev_offset,
|
// address_size.
|
// address_size.
|
if (this->is_big_endian())
|
if (this->is_big_endian())
|
{
|
{
|
elfcpp::Swap<32, true>::writeval(pov, len - 4);
|
elfcpp::Swap_unaligned<32, true>::writeval(pov, len - 4);
|
elfcpp::Swap<16, true>::writeval(pov + 4, this->version);
|
elfcpp::Swap_unaligned<16, true>::writeval(pov + 4, this->version);
|
elfcpp::Swap<32, true>::writeval(pov + 6, 0);
|
elfcpp::Swap_unaligned<32, true>::writeval(pov + 6, 0);
|
}
|
}
|
else
|
else
|
{
|
{
|
elfcpp::Swap<32, false>::writeval(pov, len - 4);
|
elfcpp::Swap_unaligned<32, false>::writeval(pov, len - 4);
|
elfcpp::Swap<16, false>::writeval(pov + 4, this->version);
|
elfcpp::Swap_unaligned<16, false>::writeval(pov + 4, this->version);
|
elfcpp::Swap<32, false>::writeval(pov + 6, 0);
|
elfcpp::Swap_unaligned<32, false>::writeval(pov + 6, 0);
|
}
|
}
|
pov += 4 + 2 + 4;
|
pov += 4 + 2 + 4;
|
*pov++ = 4;
|
*pov++ = 4;
|
|
|
// For type units, the additional header fields -- type_signature,
|
// For type units, the additional header fields -- type_signature,
|
Line 2003... |
Line 2016... |
// .debug_line section.
|
// .debug_line section.
|
|
|
void
|
void
|
Output_fill_debug_line::do_write(Output_file* of, off_t off, size_t len) const
|
Output_fill_debug_line::do_write(Output_file* of, off_t off, size_t len) const
|
{
|
{
|
gold_debug(DEBUG_INCREMENTAL, "fill_debug_line(%08lx, %08lx)", off, len);
|
gold_debug(DEBUG_INCREMENTAL, "fill_debug_line(%08lx, %08lx)",
|
|
static_cast<long>(off), static_cast<long>(len));
|
|
|
gold_assert(len >= this->do_minimum_hole_size());
|
gold_assert(len >= this->do_minimum_hole_size());
|
|
|
unsigned char* const oview = of->get_output_view(off, len);
|
unsigned char* const oview = of->get_output_view(off, len);
|
unsigned char* pov = oview;
|
unsigned char* pov = oview;
|
Line 2017... |
Line 2031... |
// opcode_base, standard_opcode_lengths[], include_directories, filenames.
|
// opcode_base, standard_opcode_lengths[], include_directories, filenames.
|
// We set the header_length field to cover the entire hole, so the
|
// We set the header_length field to cover the entire hole, so the
|
// line number program is empty.
|
// line number program is empty.
|
if (this->is_big_endian())
|
if (this->is_big_endian())
|
{
|
{
|
elfcpp::Swap<32, true>::writeval(pov, len - 4);
|
elfcpp::Swap_unaligned<32, true>::writeval(pov, len - 4);
|
elfcpp::Swap<16, true>::writeval(pov + 4, this->version);
|
elfcpp::Swap_unaligned<16, true>::writeval(pov + 4, this->version);
|
elfcpp::Swap<32, true>::writeval(pov + 6, len - (4 + 2 + 4));
|
elfcpp::Swap_unaligned<32, true>::writeval(pov + 6, len - (4 + 2 + 4));
|
}
|
}
|
else
|
else
|
{
|
{
|
elfcpp::Swap<32, false>::writeval(pov, len - 4);
|
elfcpp::Swap_unaligned<32, false>::writeval(pov, len - 4);
|
elfcpp::Swap<16, false>::writeval(pov + 4, this->version);
|
elfcpp::Swap_unaligned<16, false>::writeval(pov + 4, this->version);
|
elfcpp::Swap<32, false>::writeval(pov + 6, len - (4 + 2 + 4));
|
elfcpp::Swap_unaligned<32, false>::writeval(pov + 6, len - (4 + 2 + 4));
|
}
|
}
|
pov += 4 + 2 + 4;
|
pov += 4 + 2 + 4;
|
*pov++ = 1; // minimum_instruction_length
|
*pov++ = 1; // minimum_instruction_length
|
*pov++ = 0; // default_is_stmt
|
*pov++ = 0; // default_is_stmt
|
*pov++ = 0; // line_base
|
*pov++ = 0; // line_base
|
Line 2472... |
Line 2486... |
|| parameters->options().user_set_Map()
|
|| parameters->options().user_set_Map()
|
|| parameters->target().may_relax()
|
|| parameters->target().may_relax()
|
|| layout->is_section_ordering_specified())
|
|| layout->is_section_ordering_specified())
|
{
|
{
|
Input_section isecn(object, shndx, input_section_size, addralign);
|
Input_section isecn(object, shndx, input_section_size, addralign);
|
if (layout->is_section_ordering_specified())
|
/* If section ordering is requested by specifying a ordering file,
|
|
using --section-ordering-file, match the section name with
|
|
a pattern. */
|
|
if (parameters->options().section_ordering_file())
|
{
|
{
|
unsigned int section_order_index =
|
unsigned int section_order_index =
|
layout->find_section_order_index(std::string(secname));
|
layout->find_section_order_index(std::string(secname));
|
if (section_order_index != 0)
|
if (section_order_index != 0)
|
{
|
{
|
Line 3481... |
Line 3498... |
// This updates the section order index of input sections according to the
|
// This updates the section order index of input sections according to the
|
// the order specified in the mapping from Section id to order index.
|
// the order specified in the mapping from Section id to order index.
|
|
|
void
|
void
|
Output_section::update_section_layout(
|
Output_section::update_section_layout(
|
const Section_layout_order& order_map)
|
const Section_layout_order* order_map)
|
{
|
{
|
for (Input_section_list::iterator p = this->input_sections_.begin();
|
for (Input_section_list::iterator p = this->input_sections_.begin();
|
p != this->input_sections_.end();
|
p != this->input_sections_.end();
|
++p)
|
++p)
|
{
|
{
|
Line 3495... |
Line 3512... |
Object* obj = (p->is_input_section()
|
Object* obj = (p->is_input_section()
|
? p->relobj()
|
? p->relobj()
|
: p->relaxed_input_section()->relobj());
|
: p->relaxed_input_section()->relobj());
|
unsigned int shndx = p->shndx();
|
unsigned int shndx = p->shndx();
|
Section_layout_order::const_iterator it
|
Section_layout_order::const_iterator it
|
= order_map.find(Section_id(obj, shndx));
|
= order_map->find(Section_id(obj, shndx));
|
if (it == order_map.end())
|
if (it == order_map->end())
|
continue;
|
continue;
|
unsigned int section_order_index = it->second;
|
unsigned int section_order_index = it->second;
|
if (section_order_index != 0)
|
if (section_order_index != 0)
|
{
|
{
|
p->set_section_order_index(section_order_index);
|
p->set_section_order_index(section_order_index);
|
Line 4876... |
Line 4893... |
// new output file and read the contents from the base file into
|
// new output file and read the contents from the base file into
|
// the newly-mapped region.
|
// the newly-mapped region.
|
if (use_base_file)
|
if (use_base_file)
|
{
|
{
|
this->open(s.st_size);
|
this->open(s.st_size);
|
ssize_t len = ::read(o, this->base_, s.st_size);
|
ssize_t bytes_to_read = s.st_size;
|
|
unsigned char* p = this->base_;
|
|
while (bytes_to_read > 0)
|
|
{
|
|
ssize_t len = ::read(o, p, bytes_to_read);
|
if (len < 0)
|
if (len < 0)
|
{
|
{
|
gold_info(_("%s: read failed: %s"), base_name, strerror(errno));
|
gold_info(_("%s: read failed: %s"), base_name, strerror(errno));
|
return false;
|
return false;
|
}
|
}
|
if (len < s.st_size)
|
if (len == 0)
|
{
|
{
|
gold_info(_("%s: file too short"), base_name);
|
gold_info(_("%s: file too short: read only %lld of %lld bytes"),
|
|
base_name,
|
|
static_cast<long long>(s.st_size - bytes_to_read),
|
|
static_cast<long long>(s.st_size));
|
return false;
|
return false;
|
}
|
}
|
|
p += len;
|
|
bytes_to_read -= len;
|
|
}
|
::close(o);
|
::close(o);
|
return true;
|
return true;
|
}
|
}
|
|
|
this->o_ = o;
|
this->o_ = o;
|
Line 5048... |
Line 5075... |
// and exit with dirty buffers still in the cache with no assigned
|
// and exit with dirty buffers still in the cache with no assigned
|
// disk blocks. If the disk is out of space at that point, the
|
// disk blocks. If the disk is out of space at that point, the
|
// output file will wind up incomplete, but we will have already
|
// output file will wind up incomplete, but we will have already
|
// exited. The alternative to fallocate would be to use fdatasync,
|
// exited. The alternative to fallocate would be to use fdatasync,
|
// but that would be a more significant performance hit.
|
// but that would be a more significant performance hit.
|
if (writable && ::posix_fallocate(o, 0, this->file_size_) < 0)
|
if (writable)
|
gold_fatal(_("%s: %s"), this->name_, strerror(errno));
|
{
|
|
int err = ::posix_fallocate(o, 0, this->file_size_);
|
|
if (err != 0)
|
|
gold_fatal(_("%s: %s"), this->name_, strerror(err));
|
|
}
|
|
|
// Map the file into memory.
|
// Map the file into memory.
|
int prot = PROT_READ;
|
int prot = PROT_READ;
|
if (writable)
|
if (writable)
|
prot |= PROT_WRITE;
|
prot |= PROT_WRITE;
|