Snapshot. Includes first cut at output relocation sections.
authorIan Lance Taylor <iant@google.com>
Thu, 16 Nov 2006 00:38:25 +0000 (00:38 +0000)
committerIan Lance Taylor <iant@google.com>
Thu, 16 Nov 2006 00:38:25 +0000 (00:38 +0000)
17 files changed:
elfcpp/elfcpp.h
gold/Makefile.am
gold/Makefile.in
gold/i386.cc
gold/layout.cc
gold/object.cc
gold/object.h
gold/output.cc
gold/output.h
gold/po/POTFILES.in
gold/po/gold.pot
gold/reloc-types.h [new file with mode: 0644]
gold/reloc.cc
gold/resolve.cc
gold/symtab.cc
gold/symtab.h
gold/target-reloc.h

index e106fabbb125de0aba8ef944071e2933d4822bfa..afbd74d0751efb6d62526adcdf383bc16eb31c8a 100644 (file)
@@ -1163,7 +1163,7 @@ class Sym_write
   internal::Sym_data<size>* p_;
 };
 
-// Accessor classes for Elf relocation table entries.
+// Accessor classes for an ELF REL relocation entry.
 
 template<int size, bool big_endian>
 class Rel
@@ -1191,6 +1191,30 @@ class Rel
   const internal::Rel_data<size>* p_;
 };
 
+// Writer class for an ELF Rel relocation.
+
+template<int size, bool big_endian>
+class Rel_write
+{
+ public:
+  Rel_write(unsigned char* p)
+    : p_(reinterpret_cast<internal::Rel_data<size>*>(p))
+  { }
+
+  void
+  put_r_offset(typename Elf_types<size>::Elf_Addr v)
+  { this->p_->r_offset = Convert<size, big_endian>::convert_host(v); }
+
+  void
+  put_r_info(typename Elf_types<size>::Elf_WXword v)
+  { this->p_->r_info = Convert<size, big_endian>::convert_host(v); }
+
+ private:
+  internal::Rel_data<size>* p_;
+};
+
+// Accessor class for an ELF Rela relocation.
+
 template<int size, bool big_endian>
 class Rela
 {
@@ -1221,6 +1245,32 @@ class Rela
   const internal::Rela_data<size>* p_;
 };
 
+// Writer class for an ELF Rela relocation.
+
+template<int size, bool big_endian>
+class Rela_write
+{
+ public:
+  Rela_write(unsigned char* p)
+    : p_(reinterpret_cast<internal::Rela_data<size>*>(p))
+  { }
+
+  void
+  put_r_offset(typename Elf_types<size>::Elf_Addr v)
+  { this->p_->r_offset = Convert<size, big_endian>::convert_host(v); }
+
+  void
+  put_r_info(typename Elf_types<size>::Elf_WXword v)
+  { this->p_->r_info = Convert<size, big_endian>::convert_host(v); }
+
+  void
+  put_r_addend(typename Elf_types<size>::Elf_Swxword v)
+  { this->p_->r_addend = Convert<size, big_endian>::convert_host(v); }
+
+ private:
+  internal::Rela_data<size>* p_;
+};
+
 // Accessor classes for entries in the ELF SHT_DYNAMIC section aka
 // PT_DYNAMIC segment.
 
index 12ec749920746cb86bbfa1bf4ea978011ed6c349..f76ee5b00c5852c6fda7ac0181a8bdc65c569e44 100644 (file)
@@ -56,7 +56,9 @@ HFILES = \
        output.h \
        readsyms.h \
        reloc.h \
+       reloc-types.h \
        script.h \
+       script-c.h \
        stringpool.h \
        symtab.h \
        target.h \
index deef51c43ce1ad93f6fb204af8ba8351ff710b37..560f481932b6f2e00604ab92e5333d2120dfbe23 100644 (file)
@@ -272,7 +272,9 @@ HFILES = \
        output.h \
        readsyms.h \
        reloc.h \
+       reloc-types.h \
        script.h \
+       script-c.h \
        stringpool.h \
        symtab.h \
        target.h \
index dc13dca1fba656e31df0e79cd41ac28288bde373..e6522e3d364edd730a2b44c471a88f85cb69caa1 100644 (file)
@@ -96,7 +96,7 @@ class Target_i386 : public Sized_target<32, false>
     inline bool
     relocate(const Relocate_info<32, false>*, Target_i386*, size_t relnum,
             const elfcpp::Rel<32, false>&,
-            unsigned int r_type, Sized_symbol<32>*,
+            unsigned int r_type, const Sized_symbol<32>*,
             elfcpp::Elf_types<32>::Elf_Addr,
             unsigned char*, elfcpp::Elf_types<32>::Elf_Addr,
             off_t);
@@ -106,7 +106,7 @@ class Target_i386 : public Sized_target<32, false>
     inline void
     relocate_tls(const Relocate_info<32, false>*, size_t relnum,
                 const elfcpp::Rel<32, false>&,
-                unsigned int r_type, Sized_symbol<32>*,
+                unsigned int r_type, const Sized_symbol<32>*,
                 elfcpp::Elf_types<32>::Elf_Addr,
                 unsigned char*, elfcpp::Elf_types<32>::Elf_Addr, off_t);
 
@@ -529,7 +529,7 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
                                size_t relnum,
                                const elfcpp::Rel<32, false>& rel,
                                unsigned int r_type,
-                               Sized_symbol<32>* gsym,
+                               const Sized_symbol<32>* gsym,
                                elfcpp::Elf_types<32>::Elf_Addr value,
                                unsigned char* view,
                                elfcpp::Elf_types<32>::Elf_Addr address,
@@ -670,7 +670,7 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
                                    size_t relnum,
                                    const elfcpp::Rel<32, false>& rel,
                                    unsigned int r_type,
-                                   Sized_symbol<32>* gsym,
+                                   const Sized_symbol<32>* gsym,
                                    elfcpp::Elf_types<32>::Elf_Addr value,
                                    unsigned char* view,
                                    elfcpp::Elf_types<32>::Elf_Addr,
index bcb10295371700a96cce187b043b40b391a8d267..f9f55482ff44f0e2e8aab1667d11966e36637d54 100644 (file)
@@ -676,19 +676,24 @@ Layout::create_symtab_sections(int size, const Input_objects* input_objects,
   // Save space for the dummy symbol at the start of the section.  We
   // never bother to write this out--it will just be left as zero.
   off += symsize;
+  unsigned int local_symbol_index = 1;
 
   for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
        p != input_objects->relobj_end();
        ++p)
     {
       Task_lock_obj<Object> tlo(**p);
-      off = (*p)->finalize_local_symbols(off, &this->sympool_);
+      unsigned int index = (*p)->finalize_local_symbols(local_symbol_index,
+                                                       off,
+                                                       &this->sympool_);
+      off += (index - local_symbol_index) * symsize;
+      local_symbol_index = index;
     }
 
-  unsigned int local_symcount = (off - startoff) / symsize;
+  unsigned int local_symcount = local_symbol_index;
   assert(local_symcount * symsize == off - startoff);
 
-  off = symtab->finalize(off, &this->sympool_);
+  off = symtab->finalize(local_symcount, off, &this->sympool_);
 
   this->sympool_.set_string_offsets();
 
