* ld-mips-elf/reloc-4.s, ld-mips-elf/reloc-4.d,
[deliverable/binutils-gdb.git] / gold / target-reloc.h
index 2d1fe306fb434262923fa016e7d2db02482cc200..d282805dbebba9349389296216fac64e69f5139a 100644 (file)
@@ -6,42 +6,27 @@
 #include "elfcpp.h"
 #include "object.h"
 #include "symtab.h"
+#include "reloc-types.h"
 
 namespace gold
 {
 
-// Pick the ELF relocation accessor class and the size based on
-// SH_TYPE, which is either SHT_REL or SHT_RELA.
-
-template<int sh_type, int size, bool big_endian>
-struct Reloc_types;
-
-template<int size, bool big_endian>
-struct Reloc_types<elfcpp::SHT_REL, size, big_endian>
-{
-  typedef typename elfcpp::Rel<size, big_endian> Reloc;
-  static const int reloc_size = elfcpp::Elf_sizes<size>::rel_size;
-};
-
-template<int size, bool big_endian>
-struct Reloc_types<elfcpp::SHT_RELA, size, big_endian>
-{
-  typedef typename elfcpp::Rela<size, big_endian> Reloc;
-  static const int reloc_size = elfcpp::Elf_sizes<size>::rela_size;
-};
-
 // This function implements the generic part of reloc scanning.  This
 // is an inline function which takes a class whose operator()
 // implements the machine specific part of scanning.  We do it this
 // way to avoidmaking a function call for each relocation, and to
 // avoid repeating the generic code for each target.
 
-template<int size, bool big_endian, int sh_type, typename Scan>
+template<int size, bool big_endian, typename Target_type, int sh_type,
+        typename Scan>
 inline void
 scan_relocs(
     const General_options& options,
     Symbol_table* symtab,
-    Sized_object<size, big_endian>* object,
+    Layout* layout,
+    Target_type* target,
+    Sized_relobj<size, big_endian>* object,
+    unsigned int data_shndx,
     const unsigned char* prelocs,
     size_t reloc_count,
     size_t local_count,
@@ -63,11 +48,12 @@ scan_relocs(
 
       if (r_sym < local_count)
        {
-         assert(plocal_syms != NULL);
+         gold_assert(plocal_syms != NULL);
          typename elfcpp::Sym<size, big_endian> lsym(plocal_syms
                                                      + r_sym * sym_size);
          const unsigned int shndx = lsym.get_st_shndx();
          if (shndx < elfcpp::SHN_LORESERVE
+             && shndx != elfcpp::SHN_UNDEF
              && !object->is_section_included(lsym.get_st_shndx()))
            {
              // RELOC is a relocation against a local symbol in a
@@ -88,16 +74,18 @@ scan_relocs(
              continue;
            }
 
-         scan.local(options, object, reloc, r_type, lsym);
+         scan.local(options, symtab, layout, target, object, data_shndx,
+                    reloc, r_type, lsym);
        }
       else
        {
          Symbol* gsym = global_syms[r_sym - local_count];
-         assert(gsym != NULL);
+         gold_assert(gsym != NULL);
          if (gsym->is_forwarder())
            gsym = symtab->resolve_forwards(gsym);
 
-         scan.global(options, object, reloc, r_type, gsym);
+         scan.global(options, symtab, layout, target, object, data_shndx,
+                     reloc, r_type, gsym);
        }
     }
 }
@@ -117,10 +105,12 @@ scan_relocs(
 // of relocs.  VIEW is the section data, VIEW_ADDRESS is its memory
 // address, and VIEW_SIZE is the size.
 
-template<int size, bool big_endian, int sh_type, typename Relocate>
+template<int size, bool big_endian, typename Target_type, int sh_type,
+        typename Relocate>
 inline void
 relocate_section(
     const Relocate_info<size, big_endian>* relinfo,
+    Target_type* target,
     const unsigned char* prelocs,
     size_t reloc_count,
     unsigned char* view,
@@ -132,56 +122,69 @@ relocate_section(
   Relocate relocate;
 
   unsigned int local_count = relinfo->local_symbol_count;
-  typename elfcpp::Elf_types<size>::Elf_Addr *local_values = relinfo->values;
-  Symbol** global_syms = relinfo->symbols;
+  const typename Sized_relobj<size, big_endian>::Local_values* local_values =
+    relinfo->local_values;
+  const Symbol* const * global_syms = relinfo->symbols;
 
   for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
     {
       Reltype reloc(prelocs);
 
       off_t offset = reloc.get_r_offset();
-      if (offset < 0 || offset >= view_size)
-       {
-         fprintf(stderr, _("%s: %s: reloc has bad offset %zu\n"),
-                 program_name, relinfo->location(i, offset).c_str(),
-                 static_cast<size_t>(offset));
-         gold_exit(false);
-       }
 
       typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
       unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
       unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
 
-      Sized_symbol<size>* sym;
-      typename elfcpp::Elf_types<size>::Elf_Addr value;
+      const Sized_symbol<size>* sym;
 
+      Symbol_value<size> symval;
+      const Symbol_value<size> *psymval;
       if (r_sym < local_count)
        {
          sym = NULL;
-         value = local_values[r_sym];
+         psymval = &(*local_values)[r_sym];
        }
       else
        {
-         Symbol* gsym = global_syms[r_sym - local_count];
-         assert(gsym != NULL);
+         const Symbol* gsym = global_syms[r_sym - local_count];
+         gold_assert(gsym != NULL);
          if (gsym->is_forwarder())
            gsym = relinfo->symtab->resolve_forwards(gsym);
 
-         sym = static_cast<Sized_symbol<size>*>(gsym);
-         value = sym->value();
+         sym = static_cast<const Sized_symbol<size>*>(gsym);
+         if (sym->has_symtab_index())
+           symval.set_output_symtab_index(sym->symtab_index());
+         else
+           symval.set_no_output_symtab_entry();
+         symval.set_output_value(sym->value());
+         psymval = &symval;
+       }
 
-         if (sym->shnum() == elfcpp::SHN_UNDEF
-             && sym->binding() != elfcpp::STB_WEAK)
-           {
-             fprintf(stderr, _("%s: %s: undefined reference to '%s'\n"),
-                     program_name, relinfo->location(i, offset).c_str(),
-                     sym->name());
-             // gold_exit(false);
-           }
+      if (!relocate.relocate(relinfo, target, i, reloc, r_type, sym, psymval,
+                            view + offset, view_address + offset, view_size))
+       continue;
+
+      if (offset < 0 || offset >= view_size)
+       {
+         fprintf(stderr, _("%s: %s: reloc has bad offset %zu\n"),
+                 program_name, relinfo->location(i, offset).c_str(),
+                 static_cast<size_t>(offset));
+         gold_exit(false);
+       }
+
+      if (sym != NULL
+         && sym->is_undefined()
+         && sym->binding() != elfcpp::STB_WEAK)
+       {
+         fprintf(stderr, _("%s: %s: undefined reference to '%s'\n"),
+                 program_name, relinfo->location(i, offset).c_str(),
+                 sym->name());
+         // gold_exit(false);
        }
 
-      relocate.relocate(relinfo, i, reloc, r_type, sym, value, view + offset,
-                       view_address + offset, view_size);
+      if (sym != NULL && sym->has_warning())
+       relinfo->symtab->issue_warning(sym, relinfo->location(i, offset));
     }
 }
 
This page took 0.025298 seconds and 4 git commands to generate.