2007-08-06 Paul Brook <paul@codesourcery.com>
[binutils.git] / gold / target-reloc.h
blobd282805dbebba9349389296216fac64e69f5139a
1 // target-reloc.h -- target specific relocation support -*- C++ -*-
3 #ifndef GOLD_TARGET_RELOC_H
4 #define GOLD_TARGET_RELOC_H
6 #include "elfcpp.h"
7 #include "object.h"
8 #include "symtab.h"
9 #include "reloc-types.h"
11 namespace gold
14 // This function implements the generic part of reloc scanning. This
15 // is an inline function which takes a class whose operator()
16 // implements the machine specific part of scanning. We do it this
17 // way to avoidmaking a function call for each relocation, and to
18 // avoid repeating the generic code for each target.
20 template<int size, bool big_endian, typename Target_type, int sh_type,
21 typename Scan>
22 inline void
23 scan_relocs(
24 const General_options& options,
25 Symbol_table* symtab,
26 Layout* layout,
27 Target_type* target,
28 Sized_relobj<size, big_endian>* object,
29 unsigned int data_shndx,
30 const unsigned char* prelocs,
31 size_t reloc_count,
32 size_t local_count,
33 const unsigned char* plocal_syms,
34 Symbol** global_syms)
36 typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
37 const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
38 const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
39 Scan scan;
41 for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
43 Reltype reloc(prelocs);
45 typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
46 unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
47 unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
49 if (r_sym < local_count)
51 gold_assert(plocal_syms != NULL);
52 typename elfcpp::Sym<size, big_endian> lsym(plocal_syms
53 + r_sym * sym_size);
54 const unsigned int shndx = lsym.get_st_shndx();
55 if (shndx < elfcpp::SHN_LORESERVE
56 && shndx != elfcpp::SHN_UNDEF
57 && !object->is_section_included(lsym.get_st_shndx()))
59 // RELOC is a relocation against a local symbol in a
60 // section we are discarding. We can ignore this
61 // relocation. It will eventually become a reloc
62 // against the value zero.
64 // FIXME: We should issue a warning if this is an
65 // allocated section; is this the best place to do it?
66 //
67 // FIXME: The old GNU linker would in some cases look
68 // for the linkonce section which caused this section to
69 // be discarded, and, if the other section was the same
70 // size, change the reloc to refer to the other section.
71 // That seems risky and weird to me, and I don't know of
72 // any case where it is actually required.
74 continue;
77 scan.local(options, symtab, layout, target, object, data_shndx,
78 reloc, r_type, lsym);
80 else
82 Symbol* gsym = global_syms[r_sym - local_count];
83 gold_assert(gsym != NULL);
84 if (gsym->is_forwarder())
85 gsym = symtab->resolve_forwards(gsym);
87 scan.global(options, symtab, layout, target, object, data_shndx,
88 reloc, r_type, gsym);
93 // This function implements the generic part of relocation processing.
94 // This is an inline function which take a class whose operator()
95 // implements the machine specific part of relocation. We do it this
96 // way to avoid making a function call for each relocation, and to
97 // avoid repeating the generic relocation handling code for each
98 // target.
100 // SIZE is the ELF size: 32 or 64. BIG_ENDIAN is the endianness of
101 // the data. SH_TYPE is the section type: SHT_REL or SHT_RELA.
102 // RELOCATE implements operator() to do a relocation.
104 // PRELOCS points to the relocation data. RELOC_COUNT is the number
105 // of relocs. VIEW is the section data, VIEW_ADDRESS is its memory
106 // address, and VIEW_SIZE is the size.
108 template<int size, bool big_endian, typename Target_type, int sh_type,
109 typename Relocate>
110 inline void
111 relocate_section(
112 const Relocate_info<size, big_endian>* relinfo,
113 Target_type* target,
114 const unsigned char* prelocs,
115 size_t reloc_count,
116 unsigned char* view,
117 typename elfcpp::Elf_types<size>::Elf_Addr view_address,
118 off_t view_size)
120 typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
121 const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
122 Relocate relocate;
124 unsigned int local_count = relinfo->local_symbol_count;
125 const typename Sized_relobj<size, big_endian>::Local_values* local_values =
126 relinfo->local_values;
127 const Symbol* const * global_syms = relinfo->symbols;
129 for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
131 Reltype reloc(prelocs);
133 off_t offset = reloc.get_r_offset();
135 typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
136 unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
137 unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
139 const Sized_symbol<size>* sym;
141 Symbol_value<size> symval;
142 const Symbol_value<size> *psymval;
143 if (r_sym < local_count)
145 sym = NULL;
146 psymval = &(*local_values)[r_sym];
148 else
150 const Symbol* gsym = global_syms[r_sym - local_count];
151 gold_assert(gsym != NULL);
152 if (gsym->is_forwarder())
153 gsym = relinfo->symtab->resolve_forwards(gsym);
155 sym = static_cast<const Sized_symbol<size>*>(gsym);
156 if (sym->has_symtab_index())
157 symval.set_output_symtab_index(sym->symtab_index());
158 else
159 symval.set_no_output_symtab_entry();
160 symval.set_output_value(sym->value());
161 psymval = &symval;
164 if (!relocate.relocate(relinfo, target, i, reloc, r_type, sym, psymval,
165 view + offset, view_address + offset, view_size))
166 continue;
168 if (offset < 0 || offset >= view_size)
170 fprintf(stderr, _("%s: %s: reloc has bad offset %zu\n"),
171 program_name, relinfo->location(i, offset).c_str(),
172 static_cast<size_t>(offset));
173 gold_exit(false);
176 if (sym != NULL
177 && sym->is_undefined()
178 && sym->binding() != elfcpp::STB_WEAK)
180 fprintf(stderr, _("%s: %s: undefined reference to '%s'\n"),
181 program_name, relinfo->location(i, offset).c_str(),
182 sym->name());
183 // gold_exit(false);
186 if (sym != NULL && sym->has_warning())
187 relinfo->symtab->issue_warning(sym, relinfo->location(i, offset));
191 } // End namespace gold.
193 #endif // !defined(GOLD_TARGET_RELOC_H)