index 1bfd9698e06f3c98827bef16ce3048522b3299d1..74c1347712ee63e0d3c8c92a994606c3f63f563c 100644 (file)
@@ -128,7 +128,8 @@ Sized_relobj<size, big_endian>::Sized_relobj(
     output_local_symbol_count_(0),
     symbols_(NULL),
     local_symbol_offset_(0),
-    values_(NULL)
+    local_values_(),
+    local_indexes_()
 {
 }
 
@@ -505,23 +506,25 @@ Sized_relobj<size, big_endian>::do_add_symbols(Symbol_table* symtab,
 
 // Finalize the local symbols.  Here we record the file offset at
 // which they should be output, we add their names to *POOL, and we
-// add their values to THIS->VALUES_.  Return the new file offset.
-// This function is always called from the main thread.  The actual
-// output of the local symbols will occur in a separate task.
+// add their values to THIS->LOCAL_VALUES_ and their indexes in the
+// output symbol table to THIS->LOCAL_INDEXES_.  Return the symbol
+// index.  This function is always called from the main thread.  The
+// actual output of the local symbols will occur in a separate task.
 
 template<int size, bool big_endian>
-off_t
-Sized_relobj<size, big_endian>::do_finalize_local_symbols(off_t off,
+unsigned int
+Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index,
+                                                         off_t off,
                                                          Stringpool* pool)
 {
   assert(this->symtab_shndx_ != -1U);
   if (this->symtab_shndx_ == 0)
     {
       // This object has no symbols.  Weird but legal.
-      return off;
+      return index;
     }
 
-  off = align_address(off, size >> 3);
+  assert(off == static_cast<off_t>(align_address(off, size >> 3)));
 
   this->local_symbol_offset_ = off;
 
@@ -539,7 +542,8 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(off_t off,
   const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(),
                                              locsize);
 
-  this->values_ = new typename elfcpp::Elf_types<size>::Elf_Addr[loccount];
+  this->local_values_.resize(loccount);
+  this->local_indexes_.resize(loccount);
 
   // Read the symbol names.
   const unsigned int strtab_shndx = symtabshdr.get_sh_link();
@@ -550,7 +554,7 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(off_t off,
 
   // Loop over the local symbols.
 
-  std::vector<Map_to_output>& mo(this->map_to_output());
+  const std::vector<Map_to_output>& mo(this->map_to_output());
   unsigned int shnum = this->shnum();
   unsigned int count = 0;
   // Skip the first, dummy, symbol.
@@ -564,7 +568,7 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(off_t off,
       if (shndx >= elfcpp::SHN_LORESERVE)
        {
          if (shndx == elfcpp::SHN_ABS)
-           this->values_[i] = sym.get_st_value();
+           this->local_values_[i] = sym.get_st_value();
          else
            {
              // FIXME: Handle SHN_XINDEX.
@@ -588,37 +592,46 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(off_t off,
 
          if (mo[shndx].output_section == NULL)
            {
-             this->values_[i] = 0;
+             this->local_values_[i] = 0;
+             this->local_indexes_[i] = -1U;
              continue;
            }
 
-         this->values_[i] = (mo[shndx].output_section->address()
-                             + mo[shndx].offset
-                             + sym.get_st_value());
+         this->local_values_[i] = (mo[shndx].output_section->address()
+                                   + mo[shndx].offset
+                                   + sym.get_st_value());
        }
 
-      if (sym.get_st_type() != elfcpp::STT_SECTION)
+      // Decide whether this symbol should go into the output file.
+
+      if (sym.get_st_type() == elfcpp::STT_SECTION)
        {
-         if (sym.get_st_name() >= strtab_size)
-           {
-             fprintf(stderr,
-                     _("%s: %s: local symbol %u section name "
-                       "out of range: %u >= %u\n"),
-                     program_name, this->name().c_str(),
-                     i, sym.get_st_name(),
-                     static_cast<unsigned int>(strtab_size));
-             gold_exit(false);
-           }
+         this->local_indexes_[i] = -1U;
+         continue;
+       }
 
-         pool->add(pnames + sym.get_st_name(), NULL);
-         off += sym_size;
-         ++count;
+      if (sym.get_st_name() >= strtab_size)
+       {
+         fprintf(stderr,
+                 _("%s: %s: local symbol %u section name "
+                   "out of range: %u >= %u\n"),
+                 program_name, this->name().c_str(),
+                 i, sym.get_st_name(),
+                 static_cast<unsigned int>(strtab_size));
+         gold_exit(false);
        }
+
+      const char* name = pnames + sym.get_st_name();
+      pool->add(name, NULL);
+      this->local_indexes_[i] = index;
+      ++index;
+      off += sym_size;
+      ++count;
     }
 
   this->output_local_symbol_count_ = count;
 
-  return off;
+  return index;
 }
 
 // Write out the local symbols.
@@ -661,16 +674,20 @@ Sized_relobj<size, big_endian>::write_local_symbols(Output_file* of,
   unsigned char* oview = of->get_output_view(this->local_symbol_offset_,
                                             output_size);
 
-  std::vector<Map_to_output>& mo(this->map_to_output());
+  const std::vector<Map_to_output>& mo(this->map_to_output());
+
+  assert(this->local_values_.size() == loccount);
+  assert(this->local_indexes_.size() == loccount);
 
-  psyms += sym_size;
   unsigned char* ov = oview;
+  psyms += sym_size;
   for (unsigned int i = 1; i < loccount; ++i, psyms += sym_size)
     {
       elfcpp::Sym<size, big_endian> isym(psyms);
 
-      if (isym.get_st_type() == elfcpp::STT_SECTION)
+      if (this->local_indexes_[i] == -1U)
        continue;
+      assert(this->local_indexes_[i] != 0);
 
       unsigned int st_shndx = isym.get_st_shndx();
       if (st_shndx < elfcpp::SHN_LORESERVE)
@@ -684,8 +701,9 @@ Sized_relobj<size, big_endian>::write_local_symbols(Output_file* of,
       elfcpp::Sym_write<size, big_endian> osym(ov);
 
       assert(isym.get_st_name() < strtab_size);
-      osym.put_st_name(sympool->get_offset(pnames + isym.get_st_name()));
-      osym.put_st_value(this->values_[i]);
+      const char* name = pnames + isym.get_st_name();
+      osym.put_st_name(sympool->get_offset(name));
+      osym.put_st_value(this->local_values_[i]);
       osym.put_st_size(isym.get_st_size());
       osym.put_st_info(isym.get_st_info());
       osym.put_st_other(isym.get_st_other());
index 63613569493bea42cda021830def731026f86756..b2f470605cf6e9f9097fd3653ba462e013268766 100644 (file)
@@ -352,10 +352,10 @@ class Relobj : public Object
 
   // Initial local symbol processing: set the offset where local
   // symbol information will be stored; add local symbol names to
-  // *POOL; return the offset following the local symbols.
-  off_t
-  finalize_local_symbols(off_t off, Stringpool* pool)
-  { return this->do_finalize_local_symbols(off, pool); }
+  // *POOL; return the new local symbol index.
+  unsigned int
+  finalize_local_symbols(unsigned int index, off_t off, Stringpool* pool)
+  { return this->do_finalize_local_symbols(index, off, pool); }
 
   // Relocate the input sections and write out the local symbols.
   void
@@ -408,8 +408,8 @@ class Relobj : public Object
                 Read_relocs_data*) = 0;
 
   // Finalize local symbols--implemented by child class.
-  virtual off_t
-  do_finalize_local_symbols(off_t, Stringpool*) = 0;
+  virtual unsigned int
+  do_finalize_local_symbols(unsigned int, off_t, Stringpool*) = 0;
 
   // Relocate the input sections and write out the local
   // symbols--implemented by child class.
@@ -443,6 +443,9 @@ template<int size, bool big_endian>
 class Sized_relobj : public Relobj
 {
  public:
+  typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
+  typedef std::vector<Address> Local_values;
+
   Sized_relobj(const std::string& name, Input_file* input_file, off_t offset,
               const typename elfcpp::Ehdr<size, big_endian>&);
 
@@ -452,6 +455,16 @@ class Sized_relobj : public Relobj
   void
   setup(const typename elfcpp::Ehdr<size, big_endian>&);
 
+  // Return the index of local symbol SYM in the ordinary symbol
+  // table.  A value of -1U means that the symbol is not being output.
+  unsigned int
+  symtab_index(unsigned int sym) const
+  {
+    assert(sym < this->local_indexes_.size());
+    assert(this->local_indexes_[sym] != 0);
+    return this->local_indexes_[sym];
+  }
+
   // Read the symbols.
   void
   do_read_symbols(Read_symbols_data*);
@@ -475,8 +488,8 @@ class Sized_relobj : public Relobj
                 Read_relocs_data*);
 
   // Finalize the local symbols.
-  off_t
-  do_finalize_local_symbols(off_t, Stringpool*);
+  unsigned int
+  do_finalize_local_symbols(unsigned int, off_t, Stringpool*);
 
   // Relocate the input sections and write out the local symbols.
   void
@@ -563,7 +576,9 @@ class Sized_relobj : public Relobj
   // File offset for local symbols.
   off_t local_symbol_offset_;
   // Values of local symbols.
-  typename elfcpp::Elf_types<size>::Elf_Addr *values_;
+  Local_values local_values_;
+  // Indexes of local symbols in the output file; -1U if not present.
+  std::vector<unsigned int> local_indexes_;
 };
 
 // A class to manage the list of all objects.
@@ -643,9 +658,9 @@ struct Relocate_info
   // Number of local symbols.
   unsigned int local_symbol_count;
   // Values of local symbols.
-  typename elfcpp::Elf_types<size>::Elf_Addr *values;
+  const typename Sized_relobj<size, big_endian>::Local_values* local_values;
   // Global symbols.
-  Symbol** symbols;
+  const Symbol* const * symbols;
   // Section index of relocation section.
   unsigned int reloc_shndx;
   // Section index of section being relocated.
index aba8ee170596670a664c2521fd823540da7e9454..0330384fac34ab5afaf14f916b417a5bf82f23e9 100644 (file)
@@ -366,6 +366,120 @@ Output_section_data::do_out_shndx() const
   return this->output_section_->out_shndx();
 }
 
+// Output_reloc methods.
+
+// Get the symbol index of a relocation.
+
+template<bool dynamic, int size, bool big_endian>
+unsigned int
+Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::get_symbol_index()
+  const
+{
+  unsigned int index;
+  switch (this->local_sym_index_)
+    {
+    case INVALID_CODE:
+      abort();
+
+    case GSYM_CODE:
+      if (this->u_.gsym == NULL)
+       index = 0;
+      else if (dynamic)
+       index = this->u_.gsym->dynsym_index();
+      else
+       index = this->u_.gsym->symtab_index();
+      break;
+
+    case SECTION_CODE:
+      if (dynamic)
+       index = this->u_.os->dynsym_index();
+      else
+       index = this->u_.os->symtab_index();
+      break;
+
+    default:
+      if (dynamic)
+       {
+         // FIXME: It seems that some targets may need to generate
+         // dynamic relocations against local symbols for some
+         // reasons.  This will have to be addressed at some point.
+         abort();
+       }
+      else
+       index = this->u_.object->symtab_index(this->local_sym_index_);
+      break;
+    }
+  assert(index != -1U);
+  return index;
+}
+
+// Write out the offset and info fields of a Rel or Rela relocation
+// entry.
+
+template<bool dynamic, int size, bool big_endian>
+template<typename Write_rel>
+void
+Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::write_rel(
+    Write_rel* wr) const
+{
+  wr->put_r_offset(this->address_);
+  wr->put_r_info(elfcpp::elf_r_info<size>(this->get_symbol_index(),
+                                         this->type_));
+}
+
+// Write out a Rel relocation.
+
+template<bool dynamic, int size, bool big_endian>
+void
+Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::write(
+    unsigned char* pov) const
+{
+  elfcpp::Rel_write<size, big_endian> orel(pov);
+  this->write_rel(&orel);
+}
+
+// Write out a Rela relocation.
+
+template<bool dynamic, int size, bool big_endian>
+void
+Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>::write(
+    unsigned char* pov) const
+{
+  elfcpp::Rela_write<size, big_endian> orel(pov);
+  this->rel_.write_rel(&orel);
+  orel.put_r_addend(this->addend_);
+}
+
+// Output_data_reloc_base methods.
+
+// Write out relocation data.
+
+template<int sh_type, bool dynamic, int size, bool big_endian>
+void
+Output_data_reloc_base<sh_type, dynamic, size, big_endian>::do_write(
+    Output_file* of)
+{
+  const off_t off = this->offset();
+  const off_t oview_size = this->data_size();
+  unsigned char* const oview = of->get_output_view(off, oview_size);
+
+  unsigned char* pov = oview;
+  for (typename Relocs::const_iterator p = this->relocs_.begin();
+       p != this->relocs_.end();
+       ++p)
+    {
+      p->write(pov);
+      pov += reloc_size;
+    }
+
+  assert(pov - oview == oview_size);
+
+  of->write_output_view(off, oview_size, oview);
+
+  // We no longer need the relocation entries.
+  this->relocs_.clear();
+}
+
 // Output_data_got::Got_entry methods.
 
 // Write out the entry.
@@ -439,7 +553,7 @@ Output_data_got<size, big_endian>::do_write(Output_file* of)
   const int add = size / 8;
 
   const off_t off = this->offset();
-  const off_t oview_size = this->entries_.size() * add;
+  const off_t oview_size = this->data_size();
   unsigned char* const oview = of->get_output_view(off, oview_size);
 
   unsigned char* pov = oview;
@@ -451,6 +565,8 @@ Output_data_got<size, big_endian>::do_write(Output_file* of)
       pov += add;
     }
 
+  assert(pov - oview == oview_size);
+
   of->write_output_view(off, oview_size, oview);
 
   // We no longer need the GOT entries.
@@ -508,6 +624,8 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
     type_(type),
     flags_(flags),
     out_shndx_(0),
+    symtab_index_(0),
+    dynsym_index_(0),
     input_sections_(),
     first_input_offset_(0),
     may_add_data_(may_add_data)
@@ -564,12 +682,17 @@ Output_section::add_input_section(Relobj* object, unsigned int shndx,
 void
 Output_section::add_output_section_data(Output_section_data* posd)
 {
+  assert(this->may_add_data_);
+
   if (this->input_sections_.empty())
     this->first_input_offset_ = this->data_size();
+
   this->input_sections_.push_back(Input_section(posd));
+
   uint64_t addralign = posd->addralign();
   if (addralign > this->addralign_)
     this->addralign_ = addralign;
+
   posd->set_output_section(this);
 }
 
@@ -627,14 +750,6 @@ Output_section::do_write(Output_file* of)
     p->write(of);
 }
 
-// Output_section_symtab methods.
-
-Output_section_symtab::Output_section_symtab(const char* name, off_t size)
-  : Output_section(name, elfcpp::SHT_SYMTAB, 0, false)
-{
-  this->set_data_size(size);
-}
-
 // Output_section_strtab methods.
 
 Output_section_strtab::Output_section_strtab(const char* name,
@@ -1143,6 +1258,54 @@ Output_section::add_input_section<64, true>(
     const char* secname,
     const elfcpp::Shdr<64, true>& shdr);
 
+template
+class Output_data_reloc<elfcpp::SHT_REL, false, 32, false>;
+
+template
+class Output_data_reloc<elfcpp::SHT_REL, false, 32, true>;
+
+template
+class Output_data_reloc<elfcpp::SHT_REL, false, 64, false>;
+
+template
+class Output_data_reloc<elfcpp::SHT_REL, false, 64, true>;
+
+template
+class Output_data_reloc<elfcpp::SHT_REL, true, 32, false>;
+
+template
+class Output_data_reloc<elfcpp::SHT_REL, true, 32, true>;
+
+template
+class Output_data_reloc<elfcpp::SHT_REL, true, 64, false>;
+
+template
+class Output_data_reloc<elfcpp::SHT_REL, true, 64, true>;
+
+template
+class Output_data_reloc<elfcpp::SHT_RELA, false, 32, false>;
+
+template
+class Output_data_reloc<elfcpp::SHT_RELA, false, 32, true>;
+
+template
+class Output_data_reloc<elfcpp::SHT_RELA, false, 64, false>;
+
+template
+class Output_data_reloc<elfcpp::SHT_RELA, false, 64, true>;
+
+template
+class Output_data_reloc<elfcpp::SHT_RELA, true, 32, false>;
+
+template
+class Output_data_reloc<elfcpp::SHT_RELA, true, 32, true>;
+
+template
+class Output_data_reloc<elfcpp::SHT_RELA, true, 64, false>;
+
+template
+class Output_data_reloc<elfcpp::SHT_RELA, true, 64, true>;
+
 template
 class Output_data_got<32, false>;
 
index 9763d7490189a7508523787b67e368a04370147c..c31640f0c861861ff525713963f6214d3b676435 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "elfcpp.h"
 #include "layout.h"
+#include "reloc-types.h"
 
 namespace gold
 {
@@ -16,9 +17,11 @@ namespace gold
 class General_options;
 class Object;
 class Output_file;
-
+class Output_section;
 template<int size, bool big_endian>
 class Sized_target;
+template<int size, bool big_endian>
+class Sized_relobj;
 
 // An abtract class for data which has to go into the output file.
 
@@ -361,6 +364,262 @@ class Output_data_common : public Output_section_data
   { }
 };
 
+// This POD class is used to represent a single reloc in the output
+// file.  This could be a private class within Output_data_reloc, but
+// the templatization is complex enough that I broke it out into a
+// separate class.  The class is templatized on either elfcpp::SHT_REL
+// or elfcpp::SHT_RELA, and also on whether this is a dynamic
+// relocation or an ordinary relocation.
+
+// A relocation can be against a global symbol, a local symbol, an
+// output section, or the undefined symbol at index 0.  We represent
+// the latter by using a NULL global symbol.
+
+template<int sh_type, bool dynamic, int size, bool big_endian>
+class Output_reloc;
+
+template<bool dynamic, int size, bool big_endian>
+class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
+{
+ public:
+  typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
+
+  // An uninitialized entry.  We need this because we want to put
+  // instances of this class into an STL container.
+  Output_reloc()
+    : local_sym_index_(INVALID_CODE)
+  { }
+
+  // A reloc against a global symbol.
+  Output_reloc(Symbol* gsym, unsigned int type, Address address)
+    : local_sym_index_(GSYM_CODE), type_(type), address_(address)
+  { this->u_.gsym = gsym; }
+
+  // A reloc against a local symbol.
+  Output_reloc(Sized_relobj<size, big_endian>* object,
+              unsigned int local_sym_index,
+              unsigned int type, Address address)
+    : local_sym_index_(local_sym_index), type_(type), address_(address)
+  {
+    assert(local_sym_index != GSYM_CODE && local_sym_index != INVALID_CODE);
+    this->u_.object = object;
+  }
+
+  // A reloc against the STT_SECTION symbol of an output section.
+  Output_reloc(Output_section* os, unsigned int type, Address address)
+    : local_sym_index_(SECTION_CODE), type_(type), address_(address)
+  { this->u_.os = os; }
+
+  // Write the reloc entry to an output view.
+  void
+  write(unsigned char* pov) const;
+
+  // Write the offset and info fields to Write_rel.
+  template<typename Write_rel>
+  void write_rel(Write_rel*) const;
+
+ private:
+  // Return the symbol index.  We can't do a double template
+  // specialization, so we do a secondary template here.
+  unsigned int
+  get_symbol_index() const;
+
+  // Codes for local_sym_index_.
+  enum
+  {
+    // Global symbol.
+    GSYM_CODE = -1U,
+    // Output section.
+    SECTION_CODE = -2U,
+    // Invalid uninitialized entry.
+    INVALID_CODE = -3U
+  };
+
+  union
+  {
+    // For a local symbol, the object.  We will never generate a
+    // relocation against a local symbol in a dynamic object; that
+    // doesn't make sense.  And our callers will always be
+    // templatized, so we use Sized_relobj here.
+    Sized_relobj<size, big_endian>* object;
+    // For a global symbol, the symbol.  If this is NULL, it indicates
+    // a relocation against the undefined 0 symbol.
+    Symbol* gsym;
+    // For a relocation against an output section, the output section.
+    Output_section* os;
+  } u_;
+  // For a local symbol, the local symbol index.  This is GSYM_CODE
+  // for a global symbol, or INVALID_CODE for an uninitialized value.
+  unsigned int local_sym_index_;
+  unsigned int type_;
+  Address address_;
+};
+
+// The SHT_RELA version of Output_reloc<>.  This is just derived from
+// the SHT_REL version of Output_reloc, but it adds an addend.
+
+template<bool dynamic, int size, bool big_endian>
+class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
+{
+ public:
+  typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
+  typedef typename elfcpp::Elf_types<size>::Elf_Addr Addend;
+
+  // An uninitialized entry.
+  Output_reloc()
+    : rel_()
+  { }
+
+  // A reloc against a global symbol.
+  Output_reloc(Symbol* gsym, unsigned int type, Address address, Addend addend)
+    : rel_(gsym, type, address), addend_(addend)
+  { }
+
+  // A reloc against a local symbol.
+  Output_reloc(Sized_relobj<size, big_endian>* object,
+              unsigned int local_sym_index,
+              unsigned int type, Address address, Addend addend)
+    : rel_(object, local_sym_index, type, address), addend_(addend)
+  { }
+
+  // A reloc against the STT_SECTION symbol of an output section.
+  Output_reloc(Output_section* os, unsigned int type, Address address,
+              Addend addend)
+    : rel_(os, type, address), addend_(addend)
+  { }
+
+  // Write the reloc entry to an output view.
+  void
+  write(unsigned char* pov) const;
+
+ private:
+  // The basic reloc.
+  Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> rel_;
+  // The addend.
+  Addend addend_;
+};
+
+// Output_data_reloc is used to manage a section containing relocs.
+// SH_TYPE is either elfcpp::SHT_REL or elfcpp::SHT_RELA.  DYNAMIC
+// indicates whether this is a dynamic relocation or a normal
+// relocation.  Output_data_reloc_base is a base class.
+// Output_data_reloc is the real class, which we specialize based on
+// the reloc type.
+
+template<int sh_type, bool dynamic, int size, bool big_endian>
+class Output_data_reloc_base : public Output_section_data
+{
+ public:
+  typedef Output_reloc<sh_type, dynamic, size, big_endian> Output_reloc_type;
+  typedef typename Output_reloc_type::Address Address;
+  static const int reloc_size =
+    Reloc_types<sh_type, size, big_endian>::reloc_size;
+
+  // Construct the section.
+  Output_data_reloc_base()
+    : Output_section_data(Output_data::default_alignment(size))
+  { }
+
+  // Write out the data.
+  void
+  do_write(Output_file*);
+
+ protected:
+  // Add a relocation entry.
+  void
+  add(const Output_reloc_type& reloc)
+  {
+    this->relocs_.push_back(reloc);
+    this->set_data_size(this->relocs_.size() * reloc_size);
+  }
+
+ private:
+  typedef std::vector<Output_reloc_type> Relocs;
+
+  Relocs relocs_;
+};
+
+// The class which callers actually create.
+
+template<int sh_type, bool dynamic, int size, bool big_endian>
+class Output_data_reloc;
+
+// The SHT_REL version of Output_data_reloc.
+
+template<bool dynamic, int size, bool big_endian>
+class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
+  : public Output_data_reloc_base<elfcpp::SHT_REL, dynamic, size, big_endian>
+{
+ private: 
+  typedef Output_data_reloc_base<elfcpp::SHT_REL, dynamic, size,
+                                big_endian> Base;
+
+ public:
+  typedef typename Base::Output_reloc_type Output_reloc_type;
+  typedef typename Output_reloc_type::Address Address;
+
+  Output_data_reloc()
+    : Output_data_reloc_base<elfcpp::SHT_REL, dynamic, size, big_endian>()
+  { }
+
+  // Add a reloc against a global symbol.
+  void
+  add_global(Symbol* gsym, unsigned int type, Address address)
+  { this->add(Output_reloc_type(gsym, type, address)); }
+
+  // Add a reloc against a local symbol.
+  void
+  add_local(Sized_relobj<size, big_endian>* object,
+           unsigned int local_sym_index, unsigned int type, Address address)
+  { this->add(Output_reloc_type(object, local_sym_index, type, address)); }
+
+  // A reloc against the STT_SECTION symbol of an output section.
+  void
+  add_output_section(Output_section* os, unsigned int type, Address address)
+  { this->add(Output_reloc_type(os, type, address)); }
+};
+
+// The SHT_RELA version of Output_data_reloc.
+
+template<bool dynamic, int size, bool big_endian>
+class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
+  : public Output_data_reloc_base<elfcpp::SHT_RELA, dynamic, size, big_endian>
+{
+ private: 
+  typedef Output_data_reloc_base<elfcpp::SHT_RELA, dynamic, size,
+                                big_endian> Base;
+
+ public:
+  typedef typename Base::Output_reloc_type Output_reloc_type;
+  typedef typename Output_reloc_type::Address Address;
+  typedef typename Output_reloc_type::Addend Addend;
+
+  Output_data_reloc()
+    : Output_data_reloc_base<elfcpp::SHT_RELA, dynamic, size, big_endian>()
+  { }
+
+  // Add a reloc against a global symbol.
+  void
+  add_global(Symbol* gsym, unsigned int type, Address address, Addend addend)
+  { this->add(Output_reloc_type(gsym, type, address, addend)); }
+
+  // Add a reloc against a local symbol.
+  void
+  add_local(Sized_relobj<size, big_endian>* object,
+           unsigned int local_sym_index, unsigned int type,
+           Address address, Addend addend)
+  {
+    this->add(Output_reloc_type(object, local_sym_index, type, address,
+                               addend));
+  }
+
+  // A reloc against the STT_SECTION symbol of an output section.
+  void
+  add_output_section(Output_section* os, unsigned int type, Address address,
+                    Addend addend)
+  { this->add(Output_reloc_type(os, type, address, addend)); }
+};
+
 // Output_data_got is used to manage a GOT.  Each entry in the GOT is
 // for one symbol--either a global symbol or a local symbol in an
 // object.  The target specific code adds entries to the GOT as
@@ -456,8 +715,8 @@ class Output_data_got : public Output_section_data
       // For a constant, the constant.
       Valtype constant;
     } u_;
-    // For a local symbol, the local symbol index.  This is -1U for a
-    // global symbol, or -2U for a constant.
+    // For a local symbol, the local symbol index.  This is GSYM_CODE
+    // for a global symbol, or CONSTANT_CODE for a constant.
     unsigned int local_sym_index_;
   };
 
@@ -501,7 +760,7 @@ class Output_section : public Output_data
                    const elfcpp::Shdr<size, big_endian>& shdr);
 
   // Add generated data ODATA to this output section.
-  virtual void
+  void
   add_output_section_data(Output_section_data* posd);
 
   // Return the section name.
@@ -549,6 +808,58 @@ class Output_section : public Output_data
   set_addralign(uint64_t v)
   { this->addralign_ = v; }
 
+  // Indicate that we need a symtab index.
+  void
+  set_needs_symtab_index()
+  { this->needs_symtab_index_ = true; }
+
+  // Return whether we need a symtab index.
+  bool
+  needs_symtab_index() const
+  { return this->needs_symtab_index_; }
+
+  // Get the symtab index.
+  unsigned int
+  symtab_index() const
+  {
+    assert(this->symtab_index_ != 0);
+    return this->symtab_index_;
+  }
+
+  // Set the symtab index.
+  void
+  set_symtab_index(unsigned int index)
+  {
+    assert(index != 0);
+    this->symtab_index_ = index;
+  }
+
+  // Indicate that we need a dynsym index.
+  void
+  set_needs_dynsym_index()
+  { this->needs_dynsym_index_ = true; }
+
+  // Return whether we need a dynsym index.
+  bool
+  needs_dynsym_index() const
+  { return this->needs_dynsym_index_; }
+
+  // Get the dynsym index.
+  unsigned int
+  dynsym_index() const
+  {
+    assert(this->dynsym_index_ != 0);
+    return this->dynsym_index_;
+  }
+
+  // Set the dynsym index.
+  void
+  set_dynsym_index(unsigned int index)
+  {
+    assert(index != 0);
+    this->dynsym_index_ = index;
+  }
+
   // Set the address of the Output_section.  For a typical
   // Output_section, there is nothing to do, but if there are any
   // Output_section_data objects we need to set the final addresses
@@ -686,13 +997,31 @@ class Output_section : public Output_data
   elfcpp::Elf_Xword flags_;
   // The section index.
   unsigned int out_shndx_;
+  // If there is a STT_SECTION for this output section in the normal
+  // symbol table, this is the symbol index.  This starts out as zero.
+  // It is initialized in Layout::finalize() to be the index, or -1U
+  // if there isn't one.
+  unsigned int symtab_index_;
+  // If there is a STT_SECTION for this output section in the dynamic
+  // symbol table, this is the symbol index.  This starts out as zero.
+  // It is initialized in Layout::finalize() to be the index, or -1U
+  // if there isn't one.
+  unsigned int dynsym_index_;
   // The input sections.  This will be empty in cases where we don't
   // need to keep track of them.
   Input_section_list input_sections_;
   // The offset of the first entry in input_sections_.
   off_t first_input_offset_;
   // Whether we permit adding data.
-  bool may_add_data_;
+  bool may_add_data_ : 1;
+  // Whether this output section needs a STT_SECTION symbol in the
+  // normal symbol table.  This will be true if there is a relocation
+  // which needs it.
+  bool needs_symtab_index_ : 1;
+  // Whether this output section needs a STT_SECTION symbol in the
+  // dynamic symbol table.  This will be true if there is a dynamic
+  // relocation which needs it.
+  bool needs_dynsym_index_ : 1;
 };
 
 // A special Output_section which represents the symbol table
@@ -702,18 +1031,33 @@ class Output_section : public Output_data
 class Output_section_symtab : public Output_section
 {
  public:
-  Output_section_symtab(const char* name, off_t size);
+  Output_section_symtab(const char* name, off_t data_size)
+    : Output_section(name, elfcpp::SHT_SYMTAB, 0, false)
+  { this->set_data_size(data_size); }
 
   // The data is written out by Symbol_table::write_globals.  We don't
   // do anything here.
   void
   do_write(Output_file*)
   { }
+};
+
+// A special Output_section which represents the dynamic symbol table
+// (SHT_DYNSYM).  The actual data is written out by
+// Symbol_table::write_globals.
+
+class Output_section_dynsym : public Output_section
+{
+ public:
+  Output_section_dynsym(const char* name, off_t data_size)
+    : Output_section(name, elfcpp::SHT_DYNSYM, 0, false)
+  { this->set_data_size(data_size); }
 
-  // We don't expect to see any input sections or data here.
+  // The data is written out by Symbol_table::write_globals.  We don't
+  // do anything here.
   void
-  add_output_section_data(Output_section_data*)
-  { abort(); }
+  do_write(Output_file*)
+  { }
 };
 
 // A special Output_section which holds a string table.
@@ -727,11 +1071,6 @@ class Output_section_strtab : public Output_section
   void
   do_write(Output_file*);
 
-  // We don't expect to see any input sections or data here.
-  void
-  add_output_section_data(Output_section_data*)
-  { abort(); }
-
  private:
   Stringpool* contents_;
 };
