* observer.sh: Set LANG/LC_ALL to C, not c.
[deliverable/binutils-gdb.git] / gold / powerpc.cc
index 2fc2ed891c8528068e80e26d33b6b552520469f9..9e3d327d01a396dc6947405fd04d039eaadcbfd2 100644 (file)
@@ -1,6 +1,6 @@
 // powerpc.cc -- powerpc target support for gold.
 
-// Copyright 2008 Free Software Foundation, Inc.
+// Copyright 2008, 2009 Free Software Foundation, Inc.
 // Written by David S. Miller <davem@davemloft.net>
 //        and David Edelsohn <edelsohn@gnu.org>
 
@@ -61,6 +61,22 @@ class Target_powerpc : public Sized_target<size, big_endian>
   {
   }
 
+  // Process the relocations to determine unreferenced sections for 
+  // garbage collection.
+  void
+  gc_process_relocs(const General_options& options,
+                   Symbol_table* symtab,
+                   Layout* layout,
+                   Sized_relobj<size, big_endian>* object,
+                   unsigned int data_shndx,
+                   unsigned int sh_type,
+                   const unsigned char* prelocs,
+                   size_t reloc_count,
+                   Output_section* output_section,
+                   bool needs_special_offset_handling,
+                   size_t local_symbol_count,
+                   const unsigned char* plocal_symbols);
+
   // Scan the relocations to look for symbol adjustments.
   void
   scan_relocs(const General_options& options,
@@ -129,7 +145,7 @@ class Target_powerpc : public Sized_target<size, big_endian>
 
   // Return whether SYM is defined by the ABI.
   bool
-  do_is_defined_by_abi(Symbol* sym) const
+  do_is_defined_by_abi(const Symbol* sym) const
   {
     return strcmp(sym->name(), "___tls_get_addr") == 0;
   }
@@ -198,7 +214,8 @@ class Target_powerpc : public Sized_target<size, big_endian>
     // any warnings about this relocation.
     inline bool
     relocate(const Relocate_info<size, big_endian>*, Target_powerpc*,
-            size_t relnum, const elfcpp::Rela<size, big_endian>&,
+            Output_section*, size_t relnum,
+            const elfcpp::Rela<size, big_endian>&,
             unsigned int r_type, const Sized_symbol<size>*,
             const Symbol_value<size>*,
             unsigned char*,
@@ -280,7 +297,8 @@ class Target_powerpc : public Sized_target<size, big_endian>
 
   // Copy a relocation against a global symbol.
   void
-  copy_reloc(Symbol_table* symtab, Layout* layout, Relobj* object,
+  copy_reloc(Symbol_table* symtab, Layout* layout,
+             Sized_relobj<size, big_endian>* object,
             unsigned int shndx, Output_section* output_section,
             Symbol* sym, const elfcpp::Rela<size, big_endian>& reloc)
   {
@@ -594,9 +612,6 @@ public:
            typename elfcpp::Elf_types<size>::Elf_Addr value,
            typename elfcpp::Elf_types<size>::Elf_Addr addend)
   {
-    typedef typename elfcpp::Swap<16, true>::Valtype Valtype;
-    Valtype* wv = reinterpret_cast<Valtype*>(view);
-    Valtype val = elfcpp::Swap<16, true>::readval(wv);
     typename elfcpp::Elf_types<size>::Elf_Addr reloc;
 
     reloc = value + addend;
@@ -605,10 +620,7 @@ public:
       reloc += 0x10000;
     reloc >>= 16;
 
-    val &= ~0xffff;
-    reloc &= 0xffff;
-
-    elfcpp::Swap<16, true>::writeval(wv, val | reloc);
+    elfcpp::Swap<16, big_endian>::writeval(view, reloc);
   }
 
   static inline void
@@ -617,9 +629,6 @@ public:
            const Symbol_value<size>* psymval,
            typename elfcpp::Elf_types<size>::Elf_Addr addend)
   {
-    typedef typename elfcpp::Swap<16, true>::Valtype Valtype;
-    Valtype* wv = reinterpret_cast<Valtype*>(view);
-    Valtype val = elfcpp::Swap<16, true>::readval(wv);
     typename elfcpp::Elf_types<size>::Elf_Addr reloc;
 
     reloc = psymval->value(object, addend);
@@ -628,10 +637,7 @@ public:
       reloc += 0x10000;
     reloc >>= 16;
 
-    val &= ~0xffff;
-    reloc &= 0xffff;
-
-    elfcpp::Swap<16, true>::writeval(wv, val | reloc);
+    elfcpp::Swap<16, big_endian>::writeval(view, reloc);
   }
 
   // R_PPC_REL16: (Symbol + Addend - Address) & 0xffff
@@ -674,9 +680,6 @@ public:
           typename elfcpp::Elf_types<size>::Elf_Addr addend,
           typename elfcpp::Elf_types<size>::Elf_Addr address)
   {
-    typedef typename elfcpp::Swap<16, true>::Valtype Valtype;
-    Valtype* wv = reinterpret_cast<Valtype*>(view);
-    Valtype val = elfcpp::Swap<16, true>::readval(wv);
     typename elfcpp::Elf_types<size>::Elf_Addr reloc;
 
     reloc = (psymval->value(object, addend) - address);
@@ -684,10 +687,7 @@ public:
       reloc += 0x10000;
     reloc >>= 16;
 
-    val &= ~0xffff;
-    reloc &= 0xffff;
-
-    elfcpp::Swap<16, true>::writeval(wv, val | reloc);
+    elfcpp::Swap<16, big_endian>::writeval(view, reloc);
   }
 };
 
