diff options
Diffstat (limited to 'gold/incremental.h')
-rw-r--r-- | gold/incremental.h | 81 |
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_; |