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