index d13ddf5ab027ea265f8107f431e4d982c3c23ced..834e31aacb08bbcad7153acd9dd789a07e22d125 100644 (file)
@@ -27,8 +27,10 @@ readsyms.cc
 readsyms.h
 reloc.cc
 reloc.h
+reloc-types.h
 resolve.cc
 script.cc
+script-c.h
 script.h
 stringpool.cc
 stringpool.h
index c002c5c3411be05a3f04bdbbdedb41a183acb296..b5725e50fc495070e590ff83a949606bd92fd2a5 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2006-11-14 11:17-0800\n"
+"POT-Creation-Date: 2006-11-15 16:35-0800\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -101,7 +101,7 @@ msgstr ""
 msgid "%s: %s: dynamic symbol table name section has wrong type: %u\n"
 msgstr ""
 
-#: dynobj.cc:356 object.cc:421
+#: dynobj.cc:356 object.cc:422
 #, c-format
 msgid "%s: %s: bad section name offset for section %u: %lu\n"
 msgstr ""
@@ -300,87 +300,87 @@ msgstr ""
 msgid "%s: %s: section name section has wrong type: %u\n"
 msgstr ""
 
-#: object.cc:229
+#: object.cc:230
 #, c-format
 msgid "%s: %s: invalid symbol table name index: %u\n"
 msgstr ""
 
