Can now dynamically link hello, world.
authorIan Lance Taylor <iant@google.com>
Fri, 1 Dec 2006 16:51:25 +0000 (16:51 +0000)
committerIan Lance Taylor <iant@google.com>
Fri, 1 Dec 2006 16:51:25 +0000 (16:51 +0000)
12 files changed:
gold/gold.cc
gold/i386.cc
gold/layout.cc
gold/layout.h
gold/output.cc
gold/output.h
gold/po/gold.pot
gold/reloc.cc
gold/resolve.cc
gold/symtab.cc
gold/symtab.h
gold/target.h

index 5051a13a6aaeaa31429592bca5050fcd781fee13..e7b7ae2939d7d470c5d6506a68eae7c1ab3dd217 100644 (file)
@@ -217,8 +217,11 @@ queue_final_tasks(const General_options& options,
 
   // Queue a task to write out the symbol table.
   final_blocker->add_blocker();
-  workqueue->queue(new Write_symbols_task(symtab, input_objects->target(),
-                                         layout->sympool(), of,
+  workqueue->queue(new Write_symbols_task(symtab,
+                                         input_objects->target(),
+                                         layout->sympool(),
+                                         layout->dynpool(),
+                                         of,
                                          final_blocker));
 
   // Queue a task to write out everything else.
index 4cf90e99f9eaf54a368f84b7b58e82439551490a..ee3654c5a05cd354d503e2fd04caf45ac4c772bc 100644 (file)
@@ -51,7 +51,7 @@ class Target_i386 : public Sized_target<32, false>
 
   // Finalize the sections.
   void
-  do_finalize_sections(Layout*);
+  do_finalize_sections(const General_options*, Layout*);
 
   // Relocate a section.
   void
@@ -231,7 +231,8 @@ Target_i386::got_section(const General_options* options, Symbol_table* symtab,
       this->got_ = new Output_data_got<32, false>(options);
 
       layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
-                                     elfcpp::SHF_ALLOC, this->got_);
+                                     elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
+                                     this->got_);
 
       // The old GNU linker creates a .got.plt section.  We just
       // create another set of data in the .got section.  Note that we
@@ -239,7 +240,8 @@ Target_i386::got_section(const General_options* options, Symbol_table* symtab,
       // might be empty.
       this->got_plt_ = new Output_data_space(4);
       layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
-                                     elfcpp::SHF_ALLOC, this->got_plt_);
+                                     elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
+                                     this->got_plt_);
 
       // The first three entries are reserved.
       this->got_plt_->set_space_size(3 * 4);
@@ -248,7 +250,7 @@ Target_i386::got_section(const General_options* options, Symbol_table* symtab,
       symtab->define_in_output_data(this, "_GLOBAL_OFFSET_TABLE_",
                                    this->got_plt_,
                                    0, 0, elfcpp::STT_OBJECT,
-                                   elfcpp::STB_GLOBAL,
+                                   elfcpp::STB_LOCAL,
                                    elfcpp::STV_HIDDEN, 0,
                                    false, false);
     }
@@ -284,6 +286,15 @@ class Output_data_plt_i386 : public Output_section_data
   void
   add_entry(Symbol* gsym);
 
+  // Return the .rel.plt section data.
+  const Reloc_section*
+  rel_plt() const
+  { return this->rel_; }
+
+ protected:
+  void
+  do_adjust_output_section(Output_section* os);
+
  private:
   // The size of an entry in the PLT.
   static const int plt_entry_size = 16;
@@ -333,6 +344,16 @@ Output_data_plt_i386::Output_data_plt_i386(Layout* layout,
                                  elfcpp::SHF_ALLOC, this->rel_);
 }
 
+// For some reason
+
+void
+Output_data_plt_i386::do_adjust_output_section(Output_section* os)
+{
+  // UnixWare sets the entsize of .plt to 4, and so does the old GNU
+  // linker, and so do we.
+  os->set_entsize(4);
+}
+
 // Add an entry to the PLT.
 
 void
@@ -354,6 +375,7 @@ Output_data_plt_i386::add_entry(Symbol* gsym)
   this->got_plt_->set_space_size(got_offset + 4);
 
   // Every PLT entry needs a reloc.
+  gsym->set_needs_dynsym_entry();
   this->rel_->add_global(gsym, elfcpp::R_386_JUMP_SLOT, this->got_plt_,
                         got_offset);
 
@@ -503,6 +525,10 @@ Target_i386::make_plt_entry(const General_options* options,
 
       this->plt_ = new Output_data_plt_i386(layout, this->got_plt_,
                                            options->is_shared());
+      layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
+                                     (elfcpp::SHF_ALLOC
+                                      | elfcpp::SHF_EXECINSTR),
+                                     this->plt_);
     }
 
   this->plt_->add_entry(gsym);
@@ -587,6 +613,7 @@ Target_i386::copy_reloc(const General_options* options,
                                    false, false);
 
       // Add the COPY reloc.
+      ssym->set_needs_dynsym_entry();
       Reloc_section* rel_dyn = this->rel_dyn_section(layout);
       rel_dyn->add_global(ssym, elfcpp::R_386_COPY, dynbss, offset);
     }
@@ -940,12 +967,46 @@ Target_i386::scan_relocs(const General_options& options,
     global_symbols);
 }
 
-// Finalize the sections.  This is where we emit any relocs we saved
-// in an attempt to avoid generating extra COPY relocs.
+// Finalize the sections.
 
 void
-Target_i386::do_finalize_sections(Layout* layout)
+Target_i386::do_finalize_sections(const General_options* options,
+                                 Layout* layout)
 {
+  // Fill in some more dynamic tags.
+  Output_data_dynamic* const odyn = layout->dynamic_data();
+  if (odyn != NULL)
+    {
+      if (this->got_plt_ != NULL)
+       odyn->add_section_address(elfcpp::DT_PLTGOT, this->got_plt_);
+
+      if (this->plt_ != NULL)
+       {
+         const Output_data* od = this->plt_->rel_plt();
+         odyn->add_section_size(elfcpp::DT_PLTRELSZ, od);
+         odyn->add_section_address(elfcpp::DT_JMPREL, od);
+         odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_REL);
+       }
+
+      if (this->rel_dyn_ != NULL)
+       {
+         const Output_data* od = this->rel_dyn_;
+         odyn->add_section_address(elfcpp::DT_REL, od);
+         odyn->add_section_size(elfcpp::DT_RELSZ, od);
+         odyn->add_constant(elfcpp::DT_RELENT,
+                            elfcpp::Elf_sizes<32>::rel_size);
+       }
+
+      if (!options->is_shared())
+       {
+         // The value of the DT_DEBUG tag is filled in by the dynamic
+         // linker at run time, and used by the debugger.
+         odyn->add_constant(elfcpp::DT_DEBUG, 0);
+       }
+    }
+
+  // Emit any relocs we saved in an attempt to avoid generating COPY
+  // relocs.
   if (this->copy_relocs_ == NULL)
     return;
   if (this->copy_relocs_->any_to_emit())
@@ -992,7 +1053,7 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
   if (gsym != NULL && gsym->is_defined_in_dynobj())
     {
       if (gsym->has_plt_offset())
-       address = target->plt_section()->address() + gsym->plt_offset();
+       value = target->plt_section()->address() + gsym->plt_offset();
       else
        gold_unreachable();
     }
index 0de42c2f758ab34d5f35e0b73f99ef1718de76aa..f424bb4438e408ca02e8d27ab4f79208f4b78afe 100644 (file)
@@ -42,7 +42,8 @@ Layout::Layout(const General_options& options)
   : options_(options), namepool_(), sympool_(), dynpool_(), signatures_(),
     section_name_map_(), segment_list_(), section_list_(),
     unattached_section_list_(), special_output_list_(),
