* copy-relocs.cc (Copy_relocs::copy_reloc): Call make_copy_reloc

instead of emit_copy_reloc.
	(Copy_relocs::emit_copy_reloc): Refactor.
	(Copy_relocs::make_copy_reloc): New function.
	(Copy_relocs::add_copy_reloc): Remove.
	* copy-relocs.h (Copy_relocs::emit_copy_reloc): Move to public
	section.
	(Copy_relocs::make_copy_reloc): New function.
	(Copy_relocs::add_copy_reloc): Remove.
	* gold.cc (queue_middle_tasks): Emit old COPY relocations from
	unchanged input files.
	* incremental-dump.cc (dump_incremental_inputs): Print "COPY" flag.
	* incremental.cc (Sized_incremental_binary::do_reserve_layout):
	Reserve BSS space for COPY relocations.
	(Sized_incremental_binary::do_emit_copy_relocs): New function.
	(Output_section_incremental_inputs::write_info_blocks): Record
	whether a symbol is copied from a shared object.
	(Sized_incr_dynobj::do_add_symbols): Record COPY relocations.
	* incremental.h (enum Incremental_shlib_symbol_flags): New type.
	(INCREMENTAL_SHLIB_SYM_FLAGS_SHIFT): New constant.
	(Incremental_input_entry_reader::get_output_symbol_index): Add
	is_copy parameter.
	(Incremental_binary::emit_copy_relocs): New function.
	(Incremental_binary::do_emit_copy_relocs): New function.
	(Sized_incremental_binary::Sized_incremental_binary): Initialize
	new data member.
	(Sized_incremental_binary::add_copy_reloc): New function.
	(Sized_incremental_binary::do_emit_copy_relocs): New function.
	(Sized_incremental_binary::Copy_reloc): New struct.
	(Sized_incremental_binary::Copy_relocs): New typedef.
	(Sized_incremental_binary::copy_relocs_): New data member.
	* symtab.cc (Symbol_table::add_from_incrobj): Change return type.
	* symtab.h (Symbol_table::add_from_incrobj): Change return type.
	* target.h (Sized_target::emit_copy_reloc): New function.
	* x86_64.cc (Target_x86_64::emit_copy_reloc): New function.
This commit is contained in:
Cary Coutant
2011-06-08 03:50:12 +00:00
parent b8e9bd6c64
commit 26d3c67de1
11 changed files with 267 additions and 52 deletions

View File

