* 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:
parent
b8e9bd6c64
commit
26d3c67de1
|
@ -1,3 +1,41 @@
|
||||||
|
2011-06-07 Cary Coutant <ccoutant@google.com>
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
2011-06-02 Cary Coutant <ccoutant@google.com>
|
2011-06-02 Cary Coutant <ccoutant@google.com>
|
||||||
|
|
||||||
PR gold/12163
|
PR gold/12163
|
||||||
|
|
|
@ -65,7 +65,7 @@ Copy_relocs<sh_type, size, big_endian>::copy_reloc(
|
||||||
Output_data_reloc<sh_type, true, size, big_endian>* reloc_section)
|
Output_data_reloc<sh_type, true, size, big_endian>* reloc_section)
|
||||||
{
|
{
|
||||||
if (this->need_copy_reloc(sym, object, shndx))
|
if (this->need_copy_reloc(sym, object, shndx))
|
||||||
this->emit_copy_reloc(symtab, layout, sym, reloc_section);
|
this->make_copy_reloc(symtab, layout, sym, reloc_section);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We may not need a COPY relocation. Save this relocation to
|
// We may not need a COPY relocation. Save this relocation to
|
||||||
|
@ -105,6 +105,24 @@ Copy_relocs<sh_type, size, big_endian>::need_copy_reloc(
|
||||||
template<int sh_type, int size, bool big_endian>
|
template<int sh_type, int size, bool big_endian>
|
||||||
void
|
void
|
||||||
Copy_relocs<sh_type, size, big_endian>::emit_copy_reloc(
|
Copy_relocs<sh_type, size, big_endian>::emit_copy_reloc(
|
||||||
|
Symbol_table* symtab,
|
||||||
|
Sized_symbol<size>* sym,
|
||||||
|
Output_data* posd,
|
||||||
|
off_t offset,
|
||||||
|
Output_data_reloc<sh_type, true, size, big_endian>* reloc_section)
|
||||||
|
{
|
||||||
|
// Define the symbol as being copied.
|
||||||
|
symtab->define_with_copy_reloc(sym, posd, offset);
|
||||||
|
|
||||||
|
// Add the COPY relocation to the dynamic reloc section.
|
||||||
|
reloc_section->add_global(sym, this->copy_reloc_type_, posd, offset, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a COPY relocation for SYM and emit it.
|
||||||
|
|
||||||
|
template<int sh_type, int size, bool big_endian>
|
||||||
|
void
|
||||||
|
Copy_relocs<sh_type, size, big_endian>::make_copy_reloc(
|
||||||
Symbol_table* symtab,
|
Symbol_table* symtab,
|
||||||
Layout* layout,
|
Layout* layout,
|
||||||
Sized_symbol<size>* sym,
|
Sized_symbol<size>* sym,
|
||||||
|
@ -164,24 +182,7 @@ Copy_relocs<sh_type, size, big_endian>::emit_copy_reloc(
|
||||||
section_size_type offset = dynbss_size;
|
section_size_type offset = dynbss_size;
|
||||||
dynbss->set_current_data_size(dynbss_size + symsize);
|
dynbss->set_current_data_size(dynbss_size + symsize);
|
||||||
|
|
||||||
// Define the symbol as being copied.
|
this->emit_copy_reloc(symtab, sym, dynbss, offset, reloc_section);
|
||||||
symtab->define_with_copy_reloc(sym, dynbss, offset);
|
|
||||||
|
|
||||||
// Add the COPY relocation to the dynamic reloc section.
|
|
||||||
this->add_copy_reloc(sym, offset, reloc_section);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a COPY relocation for SYM to RELOC_SECTION.
|
|
||||||
|
|
||||||
template<int sh_type, int size, bool big_endian>
|
|
||||||
void
|
|
||||||
Copy_relocs<sh_type, size, big_endian>::add_copy_reloc(
|
|
||||||
Symbol* sym,
|
|
||||||
section_size_type offset,
|
|
||||||
Output_data_reloc<sh_type, true, size, big_endian>* reloc_section)
|
|
||||||
{
|
|
||||||
reloc_section->add_global(sym, this->copy_reloc_type_, this->dynbss_,
|
|
||||||
offset, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save a relocation to possibly be emitted later.
|
// Save a relocation to possibly be emitted later.
|
||||||
|
|
|
@ -81,6 +81,12 @@ class Copy_relocs
|
||||||
void
|
void
|
||||||
emit(Output_data_reloc<sh_type, true, size, big_endian>*);
|
emit(Output_data_reloc<sh_type, true, size, big_endian>*);
|
||||||
|
|
||||||
|
// Emit a COPY reloc.
|
||||||
|
void
|
||||||
|
emit_copy_reloc(Symbol_table*, Sized_symbol<size>*,
|
||||||
|
Output_data*, off_t,
|
||||||
|
Output_data_reloc<sh_type, true, size, big_endian>*);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
|
typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
|
||||||
typedef typename elfcpp::Elf_types<size>::Elf_Addr Addend;
|
typedef typename elfcpp::Elf_types<size>::Elf_Addr Addend;
|
||||||
|
@ -126,16 +132,11 @@ class Copy_relocs
|
||||||
Sized_relobj_file<size, big_endian>* object,
|
Sized_relobj_file<size, big_endian>* object,
|
||||||
unsigned int shndx) const;
|
unsigned int shndx) const;
|
||||||
|
|
||||||
// Emit a COPY reloc.
|
// Make a new COPY reloc and emit it.
|
||||||
void
|
void
|
||||||
emit_copy_reloc(Symbol_table*, Layout*, Sized_symbol<size>*,
|
make_copy_reloc(Symbol_table*, Layout*, Sized_symbol<size>*,
|
||||||
Output_data_reloc<sh_type, true, size, big_endian>*);
|
Output_data_reloc<sh_type, true, size, big_endian>*);
|
||||||
|
|
||||||
// Add a COPY reloc to the dynamic reloc section.
|
|
||||||
void
|
|
||||||
add_copy_reloc(Symbol*, section_size_type,
|
|
||||||
Output_data_reloc<sh_type, true, size, big_endian>*);
|
|
||||||
|
|
||||||
// Save a reloc against SYM for possible emission later.
|
// Save a reloc against SYM for possible emission later.
|
||||||
void
|
void
|
||||||
save(Symbol*, Sized_relobj_file<size, big_endian>*, unsigned int shndx,
|
save(Symbol*, Sized_relobj_file<size, big_endian>*, unsigned int shndx,
|
||||||
|
|
|
@ -622,11 +622,13 @@ queue_middle_tasks(const General_options& options,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For incremental updates, record the existing GOT and PLT entries.
|
// For incremental updates, record the existing GOT and PLT entries,
|
||||||
|
// and the COPY relocations.
|
||||||
if (parameters->incremental_update())
|
if (parameters->incremental_update())
|
||||||
{
|
{
|
||||||
Incremental_binary* ibase = layout->incremental_base();
|
Incremental_binary* ibase = layout->incremental_base();
|
||||||
ibase->process_got_plt(symtab, layout);
|
ibase->process_got_plt(symtab, layout);
|
||||||
|
ibase->emit_copy_relocs(symtab);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_debugging_enabled(DEBUG_SCRIPT))
|
if (is_debugging_enabled(DEBUG_SCRIPT))
|
||||||
|
|
|
@ -293,8 +293,9 @@ dump_incremental_inputs(const char* argv0, const char* filename,
|
||||||
for (unsigned int symndx = 0; symndx < nsyms; ++symndx)
|
for (unsigned int symndx = 0; symndx < nsyms; ++symndx)
|
||||||
{
|
{
|
||||||
bool is_def;
|
bool is_def;
|
||||||
|
bool is_copy;
|
||||||
unsigned int output_symndx =
|
unsigned int output_symndx =
|
||||||
input_file.get_output_symbol_index(symndx, &is_def);
|
input_file.get_output_symbol_index(symndx, &is_def, &is_copy);
|
||||||
sym_p = symtab_view.data() + output_symndx * sym_size;
|
sym_p = symtab_view.data() + output_symndx * sym_size;
|
||||||
elfcpp::Sym<size, big_endian> sym(sym_p);
|
elfcpp::Sym<size, big_endian> sym(sym_p);
|
||||||
const char* symname;
|
const char* symname;
|
||||||
|
@ -303,7 +304,7 @@ dump_incremental_inputs(const char* argv0, const char* filename,
|
||||||
printf(" %6d %6s %8s %8s %8s %8s %-5s %s\n",
|
printf(" %6d %6s %8s %8s %8s %8s %-5s %s\n",
|
||||||
output_symndx,
|
output_symndx,
|
||||||
"", "", "", "", "",
|
"", "", "", "", "",
|
||||||
is_def ? "DEF" : "UNDEF",
|
is_copy ? "COPY" : (is_def ? "DEF" : "UNDEF"),
|
||||||
symname);
|
symname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include "gold.h"
|
#include "gold.h"
|
||||||
|
|
||||||
|
#include <set>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include "libiberty.h"
|
#include "libiberty.h"
|
||||||
|
|
||||||
|
@ -518,11 +519,45 @@ void
|
||||||
Sized_incremental_binary<size, big_endian>::do_reserve_layout(
|
Sized_incremental_binary<size, big_endian>::do_reserve_layout(
|
||||||
unsigned int input_file_index)
|
unsigned int input_file_index)
|
||||||
{
|
{
|
||||||
|
const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
|
||||||
|
|
||||||
Input_entry_reader input_file =
|
Input_entry_reader input_file =
|
||||||
this->inputs_reader_.input_file(input_file_index);
|
this->inputs_reader_.input_file(input_file_index);
|
||||||
|
|
||||||
if (input_file.type() == INCREMENTAL_INPUT_SHARED_LIBRARY)
|
if (input_file.type() == INCREMENTAL_INPUT_SHARED_LIBRARY)
|
||||||
return;
|
{
|
||||||
|
// Reserve the BSS space used for COPY relocations.
|
||||||
|
unsigned int nsyms = input_file.get_global_symbol_count();
|
||||||
|
Incremental_binary::View symtab_view(NULL);
|
||||||
|
unsigned int symtab_count;
|
||||||
|
elfcpp::Elf_strtab strtab(NULL, 0);
|
||||||
|
this->get_symtab_view(&symtab_view, &symtab_count, &strtab);
|
||||||
|
for (unsigned int i = 0; i < nsyms; ++i)
|
||||||
|
{
|
||||||
|
bool is_def;
|
||||||
|
bool is_copy;
|
||||||
|
unsigned int output_symndx =
|
||||||
|
input_file.get_output_symbol_index(i, &is_def, &is_copy);
|
||||||
|
if (is_copy)
|
||||||
|
{
|
||||||
|
const unsigned char* sym_p = (symtab_view.data()
|
||||||
|
+ output_symndx * sym_size);
|
||||||
|
elfcpp::Sym<size, big_endian> gsym(sym_p);
|
||||||
|
unsigned int shndx = gsym.get_st_shndx();
|
||||||
|
if (shndx < 1 || shndx >= this->section_map_.size())
|
||||||
|
continue;
|
||||||
|
Output_section* os = this->section_map_[shndx];
|
||||||
|
off_t offset = gsym.get_st_value() - os->address();
|
||||||
|
os->reserve(offset, gsym.get_st_size());
|
||||||
|
gold_debug(DEBUG_INCREMENTAL,
|
||||||
|
"Reserve for COPY reloc: %s, off %d, size %d",
|
||||||
|
os->name(),
|
||||||
|
static_cast<int>(offset),
|
||||||
|
static_cast<int>(gsym.get_st_size()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int shnum = input_file.get_input_section_count();
|
unsigned int shnum = input_file.get_input_section_count();
|
||||||
for (unsigned int i = 0; i < shnum; i++)
|
for (unsigned int i = 0; i < shnum; i++)
|
||||||
|
@ -616,6 +651,26 @@ Sized_incremental_binary<size, big_endian>::do_process_got_plt(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emit COPY relocations from the existing output file.
|
||||||
|
|
||||||
|
template<int size, bool big_endian>
|
||||||
|
void
|
||||||
|
Sized_incremental_binary<size, big_endian>::do_emit_copy_relocs(
|
||||||
|
Symbol_table* symtab)
|
||||||
|
{
|
||||||
|
Sized_target<size, big_endian>* target =
|
||||||
|
parameters->sized_target<size, big_endian>();
|
||||||
|
|
||||||
|
for (typename Copy_relocs::iterator p = this->copy_relocs_.begin();
|
||||||
|
p != this->copy_relocs_.end();
|
||||||
|
++p)
|
||||||
|
{
|
||||||
|
if (!(*p).symbol->is_copied_from_dynobj())
|
||||||
|
target->emit_copy_reloc(symtab, (*p).symbol, (*p).output_section,
|
||||||
|
(*p).offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Apply incremental relocations for symbols whose values have changed.
|
// Apply incremental relocations for symbols whose values have changed.
|
||||||
|
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
|
@ -1545,7 +1600,9 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
|
||||||
== (*p)->get_info_offset());
|
== (*p)->get_info_offset());
|
||||||
Incremental_dynobj_entry* entry = (*p)->dynobj_entry();
|
Incremental_dynobj_entry* entry = (*p)->dynobj_entry();
|
||||||
gold_assert(entry != NULL);
|
gold_assert(entry != NULL);
|
||||||
const Object* obj = entry->object();
|
Object* obj = entry->object();
|
||||||
|
Dynobj* dynobj = obj->dynobj();
|
||||||
|
gold_assert(dynobj != NULL);
|
||||||
const Object::Symbols* syms = obj->get_global_symbols();
|
const Object::Symbols* syms = obj->get_global_symbols();
|
||||||
|
|
||||||
// Write the soname string table index.
|
// Write the soname string table index.
|
||||||
|
@ -1570,12 +1627,16 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
|
||||||
sym = this->symtab_->resolve_forwards(sym);
|
sym = this->symtab_->resolve_forwards(sym);
|
||||||
if (sym->symtab_index() == -1U)
|
if (sym->symtab_index() == -1U)
|
||||||
continue;
|
continue;
|
||||||
unsigned int def_flag = 0;
|
unsigned int flags = 0;
|
||||||
if (sym->source() == Symbol::FROM_OBJECT
|
if (sym->source() == Symbol::FROM_OBJECT
|
||||||
&& sym->object() == obj
|
&& sym->object() == obj
|
||||||
&& sym->is_defined())
|
&& sym->is_defined())
|
||||||
def_flag = 1U << 31;
|
flags = INCREMENTAL_SHLIB_SYM_DEF;
|
||||||
Swap32::writeval(pov, sym->symtab_index() | def_flag);
|
else if (sym->is_copied_from_dynobj()
|
||||||
|
&& this->symtab_->get_copy_source(sym) == dynobj)
|
||||||
|
flags = INCREMENTAL_SHLIB_SYM_COPY;
|
||||||
|
flags <<= INCREMENTAL_SHLIB_SYM_FLAGS_SHIFT;
|
||||||
|
Swap32::writeval(pov, sym->symtab_index() | flags);
|
||||||
pov += 4;
|
pov += 4;
|
||||||
++nsyms_out;
|
++nsyms_out;
|
||||||
}
|
}
|
||||||
|
@ -2481,19 +2542,26 @@ Sized_incr_dynobj<size, big_endian>::do_add_symbols(
|
||||||
unsigned int isym_count = isymtab.symbol_count();
|
unsigned int isym_count = isymtab.symbol_count();
|
||||||
unsigned int first_global = symtab_count - isym_count;
|
unsigned int first_global = symtab_count - isym_count;
|
||||||
|
|
||||||
|
// We keep a set of symbols that we have generated COPY relocations
|
||||||
|
// for, indexed by the symbol value. We do not need more than one
|
||||||
|
// COPY relocation per address.
|
||||||
|
typedef typename std::set<Address> Copied_symbols;
|
||||||
|
Copied_symbols copied_symbols;
|
||||||
|
|
||||||
const unsigned char* sym_p;
|
const unsigned char* sym_p;
|
||||||
for (unsigned int i = 0; i < nsyms; ++i)
|
for (unsigned int i = 0; i < nsyms; ++i)
|
||||||
{
|
{
|
||||||
bool is_def;
|
bool is_def;
|
||||||
|
bool is_copy;
|
||||||
unsigned int output_symndx =
|
unsigned int output_symndx =
|
||||||
this->input_reader_.get_output_symbol_index(i, &is_def);
|
this->input_reader_.get_output_symbol_index(i, &is_def, &is_copy);
|
||||||
sym_p = symtab_view.data() + output_symndx * sym_size;
|
sym_p = symtab_view.data() + output_symndx * sym_size;
|
||||||
elfcpp::Sym<size, big_endian> gsym(sym_p);
|
elfcpp::Sym<size, big_endian> gsym(sym_p);
|
||||||
const char* name;
|
const char* name;
|
||||||
if (!strtab.get_c_string(gsym.get_st_name(), &name))
|
if (!strtab.get_c_string(gsym.get_st_name(), &name))
|
||||||
name = "";
|
name = "";
|
||||||
|
|
||||||
typename elfcpp::Elf_types<size>::Elf_Addr v;
|
Address v;
|
||||||
unsigned int shndx;
|
unsigned int shndx;
|
||||||
elfcpp::STB st_bind = gsym.get_st_bind();
|
elfcpp::STB st_bind = gsym.get_st_bind();
|
||||||
elfcpp::STT st_type = gsym.get_st_type();
|
elfcpp::STT st_type = gsym.get_st_type();
|
||||||
|
@ -2523,10 +2591,24 @@ Sized_incr_dynobj<size, big_endian>::do_add_symbols(
|
||||||
osym.put_st_other(gsym.get_st_other());
|
osym.put_st_other(gsym.get_st_other());
|
||||||
osym.put_st_shndx(shndx);
|
osym.put_st_shndx(shndx);
|
||||||
|
|
||||||
this->symbols_[i] =
|
Sized_symbol<size>* res =
|
||||||
symtab->add_from_incrobj<size, big_endian>(this, name, NULL, &sym);
|
symtab->add_from_incrobj<size, big_endian>(this, name, NULL, &sym);
|
||||||
|
this->symbols_[i] = res;
|
||||||
this->ibase_->add_global_symbol(output_symndx - first_global,
|
this->ibase_->add_global_symbol(output_symndx - first_global,
|
||||||
this->symbols_[i]);
|
this->symbols_[i]);
|
||||||
|
|
||||||
|
if (is_copy)
|
||||||
|
{
|
||||||
|
std::pair<typename Copied_symbols::iterator, bool> ins =
|
||||||
|
copied_symbols.insert(v);
|
||||||
|
if (ins.second)
|
||||||
|
{
|
||||||
|
unsigned int shndx = gsym.get_st_shndx();
|
||||||
|
Output_section* os = this->ibase_->output_section(shndx);
|
||||||
|
off_t offset = v - os->address();
|
||||||
|
this->ibase_->add_copy_reloc(this->symbols_[i], os, offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,20 @@ enum Incremental_input_flags
|
||||||
INCREMENTAL_INPUT_AS_NEEDED = 0x4000
|
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
|
// 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.
|
// 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
|
// 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
|
// 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
|
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);
|
gold_assert(this->type() == INCREMENTAL_INPUT_SHARED_LIBRARY);
|
||||||
const unsigned char* p = (this->inputs_->p_
|
const unsigned char* p = (this->inputs_->p_
|
||||||
+ this->info_offset_ + 8
|
+ this->info_offset_ + 8
|
||||||
+ n * 4);
|
+ n * 4);
|
||||||
unsigned int output_symndx = Swap32::readval(p);
|
unsigned int output_symndx = Swap32::readval(p);
|
||||||
*is_def = (output_symndx & (1U << 31)) != 0;
|
unsigned int flags = output_symndx >> INCREMENTAL_SHLIB_SYM_FLAGS_SHIFT;
|
||||||
return output_symndx & ((1U << 31) - 1);
|
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:
|
private:
|
||||||
|
@ -1397,6 +1427,11 @@ class Incremental_binary
|
||||||
process_got_plt(Symbol_table* symtab, Layout* layout)
|
process_got_plt(Symbol_table* symtab, Layout* layout)
|
||||||
{ this->do_process_got_plt(symtab, 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.
|
// Apply incremental relocations for symbols whose values have changed.
|
||||||
void
|
void
|
||||||
apply_incremental_relocs(const Symbol_table* symtab, Layout* layout,
|
apply_incremental_relocs(const Symbol_table* symtab, Layout* layout,
|
||||||
|
@ -1479,6 +1514,10 @@ class Incremental_binary
|
||||||
virtual void
|
virtual void
|
||||||
do_process_got_plt(Symbol_table* symtab, Layout* layout) = 0;
|
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.
|
// Apply incremental relocations for symbols whose values have changed.
|
||||||
virtual void
|
virtual void
|
||||||
do_apply_incremental_relocs(const Symbol_table*, Layout*, Output_file*) = 0;
|
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,
|
const elfcpp::Ehdr<size, big_endian>& ehdr,
|
||||||
Target* target)
|
Target* target)
|
||||||
: Incremental_binary(output, target), elf_file_(this, ehdr),
|
: Incremental_binary(output, target), elf_file_(this, ehdr),
|
||||||
input_objects_(), section_map_(), symbol_map_(), main_symtab_loc_(),
|
input_objects_(), section_map_(), symbol_map_(), copy_relocs_(),
|
||||||
main_strtab_loc_(), has_incremental_info_(false), inputs_reader_(),
|
main_symtab_loc_(), main_strtab_loc_(), has_incremental_info_(false),
|
||||||
symtab_reader_(), relocs_reader_(), got_plt_reader_(),
|
inputs_reader_(), symtab_reader_(), relocs_reader_(), got_plt_reader_(),
|
||||||
input_entry_readers_()
|
input_entry_readers_()
|
||||||
{ this->setup_readers(); }
|
{ this->setup_readers(); }
|
||||||
|
|
||||||
|
@ -1558,6 +1597,11 @@ class Sized_incremental_binary : public Incremental_binary
|
||||||
global_symbol(unsigned int symndx) const
|
global_symbol(unsigned int symndx) const
|
||||||
{ return this->symbol_map_[symndx]; }
|
{ 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.
|
// Readers for the incremental info sections.
|
||||||
|
|
||||||
const Incremental_inputs_reader<size, big_endian>&
|
const Incremental_inputs_reader<size, big_endian>&
|
||||||
|
@ -1606,6 +1650,10 @@ class Sized_incremental_binary : public Incremental_binary
|
||||||
virtual void
|
virtual void
|
||||||
do_process_got_plt(Symbol_table* symtab, Layout* layout);
|
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.
|
// Apply incremental relocations for symbols whose values have changed.
|
||||||
virtual void
|
virtual void
|
||||||
do_apply_incremental_relocs(const Symbol_table* symtab, Layout* layout,
|
do_apply_incremental_relocs(const Symbol_table* symtab, Layout* layout,
|
||||||
|
@ -1664,6 +1712,22 @@ class Sized_incremental_binary : public Incremental_binary
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
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
|
bool
|
||||||
find_incremental_inputs_sections(unsigned int* p_inputs_shndx,
|
find_incremental_inputs_sections(unsigned int* p_inputs_shndx,
|
||||||
unsigned int* p_symtab_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.
|
// Map global symbols from the input file to the symbol table.
|
||||||
std::vector<Symbol*> symbol_map_;
|
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.
|
// Locations of the main symbol table and symbol string table.
|
||||||
Location main_symtab_loc_;
|
Location main_symtab_loc_;
|
||||||
Location main_strtab_loc_;
|
Location main_strtab_loc_;
|
||||||
|
|
|
@ -1489,7 +1489,7 @@ Symbol_table::add_from_dynobj(
|
||||||
// Add a symbol from a incremental object file.
|
// Add a symbol from a incremental object file.
|
||||||
|
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
Symbol*
|
Sized_symbol<size>*
|
||||||
Symbol_table::add_from_incrobj(
|
Symbol_table::add_from_incrobj(
|
||||||
Object* obj,
|
Object* obj,
|
||||||
const char* name,
|
const char* name,
|
||||||
|
@ -3453,7 +3453,7 @@ Symbol_table::add_from_dynobj<64, true>(
|
||||||
|
|
||||||
#ifdef HAVE_TARGET_32_LITTLE
|
#ifdef HAVE_TARGET_32_LITTLE
|
||||||
template
|
template
|
||||||
Symbol*
|
Sized_symbol<32>*
|
||||||
Symbol_table::add_from_incrobj(
|
Symbol_table::add_from_incrobj(
|
||||||
Object* obj,
|
Object* obj,
|
||||||
const char* name,
|
const char* name,
|
||||||
|
@ -3463,7 +3463,7 @@ Symbol_table::add_from_incrobj(
|
||||||
|
|
||||||
#ifdef HAVE_TARGET_32_BIG
|
#ifdef HAVE_TARGET_32_BIG
|
||||||
template
|
template
|
||||||
Symbol*
|
Sized_symbol<32>*
|
||||||
Symbol_table::add_from_incrobj(
|
Symbol_table::add_from_incrobj(
|
||||||
Object* obj,
|
Object* obj,
|
||||||
const char* name,
|
const char* name,
|
||||||
|
@ -3473,7 +3473,7 @@ Symbol_table::add_from_incrobj(
|
||||||
|
|
||||||
#ifdef HAVE_TARGET_64_LITTLE
|
#ifdef HAVE_TARGET_64_LITTLE
|
||||||
template
|
template
|
||||||
Symbol*
|
Sized_symbol<64>*
|
||||||
Symbol_table::add_from_incrobj(
|
Symbol_table::add_from_incrobj(
|
||||||
Object* obj,
|
Object* obj,
|
||||||
const char* name,
|
const char* name,
|
||||||
|
@ -3483,7 +3483,7 @@ Symbol_table::add_from_incrobj(
|
||||||
|
|
||||||
#ifdef HAVE_TARGET_64_BIG
|
#ifdef HAVE_TARGET_64_BIG
|
||||||
template
|
template
|
||||||
Symbol*
|
Sized_symbol<64>*
|
||||||
Symbol_table::add_from_incrobj(
|
Symbol_table::add_from_incrobj(
|
||||||
Object* obj,
|
Object* obj,
|
||||||
const char* name,
|
const char* name,
|
||||||
|
|
|
@ -1341,7 +1341,7 @@ class Symbol_table
|
||||||
// Add one external symbol from the incremental object OBJ to the symbol
|
// Add one external symbol from the incremental object OBJ to the symbol
|
||||||
// table. Returns a pointer to the resolved symbol in the symbol table.
|
// table. Returns a pointer to the resolved symbol in the symbol table.
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
Symbol*
|
Sized_symbol<size>*
|
||||||
add_from_incrobj(Object* obj, const char* name,
|
add_from_incrobj(Object* obj, const char* name,
|
||||||
const char* ver, elfcpp::Sym<size, big_endian>* sym);
|
const char* ver, elfcpp::Sym<size, big_endian>* sym);
|
||||||
|
|
||||||
|
|
|
@ -833,6 +833,13 @@ class Sized_target : public Target
|
||||||
Symbol*)
|
Symbol*)
|
||||||
{ gold_unreachable(); }
|
{ gold_unreachable(); }
|
||||||
|
|
||||||
|
// Force a COPY relocation for a given symbol.
|
||||||
|
// A target needs to implement this to support incremental linking.
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
emit_copy_reloc(Symbol_table*, Symbol*, Output_section*, off_t)
|
||||||
|
{ gold_unreachable(); }
|
||||||
|
|
||||||
// Apply an incremental relocation.
|
// Apply an incremental relocation.
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
|
|
|
@ -405,10 +405,13 @@ class Target_x86_64 : public Target_freebsd<64, false>
|
||||||
unsigned int got_type);
|
unsigned int got_type);
|
||||||
|
|
||||||
// Register an existing PLT entry for a global symbol.
|
// Register an existing PLT entry for a global symbol.
|
||||||
// A target needs to implement this to support incremental linking.
|
|
||||||
void
|
void
|
||||||
register_global_plt_entry(unsigned int plt_index, Symbol* gsym);
|
register_global_plt_entry(unsigned int plt_index, Symbol* gsym);
|
||||||
|
|
||||||
|
// Force a COPY relocation for a given symbol.
|
||||||
|
void
|
||||||
|
emit_copy_reloc(Symbol_table*, Symbol*, Output_section*, off_t);
|
||||||
|
|
||||||
// Apply an incremental relocation.
|
// Apply an incremental relocation.
|
||||||
void
|
void
|
||||||
apply_relocation(const Relocate_info<64, false>* relinfo,
|
apply_relocation(const Relocate_info<64, false>* relinfo,
|
||||||
|
@ -1389,6 +1392,19 @@ Target_x86_64::register_global_plt_entry(unsigned int plt_index,
|
||||||
this->plt_->add_relocation(gsym, got_offset);
|
this->plt_->add_relocation(gsym, got_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Force a COPY relocation for a given symbol.
|
||||||
|
|
||||||
|
void
|
||||||
|
Target_x86_64::emit_copy_reloc(
|
||||||
|
Symbol_table* symtab, Symbol* sym, Output_section* os, off_t offset)
|
||||||
|
{
|
||||||
|
this->copy_relocs_.emit_copy_reloc(symtab,
|
||||||
|
symtab->get_sized_symbol<64>(sym),
|
||||||
|
os,
|
||||||
|
offset,
|
||||||
|
this->rela_dyn_section(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
// Define the _TLS_MODULE_BASE_ symbol in the TLS segment.
|
// Define the _TLS_MODULE_BASE_ symbol in the TLS segment.
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Reference in New Issue