Fix typo in comment.
[deliverable/binutils-gdb.git] / gold / target-reloc.h
CommitLineData
61ba1cf9
ILT
1// target-reloc.h -- target specific relocation support -*- C++ -*-
2
6cb15b7f
ILT
3// Copyright 2006, 2007 Free Software Foundation, Inc.
4// Written by Ian Lance Taylor <iant@google.com>.
5
6// This file is part of gold.
7
8// This program is free software; you can redistribute it and/or modify
9// it under the terms of the GNU General Public License as published by
10// the Free Software Foundation; either version 3 of the License, or
11// (at your option) any later version.
12
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17
18// You should have received a copy of the GNU General Public License
19// along with this program; if not, write to the Free Software
20// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21// MA 02110-1301, USA.
22
61ba1cf9
ILT
23#ifndef GOLD_TARGET_RELOC_H
24#define GOLD_TARGET_RELOC_H
25
26#include "elfcpp.h"
92e059d8 27#include "object.h"
61ba1cf9 28#include "symtab.h"
c06b7b0b 29#include "reloc-types.h"
61ba1cf9
ILT
30
31namespace gold
32{
33
92e059d8
ILT
34// This function implements the generic part of reloc scanning. This
35// is an inline function which takes a class whose operator()
36// implements the machine specific part of scanning. We do it this
37// way to avoidmaking a function call for each relocation, and to
38// avoid repeating the generic code for each target.
39
ead1e424
ILT
40template<int size, bool big_endian, typename Target_type, int sh_type,
41 typename Scan>
92e059d8
ILT
42inline void
43scan_relocs(
44 const General_options& options,
45 Symbol_table* symtab,
ead1e424
ILT
46 Layout* layout,
47 Target_type* target,
f6ce93d6 48 Sized_relobj<size, big_endian>* object,
a3ad94ed 49 unsigned int data_shndx,
92e059d8
ILT
50 const unsigned char* prelocs,
51 size_t reloc_count,
52 size_t local_count,
53 const unsigned char* plocal_syms,
54 Symbol** global_syms)
55{
56 typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
57 const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
58 const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
59 Scan scan;
60
61 for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
62 {
63 Reltype reloc(prelocs);
64
65 typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
66 unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
67 unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
68
69 if (r_sym < local_count)
70 {
a3ad94ed 71 gold_assert(plocal_syms != NULL);
92e059d8
ILT
72 typename elfcpp::Sym<size, big_endian> lsym(plocal_syms
73 + r_sym * sym_size);
74 const unsigned int shndx = lsym.get_st_shndx();
75 if (shndx < elfcpp::SHN_LORESERVE
ead1e424 76 && shndx != elfcpp::SHN_UNDEF
92e059d8
ILT
77 && !object->is_section_included(lsym.get_st_shndx()))
78 {
79 // RELOC is a relocation against a local symbol in a
80 // section we are discarding. We can ignore this
81 // relocation. It will eventually become a reloc
82 // against the value zero.
83 //
84 // FIXME: We should issue a warning if this is an
85 // allocated section; is this the best place to do it?
86 //
87 // FIXME: The old GNU linker would in some cases look
88 // for the linkonce section which caused this section to
89 // be discarded, and, if the other section was the same
90 // size, change the reloc to refer to the other section.
91 // That seems risky and weird to me, and I don't know of
92 // any case where it is actually required.
93
94 continue;
95 }
96
a3ad94ed
ILT
97 scan.local(options, symtab, layout, target, object, data_shndx,
98 reloc, r_type, lsym);
92e059d8
ILT
99 }
100 else
101 {
102 Symbol* gsym = global_syms[r_sym - local_count];
a3ad94ed 103 gold_assert(gsym != NULL);
92e059d8
ILT
104 if (gsym->is_forwarder())
105 gsym = symtab->resolve_forwards(gsym);
106
a3ad94ed
ILT
107 scan.global(options, symtab, layout, target, object, data_shndx,
108 reloc, r_type, gsym);
92e059d8
ILT
109 }
110 }
111}
112
113// This function implements the generic part of relocation processing.
72a2eed7 114// This is an inline function which take a class whose relocate()
61ba1cf9
ILT
115// implements the machine specific part of relocation. We do it this
116// way to avoid making a function call for each relocation, and to
117// avoid repeating the generic relocation handling code for each
118// target.
119
120// SIZE is the ELF size: 32 or 64. BIG_ENDIAN is the endianness of
92e059d8
ILT
121// the data. SH_TYPE is the section type: SHT_REL or SHT_RELA.
122// RELOCATE implements operator() to do a relocation.
61ba1cf9 123
92e059d8
ILT
124// PRELOCS points to the relocation data. RELOC_COUNT is the number
125// of relocs. VIEW is the section data, VIEW_ADDRESS is its memory
126// address, and VIEW_SIZE is the size.
61ba1cf9 127
ead1e424
ILT
128template<int size, bool big_endian, typename Target_type, int sh_type,
129 typename Relocate>
61ba1cf9
ILT
130inline void
131relocate_section(
92e059d8 132 const Relocate_info<size, big_endian>* relinfo,
ead1e424 133 Target_type* target,
61ba1cf9
ILT
134 const unsigned char* prelocs,
135 size_t reloc_count,
61ba1cf9
ILT
136 unsigned char* view,
137 typename elfcpp::Elf_types<size>::Elf_Addr view_address,
138 off_t view_size)
139{
140 typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
141 const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
142 Relocate relocate;
143
92e059d8 144 unsigned int local_count = relinfo->local_symbol_count;
c06b7b0b
ILT
145 const typename Sized_relobj<size, big_endian>::Local_values* local_values =
146 relinfo->local_values;
147 const Symbol* const * global_syms = relinfo->symbols;
92e059d8 148
61ba1cf9
ILT
149 for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
150 {
151 Reltype reloc(prelocs);
152
153 off_t offset = reloc.get_r_offset();
61ba1cf9
ILT
154
155 typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
156 unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
157 unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
158
c06b7b0b 159 const Sized_symbol<size>* sym;
61ba1cf9 160
b8e6aad9
ILT
161 Symbol_value<size> symval;
162 const Symbol_value<size> *psymval;
61ba1cf9
ILT
163 if (r_sym < local_count)
164 {
165 sym = NULL;
b8e6aad9 166 psymval = &(*local_values)[r_sym];
61ba1cf9
ILT
167 }
168 else
169 {
c06b7b0b 170 const Symbol* gsym = global_syms[r_sym - local_count];
a3ad94ed 171 gold_assert(gsym != NULL);
61ba1cf9 172 if (gsym->is_forwarder())
92e059d8 173 gsym = relinfo->symtab->resolve_forwards(gsym);
61ba1cf9 174
c06b7b0b 175 sym = static_cast<const Sized_symbol<size>*>(gsym);
b8e6aad9
ILT
176 if (sym->has_symtab_index())
177 symval.set_output_symtab_index(sym->symtab_index());
178 else
179 symval.set_no_output_symtab_entry();
180 symval.set_output_value(sym->value());
181 psymval = &symval;
ead1e424 182 }
61ba1cf9 183
b8e6aad9 184 if (!relocate.relocate(relinfo, target, i, reloc, r_type, sym, psymval,
ead1e424
ILT
185 view + offset, view_address + offset, view_size))
186 continue;
187
188 if (offset < 0 || offset >= view_size)
189 {
190 fprintf(stderr, _("%s: %s: reloc has bad offset %zu\n"),
191 program_name, relinfo->location(i, offset).c_str(),
192 static_cast<size_t>(offset));
193 gold_exit(false);
61ba1cf9
ILT
194 }
195
ead1e424
ILT
196 if (sym != NULL
197 && sym->is_undefined()
198 && sym->binding() != elfcpp::STB_WEAK)
199 {
200 fprintf(stderr, _("%s: %s: undefined reference to '%s'\n"),
201 program_name, relinfo->location(i, offset).c_str(),
202 sym->name());
7d00dcbd 203 gold_exit(false);
ead1e424 204 }
f6ce93d6
ILT
205
206 if (sym != NULL && sym->has_warning())
207 relinfo->symtab->issue_warning(sym, relinfo->location(i, offset));
61ba1cf9
ILT
208 }
209}
210
211} // End namespace gold.
212
213#endif // !defined(GOLD_TARGET_RELOC_H)
This page took 0.063716 seconds and 4 git commands to generate.