URL
https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk
Subversion Repositories open8_urisc
Compare Revisions
- This comparison shows the changes necessary to convert path
/open8_urisc/trunk/gnu/binutils/gold
- from Rev 27 to Rev 148
- ↔ Reverse comparison
Rev 27 → Rev 148
/errors.h
49,6 → 49,12
void |
fatal(const char* format, va_list) ATTRIBUTE_NORETURN; |
|
// Report a fallback error. After printing the error, this must exit |
// with a special status code indicating that fallback to |
// --incremental-full is required. |
void |
fallback(const char* format, va_list) ATTRIBUTE_NORETURN; |
|
// Report an error and continue. |
void |
error(const char* format, va_list); |
/main.cc
291,6 → 291,8
|
// If the user used --noinhibit-exec, we force the exit status to be |
// successful. This is compatible with GNU ld. |
gold_exit(errors.error_count() == 0 |
|| parameters->options().noinhibit_exec()); |
gold_exit((errors.error_count() == 0 |
|| parameters->options().noinhibit_exec()) |
? GOLD_OK |
: GOLD_ERR); |
} |
/gold.cc
58,15 → 58,15
Task_token*, Task_token*); |
|
void |
gold_exit(bool status) |
gold_exit(Exit_status status) |
{ |
if (parameters != NULL |
&& parameters->options_valid() |
&& parameters->options().has_plugins()) |
parameters->options().plugins()->cleanup(); |
if (!status && parameters != NULL && parameters->options_valid()) |
if (status != GOLD_OK && parameters != NULL && parameters->options_valid()) |
unlink_if_ordinary(parameters->options().output_file_name()); |
exit(status ? EXIT_SUCCESS : EXIT_FAILURE); |
exit(status); |
} |
|
void |
87,7 → 87,7
const char* const s = ": out of memory\n"; |
len = write(2, s, strlen(s)); |
} |
gold_exit(false); |
gold_exit(GOLD_ERR); |
} |
|
// Handle an unreachable case. |
97,7 → 97,7
{ |
fprintf(stderr, _("%s: internal error in %s, at %s:%d\n"), |
program_name, function, filename, lineno); |
gold_exit(false); |
gold_exit(GOLD_ERR); |
} |
|
// This class arranges to run the functions done in the middle of the |
176,7 → 176,7
if (cmdline.begin() == cmdline.end()) |
{ |
if (options.printed_version()) |
gold_exit(true); |
gold_exit(GOLD_OK); |
gold_fatal(_("no input files")); |
} |
|
200,6 → 200,9
gold_error(_("incremental linking is incompatible with --icf")); |
if (options.has_plugins()) |
gold_error(_("incremental linking is incompatible with --plugin")); |
if (strcmp(options.compress_debug_sections(), "none") != 0) |
gold_error(_("incremental linking is incompatible with " |
"--compress-debug-sections")); |
|
if (parameters->incremental_update()) |
{ |
222,7 → 225,7
if (set_parameters_incremental_full()) |
gold_info(_("linking with --incremental-full")); |
else |
gold_fatal(_("restart link with --incremental-full")); |
gold_fallback(_("restart link with --incremental-full")); |
} |
} |
} |
622,11 → 625,13
} |
} |
|
// 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()) |
{ |
Incremental_binary* ibase = layout->incremental_base(); |
ibase->process_got_plt(symtab, layout); |
ibase->emit_copy_relocs(symtab); |
} |
|
if (is_debugging_enabled(DEBUG_SCRIPT)) |
746,7 → 751,7
// THIS_BLOCKER to be NULL here. There's no real point in |
// continuing if that happens. |
gold_assert(parameters->errors()->error_count() > 0); |
gold_exit(false); |
gold_exit(GOLD_ERR); |
} |
} |
|
/common.cc
286,12 → 286,23
gold_unreachable(); |
} |
|
Output_data_space* poc = new Output_data_space(addralign, ds_name); |
Output_section* os = layout->add_output_section_data(name, |
elfcpp::SHT_NOBITS, |
flags, poc, |
ORDER_INVALID, |
false); |
Output_data_space* poc; |
Output_section* os; |
|
if (!parameters->incremental_update()) |
{ |
poc = new Output_data_space(addralign, ds_name); |
os = layout->add_output_section_data(name, elfcpp::SHT_NOBITS, flags, |
poc, ORDER_INVALID, false); |
} |
else |
{ |
// When doing an incremental update, we need to allocate each common |
// directly from the output section's free list. |
poc = NULL; |
os = layout->find_output_section(name); |
} |
|
if (os != NULL) |
{ |
if (commons_section_type == COMMONS_SMALL) |
329,12 → 340,26
if (mapfile != NULL) |
mapfile->report_allocate_common(sym, ssym->symsize()); |
|
off = align_address(off, ssym->value()); |
ssym->allocate_common(poc, off); |
off += ssym->symsize(); |
if (poc != NULL) |
{ |
off = align_address(off, ssym->value()); |
ssym->allocate_common(poc, off); |
off += ssym->symsize(); |
} |
else |
{ |
// For an incremental update, allocate from the free list. |
off = os->allocate(ssym->symsize(), ssym->value()); |
if (off == -1) |
gold_fallback(_("out of patch space in section %s; " |
"relink with --incremental-full"), |
os->name()); |
ssym->allocate_common(os, off); |
} |
} |
|
poc->set_current_data_size(off); |
if (poc != NULL) |
poc->set_current_data_size(off); |
|
commons->clear(); |
} |
/incremental.cc
22,6 → 22,7
|
#include "gold.h" |
|
#include <set> |
#include <cstdarg> |
#include "libiberty.h" |
|
518,11 → 519,45
Sized_incremental_binary<size, big_endian>::do_reserve_layout( |
unsigned int input_file_index) |
{ |
const int sym_size = elfcpp::Elf_sizes<size>::sym_size; |
|
Input_entry_reader input_file = |
this->inputs_reader_.input_file(input_file_index); |
|
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(); |
for (unsigned int i = 0; i < shnum; i++) |
595,10 → 630,14
// FIXME: This should really be a fatal error (corrupt input). |
gold_assert(symndx >= first_global && symndx < symtab_count); |
Symbol* sym = this->global_symbol(symndx - first_global); |
gold_debug(DEBUG_INCREMENTAL, |
"GOT entry %d, type %02x: %s", |
i, got_type, sym->name()); |
target->reserve_global_got_entry(i, sym, got_type); |
// Add the GOT entry only if the symbol is still referenced. |
if (sym != NULL && sym->in_reg()) |
{ |
gold_debug(DEBUG_INCREMENTAL, |
"GOT entry %d, type %02x: %s", |
i, got_type, sym->name()); |
target->reserve_global_got_entry(i, sym, got_type); |
} |
} |
} |
|
609,13 → 648,37
// FIXME: This should really be a fatal error (corrupt input). |
gold_assert(plt_desc >= first_global && plt_desc < symtab_count); |
Symbol* sym = this->global_symbol(plt_desc - first_global); |
gold_debug(DEBUG_INCREMENTAL, |
"PLT entry %d: %s", |
i, sym->name()); |
target->register_global_plt_entry(i, sym); |
// Add the PLT entry only if the symbol is still referenced. |
if (sym->in_reg()) |
{ |
gold_debug(DEBUG_INCREMENTAL, |
"PLT entry %d: %s", |
i, sym->name()); |
target->register_global_plt_entry(i, sym); |
} |
} |
} |
|
// 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. |
|
template<int size, bool big_endian> |
1493,14 → 1556,24
if (sym->is_forwarder()) |
sym = this->symtab_->resolve_forwards(sym); |
unsigned int shndx = 0; |
if (sym->source() == Symbol::FROM_OBJECT |
&& sym->object() == obj |
&& sym->is_defined()) |
if (sym->source() != Symbol::FROM_OBJECT) |
{ |
// The symbol was defined by the linker (e.g., common). |
// We mark these symbols with a special SHNDX of -1, |
// but exclude linker-predefined symbols and symbols |
// copied from shared objects. |
if (!sym->is_predefined() |
&& !sym->is_copied_from_dynobj()) |
shndx = -1U; |
} |
else if (sym->object() == obj && sym->is_defined()) |
{ |
bool is_ordinary; |
unsigned int orig_shndx = sym->shndx(&is_ordinary); |
if (is_ordinary) |
shndx = index_map[orig_shndx]; |
else |
shndx = 1; |
} |
unsigned int symtab_index = sym->symtab_index(); |
unsigned int chain = 0; |
1545,7 → 1618,9
== (*p)->get_info_offset()); |
Incremental_dynobj_entry* entry = (*p)->dynobj_entry(); |
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(); |
|
// Write the soname string table index. |
1570,12 → 1645,16
sym = this->symtab_->resolve_forwards(sym); |
if (sym->symtab_index() == -1U) |
continue; |
unsigned int def_flag = 0; |
unsigned int flags = 0; |
if (sym->source() == Symbol::FROM_OBJECT |
&& sym->object() == obj |
&& sym->is_defined()) |
def_flag = 1U << 31; |
Swap32::writeval(pov, sym->symtab_index() | def_flag); |
flags = INCREMENTAL_SHLIB_SYM_DEF; |
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; |
++nsyms_out; |
} |
1965,7 → 2044,7
st_bind = elfcpp::STB_GLOBAL; |
|
unsigned int input_shndx = info.shndx(); |
if (input_shndx == 0) |
if (input_shndx == 0 || input_shndx == -1U) |
{ |
shndx = elfcpp::SHN_UNDEF; |
v = 0; |
1992,10 → 2071,40
osym.put_st_other(gsym.get_st_other()); |
osym.put_st_shndx(shndx); |
|
this->symbols_[i] = |
symtab->add_from_incrobj(this, name, NULL, &sym); |
this->ibase_->add_global_symbol(output_symndx - first_global, |
this->symbols_[i]); |
Symbol* res = symtab->add_from_incrobj(this, name, NULL, &sym); |
|
// If this is a linker-defined symbol that hasn't yet been defined, |
// define it now. |
if (input_shndx == -1U && !res->is_defined()) |
{ |
shndx = gsym.get_st_shndx(); |
v = gsym.get_st_value(); |
Elf_size_type symsize = gsym.get_st_size(); |
if (shndx == elfcpp::SHN_ABS) |
{ |
symtab->define_as_constant(name, NULL, |
Symbol_table::INCREMENTAL_BASE, |
v, symsize, st_type, st_bind, |
gsym.get_st_visibility(), 0, |
false, false); |
} |
else |
{ |
Output_section* os = this->ibase_->output_section(shndx); |
gold_assert(os != NULL && os->has_fixed_layout()); |
v -= os->address(); |
if (symsize > 0) |
os->reserve(v, symsize); |
symtab->define_in_output_data(name, NULL, |
Symbol_table::INCREMENTAL_BASE, |
os, v, symsize, st_type, st_bind, |
gsym.get_st_visibility(), 0, |
false, false); |
} |
} |
|
this->symbols_[i] = res; |
this->ibase_->add_global_symbol(output_symndx - first_global, res); |
} |
} |
|
2481,12 → 2590,19
unsigned int isym_count = isymtab.symbol_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; |
for (unsigned int i = 0; i < nsyms; ++i) |
{ |
bool is_def; |
bool is_copy; |
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; |
elfcpp::Sym<size, big_endian> gsym(sym_p); |
const char* name; |
2493,7 → 2609,7
if (!strtab.get_c_string(gsym.get_st_name(), &name)) |
name = ""; |
|
typename elfcpp::Elf_types<size>::Elf_Addr v; |
Address v; |
unsigned int shndx; |
elfcpp::STB st_bind = gsym.get_st_bind(); |
elfcpp::STT st_type = gsym.get_st_type(); |
2523,10 → 2639,24
osym.put_st_other(gsym.get_st_other()); |
osym.put_st_shndx(shndx); |
|
this->symbols_[i] = |
symtab->add_from_incrobj<size, big_endian>(this, name, NULL, &sym); |
Sized_symbol<size>* res = |
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->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); |
} |
} |
} |
} |
|
/ChangeLog
1,3 → 1,139
2011-06-09 Ian Lance Taylor <iant@google.com> |
|
* script-sections.cc |
(Orphan_output_section::set_section_addresses): For a relocatable |
link set address to 0. |
|
2011-06-09 Cary Coutant <ccoutant@google.com> |
|
PR gold/12804 |
* gold/gold.cc (queue_initial_tasks): Warn if --incremental is |
used with --compress-debug-sections. |
* gold/object.cc (Sized_relobj_file::do_layout): Report |
uncompressed size of compressed input sections. |
|
2011-06-08 Cary Coutant <ccoutant@google.com> |
|
PR gold/12804 |
* testsuite/two_file_test_2_v1.cc: Change initialization of |
v2 to keep it in .data. |
|
2011-06-07 Cary Coutant <ccoutant@google.com> |
|
* common.cc (Symbol_table::do_allocate_commons_list): Call |
gold_fallback. |
* errors.cc (Errors::fatal): Adjust call to gold_exit. |
(Errors::fallback): New function. |
(gold_fallback): New function. |
* errors.h (Errors::fallback): New function. |
* gold.cc (gold_exit): Change status parameter to enum; adjust |
all callers. |
(queue_initial_tasks): Call gold_fallback. |
* gold.h: Include cstdlib. |
(Exit_status): New enum type. |
(gold_exit): Change status parameter to enum. |
(gold_fallback): New function. |
* layout.cc (Layout::set_section_offsets): Call gold_fallback. |
(Layout::create_symtab_sections): Likewise. |
(Layout::create_shdrs): Likewise. |
* main.cc (main): Adjust call to gold_exit. |
* output.cc (Output_data_got::add_got_entry): Call gold_fallback. |
(Output_data_got::add_got_entry_pair): Likewise. |
(Output_section::add_input_section): Likewise. |
(Output_section::add_output_section_data): Likewise. |
(Output_segment::set_section_list_addresses): Likewise. |
* x86_64.cc (Output_data_plt_x86_64::add_entry): Likewise. |
|
2011-06-07 Cary Coutant <ccoutant@google.com> |
|
* layout.cc (Layout::set_segment_offsets): Don't adjust layout |
for incremental links. |
* output.cc (Output_segment::set_section_list_addresses): Remove |
FIXME and test for TLS or BSS. |
|
2011-06-07 Cary Coutant <ccoutant@google.com> |
|
* testsuite/Makefile.am: Add incremental_copy_test, |
incremental_common_test_1. |
* testsuite/Makefile.in: Regenerate. |
* testsuite/common_test_1_v1.c: New source file. |
* testsuite/common_test_1_v2.c: New source file. |
* testsuite/copy_test_v1.cc: New source file. |
|
2011-06-07 Cary Coutant <ccoutant@google.com> |
|
* common.cc (Symbol_table::do_allocate_commons_list): For incremental |
update, allocate common from bss section's free list. |
* incremental-dump.cc (dump_incremental_inputs): Print flag for |
linker-defined symbols. |
* incremental.cc (Sized_incremental_binary::do_process_got_plt): |
Skip GOT and PLT entries that are no longer referenced. |
(Output_section_incremental_inputs::write_info_blocks): Mark |
linker-defined symbols. |
(Sized_incr_relobj::do_add_symbols): Process linker-defined symbols. |
* output.cc (Output_section::allocate): New function. |
* output.h (Output_section::allocate): New function. |
* resolve.cc (Symbol_table::report_resolve_problem): Add case for |
linker-defined symbols. |
(Symbol::override_base_with_special): Copy is_predefined_ flag. |
* symtab.cc (Symbol::init_fields): Initialize is_predefined_ flag. |
(Symbol::init_base_output_data): Likewise. |
(Symbol::init_base_output_segment): Likewise. |
(Symbol::init_base_constant): Likewise. |
(Sized_symbol::init_output_data): Likewise. |
(Sized_symbol::init_output_segment): Likewise. |
(Sized_symbol::init_constant): Likewise. |
(Symbol_table::do_define_in_output_data): Likewise. |
(Symbol_table::do_define_in_output_segment): Likewise. |
(Symbol_table::do_define_as_constant): Likewise. |
* symtab.h (Symbol::is_predefined): New function. |
(Symbol::init_base_output_data): Add is_predefined parameter. |
(Symbol::init_base_output_segment): Likewise. |
(Symbol::init_base_constant): Likewise. |
(Symbol::is_predefined_): New data member. |
(Sized_symbol::init_output_data): Add is_predefined parameter. |
(Sized_symbol::init_output_segment): Likewise. |
(Sized_symbol::init_constant): Likewise. |
(enum Symbol_table::Defined): Add INCREMENTAL_BASE. |
|
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> |
|
PR gold/12163 |
/testsuite/copy_test_v1.cc
0,0 → 1,47
// copy_test_v1.cc -- test copy relocs for gold |
|
// Copyright 2008, 2011 Free Software Foundation, Inc. |
// Written by Ian Lance Taylor <iant@google.com>. |
|
// This file is part of gold. |
|
// This program is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3 of the License, or |
// (at your option) any later version. |
|
// This program is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
|
// You should have received a copy of the GNU General Public License |
// along with this program; if not, write to the Free Software |
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
// MA 02110-1301, USA. |
|
// This source file is used for testing the --incremental option. |
// The object built from this source will be incrementally updated |
// with the correct object built from copy_test.cc. |
|
#include <cassert> |
#include <stdint.h> |
|
// Misalign the BSS section. |
static char c; |
|
// From copy_test_1.cc. |
extern char b; |
|
// From copy_test_2.cc. |
extern long long l; |
|
int |
main() |
{ |
assert(c == 0); |
assert(b == 1); |
assert(l == 3); // Deliberately incorrect. |
assert((reinterpret_cast<uintptr_t>(&l) & 0x7) == 0); |
return 0; |
} |
/testsuite/Makefile.am
1851,6 → 1851,22
cp -f two_file_test_2.o two_file_test_tmp_4.o |
$(CXXLINK) -Wl,--incremental-update,--incremental-base=incremental_test_4.base -Bgcctestdir/ two_file_test_1.o two_file_test_1b.o two_file_test_tmp_4.o two_file_test_main.o |
|
check_PROGRAMS += incremental_copy_test |
incremental_copy_test: copy_test_v1.o copy_test.o copy_test_1.so copy_test_2.so |
cp -f copy_test_v1.o copy_test_tmp.o |
$(CXXLINK) -Wl,--incremental-full -Bgcctestdir/ -Wl,-R,. copy_test_tmp.o copy_test_1.so copy_test_2.so |
@sleep 1 |
cp -f copy_test.o copy_test_tmp.o |
$(CXXLINK) -Wl,--incremental-update -Bgcctestdir/ -Wl,-R,. copy_test_tmp.o copy_test_1.so copy_test_2.so |
|
check_PROGRAMS += incremental_common_test_1 |
incremental_common_test_1: common_test_1_v1.o common_test_1_v2.o gcctestdir/ld |
cp -f common_test_1_v1.o common_test_1_tmp.o |
$(CXXLINK) -Wl,--incremental-full -Bgcctestdir/ common_test_1_tmp.o |
@sleep 1 |
cp -f common_test_1_v2.o common_test_1_tmp.o |
$(CXXLINK) -Wl,--incremental-update -Bgcctestdir/ common_test_1_tmp.o |
|
endif DEFAULT_TARGET_X86_64 |
|
endif GCC |
/testsuite/common_test_1_v1.c
0,0 → 1,79
/* common_test_1_v1.c -- test common symbol sorting |
|
Copyright 2008, 2011 Free Software Foundation, Inc. |
Written by Ian Lance Taylor <iant@google.com> |
|
This file is part of gold. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 3 of the License, or |
(at your option) any later version. |
|
This program is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
GNU General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
MA 02110-1301, USA. |
|
This is a test of a common symbol in the main program and a |
versioned symbol in a shared library. The common symbol in the |
main program should override the shared library symbol. |
|
This file is a modified version of the real test case, to be used |
while testing the --incremental option. */ |
|
#include <assert.h> |
|
/* Common symbols should be sorted by size, largest first, and then by |
alignment, largest first. We mix up the names, because gas seems |
to sort common symbols roughly by name. */ |
|
int c9[90]; |
int c8[80]; |
int c7[70]; |
int c6[60]; |
int c5[10]; |
int c4[20]; |
int c3[30]; |
int c2[40]; |
int c1[50]; |
|
int a1 __attribute__ ((aligned (1 << 9))); |
int a2 __attribute__ ((aligned (1 << 8))); |
int a3 __attribute__ ((aligned (1 << 7))); |
int a4 __attribute__ ((aligned (1 << 6))); |
int a5 __attribute__ ((aligned (1 << 1))); |
int a6 __attribute__ ((aligned (1 << 2))); |
int a7 __attribute__ ((aligned (1 << 3))); |
int a8 __attribute__ ((aligned (1 << 4))); |
int a9 __attribute__ ((aligned (1 << 5))); |
|
int |
main (int argc __attribute__ ((unused)), char** argv __attribute__ ((unused))) |
{ |
/* These tests are deliberately incorrect. */ |
assert (c5 < c4); |
assert (c4 < c3); |
assert (c3 < c2); |
assert (c2 < c1); |
assert (c1 < c6); |
assert (c6 < c7); |
assert (c7 < c8); |
assert (c8 < c9); |
|
assert (&a1 > &a2); |
assert (&a2 > &a3); |
assert (&a3 > &a4); |
assert (&a4 > &a9); |
assert (&a9 > &a8); |
assert (&a8 > &a7); |
assert (&a7 > &a6); |
assert (&a6 > &a5); |
|
return 0; |
} |
/testsuite/two_file_test_2_v1.cc
46,7 → 46,7
|
// 2 Code in file 1 refers to global data in file 2. |
|
int v2 = 0; |
int v2 = 1; |
|
// 3 Code in file 1 referes to common symbol in file 2. This is |
// initialized at runtime to 789. |
/testsuite/common_test_1_v2.c
0,0 → 1,77
/* common_test_1_v2.c -- test common symbol sorting |
|
Copyright 2008 Free Software Foundation, Inc. |
Written by Ian Lance Taylor <iant@google.com> |
|
This file is part of gold. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 3 of the License, or |
(at your option) any later version. |
|
This program is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
GNU General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
MA 02110-1301, USA. |
|
This is a test of a common symbol in the main program and a |
versioned symbol in a shared library. The common symbol in the |
main program should override the shared library symbol. */ |
|
#include <assert.h> |
|
/* Common symbols should be sorted by size, largest first, and then by |
alignment, largest first. We mix up the names, because gas seems |
to sort common symbols roughly by name. */ |
|
int c9[90]; |
int c8[80]; |
int c7[70]; |
int c6[60]; |
int c5[10]; |
int c4[20]; |
int c3[30]; |
int c2[40]; |
int c1[50]; |
|
int a1 __attribute__ ((aligned (1 << 9))); |
int a2 __attribute__ ((aligned (1 << 8))); |
int a3 __attribute__ ((aligned (1 << 7))); |
int a4 __attribute__ ((aligned (1 << 6))); |
int a5 __attribute__ ((aligned (1 << 1))); |
int a6 __attribute__ ((aligned (1 << 2))); |
int a7 __attribute__ ((aligned (1 << 3))); |
int a8 __attribute__ ((aligned (1 << 4))); |
int a9 __attribute__ ((aligned (1 << 5))); |
|
int |
main (int argc __attribute__ ((unused)), char** argv __attribute__ ((unused))) |
{ |
// After an incremental update, all guarantees about ordering |
// are null. |
assert (c5 != c4); |
assert (c4 != c3); |
assert (c3 != c2); |
assert (c2 != c1); |
assert (c1 != c6); |
assert (c6 != c7); |
assert (c7 != c8); |
assert (c8 != c9); |
|
assert (&a1 != &a2); |
assert (&a2 != &a3); |
assert (&a3 != &a4); |
assert (&a4 != &a9); |
assert (&a9 != &a8); |
assert (&a8 != &a7); |
assert (&a7 != &a6); |
assert (&a6 != &a5); |
|
return 0; |
} |
/testsuite/Makefile.in
435,7 → 435,9
# Incremental linking is currently supported only on the x86_64 target. |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_35 = incremental_test_2 \ |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ incremental_test_3 \ |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ incremental_test_4 |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ incremental_test_4 \ |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ incremental_copy_test \ |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ incremental_common_test_1 |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_36 = two_file_test_tmp_2.o \ |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_tmp_3.o \ |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ incremental_test_4.base \ |
683,7 → 685,9
@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_22 = start_lib_test$(EXEEXT) |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_23 = incremental_test_2$(EXEEXT) \ |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ incremental_test_3$(EXEEXT) \ |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ incremental_test_4$(EXEEXT) |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ incremental_test_4$(EXEEXT) \ |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ incremental_copy_test$(EXEEXT) \ |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ incremental_common_test_1$(EXEEXT) |
basic_pic_test_SOURCES = basic_pic_test.c |
basic_pic_test_OBJECTS = basic_pic_test.$(OBJEXT) |
basic_pic_test_LDADD = $(LDADD) |
1008,6 → 1012,19
ifuncmain7static_OBJECTS = $(am_ifuncmain7static_OBJECTS) |
ifuncmain7static_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ |
$(ifuncmain7static_LDFLAGS) $(LDFLAGS) -o $@ |
incremental_common_test_1_SOURCES = incremental_common_test_1.c |
incremental_common_test_1_OBJECTS = \ |
incremental_common_test_1.$(OBJEXT) |
incremental_common_test_1_LDADD = $(LDADD) |
incremental_common_test_1_DEPENDENCIES = libgoldtest.a ../libgold.a \ |
../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ |
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) |
incremental_copy_test_SOURCES = incremental_copy_test.c |
incremental_copy_test_OBJECTS = incremental_copy_test.$(OBJEXT) |
incremental_copy_test_LDADD = $(LDADD) |
incremental_copy_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ |
../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ |
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) |
incremental_test_2_SOURCES = incremental_test_2.c |
incremental_test_2_OBJECTS = incremental_test_2.$(OBJEXT) |
incremental_test_2_LDADD = $(LDADD) |
1504,7 → 1521,8
$(ifuncmain5static_SOURCES) ifuncmain5staticpic.c \ |
ifuncmain6pie.c $(ifuncmain7_SOURCES) ifuncmain7pic.c \ |
ifuncmain7picstatic.c ifuncmain7pie.c \ |
$(ifuncmain7static_SOURCES) incremental_test_2.c \ |
$(ifuncmain7static_SOURCES) incremental_common_test_1.c \ |
incremental_copy_test.c incremental_test_2.c \ |
incremental_test_3.c incremental_test_4.c $(initpri1_SOURCES) \ |
$(justsyms_SOURCES) $(large_SOURCES) local_labels_test.c \ |
many_sections_r_test.c $(many_sections_test_SOURCES) \ |
2577,6 → 2595,24
ifuncmain7static$(EXEEXT): $(ifuncmain7static_OBJECTS) $(ifuncmain7static_DEPENDENCIES) |
@rm -f ifuncmain7static$(EXEEXT) |
$(ifuncmain7static_LINK) $(ifuncmain7static_OBJECTS) $(ifuncmain7static_LDADD) $(LIBS) |
@DEFAULT_TARGET_X86_64_FALSE@incremental_common_test_1$(EXEEXT): $(incremental_common_test_1_OBJECTS) $(incremental_common_test_1_DEPENDENCIES) |
@DEFAULT_TARGET_X86_64_FALSE@ @rm -f incremental_common_test_1$(EXEEXT) |
@DEFAULT_TARGET_X86_64_FALSE@ $(LINK) $(incremental_common_test_1_OBJECTS) $(incremental_common_test_1_LDADD) $(LIBS) |
@GCC_FALSE@incremental_common_test_1$(EXEEXT): $(incremental_common_test_1_OBJECTS) $(incremental_common_test_1_DEPENDENCIES) |
@GCC_FALSE@ @rm -f incremental_common_test_1$(EXEEXT) |
@GCC_FALSE@ $(LINK) $(incremental_common_test_1_OBJECTS) $(incremental_common_test_1_LDADD) $(LIBS) |
@NATIVE_LINKER_FALSE@incremental_common_test_1$(EXEEXT): $(incremental_common_test_1_OBJECTS) $(incremental_common_test_1_DEPENDENCIES) |
@NATIVE_LINKER_FALSE@ @rm -f incremental_common_test_1$(EXEEXT) |
@NATIVE_LINKER_FALSE@ $(LINK) $(incremental_common_test_1_OBJECTS) $(incremental_common_test_1_LDADD) $(LIBS) |
@DEFAULT_TARGET_X86_64_FALSE@incremental_copy_test$(EXEEXT): $(incremental_copy_test_OBJECTS) $(incremental_copy_test_DEPENDENCIES) |
@DEFAULT_TARGET_X86_64_FALSE@ @rm -f incremental_copy_test$(EXEEXT) |
@DEFAULT_TARGET_X86_64_FALSE@ $(LINK) $(incremental_copy_test_OBJECTS) $(incremental_copy_test_LDADD) $(LIBS) |
@GCC_FALSE@incremental_copy_test$(EXEEXT): $(incremental_copy_test_OBJECTS) $(incremental_copy_test_DEPENDENCIES) |
@GCC_FALSE@ @rm -f incremental_copy_test$(EXEEXT) |
@GCC_FALSE@ $(LINK) $(incremental_copy_test_OBJECTS) $(incremental_copy_test_LDADD) $(LIBS) |
@NATIVE_LINKER_FALSE@incremental_copy_test$(EXEEXT): $(incremental_copy_test_OBJECTS) $(incremental_copy_test_DEPENDENCIES) |
@NATIVE_LINKER_FALSE@ @rm -f incremental_copy_test$(EXEEXT) |
@NATIVE_LINKER_FALSE@ $(LINK) $(incremental_copy_test_OBJECTS) $(incremental_copy_test_LDADD) $(LIBS) |
@DEFAULT_TARGET_X86_64_FALSE@incremental_test_2$(EXEEXT): $(incremental_test_2_OBJECTS) $(incremental_test_2_DEPENDENCIES) |
@DEFAULT_TARGET_X86_64_FALSE@ @rm -f incremental_test_2$(EXEEXT) |
@DEFAULT_TARGET_X86_64_FALSE@ $(LINK) $(incremental_test_2_OBJECTS) $(incremental_test_2_LDADD) $(LIBS) |
2971,6 → 3007,8
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ifuncmain7pic.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ifuncmain7picstatic.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ifuncmain7pie.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/incremental_common_test_1.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/incremental_copy_test.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/incremental_test_2.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/incremental_test_3.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/incremental_test_4.Po@am__quote@ |
3652,6 → 3690,10
@p='incremental_test_3$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) |
incremental_test_4.log: incremental_test_4$(EXEEXT) |
@p='incremental_test_4$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) |
incremental_copy_test.log: incremental_copy_test$(EXEEXT) |
@p='incremental_copy_test$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) |
incremental_common_test_1.log: incremental_common_test_1$(EXEEXT) |
@p='incremental_common_test_1$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) |
.test.log: |
@p='$<'; $(am__check_pre) $(TEST_LOG_COMPILE) "$$tst" $(am__check_post) |
@am__EXEEXT_TRUE@.test$(EXEEXT).log: |
4615,6 → 4657,18
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ @sleep 1 |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ cp -f two_file_test_2.o two_file_test_tmp_4.o |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Wl,--incremental-update,--incremental-base=incremental_test_4.base -Bgcctestdir/ two_file_test_1.o two_file_test_1b.o two_file_test_tmp_4.o two_file_test_main.o |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@incremental_copy_test: copy_test_v1.o copy_test.o copy_test_1.so copy_test_2.so |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ cp -f copy_test_v1.o copy_test_tmp.o |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Wl,--incremental-full -Bgcctestdir/ -Wl,-R,. copy_test_tmp.o copy_test_1.so copy_test_2.so |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ @sleep 1 |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ cp -f copy_test.o copy_test_tmp.o |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Wl,--incremental-update -Bgcctestdir/ -Wl,-R,. copy_test_tmp.o copy_test_1.so copy_test_2.so |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@incremental_common_test_1: common_test_1_v1.o common_test_1_v2.o gcctestdir/ld |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ cp -f common_test_1_v1.o common_test_1_tmp.o |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Wl,--incremental-full -Bgcctestdir/ common_test_1_tmp.o |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ @sleep 1 |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ cp -f common_test_1_v2.o common_test_1_tmp.o |
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Wl,--incremental-update -Bgcctestdir/ common_test_1_tmp.o |
@NATIVE_OR_CROSS_LINKER_TRUE@script_test_10.o: script_test_10.s |
@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_AS) -o $@ $< |
@NATIVE_OR_CROSS_LINKER_TRUE@script_test_10: $(srcdir)/script_test_10.t script_test_10.o gcctestdir/ld |
/object.cc
1299,8 → 1299,13
&& (shdr.get_sh_type() == elfcpp::SHT_PROGBITS |
|| shdr.get_sh_type() == elfcpp::SHT_NOBITS |
|| shdr.get_sh_type() == elfcpp::SHT_NOTE)) |
incremental_inputs->report_input_section(this, i, name, |
shdr.get_sh_size()); |
{ |
off_t sh_size = shdr.get_sh_size(); |
section_size_type uncompressed_size; |
if (this->section_is_compressed(i, &uncompressed_size)) |
sh_size = uncompressed_size; |
incremental_inputs->report_input_section(this, i, name, sh_size); |
} |
|
if (discard) |
{ |
/errors.cc
81,9 → 81,20
fprintf(stderr, _("%s: fatal error: "), this->program_name_); |
vfprintf(stderr, format, args); |
fputc('\n', stderr); |
gold_exit(false); |
gold_exit(GOLD_ERR); |
} |
|
// Report a fallback error. |
|
void |
Errors::fallback(const char* format, va_list args) |
{ |
fprintf(stderr, _("%s: fatal error: "), this->program_name_); |
vfprintf(stderr, format, args); |
fputc('\n', stderr); |
gold_exit(GOLD_FALLBACK); |
} |
|
// Report an error. |
|
void |
212,6 → 223,17
va_end(args); |
} |
|
// Report a fallback error. |
|
void |
gold_fallback(const char* format, ...) |
{ |
va_list args; |
va_start(args, format); |
parameters->errors()->fallback(format, args); |
va_end(args); |
} |
|
// Report an error. |
|
void |
/target.h
833,6 → 833,13
Symbol*) |
{ 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. |
|
virtual void |
/symtab.cc
79,6 → 79,7
this->is_defined_in_discarded_section_ = false; |
this->undef_binding_set_ = false; |
this->undef_binding_weak_ = false; |
this->is_predefined_ = false; |
} |
|
// Return the demangled version of the symbol's name, but only |
133,7 → 134,8
Symbol::init_base_output_data(const char* name, const char* version, |
Output_data* od, elfcpp::STT type, |
elfcpp::STB binding, elfcpp::STV visibility, |
unsigned char nonvis, bool offset_is_from_end) |
unsigned char nonvis, bool offset_is_from_end, |
bool is_predefined) |
{ |
this->init_fields(name, version, type, binding, visibility, nonvis); |
this->u_.in_output_data.output_data = od; |
141,6 → 143,7
this->source_ = IN_OUTPUT_DATA; |
this->in_reg_ = true; |
this->in_real_elf_ = true; |
this->is_predefined_ = is_predefined; |
} |
|
// Initialize the fields in the base class Symbol for a symbol defined |
151,7 → 154,8
Output_segment* os, elfcpp::STT type, |
elfcpp::STB binding, elfcpp::STV visibility, |
unsigned char nonvis, |
Segment_offset_base offset_base) |
Segment_offset_base offset_base, |
bool is_predefined) |
{ |
this->init_fields(name, version, type, binding, visibility, nonvis); |
this->u_.in_output_segment.output_segment = os; |
159,6 → 163,7
this->source_ = IN_OUTPUT_SEGMENT; |
this->in_reg_ = true; |
this->in_real_elf_ = true; |
this->is_predefined_ = is_predefined; |
} |
|
// Initialize the fields in the base class Symbol for a symbol defined |
167,12 → 172,14
void |
Symbol::init_base_constant(const char* name, const char* version, |
elfcpp::STT type, elfcpp::STB binding, |
elfcpp::STV visibility, unsigned char nonvis) |
elfcpp::STV visibility, unsigned char nonvis, |
bool is_predefined) |
{ |
this->init_fields(name, version, type, binding, visibility, nonvis); |
this->source_ = IS_CONSTANT; |
this->in_reg_ = true; |
this->in_real_elf_ = true; |
this->is_predefined_ = is_predefined; |
} |
|
// Initialize the fields in the base class Symbol for an undefined |
227,10 → 234,11
elfcpp::STB binding, |
elfcpp::STV visibility, |
unsigned char nonvis, |
bool offset_is_from_end) |
bool offset_is_from_end, |
bool is_predefined) |
{ |
this->init_base_output_data(name, version, od, type, binding, visibility, |
nonvis, offset_is_from_end); |
nonvis, offset_is_from_end, is_predefined); |
this->value_ = value; |
this->symsize_ = symsize; |
} |
246,10 → 254,11
elfcpp::STB binding, |
elfcpp::STV visibility, |
unsigned char nonvis, |
Segment_offset_base offset_base) |
Segment_offset_base offset_base, |
bool is_predefined) |
{ |
this->init_base_output_segment(name, version, os, type, binding, visibility, |
nonvis, offset_base); |
nonvis, offset_base, is_predefined); |
this->value_ = value; |
this->symsize_ = symsize; |
} |
262,9 → 271,11
Sized_symbol<size>::init_constant(const char* name, const char* version, |
Value_type value, Size_type symsize, |
elfcpp::STT type, elfcpp::STB binding, |
elfcpp::STV visibility, unsigned char nonvis) |
elfcpp::STV visibility, unsigned char nonvis, |
bool is_predefined) |
{ |
this->init_base_constant(name, version, type, binding, visibility, nonvis); |
this->init_base_constant(name, version, type, binding, visibility, nonvis, |
is_predefined); |
this->value_ = value; |
this->symsize_ = symsize; |
} |
1489,7 → 1500,7
// Add a symbol from a incremental object file. |
|
template<int size, bool big_endian> |
Symbol* |
Sized_symbol<size>* |
Symbol_table::add_from_incrobj( |
Object* obj, |
const char* name, |
1843,7 → 1854,8
return NULL; |
|
sym->init_output_data(name, version, od, value, symsize, type, binding, |
visibility, nonvis, offset_is_from_end); |
visibility, nonvis, offset_is_from_end, |
defined == PREDEFINED); |
|
if (oldsym == NULL) |
{ |
1956,7 → 1968,8
return NULL; |
|
sym->init_output_segment(name, version, os, value, symsize, type, binding, |
visibility, nonvis, offset_base); |
visibility, nonvis, offset_base, |
defined == PREDEFINED); |
|
if (oldsym == NULL) |
{ |
2068,7 → 2081,7
return NULL; |
|
sym->init_constant(name, version, value, symsize, type, binding, visibility, |
nonvis); |
nonvis, defined == PREDEFINED); |
|
if (oldsym == NULL) |
{ |
3453,7 → 3466,7
|
#ifdef HAVE_TARGET_32_LITTLE |
template |
Symbol* |
Sized_symbol<32>* |
Symbol_table::add_from_incrobj( |
Object* obj, |
const char* name, |
3463,7 → 3476,7
|
#ifdef HAVE_TARGET_32_BIG |
template |
Symbol* |
Sized_symbol<32>* |
Symbol_table::add_from_incrobj( |
Object* obj, |
const char* name, |
3473,7 → 3486,7
|
#ifdef HAVE_TARGET_64_LITTLE |
template |
Symbol* |
Sized_symbol<64>* |
Symbol_table::add_from_incrobj( |
Object* obj, |
const char* name, |
3483,7 → 3496,7
|
#ifdef HAVE_TARGET_64_BIG |
template |
Symbol* |
Sized_symbol<64>* |
Symbol_table::add_from_incrobj( |
Object* obj, |
const char* name, |
/symtab.h
803,6 → 803,11
&& !this->is_func()); |
} |
|
// Return true if this symbol was predefined by the linker. |
bool |
is_predefined() const |
{ return this->is_predefined_; } |
|
protected: |
// Instances of this class should always be created at a specific |
// size. |
828,7 → 833,8
void |
init_base_output_data(const char* name, const char* version, Output_data*, |
elfcpp::STT, elfcpp::STB, elfcpp::STV, |
unsigned char nonvis, bool offset_is_from_end); |
unsigned char nonvis, bool offset_is_from_end, |
bool is_predefined); |
|
// Initialize fields for an Output_segment. |
void |
836,13 → 842,14
Output_segment* os, elfcpp::STT type, |
elfcpp::STB binding, elfcpp::STV visibility, |
unsigned char nonvis, |
Segment_offset_base offset_base); |
Segment_offset_base offset_base, |
bool is_predefined); |
|
// Initialize fields for a constant. |
void |
init_base_constant(const char* name, const char* version, elfcpp::STT type, |
elfcpp::STB binding, elfcpp::STV visibility, |
unsigned char nonvis); |
unsigned char nonvis, bool is_predefined); |
|
// Initialize fields for an undefined symbol. |
void |
991,6 → 998,8
// True if this symbol was a weak undef resolved by a dynamic def |
// (bit 33). |
bool undef_binding_weak_ : 1; |
// True if this symbol is a predefined linker symbol (bit 34). |
bool is_predefined_ : 1; |
}; |
|
// The parts of a symbol which are size specific. Using a template |
1020,7 → 1029,7
init_output_data(const char* name, const char* version, Output_data*, |
Value_type value, Size_type symsize, elfcpp::STT, |
elfcpp::STB, elfcpp::STV, unsigned char nonvis, |
bool offset_is_from_end); |
bool offset_is_from_end, bool is_predefined); |
|
// Initialize fields for an Output_segment. |
void |
1027,13 → 1036,13
init_output_segment(const char* name, const char* version, Output_segment*, |
Value_type value, Size_type symsize, elfcpp::STT, |
elfcpp::STB, elfcpp::STV, unsigned char nonvis, |
Segment_offset_base offset_base); |
Segment_offset_base offset_base, bool is_predefined); |
|
// Initialize fields for a constant. |
void |
init_constant(const char* name, const char* version, Value_type value, |
Size_type symsize, elfcpp::STT, elfcpp::STB, elfcpp::STV, |
unsigned char nonvis); |
unsigned char nonvis, bool is_predefined); |
|
// Initialize fields for an undefined symbol. |
void |
1250,6 → 1259,9
SCRIPT, |
// Predefined by the linker. |
PREDEFINED, |
// Defined by the linker during an incremental base link, but not |
// a predefined symbol (e.g., common, defined in script). |
INCREMENTAL_BASE, |
}; |
|
// The order in which we sort common symbols. |
1341,7 → 1353,7
// Add one external symbol from the incremental object OBJ to the symbol |
// table. Returns a pointer to the resolved symbol in the symbol table. |
template<int size, bool big_endian> |
Symbol* |
Sized_symbol<size>* |
add_from_incrobj(Object* obj, const char* name, |
const char* ver, elfcpp::Sym<size, big_endian>* sym); |
|
/output.h
3432,6 → 3432,11
void |
reserve(uint64_t sh_offset, uint64_t sh_size); |
|
// Allocate space from the free list for the section. Used for |
// incremental update links. |
off_t |
allocate(off_t len, uint64_t addralign); |
|
protected: |
// Return the output section--i.e., the object itself. |
Output_section* |
/incremental-dump.cc
293,8 → 293,9
for (unsigned int symndx = 0; symndx < nsyms; ++symndx) |
{ |
bool is_def; |
bool is_copy; |
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; |
elfcpp::Sym<size, big_endian> sym(sym_p); |
const char* symname; |
303,7 → 304,7
printf(" %6d %6s %8s %8s %8s %8s %-5s %s\n", |
output_symndx, |
"", "", "", "", "", |
is_def ? "DEF" : "UNDEF", |
is_copy ? "COPY" : (is_def ? "DEF" : "UNDEF"), |
symname); |
} |
} |
321,12 → 322,14
symname = "<unknown>"; |
printf(" %6d %6d %8d %8d %8d %8d %-5s %s\n", |
output_symndx, |
info.shndx(), |
info.shndx() == -1U ? -1 : info.shndx(), |
input_file.get_symbol_offset(symndx), |
info.next_offset(), |
info.reloc_count(), |
info.reloc_offset(), |
info.shndx() != elfcpp::SHN_UNDEF ? "DEF" : "UNDEF", |
(info.shndx() == -1U |
? "BASE" |
: info.shndx() == 0 ? "UNDEF" : "DEF"), |
symname); |
} |
} |
/resolve.cc
830,6 → 830,7
objname = _("linker script"); |
break; |
case PREDEFINED: |
case INCREMENTAL_BASE: |
objname = _("linker defined"); |
break; |
default: |
908,6 → 909,8
if (from->needs_dynsym_value_) |
this->needs_dynsym_value_ = true; |
|
this->is_predefined_ = from->is_predefined_; |
|
// We shouldn't see these flags. If we do, we need to handle them |
// somehow. |
gold_assert(!from->is_forwarder_); |
/gold.h
27,6 → 27,7
#include "ansidecl.h" |
|
#include <cstddef> |
#include <cstdlib> |
#include <cstring> |
#include <stdint.h> |
#include <sys/types.h> |
166,6 → 167,15
template<int size, bool big_endian> |
struct Relocate_info; |
|
// Exit status codes. |
|
enum Exit_status |
{ |
GOLD_OK = EXIT_SUCCESS, |
GOLD_ERR = EXIT_FAILURE, |
GOLD_FALLBACK = EXIT_FAILURE + 1 |
}; |
|
// Some basic types. For these we use lower case initial letters. |
|
// For an offset in an input or output file, use off_t. Note that |
183,7 → 193,7
// This function is called to exit the program. Status is true to |
// exit success (0) and false to exit failure (1). |
extern void |
gold_exit(bool status) ATTRIBUTE_NORETURN; |
gold_exit(Exit_status status) ATTRIBUTE_NORETURN; |
|
// This function is called to emit an error message and then |
// immediately exit with failure. |
203,6 → 213,13
extern void |
gold_info(const char* msg, ...) ATTRIBUTE_PRINTF_1; |
|
// This function is called to emit an error message and then |
// immediately exit with fallback status (e.g., when |
// --incremental-update fails and the link needs to be restarted |
// with --incremental-full). |
extern void |
gold_fallback(const char* format, ...) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF_1; |
|
// Work around a bug in gcc 4.3.0. http://gcc.gnu.org/PR35546 . This |
// can probably be removed after the bug has been fixed for a while. |
#ifdef HAVE_TEMPLATE_ATTRIBUTES |
/script-sections.cc
2846,6 → 2846,17
uint64_t address = *dot_value; |
address = align_address(address, this->os_->addralign()); |
|
// For a relocatable link, all orphan sections are put at |
// address 0. In general we expect all sections to be at |
// address 0 for a relocatable link, but we permit the linker |
// script to override that for specific output sections. |
if (parameters->options().relocatable()) |
{ |
address = 0; |
*load_address = 0; |
have_load_address = false; |
} |
|
if ((this->os_->flags() & elfcpp::SHF_ALLOC) != 0) |
{ |
this->os_->set_address(address); |
/x86_64.cc
405,10 → 405,13
unsigned int got_type); |
|
// Register an existing PLT entry for a global symbol. |
// A target needs to implement this to support incremental linking. |
void |
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. |
void |
apply_relocation(const Relocate_info<64, false>* relinfo, |
912,8 → 915,8
// For incremental updates, find an available slot. |
plt_offset = this->free_list_.allocate(plt_entry_size, plt_entry_size, 0); |
if (plt_offset == -1) |
gold_fatal(_("out of patch space (PLT);" |
" relink with --incremental-full")); |
gold_fallback(_("out of patch space (PLT);" |
" relink with --incremental-full")); |
|
// The GOT and PLT entries have a 1-1 correspondance, so the GOT offset |
// can be calculated from the PLT index, adjusting for the three |
1389,6 → 1392,19
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. |
|
void |
/copy-relocs.cc
65,7 → 65,7
Output_data_reloc<sh_type, true, size, big_endian>* reloc_section) |
{ |
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 |
{ |
// We may not need a COPY relocation. Save this relocation to |
106,6 → 106,24
void |
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, |
Layout* layout, |
Sized_symbol<size>* sym, |
Output_data_reloc<sh_type, true, size, big_endian>* reloc_section) |
164,26 → 182,9
section_size_type offset = dynbss_size; |
dynbss->set_current_data_size(dynbss_size + symsize); |
|
// Define the symbol as being copied. |
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); |
this->emit_copy_reloc(symtab, sym, dynbss, 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. |
|
template<int sh_type, int size, bool big_endian> |
/output.cc
1705,8 → 1705,8
// 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")); |
gold_fallback(_("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; |
1735,8 → 1735,8
// 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")); |
gold_fallback(_("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; |
2270,7 → 2270,7
offset_in_section = this->free_list_.allocate(input_section_size, |
addralign, 0); |
if (offset_in_section == -1) |
gold_fatal(_("out of patch space; relink with --incremental-full")); |
gold_fallback(_("out of patch space; relink with --incremental-full")); |
aligned_offset_in_section = offset_in_section; |
} |
else |
2374,7 → 2374,8
offset_in_section = this->free_list_.allocate(posd->data_size(), |
posd->addralign(), 0); |
if (offset_in_section == -1) |
gold_fatal(_("out of patch space; relink with --incremental-full")); |
gold_fallback(_("out of patch space; " |
"relink with --incremental-full")); |
// Finalize the address and offset now. |
uint64_t addr = this->address(); |
off_t offset = this->offset(); |
3726,6 → 3727,7
|
// Reserve space within the fixed layout for the section. Used for |
// incremental update links. |
|
void |
Output_section::reserve(uint64_t sh_offset, uint64_t sh_size) |
{ |
3732,6 → 3734,15
this->free_list_.remove(sh_offset, sh_offset + sh_size); |
} |
|
// Allocate space from the free list for the section. Used for |
// incremental update links. |
|
off_t |
Output_section::allocate(off_t len, uint64_t addralign) |
{ |
return this->free_list_.allocate(len, addralign, 0); |
} |
|
// Output segment methods. |
|
Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags) |
4146,10 → 4157,7
} |
} |
|
// FIXME: Need to handle TLS and .bss with incremental update. |
if (!parameters->incremental_update() |
|| (*p)->is_section_flag_set(elfcpp::SHF_TLS) |
|| (*p)->is_section_type(elfcpp::SHT_NOBITS)) |
if (!parameters->incremental_update()) |
{ |
off = align_address(off, align); |
(*p)->set_address_and_file_offset(addr + (off - startoff), off); |
4163,17 → 4171,17
if (off == -1) |
{ |
gold_assert((*p)->output_section() != NULL); |
gold_fatal(_("out of patch space for section %s; " |
"relink with --incremental-full"), |
(*p)->output_section()->name()); |
gold_fallback(_("out of patch space for section %s; " |
"relink with --incremental-full"), |
(*p)->output_section()->name()); |
} |
(*p)->set_address_and_file_offset(addr + (off - startoff), off); |
if ((*p)->data_size() > current_size) |
{ |
gold_assert((*p)->output_section() != NULL); |
gold_fatal(_("%s: section changed size; " |
"relink with --incremental-full"), |
(*p)->output_section()->name()); |
gold_fallback(_("%s: section changed size; " |
"relink with --incremental-full"), |
(*p)->output_section()->name()); |
} |
} |
} |
/copy-relocs.h
81,6 → 81,12
void |
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: |
typedef typename elfcpp::Elf_types<size>::Elf_Addr Address; |
typedef typename elfcpp::Elf_types<size>::Elf_Addr Addend; |
126,16 → 132,11
Sized_relobj_file<size, big_endian>* object, |
unsigned int shndx) const; |
|
// Emit a COPY reloc. |
// Make a new COPY reloc and emit it. |
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>*); |
|
// 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. |
void |
save(Symbol*, Sized_relobj_file<size, big_endian>*, unsigned int shndx, |
/incremental.h
68,6 → 68,20
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,9 → 1026,10
|
// 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_ |
1021,8 → 1036,23
+ 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
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
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
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
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
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
} |
|
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
// 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_; |
/layout.cc
2957,7 → 2957,7
if (!are_addresses_set |
&& !has_relro |
&& aligned_addr != addr |
&& !parameters->incremental_update()) |
&& !parameters->incremental()) |
{ |
uint64_t first_off = (common_pagesize |
- (aligned_addr |
3125,9 → 3125,9
if (is_debugging_enabled(DEBUG_INCREMENTAL)) |
this->free_list_.dump(); |
gold_assert((*p)->output_section() != NULL); |
gold_fatal(_("out of patch space for section %s; " |
"relink with --incremental-full"), |
(*p)->output_section()->name()); |
gold_fallback(_("out of patch space for section %s; " |
"relink with --incremental-full"), |
(*p)->output_section()->name()); |
} |
(*p)->set_file_offset(off); |
(*p)->finalize_data_size(); |
3134,9 → 3134,9
if ((*p)->data_size() > current_size) |
{ |
gold_assert((*p)->output_section() != NULL); |
gold_fatal(_("%s: section changed size; " |
"relink with --incremental-full"), |
(*p)->output_section()->name()); |
gold_fallback(_("%s: section changed size; " |
"relink with --incremental-full"), |
(*p)->output_section()->name()); |
} |
gold_debug(DEBUG_INCREMENTAL, |
"set_section_offsets: %08lx %08lx %s", |
3391,8 → 3391,8
{ |
symtab_off = this->allocate(off, align, *poff); |
if (off == -1) |
gold_fatal(_("out of patch space for symbol table; " |
"relink with --incremental-full")); |
gold_fallback(_("out of patch space for symbol table; " |
"relink with --incremental-full")); |
gold_debug(DEBUG_INCREMENTAL, |
"create_symtab_sections: %08lx %08lx .symtab", |
static_cast<long>(symtab_off), |
3462,8 → 3462,8
oshdrs->pre_finalize_data_size(); |
off = this->allocate(oshdrs->data_size(), oshdrs->addralign(), *poff); |
if (off == -1) |
gold_fatal(_("out of patch space for section header table; " |
"relink with --incremental-full")); |
gold_fallback(_("out of patch space for section header table; " |
"relink with --incremental-full")); |
gold_debug(DEBUG_INCREMENTAL, |
"create_shdrs: %08lx %08lx (section header table)", |
static_cast<long>(off), |