-#: object.cc:237
+#: object.cc:238
 #, c-format
 msgid "%s: %s: symbol table name section has wrong type: %u\n"
 msgstr ""
 
-#: object.cc:293
+#: object.cc:294
 #, c-format
 msgid "%s: %s: section group %u info %u out of range\n"
 msgstr ""
 
-#: object.cc:310
+#: object.cc:311
 #, c-format
 msgid "%s: %s: symbol %u name offset %u out of range\n"
 msgstr ""
 
-#: object.cc:344
+#: object.cc:345
 #, c-format
 msgid "%s: %s: section %u in section group %u out of range"
 msgstr ""
 
-#: object.cc:488
+#: object.cc:489
 #, c-format
 msgid "%s: %s: size of symbols is not multiple of symbol size\n"
 msgstr ""
 
-#: object.cc:572
+#: object.cc:576
 #, c-format
 msgid "%s: %s: unknown section index %u for local symbol %u\n"
 msgstr ""
 
-#: object.cc:583
+#: object.cc:587
 #, c-format
 msgid "%s: %s: local symbol %u section index %u out of range\n"
 msgstr ""
 
-#: object.cc:605
+#: object.cc:616
 #, c-format
 msgid "%s: %s: local symbol %u section name out of range: %u >= %u\n"
 msgstr ""
 