@ -68,6 +68,20 @@ enum Incremental_input_flags
INCREMENTAL_INPUT_AS_NEEDED = 0x4000
};
// Symbol flags for the incremental symbol table.
// These flags are stored in the top two bits of
// the symbol index field.
enum Incremental_shlib_symbol_flags
{
// Symbol is defined in this library.
INCREMENTAL_SHLIB_SYM_DEF = 2,
// Symbol is defined in this library, with a COPY relocation.
INCREMENTAL_SHLIB_SYM_COPY = 3
};
static const int INCREMENTAL_SHLIB_SYM_FLAGS_SHIFT = 30;
// Create an Incremental_binary object for FILE. Returns NULL is this is not
// possible, e.g. FILE is not an ELF file or has an unsupported target.
@ -1012,17 +1026,33 @@ class Incremental_inputs_reader
// Return the output symbol index for the Nth global symbol -- for shared
// libraries only. Sets *IS_DEF to TRUE if the symbol is defined in this
// input file.
// input file. Sets *IS_COPY to TRUE if the symbol was copied from this
// input file with a COPY relocation.
unsigned int
get_output_symbol_index(unsigned int n, bool* is_def)
get_output_symbol_index(unsigned int n, bool* is_def, bool* is_copy)
{
gold_assert(this->type() == INCREMENTAL_INPUT_SHARED_LIBRARY);
const unsigned char* p = (this->inputs_->p_
+ this->info_offset_ + 8
+ n * 4);
unsigned int output_symndx = Swap32::readval(p);
*is_def = (output_symndx & (1U << 31)) != 0;
return output_symndx & ((1U << 31) - 1);
unsigned int flags = output_symndx >> INCREMENTAL_SHLIB_SYM_FLAGS_SHIFT;
output_symndx &= ((1U << INCREMENTAL_SHLIB_SYM_FLAGS_SHIFT) - 1);
switch (flags)
{
case INCREMENTAL_SHLIB_SYM_DEF:
*is_def = true;
*is_copy = false;
break;
case INCREMENTAL_SHLIB_SYM_COPY:
*is_def = true;
*is_copy = true;
break;
default:
*is_def = false;
*is_copy = false;
}
return output_symndx;
}
private:
@ -1397,6 +1427,11 @@ class Incremental_binary
process_got_plt(Symbol_table* symtab, Layout* layout)
{ this->do_process_got_plt(symtab, layout); }
// Emit COPY relocations from the existing output file.
void
emit_copy_relocs(Symbol_table* symtab)
{ this->do_emit_copy_relocs(symtab); }
// Apply incremental relocations for symbols whose values have changed.
void
apply_incremental_relocs(const Symbol_table* symtab, Layout* layout,
@ -1479,6 +1514,10 @@ class Incremental_binary
virtual void
do_process_got_plt(Symbol_table* symtab, Layout* layout) = 0;
// Emit COPY relocations from the existing output file.
virtual void
do_emit_copy_relocs(Symbol_table* symtab) = 0;
// Apply incremental relocations for symbols whose values have changed.
virtual void
do_apply_incremental_relocs(const Symbol_table*, Layout*, Output_file*) = 0;
@ -1514,9 +1553,9 @@ class Sized_incremental_binary : public Incremental_binary
const elfcpp::Ehdr<size, big_endian>& ehdr,
Target* target)
: Incremental_binary(output, target), elf_file_(this, ehdr),
input_objects_(), section_map_(), symbol_map_(), main_symtab_loc_(),
main_strtab_loc_(), has_incremental_info_(false), inputs_reader_(),
symtab_reader_(), relocs_reader_(), got_plt_reader_(),
input_objects_(), section_map_(), symbol_map_(), copy_relocs_(),
main_symtab_loc_(), main_strtab_loc_(), has_incremental_info_(false),
inputs_reader_(), symtab_reader_(), relocs_reader_(), got_plt_reader_(),
input_entry_readers_()
{ this->setup_readers(); }
@ -1558,6 +1597,11 @@ class Sized_incremental_binary : public Incremental_binary
global_symbol(unsigned int symndx) const
{ return this->symbol_map_[symndx]; }
// Add a COPY relocation for a global symbol.
void
add_copy_reloc(Symbol* gsym, Output_section* os, off_t offset)
{ this->copy_relocs_.push_back(Copy_reloc(gsym, os, offset)); }
// Readers for the incremental info sections.
const Incremental_inputs_reader<size, big_endian>&
@ -1606,6 +1650,10 @@ class Sized_incremental_binary : public Incremental_binary
virtual void
do_process_got_plt(Symbol_table* symtab, Layout* layout);
// Emit COPY relocations from the existing output file.
virtual void
do_emit_copy_relocs(Symbol_table* symtab);
// Apply incremental relocations for symbols whose values have changed.
virtual void
do_apply_incremental_relocs(const Symbol_table* symtab, Layout* layout,
@ -1664,6 +1712,22 @@ class Sized_incremental_binary : public Incremental_binary
}
private:
// List of symbols that need COPY relocations.
struct Copy_reloc
{
Copy_reloc(Symbol* sym, Output_section* os, off_t off)
: symbol(sym), output_section(os), offset(off)
{ }
// The global symbol to copy.
Symbol* symbol;
// The output section into which the symbol was copied.
Output_section* output_section;
// The offset within that output section.
off_t offset;
};
typedef std::vector<Copy_reloc> Copy_relocs;
bool
find_incremental_inputs_sections(unsigned int* p_inputs_shndx,
unsigned int* p_symtab_shndx,
@ -1687,6 +1751,9 @@ class Sized_incremental_binary : public Incremental_binary
// Map global symbols from the input file to the symbol table.
std::vector<Symbol*> symbol_map_;
// List of symbols that need COPY relocations.
Copy_relocs copy_relocs_;
// Locations of the main symbol table and symbol string table.
Location main_symtab_loc_;
Location main_strtab_loc_;