-    tls_segment_(NULL), symtab_section_(NULL), dynsym_section_(NULL)
+    tls_segment_(NULL), symtab_section_(NULL), dynsym_section_(NULL),
+    dynamic_section_(NULL), dynamic_data_(NULL)
 {
   // Make space for more than enough segments for a typical file.
   // This is just for efficiency--it's OK if we wind up needing more.
@@ -325,6 +326,11 @@ Layout::create_initial_dynamic_sections(const Input_objects* input_objects,
                                this->dynamic_section_, 0, 0,
                                elfcpp::STT_OBJECT, elfcpp::STB_LOCAL,
                                elfcpp::STV_HIDDEN, 0, false, false);
+
+  this->dynamic_data_ =  new Output_data_dynamic(input_objects->target(),
+                                                &this->dynpool_);
+
+  this->dynamic_section_->add_output_section_data(this->dynamic_data_);
 }
 
 // Find the first read-only PT_LOAD segment, creating one if
@@ -386,7 +392,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab)
   Target* const target = input_objects->target();
   const int size = target->get_size();
 
-  target->finalize_sections(this);
+  target->finalize_sections(&this->options_, this);
 
   Output_segment* phdr_seg = NULL;
   if (input_objects->any_dynamic())
@@ -399,14 +405,9 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab)
       phdr_seg = new Output_segment(elfcpp::PT_PHDR, elfcpp::PF_R);
       this->segment_list_.push_back(phdr_seg);
 
-      // This holds the dynamic tags.
-      Output_data_dynamic* odyn;
-      odyn = new Output_data_dynamic(input_objects->target(),
-                                    &this->dynpool_);
-
       // Create the dynamic symbol table, including the hash table,
       // the dynamic relocations, and the version sections.
-      this->create_dynamic_symtab(target, odyn, symtab);
+      this->create_dynamic_symtab(target, symtab);
 
       // Create the .interp section to hold the name of the
       // interpreter, and put it in a PT_INTERP segment.
@@ -414,7 +415,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab)
 
       // Finish the .dynamic section to hold the dynamic data, and put
       // it in a PT_DYNAMIC segment.
-      this->finish_dynamic_section(input_objects, symtab, odyn);
+      this->finish_dynamic_section(input_objects, symtab);
     }
 
   // FIXME: Handle PT_GNU_STACK.
@@ -452,9 +453,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab)
 
   // Create the symbol table sections.
   // FIXME: We don't need to do this if we are stripping symbols.
-  Output_section* ostrtab;
-  this->create_symtab_sections(size, input_objects, symtab, &off,
-                              &ostrtab);
+  this->create_symtab_sections(size, input_objects, symtab, &off);
 
   // Create the .shstrtab section.
   Output_section* shstrtab_section = this->create_shstrtab();
@@ -463,9 +462,6 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab)
   // segments.
   off = this->set_section_offsets(off, &shndx);
 
-  // Now the section index of OSTRTAB is set.
-  this->symtab_section_->set_link(ostrtab->out_shndx());
-
   // Create the section table header.
   Output_section_headers* oshdrs = this->create_shdrs(size, big_endian, &off);
 