-#: object.cc:782
+#: object.cc:800
 #, c-format
 msgid "%s: %s: unsupported ELF file type %d\n"
 msgstr ""
 
-#: object.cc:801 object.cc:854 object.cc:875
+#: object.cc:819 object.cc:872 object.cc:893
 #, c-format
 msgid "%s: %s: ELF file too short\n"
 msgstr ""
 
-#: object.cc:810
+#: object.cc:828
 #, c-format
 msgid "%s: %s: invalid ELF version 0\n"
 msgstr ""
 
-#: object.cc:813
+#: object.cc:831
 #, c-format
 msgid "%s: %s: unsupported ELF version %d\n"
 msgstr ""
 
-#: object.cc:821
+#: object.cc:839
 #, c-format
 msgid "%s: %s: invalid ELF class 0\n"
 msgstr ""
 
-#: object.cc:828
+#: object.cc:846
 #, c-format
 msgid "%s: %s: unsupported ELF class %d\n"
 msgstr ""
 
-#: object.cc:836
+#: object.cc:854
 #, c-format
 msgid "%s: %s: invalid ELF data encoding\n"
 msgstr ""
 
-#: object.cc:843
+#: object.cc:861
 #, c-format
 msgid "%s: %s: unsupported ELF data encoding %d\n"
 msgstr ""
@@ -496,37 +496,37 @@ msgstr ""
 msgid "%s: -%c: %s\n"
 msgstr ""
 
-#: output.cc:538
+#: output.cc:656
 #, c-format
 msgid "%s: %s: invalid alignment %lu for section \"%s\"\n"
 msgstr ""
 
-#: output.cc:1056
+#: output.cc:1171
 #, c-format
 msgid "%s: %s: open: %s\n"
 msgstr ""
 
-#: output.cc:1065
+#: output.cc:1180
 #, c-format
 msgid "%s: %s: lseek: %s\n"
 msgstr ""
 
-#: output.cc:1072
+#: output.cc:1187
 #, c-format
 msgid "%s: %s: write: %s\n"
 msgstr ""
 
-#: output.cc:1082
+#: output.cc:1197
 #, c-format
 msgid "%s: %s: mmap: %s\n"
 msgstr ""
 
-#: output.cc:1096
+#: output.cc:1211
 #, c-format
 msgid "%s: %s: munmap: %s\n"
 msgstr ""
 
-#: output.cc:1104
+#: output.cc:1219
 #, c-format
 msgid "%s: %s: close: %s\n"
 msgstr ""
@@ -567,62 +567,62 @@ msgstr ""
 msgid "%s: %s: reloc section %u size %lu uneven"
 msgstr ""
 
-#: resolve.cc:141
+#: resolve.cc:142
 #, c-format
 msgid "%s: %s: invalid STB_LOCAL symbol %s in external symbols\n"
 msgstr ""
 
-#: resolve.cc:147
+#: resolve.cc:148
 #, c-format
 msgid "%s: %s: unsupported symbol binding %d for symbol %s\n"
 msgstr ""
 
-#: symtab.cc:443 symtab.cc:540
+#: symtab.cc:446 symtab.cc:543
 #, c-format
 msgid "%s: %s: mixing 32-bit and 64-bit ELF objects\n"
 msgstr ""
 
-#: symtab.cc:460
+#: symtab.cc:463
 #, c-format
 msgid "%s: %s: bad global symbol name offset %u at %lu\n"
 msgstr ""
 
-#: symtab.cc:547
+#: symtab.cc:550
 #, c-format
 msgid "%s: %s: too few symbol versions\n"
 msgstr ""
 
-#: symtab.cc:567
+#: symtab.cc:570
 #, c-format
 msgid "%s: %s: bad symbol name offset %u at %lu\n"
 msgstr ""
 
-#: symtab.cc:611
+#: symtab.cc:614
 #, c-format
 msgid "%s: %s: versym for symbol %zu out of range: %u\n"
 msgstr ""
 
-#: symtab.cc:619
+#: symtab.cc:622
 #, c-format
 msgid "%s: %s: versym for symbol %zu has no name: %u\n"
 msgstr ""
 
-#: symtab.cc:1010 symtab.cc:1149
+#: symtab.cc:1019 symtab.cc:1158
 #, c-format
 msgid "%s: %s: unsupported symbol section 0x%x\n"
 msgstr ""
 
-#: symtab.cc:1262
+#: symtab.cc:1274
 #, c-format
 msgid "%s: %s: warning: %s\n"
 msgstr ""
 
-#: target-reloc.h:181
+#: target-reloc.h:163
 #, c-format
 msgid "%s: %s: reloc has bad offset %zu\n"
 msgstr ""
 
-#: target-reloc.h:191
+#: target-reloc.h:173
 #, c-format
 msgid "%s: %s: undefined reference to '%s'\n"
 msgstr ""
