forked from Imagelibrary/binutils-gdb
* gold.cc (queue_middle_tasks): Process existing GOT/PLT entries.
* incremental-dump.cc (dump_incremental_inputs): Mask high-order bit when checking got_type. * incremental.cc (Sized_incremental_binary::setup_readers): Store symbol table and string table locations; initialize bit vector of file status flags. (Sized_incremental_binary::do_reserve_layout): Set bit flag for unchanged files. (Sized_incremental_binary::do_process_got_plt): New function. (Sized_incremental_binary::get_symtab_view): Use stored locations. (Output_section_incremental_inputs::set_final_data_size): Record file index for each input file. (Output_section_incremental_inputs::write_got_plt): Store file index instead of input entry offset for each GOT entry. * incremental.h (Incremental_input_entry::Incremental_input_entry): Initialize new data member. (Incremental_input_entry::set_offset): Store file index. (Incremental_input_entry::get_file_index): New function. (Incremental_input_entry::file_index_): New data member. (Incremental_binary::process_got_plt): New function. (Incremental_binary::do_process_got_plt): New function. (Sized_incremental_binary::Sized_incremental_binary): Initialize new data members. (Sized_incremental_binary::~Sized_incremental_binary): New destructor. (Sized_incremental_binary::set_file_is_unchanged): New function. (Sized_incremental_binary::file_is_unchanged): New function. (Sized_incremental_binary::do_process_got_plt): New function. (Sized_incremental_binary::file_status_): New data member. (Sized_incremental_binary::main_symtab_loc_): New data member. (Sized_incremental_binary::main_strtab_loc_): New data member. * output.cc (Output_data_got::Got_entry::write): Add case RESERVED_CODE. (Output_data_got::add_global): Call add_got_entry. (Output_data_got::add_global_plt): Likewise. (Output_data_got::add_global_with_rel): Likewise. (Output_data_got::add_global_with_rela): Likewise. (Output_data_got::add_global_pair_with_rel): Call add_got_entry_pair. (Output_data_got::add_global_pair_with_rela): Likewise. (Output_data_got::add_local): Call add_got_entry. (Output_data_got::add_local_plt): Likewise. (Output_data_got::add_local_with_rel): Likewise. (Output_data_got::add_local_with_rela): Likewise. (Output_data_got::add_local_pair_with_rel): Call add_got_entry_pair. (Output_data_got::add_local_pair_with_rela): Likewise. (Output_data_got::reserve_slot): New function. (Output_data_got::reserve_slot_for_global): New function. (Output_data_got::add_got_entry): New function. (Output_data_got::add_got_entry_pair): New function. (Output_section::add_output_section_data): Edit FIXME. * output.h (Output_section_data_build::Output_section_data_build): New constructor with size parameter. (Output_data_space::Output_data_space): Likewise. (Output_data_got::Output_data_got): Initialize new data member; new constructor with size parameter. (Output_data_got::add_constant): Call add_got_entry. (Output_data_got::reserve_slot): New function. (Output_data_got::reserve_slot_for_global): New function. (class Output_data_got::Got_entry): Add RESERVED_CODE. (Output_data_got::add_got_entry): New function. (Output_data_got::add_got_entry_pair): New function. (Output_data_got::free_list_): New data member. * target.h (Sized_target::init_got_plt_for_update): New function. (Sized_target::register_global_plt_entry): New function. * x86_64.cc (Output_data_plt_x86_64::Output_data_plt_x86_64): Initialize new data member; call init; add constructor with PLT count. (Output_data_plt_x86_64::init): New function. (Output_data_plt_x86_64::add_relocation): New function. (Output_data_plt_x86_64::reserve_slot): New function. (Output_data_plt_x86_64::free_list_): New data member. (Target_x86_64::init_got_plt_for_update): New function. (Target_x86_64::register_global_plt_entry): New function. (Output_data_plt_x86_64::add_entry): Allocate from free list for incremental updates. (Output_data_plt_x86_64::add_relocation): New function. * testsuite/object_unittest.cc (Object_test): Set default options.
This commit is contained in:
173
gold/output.cc
173
gold/output.cc
@@ -1358,6 +1358,13 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
|
||||
val = this->u_.constant;
|
||||
break;
|
||||
|
||||
case RESERVED_CODE:
|
||||
// If we're doing an incremental update, don't touch this GOT entry.
|
||||
if (parameters->incremental_update())
|
||||
return;
|
||||
val = this->u_.constant;
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
const Sized_relobj<size, big_endian>* object = this->u_.object;
|
||||
@@ -1393,9 +1400,8 @@ Output_data_got<size, big_endian>::add_global(
|
||||
if (gsym->has_got_offset(got_type))
|
||||
return false;
|
||||
|
||||
this->entries_.push_back(Got_entry(gsym, false));
|
||||
this->set_got_size();
|
||||
gsym->set_got_offset(got_type, this->last_got_offset());
|
||||
unsigned int got_offset = this->add_got_entry(Got_entry(gsym, false));
|
||||
gsym->set_got_offset(got_type, got_offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1409,9 +1415,8 @@ Output_data_got<size, big_endian>::add_global_plt(Symbol* gsym,
|
||||
if (gsym->has_got_offset(got_type))
|
||||
return false;
|
||||
|
||||
this->entries_.push_back(Got_entry(gsym, true));
|
||||
this->set_got_size();
|
||||
gsym->set_got_offset(got_type, this->last_got_offset());
|
||||
unsigned int got_offset = this->add_got_entry(Got_entry(gsym, true));
|
||||
gsym->set_got_offset(got_type, got_offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1429,9 +1434,7 @@ Output_data_got<size, big_endian>::add_global_with_rel(
|
||||
if (gsym->has_got_offset(got_type))
|
||||
return;
|
||||
|
||||
this->entries_.push_back(Got_entry());
|
||||
this->set_got_size();
|
||||
unsigned int got_offset = this->last_got_offset();
|
||||
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);
|
||||
}
|
||||
@@ -1447,9 +1450,7 @@ Output_data_got<size, big_endian>::add_global_with_rela(
|
||||
if (gsym->has_got_offset(got_type))
|
||||
return;
|
||||
|
||||
this->entries_.push_back(Got_entry());
|
||||
this->set_got_size();
|
||||
unsigned int got_offset = this->last_got_offset();
|
||||
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);
|
||||
}
|
||||
@@ -1469,19 +1470,12 @@ Output_data_got<size, big_endian>::add_global_pair_with_rel(
|
||||
if (gsym->has_got_offset(got_type))
|
||||
return;
|
||||
|
||||
this->entries_.push_back(Got_entry());
|
||||
unsigned int got_offset = this->last_got_offset();
|
||||
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);
|
||||
|
||||
this->entries_.push_back(Got_entry());
|
||||
if (r_type_2 != 0)
|
||||
{
|
||||
got_offset = this->last_got_offset();
|
||||
rel_dyn->add_global(gsym, r_type_2, this, got_offset);
|
||||
}
|
||||
|
||||
this->set_got_size();
|
||||
rel_dyn->add_global(gsym, r_type_2, this, got_offset + size / 8);
|
||||
}
|
||||
|
||||
template<int size, bool big_endian>
|
||||
@@ -1496,19 +1490,12 @@ Output_data_got<size, big_endian>::add_global_pair_with_rela(
|
||||
if (gsym->has_got_offset(got_type))
|
||||
return;
|
||||
|
||||
this->entries_.push_back(Got_entry());
|
||||
unsigned int got_offset = this->last_got_offset();
|
||||
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);
|
||||
|
||||
this->entries_.push_back(Got_entry());
|
||||
if (r_type_2 != 0)
|
||||
{
|
||||
got_offset = this->last_got_offset();
|
||||
rela_dyn->add_global(gsym, r_type_2, this, got_offset, 0);
|
||||
}
|
||||
|
||||
this->set_got_size();
|
||||
rela_dyn->add_global(gsym, r_type_2, this, got_offset + size / 8, 0);
|
||||
}
|
||||
|
||||
// Add an entry for a local symbol to the GOT. This returns true if
|
||||
@@ -1525,9 +1512,9 @@ Output_data_got<size, big_endian>::add_local(
|
||||
if (object->local_has_got_offset(symndx, got_type))
|
||||
return false;
|
||||
|
||||
this->entries_.push_back(Got_entry(object, symndx, false));
|
||||
this->set_got_size();
|
||||
object->set_local_got_offset(symndx, got_type, this->last_got_offset());
|
||||
unsigned int got_offset = this->add_got_entry(Got_entry(object, symndx,
|
||||
false));
|
||||
object->set_local_got_offset(symndx, got_type, got_offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1543,9 +1530,9 @@ Output_data_got<size, big_endian>::add_local_plt(
|
||||
if (object->local_has_got_offset(symndx, got_type))
|
||||
return false;
|
||||
|
||||
this->entries_.push_back(Got_entry(object, symndx, true));
|
||||
this->set_got_size();
|
||||
object->set_local_got_offset(symndx, got_type, this->last_got_offset());
|
||||
unsigned int got_offset = this->add_got_entry(Got_entry(object, symndx,
|
||||
true));
|
||||
object->set_local_got_offset(symndx, got_type, got_offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1564,9 +1551,7 @@ Output_data_got<size, big_endian>::add_local_with_rel(
|
||||
if (object->local_has_got_offset(symndx, got_type))
|
||||
return;
|
||||
|
||||
this->entries_.push_back(Got_entry());
|
||||
this->set_got_size();
|
||||
unsigned int got_offset = this->last_got_offset();
|
||||
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);
|
||||
}
|
||||
@@ -1583,9 +1568,7 @@ Output_data_got<size, big_endian>::add_local_with_rela(
|
||||
if (object->local_has_got_offset(symndx, got_type))
|
||||
return;
|
||||
|
||||
this->entries_.push_back(Got_entry());
|
||||
this->set_got_size();
|
||||
unsigned int got_offset = this->last_got_offset();
|
||||
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);
|
||||
}
|
||||
@@ -1607,20 +1590,15 @@ Output_data_got<size, big_endian>::add_local_pair_with_rel(
|
||||
if (object->local_has_got_offset(symndx, got_type))
|
||||
return;
|
||||
|
||||
this->entries_.push_back(Got_entry());
|
||||
unsigned int got_offset = this->last_got_offset();
|
||||
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);
|
||||
|
||||
this->entries_.push_back(Got_entry(object, symndx, false));
|
||||
if (r_type_2 != 0)
|
||||
{
|
||||
got_offset = this->last_got_offset();
|
||||
rel_dyn->add_output_section(os, r_type_2, this, got_offset);
|
||||
}
|
||||
|
||||
this->set_got_size();
|
||||
rel_dyn->add_output_section(os, r_type_2, this, got_offset + size / 8);
|
||||
}
|
||||
|
||||
template<int size, bool big_endian>
|
||||
@@ -1637,20 +1615,37 @@ Output_data_got<size, big_endian>::add_local_pair_with_rela(
|
||||
if (object->local_has_got_offset(symndx, got_type))
|
||||
return;
|
||||
|
||||
this->entries_.push_back(Got_entry());
|
||||
unsigned int got_offset = this->last_got_offset();
|
||||
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);
|
||||
rela_dyn->add_output_section(os, r_type_1, this, got_offset, 0);
|
||||
|
||||
this->entries_.push_back(Got_entry(object, symndx, false));
|
||||
if (r_type_2 != 0)
|
||||
{
|
||||
got_offset = this->last_got_offset();
|
||||
rela_dyn->add_output_section(os, r_type_2, this, got_offset, 0);
|
||||
}
|
||||
rela_dyn->add_output_section(os, r_type_2, this, got_offset + size / 8, 0);
|
||||
}
|
||||
|
||||
this->set_got_size();
|
||||
// Reserve a slot in the GOT for a local symbol or the second slot of a pair.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Output_data_got<size, big_endian>::reserve_slot(unsigned int i)
|
||||
{
|
||||
this->free_list_.remove(i * size / 8, (i + 1) * size / 8);
|
||||
}
|
||||
|
||||
// Reserve a slot in the GOT for a global symbol.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Output_data_got<size, big_endian>::reserve_slot_for_global(
|
||||
unsigned int i,
|
||||
Symbol* gsym,
|
||||
unsigned int got_type)
|
||||
{
|
||||
this->free_list_.remove(i * size / 8, (i + 1) * size / 8);
|
||||
gsym->set_got_offset(got_type, this->got_offset(i));
|
||||
}
|
||||
|
||||
// Write out the GOT.
|
||||
@@ -1682,6 +1677,63 @@ Output_data_got<size, big_endian>::do_write(Output_file* of)
|
||||
this->entries_.clear();
|
||||
}
|
||||
|
||||
// Create a new GOT entry and return its offset.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
unsigned int
|
||||
Output_data_got<size, big_endian>::add_got_entry(Got_entry got_entry)
|
||||
{
|
||||
if (!this->is_data_size_valid())
|
||||
{
|
||||
this->entries_.push_back(got_entry);
|
||||
this->set_got_size();
|
||||
return this->last_got_offset();
|
||||
}
|
||||
else
|
||||
{
|
||||
// For an incremental update, find an available slot.
|
||||
off_t got_offset = this->free_list_.allocate(size / 8, size / 8, 0);
|
||||
if (got_offset == -1)
|
||||
gold_fatal(_("out of patch space (GOT);"
|
||||
" relink with --incremental-full"));
|
||||
unsigned int got_index = got_offset / (size / 8);
|
||||
gold_assert(got_index < this->entries_.size());
|
||||
this->entries_[got_index] = got_entry;
|
||||
return static_cast<unsigned int>(got_offset);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a pair of new GOT entries and return the offset of the first.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
unsigned int
|
||||
Output_data_got<size, big_endian>::add_got_entry_pair(Got_entry got_entry_1,
|
||||
Got_entry got_entry_2)
|
||||
{
|
||||
if (!this->is_data_size_valid())
|
||||
{
|
||||
unsigned int got_offset;
|
||||
this->entries_.push_back(got_entry_1);
|
||||
got_offset = this->last_got_offset();
|
||||
this->entries_.push_back(got_entry_2);
|
||||
this->set_got_size();
|
||||
return got_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
// For an incremental update, find an available pair of slots.
|
||||
off_t got_offset = this->free_list_.allocate(2 * size / 8, size / 8, 0);
|
||||
if (got_offset == -1)
|
||||
gold_fatal(_("out of patch space (GOT);"
|
||||
" relink with --incremental-full"));
|
||||
unsigned int got_index = got_offset / (size / 8);
|
||||
gold_assert(got_index < this->entries_.size());
|
||||
this->entries_[got_index] = got_entry_1;
|
||||
this->entries_[got_index + 1] = got_entry_2;
|
||||
return static_cast<unsigned int>(got_offset);
|
||||
}
|
||||
}
|
||||
|
||||
// Output_data_dynamic::Dynamic_entry methods.
|
||||
|
||||
// Write out the entry.
|
||||
@@ -2335,7 +2387,8 @@ Output_section::add_output_section_data(Output_section_data* posd)
|
||||
uint64_t addr = this->address();
|
||||
posd->set_address(addr);
|
||||
posd->set_file_offset(0);
|
||||
// FIXME: Mark *POSD as part of a fixed-layout section.
|
||||
// FIXME: This should eventually be unreachable.
|
||||
// gold_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user