Use special value when we refer a function symbol in some way other
authorIan Lance Taylor <iant@google.com>
Sun, 23 Sep 2007 05:31:48 +0000 (05:31 +0000)
committerIan Lance Taylor <iant@google.com>
Sun, 23 Sep 2007 05:31:48 +0000 (05:31 +0000)
than calling it.

gold/i386.cc
gold/symtab.cc
gold/symtab.h
gold/target.h

index 00ac2883f554a6aff9eb22b91e5b1310fdbcc007..54c388b63d89825ce03c30b567eac35c4368afe2 100644 (file)
@@ -74,6 +74,11 @@ class Target_i386 : public Sized_target<32, false>
   void
   do_finalize_sections(Layout*);
 
+  // Return the value to use for a dynamic which requires special
+  // treatment.
+  uint64_t
+  do_dynsym_value(const Symbol*) const;
+
   // Relocate a section.
   void
   relocate_section(const Relocate_info<32, false>*,
@@ -844,7 +849,18 @@ Target_i386::Scan::global(const General_options& options,
          // function, we make a PLT entry.  Otherwise we need to
          // either generate a COPY reloc or copy this reloc.
          if (gsym->type() == elfcpp::STT_FUNC)
-           target->make_plt_entry(symtab, layout, gsym);
+           {
+             target->make_plt_entry(symtab, layout, gsym);
+
+             // If this is not a PC relative reference, then we may
+             // be taking the address of the function.  In that case
+             // we need to set the entry in the dynamic symbol table
+             // to the address of the PLT entry.
+             if (r_type != elfcpp::R_386_PC32
+                 && r_type != elfcpp::R_386_PC16
+                 && r_type != elfcpp::R_386_PC8)
+               gsym->set_needs_dynsym_value();
+           }
          else
            target->copy_reloc(&options, symtab, layout, object, data_shndx,
                               gsym, reloc);
@@ -1507,6 +1523,18 @@ Target_i386::relocate_section(const Relocate_info<32, false>* relinfo,
     view_size);
 }
 
+// Return the value to use for a dynamic which requires special
+// treatment.  This is how we support equality comparisons of function
+// pointers across shared library boundaries, as described in the
+// processor specific ABI supplement.
+
+uint64_t
+Target_i386::do_dynsym_value(const Symbol* gsym) const
+{
+  gold_assert(gsym->is_from_dynobj() && gsym->has_plt_offset());
+  return this->plt_section()->address() + gsym->plt_offset();
+}
+
 // Return a string used to fill a code section with nops to take up
 // the specified length.
 
index 2260acaac6ff104510f5f383c64e165041f650dc..8cd55cdaf6ff2cc7323b78954169bbdcf75eaf56 100644 (file)
@@ -1307,7 +1307,7 @@ Symbol_table::write_globals(const Target* target, const Stringpool* sympool,
 
 template<int size, bool big_endian>
 void
-Symbol_table::sized_write_globals(const Target*,
+Symbol_table::sized_write_globals(const Target* target,
                                  const Stringpool* sympool,
                                  const Stringpool* dynpool,
                                  Output_file* of) const
@@ -1359,6 +1359,7 @@ Symbol_table::sized_write_globals(const Target*,
        }
 
       unsigned int shndx;
+      typename elfcpp::Elf_types<32>::Elf_Addr value = sym->value();
       switch (sym->source())
        {
        case Symbol::FROM_OBJECT:
@@ -1377,7 +1378,8 @@ Symbol_table::sized_write_globals(const Target*,
            Object* symobj = sym->object();
            if (symobj->is_dynamic())
              {
-               // FIXME.
+               if (sym->needs_dynsym_value())
+                 value = target->dynsym_value(sym);
                shndx = elfcpp::SHN_UNDEF;
              }
            else if (in_shndx == elfcpp::SHN_UNDEF
@@ -1413,7 +1415,7 @@ Symbol_table::sized_write_globals(const Target*,
       if (sym_index != -1U)
        {
          this->sized_write_symbol SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
-              sym, shndx, sympool, ps
+             sym, sym->value(), shndx, sympool, ps
               SELECT_SIZE_ENDIAN(size, big_endian));
          ps += sym_size;
        }
@@ -1424,7 +1426,7 @@ Symbol_table::sized_write_globals(const Target*,
          gold_assert(dynsym_index < dynamic_count);
          unsigned char* pd = dynamic_view + (dynsym_index * sym_size);
          this->sized_write_symbol SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
-              sym, shndx, dynpool, pd
+             sym, value, shndx, dynpool, pd
               SELECT_SIZE_ENDIAN(size, big_endian));
        }
     }
@@ -1441,15 +1443,17 @@ Symbol_table::sized_write_globals(const Target*,
 
 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
-                                 ACCEPT_SIZE_ENDIAN) const
+Symbol_table::sized_write_symbol(
+    Sized_symbol<size>* sym,
+    typename elfcpp::Elf_types<size>::Elf_Addr value,
+    unsigned int shndx,
+    const Stringpool* pool,
+    unsigned char* p
+    ACCEPT_SIZE_ENDIAN) 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_value(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()));
index 642063882aa5e2a6c72222ca4812a94bb0560c92..36414bc1f23ad7afc778b45033e6e90120ca1b8f 100644 (file)
@@ -323,6 +323,21 @@ class Symbol
     this->plt_offset_ = plt_offset;
   }
 
+  // Return whether this dynamic symbol needs a special value in the
+  // dynamic symbol table.
+  bool
+  needs_dynsym_value() const
+  { return this->needs_dynsym_value_; }
+
+  // Set that this dynamic symbol needs a special value in the dynamic
+  // symbol table.
+  void
+  set_needs_dynsym_value()
+  {
+    gold_assert(this->object()->is_dynamic());
+    this->needs_dynsym_value_ = true;
+  }
+
   // Return true if the final value of this symbol is known at link
   // time.
   bool
@@ -528,6 +543,9 @@ class Symbol
   bool has_got_offset_ : 1;
   // True if the symbol has an entry in the PLT section.
   bool has_plt_offset_ : 1;
+  // True if this is a dynamic symbol which needs a special value in
+  // the dynamic symbol table.
+  bool needs_dynsym_value_ : 1;
   // True if there is a warning for this symbol.
   bool has_warning_ : 1;
 };
@@ -1003,7 +1021,9 @@ class Symbol_table
   // Write out a symbol to P.
   template<int size, bool big_endian>
   void
-  sized_write_symbol(Sized_symbol<size>*, unsigned int shndx,
+  sized_write_symbol(Sized_symbol<size>*,
+                    typename elfcpp::Elf_types<size>::Elf_Addr value,
+                    unsigned int shndx,
                     const Stringpool*, unsigned char* p
                      ACCEPT_SIZE_ENDIAN) const;
 
index 32ad143a149a8cfd4a150cc322c0b1b5567d5a01..31037ef90014fba3ba2c789d4c09e3dc5b2637b4 100644 (file)
@@ -114,6 +114,13 @@ class Target
   finalize_sections(Layout* layout)
   { return this->do_finalize_sections(layout); }
 
+  // Return the value to use for a global symbol which needs a special
+  // value in the dynamic symbol table.  This will only be called if
+  // the backend first calls symbol->set_needs_dynsym_value().
+  uint64_t
+  dynsym_value(const Symbol* sym) const
+  { return this->do_dynsym_value(sym); }
+
   // Return a string to use to fill out a code section.  This is
   // basically one or more NOPS which must fill out the specified
   // length in bytes.
@@ -158,6 +165,11 @@ class Target
   do_finalize_sections(Layout*)
   { }
 
+  // Virtual function which may be implemented by the child class.
+  virtual uint64_t
+  do_dynsym_value(const Symbol*) const
+  { gold_unreachable(); }
+
   // Virtual function which must be implemented by the child class if
   // needed.
   virtual std::string
This page took 0.031814 seconds and 4 git commands to generate.