@@ -685,8 +681,7 @@ Layout::set_section_offsets(off_t off, unsigned int* pshndx)
 void
 Layout::create_symtab_sections(int size, const Input_objects* input_objects,
                               Symbol_table* symtab,
-                              off_t* poff,
-                              Output_section** postrtab)
+                              off_t* poff)
 {
   int symsize;
   unsigned int align;
@@ -742,7 +737,27 @@ Layout::create_symtab_sections(int size, const Input_objects* input_objects,
   unsigned int local_symcount = local_symbol_index;
   gold_assert(local_symcount * symsize == off - startoff);
 
-  off = symtab->finalize(local_symcount, off, &this->sympool_);
+  off_t dynoff;
+  size_t dyn_global_index;
+  size_t dyncount;
+  if (this->dynsym_section_ == NULL)
+    {
+      dynoff = 0;
+      dyn_global_index = 0;
+      dyncount = 0;
+    }
+  else
+    {
+      dyn_global_index = this->dynsym_section_->info();
+      off_t locsize = dyn_global_index * this->dynsym_section_->entsize();
+      dynoff = this->dynsym_section_->offset() + locsize;
+      dyncount = (this->dynsym_section_->data_size() - locsize) / symsize;
+      gold_assert(dyncount * symsize
+                 == this->dynsym_section_->data_size() - locsize);
+    }
+
+  off = symtab->finalize(local_symcount, off, dynoff, dyn_global_index,
+                        dyncount, &this->sympool_);
 
   this->sympool_.set_string_offsets();
 
@@ -765,11 +780,11 @@ Layout::create_symtab_sections(int size, const Input_objects* input_objects,
   ostrtab->add_output_section_data(pstr);
 
   osymtab->set_address(0, startoff);
+  osymtab->set_link_section(ostrtab);
   osymtab->set_info(local_symcount);
   osymtab->set_entsize(symsize);
 
   *poff = off;
-  *postrtab = ostrtab;
 }
 
 // Create the .shstrtab section, which holds the names of the
@@ -801,8 +816,9 @@ Output_section_headers*
 Layout::create_shdrs(int size, bool big_endian, off_t* poff)
 {
   Output_section_headers* oshdrs;
-  oshdrs = new Output_section_headers(size, big_endian, this->segment_list_,
-                                     this->unattached_section_list_,
+  oshdrs = new Output_section_headers(size, big_endian, this,
+                                     &this->segment_list_,
+                                     &this->unattached_section_list_,
                                      &this->namepool_);
   off_t off = align_address(*poff, oshdrs->addralign());
   oshdrs->set_address(0, off);
@@ -815,8 +831,7 @@ Layout::create_shdrs(int size, bool big_endian, off_t* poff)
 // Create the dynamic symbol table.
 
 void
-Layout::create_dynamic_symtab(const Target* target, Output_data_dynamic* odyn,
-                             Symbol_table* symtab)
+Layout::create_dynamic_symtab(const Target* target, Symbol_table* symtab)
 {
   // Count all the symbols in the dynamic symbol table, and set the
   // dynamic symbol indexes.
@@ -883,6 +898,7 @@ Layout::create_dynamic_symtab(const Target* target, Output_data_dynamic* odyn,
 
   this->dynsym_section_ = dynsym;
 
+  Output_data_dynamic* const odyn = this->dynamic_data_;
   odyn->add_section_address(elfcpp::DT_SYMTAB, dynsym);
   odyn->add_constant(elfcpp::DT_SYMENT, symsize);
 
@@ -894,6 +910,9 @@ Layout::create_dynamic_symtab(const Target* target, Output_data_dynamic* odyn,
   Output_section_data* strdata = new Output_data_strtab(&this->dynpool_);
   dynstr->add_output_section_data(strdata);
 
+  dynsym->set_link_section(dynstr);
+  this->dynamic_section_->set_link_section(dynstr);
+
   odyn->add_section_address(elfcpp::DT_STRTAB, dynstr);
   odyn->add_section_size(elfcpp::DT_STRSZ, dynstr);
 
@@ -914,8 +933,8 @@ Layout::create_dynamic_symtab(const Target* target, Output_data_dynamic* odyn,
                                                               align);
   hashsec->add_output_section_data(hashdata);
 
+  hashsec->set_link_section(dynsym);
   hashsec->set_entsize(4);
-  // FIXME: .hash should link to .dynsym.
 
   odyn->add_section_address(elfcpp::DT_HASH, hashsec);
 }
@@ -951,17 +970,16 @@ Layout::create_interp(const Target* target)
 
 void
 Layout::finish_dynamic_section(const Input_objects* input_objects,
-                              const Symbol_table* symtab,
-                              Output_data_dynamic* odyn)
+                              const Symbol_table* symtab)
 {
-  this->dynamic_section_->add_output_section_data(odyn);
-
   Output_segment* oseg = new Output_segment(elfcpp::PT_DYNAMIC,
                                            elfcpp::PF_R | elfcpp::PF_W);
   this->segment_list_.push_back(oseg);
   oseg->add_initial_output_section(this->dynamic_section_,
                                   elfcpp::PF_R | elfcpp::PF_W);
 
+  Output_data_dynamic* const odyn = this->dynamic_data_;
+
   for (Input_objects::Dynobj_iterator p = input_objects->dynobj_begin();
        p != input_objects->dynobj_end();
        ++p)
@@ -1231,7 +1249,8 @@ Write_symbols_task::locks(Workqueue* workqueue)
 void
 Write_symbols_task::run(Workqueue*)
 {
-  this->symtab_->write_globals(this->target_, this->sympool_, this->of_);
+  this->symtab_->write_globals(this->target_, this->sympool_, this->dynpool_,
+                              this->of_);
 }
 
 // Close_task_runner methods.
index 26948bb356f9dfe315ef7500113aeb3c41b24a7b..4c54e005554eac3de42e882c3ca485f77635c764 100644 (file)
@@ -89,6 +89,12 @@ class Layout
   sympool() const
   { return &this->sympool_; }
 
+  // Return the Stringpool used for dynamic symbol names and dynamic
+  // tags.
+  const Stringpool*
+  dynpool() const
+  { return &this->dynpool_; }
+
   // Return whether a section is a .gnu.linkonce section, given the
   // section name.
   static inline bool
@@ -106,11 +112,33 @@ class Layout
   off_t
   finalize(const Input_objects*, Symbol_table*);
 
-  // Return the TLS segment.
+  // Return the TLS segment.  This will return NULL if there isn't
+  // one.
   Output_segment*
   tls_segment() const
   { return this->tls_segment_; }
 
+  // Return the normal symbol table.
+  Output_section*
+  symtab_section() const
+  {
+    gold_assert(this->symtab_section_ != NULL);
+    return this->symtab_section_;
+  }
+
+  // Return the dynamic symbol table.
+  Output_section*
+  dynsym_section() const
+  {
+    gold_assert(this->dynsym_section_ != NULL);
+    return this->dynsym_section_;
+  }
+
+  // Return the dynamic tags.
+  Output_data_dynamic*
+  dynamic_data() const
+  { return this->dynamic_data_; }
+
   // Write out data not associated with an input file or the symbol
   // table.
   void
@@ -160,8 +188,8 @@ class Layout
 
   // Create the output sections for the symbol table.
   void
-  create_symtab_sections(int size, const Input_objects*, Symbol_table*, off_t*,
-                        Output_section** ostrtab);
+  create_symtab_sections(int size, const Input_objects*, Symbol_table*,
+                        off_t*);
 
   // Create the .shstrtab section.
   Output_section*
@@ -173,12 +201,11 @@ class Layout
 
   // Create the dynamic symbol table.
   void
-  create_dynamic_symtab(const Target*, Output_data_dynamic*, Symbol_table*);
+  create_dynamic_symtab(const Target*, Symbol_table*);
 
   // Finish the .dynamic section and PT_DYNAMIC segment.
   void
-  finish_dynamic_section(const Input_objects*, const Symbol_table*,
-                        Output_data_dynamic*);
+  finish_dynamic_section(const Input_objects*, const Symbol_table*);
 
   // Create the .interp section and PT_INTERP segment.
   void
@@ -284,6 +311,8 @@ class Layout
   Output_section* dynsym_section_;
   // The SHT_DYNAMIC output section if there is one.
   Output_section* dynamic_section_;
+  // The dynamic data which goes into dynamic_section_.
+  Output_data_dynamic* dynamic_data_;
 };
 
 // This task handles writing out data which is not part of a section
@@ -324,10 +353,10 @@ class Write_symbols_task : public Task
 {
  public:
   Write_symbols_task(const Symbol_table* symtab, const Target* target,
-                    const Stringpool* sympool, Output_file* of,
-                    Task_token* final_blocker)
-    : symtab_(symtab), target_(target), sympool_(sympool), of_(of),
-      final_blocker_(final_blocker)
+                    const Stringpool* sympool, const Stringpool* dynpool,
+                    Output_file* of, Task_token* final_blocker)
+    : symtab_(symtab), target_(target), sympool_(sympool), dynpool_(dynpool),
+      of_(of), final_blocker_(final_blocker)
   { }
 
   // The standard Task methods.
@@ -345,6 +374,7 @@ class Write_symbols_task : public Task
   const Symbol_table* symtab_;
   const Target* target_;
   const Stringpool* sympool_;
+  const Stringpool* dynpool_;
   Output_file* of_;
   Task_token* final_blocker_;
 };
index 14938472751479b4e86949e8988ec1138c352431..f0d7985732db40a8c58ae87354f576ff74091958 100644 (file)
@@ -58,23 +58,25 @@ Output_data::default_alignment(int size)
 Output_section_headers::Output_section_headers(
     int size,
     bool big_endian,
-    const Layout::Segment_list& segment_list,
-    const Layout::Section_list& unattached_section_list,
+    const Layout* layout,
+    const Layout::Segment_list* segment_list,
+    const Layout::Section_list* unattached_section_list,
     const Stringpool* secnamepool)
   : size_(size),
     big_endian_(big_endian),
+    layout_(layout),
     segment_list_(segment_list),
     unattached_section_list_(unattached_section_list),
     secnamepool_(secnamepool)
 {
   // Count all the sections.  Start with 1 for the null section.
   off_t count = 1;
-  for (Layout::Segment_list::const_iterator p = segment_list.begin();
-       p != segment_list.end();
+  for (Layout::Segment_list::const_iterator p = segment_list->begin();
+       p != segment_list->end();
        ++p)
     if ((*p)->type() == elfcpp::PT_LOAD)
       count += (*p)->output_section_count();
-  count += unattached_section_list.size();
+  count += unattached_section_list->size();
 
   int shdr_size;
   if (size == 32)
@@ -137,20 +139,20 @@ Output_section_headers::do_sized_write(Output_file* of)
   v += shdr_size;
 
   unsigned shndx = 1;
-  for (Layout::Segment_list::const_iterator p = this->segment_list_.begin();
-       p != this->segment_list_.end();
+  for (Layout::Segment_list::const_iterator p = this->segment_list_->begin();
+       p != this->segment_list_->end();
        ++p)
     v = (*p)->write_section_headers SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
-           this->secnamepool_, v, &shndx
+           this->layout_, this->secnamepool_, v, &shndx
            SELECT_SIZE_ENDIAN(size, big_endian));
   for (Layout::Section_list::const_iterator p =
-        this->unattached_section_list_.begin();
-       p != this->unattached_section_list_.end();
+        this->unattached_section_list_->begin();
+       p != this->unattached_section_list_->end();
        ++p)
     {
       gold_assert(shndx == (*p)->out_shndx());
       elfcpp::Shdr_write<size, big_endian> oshdr(v);
-      (*p)->write_header(this->secnamepool_, &oshdr);
+      (*p)->write_header(this->layout_, this->secnamepool_, &oshdr);
       v += shdr_size;
       ++shndx;
     }
@@ -372,6 +374,18 @@ Output_data_const_buffer::do_write(Output_file* of)
 
 // Output_section_data methods.
 
+// Record the output section, and set the entry size and such.
+
+void
+Output_section_data::set_output_section(Output_section* os)
+{
+  gold_assert(this->output_section_ == NULL);
+  this->output_section_ = os;
+  this->do_adjust_output_section(os);
+}
+
+// Return the section index of the output section.
+
 unsigned int
 Output_section_data::do_out_shndx() const
 {
@@ -496,6 +510,25 @@ Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>::write(
 
 // Output_data_reloc_base methods.
 
+// Adjust the output section.
+
+template<int sh_type, bool dynamic, int size, bool big_endian>
+void
+Output_data_reloc_base<sh_type, dynamic, size, big_endian>
+    ::do_adjust_output_section(Output_section* os)
+{
+  if (sh_type == elfcpp::SHT_REL)
+    os->set_entsize(elfcpp::Elf_sizes<size>::rel_size);
+  else if (sh_type == elfcpp::SHT_RELA)
+    os->set_entsize(elfcpp::Elf_sizes<size>::rela_size);
+  else
+    gold_unreachable();
+  if (dynamic)
+    os->set_should_link_to_dynsym();
+  else
+    os->set_should_link_to_symtab();
+}
+
 // Write out relocation data.
 
 template<int sh_type, bool dynamic, int size, bool big_endian>
@@ -636,16 +669,17 @@ Output_data_dynamic::Dynamic_entry::write(
       break;
 
     case DYNAMIC_SECTION_ADDRESS:
-      val = this->u_.os->address();
+      val = this->u_.od->address();
       break;
 
     case DYNAMIC_SECTION_SIZE:
-      val = this->u_.os->data_size();
+      val = this->u_.od->data_size();
       break;
 
     case DYNAMIC_SYMBOL:
       {
-       Sized_symbol<size>* s = static_cast<Sized_symbol<size>*>(this->u_.sym);
+       const Sized_symbol<size>* s =
+         static_cast<const Sized_symbol<size>*>(this->u_.sym);
        val = s->value();
       }
       break;
@@ -665,6 +699,19 @@ Output_data_dynamic::Dynamic_entry::write(
 
 // Output_data_dynamic methods.
 
+// Adjust the output section to set the entry size.
+
+void
+Output_data_dynamic::do_adjust_output_section(Output_section* os)
+{
+  if (this->target_->get_size() == 32)
+    os->set_entsize(elfcpp::Elf_sizes<32>::dyn_size);
+  else if (this->target_->get_size() == 64)
+    os->set_entsize(elfcpp::Elf_sizes<64>::dyn_size);
+  else
+    gold_unreachable();
+}
+
 // Set the final data size.
 
 void
@@ -780,7 +827,9 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
   : name_(name),
     addralign_(0),
     entsize_(0),
+    link_section_(NULL),
     link_(0),
+    info_section_(NULL),
     info_(0),
     type_(type),
     flags_(flags),
@@ -791,7 +840,9 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
     first_input_offset_(0),
     may_add_data_(may_add_data),
     needs_symtab_index_(false),
-    needs_dynsym_index_(false)
+    needs_dynsym_index_(false),
+    should_link_to_symtab_(false),
+    should_link_to_dynsym_(false)
 {
 }
 
@@ -799,6 +850,17 @@ Output_section::~Output_section()
 {
 }
 
+// Set the entry size.
+
+void
+Output_section::set_entsize(uint64_t v)
+{
+  if (this->entsize_ == 0)
+    this->entsize_ = v;
+  else
+    gold_assert(this->entsize_ == v);
+}
+
 // Add the input section SHNDX, with header SHDR, named SECNAME, in
 // OBJECT, to the Output_section.  Return the offset of the input
 // section within the output section.  We don't always keep track of
@@ -885,7 +947,8 @@ Output_section::do_set_address(uint64_t address, off_t startoff)
 
 template<int size, bool big_endian>
 void
-Output_section::write_header(const Stringpool* secnamepool,
+Output_section::write_header(const Layout* layout,
+                            const Stringpool* secnamepool,
                             elfcpp::Shdr_write<size, big_endian>* oshdr) const
 {
   oshdr->put_sh_name(secnamepool->get_offset(this->name_));
@@ -894,8 +957,18 @@ Output_section::write_header(const Stringpool* secnamepool,
   oshdr->put_sh_addr(this->address());
   oshdr->put_sh_offset(this->offset());
   oshdr->put_sh_size(this->data_size());
-  oshdr->put_sh_link(this->link_);
-  oshdr->put_sh_info(this->info_);
+  if (this->link_section_ != NULL)
+    oshdr->put_sh_link(this->link_section_->out_shndx());
+  else if (this->should_link_to_symtab_)
+    oshdr->put_sh_link(layout->symtab_section()->out_shndx());
+  else if (this->should_link_to_dynsym_)
+    oshdr->put_sh_link(layout->dynsym_section()->out_shndx());
+  else
+    oshdr->put_sh_link(this->link_);
+  if (this->info_section_ != NULL)
+    oshdr->put_sh_info(this->info_section_->out_shndx());
+  else
+    oshdr->put_sh_info(this->info_);
   oshdr->put_sh_addralign(this->addralign_);
   oshdr->put_sh_entsize(this->entsize_);
 }
@@ -1245,7 +1318,8 @@ Output_segment::write_header(elfcpp::Phdr_write<size, big_endian>* ophdr)
 
 template<int size, bool big_endian>
 unsigned char*
-Output_segment::write_section_headers(const Stringpool* secnamepool,
+Output_segment::write_section_headers(const Layout* layout,
+                                     const Stringpool* secnamepool,
                                      unsigned char* v,
                                      unsigned int *pshndx
                                       ACCEPT_SIZE_ENDIAN) const
@@ -1258,18 +1332,19 @@ Output_segment::write_section_headers(const Stringpool* secnamepool,
 
   v = this->write_section_headers_list
       SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
-          secnamepool, &this->output_data_, v, pshndx
+         layout, secnamepool, &this->output_data_, v, pshndx
           SELECT_SIZE_ENDIAN(size, big_endian));
   v = this->write_section_headers_list
       SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
-          secnamepool, &this->output_bss_, v, pshndx
+          layout, secnamepool, &this->output_bss_, v, pshndx
           SELECT_SIZE_ENDIAN(size, big_endian));
   return v;
 }
 
 template<int size, bool big_endian>
 unsigned char*
-Output_segment::write_section_headers_list(const Stringpool* secnamepool,
+Output_segment::write_section_headers_list(const Layout* layout,
+                                          const Stringpool* secnamepool,
                                           const Output_data_list* pdl,
                                           unsigned char* v,
                                           unsigned int* pshndx
@@ -1285,7 +1360,7 @@ Output_segment::write_section_headers_list(const Stringpool* secnamepool,
          const Output_section* ps = static_cast<const Output_section*>(*p);
          gold_assert(*pshndx == ps->out_shndx());
          elfcpp::Shdr_write<size, big_endian> oshdr(v);
-         ps->write_header(secnamepool, &oshdr);
+         ps->write_header(layout, secnamepool, &oshdr);
          v += shdr_size;
          ++*pshndx;
        }
index f7efdba55dc02636a19ccb2b2d044a8e3070e188..ceea87729f4599bb83de567434c99710eb34cec3 100644 (file)
@@ -185,8 +185,9 @@ class Output_section_headers : public Output_data
  public:
   Output_section_headers(int size,
                         bool big_endian,
-                        const Layout::Segment_list&,
-                        const Layout::Section_list&,
+                        const Layout*,
+                        const Layout::Segment_list*,
+                        const Layout::Section_list*,
                         const Stringpool*);
 
   // Write the data to the file.
@@ -206,8 +207,9 @@ class Output_section_headers : public Output_data
 
   int size_;
   bool big_endian_;
-  const Layout::Segment_list& segment_list_;
-  const Layout::Section_list& unattached_section_list_;
+  const Layout* layout_;
+  const Layout::Segment_list* segment_list_;
+  const Layout::Section_list* unattached_section_list_;
   const Stringpool* secnamepool_;
 };
 
@@ -303,17 +305,24 @@ class Output_section_data : public Output_data
     : Output_data(0), output_section_(NULL), addralign_(addralign)
   { }
 
+  // Return the output section.
+  const Output_section*
+  output_section() const
+  { return this->output_section_; }
+
   // Record the output section.
   void
-  set_output_section(Output_section* os)
-  {
-    gold_assert(this->output_section_ == NULL);
-    this->output_section_ = os;
-  }
+  set_output_section(Output_section* os);
 
  protected:
   // The child class must implement do_write.
 
+  // The child class may implement specific adjustments to the output
+  // section.
+  virtual void
+  do_adjust_output_section(Output_section*)
+  { }
+
   // Return the required alignment.
   uint64_t
   do_addralign() const
@@ -695,6 +704,10 @@ class Output_data_reloc_base : public Output_section_data
   do_write(Output_file*);
 
  protected:
+  // Set the entry size and the link.
+  void
+  do_adjust_output_section(Output_section *os);
+
   // Add a relocation entry.
   void
   add(const Output_reloc_type& reloc)
@@ -975,19 +988,19 @@ class Output_data_dynamic : public Output_section_data
   add_constant(elfcpp::DT tag, unsigned int val)
   { this->add_entry(Dynamic_entry(tag, val)); }
 
-  // Add a new dynamic entry with the address of a section.
+  // Add a new dynamic entry with the address of output data.
   void
-  add_section_address(elfcpp::DT tag, Output_section* os)
-  { this->add_entry(Dynamic_entry(tag, os, false)); }
+  add_section_address(elfcpp::DT tag, const Output_data* od)
+  { this->add_entry(Dynamic_entry(tag, od, false)); }
 
-  // Add a new dynamic entry with the size of a section.
+  // Add a new dynamic entry with the size of output data.
   void
-  add_section_size(elfcpp::DT tag, Output_section* os)
-  { this->add_entry(Dynamic_entry(tag, os, true)); }
+  add_section_size(elfcpp::DT tag, const Output_data* od)
+  { this->add_entry(Dynamic_entry(tag, od, true)); }
 
   // Add a new dynamic entry with the address of a symbol.
   void
-  add_symbol(elfcpp::DT tag, Symbol* sym)
+  add_symbol(elfcpp::DT tag, const Symbol* sym)
   { this->add_entry(Dynamic_entry(tag, sym)); }
 
   // Add a new dynamic entry with a string.
@@ -1003,6 +1016,11 @@ class Output_data_dynamic : public Output_section_data
   void
   do_write(Output_file*);
 
+ protected:
+  // Adjust the output section to set the entry size.
+  void
+  do_adjust_output_section(Output_section*);
+
  private:
   // This POD class holds a single dynamic entry.
   class Dynamic_entry
@@ -1014,15 +1032,15 @@ class Output_data_dynamic : public Output_section_data
     { this->u_.val = val; }
 
     // Create an entry with the size or address of a section.
-    Dynamic_entry(elfcpp::DT tag, Output_section* os, bool section_size)
+    Dynamic_entry(elfcpp::DT tag, const Output_data* od, bool section_size)
       : tag_(tag),
        classification_(section_size
                        ? DYNAMIC_SECTION_SIZE
                        : DYNAMIC_SECTION_ADDRESS)
-    { this->u_.os = os; }
+    { this->u_.od = od; }
 
     // Create an entry with the address of a symbol.
-    Dynamic_entry(elfcpp::DT tag, Symbol* sym)
+    Dynamic_entry(elfcpp::DT tag, const Symbol* sym)
       : tag_(tag), classification_(DYNAMIC_SYMBOL)
     { this->u_.sym = sym; }
 
@@ -1056,9 +1074,9 @@ class Output_data_dynamic : public Output_section_data
       // For DYNAMIC_NUMBER.
       unsigned int val;
       // For DYNAMIC_SECTION_ADDRESS and DYNAMIC_SECTION_SIZE.
-      Output_section* os;
+      const Output_data* od;
       // For DYNAMIC_SYMBOL.
-      Symbol* sym;
+      const Symbol* sym;
       // For DYNAMIC_STRING.
       const char* str;
     } u_;
@@ -1143,18 +1161,71 @@ class Output_section : public Output_data
 
   // Set the entsize field.
   void
-  set_entsize(uint64_t v)
-  { this->entsize_ = v; }
+  set_entsize(uint64_t v);
 
-  // Set the link field.
+  // Set the link field to the output section index of a section.
+  void
+  set_link_section(Output_data* od)
+  {
+    gold_assert(this->link_ == 0
+               && !this->should_link_to_symtab_
+               && !this->should_link_to_dynsym_);
+    this->link_section_ = od;
+  }
+
+  // Set the link field to a constant.
   void
   set_link(unsigned int v)
-  { this->link_ = v; }
+  {
+    gold_assert(this->link_section_ == NULL
+               && !this->should_link_to_symtab_
+               && !this->should_link_to_dynsym_);
+    this->link_ = v;
+  }
 
-  // Set the info field.
+  // Record that this section should link to the normal symbol table.
+  void
+  set_should_link_to_symtab()
+  {
+    gold_assert(this->link_section_ == NULL
+               && this->link_ == 0
+               && !this->should_link_to_dynsym_);
+    this->should_link_to_symtab_ = true;
+  }
+
+  // Record that this section should link to the dynamic symbol table.
+  void
+  set_should_link_to_dynsym()
+  {
+    gold_assert(this->link_section_ == NULL
+               && this->link_ == 0
+               && !this->should_link_to_symtab_);
+    this->should_link_to_dynsym_ = true;
+  }
+
+  // Return the info field.
+  unsigned int
+  info() const
+  {
+    gold_assert(this->info_section_ == NULL);
+    return this->info_;
+  }
+
+  // Set the info field to the output section index of a section.
+  void
+  set_info_section(Output_data* od)
+  {
+    gold_assert(this->info_ == 0);
+    this->info_section_ = od;
+  }
+
+  // Set the info field to a constant.
   void
   set_info(unsigned int v)
-  { this->info_ = v; }
+  {
+    gold_assert(this->info_section_ == NULL);
+    this->info_ = v;
+  }
 
   // Set the addralign field.
   void
@@ -1250,7 +1321,8 @@ class Output_section : public Output_data
   // Write the section header into *OPHDR.
   template<int size, bool big_endian>
   void
-  write_header(const Stringpool*, elfcpp::Shdr_write<size, big_endian>*) const;
+  write_header(const Layout*, const Stringpool*,
+              elfcpp::Shdr_write<size, big_endian>*) const;
 
  private:
   // In some cases we need to keep a list of the input sections
@@ -1344,9 +1416,13 @@ class Output_section : public Output_data
   // The section entry size.
   uint64_t entsize_;
   // The file offset is in the parent class.
-  // The section link field.
+  // Set the section link field to the index of this section.
+  Output_data* link_section_;
+  // If link_section_ is NULL, this is the link field.
   unsigned int link_;
-  // The section info field.
+  // Set the section info field to the index of this section.
+  Output_data* info_section_;
+  // If info_section_ is NULL, this is the section info field.
   unsigned int info_;
   // The section type.
   elfcpp::Elf_Word type_;
@@ -1379,6 +1455,12 @@ class Output_section : public Output_data
   // dynamic symbol table.  This will be true if there is a dynamic
   // relocation which needs it.
   bool needs_dynsym_index_ : 1;
+  // Whether the link field of this output section should point to the
+  // normal symbol table.
+  bool should_link_to_symtab_ : 1;
+  // Whether the link field of this output section should point to the
+  // dynamic symbol table.
+  bool should_link_to_dynsym_ : 1;
 };
 
 // An output segment.  PT_LOAD segments are built from collections of
@@ -1466,8 +1548,7 @@ class Output_segment
   // Write the section headers of associated sections into V.
   template<int size, bool big_endian>
   unsigned char*
-  write_section_headers(const Stringpool*,
-                        unsigned char* v,
+  write_section_headers(const Layout*, const Stringpool*, unsigned char* v,
                        unsigned int* pshndx ACCEPT_SIZE_ENDIAN) const;
 
  private:
@@ -1497,8 +1578,8 @@ class Output_segment
   // Write the section headers in the list into V.
   template<int size, bool big_endian>
   unsigned char*
-  write_section_headers_list(const Stringpool*, const Output_data_list*,
-                            unsigned char* v,
+  write_section_headers_list(const Layout*, const Stringpool*,
+                            const Output_data_list*, unsigned char* v,
                             unsigned int* pshdx ACCEPT_SIZE_ENDIAN) const;
 
   // The list of output data with contents attached to this segment.
index 4a852a1e720e731b9b8ec12e1fb8605ed8b4f673..dbfa857cf1eb5da4d32424189c7c641467f361e2 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2006-11-30 15:37-0800\n"
+"POT-Creation-Date: 2006-12-01 08:46-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"
@@ -240,52 +240,52 @@ msgstr ""
 msgid "%s: missing expected TLS relocation\n"
 msgstr ""
 
-#: i386.cc:702 i386.cc:843 i386.cc:1064
+#: i386.cc:729 i386.cc:870 i386.cc:1125
 #, c-format
 msgid "%s: %s: unexpected reloc %u in object file\n"
 msgstr ""
 
-#: i386.cc:738 i386.cc:757
+#: i386.cc:765 i386.cc:784
 #, c-format
 msgid "%s: %s: unsupported reloc %u against local symbol\n"
 msgstr ""
 
-#: i386.cc:879 i386.cc:900
+#: i386.cc:906 i386.cc:927
 #, c-format
 msgid "%s: %s: unsupported reloc %u against global symbol %s\n"
 msgstr ""
 
-#: i386.cc:923
+#: i386.cc:950
 #, c-format
 msgid "%s: %s: unsupported RELA reloc section\n"
 msgstr ""
 
-#: i386.cc:980
+#: i386.cc:1041
 #, c-format
 msgid "%s: %s: missing expected TLS relocation\n"
 msgstr ""
 
-#: i386.cc:1096 i386.cc:1171 i386.cc:1182
+#: i386.cc:1157 i386.cc:1232 i386.cc:1243
 #, c-format
 msgid "%s: %s: unsupported reloc %u\n"
 msgstr ""
 
-#: i386.cc:1123
+#: i386.cc:1184
 #, c-format
 msgid "%s: %s: TLS reloc but no TLS segment\n"
 msgstr ""
 
-#: i386.cc:1156
+#: i386.cc:1217
 #, c-format
 msgid "%s: %s: unsupported reloc type %u\n"
 msgstr ""
 
-#: i386.cc:1365
+#: i386.cc:1426
 #, c-format
 msgid "%s: %s: TLS relocation out of range\n"
 msgstr ""
 
-#: i386.cc:1383
+#: i386.cc:1444
 #, c-format
 msgid "%s: %s: TLS relocation against invalid instruction\n"
 msgstr ""
@@ -496,37 +496,37 @@ msgstr ""
 msgid "%s: -%c: %s\n"
 msgstr ""
 
-#: output.cc:817
+#: output.cc:881
 #, c-format
 msgid "%s: %s: invalid alignment %lu for section \"%s\"\n"
 msgstr ""
 
-#: output.cc:1316
+#: output.cc:1393
 #, c-format
 msgid "%s: %s: open: %s\n"
 msgstr ""
 
-#: output.cc:1325
+#: output.cc:1402
 #, c-format
 msgid "%s: %s: lseek: %s\n"
 msgstr ""
 
-#: output.cc:1332
+#: output.cc:1409
 #, c-format
 msgid "%s: %s: write: %s\n"
 msgstr ""
 
-#: output.cc:1342
+#: output.cc:1419
 #, c-format
 msgid "%s: %s: mmap: %s\n"
 msgstr ""
 
-#: output.cc:1356
+#: output.cc:1433
 #, c-format
 msgid "%s: %s: munmap: %s\n"
 msgstr ""
 
-#: output.cc:1364
+#: output.cc:1441
 #, c-format
 msgid "%s: %s: close: %s\n"
 msgstr ""
@@ -607,12 +607,12 @@ msgstr ""
 msgid "%s: %s: versym for symbol %zu has no name: %u\n"
 msgstr ""
 
-#: symtab.cc:1050 symtab.cc:1201
+#: symtab.cc:1063 symtab.cc:1235
 #, c-format
 msgid "%s: %s: unsupported symbol section 0x%x\n"
 msgstr ""
 
-#: symtab.cc:1364
+#: symtab.cc:1423
 #, c-format
 msgid "%s: %s: warning: %s\n"
 msgstr ""
index 915656c374e56f4f28cc3f9554375b31b2cac7a1..5b4db46ccb3e901c79e507064c0c2fba0aec6f70 100644 (file)
@@ -497,6 +497,7 @@ void
 Copy_relocs<size, big_endian>::Copy_reloc_entry::emit(
     Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian>* reloc_data)
 {
+  this->sym_->set_needs_dynsym_entry();
   reloc_data->add_global(this->sym_, this->reloc_type_, this->relobj_,
                         this->shndx_, this->address_);
 }
@@ -508,6 +509,7 @@ void
 Copy_relocs<size, big_endian>::Copy_reloc_entry::emit(
     Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>* reloc_data)
 {
+  this->sym_->set_needs_dynsym_entry();
   reloc_data->add_global(this->sym_, this->reloc_type_, this->relobj_,
                         this->shndx_, this->address_, this->addend_);
 }
index 891de8c7c9476ea1967783781bfc0966f61a890a..b8e5e701cb74c58b5abce3a0c1d468228fabf8a5 100644 (file)
@@ -22,7 +22,7 @@ Symbol::override_base(const elfcpp::Sym<size, big_endian>& sym,
   gold_assert(this->source_ == FROM_OBJECT);
   this->u_.from_object.object = object;
   // FIXME: Handle SHN_XINDEX.
-  this->u_.from_object.shnum = sym.get_st_shndx();
+  this->u_.from_object.shndx = sym.get_st_shndx();
   this->type_ = sym.get_st_type();
   this->binding_ = sym.get_st_bind();
   this->visibility_ = sym.get_st_visibility();
@@ -110,7 +110,7 @@ Symbol_table::resolve(Sized_symbol<size>* to,
       && to->object()->is_dynamic())
     tobits |= (1 << 1);
 
-  switch (to->shnum())
+  switch (to->shndx())
     {
     case elfcpp::SHN_UNDEF:
       tobits |= (1 << 2);
index 4d2bb1afecbf14283e24e66fbb194e126347eadb..21192c1ec43d544b831f49996bd494a7707e4b94 100644 (file)
@@ -55,7 +55,7 @@ Symbol::init_base(const char* name, const char* version, Object* object,
                    sym.get_st_visibility(), sym.get_st_nonvis());
   this->u_.from_object.object = object;
   // FIXME: Handle SHN_XINDEX.
-  this->u_.from_object.shnum = sym.get_st_shndx();
+  this->u_.from_object.shndx = sym.get_st_shndx();
   this->source_ = FROM_OBJECT;
   this->in_dyn_ = object->is_dynamic();
 }
@@ -258,7 +258,7 @@ Symbol_table::resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from
   esym.put_st_size(from->symsize());
   esym.put_st_info(from->binding(), from->type());
   esym.put_st_other(from->visibility(), from->nonvis());
-  esym.put_st_shndx(from->shnum());
+  esym.put_st_shndx(from->shndx());
   Symbol_table::resolve(to, esym.sym(), from->object());
 }
 
@@ -717,9 +717,9 @@ Symbol_table::define_special_symbol(Target* target, const char* name,
       sym = this->get_sized_symbol SELECT_SIZE_NAME(size) (oldsym
                                                            SELECT_SIZE(size));
       gold_assert(sym->source() == Symbol::FROM_OBJECT);
-      const int old_shnum = sym->shnum();
-      if (old_shnum != elfcpp::SHN_UNDEF
-         && old_shnum != elfcpp::SHN_COMMON
+      const int old_shndx = sym->shndx();
+      if (old_shndx != elfcpp::SHN_UNDEF
+         && old_shndx != elfcpp::SHN_COMMON
          && !sym->object()->is_dynamic())
        {
          fprintf(stderr, "%s: linker defined: multiple definition of %s\n",
@@ -969,7 +969,14 @@ Symbol_table::set_dynsym_indexes(unsigned int index,
        ++p)
     {
       Symbol* sym = p->second;
-      if (sym->needs_dynsym_entry())
+
+      // Note that SYM may already have a dynamic symbol index, since
+      // some symbols appear more than once in the symbol table, with
+      // and without a version.
+
+      if (!sym->needs_dynsym_entry())
+       sym->set_dynsym_index(-1U);
+      else if (!sym->has_dynsym_index())
        {
          sym->set_dynsym_index(index);
          ++index;
@@ -986,13 +993,19 @@ Symbol_table::set_dynsym_indexes(unsigned int index,
 // OFF.  Add their names to POOL.  Return the new file offset.
 
 off_t
-Symbol_table::finalize(unsigned int index, off_t off, Stringpool* pool)
+Symbol_table::finalize(unsigned int index, off_t off, off_t dynoff,
+                      size_t dyn_global_index, size_t dyncount,
+                      Stringpool* pool)
 {
   off_t ret;
 
   gold_assert(index != 0);
   this->first_global_index_ = index;
 
+  this->dynamic_offset_ = dynoff;
+  this->first_dynamic_global_index_ = dyn_global_index;
+  this->dynamic_count_ = dyncount;
+
   if (this->size_ == 32)
     ret = this->sized_finalize<32>(index, off, pool);
   else if (this->size_ == 64)
@@ -1041,14 +1054,14 @@ Symbol_table::sized_finalize(unsigned index, off_t off, Stringpool* pool)
        {
        case Symbol::FROM_OBJECT:
          {
-           unsigned int shnum = sym->shnum();
+           unsigned int shndx = sym->shndx();
 
            // FIXME: We need some target specific support here.
-           if (shnum >= elfcpp::SHN_LORESERVE
-               && shnum != elfcpp::SHN_ABS)
+           if (shndx >= elfcpp::SHN_LORESERVE
+               && shndx != elfcpp::SHN_ABS)
              {
                fprintf(stderr, _("%s: %s: unsupported symbol section 0x%x\n"),
-                       program_name, sym->name(), shnum);
+                       program_name, sym->name(), shndx);
                gold_exit(false);
              }
 
@@ -1056,21 +1069,22 @@ Symbol_table::sized_finalize(unsigned index, off_t off, Stringpool* pool)
            if (symobj->is_dynamic())
              {
                value = 0;
-               shnum = elfcpp::SHN_UNDEF;
+               shndx = elfcpp::SHN_UNDEF;
              }
-           else if (shnum == elfcpp::SHN_UNDEF)
+           else if (shndx == elfcpp::SHN_UNDEF)
              value = 0;
-           else if (shnum == elfcpp::SHN_ABS)
+           else if (shndx == elfcpp::SHN_ABS)
              value = sym->value();
            else
              {
                Relobj* relobj = static_cast<Relobj*>(symobj);
                off_t secoff;
-               Output_section* os = relobj->output_section(shnum, &secoff);
+               Output_section* os = relobj->output_section(shndx, &secoff);
 
                if (os == NULL)
                  {
                    sym->set_symtab_index(-1U);
+                   gold_assert(sym->dynsym_index() == -1U);
                    continue;
                  }
 
@@ -1132,21 +1146,21 @@ Symbol_table::sized_finalize(unsigned index, off_t off, Stringpool* pool)
 
 void
 Symbol_table::write_globals(const Target* target, const Stringpool* sympool,
-                           Output_file* of) const
+                           const Stringpool* dynpool, Output_file* of) const
 {
   if (this->size_ == 32)
     {
       if (target->is_big_endian())
-       this->sized_write_globals<32, true>(target, sympool, of);
+       this->sized_write_globals<32, true>(target, sympool, dynpool, of);
       else
-       this->sized_write_globals<32, false>(target, sympool, of);
+       this->sized_write_globals<32, false>(target, sympool, dynpool, of);
     }
   else if (this->size_ == 64)
     {
       if (target->is_big_endian())
-       this->sized_write_globals<64, true>(target, sympool, of);
+       this->sized_write_globals<64, true>(target, sympool, dynpool, of);
       else
-       this->sized_write_globals<64, false>(target, sympool, of);
+       this->sized_write_globals<64, false>(target, sympool, dynpool, of);
     }
   else
     gold_unreachable();
@@ -1158,12 +1172,22 @@ template<int size, bool big_endian>
 void
 Symbol_table::sized_write_globals(const Target*,
                                  const Stringpool* sympool,
+                                 const Stringpool* dynpool,
                                  Output_file* of) const
 {
   const int sym_size = elfcpp::Elf_sizes<size>::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* const psyms = of->get_output_view(this->offset_, oview_size);
+
+  unsigned int dynamic_count = this->dynamic_count_;
+  off_t dynamic_size = dynamic_count * sym_size;
+  unsigned int first_dynamic_global_index = this->first_dynamic_global_index_;
+  unsigned char* dynamic_view;
+  if (this->dynamic_offset_ == 0)
+    dynamic_view = NULL;
+  else
+    dynamic_view = of->get_output_view(this->dynamic_offset_, dynamic_size);
 
   unsigned char* ps = psyms;
   for (Symbol_table_type::const_iterator p = this->table_.begin();
@@ -1173,33 +1197,43 @@ Symbol_table::sized_write_globals(const Target*,
       Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(p->second);
 
       unsigned int sym_index = sym->symtab_index();
-      if (sym_index == -1U)
+      unsigned int dynsym_index;
+      if (dynamic_view == NULL)
+       dynsym_index = -1U;
+      else
+       dynsym_index = sym->dynsym_index();
+
+      if (sym_index == -1U && dynsym_index == -1U)
        {
          // This symbol is not included in the output file.
          continue;
        }
-      if (sym_index != index)
+
+      if (sym_index == index)
+       ++index;
+      else if (sym_index != -1U)
        {
          // We have already seen this symbol, because it has a
          // default version.
          gold_assert(sym_index < index);
-         continue;
+         if (dynsym_index == -1U)
+           continue;
+         sym_index = -1U;
        }
-      ++index;
 
       unsigned int shndx;
       switch (sym->source())
        {
        case Symbol::FROM_OBJECT:
          {
-           unsigned int shnum = sym->shnum();
+           unsigned int in_shndx = sym->shndx();
 
            // FIXME: We need some target specific support here.
-           if (shnum >= elfcpp::SHN_LORESERVE
-               && shnum != elfcpp::SHN_ABS)
+           if (in_shndx >= elfcpp::SHN_LORESERVE
+               && in_shndx != elfcpp::SHN_ABS)
              {
                fprintf(stderr, _("%s: %s: unsupported symbol section 0x%x\n"),
-                       program_name, sym->name(), sym->shnum());
+                       program_name, sym->name(), in_shndx);
                gold_exit(false);
              }
 
@@ -1209,13 +1243,14 @@ Symbol_table::sized_write_globals(const Target*,
                // FIXME.
                shndx = elfcpp::SHN_UNDEF;
              }
-           else if (shnum == elfcpp::SHN_UNDEF || shnum == elfcpp::SHN_ABS)
-             shndx = shnum;
+           else if (in_shndx == elfcpp::SHN_UNDEF
+                    || in_shndx == elfcpp::SHN_ABS)
+             shndx = in_shndx;
            else
              {
                Relobj* relobj = static_cast<Relobj*>(symobj);
                off_t secoff;
-               Output_section* os = relobj->output_section(shnum, &secoff);
+               Output_section* os = relobj->output_section(in_shndx, &secoff);
                gold_assert(os != NULL);
                shndx = os->out_shndx();
              }
@@ -1238,21 +1273,45 @@ Symbol_table::sized_write_globals(const Target*,
          gold_unreachable();
        }
 
-      elfcpp::Sym_write<size, big_endian> osym(ps);
-      osym.put_st_name(sympool->get_offset(sym->name()));
-      osym.put_st_value(sym->value());
-      osym.put_st_size(sym->symsize());
-      osym.put_st_info(elfcpp::elf_st_info(sym->binding(), sym->type()));
-      osym.put_st_other(elfcpp::elf_st_other(sym->visibility(),
-                                            sym->nonvis()));
-      osym.put_st_shndx(shndx);
+      if (sym_index != -1U)
+       {
+         this->sized_write_symbol<size, big_endian>(sym, shndx, sympool, ps);
+         ps += sym_size;
+       }
 
-      ps += sym_size;
+      if (dynsym_index != -1U)
+       {
+         dynsym_index -= first_dynamic_global_index;
+         gold_assert(dynsym_index < dynamic_count);
+         unsigned char* pd = dynamic_view + (dynsym_index * sym_size);
+         this->sized_write_symbol<size, big_endian>(sym, shndx, dynpool, pd);
+       }
     }
 
   gold_assert(ps - psyms == oview_size);
 
   of->write_output_view(this->offset_, oview_size, psyms);
+  if (dynamic_view != NULL)
+    of->write_output_view(this->dynamic_offset_, dynamic_size, dynamic_view);
+}
+
+// Write out the symbol SYM, in section SHNDX, to P.  POOL is the
+// strtab holding the name.
+
+template<int size, bool big_endian>
+void
+Symbol_table::sized_write_symbol(Sized_symbol<size>* sym,
+                                unsigned int shndx,
+                                const Stringpool* pool,
+                                unsigned char* p) const
+{
+  elfcpp::Sym_write<size, big_endian> osym(p);
+  osym.put_st_name(pool->get_offset(sym->name()));
+  osym.put_st_value(sym->value());
+  osym.put_st_size(sym->symsize());
+  osym.put_st_info(elfcpp::elf_st_info(sym->binding(), sym->type()));
+  osym.put_st_other(elfcpp::elf_st_other(sym->visibility(), sym->nonvis()));
+  osym.put_st_shndx(shndx);
 }
 
 // Write out a section symbol.  Return the update offset.
index 1350bf11a0ff4fccd71b88ea04ea07bc113a7286..ee3b3a8e2d5ff9da6eb52b767fd79eda95c44966 100644 (file)
@@ -97,10 +97,10 @@ class Symbol
   // Return the index of the section in the input relocatable or
   // dynamic object file.
   unsigned int
-  shnum() const
+  shndx() const
   {
     gold_assert(this->source_ == FROM_OBJECT);
-    return this->u_.from_object.shnum;
+    return this->u_.from_object.shndx;
   }
 
   // Return the output data section with which this symbol is
@@ -235,6 +235,12 @@ class Symbol
     this->dynsym_index_ = index;
   }
 
+  // Return whether this symbol already has an index in the dynamic
+  // symbol table.
+  bool
+  has_dynsym_index() const
+  { return this->dynsym_index_ != 0; }
+
   // Return whether this symbol has an entry in the GOT section.
   bool
   has_got_offset() const
@@ -293,8 +299,8 @@ class Symbol
   is_defined() const
   {
     return (this->source_ != FROM_OBJECT
-           || (this->shnum() != elfcpp::SHN_UNDEF
-               && this->shnum() != elfcpp::SHN_COMMON));
+           || (this->shndx() != elfcpp::SHN_UNDEF
+               && this->shndx() != elfcpp::SHN_COMMON));
   }
 
   // Return whether this symbol is defined in a dynamic object.
@@ -310,7 +316,7 @@ class Symbol
   bool
   is_undefined() const
   {
-    return this->source_ == FROM_OBJECT && this->shnum() == elfcpp::SHN_UNDEF;
+    return this->source_ == FROM_OBJECT && this->shndx() == elfcpp::SHN_UNDEF;
   }
 
   // Return whether this is a common symbol.
@@ -318,7 +324,7 @@ class Symbol
   is_common() const
   {
     return (this->source_ == FROM_OBJECT
-           && (this->shnum() == elfcpp::SHN_COMMON
+           && (this->shndx() == elfcpp::SHN_COMMON
                || this->type_ == elfcpp::STT_COMMON));
   }
 
@@ -391,7 +397,7 @@ class Symbol
       // seen.
       Object* object;
       // Section number in object_ in which symbol is defined.
-      unsigned int shnum;
+      unsigned int shndx;
     } from_object;
 
     // This struct is used if SOURCE_ == IN_OUTPUT_DATA.
@@ -824,14 +830,19 @@ class Symbol_table
   // Finalize the symbol table after we have set the final addresses
   // 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.
+  // first global symbol.  OFF is the file offset of the global symbol
+  // table, DYNOFF is the offset of the globals in the dynamic symbol
+  // table, DYN_GLOBAL_INDEX is the index of the first global dynamic
+  // symbol, and DYNCOUNT is the number of global dynamic symbols.
+  // This records the parameters, and returns the new file offset.
   off_t
-  finalize(unsigned int index, off_t off, Stringpool* pool);
+  finalize(unsigned int index, off_t off, off_t dynoff,
+          size_t dyn_global_index, size_t dyncount, Stringpool* pool);
 
   // Write out the global symbols.
   void
-  write_globals(const Target*, const Stringpool*, Output_file*) const;
+  write_globals(const Target*, const Stringpool*, const Stringpool*,
+               Output_file*) const;
 
   // Write out a section symbol.  Return the updated offset.
   void
@@ -915,7 +926,14 @@ class Symbol_table
   // Write globals specialized for size and endianness.
   template<int size, bool big_endian>
   void
-  sized_write_globals(const Target*, const Stringpool*, Output_file*) const;
+  sized_write_globals(const Target*, const Stringpool*, const Stringpool*,
+                     Output_file*) const;
+
+  // Write out a symbol to P.
+  template<int size, bool big_endian>
+  void
+  sized_write_symbol(Sized_symbol<size>*, unsigned int shndx,
+                    const Stringpool*, unsigned char* p) const;
 
   // Write out a section symbol, specialized for size and endianness.
   template<int size, bool big_endian>
@@ -962,6 +980,15 @@ class Symbol_table
   // The number of global symbols we want to write out.
   size_t output_count_;
 
+  // The file offset of the global dynamic symbols, or 0 if none.
+  off_t dynamic_offset_;
+
+  // The index of the first global dynamic symbol.
+  unsigned int first_dynamic_global_index_;
+
+  // The number of global dynamic symbols, or 0 if none.
+  off_t dynamic_count_;
+
   // The symbol hash table.
   Symbol_table_type table_;
 
index a031c403302197dd8e7f340767ab6026557491c3..42bed9ed37df88d8bf4b9a0619695de9d74653e2 100644 (file)
@@ -86,8 +86,8 @@ class Target
   // This is called to tell the target to complete any sections it is
   // handling.  After this all sections must have their final size.
   void
-  finalize_sections(Layout* layout)
-  { return this->do_finalize_sections(layout); }
+  finalize_sections(const General_options* options, Layout* layout)
+  { return this->do_finalize_sections(options, layout); }
 
  protected:
   // This struct holds the constant information for a child class.  We
@@ -121,7 +121,7 @@ class Target
 
   // Virtual function which may be implemented by the child class.
   virtual void
-  do_finalize_sections(Layout*)
+  do_finalize_sections(const General_options*, Layout*)
   { }
 
  private: