]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gold/target-reloc.h
Hash tables, dynamic section, i386 PLT, gold_assert.
[thirdparty/binutils-gdb.git] / gold / target-reloc.h
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"
7 #include "object.h"
8 #include "symtab.h"
9 #include "reloc-types.h"
10
11 namespace gold
12 {
13
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
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)
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 {
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()))
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
77 scan.local(options, symtab, layout, target, object, data_shndx,
78 reloc, r_type, lsym);
79 }
80 else
81 {
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);
86
87 scan.global(options, symtab, layout, target, object, data_shndx,
88 reloc, r_type, gsym);
89 }
90 }
91 }
92
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.
99
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.
103
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.
107
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)
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
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;
128
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();
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
139 const Sized_symbol<size>* sym;
140 typename elfcpp::Elf_types<size>::Elf_Addr value;
141
142 if (r_sym < local_count)
143 {
144 sym = NULL;
145 value = (*local_values)[r_sym];
146 }
147 else
148 {
149 const Symbol* gsym = global_syms[r_sym - local_count];
150 gold_assert(gsym != NULL);
151 if (gsym->is_forwarder())
152 gsym = relinfo->symtab->resolve_forwards(gsym);
153
154 sym = static_cast<const Sized_symbol<size>*>(gsym);
155 value = sym->value();
156 }
157
158 if (!relocate.relocate(relinfo, target, i, reloc, r_type, sym, value,
159 view + offset, view_address + offset, view_size))
160 continue;
161
162 if (offset < 0 || offset >= view_size)
163 {
164 fprintf(stderr, _("%s: %s: reloc has bad offset %zu\n"),
165 program_name, relinfo->location(i, offset).c_str(),
166 static_cast<size_t>(offset));
167 gold_exit(false);
168 }
169
170 if (sym != NULL
171 && sym->is_undefined()
172 && sym->binding() != elfcpp::STB_WEAK)
173 {
174 fprintf(stderr, _("%s: %s: undefined reference to '%s'\n"),
175 program_name, relinfo->location(i, offset).c_str(),
176 sym->name());
177 // gold_exit(false);
178 }
179
180 if (sym != NULL && sym->has_warning())
181 relinfo->symtab->issue_warning(sym, relinfo->location(i, offset));
182 }
183 }
184
185 } // End namespace gold.
186
187 #endif // !defined(GOLD_TARGET_RELOC_H)