Remove unnecessary elfcpp_config.h file.
[deliverable/binutils-gdb.git] / gold / target-reloc.h
CommitLineData
61ba1cf9
ILT
1// target-reloc.h -- target specific relocation support -*- C++ -*-
2
3#ifndef GOLD_TARGET_RELOC_H
4#define GOLD_TARGET_RELOC_H
5
6#include "elfcpp.h"
92e059d8 7#include "object.h"
61ba1cf9 8#include "symtab.h"
c06b7b0b 9#include "reloc-types.h"
61ba1cf9
ILT
10
11namespace gold
12{
13
92e059d8
ILT
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.
19
ead1e424
ILT
20template<int size, bool big_endian, typename Target_type, int sh_type,
21 typename Scan>
92e059d8
ILT
22inline void
23scan_relocs(
24 const General_options& options,
25 Symbol_table* symtab,
ead1e424
ILT
26 Layout* layout,
27 Target_type* target,
f6ce93d6 28 Sized_relobj<size, big_endian>* object,
a3ad94ed 29 unsigned int data_shndx,
92e059d8
ILT
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)
35{
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;
40
41 for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
42 {
43 Reltype reloc(prelocs);
44
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);
48
49 if (r_sym < local_count)
50 {
a3ad94ed 51 gold_assert(plocal_syms != NULL);
92e059d8
ILT
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
ead1e424 56 && shndx != elfcpp::SHN_UNDEF
92e059d8
ILT
57 && !object->is_section_included(lsym.get_st_shndx()))
58 {
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.
63 //
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.
73
74 continue;
75 }
76
a3ad94ed
ILT
77 scan.local(options, symtab, layout, target, object, data_shndx,
78 reloc, r_type, lsym);
92e059d8
ILT
79 }
80 else
81 {
82 Symbol* gsym = global_syms[r_sym - local_count];
a3ad94ed 83 gold_assert(gsym != NULL);
92e059d8
ILT
84 if (gsym->is_forwarder())
85 gsym = symtab->resolve_forwards(gsym);
86
a3ad94ed
ILT
87 scan.global(options, symtab, layout, target, object, data_shndx,
88 reloc, r_type, gsym);
92e059d8
ILT
89 }
90 }
91}
92
93// This function implements the generic part of relocation processing.
72a2eed7 94// This is an inline function which take a class whose relocate()
61ba1cf9
ILT
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.
99
100// SIZE is the ELF size: 32 or 64. BIG_ENDIAN is the endianness of
92e059d8
ILT
101// the data. SH_TYPE is the section type: SHT_REL or SHT_RELA.
102// RELOCATE implements operator() to do a relocation.
61ba1cf9 103
92e059d8
ILT
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.
61ba1cf9 107
ead1e424
ILT
108template<int size, bool big_endian, typename Target_type, int sh_type,
109 typename Relocate>
61ba1cf9
ILT
110inline void
111relocate_section(
92e059d8 112 const Relocate_info<size, big_endian>* relinfo,
ead1e424 113 Target_type* target,
61ba1cf9
ILT
114 const unsigned char* prelocs,
115 size_t reloc_count,
61ba1cf9
ILT
116 unsigned char* view,
117 typename elfcpp::Elf_types<size>::Elf_Addr view_address,
118 off_t view_size)
119{
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;
123
92e059d8 124 unsigned int local_count = relinfo->local_symbol_count;
c06b7b0b
ILT
125 const typename Sized_relobj<size, big_endian>::Local_values* local_values =
126 relinfo->local_values;
127 const Symbol* const * global_syms = relinfo->symbols;
92e059d8 128
61ba1cf9
ILT
129 for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
130 {
131 Reltype reloc(prelocs);
132
133 off_t offset = reloc.get_r_offset();
61ba1cf9
ILT
134
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);
138
c06b7b0b 139 const Sized_symbol<size>* sym;
61ba1cf9 140
b8e6aad9
ILT
141 Symbol_value<size> symval;
142 const Symbol_value<size> *psymval;
61ba1cf9
ILT
143 if (r_sym < local_count)
144 {
145 sym = NULL;
b8e6aad9 146 psymval = &(*local_values)[r_sym];
61ba1cf9
ILT
147 }
148 else
149 {
c06b7b0b 150 const Symbol* gsym = global_syms[r_sym - local_count];
a3ad94ed 151 gold_assert(gsym != NULL);
61ba1cf9 152 if (gsym->is_forwarder())
92e059d8 153 gsym = relinfo->symtab->resolve_forwards(gsym);
61ba1cf9 154
c06b7b0b 155 sym = static_cast<const Sized_symbol<size>*>(gsym);
b8e6aad9
ILT
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;
ead1e424 162 }
61ba1cf9 163
b8e6aad9 164 if (!relocate.relocate(relinfo, target, i, reloc, r_type, sym, psymval,
ead1e424
ILT
165 view + offset, view_address + offset, view_size))
166 continue;
167
168 if (offset < 0 || offset >= view_size)
169 {
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);
61ba1cf9
ILT
174 }
175
ead1e424
ILT
176 if (sym != NULL
177 && sym->is_undefined()
178 && sym->binding() != elfcpp::STB_WEAK)
179 {
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);
184 }
f6ce93d6
ILT
185
186 if (sym != NULL && sym->has_warning())
187 relinfo->symtab->issue_warning(sym, relinfo->location(i, offset));
61ba1cf9
ILT
188 }
189}
190
191} // End namespace gold.
192
193#endif // !defined(GOLD_TARGET_RELOC_H)
This page took 0.070067 seconds and 4 git commands to generate.