* options.h (class General_options): Define --wrap as a special
[deliverable/binutils-gdb.git] / gold / i386.cc
index 8bd3f32bb24386751d05308ee34308ba76cbc0b0..7cfe117854b126e2de3db40346e1de0192ea1ed1 100644 (file)
@@ -1,6 +1,6 @@
 // i386.cc -- i386 target support for gold.
 
-// Copyright 2006, 2007 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -129,7 +129,7 @@ class Target_i386 : public Sized_target<32, false>
 
   // Return a string used to fill a code section with nops.
   std::string
-  do_code_fill(section_size_type length);
+  do_code_fill(section_size_type length) const;
 
   // Return whether SYM is defined by the ABI.
   bool
@@ -324,7 +324,7 @@ class Target_i386 : public Sized_target<32, false>
   bool
   may_need_copy_reloc(Symbol* gsym)
   {
-    return (!parameters->output_is_shared()
+    return (!parameters->options().shared()
             && gsym->is_from_dynobj()
             && gsym->type() != elfcpp::STT_FUNC);
   }
@@ -339,6 +339,15 @@ class Target_i386 : public Sized_target<32, false>
   // general Target structure.
   static const Target::Target_info i386_info;
 
+  // The types of GOT entries needed for this platform.
+  enum Got_type
+  {
+    GOT_TYPE_STANDARD = 0,      // GOT entry for a regular symbol
+    GOT_TYPE_TLS_OFFSET = 1,    // GOT entry for TLS offset
+    GOT_TYPE_TLS_PAIR = 2,      // GOT entry for TLS module/offset pair
+    GOT_TYPE_TLS_DESC = 3       // GOT entry for TLS_DESC pair
+  };
+
   // The GOT section.
   Output_data_got<32, false>* got_;
   // The PLT section.
@@ -364,10 +373,11 @@ const Target::Target_info Target_i386::i386_info =
   false,               // has_resolve
   true,                        // has_code_fill
   true,                        // is_default_stack_executable
+  '\0',                        // wrap_char
   "/usr/lib/libc.so.1",        // dynamic_linker
   0x08048000,          // default_text_segment_address
-  0x1000,              // abi_pagesize
-  0x1000               // common_pagesize
+  0x1000,              // abi_pagesize (overridable by -z max-page-size)
+  0x1000               // common_pagesize (overridable by -z common-page-size)
 };
 
 // Get the GOT section, creating it if necessary.
@@ -597,7 +607,7 @@ Output_data_plt_i386::do_write(Output_file* of)
   elfcpp::Elf_types<32>::Elf_Addr plt_address = this->address();
   elfcpp::Elf_types<32>::Elf_Addr got_address = this->got_plt_->address();
 
