Fix buglet in last patch.
[deliverable/binutils-gdb.git] / gold / target-reloc.h
index 5b057ac0fb808364ef94c31c86245540427b05b1..771869149caaac6a35973edcfb822cd24555a673 100644 (file)
@@ -1,10 +1,29 @@
 // target-reloc.h -- target specific relocation support  -*- C++ -*-
 
+// Copyright 2006, 2007 Free Software Foundation, Inc.
+// Written by Ian Lance Taylor <iant@google.com>.
+
+// This file is part of gold.
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+// MA 02110-1301, USA.
+
 #ifndef GOLD_TARGET_RELOC_H
 #define GOLD_TARGET_RELOC_H
 
 #include "elfcpp.h"
-#include "object.h"
 #include "symtab.h"
 #include "reloc-types.h"
 
@@ -12,10 +31,10 @@ namespace gold
 {
 
 // 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.
+// is an inline function which takes a class whose member functions
+// local() and global() implement 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, typename Target_type, int sh_type,
         typename Scan>
@@ -26,11 +45,13 @@ scan_relocs(
     Layout* layout,
     Target_type* target,
     Sized_relobj<size, big_endian>* object,
+    unsigned int data_shndx,
     const unsigned char* prelocs,
     size_t reloc_count,
+    Output_section* output_section,
+    bool needs_special_offset_handling,
     size_t local_count,
-    const unsigned char* plocal_syms,
-    Symbol** global_syms)
+    const unsigned char* plocal_syms)
 {
   typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
   const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
@@ -41,13 +62,18 @@ scan_relocs(
     {
       Reltype reloc(prelocs);
 
+      if (needs_special_offset_handling
+         && !output_section->is_input_address_mapped(object, data_shndx,
+                                                     reloc.get_r_offset()))
+       continue;
+
       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);
 
       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();
@@ -73,24 +99,24 @@ scan_relocs(
              continue;
            }
 
-         scan.local(options, symtab, layout, target, object, reloc, r_type,
-                    lsym);
+         scan.local(options, symtab, layout, target, object, data_shndx,
+                    output_section, reloc, r_type, lsym);
        }
       else
        {
-         Symbol* gsym = global_syms[r_sym - local_count];
-         assert(gsym != NULL);
+         Symbol* gsym = object->global_symbol(r_sym);
+         gold_assert(gsym != NULL);
          if (gsym->is_forwarder())
            gsym = symtab->resolve_forwards(gsym);
 
-         scan.global(options, symtab, layout, target, object, reloc, r_type,
-                     gsym);
+         scan.global(options, symtab, layout, target, object, data_shndx,
+                     output_section, reloc, r_type, gsym);
        }
     }
 }
 
 // This function implements the generic part of relocation processing.
-// This is an inline function which take a class whose operator()
+// This is an inline function which take a class whose relocate()
 // implements the machine specific part of relocation.  We do it this
 // way to avoid making a function call for each relocation, and to
 // avoid repeating the generic relocation handling code for each
@@ -101,8 +127,14 @@ scan_relocs(
 // RELOCATE implements operator() to do a relocation.
 
 // PRELOCS points to the relocation data.  RELOC_COUNT is the number
-// of relocs.  VIEW is the section data, VIEW_ADDRESS is its memory
-// address, and VIEW_SIZE is the size.
+// of relocs.  OUTPUT_SECTION is the output section.
+// NEEDS_SPECIAL_OFFSET_HANDLING is true if input offsets need to be
+// mapped to output offsets.
+
+// VIEW is the section data, VIEW_ADDRESS is its memory address, and
+// VIEW_SIZE is the size.  These refer to the input section, unless
+// NEEDS_SPECIAL_OFFSET_HANDLING is true, in which case they refer to
+// the output section.
 
 template<int size, bool big_endian, typename Target_type, int sh_type,
         typename Relocate>
@@ -112,72 +144,84 @@ relocate_section(
     Target_type* target,
     const unsigned char* prelocs,
     size_t reloc_count,
+    Output_section* output_section,
+    bool needs_special_offset_handling,
     unsigned char* view,
     typename elfcpp::Elf_types<size>::Elf_Addr view_address,
-    off_t view_size)
+    section_size_type view_size)
 {
   typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
   const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
   Relocate relocate;
 
-  unsigned int local_count = relinfo->local_symbol_count;
-  const typename Sized_relobj<size, big_endian>::Local_values* local_values =
-    relinfo->local_values;
-  const Symbol* const * global_syms = relinfo->symbols;
+  Sized_relobj<size, big_endian>* object = relinfo->object;
+  unsigned int local_count = object->local_symbol_count();
 
   for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
     {
       Reltype reloc(prelocs);
 
-      off_t offset = reloc.get_r_offset();
+      section_offset_type offset =
+       convert_to_section_size_type(reloc.get_r_offset());
+
+      if (needs_special_offset_handling)
+       {
+         offset = output_section->output_offset(relinfo->object,
+                                                relinfo->data_shndx,
+                                                offset);
+         if (offset == -1)
+           continue;
+       }
 
       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);
 
       const Sized_symbol<size>* sym;
-      typename elfcpp::Elf_types<size>::Elf_Addr value;
 
+      Symbol_value<size> symval;
+      const Symbol_value<size> *psymval;
       if (r_sym < local_count)
        {
          sym = NULL;
-         value = (*local_values)[r_sym];
+         psymval = object->local_symbol(r_sym);
        }
       else
        {
-         const Symbol* gsym = global_syms[r_sym - local_count];
-         assert(gsym != NULL);
+         const Symbol* gsym = object->global_symbol(r_sym);
+         gold_assert(gsym != NULL);
          if (gsym->is_forwarder())
            gsym = relinfo->symtab->resolve_forwards(gsym);
 
          sym = static_cast<const Sized_symbol<size>*>(gsym);
-         value = sym->value();
+         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 (!relocate.relocate(relinfo, target, i, reloc, r_type, sym, value,
+      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)
+      if (offset < 0 || static_cast<section_size_type>(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);
+         gold_error_at_location(relinfo, i, offset,
+                                _("reloc has bad offset %zu"),
+                                static_cast<size_t>(offset));
+         continue;
        }
 
       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);
-       }
+         && sym->binding() != elfcpp::STB_WEAK
+         && !parameters->output_is_shared())
+       gold_undefined_symbol(sym, relinfo, i, offset);
 
       if (sym != NULL && sym->has_warning())
-       relinfo->symtab->issue_warning(sym, relinfo->location(i, offset));
+       relinfo->symtab->issue_warning(sym, relinfo, i, offset);
     }
 }
 
This page took 0.026777 seconds and 4 git commands to generate.