diff --git a/gold/reloc-types.h b/gold/reloc-types.h
new file mode 100644 (file)
index 0000000..62538d6
--- /dev/null
@@ -0,0 +1,36 @@
+// reloc-types.h -- ELF relocation templates for gold  -*- C++ -*-
+
+// This header files defines a few convenient templated types for use
+// when handling ELF relocations.
+
+#ifndef GOLD_RELOC_TYPES_H
+#define GOLD_RELOC_TYPES_H
+
+#include "elfcpp.h"
+
+namespace gold
+{
+
+// Pick the ELF relocation accessor class and the size based on
+// SH_TYPE, which is either elfcpp::SHT_REL or elfcpp::SHT_RELA.
+
+template<int sh_type, int size, bool big_endian>
+struct Reloc_types;
+
+template<int size, bool big_endian>
+struct Reloc_types<elfcpp::SHT_REL, size, big_endian>
+{
+  typedef typename elfcpp::Rel<size, big_endian> Reloc;
+  static const int reloc_size = elfcpp::Elf_sizes<size>::rel_size;
+};
+
+template<int size, bool big_endian>
+struct Reloc_types<elfcpp::SHT_RELA, size, big_endian>
+{
+  typedef typename elfcpp::Rela<size, big_endian> Reloc;
+  static const int reloc_size = elfcpp::Elf_sizes<size>::rela_size;
+};
+
+}; // End namespace gold.
+
+#endif // !defined(GOLD_RELOC_TYPE_SH)
index dd3eef12fee623e9b6e96d4c63e8e9017ebf6523..ce6af0bd0e39245e8155b6df86d8746659367da0 100644 (file)
@@ -391,7 +391,7 @@ Sized_relobj<size, big_endian>::relocate_sections(
   relinfo.layout = layout;
   relinfo.object = this;
   relinfo.local_symbol_count = this->local_symbol_count_;
-  relinfo.values = this->values_;
+  relinfo.local_values = &this->local_values_;
   relinfo.symbols = this->symbols_;
 
   const unsigned char* p = pshdrs + This::shdr_size;
index 86645a4a188eb95b227e8c624a3692e9b159b9ff..2b6d65cd6b83d098d1f9b091a29c2e674a076e17 100644 (file)
@@ -106,7 +106,8 @@ Symbol_table::resolve(Sized_symbol<size>* to,
       abort();
     }
 
-  if (to->object() != NULL && to->object()->is_dynamic())
+  if (to->source() == Symbol::FROM_OBJECT
+      && to->object()->is_dynamic())
     tobits |= (1 << 1);
 
   switch (to->shnum())
@@ -174,6 +175,15 @@ Symbol_table::resolve(Sized_symbol<size>* to,
       break;
     }
 
+  if ((tobits & (1 << 1)) != (frombits & (1 << 1)))
+    {
+      // This symbol is seen in both a dynamic object and a regular
+      // object.  That means that we need the symbol to go into the
+      // dynamic symbol table, so that the dynamic linker can use the
+      // regular symbol to override or define the dynamic symbol.
+      to->set_needs_dynsym_entry();
+    }
+
   // FIXME: Warn if either but not both of TO and SYM are STT_TLS.
 
   // We use a giant switch table for symbol resolution.  This code is
index 9279d265672c2623cd9755bd5852dfd698606038..92d558376082cd3f64dbb2caccb6498886d978bb 100644 (file)
@@ -29,6 +29,8 @@ Symbol::init_fields(const char* name, const char* version,
 {
   this->name_ = name;
   this->version_ = version;
+  this->symtab_index_ = 0;
+  this->dynsym_index_ = 0;
   this->got_offset_ = 0;
   this->type_ = type;
   this->binding_ = binding;
@@ -37,6 +39,7 @@ Symbol::init_fields(const char* name, const char* version,
   this->is_target_special_ = false;
   this->is_def_ = false;
   this->is_forwarder_ = false;
+  this->needs_dynsym_entry_ = false;
   this->in_dyn_ = false;
   this->has_got_offset_ = false;
   this->has_warning_ = false;
@@ -204,10 +207,10 @@ Symbol_table::make_forwarder(Symbol* from, Symbol* to)
 // Resolve the forwards from FROM, returning the real symbol.
 
 Symbol*
-Symbol_table::resolve_forwards(Symbol* from) const
+Symbol_table::resolve_forwards(const Symbol* from) const
 {
   assert(from->is_forwarder());
-  Unordered_map<Symbol*, Symbol*>::const_iterator p =
+  Unordered_map<const Symbol*, Symbol*>::const_iterator p =
     this->forwarders_.find(from);
   assert(p != this->forwarders_.end());
   return p->second;
@@ -952,18 +955,22 @@ Symbol_table::define_symbols(const Layout* layout, Target* target, int count,
     }
 }
 
-// Set the final values for all the symbols.  Record the file offset
+// Set the final values for all the symbols.  The index of the first
+// global symbol in the output file is INDEX.  Record the file offset
 // OFF.  Add their names to POOL.  Return the new file offset.
 
 off_t
-Symbol_table::finalize(off_t off, Stringpool* pool)
+Symbol_table::finalize(unsigned int index, off_t off, Stringpool* pool)
 {
   off_t ret;
 
+  assert(index != 0);
+  this->first_global_index_ = index;
+
   if (this->size_ == 32)
-    ret = this->sized_finalize<32>(off, pool);
+    ret = this->sized_finalize<32>(index, off, pool);
   else if (this->size_ == 64)
-    ret = this->sized_finalize<64>(off, pool);
+    ret = this->sized_finalize<64>(index, off, pool);
   else
     abort();
 
@@ -980,15 +987,17 @@ Symbol_table::finalize(off_t off, Stringpool* pool)
 
 template<int size>
 off_t
-Symbol_table::sized_finalize(off_t off, Stringpool* pool)
+Symbol_table::sized_finalize(unsigned index, off_t off, Stringpool* pool)
 {
   off = align_address(off, size >> 3);
   this->offset_ = off;
 
+  size_t orig_index = index;
+
   const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
-  Symbol_table_type::iterator p = this->table_.begin();
-  size_t count = 0;
-  while (p != this->table_.end())
+  for (Symbol_table_type::iterator p = this->table_.begin();
+       p != this->table_.end();
+       ++p)
     {
       Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(p->second);
 
@@ -1030,12 +1039,7 @@ Symbol_table::sized_finalize(off_t off, Stringpool* pool)
 
                if (os == NULL)
                  {
-                   // We should be able to erase this symbol from the
-                   // symbol table, but at least with gcc 4.0.2
-                   // std::unordered_map::erase doesn't appear to return
-                   // the new iterator.
-                   // p = this->table_.erase(p);
-                   ++p;
+                   sym->set_symtab_index(-1U);
                    continue;
                  }
 
@@ -1082,13 +1086,13 @@ Symbol_table::sized_finalize(off_t off, Stringpool* pool)
        }
 
       sym->set_value(value);
+      sym->set_symtab_index(index);
       pool->add(sym->name(), NULL);
-      ++count;
+      ++index;
       off += sym_size;
-      ++p;
     }
 
-  this->output_count_ = count;
+  this->output_count_ = index - orig_index;
 
   return off;
 }
@@ -1126,8 +1130,10 @@ Symbol_table::sized_write_globals(const Target*,
                                  Output_file* of) const
 {
   const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
-  unsigned char* psyms = of->get_output_view(this->offset_,
-                                            this->output_count_ * sym_size);
+  unsigned int index = this->first_global_index_;
+  const off_t oview_size = this->output_count_ * sym_size;
+  unsigned char* psyms = of->get_output_view(this->offset_, oview_size);
+
   unsigned char* ps = psyms;
   for (Symbol_table_type::const_iterator p = this->table_.begin();
        p != this->table_.end();
@@ -1135,6 +1141,9 @@ Symbol_table::sized_write_globals(const Target*,
     {
       Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(p->second);
 
+      if (sym->symtab_index() == -1U)
+       continue;
+
       unsigned int shndx;
       switch (sym->source())
        {
@@ -1164,9 +1173,7 @@ Symbol_table::sized_write_globals(const Target*,
                Relobj* relobj = static_cast<Relobj*>(symobj);
                off_t secoff;
                Output_section* os = relobj->output_section(shnum, &secoff);
-               if (os == NULL)
-                 continue;
-
+               assert(os != NULL);
                shndx = os->out_shndx();
              }
          }
@@ -1188,6 +1195,9 @@ Symbol_table::sized_write_globals(const Target*,
          abort();
        }
 
+      assert(sym->symtab_index() == index);
+      ++index;
+
       elfcpp::Sym_write<size, big_endian> osym(ps);
       osym.put_st_name(sympool->get_offset(sym->name()));
       osym.put_st_value(sym->value());
@@ -1200,7 +1210,9 @@ Symbol_table::sized_write_globals(const Target*,
       ps += sym_size;
     }
 
-  of->write_output_view(this->offset_, this->output_count_ * sym_size, psyms);
+  assert(ps - psyms == oview_size);
+
+  of->write_output_view(this->offset_, oview_size, psyms);
 }
 
 // Warnings functions.
@@ -1254,7 +1266,7 @@ Warnings::note_warnings(Symbol_table* symtab)
 // symbol for which has a warning.
 
 void
-Warnings::issue_warning(Symbol* sym, const std::string& location) const
+Warnings::issue_warning(const Symbol* sym, const std::string& location) const
 {
   assert(sym->has_warning());
   Warning_table::const_iterator p = this->warnings_.find(sym->name());
index e97260024989f948d27d9a64a11793695e667dd3..06a4b6b298240848cd794cf488e3b9331248344e 100644 (file)
@@ -173,6 +173,17 @@ class Symbol
   set_forwarder()
   { this->is_forwarder_ = true; }
 
+  // Return whether this symbol needs an entry in the dynamic symbol
+  // table.
+  bool
+  needs_dynsym_entry() const
+  { return this->needs_dynsym_entry_; }
+
+  // Mark this symbol as needing an entry in the dynamic symbol table.
+  void
+  set_needs_dynsym_entry()
+  { this->needs_dynsym_entry_ = true; }
+
   // Return whether this symbol was ever seen in a dynamic object.
   bool
   in_dyn() const
@@ -183,6 +194,46 @@ class Symbol
   set_in_dyn()
   { this->in_dyn_ = true; }
 
+  // Return the index of this symbol in the output file symbol table.
+  // A value of -1U means that this symbol is not going into the
+  // output file.  This starts out as zero, and is set to a non-zero
+  // value by Symbol_table::finalize.  It is an error to ask for the
+  // symbol table index before it has been set.
+  unsigned int
+  symtab_index() const
+  {
+    assert(this->symtab_index_ != 0);
+    return this->symtab_index_;
+  }
+
+  // Set the index of the symbol in the output file symbol table.
+  void
+  set_symtab_index(unsigned int index)
+  {
+    assert(index != 0);
+    this->symtab_index_ = index;
+  }
+
+  // Return the index of this symbol in the dynamic symbol table.  A
+  // value of -1U means that this symbol is not going into the dynamic
+  // symbol table.  This starts out as zero, and is set to a non-zero
+  // during Layout::finalize.  It is an error to ask for the dynamic
+  // symbol table index before it has been set.
+  unsigned int
+  dynsym_index() const
+  {
+    assert(this->dynsym_index_ != 0);
+    return this->dynsym_index_;
+  }
+
+  // Set the index of the symbol in the dynamic symbol table.
+  void
+  set_dynsym_index(unsigned int index)
+  {
+    assert(index != 0);
+    this->dynsym_index_ = index;
+  }
+
   // Return whether this symbol has an entry in the GOT section.
   bool
   has_got_offset() const
@@ -334,9 +385,22 @@ class Symbol
     } in_output_segment;
   } u_;
 
+  // The index of this symbol in the output file.  If the symbol is
+  // not going into the output file, this value is -1U.  This field
+  // starts as always holding zero.  It is set to a non-zero value by
+  // Symbol_table::finalize.
+  unsigned int symtab_index_;
+
+  // The index of this symbol in the dynamic symbol table.  If the
+  // symbol is not going into the dynamic symbol table, this value is
+  // -1U.  This field starts as always holding zero.  It is set to a
+  // non-zero value during Layout::finalize.
+  unsigned int dynsym_index_;
+
   // If this symbol has an entry in the GOT section (has_got_offset_
-  // is true), this is the offset.
+  // is true), this is the offset from the start of the GOT section.
   unsigned int got_offset_;
+
   // Symbol type.
   elfcpp::STT type_ : 4;
   // Symbol binding.
@@ -360,6 +424,8 @@ class Symbol
   // It forwards to the symbol found in the forwarders_ map of
   // Symbol_table.
   bool is_forwarder_ : 1;
+  // True if this symbol needs to be in the dynamic symbol table.
+  bool needs_dynsym_entry_ : 1;
   // True if we've seen this symbol in a dynamic object.
   bool in_dyn_ : 1;
   // True if the symbol has an entry in the GOT section.
@@ -548,7 +614,7 @@ class Warnings
 
   // Issue a warning for a reference to SYM at LOCATION.
   void
-  issue_warning(Symbol* sym, const std::string& location) const;
+  issue_warning(const Symbol* sym, const std::string& location) const;
 
  private:
   Warnings(const Warnings&);
@@ -667,7 +733,7 @@ class Symbol_table
 
   // Return the real symbol associated with the forwarder symbol FROM.
   Symbol*
-  resolve_forwards(Symbol* from) const;
+  resolve_forwards(const Symbol* from) const;
 
   // Return the size of the symbols in the table.
   int
@@ -705,15 +771,16 @@ class Symbol_table
   // Possibly issue a warning for a reference to SYM at LOCATION which
   // is in OBJ.
   void
-  issue_warning(Symbol* sym, const std::string& location) const
+  issue_warning(const Symbol* sym, const std::string& location) const
   { this->warnings_.issue_warning(sym, location); }
 
   // Finalize the symbol table after we have set the final addresses
-  // of all the input sections.  This sets the final symbol values and
-  // adds the names to *POOL.  It records the file offset OFF, and
+  // of all the input sections.  This sets the final symbol indexes,
+  // values and adds the names to *POOL.  INDEX is the index of the
+  // first global symbol.  This records the file offset OFF, and
   // returns the new file offset.
   off_t
-  finalize(off_t, Stringpool*);
+  finalize(unsigned int index, off_t off, Stringpool* pool);
 
   // Write out the global symbols.
   void
@@ -791,7 +858,7 @@ class Symbol_table
   // Finalize symbols specialized for size.
   template<int size>
   off_t
-  sized_finalize(off_t, Stringpool*);
+  sized_finalize(unsigned int, off_t, Stringpool*);
 
   // Write globals specialized for size and endianness.
   template<int size, bool big_endian>
@@ -828,6 +895,9 @@ class Symbol_table
   // use in archive groups.
   int saw_undefined_;
 
+  // The index of the first global symbol in the output file.
+  unsigned int first_global_index_;
+
   // The file offset within the output symtab section where we should
   // write the table.
   off_t offset_;
@@ -843,7 +913,7 @@ class Symbol_table
   Stringpool namepool_;
 
   // Forwarding symbols.
-  Unordered_map<Symbol*, Symbol*> forwarders_;
+  Unordered_map<const Symbol*, Symbol*> forwarders_;
 
   // We don't expect there to be very many common symbols, so we keep
   // a list of them.  When we find a common symbol we add it to this
index 70692783e08a2314ddf1693ac8f8a3a46f184ef4..5b057ac0fb808364ef94c31c86245540427b05b1 100644 (file)
@@ -6,30 +6,11 @@
 #include "elfcpp.h"
 #include "object.h"
 #include "symtab.h"
+#include "reloc-types.h"
 
 namespace gold
 {
 
-// Pick the ELF relocation accessor class and the size based on
-// SH_TYPE, which is either SHT_REL or SHT_RELA.
-
-template<int sh_type, int size, bool big_endian>
-struct Reloc_types;
-
-template<int size, bool big_endian>
-struct Reloc_types<elfcpp::SHT_REL, size, big_endian>
-{
-  typedef typename elfcpp::Rel<size, big_endian> Reloc;
-  static const int reloc_size = elfcpp::Elf_sizes<size>::rel_size;
-};
-
-template<int size, bool big_endian>
-struct Reloc_types<elfcpp::SHT_RELA, size, big_endian>
-{
-  typedef typename elfcpp::Rela<size, big_endian> Reloc;
-  static const int reloc_size = elfcpp::Elf_sizes<size>::rela_size;
-};
-
 // This function implements the generic part of reloc scanning.  This
 // is an inline function which takes a class whose operator()
 // implements the machine specific part of scanning.  We do it this
@@ -140,8 +121,9 @@ relocate_section(
   Relocate relocate;
 
   unsigned int local_count = relinfo->local_symbol_count;
-  typename elfcpp::Elf_types<size>::Elf_Addr *local_values = relinfo->values;
-  Symbol** global_syms = relinfo->symbols;
+  const typename Sized_relobj<size, big_endian>::Local_values* local_values =
+    relinfo->local_values;
+  const Symbol* const * global_syms = relinfo->symbols;
 
   for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
     {
@@ -153,22 +135,22 @@ relocate_section(
       unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
       unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
 
-      Sized_symbol<size>* sym;
+      const Sized_symbol<size>* sym;
       typename elfcpp::Elf_types<size>::Elf_Addr value;
 
       if (r_sym < local_count)
        {
          sym = NULL;
-         value = local_values[r_sym];
+         value = (*local_values)[r_sym];
        }
       else
        {
-         Symbol* gsym = global_syms[r_sym - local_count];
+         const Symbol* gsym = global_syms[r_sym - local_count];
          assert(gsym != NULL);
          if (gsym->is_forwarder())
            gsym = relinfo->symtab->resolve_forwards(gsym);
 
-         sym = static_cast<Sized_symbol<size>*>(gsym);
+         sym = static_cast<const Sized_symbol<size>*>(gsym);
          value = sym->value();
        }