-  if (parameters->output_is_shared())
+  if (parameters->options().shared())
     memcpy(pov, dyn_first_plt_entry, plt_entry_size);
   else
     {
@@ -629,7 +639,7 @@ Output_data_plt_i386::do_write(Output_file* of)
     {
       // Set and adjust the PLT entry itself.
 
-      if (parameters->output_is_shared())
+      if (parameters->options().shared())
        {
          memcpy(pov, dyn_plt_entry, plt_entry_size);
          elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, got_offset);
@@ -726,9 +736,7 @@ Target_i386::copy_reloc(const General_options* options,
                        Symbol* gsym,
                        const elfcpp::Rel<32, false>& rel)
 {
-  Sized_symbol<32>* ssym;
-  ssym = symtab->get_sized_symbol SELECT_SIZE_NAME(32) (gsym
-                                                       SELECT_SIZE(32));
+  Sized_symbol<32>* ssym = symtab->get_sized_symbol<32>(gsym);
 
   if (!Copy_relocs<32, false>::need_copy_reloc(options, object,
                                               data_shndx, ssym))
@@ -792,7 +800,7 @@ Target_i386::optimize_tls_reloc(bool is_final, int r_type)
 {
   // If we are generating a shared library, then we can't do anything
   // in the linker.
-  if (parameters->output_is_shared())
+  if (parameters->options().shared())
     return tls::TLSOPT_NONE;
 
   switch (r_type)
@@ -878,7 +886,7 @@ Target_i386::Scan::local(const General_options&,
       // apply the link-time value, so we flag the location with
       // an R_386_RELATIVE relocation so the dynamic loader can
       // relocate it easily.
-      if (parameters->output_is_position_independent())
+      if (parameters->options().output_is_position_independent())
         {
           Reloc_section* rel_dyn = target->rel_dyn_section(layout);
           unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
@@ -895,7 +903,7 @@ Target_i386::Scan::local(const General_options&,
       // this location. Because the addend needs to remain in the
       // data section, we need to be careful not to apply this
       // relocation statically.
-      if (parameters->output_is_position_independent())
+      if (parameters->options().output_is_position_independent())
         {
           Reloc_section* rel_dyn = target->rel_dyn_section(layout);
           if (lsym.get_st_type() != elfcpp::STT_SECTION)
@@ -935,18 +943,17 @@ Target_i386::Scan::local(const General_options&,
         // The symbol requires a GOT entry.
         Output_data_got<32, false>* got = target->got_section(symtab, layout);
         unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
-        if (got->add_local(object, r_sym))
+        if (got->add_local(object, r_sym, GOT_TYPE_STANDARD))
           {
             // If we are generating a shared object, we need to add a
             // dynamic RELATIVE relocation for this symbol's GOT entry.
-            if (parameters->output_is_position_independent())
+            if (parameters->options().output_is_position_independent())
               {
                 Reloc_section* rel_dyn = target->rel_dyn_section(layout);
                 unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
-                rel_dyn->add_local_relative(object, r_sym,
-                                            elfcpp::R_386_RELATIVE,
-                                            got,
-                                            object->local_got_offset(r_sym));
+                rel_dyn->add_local_relative(
+                    object, r_sym, elfcpp::R_386_RELATIVE, got,
+                    object->local_got_offset(r_sym, GOT_TYPE_STANDARD));
               }
           }
       }
@@ -980,7 +987,7 @@ Target_i386::Scan::local(const General_options&,
     case elfcpp::R_386_TLS_LE:            // Local-exec
     case elfcpp::R_386_TLS_LE_32:
       {
-       bool output_is_shared = parameters->output_is_shared();
+       bool output_is_shared = parameters->options().shared();
        const tls::Tls_optimization optimized_type
             = Target_i386::optimize_tls_reloc(!output_is_shared, r_type);
        switch (r_type)
@@ -993,10 +1000,11 @@ Target_i386::Scan::local(const General_options&,
                 Output_data_got<32, false>* got
                     = target->got_section(symtab, layout);
                 unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
-                got->add_local_tls_with_rel(object, r_sym, 
-                                            lsym.get_st_shndx(), true,
-                                            target->rel_dyn_section(layout),
-                                            elfcpp::R_386_TLS_DTPMOD32);
+                got->add_local_pair_with_rel(object, r_sym, 
+                                             lsym.get_st_shndx(),
+                                             GOT_TYPE_TLS_PAIR,
+                                             target->rel_dyn_section(layout),
+                                             elfcpp::R_386_TLS_DTPMOD32, 0);
              }
            else if (optimized_type != tls::TLSOPT_TO_LE)
              unsupported_reloc_local(object, r_type);
@@ -1032,7 +1040,7 @@ Target_i386::Scan::local(const General_options&,
                // For the R_386_TLS_IE relocation, we need to create a
                // dynamic relocation when building a shared library.
                if (r_type == elfcpp::R_386_TLS_IE
-                   && parameters->output_is_shared())
+                   && parameters->options().shared())
                  {
                     Reloc_section* rel_dyn = target->rel_dyn_section(layout);
                     unsigned int r_sym
@@ -1049,7 +1057,7 @@ Target_i386::Scan::local(const General_options&,
                unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_IE_32
                                           ? elfcpp::R_386_TLS_TPOFF32
                                           : elfcpp::R_386_TLS_TPOFF);
-                got->add_local_with_rel(object, r_sym,
+                got->add_local_with_rel(object, r_sym, GOT_TYPE_TLS_OFFSET,
                                         target->rel_dyn_section(layout),
                                         dyn_r_type);
              }
@@ -1140,7 +1148,7 @@ Target_i386::Scan::global(const General_options& options,
             // taking the address of a function. In that case we need to
             // set the entry in the dynamic symbol table to the address of
             // the PLT entry.
-            if (gsym->is_from_dynobj() && !parameters->output_is_shared())
+            if (gsym->is_from_dynobj() && !parameters->options().shared())
               gsym->set_needs_dynsym_value();
           }
         // Make a dynamic relocation if necessary.
@@ -1182,7 +1190,7 @@ Target_i386::Scan::global(const General_options& options,
             // PLT entry and let the dynamic linker bind the call directly
             // to the target.  For smaller relocations, we should use a
             // PLT entry to ensure that the call can reach.
-            if (!parameters->output_is_shared()
+            if (!parameters->options().shared()
                 || r_type != elfcpp::R_386_PC32)
               target->make_plt_entry(symtab, layout, gsym);
           }
@@ -1212,7 +1220,7 @@ Target_i386::Scan::global(const General_options& options,
         // The symbol requires a GOT entry.
         Output_data_got<32, false>* got = target->got_section(symtab, layout);
         if (gsym->final_value_is_known())
-          got->add_global(gsym);
+          got->add_global(gsym, GOT_TYPE_STANDARD);
         else
           {
             // If this symbol is not fully resolved, we need to add a
@@ -1221,12 +1229,14 @@ Target_i386::Scan::global(const General_options& options,
             if (gsym->is_from_dynobj()
                 || gsym->is_undefined()
                 || gsym->is_preemptible())
-              got->add_global_with_rel(gsym, rel_dyn, elfcpp::R_386_GLOB_DAT);
+              got->add_global_with_rel(gsym, GOT_TYPE_STANDARD,
+                                       rel_dyn, elfcpp::R_386_GLOB_DAT);
             else
               {
-                if (got->add_global(gsym))
-                  rel_dyn->add_global_relative(gsym, elfcpp::R_386_RELATIVE,
-                                               got, gsym->got_offset());
+                if (got->add_global(gsym, GOT_TYPE_STANDARD))
+                  rel_dyn->add_global_relative(
+                      gsym, elfcpp::R_386_RELATIVE, got,
+                      gsym->got_offset(GOT_TYPE_STANDARD));
               }
           }
       }
@@ -1293,7 +1303,7 @@ Target_i386::Scan::global(const General_options& options,
                // dtv-relative offset.
                 Output_data_got<32, false>* got
                     = target->got_section(symtab, layout);
-                got->add_global_tls_with_rel(gsym,
+                got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
                                              target->rel_dyn_section(layout),
                                              elfcpp::R_386_TLS_DTPMOD32,
                                              elfcpp::R_386_TLS_DTPOFF32);
@@ -1303,7 +1313,8 @@ Target_i386::Scan::global(const General_options& options,
                // Create a GOT entry for the tp-relative offset.
                 Output_data_got<32, false>* got
                     = target->got_section(symtab, layout);
-                got->add_global_with_rel(gsym, target->rel_dyn_section(layout),
+                got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
+                                         target->rel_dyn_section(layout),
                                          elfcpp::R_386_TLS_TPOFF32);
              }
            else if (optimized_type != tls::TLSOPT_TO_LE)
@@ -1341,7 +1352,7 @@ Target_i386::Scan::global(const General_options& options,
                // For the R_386_TLS_IE relocation, we need to create a
                // dynamic relocation when building a shared library.
                if (r_type == elfcpp::R_386_TLS_IE
-                   && parameters->output_is_shared())
+                   && parameters->options().shared())
                  {
                     Reloc_section* rel_dyn = target->rel_dyn_section(layout);
                     rel_dyn->add_global_relative(gsym, elfcpp::R_386_RELATIVE,
@@ -1355,7 +1366,7 @@ Target_i386::Scan::global(const General_options& options,
                unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_IE_32
                                           ? elfcpp::R_386_TLS_TPOFF32
                                           : elfcpp::R_386_TLS_TPOFF);
-                got->add_global_with_rel(gsym,
+                got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
                                          target->rel_dyn_section(layout),
                                          dyn_r_type);
              }
@@ -1366,7 +1377,7 @@ Target_i386::Scan::global(const General_options& options,
          case elfcpp::R_386_TLS_LE:          // Local-exec
          case elfcpp::R_386_TLS_LE_32:
            layout->set_has_static_tls();
-           if (parameters->output_is_shared())
+           if (parameters->options().shared())
              {
                // We need to create a dynamic relocation.
                 unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_LE_32
@@ -1468,7 +1479,7 @@ Target_i386::do_finalize_sections(Layout* layout)
                             elfcpp::Elf_sizes<32>::rel_size);
        }
 
-      if (!parameters->output_is_shared())
+      if (!parameters->options().shared())
        {
          // The value of the DT_DEBUG tag is filled in by the dynamic
          // linker at run time, and used by the debugger.
@@ -1505,7 +1516,7 @@ Target_i386::Relocate::should_apply_static_reloc(const Sized_symbol<32>* gsym,
   // (b) the relocation is absolute (not pc- or segment-relative), and
   // (c) the relocation is not 32 bits wide.
   if (gsym == NULL)
-    return !(parameters->output_is_position_independent()
+    return !(parameters->options().output_is_position_independent()
              && (ref_flags & Symbol::ABSOLUTE_REF)
              && !is_32bit);
 
@@ -1555,10 +1566,10 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
                     || r_type == elfcpp::R_386_PC32);
   if (gsym != NULL
       && (gsym->is_from_dynobj()
-          || (parameters->output_is_shared()
+          || (parameters->options().shared()
               && (gsym->is_undefined() || gsym->is_preemptible())))
       && gsym->has_plt_offset()
-      && (!is_nonpic || !parameters->output_is_shared()))
+      && (!is_nonpic || !parameters->options().shared()))
     {
       symval.set_output_value(target->plt_section()->address()
                              + gsym->plt_offset());
@@ -1578,14 +1589,16 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
     case elfcpp::R_386_GOT32:
       if (gsym != NULL)
         {
-          gold_assert(gsym->has_got_offset());
-          got_offset = gsym->got_offset() - target->got_size();
+          gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
+          got_offset = (gsym->got_offset(GOT_TYPE_STANDARD)
+                        - target->got_size());
         }
       else
         {
           unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
-          gold_assert(object->local_has_got_offset(r_sym));
-          got_offset = object->local_got_offset(r_sym) - target->got_size();
+          gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
+          got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
+                        - target->got_size());
         }
       have_got_offset = true;
       break;
@@ -1750,9 +1763,10 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
 
   elfcpp::Elf_types<32>::Elf_Addr value = psymval->value(object, 0);
 
-  const bool is_final = (gsym == NULL
-                        ? !parameters->output_is_position_independent()
-                        : gsym->final_value_is_known());
+  const bool is_final =
+    (gsym == NULL
+     ? !parameters->options().output_is_position_independent()
+     : gsym->final_value_is_known());
   const tls::Tls_optimization optimized_type
       = Target_i386::optimize_tls_reloc(is_final, r_type);
   switch (r_type)
@@ -1771,14 +1785,16 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
           unsigned int got_offset;
           if (gsym != NULL)
             {
-              gold_assert(gsym->has_tls_got_offset(true));
-              got_offset = gsym->tls_got_offset(true) - target->got_size();
+              gold_assert(gsym->has_got_offset(GOT_TYPE_TLS_PAIR));
+              got_offset = (gsym->got_offset(GOT_TYPE_TLS_PAIR)
+                            - target->got_size());
             }
           else
             {
               unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
-              gold_assert(object->local_has_tls_got_offset(r_sym, true));
-              got_offset = (object->local_tls_got_offset(r_sym, true)
+              gold_assert(object->local_has_got_offset(r_sym,
+                                                       GOT_TYPE_TLS_PAIR));
+              got_offset = (object->local_got_offset(r_sym, GOT_TYPE_TLS_PAIR)
                            - target->got_size());
             }
           if (optimized_type == tls::TLSOPT_TO_IE)
@@ -1869,14 +1885,16 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
           unsigned int got_offset;
           if (gsym != NULL)
             {
-              gold_assert(gsym->has_got_offset());
-              got_offset = gsym->got_offset();
+              gold_assert(gsym->has_got_offset(GOT_TYPE_TLS_OFFSET));
+              got_offset = gsym->got_offset(GOT_TYPE_TLS_OFFSET);
             }
           else
             {
               unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
-              gold_assert(object->local_has_got_offset(r_sym));
-              got_offset = object->local_got_offset(r_sym);
+              gold_assert(object->local_has_got_offset(r_sym,
+                                                       GOT_TYPE_TLS_OFFSET));
+              got_offset = object->local_got_offset(r_sym,
+                                                    GOT_TYPE_TLS_OFFSET);
             }
           // For the R_386_TLS_IE relocation, we need to apply the
           // absolute address of the GOT entry.
@@ -1895,7 +1913,7 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
     case elfcpp::R_386_TLS_LE:           // Local-exec
       // If we're creating a shared library, a dynamic relocation will
       // have been created for this location, so do not apply it now.
-      if (!parameters->output_is_shared())
+      if (!parameters->options().shared())
         {
           gold_assert(tls_segment != NULL);
           value -= tls_segment->memsz();
@@ -1906,7 +1924,7 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
     case elfcpp::R_386_TLS_LE_32:
       // If we're creating a shared library, a dynamic relocation will
       // have been created for this location, so do not apply it now.
-      if (!parameters->output_is_shared())
+      if (!parameters->options().shared())
         {
           gold_assert(tls_segment != NULL);
           value = tls_segment->memsz() - value;
@@ -2297,7 +2315,7 @@ Target_i386::scan_relocatable_relocs(const General_options& options,
   typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_REL,
     Relocatable_size_for_reloc> Scan_relocatable_relocs;
 
-  gold::scan_relocatable_relocs<32, false, Target_i386, elfcpp::SHT_REL,
+  gold::scan_relocatable_relocs<32, false, elfcpp::SHT_REL,
       Scan_relocatable_relocs>(
     options,
     symtab,
@@ -2332,7 +2350,7 @@ Target_i386::relocate_for_relocatable(
 {
   gold_assert(sh_type == elfcpp::SHT_REL);
 
-  gold::relocate_for_relocatable<32, false, Target_i386, elfcpp::SHT_REL>(
+  gold::relocate_for_relocatable<32, false, elfcpp::SHT_REL>(
     relinfo,
     prelocs,
     reloc_count,
@@ -2362,7 +2380,7 @@ Target_i386::do_dynsym_value(const Symbol* gsym) const
 // the specified length.
 
 std::string
-Target_i386::do_code_fill(section_size_type length)
+Target_i386::do_code_fill(section_size_type length) const
 {
   if (length >= 16)
     {
@@ -2427,40 +2445,14 @@ class Target_selector_i386 : public Target_selector
 {
 public:
   Target_selector_i386()
-    : Target_selector(elfcpp::EM_386, 32, false)
+    : Target_selector(elfcpp::EM_386, 32, false, "elf32-i386")
   { }
 
   Target*
-  recognize(int machine, int osabi, int abiversion);
-
-  Target*
-  recognize_by_name(const char* name);
-
- private:
-  Target_i386* target_;
+  do_instantiate_target()
+  { return new Target_i386(); }
 };
 
-// Recognize an i386 object file when we already know that the machine
-// number is EM_386.
-
-Target*
-Target_selector_i386::recognize(int, int, int)
-{
-  if (this->target_ == NULL)
-    this->target_ = new Target_i386();
-  return this->target_;
-}
-
-Target*
-Target_selector_i386::recognize_by_name(const char* name)
-{
-  if (strcmp(name, "elf32-i386") != 0)
-    return NULL;
-  if (this->target_ == NULL)
-    this->target_ = new Target_i386();
-  return this->target_;
-}
-
 Target_selector_i386 target_selector_i386;
 
 } // End anonymous namespace.
This page took 0.038438 seconds and 4 git commands to generate.