* copy-relocs.cc (Copy_relocs::copy_reloc): Call make_copy_reloc
authorCary Coutant <ccoutant@google.com>
Wed, 8 Jun 2011 03:50:12 +0000 (03:50 +0000)
committerCary Coutant <ccoutant@google.com>
Wed, 8 Jun 2011 03:50:12 +0000 (03:50 +0000)
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.

gold/ChangeLog
gold/copy-relocs.cc
gold/copy-relocs.h
gold/gold.cc
gold/incremental-dump.cc
gold/incremental.cc
gold/incremental.h
gold/symtab.cc
gold/symtab.h
gold/target.h
gold/x86_64.cc

index a974f8f40d64e3a72242e6d6cc1aeb5d2f97e589..2626867eae126821ad7ed063f6d41d172fe36be2 100644 (file)
@@ -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>
 
        PR gold/12163
index bfdbb90ce382c2a5d957c47ac36d41cffe92dc10..20b110dba2ca187b9b8b00ed88ef303210e9efa6 100644 (file)
@@ -65,7 +65,7 @@ Copy_relocs<sh_type, size, big_endian>::copy_reloc(
     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
@@ -105,6 +105,24 @@ Copy_relocs<sh_type, size, big_endian>::need_copy_reloc(
 template<int sh_type, int size, bool big_endian>
 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,
@@ -164,24 +182,7 @@ Copy_relocs<sh_type, size, big_endian>::emit_copy_reloc(
   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);
-}
-
-// 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);
+  this->emit_copy_reloc(symtab, sym, dynbss, offset, reloc_section);
 }
 
 // Save a relocation to possibly be emitted later.
index 3fa2a6110e042948be5a411f573f30c6e4e7b279..d1e2323b25c6baffc4970621f5f9d926111043e4 100644 (file)
@@ -81,6 +81,12 @@ class Copy_relocs
   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 @@ class Copy_relocs
                   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,
index fc3974edb13df5bcecb79175e23217721a323142..0b901bb120d7caabae3b640c84882a6515953d67 100644 (file)
@@ -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())
     {
       Incremental_binary* ibase = layout->incremental_base();
       ibase->process_got_plt(symtab, layout);
+      ibase->emit_copy_relocs(symtab);
     }
 
   if (is_debugging_enabled(DEBUG_SCRIPT))
index fff4637617a8cdb11a6b5e72756bbea381bd3b71..e7e838aaaf8466a7949676bfc52298539d14caf6 100644 (file)
@@ -293,8 +293,9 @@ dump_incremental_inputs(const char* argv0, const char* filename,
          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 @@ dump_incremental_inputs(const char* argv0, const char* filename,
              printf("    %6d  %6s  %8s  %8s  %8s  %8s  %-5s  %s\n",
                     output_symndx,
                     "", "", "", "", "",
-                    is_def ? "DEF" : "UNDEF",
+                    is_copy ? "COPY" : (is_def ? "DEF" : "UNDEF"),
                     symname);
            }
        }
index f4eb22c50bf8aeb405e553ffb97df3e08c837432..98f09d073743bc9696417efb1cc13ac6e1c9df1a 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "gold.h"
 
+#include <set>
 #include <cstdarg>
 #include "libiberty.h"
 
@@ -518,11 +519,45 @@ void
 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++)
@@ -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.
 
 template<int size, bool big_endian>
@@ -1545,7 +1600,9 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
                        == (*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 +1627,16 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
                  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;
              }
@@ -2481,19 +2542,26 @@ Sized_incr_dynobj<size, big_endian>::do_add_symbols(
   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;
       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 +2591,24 @@ Sized_incr_dynobj<size, big_endian>::do_add_symbols(
       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);
+           }
+       }
     }
 }
 
index f1fd1f88ae1eb6aed2de45848c19bc5929972475..3bd2a31d4139290d194abd5cff5e997055a9055a 100644 (file)
@@ -68,6 +68,20 @@ enum Incremental_input_flags
   INCREMENTAL_INPUT_AS_NEEDED = 0x4000
 };
 
+// Symbol flags for the incremental symbol table.
+// These flags are stored in the top two bits of
+// the symbol index field.
+
+enum Incremental_shlib_symbol_flags
+{
+  // Symbol is defined in this library.
+  INCREMENTAL_SHLIB_SYM_DEF = 2,
+  // Symbol is defined in this library, with a COPY relocation.
+  INCREMENTAL_SHLIB_SYM_COPY = 3
+};
+
+static const int INCREMENTAL_SHLIB_SYM_FLAGS_SHIFT = 30;
+
 // Create an Incremental_binary object for FILE. Returns NULL is this is not
 // possible, e.g. FILE is not an ELF file or has an unsupported target.
 
@@ -1012,17 +1026,33 @@ class Incremental_inputs_reader
 
     // Return the output symbol index for the Nth global symbol -- for shared
     // libraries only.  Sets *IS_DEF to TRUE if the symbol is defined in this
-    // input file.
+    // input file.  Sets *IS_COPY to TRUE if the symbol was copied from this
+    // input file with a COPY relocation.
     unsigned int
-    get_output_symbol_index(unsigned int n, bool* is_def)
+    get_output_symbol_index(unsigned int n, bool* is_def, bool* is_copy)
     {
       gold_assert(this->type() == INCREMENTAL_INPUT_SHARED_LIBRARY);
       const unsigned char* p = (this->inputs_->p_
                                + this->info_offset_ + 8
                                + n * 4);
       unsigned int output_symndx = Swap32::readval(p);
-      *is_def = (output_symndx & (1U << 31)) != 0;
-      return output_symndx & ((1U << 31) - 1);
+      unsigned int flags = output_symndx >> INCREMENTAL_SHLIB_SYM_FLAGS_SHIFT;
+      output_symndx &= ((1U << INCREMENTAL_SHLIB_SYM_FLAGS_SHIFT) - 1);
+      switch (flags)
+       {
+         case INCREMENTAL_SHLIB_SYM_DEF:
+           *is_def = true;
+           *is_copy = false;
+           break;
+         case INCREMENTAL_SHLIB_SYM_COPY:
+           *is_def = true;
+           *is_copy = true;
+           break;
+         default:
+           *is_def = false;
+           *is_copy = false;
+       }
+      return output_symndx;
     }
 
    private:
@@ -1397,6 +1427,11 @@ class Incremental_binary
   process_got_plt(Symbol_table* symtab, Layout* layout)
   { this->do_process_got_plt(symtab, layout); }
 
+  // Emit COPY relocations from the existing output file.
+  void
+  emit_copy_relocs(Symbol_table* symtab)
+  { this->do_emit_copy_relocs(symtab); }
+
   // Apply incremental relocations for symbols whose values have changed.
   void
   apply_incremental_relocs(const Symbol_table* symtab, Layout* layout,
@@ -1479,6 +1514,10 @@ class Incremental_binary
   virtual void
   do_process_got_plt(Symbol_table* symtab, Layout* layout) = 0;
 
+  // Emit COPY relocations from the existing output file.
+  virtual void
+  do_emit_copy_relocs(Symbol_table* symtab) = 0;
+
   // Apply incremental relocations for symbols whose values have changed.
   virtual void
   do_apply_incremental_relocs(const Symbol_table*, Layout*, Output_file*) = 0;
@@ -1514,9 +1553,9 @@ class Sized_incremental_binary : public Incremental_binary
                            const elfcpp::Ehdr<size, big_endian>& ehdr,
                            Target* target)
     : Incremental_binary(output, target), elf_file_(this, ehdr),
-      input_objects_(), section_map_(), symbol_map_(), main_symtab_loc_(),
-      main_strtab_loc_(), has_incremental_info_(false), inputs_reader_(),
-      symtab_reader_(), relocs_reader_(), got_plt_reader_(),
+      input_objects_(), section_map_(), symbol_map_(), copy_relocs_(),
+      main_symtab_loc_(), main_strtab_loc_(), has_incremental_info_(false),
+      inputs_reader_(), symtab_reader_(), relocs_reader_(), got_plt_reader_(),
       input_entry_readers_()
   { this->setup_readers(); }
 
@@ -1558,6 +1597,11 @@ class Sized_incremental_binary : public Incremental_binary
   global_symbol(unsigned int symndx) const
   { return this->symbol_map_[symndx]; }
 
+  // Add a COPY relocation for a global symbol.
+  void
+  add_copy_reloc(Symbol* gsym, Output_section* os, off_t offset)
+  { this->copy_relocs_.push_back(Copy_reloc(gsym, os, offset)); }
+
   // Readers for the incremental info sections.
 
   const Incremental_inputs_reader<size, big_endian>&
@@ -1606,6 +1650,10 @@ class Sized_incremental_binary : public Incremental_binary
   virtual void
   do_process_got_plt(Symbol_table* symtab, Layout* layout);
 
+  // Emit COPY relocations from the existing output file.
+  virtual void
+  do_emit_copy_relocs(Symbol_table* symtab);
+
   // Apply incremental relocations for symbols whose values have changed.
   virtual void
   do_apply_incremental_relocs(const Symbol_table* symtab, Layout* layout,
@@ -1664,6 +1712,22 @@ class Sized_incremental_binary : public Incremental_binary
   }
 
  private:
+  // List of symbols that need COPY relocations.
+  struct Copy_reloc
+  {
+    Copy_reloc(Symbol* sym, Output_section* os, off_t off)
+      : symbol(sym), output_section(os), offset(off)
+    { }
+
+    // The global symbol to copy.
+    Symbol* symbol;
+    // The output section into which the symbol was copied.
+    Output_section* output_section;
+    // The offset within that output section.
+    off_t offset;
+  };
+  typedef std::vector<Copy_reloc> Copy_relocs;
+
   bool
   find_incremental_inputs_sections(unsigned int* p_inputs_shndx,
                                   unsigned int* p_symtab_shndx,
@@ -1687,6 +1751,9 @@ class Sized_incremental_binary : public Incremental_binary
   // Map global symbols from the input file to the symbol table.
   std::vector<Symbol*> symbol_map_;
 
+  // List of symbols that need COPY relocations.
+  Copy_relocs copy_relocs_;
+
   // Locations of the main symbol table and symbol string table.
   Location main_symtab_loc_;
   Location main_strtab_loc_;
index a1ce3b754ef1bcf91c64eb2143a796cfd7113455..12e2762bdd0048273684ac74139822884b7fec6b 100644 (file)
@@ -1489,7 +1489,7 @@ Symbol_table::add_from_dynobj(
 // 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,
@@ -3453,7 +3453,7 @@ Symbol_table::add_from_dynobj<64, true>(
 
 #ifdef HAVE_TARGET_32_LITTLE
 template
-Symbol*
+Sized_symbol<32>*
 Symbol_table::add_from_incrobj(
     Object* obj,
     const char* name,
@@ -3463,7 +3463,7 @@ Symbol_table::add_from_incrobj(
 
 #ifdef HAVE_TARGET_32_BIG
 template
-Symbol*
+Sized_symbol<32>*
 Symbol_table::add_from_incrobj(
     Object* obj,
     const char* name,
@@ -3473,7 +3473,7 @@ Symbol_table::add_from_incrobj(
 
 #ifdef HAVE_TARGET_64_LITTLE
 template
-Symbol*
+Sized_symbol<64>*
 Symbol_table::add_from_incrobj(
     Object* obj,
     const char* name,
@@ -3483,7 +3483,7 @@ Symbol_table::add_from_incrobj(
 
 #ifdef HAVE_TARGET_64_BIG
 template
-Symbol*
+Sized_symbol<64>*
 Symbol_table::add_from_incrobj(
     Object* obj,
     const char* name,
index 87e70990d1dc4c54273bcbe8852f7867ed277518..43e3efaf35f453bac6dc1bd3209d9a6bc0364eff 100644 (file)
@@ -1341,7 +1341,7 @@ class Symbol_table
   // 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);
 
index 19e975d7b1b90e3ad8d86d160936fdedbe9ce00a..a7e2ca7e43b54b97b7bb9cf95eefa18222358451 100644 (file)
@@ -833,6 +833,13 @@ class Sized_target : public Target
                            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
index a447d38c07715364ea74ac0e3f0f02c6b2c4e4c9..0a6a960ef4ffef9c1140108773f6df89c637240c 100644 (file)
@@ -405,10 +405,13 @@ class Target_x86_64 : public Target_freebsd<64, false>
                           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,
@@ -1389,6 +1392,19 @@ Target_x86_64::register_global_plt_entry(unsigned int plt_index,
   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