@@ -906,7 +906,7 @@ Output_data_plt_powerpc<size, big_endian>::do_write(Output_file* of)
                                           lwz_11_30 + plt_offset);
          elfcpp::Swap<32, true>::writeval(pov + 0x04, mtctr_11);
          elfcpp::Swap<32, true>::writeval(pov + 0x08, bctr);
-         elfcpp::Swap<32, true>::writeval(pov + 0x0b, nop);
+         elfcpp::Swap<32, true>::writeval(pov + 0x0c, nop);
          pov += base_plt_entry_size;
          plt_offset += base_plt_entry_size;
        }
@@ -1094,6 +1094,7 @@ Target_powerpc<size, big_endian>::Scan::check_non_pic(Relobj* object,
   // error per object file.
   if (this->issued_non_pic_error_)
     return;
+  gold_assert(parameters->options().output_is_position_independent());
   object->error(_("requires unsupported dynamic reloc; "
                  "recompile with -fPIC"));
   this->issued_non_pic_error_ = true;
@@ -1431,6 +1432,42 @@ Target_powerpc<size, big_endian>::Scan::global(
     }
 }
 
+// Process relocations for gc.
+
+template<int size, bool big_endian>
+void
+Target_powerpc<size, big_endian>::gc_process_relocs(
+                       const General_options& options,
+                       Symbol_table* symtab,
+                       Layout* layout,
+                       Sized_relobj<size, big_endian>* object,
+                       unsigned int data_shndx,
+                       unsigned int,
+                       const unsigned char* prelocs,
+                       size_t reloc_count,
+                       Output_section* output_section,
+                       bool needs_special_offset_handling,
+                       size_t local_symbol_count,
+                       const unsigned char* plocal_symbols)
+{
+  typedef Target_powerpc<size, big_endian> Powerpc;
+  typedef typename Target_powerpc<size, big_endian>::Scan Scan;
+
+  gold::gc_process_relocs<size, big_endian, Powerpc, elfcpp::SHT_RELA, Scan>(
+    options,
+    symtab,
+    layout,
+    this,
+    object,
+    data_shndx,
+    prelocs,
+    reloc_count,
+    output_section,
+    needs_special_offset_handling,
+    local_symbol_count,
+    plocal_symbols);
+}
+
 // Scan relocations for a section.
 
 template<int size, bool big_endian>
@@ -1543,6 +1580,7 @@ inline bool
 Target_powerpc<size, big_endian>::Relocate::relocate(
                        const Relocate_info<size, big_endian>* relinfo,
                        Target_powerpc* target,
+                       Output_section*,
                        size_t relnum,
                        const elfcpp::Rela<size, big_endian>& rela,
                        unsigned int r_type,
@@ -1558,10 +1596,12 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
   // Pick the value to use for symbols defined in shared objects.
   Symbol_value<size> symval;
   if (gsym != NULL
-      && (gsym->is_from_dynobj()
-          || (parameters->options().shared()
-              && (gsym->is_undefined() || gsym->is_preemptible())))
-      && gsym->has_plt_offset())
+      && gsym->use_plt_offset(r_type == elfcpp::R_POWERPC_REL24
+                             || r_type == elfcpp::R_PPC_LOCAL24PC
+                             || r_type == elfcpp::R_PPC_REL16
+                             || r_type == elfcpp::R_PPC_REL16_LO
+                             || r_type == elfcpp::R_PPC_REL16_HI
+                             || r_type == elfcpp::R_PPC_REL16_HA))
     {
       elfcpp::Elf_Xword value;
 
@@ -1690,7 +1730,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
       break;
 
     case elfcpp::R_PPC_REL16_HA:
-      Reloc::rel16_lo(view, object, psymval, addend, address);
+      Reloc::rel16_ha(view, object, psymval, addend, address);
       break;
 
     case elfcpp::R_POWERPC_GOT16:
@@ -1943,8 +1983,6 @@ public:
                       (big_endian ? "elf32-powerpc" : "elf32-powerpcle")))
   { }
 
-  Target* instantiated_target_;
-
   Target* do_recognize(int machine, int, int)
   {
     switch (size)
@@ -1963,15 +2001,11 @@ public:
        return NULL;
       }
 
-    return do_instantiate_target();
+    return this->instantiate_target();
   }
 
   Target* do_instantiate_target()
-  {
-    if (this->instantiated_target_ == NULL)
-      this->instantiated_target_ = new Target_powerpc<size, big_endian>();
-    return this->instantiated_target_;
-  }
+  { return new Target_powerpc<size, big_endian>(); }
 };
 
 Target_selector_powerpc<32, true> target_selector_ppc32;
This page took 0.026665 seconds and 4 git commands to generate.