elf32-microblaze.c revision 1.1.1.7.4.1 1 1.1 christos /* Xilinx MicroBlaze-specific support for 32-bit ELF
2 1.1 christos
3 1.1.1.7.4.1 christos Copyright (C) 2009-2019 Free Software Foundation, Inc.
4 1.1 christos
5 1.1 christos This file is part of BFD, the Binary File Descriptor library.
6 1.1 christos
7 1.1 christos This program is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3 of the License, or
10 1.1 christos (at your option) any later version.
11 1.1 christos
12 1.1 christos This program is distributed in the hope that it will be useful,
13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 christos GNU General Public License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program; if not, write to the
19 1.1 christos Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20 1.1 christos Boston, MA 02110-1301, USA. */
21 1.1 christos
22 1.1 christos
23 1.1 christos int dbg = 0;
24 1.1 christos
25 1.1 christos #include "sysdep.h"
26 1.1.1.2 christos #include "bfd.h"
27 1.1 christos #include "bfdlink.h"
28 1.1 christos #include "libbfd.h"
29 1.1 christos #include "elf-bfd.h"
30 1.1 christos #include "elf/microblaze.h"
31 1.1 christos #include <assert.h>
32 1.1 christos
33 1.1 christos #define USE_RELA /* Only USE_REL is actually significant, but this is
34 1.1 christos here are a reminder... */
35 1.1 christos #define INST_WORD_SIZE 4
36 1.1 christos
37 1.1 christos static int ro_small_data_pointer = 0;
38 1.1 christos static int rw_small_data_pointer = 0;
39 1.1 christos
40 1.1 christos static reloc_howto_type * microblaze_elf_howto_table [(int) R_MICROBLAZE_max];
41 1.1 christos
42 1.1 christos static reloc_howto_type microblaze_elf_howto_raw[] =
43 1.1 christos {
44 1.1 christos /* This reloc does nothing. */
45 1.1 christos HOWTO (R_MICROBLAZE_NONE, /* Type. */
46 1.1.1.7.4.1 christos 0, /* Rightshift. */
47 1.1.1.7.4.1 christos 3, /* Size (0 = byte, 1 = short, 2 = long). */
48 1.1.1.7.4.1 christos 0, /* Bitsize. */
49 1.1.1.7.4.1 christos FALSE, /* PC_relative. */
50 1.1.1.7.4.1 christos 0, /* Bitpos. */
51 1.1.1.7.4.1 christos complain_overflow_dont, /* Complain on overflow. */
52 1.1.1.7.4.1 christos NULL, /* Special Function. */
53 1.1.1.7.4.1 christos "R_MICROBLAZE_NONE", /* Name. */
54 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
55 1.1.1.7.4.1 christos 0, /* Source Mask. */
56 1.1.1.7.4.1 christos 0, /* Dest Mask. */
57 1.1.1.7.4.1 christos FALSE), /* PC relative offset? */
58 1.1 christos
59 1.1 christos /* A standard 32 bit relocation. */
60 1.1.1.7.4.1 christos HOWTO (R_MICROBLAZE_32, /* Type. */
61 1.1.1.7.4.1 christos 0, /* Rightshift. */
62 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
63 1.1.1.7.4.1 christos 32, /* Bitsize. */
64 1.1.1.7.4.1 christos FALSE, /* PC_relative. */
65 1.1.1.7.4.1 christos 0, /* Bitpos. */
66 1.1.1.7.4.1 christos complain_overflow_bitfield, /* Complain on overflow. */
67 1.1.1.7.4.1 christos bfd_elf_generic_reloc,/* Special Function. */
68 1.1.1.7.4.1 christos "R_MICROBLAZE_32", /* Name. */
69 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
70 1.1.1.7.4.1 christos 0, /* Source Mask. */
71 1.1.1.7.4.1 christos 0xffffffff, /* Dest Mask. */
72 1.1.1.7.4.1 christos FALSE), /* PC relative offset? */
73 1.1 christos
74 1.1 christos /* A standard PCREL 32 bit relocation. */
75 1.1 christos HOWTO (R_MICROBLAZE_32_PCREL,/* Type. */
76 1.1.1.7.4.1 christos 0, /* Rightshift. */
77 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
78 1.1.1.7.4.1 christos 32, /* Bitsize. */
79 1.1.1.7.4.1 christos TRUE, /* PC_relative. */
80 1.1.1.7.4.1 christos 0, /* Bitpos. */
81 1.1.1.7.4.1 christos complain_overflow_bitfield, /* Complain on overflow. */
82 1.1.1.7.4.1 christos bfd_elf_generic_reloc,/* Special Function. */
83 1.1.1.7.4.1 christos "R_MICROBLAZE_32_PCREL", /* Name. */
84 1.1.1.7.4.1 christos TRUE, /* Partial Inplace. */
85 1.1.1.7.4.1 christos 0, /* Source Mask. */
86 1.1.1.7.4.1 christos 0xffffffff, /* Dest Mask. */
87 1.1.1.7.4.1 christos TRUE), /* PC relative offset? */
88 1.1 christos
89 1.1 christos /* A 64 bit PCREL relocation. Table-entry not really used. */
90 1.1 christos HOWTO (R_MICROBLAZE_64_PCREL,/* Type. */
91 1.1.1.7.4.1 christos 0, /* Rightshift. */
92 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
93 1.1.1.7.4.1 christos 16, /* Bitsize. */
94 1.1.1.7.4.1 christos TRUE, /* PC_relative. */
95 1.1.1.7.4.1 christos 0, /* Bitpos. */
96 1.1.1.7.4.1 christos complain_overflow_dont, /* Complain on overflow. */
97 1.1.1.7.4.1 christos bfd_elf_generic_reloc,/* Special Function. */
98 1.1.1.7.4.1 christos "R_MICROBLAZE_64_PCREL", /* Name. */
99 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
100 1.1.1.7.4.1 christos 0, /* Source Mask. */
101 1.1.1.7.4.1 christos 0x0000ffff, /* Dest Mask. */
102 1.1.1.7.4.1 christos TRUE), /* PC relative offset? */
103 1.1 christos
104 1.1 christos /* The low half of a PCREL 32 bit relocation. */
105 1.1.1.7.4.1 christos HOWTO (R_MICROBLAZE_32_PCREL_LO, /* Type. */
106 1.1.1.7.4.1 christos 0, /* Rightshift. */
107 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
108 1.1.1.7.4.1 christos 16, /* Bitsize. */
109 1.1.1.7.4.1 christos TRUE, /* PC_relative. */
110 1.1.1.7.4.1 christos 0, /* Bitpos. */
111 1.1.1.7.4.1 christos complain_overflow_signed, /* Complain on overflow. */
112 1.1.1.7.4.1 christos bfd_elf_generic_reloc, /* Special Function. */
113 1.1.1.7.4.1 christos "R_MICROBLAZE_32_PCREL_LO", /* Name. */
114 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
115 1.1.1.7.4.1 christos 0, /* Source Mask. */
116 1.1.1.7.4.1 christos 0x0000ffff, /* Dest Mask. */
117 1.1.1.7.4.1 christos TRUE), /* PC relative offset? */
118 1.1 christos
119 1.1 christos /* A 64 bit relocation. Table entry not really used. */
120 1.1.1.7.4.1 christos HOWTO (R_MICROBLAZE_64, /* Type. */
121 1.1.1.7.4.1 christos 0, /* Rightshift. */
122 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
123 1.1.1.7.4.1 christos 16, /* Bitsize. */
124 1.1.1.7.4.1 christos FALSE, /* PC_relative. */
125 1.1.1.7.4.1 christos 0, /* Bitpos. */
126 1.1.1.7.4.1 christos complain_overflow_dont, /* Complain on overflow. */
127 1.1.1.7.4.1 christos bfd_elf_generic_reloc,/* Special Function. */
128 1.1.1.7.4.1 christos "R_MICROBLAZE_64", /* Name. */
129 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
130 1.1.1.7.4.1 christos 0, /* Source Mask. */
131 1.1.1.7.4.1 christos 0x0000ffff, /* Dest Mask. */
132 1.1.1.7.4.1 christos FALSE), /* PC relative offset? */
133 1.1 christos
134 1.1 christos /* The low half of a 32 bit relocation. */
135 1.1.1.7.4.1 christos HOWTO (R_MICROBLAZE_32_LO, /* Type. */
136 1.1.1.7.4.1 christos 0, /* Rightshift. */
137 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
138 1.1.1.7.4.1 christos 16, /* Bitsize. */
139 1.1.1.7.4.1 christos FALSE, /* PC_relative. */
140 1.1.1.7.4.1 christos 0, /* Bitpos. */
141 1.1.1.7.4.1 christos complain_overflow_signed, /* Complain on overflow. */
142 1.1.1.7.4.1 christos bfd_elf_generic_reloc,/* Special Function. */
143 1.1.1.7.4.1 christos "R_MICROBLAZE_32_LO", /* Name. */
144 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
145 1.1.1.7.4.1 christos 0, /* Source Mask. */
146 1.1.1.7.4.1 christos 0x0000ffff, /* Dest Mask. */
147 1.1.1.7.4.1 christos FALSE), /* PC relative offset? */
148 1.1 christos
149 1.1 christos /* Read-only small data section relocation. */
150 1.1.1.7.4.1 christos HOWTO (R_MICROBLAZE_SRO32, /* Type. */
151 1.1.1.7.4.1 christos 0, /* Rightshift. */
152 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
153 1.1.1.7.4.1 christos 16, /* Bitsize. */
154 1.1.1.7.4.1 christos FALSE, /* PC_relative. */
155 1.1.1.7.4.1 christos 0, /* Bitpos. */
156 1.1.1.7.4.1 christos complain_overflow_bitfield, /* Complain on overflow. */
157 1.1.1.7.4.1 christos bfd_elf_generic_reloc,/* Special Function. */
158 1.1.1.7.4.1 christos "R_MICROBLAZE_SRO32", /* Name. */
159 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
160 1.1.1.7.4.1 christos 0, /* Source Mask. */
161 1.1.1.7.4.1 christos 0x0000ffff, /* Dest Mask. */
162 1.1.1.7.4.1 christos FALSE), /* PC relative offset? */
163 1.1 christos
164 1.1 christos /* Read-write small data area relocation. */
165 1.1.1.7.4.1 christos HOWTO (R_MICROBLAZE_SRW32, /* Type. */
166 1.1.1.7.4.1 christos 0, /* Rightshift. */
167 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
168 1.1.1.7.4.1 christos 16, /* Bitsize. */
169 1.1.1.7.4.1 christos FALSE, /* PC_relative. */
170 1.1.1.7.4.1 christos 0, /* Bitpos. */
171 1.1.1.7.4.1 christos complain_overflow_bitfield, /* Complain on overflow. */
172 1.1.1.7.4.1 christos bfd_elf_generic_reloc,/* Special Function. */
173 1.1.1.7.4.1 christos "R_MICROBLAZE_SRW32", /* Name. */
174 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
175 1.1.1.7.4.1 christos 0, /* Source Mask. */
176 1.1.1.7.4.1 christos 0x0000ffff, /* Dest Mask. */
177 1.1.1.7.4.1 christos FALSE), /* PC relative offset? */
178 1.1 christos
179 1.1.1.7.4.1 christos /* This reloc does nothing. Used for relaxation. */
180 1.1 christos HOWTO (R_MICROBLAZE_64_NONE, /* Type. */
181 1.1.1.7.4.1 christos 0, /* Rightshift. */
182 1.1.1.7.4.1 christos 3, /* Size (0 = byte, 1 = short, 2 = long). */
183 1.1.1.7.4.1 christos 0, /* Bitsize. */
184 1.1.1.7.4.1 christos TRUE, /* PC_relative. */
185 1.1.1.7.4.1 christos 0, /* Bitpos. */
186 1.1.1.7.4.1 christos complain_overflow_dont, /* Complain on overflow. */
187 1.1.1.7.4.1 christos NULL, /* Special Function. */
188 1.1.1.7.4.1 christos "R_MICROBLAZE_64_NONE",/* Name. */
189 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
190 1.1.1.7.4.1 christos 0, /* Source Mask. */
191 1.1.1.7.4.1 christos 0, /* Dest Mask. */
192 1.1.1.7.4.1 christos FALSE), /* PC relative offset? */
193 1.1 christos
194 1.1 christos /* Symbol Op Symbol relocation. */
195 1.1.1.7.4.1 christos HOWTO (R_MICROBLAZE_32_SYM_OP_SYM, /* Type. */
196 1.1.1.7.4.1 christos 0, /* Rightshift. */
197 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
198 1.1.1.7.4.1 christos 32, /* Bitsize. */
199 1.1.1.7.4.1 christos FALSE, /* PC_relative. */
200 1.1.1.7.4.1 christos 0, /* Bitpos. */
201 1.1.1.7.4.1 christos complain_overflow_bitfield, /* Complain on overflow. */
202 1.1.1.7.4.1 christos bfd_elf_generic_reloc,/* Special Function. */
203 1.1.1.7.4.1 christos "R_MICROBLAZE_32_SYM_OP_SYM", /* Name. */
204 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
205 1.1.1.7.4.1 christos 0, /* Source Mask. */
206 1.1.1.7.4.1 christos 0xffffffff, /* Dest Mask. */
207 1.1.1.7.4.1 christos FALSE), /* PC relative offset? */
208 1.1 christos
209 1.1 christos /* GNU extension to record C++ vtable hierarchy. */
210 1.1 christos HOWTO (R_MICROBLAZE_GNU_VTINHERIT, /* Type. */
211 1.1.1.7.4.1 christos 0, /* Rightshift. */
212 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
213 1.1.1.7.4.1 christos 0, /* Bitsize. */
214 1.1.1.7.4.1 christos FALSE, /* PC_relative. */
215 1.1.1.7.4.1 christos 0, /* Bitpos. */
216 1.1.1.7.4.1 christos complain_overflow_dont,/* Complain on overflow. */
217 1.1.1.7.4.1 christos NULL, /* Special Function. */
218 1.1.1.7.4.1 christos "R_MICROBLAZE_GNU_VTINHERIT", /* Name. */
219 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
220 1.1.1.7.4.1 christos 0, /* Source Mask. */
221 1.1.1.7.4.1 christos 0, /* Dest Mask. */
222 1.1.1.7.4.1 christos FALSE), /* PC relative offset? */
223 1.1 christos
224 1.1 christos /* GNU extension to record C++ vtable member usage. */
225 1.1 christos HOWTO (R_MICROBLAZE_GNU_VTENTRY, /* Type. */
226 1.1.1.7.4.1 christos 0, /* Rightshift. */
227 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
228 1.1.1.7.4.1 christos 0, /* Bitsize. */
229 1.1.1.7.4.1 christos FALSE, /* PC_relative. */
230 1.1.1.7.4.1 christos 0, /* Bitpos. */
231 1.1.1.7.4.1 christos complain_overflow_dont,/* Complain on overflow. */
232 1.1.1.7.4.1 christos _bfd_elf_rel_vtable_reloc_fn, /* Special Function. */
233 1.1.1.7.4.1 christos "R_MICROBLAZE_GNU_VTENTRY", /* Name. */
234 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
235 1.1.1.7.4.1 christos 0, /* Source Mask. */
236 1.1.1.7.4.1 christos 0, /* Dest Mask. */
237 1.1.1.7.4.1 christos FALSE), /* PC relative offset? */
238 1.1 christos
239 1.1 christos /* A 64 bit GOTPC relocation. Table-entry not really used. */
240 1.1.1.7.4.1 christos HOWTO (R_MICROBLAZE_GOTPC_64, /* Type. */
241 1.1.1.7.4.1 christos 0, /* Rightshift. */
242 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
243 1.1.1.7.4.1 christos 16, /* Bitsize. */
244 1.1.1.7.4.1 christos TRUE, /* PC_relative. */
245 1.1.1.7.4.1 christos 0, /* Bitpos. */
246 1.1.1.7.4.1 christos complain_overflow_dont, /* Complain on overflow. */
247 1.1.1.7.4.1 christos bfd_elf_generic_reloc, /* Special Function. */
248 1.1.1.7.4.1 christos "R_MICROBLAZE_GOTPC_64", /* Name. */
249 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
250 1.1.1.7.4.1 christos 0, /* Source Mask. */
251 1.1.1.7.4.1 christos 0x0000ffff, /* Dest Mask. */
252 1.1.1.7.4.1 christos TRUE), /* PC relative offset? */
253 1.1.1.7.4.1 christos
254 1.1.1.7.4.1 christos /* A 64 bit TEXTPCREL relocation. Table-entry not really used. */
255 1.1.1.7.4.1 christos HOWTO (R_MICROBLAZE_TEXTPCREL_64, /* Type. */
256 1.1.1.7.4.1 christos 0, /* Rightshift. */
257 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
258 1.1.1.7.4.1 christos 16, /* Bitsize. */
259 1.1.1.7.4.1 christos TRUE, /* PC_relative. */
260 1.1.1.7.4.1 christos 0, /* Bitpos. */
261 1.1.1.7.4.1 christos complain_overflow_dont, /* Complain on overflow. */
262 1.1.1.7.4.1 christos bfd_elf_generic_reloc, /* Special Function. */
263 1.1.1.7.4.1 christos "R_MICROBLAZE_TEXTPCREL_64", /* Name. */
264 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
265 1.1.1.7.4.1 christos 0, /* Source Mask. */
266 1.1.1.7.4.1 christos 0x0000ffff, /* Dest Mask. */
267 1.1.1.7.4.1 christos TRUE), /* PC relative offset? */
268 1.1 christos
269 1.1 christos /* A 64 bit GOT relocation. Table-entry not really used. */
270 1.1 christos HOWTO (R_MICROBLAZE_GOT_64, /* Type. */
271 1.1.1.7.4.1 christos 0, /* Rightshift. */
272 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
273 1.1.1.7.4.1 christos 16, /* Bitsize. */
274 1.1.1.7.4.1 christos FALSE, /* PC_relative. */
275 1.1.1.7.4.1 christos 0, /* Bitpos. */
276 1.1.1.7.4.1 christos complain_overflow_dont, /* Complain on overflow. */
277 1.1.1.7.4.1 christos bfd_elf_generic_reloc,/* Special Function. */
278 1.1.1.7.4.1 christos "R_MICROBLAZE_GOT_64",/* Name. */
279 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
280 1.1.1.7.4.1 christos 0, /* Source Mask. */
281 1.1.1.7.4.1 christos 0x0000ffff, /* Dest Mask. */
282 1.1.1.7.4.1 christos FALSE), /* PC relative offset? */
283 1.1.1.7.4.1 christos
284 1.1.1.7.4.1 christos /* A 64 bit TEXTREL relocation. Table-entry not really used. */
285 1.1.1.7.4.1 christos HOWTO (R_MICROBLAZE_TEXTREL_64, /* Type. */
286 1.1.1.7.4.1 christos 0, /* Rightshift. */
287 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
288 1.1.1.7.4.1 christos 16, /* Bitsize. */
289 1.1.1.7.4.1 christos FALSE, /* PC_relative. */
290 1.1.1.7.4.1 christos 0, /* Bitpos. */
291 1.1.1.7.4.1 christos complain_overflow_dont, /* Complain on overflow. */
292 1.1.1.7.4.1 christos bfd_elf_generic_reloc,/* Special Function. */
293 1.1.1.7.4.1 christos "R_MICROBLAZE_TEXTREL_64",/* Name. */
294 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
295 1.1.1.7.4.1 christos 0, /* Source Mask. */
296 1.1.1.7.4.1 christos 0x0000ffff, /* Dest Mask. */
297 1.1.1.7.4.1 christos FALSE), /* PC relative offset? */
298 1.1 christos
299 1.1 christos /* A 64 bit PLT relocation. Table-entry not really used. */
300 1.1 christos HOWTO (R_MICROBLAZE_PLT_64, /* Type. */
301 1.1.1.7.4.1 christos 0, /* Rightshift. */
302 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
303 1.1.1.7.4.1 christos 16, /* Bitsize. */
304 1.1.1.7.4.1 christos TRUE, /* PC_relative. */
305 1.1.1.7.4.1 christos 0, /* Bitpos. */
306 1.1.1.7.4.1 christos complain_overflow_dont, /* Complain on overflow. */
307 1.1.1.7.4.1 christos bfd_elf_generic_reloc,/* Special Function. */
308 1.1.1.7.4.1 christos "R_MICROBLAZE_PLT_64",/* Name. */
309 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
310 1.1.1.7.4.1 christos 0, /* Source Mask. */
311 1.1.1.7.4.1 christos 0x0000ffff, /* Dest Mask. */
312 1.1.1.7.4.1 christos TRUE), /* PC relative offset? */
313 1.1 christos
314 1.1 christos /* Table-entry not really used. */
315 1.1.1.7.4.1 christos HOWTO (R_MICROBLAZE_REL, /* Type. */
316 1.1.1.7.4.1 christos 0, /* Rightshift. */
317 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
318 1.1.1.7.4.1 christos 16, /* Bitsize. */
319 1.1.1.7.4.1 christos TRUE, /* PC_relative. */
320 1.1.1.7.4.1 christos 0, /* Bitpos. */
321 1.1.1.7.4.1 christos complain_overflow_dont, /* Complain on overflow. */
322 1.1.1.7.4.1 christos bfd_elf_generic_reloc,/* Special Function. */
323 1.1.1.7.4.1 christos "R_MICROBLAZE_REL", /* Name. */
324 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
325 1.1.1.7.4.1 christos 0, /* Source Mask. */
326 1.1.1.7.4.1 christos 0x0000ffff, /* Dest Mask. */
327 1.1.1.7.4.1 christos TRUE), /* PC relative offset? */
328 1.1 christos
329 1.1 christos /* Table-entry not really used. */
330 1.1 christos HOWTO (R_MICROBLAZE_JUMP_SLOT,/* Type. */
331 1.1.1.7.4.1 christos 0, /* Rightshift. */
332 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
333 1.1.1.7.4.1 christos 16, /* Bitsize. */
334 1.1.1.7.4.1 christos TRUE, /* PC_relative. */
335 1.1.1.7.4.1 christos 0, /* Bitpos. */
336 1.1.1.7.4.1 christos complain_overflow_dont, /* Complain on overflow. */
337 1.1.1.7.4.1 christos bfd_elf_generic_reloc,/* Special Function. */
338 1.1.1.7.4.1 christos "R_MICROBLAZE_JUMP_SLOT", /* Name. */
339 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
340 1.1.1.7.4.1 christos 0, /* Source Mask. */
341 1.1.1.7.4.1 christos 0x0000ffff, /* Dest Mask. */
342 1.1.1.7.4.1 christos TRUE), /* PC relative offset? */
343 1.1 christos
344 1.1 christos /* Table-entry not really used. */
345 1.1 christos HOWTO (R_MICROBLAZE_GLOB_DAT,/* Type. */
346 1.1.1.7.4.1 christos 0, /* Rightshift. */
347 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
348 1.1.1.7.4.1 christos 16, /* Bitsize. */
349 1.1.1.7.4.1 christos TRUE, /* PC_relative. */
350 1.1.1.7.4.1 christos 0, /* Bitpos. */
351 1.1.1.7.4.1 christos complain_overflow_dont, /* Complain on overflow. */
352 1.1.1.7.4.1 christos bfd_elf_generic_reloc,/* Special Function. */
353 1.1.1.7.4.1 christos "R_MICROBLAZE_GLOB_DAT", /* Name. */
354 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
355 1.1.1.7.4.1 christos 0, /* Source Mask. */
356 1.1.1.7.4.1 christos 0x0000ffff, /* Dest Mask. */
357 1.1.1.7.4.1 christos TRUE), /* PC relative offset? */
358 1.1 christos
359 1.1 christos /* A 64 bit GOT relative relocation. Table-entry not really used. */
360 1.1.1.7.4.1 christos HOWTO (R_MICROBLAZE_GOTOFF_64, /* Type. */
361 1.1.1.7.4.1 christos 0, /* Rightshift. */
362 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
363 1.1.1.7.4.1 christos 16, /* Bitsize. */
364 1.1.1.7.4.1 christos FALSE, /* PC_relative. */
365 1.1.1.7.4.1 christos 0, /* Bitpos. */
366 1.1.1.7.4.1 christos complain_overflow_dont, /* Complain on overflow. */
367 1.1.1.7.4.1 christos bfd_elf_generic_reloc,/* Special Function. */
368 1.1.1.7.4.1 christos "R_MICROBLAZE_GOTOFF_64", /* Name. */
369 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
370 1.1.1.7.4.1 christos 0, /* Source Mask. */
371 1.1.1.7.4.1 christos 0x0000ffff, /* Dest Mask. */
372 1.1.1.7.4.1 christos FALSE), /* PC relative offset? */
373 1.1 christos
374 1.1 christos /* A 32 bit GOT relative relocation. Table-entry not really used. */
375 1.1.1.7.4.1 christos HOWTO (R_MICROBLAZE_GOTOFF_32, /* Type. */
376 1.1.1.7.4.1 christos 0, /* Rightshift. */
377 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
378 1.1.1.7.4.1 christos 16, /* Bitsize. */
379 1.1.1.7.4.1 christos FALSE, /* PC_relative. */
380 1.1.1.7.4.1 christos 0, /* Bitpos. */
381 1.1.1.7.4.1 christos complain_overflow_dont, /* Complain on overflow. */
382 1.1.1.7.4.1 christos bfd_elf_generic_reloc, /* Special Function. */
383 1.1.1.7.4.1 christos "R_MICROBLAZE_GOTOFF_32", /* Name. */
384 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
385 1.1.1.7.4.1 christos 0, /* Source Mask. */
386 1.1.1.7.4.1 christos 0x0000ffff, /* Dest Mask. */
387 1.1.1.7.4.1 christos FALSE), /* PC relative offset? */
388 1.1 christos
389 1.1 christos /* COPY relocation. Table-entry not really used. */
390 1.1.1.7.4.1 christos HOWTO (R_MICROBLAZE_COPY, /* Type. */
391 1.1.1.7.4.1 christos 0, /* Rightshift. */
392 1.1.1.7.4.1 christos 2, /* Size (0 = byte, 1 = short, 2 = long). */
393 1.1.1.7.4.1 christos 16, /* Bitsize. */
394 1.1.1.7.4.1 christos FALSE, /* PC_relative. */
395 1.1.1.7.4.1 christos 0, /* Bitpos. */
396 1.1.1.7.4.1 christos complain_overflow_dont, /* Complain on overflow. */
397 1.1.1.7.4.1 christos bfd_elf_generic_reloc,/* Special Function. */
398 1.1.1.7.4.1 christos "R_MICROBLAZE_COPY", /* Name. */
399 1.1.1.7.4.1 christos FALSE, /* Partial Inplace. */
400 1.1.1.7.4.1 christos 0, /* Source Mask. */
401 1.1.1.7.4.1 christos 0x0000ffff, /* Dest Mask. */
402 1.1.1.7.4.1 christos FALSE), /* PC relative offset? */
403 1.1.1.2 christos
404 1.1.1.2 christos /* Marker relocs for TLS. */
405 1.1.1.2 christos HOWTO (R_MICROBLAZE_TLS,
406 1.1.1.2 christos 0, /* rightshift */
407 1.1.1.2 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
408 1.1.1.2 christos 32, /* bitsize */
409 1.1.1.2 christos FALSE, /* pc_relative */
410 1.1.1.2 christos 0, /* bitpos */
411 1.1.1.2 christos complain_overflow_dont, /* complain_on_overflow */
412 1.1.1.2 christos bfd_elf_generic_reloc, /* special_function */
413 1.1.1.2 christos "R_MICROBLAZE_TLS", /* name */
414 1.1.1.2 christos FALSE, /* partial_inplace */
415 1.1.1.2 christos 0, /* src_mask */
416 1.1.1.2 christos 0x0000ffff, /* dst_mask */
417 1.1.1.2 christos FALSE), /* pcrel_offset */
418 1.1.1.2 christos
419 1.1.1.2 christos HOWTO (R_MICROBLAZE_TLSGD,
420 1.1.1.2 christos 0, /* rightshift */
421 1.1.1.2 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
422 1.1.1.2 christos 32, /* bitsize */
423 1.1.1.2 christos FALSE, /* pc_relative */
424 1.1.1.2 christos 0, /* bitpos */
425 1.1.1.2 christos complain_overflow_dont, /* complain_on_overflow */
426 1.1.1.2 christos bfd_elf_generic_reloc, /* special_function */
427 1.1.1.2 christos "R_MICROBLAZE_TLSGD", /* name */
428 1.1.1.2 christos FALSE, /* partial_inplace */
429 1.1.1.2 christos 0, /* src_mask */
430 1.1.1.2 christos 0x0000ffff, /* dst_mask */
431 1.1.1.2 christos FALSE), /* pcrel_offset */
432 1.1.1.2 christos
433 1.1.1.2 christos HOWTO (R_MICROBLAZE_TLSLD,
434 1.1.1.2 christos 0, /* rightshift */
435 1.1.1.2 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
436 1.1.1.2 christos 32, /* bitsize */
437 1.1.1.2 christos FALSE, /* pc_relative */
438 1.1.1.2 christos 0, /* bitpos */
439 1.1.1.2 christos complain_overflow_dont, /* complain_on_overflow */
440 1.1.1.2 christos bfd_elf_generic_reloc, /* special_function */
441 1.1.1.2 christos "R_MICROBLAZE_TLSLD", /* name */
442 1.1.1.2 christos FALSE, /* partial_inplace */
443 1.1.1.2 christos 0, /* src_mask */
444 1.1.1.2 christos 0x0000ffff, /* dst_mask */
445 1.1.1.2 christos FALSE), /* pcrel_offset */
446 1.1.1.2 christos
447 1.1.1.2 christos /* Computes the load module index of the load module that contains the
448 1.1.1.2 christos definition of its TLS sym. */
449 1.1.1.2 christos HOWTO (R_MICROBLAZE_TLSDTPMOD32,
450 1.1.1.2 christos 0, /* rightshift */
451 1.1.1.2 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
452 1.1.1.2 christos 32, /* bitsize */
453 1.1.1.2 christos FALSE, /* pc_relative */
454 1.1.1.2 christos 0, /* bitpos */
455 1.1.1.2 christos complain_overflow_dont, /* complain_on_overflow */
456 1.1.1.2 christos bfd_elf_generic_reloc, /* special_function */
457 1.1.1.2 christos "R_MICROBLAZE_TLSDTPMOD32", /* name */
458 1.1.1.2 christos FALSE, /* partial_inplace */
459 1.1.1.2 christos 0, /* src_mask */
460 1.1.1.2 christos 0x0000ffff, /* dst_mask */
461 1.1.1.2 christos FALSE), /* pcrel_offset */
462 1.1.1.2 christos
463 1.1.1.2 christos /* Computes a dtv-relative displacement, the difference between the value
464 1.1.1.2 christos of sym+add and the base address of the thread-local storage block that
465 1.1.1.2 christos contains the definition of sym, minus 0x8000. Used for initializing GOT */
466 1.1.1.2 christos HOWTO (R_MICROBLAZE_TLSDTPREL32,
467 1.1.1.2 christos 0, /* rightshift */
468 1.1.1.2 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
469 1.1.1.2 christos 32, /* bitsize */
470 1.1.1.2 christos FALSE, /* pc_relative */
471 1.1.1.2 christos 0, /* bitpos */
472 1.1.1.2 christos complain_overflow_dont, /* complain_on_overflow */
473 1.1.1.2 christos bfd_elf_generic_reloc, /* special_function */
474 1.1.1.2 christos "R_MICROBLAZE_TLSDTPREL32", /* name */
475 1.1.1.2 christos FALSE, /* partial_inplace */
476 1.1.1.2 christos 0, /* src_mask */
477 1.1.1.2 christos 0x0000ffff, /* dst_mask */
478 1.1.1.2 christos FALSE), /* pcrel_offset */
479 1.1.1.2 christos
480 1.1.1.2 christos /* Computes a dtv-relative displacement, the difference between the value
481 1.1.1.2 christos of sym+add and the base address of the thread-local storage block that
482 1.1.1.2 christos contains the definition of sym, minus 0x8000. */
483 1.1.1.2 christos HOWTO (R_MICROBLAZE_TLSDTPREL64,
484 1.1.1.2 christos 0, /* rightshift */
485 1.1.1.2 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
486 1.1.1.2 christos 32, /* bitsize */
487 1.1.1.2 christos FALSE, /* pc_relative */
488 1.1.1.2 christos 0, /* bitpos */
489 1.1.1.2 christos complain_overflow_dont, /* complain_on_overflow */
490 1.1.1.2 christos bfd_elf_generic_reloc, /* special_function */
491 1.1.1.2 christos "R_MICROBLAZE_TLSDTPREL64", /* name */
492 1.1.1.2 christos FALSE, /* partial_inplace */
493 1.1.1.2 christos 0, /* src_mask */
494 1.1.1.2 christos 0x0000ffff, /* dst_mask */
495 1.1.1.2 christos FALSE), /* pcrel_offset */
496 1.1.1.2 christos
497 1.1.1.2 christos /* Computes a tp-relative displacement, the difference between the value of
498 1.1.1.2 christos sym+add and the value of the thread pointer (r13). */
499 1.1.1.2 christos HOWTO (R_MICROBLAZE_TLSGOTTPREL32,
500 1.1.1.2 christos 0, /* rightshift */
501 1.1.1.2 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
502 1.1.1.2 christos 32, /* bitsize */
503 1.1.1.2 christos FALSE, /* pc_relative */
504 1.1.1.2 christos 0, /* bitpos */
505 1.1.1.2 christos complain_overflow_dont, /* complain_on_overflow */
506 1.1.1.2 christos bfd_elf_generic_reloc, /* special_function */
507 1.1.1.2 christos "R_MICROBLAZE_TLSGOTTPREL32", /* name */
508 1.1.1.2 christos FALSE, /* partial_inplace */
509 1.1.1.2 christos 0, /* src_mask */
510 1.1.1.2 christos 0x0000ffff, /* dst_mask */
511 1.1.1.2 christos FALSE), /* pcrel_offset */
512 1.1.1.2 christos
513 1.1.1.2 christos /* Computes a tp-relative displacement, the difference between the value of
514 1.1.1.2 christos sym+add and the value of the thread pointer (r13). */
515 1.1.1.2 christos HOWTO (R_MICROBLAZE_TLSTPREL32,
516 1.1.1.2 christos 0, /* rightshift */
517 1.1.1.2 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
518 1.1.1.2 christos 32, /* bitsize */
519 1.1.1.2 christos FALSE, /* pc_relative */
520 1.1.1.2 christos 0, /* bitpos */
521 1.1.1.2 christos complain_overflow_dont, /* complain_on_overflow */
522 1.1.1.2 christos bfd_elf_generic_reloc, /* special_function */
523 1.1.1.2 christos "R_MICROBLAZE_TLSTPREL32", /* name */
524 1.1.1.2 christos FALSE, /* partial_inplace */
525 1.1.1.2 christos 0, /* src_mask */
526 1.1.1.2 christos 0x0000ffff, /* dst_mask */
527 1.1.1.2 christos FALSE), /* pcrel_offset */
528 1.1.1.2 christos
529 1.1 christos };
530 1.1 christos
531 1.1 christos #ifndef NUM_ELEM
532 1.1 christos #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
533 1.1 christos #endif
534 1.1 christos
535 1.1 christos /* Initialize the microblaze_elf_howto_table, so that linear accesses can be done. */
537 1.1 christos
538 1.1 christos static void
539 1.1 christos microblaze_elf_howto_init (void)
540 1.1 christos {
541 1.1 christos unsigned int i;
542 1.1 christos
543 1.1 christos for (i = NUM_ELEM (microblaze_elf_howto_raw); i--;)
544 1.1 christos {
545 1.1 christos unsigned int type;
546 1.1 christos
547 1.1 christos type = microblaze_elf_howto_raw[i].type;
548 1.1 christos
549 1.1 christos BFD_ASSERT (type < NUM_ELEM (microblaze_elf_howto_table));
550 1.1 christos
551 1.1 christos microblaze_elf_howto_table [type] = & microblaze_elf_howto_raw [i];
552 1.1 christos }
553 1.1 christos }
554 1.1 christos
555 1.1 christos static reloc_howto_type *
557 1.1 christos microblaze_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
558 1.1 christos bfd_reloc_code_real_type code)
559 1.1 christos {
560 1.1 christos enum elf_microblaze_reloc_type microblaze_reloc = R_MICROBLAZE_NONE;
561 1.1 christos
562 1.1 christos switch (code)
563 1.1 christos {
564 1.1 christos case BFD_RELOC_NONE:
565 1.1 christos microblaze_reloc = R_MICROBLAZE_NONE;
566 1.1 christos break;
567 1.1 christos case BFD_RELOC_MICROBLAZE_64_NONE:
568 1.1 christos microblaze_reloc = R_MICROBLAZE_64_NONE;
569 1.1 christos break;
570 1.1 christos case BFD_RELOC_32:
571 1.1 christos microblaze_reloc = R_MICROBLAZE_32;
572 1.1 christos break;
573 1.1 christos /* RVA is treated the same as 32 */
574 1.1 christos case BFD_RELOC_RVA:
575 1.1 christos microblaze_reloc = R_MICROBLAZE_32;
576 1.1 christos break;
577 1.1 christos case BFD_RELOC_32_PCREL:
578 1.1 christos microblaze_reloc = R_MICROBLAZE_32_PCREL;
579 1.1 christos break;
580 1.1 christos case BFD_RELOC_64_PCREL:
581 1.1 christos microblaze_reloc = R_MICROBLAZE_64_PCREL;
582 1.1 christos break;
583 1.1 christos case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
584 1.1 christos microblaze_reloc = R_MICROBLAZE_32_PCREL_LO;
585 1.1 christos break;
586 1.1 christos case BFD_RELOC_64:
587 1.1 christos microblaze_reloc = R_MICROBLAZE_64;
588 1.1 christos break;
589 1.1 christos case BFD_RELOC_MICROBLAZE_32_LO:
590 1.1 christos microblaze_reloc = R_MICROBLAZE_32_LO;
591 1.1 christos break;
592 1.1 christos case BFD_RELOC_MICROBLAZE_32_ROSDA:
593 1.1 christos microblaze_reloc = R_MICROBLAZE_SRO32;
594 1.1 christos break;
595 1.1 christos case BFD_RELOC_MICROBLAZE_32_RWSDA:
596 1.1 christos microblaze_reloc = R_MICROBLAZE_SRW32;
597 1.1 christos break;
598 1.1 christos case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
599 1.1 christos microblaze_reloc = R_MICROBLAZE_32_SYM_OP_SYM;
600 1.1 christos break;
601 1.1 christos case BFD_RELOC_VTABLE_INHERIT:
602 1.1 christos microblaze_reloc = R_MICROBLAZE_GNU_VTINHERIT;
603 1.1 christos break;
604 1.1 christos case BFD_RELOC_VTABLE_ENTRY:
605 1.1 christos microblaze_reloc = R_MICROBLAZE_GNU_VTENTRY;
606 1.1 christos break;
607 1.1 christos case BFD_RELOC_MICROBLAZE_64_GOTPC:
608 1.1 christos microblaze_reloc = R_MICROBLAZE_GOTPC_64;
609 1.1 christos break;
610 1.1 christos case BFD_RELOC_MICROBLAZE_64_GOT:
611 1.1.1.7.4.1 christos microblaze_reloc = R_MICROBLAZE_GOT_64;
612 1.1.1.7.4.1 christos break;
613 1.1.1.7.4.1 christos case BFD_RELOC_MICROBLAZE_64_TEXTPCREL:
614 1.1.1.7.4.1 christos microblaze_reloc = R_MICROBLAZE_TEXTPCREL_64;
615 1.1.1.7.4.1 christos break;
616 1.1.1.7.4.1 christos case BFD_RELOC_MICROBLAZE_64_TEXTREL:
617 1.1 christos microblaze_reloc = R_MICROBLAZE_TEXTREL_64;
618 1.1 christos break;
619 1.1 christos case BFD_RELOC_MICROBLAZE_64_PLT:
620 1.1 christos microblaze_reloc = R_MICROBLAZE_PLT_64;
621 1.1 christos break;
622 1.1 christos case BFD_RELOC_MICROBLAZE_64_GOTOFF:
623 1.1 christos microblaze_reloc = R_MICROBLAZE_GOTOFF_64;
624 1.1 christos break;
625 1.1 christos case BFD_RELOC_MICROBLAZE_32_GOTOFF:
626 1.1.1.2 christos microblaze_reloc = R_MICROBLAZE_GOTOFF_32;
627 1.1.1.2 christos break;
628 1.1.1.2 christos case BFD_RELOC_MICROBLAZE_64_TLSGD:
629 1.1.1.2 christos microblaze_reloc = R_MICROBLAZE_TLSGD;
630 1.1.1.2 christos break;
631 1.1.1.2 christos case BFD_RELOC_MICROBLAZE_64_TLSLD:
632 1.1.1.2 christos microblaze_reloc = R_MICROBLAZE_TLSLD;
633 1.1.1.2 christos break;
634 1.1.1.2 christos case BFD_RELOC_MICROBLAZE_32_TLSDTPREL:
635 1.1.1.2 christos microblaze_reloc = R_MICROBLAZE_TLSDTPREL32;
636 1.1.1.2 christos break;
637 1.1.1.2 christos case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
638 1.1.1.2 christos microblaze_reloc = R_MICROBLAZE_TLSDTPREL64;
639 1.1.1.2 christos break;
640 1.1.1.2 christos case BFD_RELOC_MICROBLAZE_32_TLSDTPMOD:
641 1.1.1.2 christos microblaze_reloc = R_MICROBLAZE_TLSDTPMOD32;
642 1.1.1.2 christos break;
643 1.1.1.2 christos case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL:
644 1.1.1.2 christos microblaze_reloc = R_MICROBLAZE_TLSGOTTPREL32;
645 1.1.1.2 christos break;
646 1.1.1.2 christos case BFD_RELOC_MICROBLAZE_64_TLSTPREL:
647 1.1 christos microblaze_reloc = R_MICROBLAZE_TLSTPREL32;
648 1.1 christos break;
649 1.1 christos case BFD_RELOC_MICROBLAZE_COPY:
650 1.1 christos microblaze_reloc = R_MICROBLAZE_COPY;
651 1.1 christos break;
652 1.1 christos default:
653 1.1 christos return (reloc_howto_type *) NULL;
654 1.1 christos }
655 1.1 christos
656 1.1 christos if (!microblaze_elf_howto_table [R_MICROBLAZE_32])
657 1.1 christos /* Initialize howto table if needed. */
658 1.1 christos microblaze_elf_howto_init ();
659 1.1 christos
660 1.1 christos return microblaze_elf_howto_table [(int) microblaze_reloc];
661 1.1 christos };
662 1.1 christos
663 1.1 christos static reloc_howto_type *
664 1.1 christos microblaze_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
665 1.1 christos const char *r_name)
666 1.1 christos {
667 1.1 christos unsigned int i;
668 1.1 christos
669 1.1 christos for (i = 0; i < NUM_ELEM (microblaze_elf_howto_raw); i++)
670 1.1 christos if (microblaze_elf_howto_raw[i].name != NULL
671 1.1 christos && strcasecmp (microblaze_elf_howto_raw[i].name, r_name) == 0)
672 1.1 christos return µblaze_elf_howto_raw[i];
673 1.1 christos
674 1.1 christos return NULL;
675 1.1 christos }
676 1.1 christos
677 1.1.1.7.4.1 christos /* Set the howto pointer for a RCE ELF reloc. */
678 1.1.1.7.4.1 christos
679 1.1 christos static bfd_boolean
680 1.1 christos microblaze_elf_info_to_howto (bfd * abfd,
681 1.1 christos arelent * cache_ptr,
682 1.1.1.5 christos Elf_Internal_Rela * dst)
683 1.1.1.5 christos {
684 1.1 christos unsigned int r_type;
685 1.1 christos
686 1.1 christos if (!microblaze_elf_howto_table [R_MICROBLAZE_32])
687 1.1 christos /* Initialize howto table if needed. */
688 1.1.1.5 christos microblaze_elf_howto_init ();
689 1.1.1.5 christos
690 1.1.1.5 christos r_type = ELF32_R_TYPE (dst->r_info);
691 1.1.1.7 christos if (r_type >= R_MICROBLAZE_max)
692 1.1.1.7.4.1 christos {
693 1.1.1.7 christos /* xgettext:c-format */
694 1.1.1.5 christos _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
695 1.1.1.7.4.1 christos abfd, r_type);
696 1.1.1.5 christos bfd_set_error (bfd_error_bad_value);
697 1.1 christos return FALSE;
698 1.1.1.5 christos }
699 1.1.1.7.4.1 christos
700 1.1 christos cache_ptr->howto = microblaze_elf_howto_table [r_type];
701 1.1 christos return TRUE;
702 1.1 christos }
703 1.1 christos
704 1.1 christos /* Microblaze ELF local labels start with 'L.' or '$L', not '.L'. */
705 1.1 christos
706 1.1 christos static bfd_boolean
707 1.1 christos microblaze_elf_is_local_label_name (bfd *abfd, const char *name)
708 1.1 christos {
709 1.1 christos if (name[0] == 'L' && name[1] == '.')
710 1.1 christos return TRUE;
711 1.1 christos
712 1.1 christos if (name[0] == '$' && name[1] == 'L')
713 1.1 christos return TRUE;
714 1.1 christos
715 1.1 christos /* With gcc, the labels go back to starting with '.', so we accept
716 1.1 christos the generic ELF local label syntax as well. */
717 1.1 christos return _bfd_elf_is_local_label_name (abfd, name);
718 1.1 christos }
719 1.1 christos
720 1.1 christos /* ELF linker hash entry. */
721 1.1 christos
722 1.1 christos struct elf32_mb_link_hash_entry
723 1.1 christos {
724 1.1 christos struct elf_link_hash_entry elf;
725 1.1.1.7.4.1 christos
726 1.1 christos /* Track dynamic relocs copied for this symbol. */
727 1.1.1.2 christos struct elf_dyn_relocs *dyn_relocs;
728 1.1.1.2 christos
729 1.1.1.2 christos /* TLS Reference Types for the symbol; Updated by check_relocs */
730 1.1.1.2 christos #define TLS_GD 1 /* GD reloc. */
731 1.1.1.2 christos #define TLS_LD 2 /* LD reloc. */
732 1.1.1.2 christos #define TLS_TPREL 4 /* TPREL reloc, => IE. */
733 1.1.1.2 christos #define TLS_DTPREL 8 /* DTPREL reloc, => LD. */
734 1.1.1.2 christos #define TLS_TLS 16 /* Any TLS reloc. */
735 1.1 christos unsigned char tls_mask;
736 1.1 christos
737 1.1.1.2 christos };
738 1.1.1.2 christos
739 1.1.1.2 christos #define IS_TLS_GD(x) (x == (TLS_TLS | TLS_GD))
740 1.1.1.2 christos #define IS_TLS_LD(x) (x == (TLS_TLS | TLS_LD))
741 1.1.1.2 christos #define IS_TLS_DTPREL(x) (x == (TLS_TLS | TLS_DTPREL))
742 1.1 christos #define IS_TLS_NONE(x) (x == 0)
743 1.1 christos
744 1.1 christos #define elf32_mb_hash_entry(ent) ((struct elf32_mb_link_hash_entry *)(ent))
745 1.1 christos
746 1.1 christos /* ELF linker hash table. */
747 1.1 christos
748 1.1 christos struct elf32_mb_link_hash_table
749 1.1 christos {
750 1.1 christos struct elf_link_hash_table elf;
751 1.1 christos
752 1.1.1.2 christos /* Small local sym to section mapping cache. */
753 1.1.1.2 christos struct sym_cache sym_sec;
754 1.1.1.2 christos
755 1.1.1.2 christos /* TLS Local Dynamic GOT Entry */
756 1.1.1.2 christos union {
757 1.1.1.2 christos bfd_signed_vma refcount;
758 1.1 christos bfd_vma offset;
759 1.1 christos } tlsld_got;
760 1.1.1.2 christos };
761 1.1.1.2 christos
762 1.1.1.2 christos /* Nonzero if this section has TLS related relocations. */
763 1.1 christos #define has_tls_reloc sec_flg0
764 1.1 christos
765 1.1 christos /* Get the ELF linker hash table from a link_info structure. */
766 1.1 christos
767 1.1 christos #define elf32_mb_hash_table(p) \
768 1.1 christos (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
769 1.1 christos == MICROBLAZE_ELF_DATA ? ((struct elf32_mb_link_hash_table *) ((p)->hash)) : NULL)
770 1.1 christos
771 1.1 christos /* Create an entry in a microblaze ELF linker hash table. */
772 1.1 christos
773 1.1 christos static struct bfd_hash_entry *
774 1.1 christos link_hash_newfunc (struct bfd_hash_entry *entry,
775 1.1 christos struct bfd_hash_table *table,
776 1.1 christos const char *string)
777 1.1 christos {
778 1.1 christos /* Allocate the structure if it has not already been allocated by a
779 1.1 christos subclass. */
780 1.1 christos if (entry == NULL)
781 1.1 christos {
782 1.1 christos entry = bfd_hash_allocate (table,
783 1.1 christos sizeof (struct elf32_mb_link_hash_entry));
784 1.1 christos if (entry == NULL)
785 1.1 christos return entry;
786 1.1 christos }
787 1.1 christos
788 1.1 christos /* Call the allocation method of the superclass. */
789 1.1 christos entry = _bfd_elf_link_hash_newfunc (entry, table, string);
790 1.1 christos if (entry != NULL)
791 1.1 christos {
792 1.1 christos struct elf32_mb_link_hash_entry *eh;
793 1.1 christos
794 1.1.1.2 christos eh = (struct elf32_mb_link_hash_entry *) entry;
795 1.1 christos eh->dyn_relocs = NULL;
796 1.1 christos eh->tls_mask = 0;
797 1.1 christos }
798 1.1 christos
799 1.1 christos return entry;
800 1.1 christos }
801 1.1 christos
802 1.1 christos /* Create a mb ELF linker hash table. */
803 1.1 christos
804 1.1 christos static struct bfd_link_hash_table *
805 1.1 christos microblaze_elf_link_hash_table_create (bfd *abfd)
806 1.1 christos {
807 1.1 christos struct elf32_mb_link_hash_table *ret;
808 1.1 christos bfd_size_type amt = sizeof (struct elf32_mb_link_hash_table);
809 1.1 christos
810 1.1 christos ret = (struct elf32_mb_link_hash_table *) bfd_zmalloc (amt);
811 1.1 christos if (ret == NULL)
812 1.1 christos return NULL;
813 1.1 christos
814 1.1 christos if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
815 1.1 christos sizeof (struct elf32_mb_link_hash_entry),
816 1.1 christos MICROBLAZE_ELF_DATA))
817 1.1 christos {
818 1.1 christos free (ret);
819 1.1 christos return NULL;
820 1.1 christos }
821 1.1 christos
822 1.1 christos return &ret->elf.root;
823 1.1 christos }
824 1.1 christos
825 1.1 christos /* Set the values of the small data pointers. */
827 1.1 christos
828 1.1 christos static void
829 1.1 christos microblaze_elf_final_sdp (struct bfd_link_info *info)
830 1.1 christos {
831 1.1 christos struct bfd_link_hash_entry *h;
832 1.1 christos
833 1.1 christos h = bfd_link_hash_lookup (info->hash, RO_SDA_ANCHOR_NAME, FALSE, FALSE, TRUE);
834 1.1.1.7.4.1 christos if (h != (struct bfd_link_hash_entry *) NULL
835 1.1.1.7.4.1 christos && h->type == bfd_link_hash_defined)
836 1.1 christos ro_small_data_pointer = (h->u.def.value
837 1.1 christos + h->u.def.section->output_section->vma
838 1.1 christos + h->u.def.section->output_offset);
839 1.1 christos
840 1.1 christos h = bfd_link_hash_lookup (info->hash, RW_SDA_ANCHOR_NAME, FALSE, FALSE, TRUE);
841 1.1.1.7.4.1 christos if (h != (struct bfd_link_hash_entry *) NULL
842 1.1.1.7.4.1 christos && h->type == bfd_link_hash_defined)
843 1.1 christos rw_small_data_pointer = (h->u.def.value
844 1.1 christos + h->u.def.section->output_section->vma
845 1.1.1.2 christos + h->u.def.section->output_offset);
846 1.1.1.2 christos }
847 1.1.1.2 christos
848 1.1.1.2 christos static bfd_vma
849 1.1.1.2 christos dtprel_base (struct bfd_link_info *info)
850 1.1.1.2 christos {
851 1.1.1.2 christos /* If tls_sec is NULL, we should have signalled an error already. */
852 1.1.1.2 christos if (elf_hash_table (info)->tls_sec == NULL)
853 1.1.1.2 christos return 0;
854 1.1.1.2 christos return elf_hash_table (info)->tls_sec->vma;
855 1.1.1.2 christos }
856 1.1.1.2 christos
857 1.1.1.2 christos /* The size of the thread control block. */
858 1.1.1.2 christos #define TCB_SIZE 8
859 1.1.1.2 christos
860 1.1.1.2 christos /* Output a simple dynamic relocation into SRELOC. */
861 1.1.1.2 christos
862 1.1.1.2 christos static void
863 1.1.1.2 christos microblaze_elf_output_dynamic_relocation (bfd *output_bfd,
864 1.1.1.2 christos asection *sreloc,
865 1.1.1.2 christos unsigned long reloc_index,
866 1.1.1.2 christos unsigned long indx,
867 1.1.1.2 christos int r_type,
868 1.1.1.2 christos bfd_vma offset,
869 1.1.1.2 christos bfd_vma addend)
870 1.1.1.2 christos {
871 1.1.1.2 christos
872 1.1.1.2 christos Elf_Internal_Rela rel;
873 1.1.1.2 christos
874 1.1.1.2 christos rel.r_info = ELF32_R_INFO (indx, r_type);
875 1.1.1.2 christos rel.r_offset = offset;
876 1.1.1.7.4.1 christos rel.r_addend = addend;
877 1.1.1.2 christos
878 1.1.1.2 christos bfd_elf32_swap_reloca_out (output_bfd, &rel,
879 1.1 christos (sreloc->contents + reloc_index * sizeof (Elf32_External_Rela)));
880 1.1 christos }
881 1.1 christos
882 1.1 christos /* This code is taken from elf32-m32r.c
883 1.1 christos There is some attempt to make this function usable for many architectures,
884 1.1 christos both USE_REL and USE_RELA ['twould be nice if such a critter existed],
885 1.1 christos if only to serve as a learning tool.
886 1.1 christos
887 1.1 christos The RELOCATE_SECTION function is called by the new ELF backend linker
888 1.1 christos to handle the relocations for a section.
889 1.1 christos
890 1.1 christos The relocs are always passed as Rela structures; if the section
891 1.1 christos actually uses Rel structures, the r_addend field will always be
892 1.1 christos zero.
893 1.1 christos
894 1.1 christos This function is responsible for adjust the section contents as
895 1.1 christos necessary, and (if using Rela relocs and generating a
896 1.1 christos relocatable output file) adjusting the reloc addend as
897 1.1 christos necessary.
898 1.1 christos
899 1.1 christos This function does not have to worry about setting the reloc
900 1.1 christos address or the reloc symbol index.
901 1.1 christos
902 1.1 christos LOCAL_SYMS is a pointer to the swapped in local symbols.
903 1.1 christos
904 1.1 christos LOCAL_SECTIONS is an array giving the section in the input file
905 1.1 christos corresponding to the st_shndx field of each local symbol.
906 1.1 christos
907 1.1 christos The global hash table entry for the global symbols can be found
908 1.1 christos via elf_sym_hashes (input_bfd).
909 1.1 christos
910 1.1 christos When generating relocatable output, this function must handle
911 1.1 christos STB_LOCAL/STT_SECTION symbols specially. The output symbol is
912 1.1 christos going to be the section symbol corresponding to the output
913 1.1 christos section, which means that the addend must be adjusted
914 1.1 christos accordingly. */
915 1.1.1.7.4.1 christos
916 1.1.1.7.4.1 christos static bfd_boolean
917 1.1.1.7.4.1 christos microblaze_elf_relocate_section (bfd *output_bfd,
918 1.1.1.7.4.1 christos struct bfd_link_info *info,
919 1.1.1.7.4.1 christos bfd *input_bfd,
920 1.1.1.7.4.1 christos asection *input_section,
921 1.1.1.7.4.1 christos bfd_byte *contents,
922 1.1 christos Elf_Internal_Rela *relocs,
923 1.1 christos Elf_Internal_Sym *local_syms,
924 1.1 christos asection **local_sections)
925 1.1 christos {
926 1.1 christos struct elf32_mb_link_hash_table *htab;
927 1.1.1.2 christos Elf_Internal_Shdr *symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
928 1.1 christos struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
929 1.1 christos Elf_Internal_Rela *rel, *relend;
930 1.1 christos int endian = (bfd_little_endian (output_bfd)) ? 0 : 2;
931 1.1 christos /* Assume success. */
932 1.1.1.2 christos bfd_boolean ret = TRUE;
933 1.1 christos asection *sreloc;
934 1.1 christos bfd_vma *local_got_offsets;
935 1.1 christos unsigned int tls_type;
936 1.1 christos
937 1.1 christos if (!microblaze_elf_howto_table[R_MICROBLAZE_max-1])
938 1.1 christos microblaze_elf_howto_init ();
939 1.1 christos
940 1.1 christos htab = elf32_mb_hash_table (info);
941 1.1 christos if (htab == NULL)
942 1.1 christos return FALSE;
943 1.1 christos
944 1.1 christos local_got_offsets = elf_local_got_offsets (input_bfd);
945 1.1 christos
946 1.1 christos sreloc = elf_section_data (input_section)->sreloc;
947 1.1 christos
948 1.1 christos rel = relocs;
949 1.1 christos relend = relocs + input_section->reloc_count;
950 1.1 christos for (; rel < relend; rel++)
951 1.1 christos {
952 1.1 christos int r_type;
953 1.1 christos reloc_howto_type *howto;
954 1.1 christos unsigned long r_symndx;
955 1.1 christos bfd_vma addend = rel->r_addend;
956 1.1 christos bfd_vma offset = rel->r_offset;
957 1.1 christos struct elf_link_hash_entry *h;
958 1.1 christos Elf_Internal_Sym *sym;
959 1.1 christos asection *sec;
960 1.1 christos const char *sym_name;
961 1.1 christos bfd_reloc_status_type r = bfd_reloc_ok;
962 1.1 christos const char *errmsg = NULL;
963 1.1 christos bfd_boolean unresolved_reloc = FALSE;
964 1.1.1.2 christos
965 1.1.1.2 christos h = NULL;
966 1.1 christos r_type = ELF32_R_TYPE (rel->r_info);
967 1.1 christos tls_type = 0;
968 1.1.1.7 christos
969 1.1.1.7.4.1 christos if (r_type < 0 || r_type >= (int) R_MICROBLAZE_max)
970 1.1.1.7 christos {
971 1.1 christos /* xgettext:c-format */
972 1.1 christos _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
973 1.1 christos input_bfd, (int) r_type);
974 1.1 christos bfd_set_error (bfd_error_bad_value);
975 1.1 christos ret = FALSE;
976 1.1 christos continue;
977 1.1 christos }
978 1.1 christos
979 1.1.1.6 christos howto = microblaze_elf_howto_table[r_type];
980 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info);
981 1.1 christos
982 1.1 christos if (bfd_link_relocatable (info))
983 1.1 christos {
984 1.1 christos /* This is a relocatable link. We don't have to change
985 1.1 christos anything, unless the reloc is against a section symbol,
986 1.1 christos in which case we have to adjust according to where the
987 1.1 christos section symbol winds up in the output section. */
988 1.1 christos sec = NULL;
989 1.1 christos if (r_symndx >= symtab_hdr->sh_info)
990 1.1 christos /* External symbol. */
991 1.1 christos continue;
992 1.1 christos
993 1.1 christos /* Local symbol. */
994 1.1 christos sym = local_syms + r_symndx;
995 1.1 christos sym_name = "<local symbol>";
996 1.1 christos /* STT_SECTION: symbol is associated with a section. */
997 1.1 christos if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
998 1.1 christos /* Symbol isn't associated with a section. Nothing to do. */
999 1.1 christos continue;
1000 1.1 christos
1001 1.1 christos sec = local_sections[r_symndx];
1002 1.1 christos addend += sec->output_offset + sym->st_value;
1003 1.1 christos #ifndef USE_REL
1004 1.1 christos /* This can't be done for USE_REL because it doesn't mean anything
1005 1.1 christos and elf_link_input_bfd asserts this stays zero. */
1006 1.1 christos /* rel->r_addend = addend; */
1007 1.1 christos #endif
1008 1.1 christos
1009 1.1 christos #ifndef USE_REL
1010 1.1 christos /* Addends are stored with relocs. We're done. */
1011 1.1 christos continue;
1012 1.1 christos #else /* USE_REL */
1013 1.1 christos /* If partial_inplace, we need to store any additional addend
1014 1.1 christos back in the section. */
1015 1.1 christos if (!howto->partial_inplace)
1016 1.1 christos continue;
1017 1.1 christos /* ??? Here is a nice place to call a special_function like handler. */
1018 1.1 christos r = _bfd_relocate_contents (howto, input_bfd, addend,
1019 1.1 christos contents + offset);
1020 1.1 christos #endif /* USE_REL */
1021 1.1 christos }
1022 1.1.1.7.4.1 christos else
1023 1.1 christos {
1024 1.1 christos bfd_vma relocation;
1025 1.1 christos bfd_boolean resolved_to_zero;
1026 1.1 christos
1027 1.1 christos /* This is a final link. */
1028 1.1 christos sym = NULL;
1029 1.1 christos sec = NULL;
1030 1.1 christos unresolved_reloc = FALSE;
1031 1.1 christos
1032 1.1 christos if (r_symndx < symtab_hdr->sh_info)
1033 1.1 christos {
1034 1.1 christos /* Local symbol. */
1035 1.1 christos sym = local_syms + r_symndx;
1036 1.1 christos sec = local_sections[r_symndx];
1037 1.1 christos if (sec == 0)
1038 1.1 christos continue;
1039 1.1 christos sym_name = "<local symbol>";
1040 1.1 christos relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
1041 1.1 christos /* r_addend may have changed if the reference section was
1042 1.1 christos a merge section. */
1043 1.1 christos addend = rel->r_addend;
1044 1.1 christos }
1045 1.1 christos else
1046 1.1.1.3 christos {
1047 1.1 christos /* External symbol. */
1048 1.1 christos bfd_boolean warned ATTRIBUTE_UNUSED;
1049 1.1 christos bfd_boolean ignored ATTRIBUTE_UNUSED;
1050 1.1 christos
1051 1.1.1.3 christos RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
1052 1.1 christos r_symndx, symtab_hdr, sym_hashes,
1053 1.1 christos h, sec, relocation,
1054 1.1 christos unresolved_reloc, warned, ignored);
1055 1.1 christos sym_name = h->root.root.string;
1056 1.1.1.2 christos }
1057 1.1 christos
1058 1.1 christos /* Sanity check the address. */
1059 1.1 christos if (offset > bfd_get_section_limit (input_bfd, input_section))
1060 1.1 christos {
1061 1.1 christos r = bfd_reloc_outofrange;
1062 1.1.1.7.4.1 christos goto check_reloc;
1063 1.1.1.7.4.1 christos }
1064 1.1.1.7.4.1 christos
1065 1.1 christos resolved_to_zero = (h != NULL
1066 1.1 christos && UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
1067 1.1 christos
1068 1.1 christos switch ((int) r_type)
1069 1.1 christos {
1070 1.1 christos case (int) R_MICROBLAZE_SRO32 :
1071 1.1 christos {
1072 1.1 christos const char *name;
1073 1.1 christos
1074 1.1.1.2 christos /* Only relocate if the symbol is defined. */
1075 1.1 christos if (sec)
1076 1.1 christos {
1077 1.1 christos name = bfd_get_section_name (sec->owner, sec);
1078 1.1 christos
1079 1.1 christos if (strcmp (name, ".sdata2") == 0
1080 1.1 christos || strcmp (name, ".sbss2") == 0)
1081 1.1 christos {
1082 1.1 christos if (ro_small_data_pointer == 0)
1083 1.1 christos microblaze_elf_final_sdp (info);
1084 1.1 christos if (ro_small_data_pointer == 0)
1085 1.1 christos {
1086 1.1 christos ret = FALSE;
1087 1.1 christos r = bfd_reloc_undefined;
1088 1.1 christos goto check_reloc;
1089 1.1 christos }
1090 1.1 christos
1091 1.1 christos /* At this point `relocation' contains the object's
1092 1.1 christos address. */
1093 1.1 christos relocation -= ro_small_data_pointer;
1094 1.1 christos /* Now it contains the offset from _SDA2_BASE_. */
1095 1.1 christos r = _bfd_final_link_relocate (howto, input_bfd,
1096 1.1 christos input_section,
1097 1.1 christos contents, offset,
1098 1.1 christos relocation, addend);
1099 1.1.1.7 christos }
1100 1.1.1.7 christos else
1101 1.1.1.7.4.1 christos {
1102 1.1.1.7.4.1 christos _bfd_error_handler
1103 1.1.1.7 christos /* xgettext:c-format */
1104 1.1.1.7 christos (_("%pB: the target (%s) of an %s relocation"
1105 1.1.1.7 christos " is in the wrong section (%pA)"),
1106 1.1.1.7 christos input_bfd,
1107 1.1 christos sym_name,
1108 1.1 christos microblaze_elf_howto_table[(int) r_type]->name,
1109 1.1 christos sec);
1110 1.1 christos /*bfd_set_error (bfd_error_bad_value); ??? why? */
1111 1.1 christos ret = FALSE;
1112 1.1 christos continue;
1113 1.1 christos }
1114 1.1 christos }
1115 1.1 christos }
1116 1.1 christos break;
1117 1.1 christos
1118 1.1 christos case (int) R_MICROBLAZE_SRW32 :
1119 1.1 christos {
1120 1.1 christos const char *name;
1121 1.1 christos
1122 1.1.1.2 christos /* Only relocate if the symbol is defined. */
1123 1.1 christos if (sec)
1124 1.1 christos {
1125 1.1 christos name = bfd_get_section_name (sec->owner, sec);
1126 1.1 christos
1127 1.1 christos if (strcmp (name, ".sdata") == 0
1128 1.1 christos || strcmp (name, ".sbss") == 0)
1129 1.1 christos {
1130 1.1 christos if (rw_small_data_pointer == 0)
1131 1.1 christos microblaze_elf_final_sdp (info);
1132 1.1 christos if (rw_small_data_pointer == 0)
1133 1.1 christos {
1134 1.1 christos ret = FALSE;
1135 1.1 christos r = bfd_reloc_undefined;
1136 1.1 christos goto check_reloc;
1137 1.1 christos }
1138 1.1 christos
1139 1.1 christos /* At this point `relocation' contains the object's
1140 1.1 christos address. */
1141 1.1 christos relocation -= rw_small_data_pointer;
1142 1.1 christos /* Now it contains the offset from _SDA_BASE_. */
1143 1.1 christos r = _bfd_final_link_relocate (howto, input_bfd,
1144 1.1 christos input_section,
1145 1.1 christos contents, offset,
1146 1.1 christos relocation, addend);
1147 1.1.1.7 christos }
1148 1.1.1.7 christos else
1149 1.1.1.7.4.1 christos {
1150 1.1.1.7.4.1 christos _bfd_error_handler
1151 1.1.1.7 christos /* xgettext:c-format */
1152 1.1.1.7 christos (_("%pB: the target (%s) of an %s relocation"
1153 1.1.1.7 christos " is in the wrong section (%pA)"),
1154 1.1.1.7 christos input_bfd,
1155 1.1 christos sym_name,
1156 1.1 christos microblaze_elf_howto_table[(int) r_type]->name,
1157 1.1 christos sec);
1158 1.1 christos /*bfd_set_error (bfd_error_bad_value); ??? why? */
1159 1.1 christos ret = FALSE;
1160 1.1 christos continue;
1161 1.1 christos }
1162 1.1 christos }
1163 1.1 christos }
1164 1.1 christos break;
1165 1.1 christos
1166 1.1 christos case (int) R_MICROBLAZE_32_SYM_OP_SYM:
1167 1.1.1.7 christos break; /* Do nothing. */
1168 1.1.1.7 christos
1169 1.1 christos case (int) R_MICROBLAZE_GOTPC_64:
1170 1.1 christos relocation = (htab->elf.sgotplt->output_section->vma
1171 1.1 christos + htab->elf.sgotplt->output_offset);
1172 1.1 christos relocation -= (input_section->output_section->vma
1173 1.1 christos + input_section->output_offset
1174 1.1.1.7.4.1 christos + offset + INST_WORD_SIZE);
1175 1.1 christos relocation += addend;
1176 1.1.1.7.4.1 christos bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
1177 1.1.1.7.4.1 christos contents + offset + endian);
1178 1.1.1.7.4.1 christos bfd_put_16 (input_bfd, relocation & 0xffff,
1179 1.1.1.7.4.1 christos contents + offset + endian + INST_WORD_SIZE);
1180 1.1.1.7.4.1 christos break;
1181 1.1.1.7.4.1 christos
1182 1.1.1.7.4.1 christos case (int) R_MICROBLAZE_TEXTPCREL_64:
1183 1.1.1.7.4.1 christos relocation = input_section->output_section->vma;
1184 1.1.1.7.4.1 christos relocation -= (input_section->output_section->vma
1185 1.1.1.7.4.1 christos + input_section->output_offset
1186 1.1.1.7.4.1 christos + offset + INST_WORD_SIZE);
1187 1.1.1.7.4.1 christos relocation += addend;
1188 1.1.1.7.4.1 christos bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
1189 1.1 christos contents + offset + endian);
1190 1.1 christos bfd_put_16 (input_bfd, relocation & 0xffff,
1191 1.1 christos contents + offset + endian + INST_WORD_SIZE);
1192 1.1 christos break;
1193 1.1 christos
1194 1.1.1.7 christos case (int) R_MICROBLAZE_PLT_64:
1195 1.1 christos {
1196 1.1 christos bfd_vma immediate;
1197 1.1.1.7 christos if (htab->elf.splt != NULL && h != NULL
1198 1.1.1.7 christos && h->plt.offset != (bfd_vma) -1)
1199 1.1 christos {
1200 1.1 christos relocation = (htab->elf.splt->output_section->vma
1201 1.1 christos + htab->elf.splt->output_offset
1202 1.1 christos + h->plt.offset);
1203 1.1 christos unresolved_reloc = FALSE;
1204 1.1 christos immediate = relocation - (input_section->output_section->vma
1205 1.1.1.7.4.1 christos + input_section->output_offset
1206 1.1 christos + offset + INST_WORD_SIZE);
1207 1.1.1.7.4.1 christos bfd_put_16 (input_bfd, (immediate >> 16) & 0xffff,
1208 1.1 christos contents + offset + endian);
1209 1.1 christos bfd_put_16 (input_bfd, immediate & 0xffff,
1210 1.1 christos contents + offset + endian + INST_WORD_SIZE);
1211 1.1 christos }
1212 1.1 christos else
1213 1.1 christos {
1214 1.1 christos relocation -= (input_section->output_section->vma
1215 1.1 christos + input_section->output_offset
1216 1.1.1.7.4.1 christos + offset + INST_WORD_SIZE);
1217 1.1 christos immediate = relocation;
1218 1.1.1.7.4.1 christos bfd_put_16 (input_bfd, (immediate >> 16) & 0xffff,
1219 1.1 christos contents + offset + endian);
1220 1.1 christos bfd_put_16 (input_bfd, immediate & 0xffff,
1221 1.1 christos contents + offset + endian + INST_WORD_SIZE);
1222 1.1 christos }
1223 1.1.1.2 christos break;
1224 1.1.1.2 christos }
1225 1.1.1.2 christos
1226 1.1.1.2 christos case (int) R_MICROBLAZE_TLSGD:
1227 1.1.1.2 christos tls_type = (TLS_TLS | TLS_GD);
1228 1.1.1.7 christos goto dogot;
1229 1.1.1.2 christos case (int) R_MICROBLAZE_TLSLD:
1230 1.1 christos tls_type = (TLS_TLS | TLS_LD);
1231 1.1 christos /* Fall through. */
1232 1.1.1.2 christos dogot:
1233 1.1.1.2 christos case (int) R_MICROBLAZE_GOT_64:
1234 1.1.1.2 christos {
1235 1.1.1.2 christos bfd_vma *offp;
1236 1.1.1.2 christos bfd_vma off, off2;
1237 1.1.1.2 christos unsigned long indx;
1238 1.1.1.7 christos bfd_vma static_value;
1239 1.1 christos
1240 1.1.1.2 christos bfd_boolean need_relocs = FALSE;
1241 1.1.1.2 christos if (htab->elf.sgot == NULL)
1242 1.1.1.2 christos abort ();
1243 1.1.1.2 christos
1244 1.1.1.2 christos indx = 0;
1245 1.1.1.2 christos offp = NULL;
1246 1.1.1.2 christos
1247 1.1.1.2 christos /* 1. Identify GOT Offset;
1248 1.1.1.2 christos 2. Compute Static Values
1249 1.1.1.2 christos 3. Process Module Id, Process Offset
1250 1.1.1.2 christos 4. Fixup Relocation with GOT offset value. */
1251 1.1.1.2 christos
1252 1.1.1.2 christos /* 1. Determine GOT Offset to use : TLS_LD, global, local */
1253 1.1.1.2 christos if (IS_TLS_LD (tls_type))
1254 1.1.1.7 christos offp = &htab->tlsld_got.offset;
1255 1.1.1.7 christos else if (h != NULL)
1256 1.1.1.7 christos {
1257 1.1.1.2 christos if (htab->elf.sgotplt != NULL
1258 1.1.1.7 christos && h->got.offset != (bfd_vma) -1)
1259 1.1.1.2 christos offp = &h->got.offset;
1260 1.1.1.2 christos else
1261 1.1 christos abort ();
1262 1.1 christos }
1263 1.1 christos else
1264 1.1.1.2 christos {
1265 1.1.1.2 christos if (local_got_offsets == NULL)
1266 1.1.1.2 christos abort ();
1267 1.1.1.2 christos offp = &local_got_offsets[r_symndx];
1268 1.1.1.2 christos }
1269 1.1.1.2 christos
1270 1.1.1.2 christos if (!offp)
1271 1.1.1.2 christos abort ();
1272 1.1.1.2 christos
1273 1.1.1.2 christos off = (*offp) & ~1;
1274 1.1.1.2 christos off2 = off;
1275 1.1.1.2 christos
1276 1.1.1.2 christos if (IS_TLS_LD(tls_type) || IS_TLS_GD(tls_type))
1277 1.1.1.2 christos off2 = off + 4;
1278 1.1.1.2 christos
1279 1.1.1.2 christos /* Symbol index to use for relocs */
1280 1.1.1.2 christos if (h != NULL)
1281 1.1.1.2 christos {
1282 1.1.1.6 christos bfd_boolean dyn =
1283 1.1.1.6 christos elf_hash_table (info)->dynamic_sections_created;
1284 1.1.1.6 christos
1285 1.1.1.6 christos if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
1286 1.1.1.6 christos bfd_link_pic (info),
1287 1.1.1.2 christos h)
1288 1.1.1.2 christos && (!bfd_link_pic (info)
1289 1.1.1.2 christos || !SYMBOL_REFERENCES_LOCAL (info, h)))
1290 1.1.1.2 christos indx = h->dynindx;
1291 1.1.1.6 christos }
1292 1.1.1.2 christos
1293 1.1.1.7.4.1 christos /* Need to generate relocs ? */
1294 1.1.1.7.4.1 christos if ((bfd_link_pic (info) || indx != 0)
1295 1.1.1.2 christos && (h == NULL
1296 1.1.1.2 christos || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
1297 1.1.1.2 christos && !resolved_to_zero)
1298 1.1.1.2 christos || h->root.type != bfd_link_hash_undefweak))
1299 1.1.1.2 christos need_relocs = TRUE;
1300 1.1.1.2 christos
1301 1.1.1.2 christos /* 2. Compute/Emit Static value of r-expression */
1302 1.1.1.2 christos static_value = relocation + addend;
1303 1.1.1.2 christos
1304 1.1.1.2 christos /* 3. Process module-id and offset */
1305 1.1.1.2 christos if (! ((*offp) & 1) )
1306 1.1.1.7 christos {
1307 1.1.1.7 christos bfd_vma got_offset;
1308 1.1.1.2 christos
1309 1.1 christos got_offset = (htab->elf.sgot->output_section->vma
1310 1.1.1.2 christos + htab->elf.sgot->output_offset
1311 1.1.1.2 christos + off);
1312 1.1.1.2 christos
1313 1.1.1.6 christos /* Process module-id */
1314 1.1.1.7 christos if (IS_TLS_LD(tls_type))
1315 1.1.1.7 christos {
1316 1.1.1.2 christos if (! bfd_link_pic (info))
1317 1.1.1.7 christos bfd_put_32 (output_bfd, 1,
1318 1.1.1.7 christos htab->elf.sgot->contents + off);
1319 1.1.1.7 christos else
1320 1.1.1.7 christos microblaze_elf_output_dynamic_relocation
1321 1.1.1.7 christos (output_bfd,
1322 1.1.1.7 christos htab->elf.srelgot,
1323 1.1 christos htab->elf.srelgot->reloc_count++,
1324 1.1.1.2 christos /* symindex= */ 0, R_MICROBLAZE_TLSDTPMOD32,
1325 1.1.1.2 christos got_offset, 0);
1326 1.1.1.7.4.1 christos }
1327 1.1.1.7 christos else if (IS_TLS_GD(tls_type))
1328 1.1.1.7 christos {
1329 1.1.1.7.4.1 christos if (! need_relocs)
1330 1.1.1.7 christos bfd_put_32 (output_bfd, 1,
1331 1.1.1.7 christos htab->elf.sgot->contents + off);
1332 1.1.1.7 christos else
1333 1.1.1.7 christos microblaze_elf_output_dynamic_relocation
1334 1.1.1.7 christos (output_bfd,
1335 1.1.1.7 christos htab->elf.srelgot,
1336 1.1.1.2 christos htab->elf.srelgot->reloc_count++,
1337 1.1.1.2 christos /* symindex= */ indx, R_MICROBLAZE_TLSDTPMOD32,
1338 1.1.1.2 christos got_offset, indx ? 0 : static_value);
1339 1.1.1.7 christos }
1340 1.1.1.2 christos
1341 1.1.1.2 christos /* Process Offset */
1342 1.1.1.7 christos if (htab->elf.srelgot == NULL)
1343 1.1.1.7 christos abort ();
1344 1.1.1.2 christos
1345 1.1.1.2 christos got_offset = (htab->elf.sgot->output_section->vma
1346 1.1.1.2 christos + htab->elf.sgot->output_offset
1347 1.1.1.7.4.1 christos + off2);
1348 1.1.1.7.4.1 christos if (IS_TLS_LD(tls_type))
1349 1.1.1.7.4.1 christos {
1350 1.1.1.7 christos /* For LD, offset should be 0 */
1351 1.1.1.2 christos *offp |= 1;
1352 1.1.1.2 christos bfd_put_32 (output_bfd, 0,
1353 1.1 christos htab->elf.sgot->contents + off2);
1354 1.1.1.7.4.1 christos }
1355 1.1.1.7.4.1 christos else if (IS_TLS_GD(tls_type))
1356 1.1.1.7.4.1 christos {
1357 1.1.1.7 christos *offp |= 1;
1358 1.1.1.7 christos static_value -= dtprel_base(info);
1359 1.1.1.7 christos if (need_relocs)
1360 1.1.1.7 christos microblaze_elf_output_dynamic_relocation
1361 1.1.1.7 christos (output_bfd,
1362 1.1.1.7 christos htab->elf.srelgot,
1363 1.1.1.7.4.1 christos htab->elf.srelgot->reloc_count++,
1364 1.1.1.7 christos /* symindex= */ indx, R_MICROBLAZE_TLSDTPREL32,
1365 1.1.1.7 christos got_offset, indx ? 0 : static_value);
1366 1.1 christos else
1367 1.1 christos bfd_put_32 (output_bfd, static_value,
1368 1.1.1.2 christos htab->elf.sgot->contents + off2);
1369 1.1.1.7 christos }
1370 1.1.1.7 christos else
1371 1.1.1.2 christos {
1372 1.1.1.7 christos bfd_put_32 (output_bfd, static_value,
1373 1.1.1.7 christos htab->elf.sgot->contents + off2);
1374 1.1.1.7 christos
1375 1.1.1.7 christos /* Relocs for dyn symbols generated by
1376 1.1.1.7 christos finish_dynamic_symbols */
1377 1.1.1.7 christos if (bfd_link_pic (info) && h == NULL)
1378 1.1.1.7 christos {
1379 1.1.1.7 christos *offp |= 1;
1380 1.1.1.7 christos microblaze_elf_output_dynamic_relocation
1381 1.1.1.7 christos (output_bfd,
1382 1.1.1.7 christos htab->elf.srelgot,
1383 1.1.1.7 christos htab->elf.srelgot->reloc_count++,
1384 1.1.1.2 christos /* symindex= */ indx, R_MICROBLAZE_REL,
1385 1.1 christos got_offset, static_value);
1386 1.1.1.2 christos }
1387 1.1.1.2 christos }
1388 1.1.1.2 christos }
1389 1.1.1.2 christos
1390 1.1.1.7 christos /* 4. Fixup Relocation with GOT offset value
1391 1.1.1.7 christos Compute relative address of GOT entry for applying
1392 1.1.1.2 christos the current relocation */
1393 1.1.1.7 christos relocation = htab->elf.sgot->output_section->vma
1394 1.1.1.7 christos + htab->elf.sgot->output_offset
1395 1.1.1.2 christos + off
1396 1.1.1.2 christos - htab->elf.sgotplt->output_section->vma
1397 1.1 christos - htab->elf.sgotplt->output_offset;
1398 1.1.1.7.4.1 christos
1399 1.1 christos /* Apply Current Relocation */
1400 1.1.1.7.4.1 christos bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
1401 1.1.1.2 christos contents + offset + endian);
1402 1.1.1.2 christos bfd_put_16 (input_bfd, relocation & 0xffff,
1403 1.1 christos contents + offset + endian + INST_WORD_SIZE);
1404 1.1 christos
1405 1.1 christos unresolved_reloc = FALSE;
1406 1.1 christos break;
1407 1.1 christos }
1408 1.1 christos
1409 1.1 christos case (int) R_MICROBLAZE_GOTOFF_64:
1410 1.1 christos {
1411 1.1.1.7 christos bfd_vma immediate;
1412 1.1.1.7 christos unsigned short lo, high;
1413 1.1 christos relocation += addend;
1414 1.1 christos relocation -= (htab->elf.sgotplt->output_section->vma
1415 1.1 christos + htab->elf.sgotplt->output_offset);
1416 1.1 christos /* Write this value into correct location. */
1417 1.1.1.2 christos immediate = relocation;
1418 1.1.1.7 christos lo = immediate & 0x0000ffff;
1419 1.1.1.7 christos high = (immediate >> 16) & 0x0000ffff;
1420 1.1 christos bfd_put_16 (input_bfd, high, contents + offset + endian);
1421 1.1 christos bfd_put_16 (input_bfd, lo,
1422 1.1 christos contents + offset + INST_WORD_SIZE + endian);
1423 1.1 christos break;
1424 1.1 christos }
1425 1.1 christos
1426 1.1.1.7 christos case (int) R_MICROBLAZE_GOTOFF_32:
1427 1.1.1.7 christos {
1428 1.1 christos relocation += addend;
1429 1.1 christos relocation -= (htab->elf.sgotplt->output_section->vma
1430 1.1 christos + htab->elf.sgotplt->output_offset);
1431 1.1 christos /* Write this value into correct location. */
1432 1.1 christos bfd_put_32 (input_bfd, relocation, contents + offset);
1433 1.1.1.2 christos break;
1434 1.1.1.2 christos }
1435 1.1.1.2 christos
1436 1.1.1.2 christos case (int) R_MICROBLAZE_TLSDTPREL64:
1437 1.1.1.2 christos relocation += addend;
1438 1.1.1.2 christos relocation -= dtprel_base(info);
1439 1.1.1.2 christos bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
1440 1.1.1.2 christos contents + offset + 2);
1441 1.1.1.7.4.1 christos bfd_put_16 (input_bfd, relocation & 0xffff,
1442 1.1.1.7.4.1 christos contents + offset + 2 + INST_WORD_SIZE);
1443 1.1 christos break;
1444 1.1 christos case (int) R_MICROBLAZE_TEXTREL_64:
1445 1.1 christos case (int) R_MICROBLAZE_TEXTREL_32_LO:
1446 1.1 christos case (int) R_MICROBLAZE_64_PCREL :
1447 1.1 christos case (int) R_MICROBLAZE_64:
1448 1.1 christos case (int) R_MICROBLAZE_32:
1449 1.1 christos {
1450 1.1 christos /* r_symndx will be STN_UNDEF (zero) only for relocs against symbols
1451 1.1 christos from removed linkonce sections, or sections discarded by
1452 1.1 christos a linker script. */
1453 1.1 christos if (r_symndx == STN_UNDEF || (input_section->flags & SEC_ALLOC) == 0)
1454 1.1 christos {
1455 1.1 christos relocation += addend;
1456 1.1 christos if (r_type == R_MICROBLAZE_32)
1457 1.1 christos bfd_put_32 (input_bfd, relocation, contents + offset);
1458 1.1 christos else
1459 1.1 christos {
1460 1.1 christos if (r_type == R_MICROBLAZE_64_PCREL)
1461 1.1.1.7.4.1 christos relocation -= (input_section->output_section->vma
1462 1.1.1.7.4.1 christos + input_section->output_offset
1463 1.1.1.7.4.1 christos + offset + INST_WORD_SIZE);
1464 1.1.1.7.4.1 christos else if (r_type == R_MICROBLAZE_TEXTREL_64
1465 1.1.1.7.4.1 christos || r_type == R_MICROBLAZE_TEXTREL_32_LO)
1466 1.1.1.7.4.1 christos relocation -= input_section->output_section->vma;
1467 1.1.1.7.4.1 christos
1468 1.1.1.7.4.1 christos if (r_type == R_MICROBLAZE_TEXTREL_32_LO)
1469 1.1.1.7.4.1 christos bfd_put_16 (input_bfd, relocation & 0xffff,
1470 1.1.1.7.4.1 christos contents + offset + endian);
1471 1.1.1.7.4.1 christos
1472 1.1.1.7.4.1 christos else
1473 1.1.1.7.4.1 christos {
1474 1.1.1.7.4.1 christos bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
1475 1.1 christos contents + offset + endian);
1476 1.1.1.7.4.1 christos bfd_put_16 (input_bfd, relocation & 0xffff,
1477 1.1 christos contents + offset + endian + INST_WORD_SIZE);
1478 1.1 christos }
1479 1.1 christos }
1480 1.1.1.6 christos break;
1481 1.1 christos }
1482 1.1.1.7.4.1 christos
1483 1.1.1.7.4.1 christos if ((bfd_link_pic (info)
1484 1.1 christos && (h == NULL
1485 1.1 christos || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
1486 1.1 christos && !resolved_to_zero)
1487 1.1 christos || h->root.type != bfd_link_hash_undefweak)
1488 1.1 christos && (!howto->pc_relative
1489 1.1 christos || (h != NULL
1490 1.1.1.6 christos && h->dynindx != -1
1491 1.1 christos && (!info->symbolic
1492 1.1 christos || !h->def_regular))))
1493 1.1 christos || (!bfd_link_pic (info)
1494 1.1 christos && h != NULL
1495 1.1 christos && h->dynindx != -1
1496 1.1 christos && !h->non_got_ref
1497 1.1 christos && ((h->def_dynamic
1498 1.1 christos && !h->def_regular)
1499 1.1 christos || h->root.type == bfd_link_hash_undefweak
1500 1.1 christos || h->root.type == bfd_link_hash_undefined)))
1501 1.1 christos {
1502 1.1 christos Elf_Internal_Rela outrel;
1503 1.1 christos bfd_byte *loc;
1504 1.1 christos bfd_boolean skip;
1505 1.1 christos
1506 1.1 christos /* When generating a shared object, these relocations
1507 1.1 christos are copied into the output file to be resolved at run
1508 1.1 christos time. */
1509 1.1 christos
1510 1.1 christos BFD_ASSERT (sreloc != NULL);
1511 1.1 christos
1512 1.1 christos skip = FALSE;
1513 1.1 christos
1514 1.1 christos outrel.r_offset =
1515 1.1 christos _bfd_elf_section_offset (output_bfd, info, input_section,
1516 1.1 christos rel->r_offset);
1517 1.1 christos if (outrel.r_offset == (bfd_vma) -1)
1518 1.1 christos skip = TRUE;
1519 1.1 christos else if (outrel.r_offset == (bfd_vma) -2)
1520 1.1 christos skip = TRUE;
1521 1.1 christos outrel.r_offset += (input_section->output_section->vma
1522 1.1 christos + input_section->output_offset);
1523 1.1 christos
1524 1.1 christos if (skip)
1525 1.1 christos memset (&outrel, 0, sizeof outrel);
1526 1.1 christos /* h->dynindx may be -1 if the symbol was marked to
1527 1.1 christos become local. */
1528 1.1 christos else if (h != NULL
1529 1.1 christos && ((! info->symbolic && h->dynindx != -1)
1530 1.1 christos || !h->def_regular))
1531 1.1 christos {
1532 1.1 christos BFD_ASSERT (h->dynindx != -1);
1533 1.1 christos outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
1534 1.1 christos outrel.r_addend = addend;
1535 1.1 christos }
1536 1.1 christos else
1537 1.1 christos {
1538 1.1 christos if (r_type == R_MICROBLAZE_32)
1539 1.1 christos {
1540 1.1 christos outrel.r_info = ELF32_R_INFO (0, R_MICROBLAZE_REL);
1541 1.1 christos outrel.r_addend = relocation + addend;
1542 1.1 christos }
1543 1.1.1.7 christos else
1544 1.1.1.7.4.1 christos {
1545 1.1 christos BFD_FAIL ();
1546 1.1 christos _bfd_error_handler
1547 1.1 christos (_("%pB: probably compiled without -fPIC?"),
1548 1.1 christos input_bfd);
1549 1.1 christos bfd_set_error (bfd_error_bad_value);
1550 1.1 christos return FALSE;
1551 1.1 christos }
1552 1.1 christos }
1553 1.1 christos
1554 1.1 christos loc = sreloc->contents;
1555 1.1 christos loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela);
1556 1.1 christos bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
1557 1.1 christos break;
1558 1.1 christos }
1559 1.1 christos else
1560 1.1 christos {
1561 1.1 christos relocation += addend;
1562 1.1 christos if (r_type == R_MICROBLAZE_32)
1563 1.1 christos bfd_put_32 (input_bfd, relocation, contents + offset);
1564 1.1 christos else
1565 1.1 christos {
1566 1.1 christos if (r_type == R_MICROBLAZE_64_PCREL)
1567 1.1.1.7.4.1 christos relocation -= (input_section->output_section->vma
1568 1.1.1.7.4.1 christos + input_section->output_offset
1569 1.1.1.7.4.1 christos + offset + INST_WORD_SIZE);
1570 1.1.1.7.4.1 christos else if (r_type == R_MICROBLAZE_TEXTREL_64
1571 1.1.1.7.4.1 christos || r_type == R_MICROBLAZE_TEXTREL_32_LO)
1572 1.1.1.7.4.1 christos relocation -= input_section->output_section->vma;
1573 1.1.1.7.4.1 christos
1574 1.1.1.7.4.1 christos if (r_type == R_MICROBLAZE_TEXTREL_32_LO)
1575 1.1.1.7.4.1 christos {
1576 1.1.1.7.4.1 christos bfd_put_16 (input_bfd, relocation & 0xffff,
1577 1.1.1.7.4.1 christos contents + offset + endian);
1578 1.1.1.7.4.1 christos }
1579 1.1.1.7.4.1 christos else
1580 1.1.1.7.4.1 christos {
1581 1.1.1.7.4.1 christos bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
1582 1.1.1.7.4.1 christos contents + offset + endian);
1583 1.1.1.7.4.1 christos bfd_put_16 (input_bfd, relocation & 0xffff,
1584 1.1.1.7.4.1 christos contents + offset + endian
1585 1.1 christos + INST_WORD_SIZE);
1586 1.1 christos }
1587 1.1 christos }
1588 1.1 christos break;
1589 1.1 christos }
1590 1.1 christos }
1591 1.1 christos
1592 1.1 christos default :
1593 1.1 christos r = _bfd_final_link_relocate (howto, input_bfd, input_section,
1594 1.1 christos contents, offset,
1595 1.1 christos relocation, addend);
1596 1.1 christos break;
1597 1.1 christos }
1598 1.1 christos }
1599 1.1 christos
1600 1.1 christos check_reloc:
1601 1.1 christos
1602 1.1 christos if (r != bfd_reloc_ok)
1603 1.1 christos {
1604 1.1 christos /* FIXME: This should be generic enough to go in a utility. */
1605 1.1 christos const char *name;
1606 1.1 christos
1607 1.1 christos if (h != NULL)
1608 1.1 christos name = h->root.root.string;
1609 1.1 christos else
1610 1.1 christos {
1611 1.1 christos name = (bfd_elf_string_from_elf_section
1612 1.1 christos (input_bfd, symtab_hdr->sh_link, sym->st_name));
1613 1.1 christos if (name == NULL || *name == '\0')
1614 1.1 christos name = bfd_section_name (input_bfd, sec);
1615 1.1 christos }
1616 1.1 christos
1617 1.1 christos if (errmsg != NULL)
1618 1.1 christos goto common_error;
1619 1.1 christos
1620 1.1.1.6 christos switch (r)
1621 1.1.1.6 christos {
1622 1.1.1.6 christos case bfd_reloc_overflow:
1623 1.1 christos (*info->callbacks->reloc_overflow)
1624 1.1 christos (info, (h ? &h->root : NULL), name, howto->name,
1625 1.1 christos (bfd_vma) 0, input_bfd, input_section, offset);
1626 1.1.1.6 christos break;
1627 1.1.1.6 christos
1628 1.1 christos case bfd_reloc_undefined:
1629 1.1 christos (*info->callbacks->undefined_symbol)
1630 1.1 christos (info, name, input_bfd, input_section, offset, TRUE);
1631 1.1 christos break;
1632 1.1 christos
1633 1.1 christos case bfd_reloc_outofrange:
1634 1.1 christos errmsg = _("internal error: out of range error");
1635 1.1 christos goto common_error;
1636 1.1 christos
1637 1.1 christos case bfd_reloc_notsupported:
1638 1.1 christos errmsg = _("internal error: unsupported relocation error");
1639 1.1 christos goto common_error;
1640 1.1 christos
1641 1.1 christos case bfd_reloc_dangerous:
1642 1.1 christos errmsg = _("internal error: dangerous error");
1643 1.1 christos goto common_error;
1644 1.1 christos
1645 1.1 christos default:
1646 1.1.1.6 christos errmsg = _("internal error: unknown error");
1647 1.1.1.6 christos /* Fall through. */
1648 1.1 christos common_error:
1649 1.1 christos (*info->callbacks->warning) (info, errmsg, name, input_bfd,
1650 1.1 christos input_section, offset);
1651 1.1 christos break;
1652 1.1 christos }
1653 1.1 christos }
1654 1.1 christos }
1655 1.1 christos
1656 1.1 christos return ret;
1657 1.1 christos }
1658 1.1 christos
1659 1.1.1.2 christos /* Calculate fixup value for reference. */
1661 1.1.1.2 christos
1662 1.1 christos static int
1663 1.1 christos calc_fixup (bfd_vma start, bfd_vma size, asection *sec)
1664 1.1 christos {
1665 1.1 christos bfd_vma end = start + size;
1666 1.1 christos int i, fixup = 0;
1667 1.1 christos
1668 1.1 christos if (sec == NULL || sec->relax == NULL)
1669 1.1 christos return 0;
1670 1.1.1.2 christos
1671 1.1.1.7.4.1 christos /* Look for addr in relax table, total fixup value. */
1672 1.1.1.2 christos for (i = 0; i < sec->relax_count; i++)
1673 1.1.1.7.4.1 christos {
1674 1.1 christos if (end <= sec->relax[i].addr)
1675 1.1 christos break;
1676 1.1 christos if ((end != start) && (start > sec->relax[i].addr))
1677 1.1 christos continue;
1678 1.1 christos fixup += sec->relax[i].size;
1679 1.1.1.2 christos }
1680 1.1.1.2 christos return fixup;
1681 1.1.1.2 christos }
1682 1.1.1.2 christos
1683 1.1.1.2 christos /* Read-modify-write into the bfd, an immediate value into appropriate fields of
1684 1.1.1.2 christos a 32-bit instruction. */
1685 1.1.1.2 christos static void
1686 1.1.1.2 christos microblaze_bfd_write_imm_value_32 (bfd *abfd, bfd_byte *bfd_addr, bfd_vma val)
1687 1.1.1.2 christos {
1688 1.1.1.2 christos unsigned long instr = bfd_get_32 (abfd, bfd_addr);
1689 1.1.1.2 christos instr &= ~0x0000ffff;
1690 1.1.1.2 christos instr |= (val & 0x0000ffff);
1691 1.1.1.2 christos bfd_put_32 (abfd, instr, bfd_addr);
1692 1.1.1.2 christos }
1693 1.1.1.2 christos
1694 1.1.1.2 christos /* Read-modify-write into the bfd, an immediate value into appropriate fields of
1695 1.1.1.2 christos two consecutive 32-bit instructions. */
1696 1.1.1.2 christos static void
1697 1.1.1.2 christos microblaze_bfd_write_imm_value_64 (bfd *abfd, bfd_byte *bfd_addr, bfd_vma val)
1698 1.1.1.2 christos {
1699 1.1.1.2 christos unsigned long instr_hi;
1700 1.1.1.2 christos unsigned long instr_lo;
1701 1.1.1.2 christos
1702 1.1.1.2 christos instr_hi = bfd_get_32 (abfd, bfd_addr);
1703 1.1.1.2 christos instr_hi &= ~0x0000ffff;
1704 1.1.1.2 christos instr_hi |= ((val >> 16) & 0x0000ffff);
1705 1.1.1.2 christos bfd_put_32 (abfd, instr_hi, bfd_addr);
1706 1.1.1.2 christos
1707 1.1.1.2 christos instr_lo = bfd_get_32 (abfd, bfd_addr + INST_WORD_SIZE);
1708 1.1.1.2 christos instr_lo &= ~0x0000ffff;
1709 1.1 christos instr_lo |= (val & 0x0000ffff);
1710 1.1 christos bfd_put_32 (abfd, instr_lo, bfd_addr + INST_WORD_SIZE);
1711 1.1 christos }
1712 1.1 christos
1713 1.1 christos static bfd_boolean
1714 1.1 christos microblaze_elf_relax_section (bfd *abfd,
1715 1.1 christos asection *sec,
1716 1.1 christos struct bfd_link_info *link_info,
1717 1.1 christos bfd_boolean *again)
1718 1.1 christos {
1719 1.1 christos Elf_Internal_Shdr *symtab_hdr;
1720 1.1 christos Elf_Internal_Rela *internal_relocs;
1721 1.1 christos Elf_Internal_Rela *free_relocs = NULL;
1722 1.1 christos Elf_Internal_Rela *irel, *irelend;
1723 1.1 christos bfd_byte *contents = NULL;
1724 1.1 christos bfd_byte *free_contents = NULL;
1725 1.1 christos int rel_count;
1726 1.1 christos unsigned int shndx;
1727 1.1 christos int i, sym_index;
1728 1.1 christos asection *o;
1729 1.1 christos struct elf_link_hash_entry *sym_hash;
1730 1.1 christos Elf_Internal_Sym *isymbuf, *isymend;
1731 1.1 christos Elf_Internal_Sym *isym;
1732 1.1 christos int symcount;
1733 1.1 christos int offset;
1734 1.1 christos bfd_vma src, dest;
1735 1.1 christos
1736 1.1 christos /* We only do this once per section. We may be able to delete some code
1737 1.1.1.6 christos by running multiple passes, but it is not worth it. */
1738 1.1 christos *again = FALSE;
1739 1.1.1.2 christos
1740 1.1.1.2 christos /* Only do this for a text section. */
1741 1.1 christos if (bfd_link_relocatable (link_info)
1742 1.1 christos || (sec->flags & SEC_RELOC) == 0
1743 1.1 christos || (sec->reloc_count == 0)
1744 1.1 christos || (sec->flags & SEC_CODE) == 0)
1745 1.1 christos return TRUE;
1746 1.1 christos
1747 1.1 christos BFD_ASSERT ((sec->size > 0) || (sec->rawsize > 0));
1748 1.1 christos
1749 1.1 christos /* If this is the first time we have been called for this section,
1750 1.1 christos initialize the cooked size. */
1751 1.1 christos if (sec->size == 0)
1752 1.1 christos sec->size = sec->rawsize;
1753 1.1 christos
1754 1.1 christos /* Get symbols for this section. */
1755 1.1 christos symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1756 1.1.1.7.4.1 christos isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1757 1.1 christos symcount = symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
1758 1.1 christos if (isymbuf == NULL)
1759 1.1 christos isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, symcount,
1760 1.1 christos 0, NULL, NULL, NULL);
1761 1.1 christos BFD_ASSERT (isymbuf != NULL);
1762 1.1 christos
1763 1.1 christos internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, link_info->keep_memory);
1764 1.1 christos if (internal_relocs == NULL)
1765 1.1 christos goto error_return;
1766 1.1 christos if (! link_info->keep_memory)
1767 1.1 christos free_relocs = internal_relocs;
1768 1.1 christos
1769 1.1 christos sec->relax = (struct relax_table *) bfd_malloc ((sec->reloc_count + 1)
1770 1.1 christos * sizeof (struct relax_table));
1771 1.1 christos if (sec->relax == NULL)
1772 1.1 christos goto error_return;
1773 1.1 christos sec->relax_count = 0;
1774 1.1 christos
1775 1.1 christos irelend = internal_relocs + sec->reloc_count;
1776 1.1 christos rel_count = 0;
1777 1.1.1.7.4.1 christos for (irel = internal_relocs; irel < irelend; irel++, rel_count++)
1778 1.1.1.7.4.1 christos {
1779 1.1 christos bfd_vma symval;
1780 1.1 christos if ((ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64_PCREL)
1781 1.1 christos && (ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64)
1782 1.1 christos && (ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_TEXTREL_64))
1783 1.1 christos continue; /* Can't delete this reloc. */
1784 1.1 christos
1785 1.1 christos /* Get the section contents. */
1786 1.1 christos if (contents == NULL)
1787 1.1 christos {
1788 1.1 christos if (elf_section_data (sec)->this_hdr.contents != NULL)
1789 1.1 christos contents = elf_section_data (sec)->this_hdr.contents;
1790 1.1 christos else
1791 1.1 christos {
1792 1.1 christos contents = (bfd_byte *) bfd_malloc (sec->size);
1793 1.1 christos if (contents == NULL)
1794 1.1 christos goto error_return;
1795 1.1 christos free_contents = contents;
1796 1.1.1.7.4.1 christos
1797 1.1 christos if (!bfd_get_section_contents (abfd, sec, contents,
1798 1.1 christos (file_ptr) 0, sec->size))
1799 1.1 christos goto error_return;
1800 1.1 christos elf_section_data (sec)->this_hdr.contents = contents;
1801 1.1 christos }
1802 1.1 christos }
1803 1.1 christos
1804 1.1 christos /* Get the value of the symbol referred to by the reloc. */
1805 1.1 christos if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1806 1.1 christos {
1807 1.1.1.7.4.1 christos /* A local symbol. */
1808 1.1 christos asection *sym_sec;
1809 1.1 christos
1810 1.1 christos isym = isymbuf + ELF32_R_SYM (irel->r_info);
1811 1.1 christos if (isym->st_shndx == SHN_UNDEF)
1812 1.1 christos sym_sec = bfd_und_section_ptr;
1813 1.1 christos else if (isym->st_shndx == SHN_ABS)
1814 1.1 christos sym_sec = bfd_abs_section_ptr;
1815 1.1 christos else if (isym->st_shndx == SHN_COMMON)
1816 1.1 christos sym_sec = bfd_com_section_ptr;
1817 1.1 christos else
1818 1.1 christos sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1819 1.1 christos
1820 1.1 christos symval = _bfd_elf_rela_local_sym (abfd, isym, &sym_sec, irel);
1821 1.1 christos }
1822 1.1 christos else
1823 1.1 christos {
1824 1.1 christos unsigned long indx;
1825 1.1 christos struct elf_link_hash_entry *h;
1826 1.1 christos
1827 1.1.1.7.4.1 christos indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1828 1.1 christos h = elf_sym_hashes (abfd)[indx];
1829 1.1 christos BFD_ASSERT (h != NULL);
1830 1.1 christos
1831 1.1 christos if (h->root.type != bfd_link_hash_defined
1832 1.1 christos && h->root.type != bfd_link_hash_defweak)
1833 1.1 christos /* This appears to be a reference to an undefined
1834 1.1 christos symbol. Just ignore it--it will be caught by the
1835 1.1 christos regular reloc processing. */
1836 1.1 christos continue;
1837 1.1 christos
1838 1.1 christos symval = (h->root.u.def.value
1839 1.1 christos + h->root.u.def.section->output_section->vma
1840 1.1.1.7.4.1 christos + h->root.u.def.section->output_offset);
1841 1.1 christos }
1842 1.1 christos
1843 1.1 christos /* If this is a PC-relative reloc, subtract the instr offset from
1844 1.1 christos the symbol value. */
1845 1.1 christos if (ELF32_R_TYPE (irel->r_info) == (int) R_MICROBLAZE_64_PCREL)
1846 1.1 christos {
1847 1.1.1.7.4.1 christos symval = symval + irel->r_addend
1848 1.1.1.7.4.1 christos - (irel->r_offset
1849 1.1.1.7.4.1 christos + sec->output_section->vma
1850 1.1.1.7.4.1 christos + sec->output_offset);
1851 1.1.1.7.4.1 christos }
1852 1.1 christos else if (ELF32_R_TYPE (irel->r_info) == (int) R_MICROBLAZE_TEXTREL_64)
1853 1.1 christos {
1854 1.1 christos symval = symval + irel->r_addend - (sec->output_section->vma);
1855 1.1 christos }
1856 1.1 christos else
1857 1.1 christos symval += irel->r_addend;
1858 1.1.1.7.4.1 christos
1859 1.1 christos if ((symval & 0xffff8000) == 0
1860 1.1 christos || (symval & 0xffff8000) == 0xffff8000)
1861 1.1 christos {
1862 1.1 christos /* We can delete this instruction. */
1863 1.1 christos sec->relax[sec->relax_count].addr = irel->r_offset;
1864 1.1.1.7.4.1 christos sec->relax[sec->relax_count].size = INST_WORD_SIZE;
1865 1.1 christos sec->relax_count++;
1866 1.1 christos
1867 1.1 christos /* Rewrite relocation type. */
1868 1.1.1.7.4.1 christos switch ((enum elf_microblaze_reloc_type) ELF32_R_TYPE (irel->r_info))
1869 1.1 christos {
1870 1.1 christos case R_MICROBLAZE_64_PCREL:
1871 1.1.1.7.4.1 christos irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1872 1.1.1.7.4.1 christos (int) R_MICROBLAZE_32_PCREL_LO);
1873 1.1.1.7.4.1 christos break;
1874 1.1.1.7.4.1 christos case R_MICROBLAZE_64:
1875 1.1.1.7.4.1 christos irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1876 1.1.1.7.4.1 christos (int) R_MICROBLAZE_32_LO);
1877 1.1 christos break;
1878 1.1 christos case R_MICROBLAZE_TEXTREL_64:
1879 1.1 christos irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1880 1.1 christos (int) R_MICROBLAZE_TEXTREL_32_LO);
1881 1.1.1.7.4.1 christos break;
1882 1.1.1.7.4.1 christos default:
1883 1.1 christos /* Cannot happen. */
1884 1.1 christos BFD_ASSERT (FALSE);
1885 1.1 christos }
1886 1.1 christos }
1887 1.1 christos } /* Loop through all relocations. */
1888 1.1 christos
1889 1.1 christos /* Loop through the relocs again, and see if anything needs to change. */
1890 1.1 christos if (sec->relax_count > 0)
1891 1.1 christos {
1892 1.1 christos shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1893 1.1.1.7.4.1 christos rel_count = 0;
1894 1.1 christos sec->relax[sec->relax_count].addr = sec->size;
1895 1.1 christos
1896 1.1.1.7.4.1 christos for (irel = internal_relocs; irel < irelend; irel++, rel_count++)
1897 1.1.1.2 christos {
1898 1.1.1.7.4.1 christos bfd_vma nraddr;
1899 1.1 christos
1900 1.1 christos /* Get the new reloc address. */
1901 1.1 christos nraddr = irel->r_offset - calc_fixup (irel->r_offset, 0, sec);
1902 1.1 christos switch ((enum elf_microblaze_reloc_type) ELF32_R_TYPE (irel->r_info))
1903 1.1 christos {
1904 1.1.1.7.4.1 christos default:
1905 1.1.1.7.4.1 christos break;
1906 1.1 christos case R_MICROBLAZE_64_PCREL:
1907 1.1 christos break;
1908 1.1 christos case R_MICROBLAZE_TEXTREL_64:
1909 1.1.1.7.4.1 christos case R_MICROBLAZE_TEXTREL_32_LO:
1910 1.1.1.7.4.1 christos case R_MICROBLAZE_64:
1911 1.1 christos case R_MICROBLAZE_32_LO:
1912 1.1.1.7.4.1 christos /* If this reloc is against a symbol defined in this
1913 1.1 christos section, we must check the addend to see it will put the value in
1914 1.1 christos range to be adjusted, and hence must be changed. */
1915 1.1 christos if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1916 1.1 christos {
1917 1.1.1.2 christos isym = isymbuf + ELF32_R_SYM (irel->r_info);
1918 1.1.1.7.4.1 christos /* Only handle relocs against .text. */
1919 1.1 christos if (isym->st_shndx == shndx
1920 1.1 christos && ELF32_ST_TYPE (isym->st_info) == STT_SECTION)
1921 1.1 christos irel->r_addend -= calc_fixup (irel->r_addend, 0, sec);
1922 1.1.1.7.4.1 christos }
1923 1.1.1.7.4.1 christos break;
1924 1.1.1.7.4.1 christos case R_MICROBLAZE_NONE:
1925 1.1.1.7.4.1 christos {
1926 1.1.1.7.4.1 christos /* This was a PC-relative instruction that was
1927 1.1.1.7.4.1 christos completely resolved. */
1928 1.1.1.7.4.1 christos int sfix, efix;
1929 1.1.1.7.4.1 christos bfd_vma target_address;
1930 1.1.1.7.4.1 christos target_address = irel->r_addend + irel->r_offset;
1931 1.1.1.7.4.1 christos sfix = calc_fixup (irel->r_offset, 0, sec);
1932 1.1.1.7.4.1 christos efix = calc_fixup (target_address, 0, sec);
1933 1.1 christos irel->r_addend -= (efix - sfix);
1934 1.1 christos /* Should use HOWTO. */
1935 1.1 christos microblaze_bfd_write_imm_value_32 (abfd, contents + irel->r_offset,
1936 1.1 christos irel->r_addend);
1937 1.1.1.7.4.1 christos }
1938 1.1.1.7.4.1 christos break;
1939 1.1.1.7.4.1 christos case R_MICROBLAZE_64_NONE:
1940 1.1.1.7.4.1 christos {
1941 1.1 christos /* This was a PC-relative 64-bit instruction that was
1942 1.1.1.2 christos completely resolved. */
1943 1.1.1.2 christos int sfix, efix;
1944 1.1 christos bfd_vma target_address;
1945 1.1.1.2 christos target_address = irel->r_addend + irel->r_offset + INST_WORD_SIZE;
1946 1.1.1.7.4.1 christos sfix = calc_fixup (irel->r_offset + INST_WORD_SIZE, 0, sec);
1947 1.1 christos efix = calc_fixup (target_address, 0, sec);
1948 1.1 christos irel->r_addend -= (efix - sfix);
1949 1.1 christos microblaze_bfd_write_imm_value_32 (abfd, contents + irel->r_offset
1950 1.1.1.7.4.1 christos + INST_WORD_SIZE, irel->r_addend);
1951 1.1.1.7.4.1 christos }
1952 1.1 christos break;
1953 1.1 christos }
1954 1.1 christos irel->r_offset = nraddr;
1955 1.1.1.7.4.1 christos } /* Change all relocs in this section. */
1956 1.1.1.7.4.1 christos
1957 1.1.1.7.4.1 christos /* Look through all other sections. */
1958 1.1.1.7.4.1 christos for (o = abfd->sections; o != NULL; o = o->next)
1959 1.1.1.7.4.1 christos {
1960 1.1.1.7.4.1 christos Elf_Internal_Rela *irelocs;
1961 1.1.1.7.4.1 christos Elf_Internal_Rela *irelscan, *irelscanend;
1962 1.1.1.7.4.1 christos bfd_byte *ocontents;
1963 1.1.1.7.4.1 christos
1964 1.1.1.7.4.1 christos if (o == sec
1965 1.1.1.7.4.1 christos || (o->flags & SEC_RELOC) == 0
1966 1.1.1.7.4.1 christos || o->reloc_count == 0)
1967 1.1.1.7.4.1 christos continue;
1968 1.1.1.7.4.1 christos
1969 1.1.1.7.4.1 christos /* We always cache the relocs. Perhaps, if info->keep_memory is
1970 1.1.1.7.4.1 christos FALSE, we should free them, if we are permitted to. */
1971 1.1.1.7.4.1 christos
1972 1.1.1.7.4.1 christos irelocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, TRUE);
1973 1.1.1.7.4.1 christos if (irelocs == NULL)
1974 1.1.1.7.4.1 christos goto error_return;
1975 1.1.1.7.4.1 christos
1976 1.1.1.7.4.1 christos ocontents = NULL;
1977 1.1.1.7.4.1 christos irelscanend = irelocs + o->reloc_count;
1978 1.1.1.7.4.1 christos for (irelscan = irelocs; irelscan < irelscanend; irelscan++)
1979 1.1.1.7.4.1 christos {
1980 1.1.1.7.4.1 christos if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32)
1981 1.1.1.7.4.1 christos {
1982 1.1.1.7.4.1 christos isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
1983 1.1.1.7.4.1 christos
1984 1.1.1.7.4.1 christos /* Look at the reloc only if the value has been resolved. */
1985 1.1.1.7.4.1 christos if (isym->st_shndx == shndx
1986 1.1.1.7.4.1 christos && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
1987 1.1.1.7.4.1 christos {
1988 1.1.1.7.4.1 christos if (ocontents == NULL)
1989 1.1.1.7.4.1 christos {
1990 1.1.1.7.4.1 christos if (elf_section_data (o)->this_hdr.contents != NULL)
1991 1.1.1.7.4.1 christos ocontents = elf_section_data (o)->this_hdr.contents;
1992 1.1.1.7.4.1 christos else
1993 1.1.1.7.4.1 christos {
1994 1.1.1.7.4.1 christos /* We always cache the section contents.
1995 1.1.1.7.4.1 christos Perhaps, if info->keep_memory is FALSE, we
1996 1.1.1.7.4.1 christos should free them, if we are permitted to. */
1997 1.1.1.7.4.1 christos if (o->rawsize == 0)
1998 1.1.1.7.4.1 christos o->rawsize = o->size;
1999 1.1.1.7.4.1 christos ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
2000 1.1 christos if (ocontents == NULL)
2001 1.1.1.7.4.1 christos goto error_return;
2002 1.1.1.7.4.1 christos if (!bfd_get_section_contents (abfd, o, ocontents,
2003 1.1.1.7.4.1 christos (file_ptr) 0,
2004 1.1 christos o->rawsize))
2005 1.1.1.7.4.1 christos goto error_return;
2006 1.1.1.2 christos elf_section_data (o)->this_hdr.contents = ocontents;
2007 1.1.1.7.4.1 christos }
2008 1.1 christos
2009 1.1 christos }
2010 1.1 christos irelscan->r_addend -= calc_fixup (irelscan->r_addend, 0, sec);
2011 1.1 christos }
2012 1.1 christos else if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_SYM_OP_SYM)
2013 1.1 christos {
2014 1.1 christos isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
2015 1.1 christos
2016 1.1 christos /* Look at the reloc only if the value has been resolved. */
2017 1.1 christos if (ocontents == NULL)
2018 1.1 christos {
2019 1.1 christos if (elf_section_data (o)->this_hdr.contents != NULL)
2020 1.1 christos ocontents = elf_section_data (o)->this_hdr.contents;
2021 1.1 christos else
2022 1.1 christos {
2023 1.1 christos /* We always cache the section contents.
2024 1.1 christos Perhaps, if info->keep_memory is FALSE, we
2025 1.1 christos should free them, if we are permitted to. */
2026 1.1 christos
2027 1.1 christos if (o->rawsize == 0)
2028 1.1 christos o->rawsize = o->size;
2029 1.1 christos ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
2030 1.1 christos if (ocontents == NULL)
2031 1.1 christos goto error_return;
2032 1.1 christos if (!bfd_get_section_contents (abfd, o, ocontents,
2033 1.1 christos (file_ptr) 0,
2034 1.1 christos o->rawsize))
2035 1.1 christos goto error_return;
2036 1.1 christos elf_section_data (o)->this_hdr.contents = ocontents;
2037 1.1.1.2 christos }
2038 1.1 christos }
2039 1.1 christos irelscan->r_addend -= calc_fixup (irel->r_addend
2040 1.1 christos + isym->st_value,
2041 1.1 christos 0,
2042 1.1.1.7.4.1 christos sec);
2043 1.1.1.7.4.1 christos }
2044 1.1.1.7.4.1 christos }
2045 1.1.1.7.4.1 christos else if ((ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_PCREL_LO)
2046 1.1 christos || (ELF32_R_TYPE (irelscan->r_info)
2047 1.1 christos == (int) R_MICROBLAZE_32_LO)
2048 1.1 christos || (ELF32_R_TYPE (irelscan->r_info)
2049 1.1 christos == (int) R_MICROBLAZE_TEXTREL_32_LO))
2050 1.1 christos {
2051 1.1 christos isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
2052 1.1 christos
2053 1.1 christos /* Look at the reloc only if the value has been resolved. */
2054 1.1 christos if (isym->st_shndx == shndx
2055 1.1 christos && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
2056 1.1 christos {
2057 1.1 christos bfd_vma immediate;
2058 1.1 christos bfd_vma target_address;
2059 1.1 christos
2060 1.1 christos if (ocontents == NULL)
2061 1.1 christos {
2062 1.1 christos if (elf_section_data (o)->this_hdr.contents != NULL)
2063 1.1 christos ocontents = elf_section_data (o)->this_hdr.contents;
2064 1.1 christos else
2065 1.1 christos {
2066 1.1 christos /* We always cache the section contents.
2067 1.1 christos Perhaps, if info->keep_memory is FALSE, we
2068 1.1 christos should free them, if we are permitted to. */
2069 1.1 christos if (o->rawsize == 0)
2070 1.1 christos o->rawsize = o->size;
2071 1.1 christos ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
2072 1.1 christos if (ocontents == NULL)
2073 1.1 christos goto error_return;
2074 1.1 christos if (!bfd_get_section_contents (abfd, o, ocontents,
2075 1.1 christos (file_ptr) 0,
2076 1.1 christos o->rawsize))
2077 1.1 christos goto error_return;
2078 1.1.1.2 christos elf_section_data (o)->this_hdr.contents = ocontents;
2079 1.1.1.2 christos }
2080 1.1 christos }
2081 1.1.1.2 christos
2082 1.1 christos unsigned long instr = bfd_get_32 (abfd, ocontents + irelscan->r_offset);
2083 1.1 christos immediate = instr & 0x0000ffff;
2084 1.1.1.7.4.1 christos target_address = immediate;
2085 1.1.1.7.4.1 christos offset = calc_fixup (target_address, 0, sec);
2086 1.1 christos immediate -= offset;
2087 1.1 christos irelscan->r_addend -= offset;
2088 1.1 christos microblaze_bfd_write_imm_value_32 (abfd, ocontents + irelscan->r_offset,
2089 1.1.1.7.4.1 christos irelscan->r_addend);
2090 1.1.1.7.4.1 christos }
2091 1.1.1.7.4.1 christos }
2092 1.1 christos
2093 1.1 christos if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64
2094 1.1 christos || (ELF32_R_TYPE (irelscan->r_info)
2095 1.1 christos == (int) R_MICROBLAZE_TEXTREL_64))
2096 1.1 christos {
2097 1.1 christos isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
2098 1.1 christos
2099 1.1 christos /* Look at the reloc only if the value has been resolved. */
2100 1.1 christos if (isym->st_shndx == shndx
2101 1.1 christos && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
2102 1.1 christos {
2103 1.1 christos bfd_vma immediate;
2104 1.1 christos
2105 1.1 christos if (ocontents == NULL)
2106 1.1 christos {
2107 1.1 christos if (elf_section_data (o)->this_hdr.contents != NULL)
2108 1.1 christos ocontents = elf_section_data (o)->this_hdr.contents;
2109 1.1 christos else
2110 1.1 christos {
2111 1.1 christos /* We always cache the section contents.
2112 1.1 christos Perhaps, if info->keep_memory is FALSE, we
2113 1.1 christos should free them, if we are permitted to. */
2114 1.1 christos
2115 1.1 christos if (o->rawsize == 0)
2116 1.1 christos o->rawsize = o->size;
2117 1.1 christos ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
2118 1.1 christos if (ocontents == NULL)
2119 1.1 christos goto error_return;
2120 1.1 christos if (!bfd_get_section_contents (abfd, o, ocontents,
2121 1.1 christos (file_ptr) 0,
2122 1.1 christos o->rawsize))
2123 1.1.1.7.4.1 christos goto error_return;
2124 1.1.1.7.4.1 christos elf_section_data (o)->this_hdr.contents = ocontents;
2125 1.1.1.7.4.1 christos }
2126 1.1.1.7.4.1 christos }
2127 1.1.1.7.4.1 christos unsigned long instr_hi = bfd_get_32 (abfd, ocontents
2128 1.1.1.7.4.1 christos + irelscan->r_offset);
2129 1.1.1.7.4.1 christos unsigned long instr_lo = bfd_get_32 (abfd, ocontents
2130 1.1.1.2 christos + irelscan->r_offset
2131 1.1 christos + INST_WORD_SIZE);
2132 1.1 christos immediate = (instr_hi & 0x0000ffff) << 16;
2133 1.1 christos immediate |= (instr_lo & 0x0000ffff);
2134 1.1 christos offset = calc_fixup (irelscan->r_addend, 0, sec);
2135 1.1 christos immediate -= offset;
2136 1.1 christos irelscan->r_addend -= offset;
2137 1.1 christos }
2138 1.1 christos }
2139 1.1 christos else if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64_PCREL)
2140 1.1 christos {
2141 1.1 christos isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
2142 1.1 christos
2143 1.1 christos /* Look at the reloc only if the value has been resolved. */
2144 1.1 christos if (isym->st_shndx == shndx
2145 1.1 christos && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
2146 1.1 christos {
2147 1.1 christos bfd_vma immediate;
2148 1.1 christos bfd_vma target_address;
2149 1.1 christos
2150 1.1 christos if (ocontents == NULL)
2151 1.1 christos {
2152 1.1 christos if (elf_section_data (o)->this_hdr.contents != NULL)
2153 1.1 christos ocontents = elf_section_data (o)->this_hdr.contents;
2154 1.1 christos else
2155 1.1 christos {
2156 1.1 christos /* We always cache the section contents.
2157 1.1 christos Perhaps, if info->keep_memory is FALSE, we
2158 1.1 christos should free them, if we are permitted to. */
2159 1.1 christos if (o->rawsize == 0)
2160 1.1 christos o->rawsize = o->size;
2161 1.1 christos ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
2162 1.1 christos if (ocontents == NULL)
2163 1.1 christos goto error_return;
2164 1.1 christos if (!bfd_get_section_contents (abfd, o, ocontents,
2165 1.1 christos (file_ptr) 0,
2166 1.1 christos o->rawsize))
2167 1.1.1.7.4.1 christos goto error_return;
2168 1.1.1.7.4.1 christos elf_section_data (o)->this_hdr.contents = ocontents;
2169 1.1.1.7.4.1 christos }
2170 1.1.1.7.4.1 christos }
2171 1.1.1.7.4.1 christos unsigned long instr_hi = bfd_get_32 (abfd, ocontents
2172 1.1.1.7.4.1 christos + irelscan->r_offset);
2173 1.1.1.7.4.1 christos unsigned long instr_lo = bfd_get_32 (abfd, ocontents
2174 1.1 christos + irelscan->r_offset
2175 1.1.1.2 christos + INST_WORD_SIZE);
2176 1.1 christos immediate = (instr_hi & 0x0000ffff) << 16;
2177 1.1 christos immediate |= (instr_lo & 0x0000ffff);
2178 1.1.1.7.4.1 christos target_address = immediate;
2179 1.1.1.7.4.1 christos offset = calc_fixup (target_address, 0, sec);
2180 1.1 christos immediate -= offset;
2181 1.1 christos irelscan->r_addend -= offset;
2182 1.1.1.7.4.1 christos microblaze_bfd_write_imm_value_64 (abfd, ocontents
2183 1.1.1.7.4.1 christos + irelscan->r_offset, immediate);
2184 1.1 christos }
2185 1.1 christos }
2186 1.1 christos }
2187 1.1 christos }
2188 1.1.1.7.4.1 christos
2189 1.1.1.7.4.1 christos /* Adjust the local symbols defined in this section. */
2190 1.1.1.7.4.1 christos isymend = isymbuf + symtab_hdr->sh_info;
2191 1.1.1.7.4.1 christos for (isym = isymbuf; isym < isymend; isym++)
2192 1.1.1.7.4.1 christos {
2193 1.1.1.7.4.1 christos if (isym->st_shndx == shndx)
2194 1.1.1.7.4.1 christos {
2195 1.1.1.7.4.1 christos isym->st_value -= calc_fixup (isym->st_value, 0, sec);
2196 1.1 christos if (isym->st_size)
2197 1.1 christos isym->st_size -= calc_fixup (isym->st_value, isym->st_size, sec);
2198 1.1 christos }
2199 1.1.1.2 christos }
2200 1.1.1.2 christos
2201 1.1.1.7.4.1 christos /* Now adjust the global symbols defined in this section. */
2202 1.1.1.7.4.1 christos isym = isymbuf + symtab_hdr->sh_info;
2203 1.1.1.7.4.1 christos symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)) - symtab_hdr->sh_info;
2204 1.1.1.7.4.1 christos for (sym_index = 0; sym_index < symcount; sym_index++)
2205 1.1.1.7.4.1 christos {
2206 1.1.1.7.4.1 christos sym_hash = elf_sym_hashes (abfd)[sym_index];
2207 1.1.1.7.4.1 christos if ((sym_hash->root.type == bfd_link_hash_defined
2208 1.1.1.7.4.1 christos || sym_hash->root.type == bfd_link_hash_defweak)
2209 1.1.1.7.4.1 christos && sym_hash->root.u.def.section == sec)
2210 1.1.1.7.4.1 christos {
2211 1.1.1.7.4.1 christos sym_hash->root.u.def.value -= calc_fixup (sym_hash->root.u.def.value,
2212 1.1.1.7.4.1 christos 0, sec);
2213 1.1.1.7.4.1 christos if (sym_hash->size)
2214 1.1 christos sym_hash->size -= calc_fixup (sym_hash->root.u.def.value,
2215 1.1 christos sym_hash->size, sec);
2216 1.1 christos }
2217 1.1 christos }
2218 1.1.1.7.4.1 christos
2219 1.1.1.7.4.1 christos /* Physically move the code and change the cooked size. */
2220 1.1.1.7.4.1 christos dest = sec->relax[0].addr;
2221 1.1.1.7.4.1 christos for (i = 0; i < sec->relax_count; i++)
2222 1.1.1.7.4.1 christos {
2223 1.1.1.7.4.1 christos int len;
2224 1.1.1.7.4.1 christos src = sec->relax[i].addr + sec->relax[i].size;
2225 1.1.1.7.4.1 christos len = sec->relax[i+1].addr - sec->relax[i].addr - sec->relax[i].size;
2226 1.1.1.7.4.1 christos
2227 1.1 christos memmove (contents + dest, contents + src, len);
2228 1.1 christos sec->size -= sec->relax[i].size;
2229 1.1 christos dest += len;
2230 1.1 christos }
2231 1.1 christos
2232 1.1 christos elf_section_data (sec)->relocs = internal_relocs;
2233 1.1 christos free_relocs = NULL;
2234 1.1 christos
2235 1.1 christos elf_section_data (sec)->this_hdr.contents = contents;
2236 1.1 christos free_contents = NULL;
2237 1.1 christos
2238 1.1 christos symtab_hdr->contents = (bfd_byte *) isymbuf;
2239 1.1 christos }
2240 1.1 christos
2241 1.1 christos if (free_relocs != NULL)
2242 1.1 christos {
2243 1.1 christos free (free_relocs);
2244 1.1 christos free_relocs = NULL;
2245 1.1 christos }
2246 1.1 christos
2247 1.1 christos if (free_contents != NULL)
2248 1.1 christos {
2249 1.1 christos if (!link_info->keep_memory)
2250 1.1 christos free (free_contents);
2251 1.1 christos else
2252 1.1 christos /* Cache the section contents for elf_link_input_bfd. */
2253 1.1 christos elf_section_data (sec)->this_hdr.contents = contents;
2254 1.1 christos free_contents = NULL;
2255 1.1.1.2 christos }
2256 1.1 christos
2257 1.1 christos if (sec->relax_count == 0)
2258 1.1 christos {
2259 1.1.1.2 christos *again = FALSE;
2260 1.1.1.2 christos free (sec->relax);
2261 1.1 christos sec->relax = NULL;
2262 1.1 christos }
2263 1.1 christos else
2264 1.1 christos *again = TRUE;
2265 1.1 christos return TRUE;
2266 1.1 christos
2267 1.1 christos error_return:
2268 1.1 christos if (free_relocs != NULL)
2269 1.1 christos free (free_relocs);
2270 1.1 christos if (free_contents != NULL)
2271 1.1 christos free (free_contents);
2272 1.1 christos if (sec->relax != NULL)
2273 1.1 christos {
2274 1.1 christos free (sec->relax);
2275 1.1 christos sec->relax = NULL;
2276 1.1 christos sec->relax_count = 0;
2277 1.1 christos }
2278 1.1 christos return FALSE;
2279 1.1 christos }
2280 1.1 christos
2281 1.1 christos /* Return the section that should be marked against GC for a given
2282 1.1 christos relocation. */
2283 1.1.1.7.4.1 christos
2284 1.1.1.7.4.1 christos static asection *
2285 1.1.1.7.4.1 christos microblaze_elf_gc_mark_hook (asection *sec,
2286 1.1 christos struct bfd_link_info * info,
2287 1.1 christos Elf_Internal_Rela * rel,
2288 1.1 christos struct elf_link_hash_entry * h,
2289 1.1 christos Elf_Internal_Sym * sym)
2290 1.1 christos {
2291 1.1 christos if (h != NULL)
2292 1.1 christos switch (ELF32_R_TYPE (rel->r_info))
2293 1.1 christos {
2294 1.1 christos case R_MICROBLAZE_GNU_VTINHERIT:
2295 1.1 christos case R_MICROBLAZE_GNU_VTENTRY:
2296 1.1 christos return NULL;
2297 1.1 christos }
2298 1.1 christos
2299 1.1 christos return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
2300 1.1 christos }
2301 1.1 christos
2302 1.1.1.7.4.1 christos /* PIC support. */
2303 1.1.1.7.4.1 christos
2304 1.1.1.7.4.1 christos #define PLT_ENTRY_SIZE 16
2305 1.1.1.7.4.1 christos
2306 1.1.1.7.4.1 christos #define PLT_ENTRY_WORD_0 0xb0000000 /* "imm 0". */
2307 1.1 christos #define PLT_ENTRY_WORD_1 0xe9940000 /* "lwi r12,r20,0" - relocated to lwi r12,r20,func@GOT. */
2308 1.1.1.2 christos #define PLT_ENTRY_WORD_1_NOPIC 0xe9800000 /* "lwi r12,r0,0" - non-PIC object. */
2309 1.1.1.2 christos #define PLT_ENTRY_WORD_2 0x98186000 /* "brad r12". */
2310 1.1.1.2 christos #define PLT_ENTRY_WORD_3 0x80000000 /* "nop". */
2311 1.1.1.2 christos
2312 1.1.1.2 christos static bfd_boolean
2313 1.1.1.2 christos update_local_sym_info (bfd *abfd,
2314 1.1.1.2 christos Elf_Internal_Shdr *symtab_hdr,
2315 1.1.1.2 christos unsigned long r_symndx,
2316 1.1.1.2 christos unsigned int tls_type)
2317 1.1.1.2 christos {
2318 1.1.1.2 christos bfd_signed_vma *local_got_refcounts = elf_local_got_refcounts (abfd);
2319 1.1.1.2 christos unsigned char *local_got_tls_masks;
2320 1.1.1.2 christos
2321 1.1.1.2 christos if (local_got_refcounts == NULL)
2322 1.1.1.2 christos {
2323 1.1.1.2 christos bfd_size_type size = symtab_hdr->sh_info;
2324 1.1.1.7.4.1 christos
2325 1.1.1.2 christos size *= (sizeof (*local_got_refcounts) + sizeof (*local_got_tls_masks));
2326 1.1.1.2 christos local_got_refcounts = bfd_zalloc (abfd, size);
2327 1.1.1.2 christos if (local_got_refcounts == NULL)
2328 1.1.1.2 christos return FALSE;
2329 1.1.1.7.4.1 christos elf_local_got_refcounts (abfd) = local_got_refcounts;
2330 1.1.1.2 christos }
2331 1.1.1.2 christos
2332 1.1.1.2 christos local_got_tls_masks =
2333 1.1.1.2 christos (unsigned char *) (local_got_refcounts + symtab_hdr->sh_info);
2334 1.1.1.2 christos local_got_tls_masks[r_symndx] |= tls_type;
2335 1.1 christos local_got_refcounts[r_symndx] += 1;
2336 1.1 christos
2337 1.1 christos return TRUE;
2338 1.1 christos }
2339 1.1 christos /* Look through the relocs for a section during the first phase. */
2340 1.1.1.7.4.1 christos
2341 1.1 christos static bfd_boolean
2342 1.1 christos microblaze_elf_check_relocs (bfd * abfd,
2343 1.1.1.7.4.1 christos struct bfd_link_info * info,
2344 1.1 christos asection * sec,
2345 1.1 christos const Elf_Internal_Rela * relocs)
2346 1.1.1.7.4.1 christos {
2347 1.1.1.7.4.1 christos Elf_Internal_Shdr * symtab_hdr;
2348 1.1 christos struct elf_link_hash_entry ** sym_hashes;
2349 1.1 christos struct elf_link_hash_entry ** sym_hashes_end;
2350 1.1 christos const Elf_Internal_Rela * rel;
2351 1.1.1.6 christos const Elf_Internal_Rela * rel_end;
2352 1.1 christos struct elf32_mb_link_hash_table *htab;
2353 1.1 christos asection *sreloc = NULL;
2354 1.1 christos
2355 1.1 christos if (bfd_link_relocatable (info))
2356 1.1 christos return TRUE;
2357 1.1 christos
2358 1.1 christos htab = elf32_mb_hash_table (info);
2359 1.1 christos if (htab == NULL)
2360 1.1 christos return FALSE;
2361 1.1 christos
2362 1.1 christos symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
2363 1.1 christos sym_hashes = elf_sym_hashes (abfd);
2364 1.1 christos sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
2365 1.1 christos if (!elf_bad_symtab (abfd))
2366 1.1 christos sym_hashes_end -= symtab_hdr->sh_info;
2367 1.1 christos
2368 1.1 christos rel_end = relocs + sec->reloc_count;
2369 1.1 christos
2370 1.1 christos for (rel = relocs; rel < rel_end; rel++)
2371 1.1.1.2 christos {
2372 1.1 christos unsigned int r_type;
2373 1.1 christos struct elf_link_hash_entry * h;
2374 1.1 christos unsigned long r_symndx;
2375 1.1 christos unsigned char tls_type = 0;
2376 1.1 christos
2377 1.1.1.7.4.1 christos r_symndx = ELF32_R_SYM (rel->r_info);
2378 1.1 christos r_type = ELF32_R_TYPE (rel->r_info);
2379 1.1.1.3 christos
2380 1.1.1.3 christos if (r_symndx < symtab_hdr->sh_info)
2381 1.1.1.7.4.1 christos h = NULL;
2382 1.1.1.7.4.1 christos else
2383 1.1.1.7.4.1 christos {
2384 1.1.1.3 christos h = sym_hashes [r_symndx - symtab_hdr->sh_info];
2385 1.1 christos while (h->root.type == bfd_link_hash_indirect
2386 1.1 christos || h->root.type == bfd_link_hash_warning)
2387 1.1.1.7.4.1 christos h = (struct elf_link_hash_entry *) h->root.u.i.link;
2388 1.1 christos }
2389 1.1 christos
2390 1.1.1.7.4.1 christos switch (r_type)
2391 1.1.1.7.4.1 christos {
2392 1.1.1.7.4.1 christos /* This relocation describes the C++ object vtable hierarchy.
2393 1.1.1.7.4.1 christos Reconstruct it for later use during GC. */
2394 1.1 christos case R_MICROBLAZE_GNU_VTINHERIT:
2395 1.1 christos if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
2396 1.1 christos return FALSE;
2397 1.1.1.7.4.1 christos break;
2398 1.1.1.7.4.1 christos
2399 1.1.1.7.4.1 christos /* This relocation describes which C++ vtable entries are actually
2400 1.1.1.7.4.1 christos used. Record for later use during GC. */
2401 1.1 christos case R_MICROBLAZE_GNU_VTENTRY:
2402 1.1 christos if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
2403 1.1.1.7.4.1 christos return FALSE;
2404 1.1.1.7.4.1 christos break;
2405 1.1 christos
2406 1.1 christos /* This relocation requires .plt entry. */
2407 1.1 christos case R_MICROBLAZE_PLT_64:
2408 1.1 christos if (h != NULL)
2409 1.1.1.7.4.1 christos {
2410 1.1 christos h->needs_plt = 1;
2411 1.1 christos h->plt.refcount += 1;
2412 1.1.1.7.4.1 christos }
2413 1.1.1.7.4.1 christos break;
2414 1.1.1.7.4.1 christos
2415 1.1.1.7.4.1 christos /* This relocation requires .got entry. */
2416 1.1.1.7.4.1 christos case R_MICROBLAZE_TLSGD:
2417 1.1.1.7 christos tls_type |= (TLS_TLS | TLS_GD);
2418 1.1.1.7.4.1 christos goto dogottls;
2419 1.1.1.7.4.1 christos case R_MICROBLAZE_TLSLD:
2420 1.1.1.7 christos tls_type |= (TLS_TLS | TLS_LD);
2421 1.1.1.7.4.1 christos /* Fall through. */
2422 1.1.1.7.4.1 christos dogottls:
2423 1.1.1.7.4.1 christos sec->has_tls_reloc = 1;
2424 1.1.1.7.4.1 christos /* Fall through. */
2425 1.1.1.7.4.1 christos case R_MICROBLAZE_GOT_64:
2426 1.1.1.7.4.1 christos if (htab->elf.sgot == NULL)
2427 1.1.1.7.4.1 christos {
2428 1.1.1.7.4.1 christos if (htab->elf.dynobj == NULL)
2429 1.1.1.7.4.1 christos htab->elf.dynobj = abfd;
2430 1.1 christos if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
2431 1.1 christos return FALSE;
2432 1.1.1.2 christos }
2433 1.1 christos if (h != NULL)
2434 1.1.1.7.4.1 christos {
2435 1.1 christos h->got.refcount += 1;
2436 1.1.1.2 christos elf32_mb_hash_entry (h)->tls_mask |= tls_type;
2437 1.1.1.2 christos }
2438 1.1 christos else
2439 1.1.1.7.4.1 christos {
2440 1.1 christos if (! update_local_sym_info(abfd, symtab_hdr, r_symndx, tls_type) )
2441 1.1.1.7.4.1 christos return FALSE;
2442 1.1.1.7.4.1 christos }
2443 1.1.1.7.4.1 christos break;
2444 1.1.1.7.4.1 christos
2445 1.1.1.7.4.1 christos case R_MICROBLAZE_GOTOFF_64:
2446 1.1.1.7.4.1 christos case R_MICROBLAZE_GOTOFF_32:
2447 1.1.1.7.4.1 christos if (htab->elf.sgot == NULL)
2448 1.1.1.7.4.1 christos {
2449 1.1.1.7.4.1 christos if (htab->elf.dynobj == NULL)
2450 1.1.1.7.4.1 christos htab->elf.dynobj = abfd;
2451 1.1.1.7.4.1 christos if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
2452 1.1.1.7.4.1 christos return FALSE;
2453 1.1.1.7.4.1 christos }
2454 1.1.1.7.4.1 christos break;
2455 1.1.1.7.4.1 christos
2456 1.1.1.7.4.1 christos case R_MICROBLAZE_64:
2457 1.1 christos case R_MICROBLAZE_64_PCREL:
2458 1.1 christos case R_MICROBLAZE_32:
2459 1.1 christos {
2460 1.1 christos if (h != NULL && !bfd_link_pic (info))
2461 1.1 christos {
2462 1.1 christos /* we may need a copy reloc. */
2463 1.1 christos h->non_got_ref = 1;
2464 1.1 christos
2465 1.1 christos /* we may also need a .plt entry. */
2466 1.1 christos h->plt.refcount += 1;
2467 1.1 christos if (ELF32_R_TYPE (rel->r_info) != R_MICROBLAZE_64_PCREL)
2468 1.1 christos h->pointer_equality_needed = 1;
2469 1.1 christos }
2470 1.1 christos
2471 1.1 christos
2472 1.1 christos /* If we are creating a shared library, and this is a reloc
2473 1.1 christos against a global symbol, or a non PC relative reloc
2474 1.1 christos against a local symbol, then we need to copy the reloc
2475 1.1 christos into the shared library. However, if we are linking with
2476 1.1 christos -Bsymbolic, we do not need to copy a reloc against a
2477 1.1 christos global symbol which is defined in an object we are
2478 1.1 christos including in the link (i.e., DEF_REGULAR is set). At
2479 1.1 christos this point we have not seen all the input files, so it is
2480 1.1 christos possible that DEF_REGULAR is not set now but will be set
2481 1.1 christos later (it is never cleared). In case of a weak definition,
2482 1.1 christos DEF_REGULAR may be cleared later by a strong definition in
2483 1.1 christos a shared library. We account for that possibility below by
2484 1.1 christos storing information in the relocs_copied field of the hash
2485 1.1 christos table entry. A similar situation occurs when creating
2486 1.1 christos shared libraries and symbol visibility changes render the
2487 1.1 christos symbol local.
2488 1.1 christos
2489 1.1 christos If on the other hand, we are creating an executable, we
2490 1.1.1.7.4.1 christos may need to keep relocations for symbols satisfied by a
2491 1.1.1.7.4.1 christos dynamic library if we manage to avoid copy relocs for the
2492 1.1.1.7.4.1 christos symbol. */
2493 1.1.1.7.4.1 christos
2494 1.1 christos if ((bfd_link_pic (info)
2495 1.1 christos && (sec->flags & SEC_ALLOC) != 0
2496 1.1 christos && (r_type != R_MICROBLAZE_64_PCREL
2497 1.1.1.7.4.1 christos || (h != NULL
2498 1.1.1.7.4.1 christos && (! info->symbolic
2499 1.1.1.7.4.1 christos || h->root.type == bfd_link_hash_defweak
2500 1.1.1.7.4.1 christos || !h->def_regular))))
2501 1.1.1.7.4.1 christos || (!bfd_link_pic (info)
2502 1.1.1.7.4.1 christos && (sec->flags & SEC_ALLOC) != 0
2503 1.1.1.7.4.1 christos && h != NULL
2504 1.1.1.7.4.1 christos && (h->root.type == bfd_link_hash_defweak
2505 1.1.1.7.4.1 christos || !h->def_regular)))
2506 1.1.1.7.4.1 christos {
2507 1.1.1.7.4.1 christos struct elf_dyn_relocs *p;
2508 1.1.1.7.4.1 christos struct elf_dyn_relocs **head;
2509 1.1 christos
2510 1.1 christos /* When creating a shared object, we must copy these
2511 1.1 christos relocs into the output file. We create a reloc
2512 1.1 christos section in dynobj and make room for the reloc. */
2513 1.1 christos
2514 1.1 christos if (sreloc == NULL)
2515 1.1 christos {
2516 1.1 christos bfd *dynobj;
2517 1.1 christos
2518 1.1.1.2 christos if (htab->elf.dynobj == NULL)
2519 1.1.1.2 christos htab->elf.dynobj = abfd;
2520 1.1 christos dynobj = htab->elf.dynobj;
2521 1.1.1.2 christos
2522 1.1 christos sreloc = _bfd_elf_make_dynamic_reloc_section (sec, dynobj,
2523 1.1 christos 2, abfd, 1);
2524 1.1 christos if (sreloc == NULL)
2525 1.1 christos return FALSE;
2526 1.1 christos }
2527 1.1 christos
2528 1.1 christos /* If this is a global symbol, we count the number of
2529 1.1 christos relocations we need for this symbol. */
2530 1.1 christos if (h != NULL)
2531 1.1 christos head = &((struct elf32_mb_link_hash_entry *) h)->dyn_relocs;
2532 1.1 christos else
2533 1.1 christos {
2534 1.1 christos /* Track dynamic relocs needed for local syms too.
2535 1.1 christos We really need local syms available to do this
2536 1.1 christos easily. Oh well. */
2537 1.1 christos
2538 1.1 christos asection *s;
2539 1.1 christos Elf_Internal_Sym *isym;
2540 1.1 christos void *vpp;
2541 1.1 christos
2542 1.1 christos isym = bfd_sym_from_r_symndx (&htab->sym_sec,
2543 1.1 christos abfd, r_symndx);
2544 1.1 christos if (isym == NULL)
2545 1.1 christos return FALSE;
2546 1.1 christos
2547 1.1 christos s = bfd_section_from_elf_index (abfd, isym->st_shndx);
2548 1.1.1.7.4.1 christos if (s == NULL)
2549 1.1 christos return FALSE;
2550 1.1 christos
2551 1.1 christos vpp = &elf_section_data (s)->local_dynrel;
2552 1.1 christos head = (struct elf_dyn_relocs **) vpp;
2553 1.1 christos }
2554 1.1 christos
2555 1.1.1.7.4.1 christos p = *head;
2556 1.1 christos if (p == NULL || p->sec != sec)
2557 1.1 christos {
2558 1.1 christos bfd_size_type amt = sizeof *p;
2559 1.1 christos p = ((struct elf_dyn_relocs *)
2560 1.1 christos bfd_alloc (htab->elf.dynobj, amt));
2561 1.1 christos if (p == NULL)
2562 1.1 christos return FALSE;
2563 1.1 christos p->next = *head;
2564 1.1 christos *head = p;
2565 1.1 christos p->sec = sec;
2566 1.1 christos p->count = 0;
2567 1.1 christos p->pc_count = 0;
2568 1.1 christos }
2569 1.1 christos
2570 1.1.1.7.4.1 christos p->count += 1;
2571 1.1.1.7.4.1 christos if (r_type == R_MICROBLAZE_64_PCREL)
2572 1.1.1.7.4.1 christos p->pc_count += 1;
2573 1.1 christos }
2574 1.1 christos }
2575 1.1 christos break;
2576 1.1 christos }
2577 1.1 christos }
2578 1.1 christos
2579 1.1 christos return TRUE;
2580 1.1 christos }
2581 1.1 christos
2582 1.1 christos /* Copy the extra info we tack onto an elf_link_hash_entry. */
2583 1.1 christos
2584 1.1 christos static void
2585 1.1 christos microblaze_elf_copy_indirect_symbol (struct bfd_link_info *info,
2586 1.1 christos struct elf_link_hash_entry *dir,
2587 1.1 christos struct elf_link_hash_entry *ind)
2588 1.1 christos {
2589 1.1 christos struct elf32_mb_link_hash_entry *edir, *eind;
2590 1.1 christos
2591 1.1 christos edir = (struct elf32_mb_link_hash_entry *) dir;
2592 1.1 christos eind = (struct elf32_mb_link_hash_entry *) ind;
2593 1.1 christos
2594 1.1.1.7.4.1 christos if (eind->dyn_relocs != NULL)
2595 1.1.1.7.4.1 christos {
2596 1.1 christos if (edir->dyn_relocs != NULL)
2597 1.1 christos {
2598 1.1 christos struct elf_dyn_relocs **pp;
2599 1.1 christos struct elf_dyn_relocs *p;
2600 1.1 christos
2601 1.1 christos if (ind->root.type == bfd_link_hash_indirect)
2602 1.1 christos abort ();
2603 1.1 christos
2604 1.1.1.7.4.1 christos /* Add reloc counts against the weak sym to the strong sym
2605 1.1 christos list. Merge any entries against the same section. */
2606 1.1 christos for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
2607 1.1 christos {
2608 1.1 christos struct elf_dyn_relocs *q;
2609 1.1 christos
2610 1.1 christos for (q = edir->dyn_relocs; q != NULL; q = q->next)
2611 1.1 christos if (q->sec == p->sec)
2612 1.1 christos {
2613 1.1 christos q->pc_count += p->pc_count;
2614 1.1 christos q->count += p->count;
2615 1.1 christos *pp = p->next;
2616 1.1 christos break;
2617 1.1 christos }
2618 1.1 christos if (q == NULL)
2619 1.1 christos pp = &p->next;
2620 1.1 christos }
2621 1.1 christos *pp = edir->dyn_relocs;
2622 1.1 christos }
2623 1.1 christos
2624 1.1.1.2 christos edir->dyn_relocs = eind->dyn_relocs;
2625 1.1.1.2 christos eind->dyn_relocs = NULL;
2626 1.1 christos }
2627 1.1 christos
2628 1.1 christos edir->tls_mask |= eind->tls_mask;
2629 1.1.1.7.4.1 christos
2630 1.1.1.7.4.1 christos _bfd_elf_link_hash_copy_indirect (info, dir, ind);
2631 1.1.1.7.4.1 christos }
2632 1.1.1.7.4.1 christos
2633 1.1.1.7.4.1 christos /* Find dynamic relocs for H that apply to read-only sections. */
2634 1.1.1.7.4.1 christos
2635 1.1.1.7.4.1 christos static asection *
2636 1.1.1.7.4.1 christos readonly_dynrelocs (struct elf_link_hash_entry *h)
2637 1.1.1.7.4.1 christos {
2638 1.1.1.7.4.1 christos struct elf_dyn_relocs *p;
2639 1.1.1.7.4.1 christos
2640 1.1.1.7.4.1 christos for (p = elf32_mb_hash_entry (h)->dyn_relocs; p != NULL; p = p->next)
2641 1.1.1.7.4.1 christos {
2642 1.1.1.7.4.1 christos asection *s = p->sec->output_section;
2643 1.1.1.7.4.1 christos
2644 1.1.1.7.4.1 christos if (s != NULL && (s->flags & SEC_READONLY) != 0)
2645 1.1.1.7.4.1 christos return p->sec;
2646 1.1 christos }
2647 1.1 christos return NULL;
2648 1.1 christos }
2649 1.1 christos
2650 1.1 christos static bfd_boolean
2651 1.1.1.7 christos microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
2652 1.1 christos struct elf_link_hash_entry *h)
2653 1.1 christos {
2654 1.1 christos struct elf32_mb_link_hash_table *htab;
2655 1.1 christos asection *s, *srel;
2656 1.1 christos unsigned int power_of_two;
2657 1.1 christos
2658 1.1 christos htab = elf32_mb_hash_table (info);
2659 1.1 christos if (htab == NULL)
2660 1.1 christos return FALSE;
2661 1.1 christos
2662 1.1 christos /* If this is a function, put it in the procedure linkage table. We
2663 1.1 christos will fill in the contents of the procedure linkage table later,
2664 1.1 christos when we know the address of the .got section. */
2665 1.1 christos if (h->type == STT_FUNC
2666 1.1 christos || h->needs_plt)
2667 1.1 christos {
2668 1.1 christos if (h->plt.refcount <= 0
2669 1.1 christos || SYMBOL_CALLS_LOCAL (info, h)
2670 1.1 christos || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
2671 1.1 christos && h->root.type == bfd_link_hash_undefweak))
2672 1.1 christos {
2673 1.1 christos /* This case can occur if we saw a PLT reloc in an input
2674 1.1 christos file, but the symbol was never referred to by a dynamic
2675 1.1 christos object, or if all references were garbage collected. In
2676 1.1 christos such a case, we don't actually need to build a procedure
2677 1.1 christos linkage table, and we can just do a PC32 reloc instead. */
2678 1.1 christos h->plt.offset = (bfd_vma) -1;
2679 1.1 christos h->needs_plt = 0;
2680 1.1 christos }
2681 1.1 christos
2682 1.1 christos return TRUE;
2683 1.1 christos }
2684 1.1 christos else
2685 1.1 christos /* It's possible that we incorrectly decided a .plt reloc was
2686 1.1 christos needed for an R_MICROBLAZE_64_PCREL reloc to a non-function sym in
2687 1.1 christos check_relocs. We can't decide accurately between function and
2688 1.1 christos non-function syms in check-relocs; Objects loaded later in
2689 1.1 christos the link may change h->type. So fix it now. */
2690 1.1 christos h->plt.offset = (bfd_vma) -1;
2691 1.1.1.7.4.1 christos
2692 1.1 christos /* If this is a weak symbol, and there is a real definition, the
2693 1.1.1.7.4.1 christos processor independent code will have arranged for us to see the
2694 1.1.1.7.4.1 christos real definition first, and we can just use the same value. */
2695 1.1.1.7.4.1 christos if (h->is_weakalias)
2696 1.1.1.7.4.1 christos {
2697 1.1 christos struct elf_link_hash_entry *def = weakdef (h);
2698 1.1 christos BFD_ASSERT (def->root.type == bfd_link_hash_defined);
2699 1.1 christos h->root.u.def.section = def->root.u.def.section;
2700 1.1 christos h->root.u.def.value = def->root.u.def.value;
2701 1.1 christos return TRUE;
2702 1.1 christos }
2703 1.1 christos
2704 1.1 christos /* This is a reference to a symbol defined by a dynamic object which
2705 1.1 christos is not a function. */
2706 1.1 christos
2707 1.1.1.6 christos /* If we are creating a shared library, we must presume that the
2708 1.1 christos only references to the symbol are via the global offset table.
2709 1.1 christos For such cases we need not do anything here; the relocations will
2710 1.1 christos be handled correctly by relocate_section. */
2711 1.1 christos if (bfd_link_pic (info))
2712 1.1 christos return TRUE;
2713 1.1 christos
2714 1.1 christos /* If there are no references to this symbol that do not use the
2715 1.1 christos GOT, we don't need to generate a copy reloc. */
2716 1.1 christos if (!h->non_got_ref)
2717 1.1 christos return TRUE;
2718 1.1 christos
2719 1.1 christos /* If -z nocopyreloc was given, we won't generate them either. */
2720 1.1 christos if (info->nocopyreloc)
2721 1.1 christos {
2722 1.1.1.7.4.1 christos h->non_got_ref = 0;
2723 1.1 christos return TRUE;
2724 1.1.1.7.4.1 christos }
2725 1.1 christos
2726 1.1 christos /* If we don't find any dynamic relocs in read-only sections, then
2727 1.1 christos we'll be keeping the dynamic relocs and avoiding the copy reloc. */
2728 1.1 christos if (!readonly_dynrelocs (h))
2729 1.1 christos {
2730 1.1 christos h->non_got_ref = 0;
2731 1.1 christos return TRUE;
2732 1.1 christos }
2733 1.1 christos
2734 1.1 christos /* We must allocate the symbol in our .dynbss section, which will
2735 1.1 christos become part of the .bss section of the executable. There will be
2736 1.1 christos an entry for this symbol in the .dynsym section. The dynamic
2737 1.1 christos object will contain position independent code, so all references
2738 1.1 christos from the dynamic object to this symbol will go through the global
2739 1.1 christos offset table. The dynamic linker will use the .dynsym entry to
2740 1.1 christos determine the address it must put in the global offset table, so
2741 1.1 christos both the dynamic object and the regular object will refer to the
2742 1.1 christos same memory location for the variable. */
2743 1.1.1.7 christos
2744 1.1.1.7 christos /* We must generate a R_MICROBLAZE_COPY reloc to tell the dynamic linker
2745 1.1.1.7 christos to copy the initial value out of the dynamic object and into the
2746 1.1.1.7 christos runtime process image. */
2747 1.1.1.7 christos if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
2748 1.1.1.7 christos {
2749 1.1.1.7 christos s = htab->elf.sdynrelro;
2750 1.1.1.7 christos srel = htab->elf.sreldynrelro;
2751 1.1.1.7 christos }
2752 1.1.1.7 christos else
2753 1.1 christos {
2754 1.1 christos s = htab->elf.sdynbss;
2755 1.1.1.7 christos srel = htab->elf.srelbss;
2756 1.1 christos }
2757 1.1 christos if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
2758 1.1 christos {
2759 1.1 christos srel->size += sizeof (Elf32_External_Rela);
2760 1.1 christos h->needs_copy = 1;
2761 1.1 christos }
2762 1.1 christos
2763 1.1 christos /* We need to figure out the alignment required for this symbol. I
2764 1.1 christos have no idea how ELF linkers handle this. */
2765 1.1 christos power_of_two = bfd_log2 (h->size);
2766 1.1.1.7 christos if (power_of_two > 3)
2767 1.1.1.7 christos power_of_two = 3;
2768 1.1 christos
2769 1.1.1.7 christos /* Apply the required alignment. */
2770 1.1 christos s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
2771 1.1 christos if (power_of_two > s->alignment_power)
2772 1.1 christos {
2773 1.1 christos if (!bfd_set_section_alignment (s->owner, s, power_of_two))
2774 1.1.1.7 christos return FALSE;
2775 1.1.1.7 christos }
2776 1.1 christos
2777 1.1 christos /* Define the symbol as being at this point in the section. */
2778 1.1.1.7 christos h->root.u.def.section = s;
2779 1.1 christos h->root.u.def.value = s->size;
2780 1.1 christos
2781 1.1 christos /* Increment the section size to make room for the symbol. */
2782 1.1 christos s->size += h->size;
2783 1.1 christos return TRUE;
2784 1.1 christos }
2785 1.1 christos
2786 1.1 christos /* Allocate space in .plt, .got and associated reloc sections for
2787 1.1 christos dynamic relocs. */
2788 1.1 christos
2789 1.1 christos static bfd_boolean
2790 1.1 christos allocate_dynrelocs (struct elf_link_hash_entry *h, void * dat)
2791 1.1.1.7.4.1 christos {
2792 1.1 christos struct bfd_link_info *info;
2793 1.1 christos struct elf32_mb_link_hash_table *htab;
2794 1.1 christos struct elf32_mb_link_hash_entry *eh;
2795 1.1 christos struct elf_dyn_relocs *p;
2796 1.1 christos
2797 1.1 christos if (h->root.type == bfd_link_hash_indirect)
2798 1.1 christos return TRUE;
2799 1.1 christos
2800 1.1 christos info = (struct bfd_link_info *) dat;
2801 1.1 christos htab = elf32_mb_hash_table (info);
2802 1.1 christos if (htab == NULL)
2803 1.1 christos return FALSE;
2804 1.1 christos
2805 1.1 christos if (htab->elf.dynamic_sections_created
2806 1.1 christos && h->plt.refcount > 0)
2807 1.1.1.7.4.1 christos {
2808 1.1.1.7.4.1 christos /* Make sure this symbol is output as a dynamic symbol.
2809 1.1.1.7.4.1 christos Undefined weak syms won't yet be marked as dynamic. */
2810 1.1.1.7.4.1 christos if (h->dynindx == -1
2811 1.1.1.7.4.1 christos && !h->forced_local)
2812 1.1 christos {
2813 1.1.1.6 christos if (! bfd_elf_link_record_dynamic_symbol (info, h))
2814 1.1.1.7.4.1 christos return FALSE;
2815 1.1.1.7.4.1 christos }
2816 1.1 christos
2817 1.1.1.7.4.1 christos if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h))
2818 1.1.1.7.4.1 christos {
2819 1.1.1.7.4.1 christos asection *s = htab->elf.splt;
2820 1.1.1.7.4.1 christos
2821 1.1.1.7.4.1 christos /* The first entry in .plt is reserved. */
2822 1.1.1.7.4.1 christos if (s->size == 0)
2823 1.1.1.7.4.1 christos s->size = PLT_ENTRY_SIZE;
2824 1.1.1.7.4.1 christos
2825 1.1.1.7.4.1 christos h->plt.offset = s->size;
2826 1.1.1.7.4.1 christos
2827 1.1.1.7.4.1 christos /* If this symbol is not defined in a regular file, and we are
2828 1.1.1.7.4.1 christos not generating a shared library, then set the symbol to this
2829 1.1.1.7.4.1 christos location in the .plt. This is required to make function
2830 1.1.1.7.4.1 christos pointers compare as equal between the normal executable and
2831 1.1.1.7.4.1 christos the shared library. */
2832 1.1.1.7.4.1 christos if (! bfd_link_pic (info)
2833 1.1.1.7.4.1 christos && !h->def_regular)
2834 1.1 christos {
2835 1.1.1.7.4.1 christos h->root.u.def.section = s;
2836 1.1.1.7.4.1 christos h->root.u.def.value = h->plt.offset;
2837 1.1 christos }
2838 1.1.1.7.4.1 christos
2839 1.1.1.7.4.1 christos /* Make room for this entry. */
2840 1.1.1.7 christos s->size += PLT_ENTRY_SIZE;
2841 1.1 christos
2842 1.1.1.7.4.1 christos /* We also need to make an entry in the .got.plt section, which
2843 1.1.1.7.4.1 christos will be placed in the .got section by the linker script. */
2844 1.1.1.7.4.1 christos htab->elf.sgotplt->size += 4;
2845 1.1 christos
2846 1.1.1.7.4.1 christos /* We also need to make an entry in the .rel.plt section. */
2847 1.1.1.7.4.1 christos htab->elf.srelplt->size += sizeof (Elf32_External_Rela);
2848 1.1.1.7.4.1 christos }
2849 1.1.1.7.4.1 christos else
2850 1.1 christos {
2851 1.1 christos h->plt.offset = (bfd_vma) -1;
2852 1.1 christos h->needs_plt = 0;
2853 1.1 christos }
2854 1.1 christos }
2855 1.1 christos else
2856 1.1 christos {
2857 1.1.1.2 christos h->plt.offset = (bfd_vma) -1;
2858 1.1 christos h->needs_plt = 0;
2859 1.1 christos }
2860 1.1.1.2 christos
2861 1.1 christos eh = (struct elf32_mb_link_hash_entry *) h;
2862 1.1 christos if (h->got.refcount > 0)
2863 1.1 christos {
2864 1.1.1.7.4.1 christos unsigned int need;
2865 1.1 christos asection *s;
2866 1.1.1.7.4.1 christos
2867 1.1.1.7.4.1 christos /* Make sure this symbol is output as a dynamic symbol.
2868 1.1.1.7.4.1 christos Undefined weak syms won't yet be marked as dynamic. */
2869 1.1.1.7.4.1 christos if (h->dynindx == -1
2870 1.1.1.7.4.1 christos && !h->forced_local)
2871 1.1 christos {
2872 1.1.1.2 christos if (! bfd_elf_link_record_dynamic_symbol (info, h))
2873 1.1.1.2 christos return FALSE;
2874 1.1.1.7.4.1 christos }
2875 1.1.1.7.4.1 christos
2876 1.1.1.7.4.1 christos need = 0;
2877 1.1.1.7.4.1 christos if ((eh->tls_mask & TLS_TLS) != 0)
2878 1.1.1.7.4.1 christos {
2879 1.1.1.7.4.1 christos /* Handle TLS Symbol */
2880 1.1.1.7.4.1 christos if ((eh->tls_mask & TLS_LD) != 0)
2881 1.1.1.7.4.1 christos {
2882 1.1.1.7.4.1 christos if (!eh->elf.def_dynamic)
2883 1.1.1.7.4.1 christos /* We'll just use htab->tlsld_got.offset. This should
2884 1.1.1.7.4.1 christos always be the case. It's a little odd if we have
2885 1.1.1.7.4.1 christos a local dynamic reloc against a non-local symbol. */
2886 1.1.1.7.4.1 christos htab->tlsld_got.refcount += 1;
2887 1.1.1.7.4.1 christos else
2888 1.1.1.7.4.1 christos need += 8;
2889 1.1.1.2 christos }
2890 1.1.1.7.4.1 christos if ((eh->tls_mask & TLS_GD) != 0)
2891 1.1.1.7.4.1 christos need += 8;
2892 1.1.1.7.4.1 christos }
2893 1.1.1.7.4.1 christos else
2894 1.1.1.2 christos {
2895 1.1.1.7.4.1 christos /* Regular (non-TLS) symbol */
2896 1.1.1.7.4.1 christos need += 4;
2897 1.1.1.7.4.1 christos }
2898 1.1.1.2 christos if (need == 0)
2899 1.1.1.7.4.1 christos {
2900 1.1.1.7.4.1 christos h->got.offset = (bfd_vma) -1;
2901 1.1.1.7.4.1 christos }
2902 1.1.1.7.4.1 christos else
2903 1.1.1.7.4.1 christos {
2904 1.1.1.7.4.1 christos s = htab->elf.sgot;
2905 1.1 christos h->got.offset = s->size;
2906 1.1 christos s->size += need;
2907 1.1 christos htab->elf.srelgot->size += need * (sizeof (Elf32_External_Rela) / 4);
2908 1.1 christos }
2909 1.1 christos }
2910 1.1 christos else
2911 1.1 christos h->got.offset = (bfd_vma) -1;
2912 1.1 christos
2913 1.1 christos if (eh->dyn_relocs == NULL)
2914 1.1 christos return TRUE;
2915 1.1 christos
2916 1.1 christos /* In the shared -Bsymbolic case, discard space allocated for
2917 1.1 christos dynamic pc-relative relocs against symbols which turn out to be
2918 1.1.1.6 christos defined in regular objects. For the normal shared case, discard
2919 1.1 christos space for pc-relative relocs that have become local due to symbol
2920 1.1 christos visibility changes. */
2921 1.1 christos
2922 1.1 christos if (bfd_link_pic (info))
2923 1.1 christos {
2924 1.1.1.7.4.1 christos if (h->def_regular
2925 1.1 christos && (h->forced_local
2926 1.1 christos || info->symbolic))
2927 1.1 christos {
2928 1.1 christos struct elf_dyn_relocs **pp;
2929 1.1 christos
2930 1.1 christos for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
2931 1.1 christos {
2932 1.1 christos p->count -= p->pc_count;
2933 1.1 christos p->pc_count = 0;
2934 1.1 christos if (p->count == 0)
2935 1.1 christos *pp = p->next;
2936 1.1.1.7.4.1 christos else
2937 1.1.1.7.4.1 christos pp = &p->next;
2938 1.1 christos }
2939 1.1 christos }
2940 1.1 christos else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
2941 1.1 christos eh->dyn_relocs = NULL;
2942 1.1 christos }
2943 1.1 christos else
2944 1.1 christos {
2945 1.1 christos /* For the non-shared case, discard space for relocs against
2946 1.1 christos symbols which turn out to need copy relocs or are not
2947 1.1 christos dynamic. */
2948 1.1 christos
2949 1.1 christos if (!h->non_got_ref
2950 1.1 christos && ((h->def_dynamic
2951 1.1 christos && !h->def_regular)
2952 1.1 christos || (htab->elf.dynamic_sections_created
2953 1.1 christos && (h->root.type == bfd_link_hash_undefweak
2954 1.1 christos || h->root.type == bfd_link_hash_undefined))))
2955 1.1 christos {
2956 1.1 christos /* Make sure this symbol is output as a dynamic symbol.
2957 1.1 christos Undefined weak syms won't yet be marked as dynamic. */
2958 1.1 christos if (h->dynindx == -1
2959 1.1 christos && !h->forced_local)
2960 1.1 christos {
2961 1.1 christos if (! bfd_elf_link_record_dynamic_symbol (info, h))
2962 1.1 christos return FALSE;
2963 1.1 christos }
2964 1.1 christos
2965 1.1 christos /* If that succeeded, we know we'll be keeping all the
2966 1.1 christos relocs. */
2967 1.1 christos if (h->dynindx != -1)
2968 1.1 christos goto keep;
2969 1.1 christos }
2970 1.1 christos
2971 1.1 christos eh->dyn_relocs = NULL;
2972 1.1 christos
2973 1.1 christos keep: ;
2974 1.1 christos }
2975 1.1 christos
2976 1.1 christos /* Finally, allocate space. */
2977 1.1 christos for (p = eh->dyn_relocs; p != NULL; p = p->next)
2978 1.1 christos {
2979 1.1 christos asection *sreloc = elf_section_data (p->sec)->sreloc;
2980 1.1 christos sreloc->size += p->count * sizeof (Elf32_External_Rela);
2981 1.1 christos }
2982 1.1 christos
2983 1.1 christos return TRUE;
2984 1.1 christos }
2985 1.1 christos
2986 1.1 christos /* Set the sizes of the dynamic sections. */
2987 1.1 christos
2988 1.1 christos static bfd_boolean
2989 1.1 christos microblaze_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
2990 1.1 christos struct bfd_link_info *info)
2991 1.1 christos {
2992 1.1 christos struct elf32_mb_link_hash_table *htab;
2993 1.1 christos bfd *dynobj;
2994 1.1 christos asection *s;
2995 1.1 christos bfd *ibfd;
2996 1.1 christos
2997 1.1 christos htab = elf32_mb_hash_table (info);
2998 1.1 christos if (htab == NULL)
2999 1.1 christos return FALSE;
3000 1.1 christos
3001 1.1 christos dynobj = htab->elf.dynobj;
3002 1.1.1.4 christos BFD_ASSERT (dynobj != NULL);
3003 1.1 christos
3004 1.1 christos /* Set up .got offsets for local syms, and space for local dynamic
3005 1.1 christos relocs. */
3006 1.1 christos for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
3007 1.1 christos {
3008 1.1.1.2 christos bfd_signed_vma *local_got;
3009 1.1 christos bfd_signed_vma *end_local_got;
3010 1.1 christos bfd_size_type locsymcount;
3011 1.1 christos Elf_Internal_Shdr *symtab_hdr;
3012 1.1.1.7.4.1 christos unsigned char *lgot_masks;
3013 1.1 christos asection *srel;
3014 1.1 christos
3015 1.1 christos if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
3016 1.1.1.7.4.1 christos continue;
3017 1.1 christos
3018 1.1.1.7.4.1 christos for (s = ibfd->sections; s != NULL; s = s->next)
3019 1.1 christos {
3020 1.1 christos struct elf_dyn_relocs *p;
3021 1.1 christos
3022 1.1 christos for (p = ((struct elf_dyn_relocs *)
3023 1.1 christos elf_section_data (s)->local_dynrel);
3024 1.1 christos p != NULL;
3025 1.1 christos p = p->next)
3026 1.1 christos {
3027 1.1 christos if (!bfd_is_abs_section (p->sec)
3028 1.1 christos && bfd_is_abs_section (p->sec->output_section))
3029 1.1 christos {
3030 1.1 christos /* Input section has been discarded, either because
3031 1.1 christos it is a copy of a linkonce section or due to
3032 1.1 christos linker script /DISCARD/, so we'll be discarding
3033 1.1 christos the relocs too. */
3034 1.1 christos }
3035 1.1 christos else if (p->count != 0)
3036 1.1 christos {
3037 1.1 christos srel = elf_section_data (p->sec)->sreloc;
3038 1.1 christos srel->size += p->count * sizeof (Elf32_External_Rela);
3039 1.1 christos if ((p->sec->output_section->flags & SEC_READONLY) != 0)
3040 1.1 christos info->flags |= DF_TEXTREL;
3041 1.1 christos }
3042 1.1 christos }
3043 1.1.1.7.4.1 christos }
3044 1.1 christos
3045 1.1 christos local_got = elf_local_got_refcounts (ibfd);
3046 1.1 christos if (!local_got)
3047 1.1 christos continue;
3048 1.1.1.2 christos
3049 1.1.1.7 christos symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
3050 1.1.1.7 christos locsymcount = symtab_hdr->sh_info;
3051 1.1 christos end_local_got = local_got + locsymcount;
3052 1.1.1.2 christos lgot_masks = (unsigned char *) end_local_got;
3053 1.1.1.2 christos s = htab->elf.sgot;
3054 1.1.1.2 christos srel = htab->elf.srelgot;
3055 1.1.1.2 christos
3056 1.1.1.2 christos for (; local_got < end_local_got; ++local_got, ++lgot_masks)
3057 1.1.1.2 christos {
3058 1.1.1.2 christos if (*local_got > 0)
3059 1.1.1.2 christos {
3060 1.1.1.2 christos unsigned int need = 0;
3061 1.1.1.2 christos if ((*lgot_masks & TLS_TLS) != 0)
3062 1.1.1.2 christos {
3063 1.1.1.2 christos if ((*lgot_masks & TLS_GD) != 0)
3064 1.1.1.2 christos need += 8;
3065 1.1.1.2 christos if ((*lgot_masks & TLS_LD) != 0)
3066 1.1.1.2 christos htab->tlsld_got.refcount += 1;
3067 1.1.1.2 christos }
3068 1.1.1.2 christos else
3069 1.1.1.2 christos need += 4;
3070 1.1.1.2 christos
3071 1.1.1.2 christos if (need == 0)
3072 1.1.1.2 christos {
3073 1.1.1.2 christos *local_got = (bfd_vma) -1;
3074 1.1.1.2 christos }
3075 1.1.1.6 christos else
3076 1.1.1.2 christos {
3077 1.1.1.2 christos *local_got = s->size;
3078 1.1.1.7.4.1 christos s->size += need;
3079 1.1.1.7.4.1 christos if (bfd_link_pic (info))
3080 1.1.1.7.4.1 christos srel->size += need * (sizeof (Elf32_External_Rela) / 4);
3081 1.1.1.7.4.1 christos }
3082 1.1 christos }
3083 1.1 christos else
3084 1.1 christos *local_got = (bfd_vma) -1;
3085 1.1 christos }
3086 1.1 christos }
3087 1.1 christos
3088 1.1.1.2 christos /* Allocate global sym .plt and .got entries, and space for global
3089 1.1.1.2 christos sym dynamic relocs. */
3090 1.1.1.7 christos elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info);
3091 1.1.1.7 christos
3092 1.1.1.6 christos if (htab->tlsld_got.refcount > 0)
3093 1.1.1.7.4.1 christos {
3094 1.1.1.2 christos htab->tlsld_got.offset = htab->elf.sgot->size;
3095 1.1.1.2 christos htab->elf.sgot->size += 8;
3096 1.1.1.2 christos if (bfd_link_pic (info))
3097 1.1.1.2 christos htab->elf.srelgot->size += sizeof (Elf32_External_Rela);
3098 1.1 christos }
3099 1.1 christos else
3100 1.1 christos htab->tlsld_got.offset = (bfd_vma) -1;
3101 1.1.1.7 christos
3102 1.1.1.7.4.1 christos if (elf_hash_table (info)->dynamic_sections_created)
3103 1.1 christos {
3104 1.1 christos /* Make space for the trailing nop in .plt. */
3105 1.1 christos if (htab->elf.splt->size > 0)
3106 1.1 christos htab->elf.splt->size += 4;
3107 1.1 christos }
3108 1.1 christos
3109 1.1 christos /* The check_relocs and adjust_dynamic_symbol entry points have
3110 1.1 christos determined the sizes of the various dynamic sections. Allocate
3111 1.1 christos memory for them. */
3112 1.1 christos for (s = dynobj->sections; s != NULL; s = s->next)
3113 1.1 christos {
3114 1.1.1.7.4.1 christos const char *name;
3115 1.1 christos bfd_boolean strip = FALSE;
3116 1.1 christos
3117 1.1.1.7.4.1 christos if ((s->flags & SEC_LINKER_CREATED) == 0)
3118 1.1 christos continue;
3119 1.1 christos
3120 1.1 christos /* It's OK to base decisions on the section name, because none
3121 1.1.1.7.4.1 christos of the dynobj section names depend upon the input files. */
3122 1.1.1.7.4.1 christos name = bfd_get_section_name (dynobj, s);
3123 1.1.1.7.4.1 christos
3124 1.1.1.7.4.1 christos if (strncmp (name, ".rela", 5) == 0)
3125 1.1.1.7.4.1 christos {
3126 1.1.1.7.4.1 christos if (s->size == 0)
3127 1.1.1.7.4.1 christos {
3128 1.1.1.7.4.1 christos /* If we don't need this section, strip it from the
3129 1.1.1.7.4.1 christos output file. This is to handle .rela.bss and
3130 1.1.1.7.4.1 christos .rela.plt. We must create it in
3131 1.1.1.7.4.1 christos create_dynamic_sections, because it must be created
3132 1.1.1.7.4.1 christos before the linker maps input sections to output
3133 1.1.1.7.4.1 christos sections. The linker does that before
3134 1.1.1.7.4.1 christos adjust_dynamic_symbol is called, and it is that
3135 1.1.1.7.4.1 christos function which decides whether anything needs to go
3136 1.1.1.7.4.1 christos into these sections. */
3137 1.1.1.7.4.1 christos strip = TRUE;
3138 1.1.1.7.4.1 christos }
3139 1.1.1.7.4.1 christos else
3140 1.1.1.7.4.1 christos {
3141 1.1.1.7.4.1 christos /* We use the reloc_count field as a counter if we need
3142 1.1.1.7 christos to copy relocs into the output file. */
3143 1.1.1.7 christos s->reloc_count = 0;
3144 1.1.1.7 christos }
3145 1.1.1.7 christos }
3146 1.1.1.7 christos else if (s != htab->elf.splt
3147 1.1.1.7.4.1 christos && s != htab->elf.sgot
3148 1.1.1.7.4.1 christos && s != htab->elf.sgotplt
3149 1.1.1.7.4.1 christos && s != htab->elf.sdynbss
3150 1.1.1.7.4.1 christos && s != htab->elf.sdynrelro)
3151 1.1 christos {
3152 1.1 christos /* It's not one of our sections, so don't allocate space. */
3153 1.1.1.7.4.1 christos continue;
3154 1.1.1.7.4.1 christos }
3155 1.1.1.7.4.1 christos
3156 1.1.1.7.4.1 christos if (strip)
3157 1.1 christos {
3158 1.1 christos s->flags |= SEC_EXCLUDE;
3159 1.1 christos continue;
3160 1.1.1.7.4.1 christos }
3161 1.1.1.7.4.1 christos
3162 1.1.1.7.4.1 christos /* Allocate memory for the section contents. */
3163 1.1.1.7.4.1 christos /* FIXME: This should be a call to bfd_alloc not bfd_zalloc.
3164 1.1 christos Unused entries should be reclaimed before the section's contents
3165 1.1 christos are written out, but at the moment this does not happen. Thus in
3166 1.1.1.7.4.1 christos order to prevent writing out garbage, we initialise the section's
3167 1.1 christos contents to zero. */
3168 1.1 christos s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
3169 1.1 christos if (s->contents == NULL && s->size != 0)
3170 1.1 christos return FALSE;
3171 1.1 christos }
3172 1.1 christos
3173 1.1 christos if (elf_hash_table (info)->dynamic_sections_created)
3174 1.1 christos {
3175 1.1 christos /* Add some entries to the .dynamic section. We fill in the
3176 1.1 christos values later, in microblaze_elf_finish_dynamic_sections, but we
3177 1.1 christos must add the entries now so that we get the correct size for
3178 1.1 christos the .dynamic section. The DT_DEBUG entry is filled in by the
3179 1.1.1.6 christos dynamic linker and used by the debugger. */
3180 1.1.1.7.4.1 christos #define add_dynamic_entry(TAG, VAL) \
3181 1.1.1.7.4.1 christos _bfd_elf_add_dynamic_entry (info, TAG, VAL)
3182 1.1.1.7.4.1 christos
3183 1.1.1.7.4.1 christos if (bfd_link_executable (info))
3184 1.1 christos {
3185 1.1 christos if (!add_dynamic_entry (DT_DEBUG, 0))
3186 1.1.1.7.4.1 christos return FALSE;
3187 1.1.1.7.4.1 christos }
3188 1.1 christos
3189 1.1 christos if (!add_dynamic_entry (DT_RELA, 0)
3190 1.1.1.7 christos || !add_dynamic_entry (DT_RELASZ, 0)
3191 1.1.1.7.4.1 christos || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
3192 1.1.1.7.4.1 christos return FALSE;
3193 1.1.1.7.4.1 christos
3194 1.1.1.7.4.1 christos if (htab->elf.splt->size != 0)
3195 1.1.1.7.4.1 christos {
3196 1.1.1.7.4.1 christos if (!add_dynamic_entry (DT_PLTGOT, 0)
3197 1.1.1.7.4.1 christos || !add_dynamic_entry (DT_PLTRELSZ, 0)
3198 1.1.1.7.4.1 christos || !add_dynamic_entry (DT_PLTREL, DT_RELA)
3199 1.1 christos || !add_dynamic_entry (DT_JMPREL, 0)
3200 1.1 christos || !add_dynamic_entry (DT_BIND_NOW, 1))
3201 1.1.1.7.4.1 christos return FALSE;
3202 1.1.1.7.4.1 christos }
3203 1.1.1.7.4.1 christos
3204 1.1.1.7.4.1 christos if (info->flags & DF_TEXTREL)
3205 1.1 christos {
3206 1.1 christos if (!add_dynamic_entry (DT_TEXTREL, 0))
3207 1.1 christos return FALSE;
3208 1.1 christos }
3209 1.1 christos }
3210 1.1 christos #undef add_dynamic_entry
3211 1.1 christos return TRUE;
3212 1.1 christos }
3213 1.1 christos
3214 1.1 christos /* Finish up dynamic symbol handling. We set the contents of various
3215 1.1 christos dynamic sections here. */
3216 1.1 christos
3217 1.1 christos static bfd_boolean
3218 1.1 christos microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
3219 1.1 christos struct bfd_link_info *info,
3220 1.1.1.2 christos struct elf_link_hash_entry *h,
3221 1.1 christos Elf_Internal_Sym *sym)
3222 1.1 christos {
3223 1.1 christos struct elf32_mb_link_hash_table *htab;
3224 1.1 christos struct elf32_mb_link_hash_entry *eh = elf32_mb_hash_entry(h);
3225 1.1 christos
3226 1.1 christos htab = elf32_mb_hash_table (info);
3227 1.1 christos if (htab == NULL)
3228 1.1 christos return FALSE;
3229 1.1 christos
3230 1.1 christos if (h->plt.offset != (bfd_vma) -1)
3231 1.1 christos {
3232 1.1 christos asection *splt;
3233 1.1 christos asection *srela;
3234 1.1 christos asection *sgotplt;
3235 1.1 christos Elf_Internal_Rela rela;
3236 1.1 christos bfd_byte *loc;
3237 1.1 christos bfd_vma plt_index;
3238 1.1.1.7.4.1 christos bfd_vma got_offset;
3239 1.1 christos bfd_vma got_addr;
3240 1.1 christos
3241 1.1.1.7 christos /* This symbol has an entry in the procedure linkage table. Set
3242 1.1.1.7 christos it up. */
3243 1.1.1.7 christos BFD_ASSERT (h->dynindx != -1);
3244 1.1 christos
3245 1.1 christos splt = htab->elf.splt;
3246 1.1 christos srela = htab->elf.srelplt;
3247 1.1 christos sgotplt = htab->elf.sgotplt;
3248 1.1 christos BFD_ASSERT (splt != NULL && srela != NULL && sgotplt != NULL);
3249 1.1 christos
3250 1.1 christos plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; /* first entry reserved. */
3251 1.1.1.6 christos got_offset = (plt_index + 3) * 4; /* 3 reserved ??? */
3252 1.1.1.7.4.1 christos got_addr = got_offset;
3253 1.1 christos
3254 1.1 christos /* For non-PIC objects we need absolute address of the GOT entry. */
3255 1.1 christos if (!bfd_link_pic (info))
3256 1.1.1.7.4.1 christos got_addr += sgotplt->output_section->vma + sgotplt->output_offset;
3257 1.1.1.6 christos
3258 1.1.1.7.4.1 christos /* Fill in the entry in the procedure linkage table. */
3259 1.1.1.7.4.1 christos bfd_put_32 (output_bfd, PLT_ENTRY_WORD_0 + ((got_addr >> 16) & 0xffff),
3260 1.1 christos splt->contents + h->plt.offset);
3261 1.1.1.7.4.1 christos if (bfd_link_pic (info))
3262 1.1.1.7.4.1 christos bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1 + (got_addr & 0xffff),
3263 1.1 christos splt->contents + h->plt.offset + 4);
3264 1.1.1.7.4.1 christos else
3265 1.1 christos bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1_NOPIC + (got_addr & 0xffff),
3266 1.1.1.7.4.1 christos splt->contents + h->plt.offset + 4);
3267 1.1 christos bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD_2,
3268 1.1 christos splt->contents + h->plt.offset + 8);
3269 1.1 christos bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD_3,
3270 1.1 christos splt->contents + h->plt.offset + 12);
3271 1.1 christos
3272 1.1 christos /* Any additions to the .got section??? */
3273 1.1 christos /* bfd_put_32 (output_bfd,
3274 1.1 christos splt->output_section->vma + splt->output_offset + h->plt.offset + 4,
3275 1.1.1.7.4.1 christos sgotplt->contents + got_offset); */
3276 1.1.1.7.4.1 christos
3277 1.1 christos /* Fill in the entry in the .rela.plt section. */
3278 1.1 christos rela.r_offset = (sgotplt->output_section->vma
3279 1.1 christos + sgotplt->output_offset
3280 1.1 christos + got_offset);
3281 1.1 christos rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_JUMP_SLOT);
3282 1.1 christos rela.r_addend = 0;
3283 1.1 christos loc = srela->contents;
3284 1.1.1.7.4.1 christos loc += plt_index * sizeof (Elf32_External_Rela);
3285 1.1.1.7.4.1 christos bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
3286 1.1.1.7.4.1 christos
3287 1.1.1.7.4.1 christos if (!h->def_regular)
3288 1.1.1.7.4.1 christos {
3289 1.1.1.7.4.1 christos /* Mark the symbol as undefined, rather than as defined in
3290 1.1 christos the .plt section. Zero the value. */
3291 1.1 christos sym->st_shndx = SHN_UNDEF;
3292 1.1.1.2 christos sym->st_value = 0;
3293 1.1.1.2 christos }
3294 1.1.1.2 christos }
3295 1.1.1.7.4.1 christos
3296 1.1 christos /* h->got.refcount to be checked ? */
3297 1.1 christos if (h->got.offset != (bfd_vma) -1 &&
3298 1.1 christos ! ((h->got.offset & 1) ||
3299 1.1.1.2 christos IS_TLS_LD(eh->tls_mask) || IS_TLS_GD(eh->tls_mask)))
3300 1.1 christos {
3301 1.1 christos asection *sgot;
3302 1.1.1.7.4.1 christos asection *srela;
3303 1.1 christos bfd_vma offset;
3304 1.1.1.7 christos
3305 1.1.1.7 christos /* This symbol has an entry in the global offset table. Set it
3306 1.1 christos up. */
3307 1.1 christos
3308 1.1.1.2 christos sgot = htab->elf.sgot;
3309 1.1.1.6 christos srela = htab->elf.srelgot;
3310 1.1 christos BFD_ASSERT (sgot != NULL && srela != NULL);
3311 1.1 christos
3312 1.1.1.7.4.1 christos offset = (sgot->output_section->vma + sgot->output_offset
3313 1.1.1.7.4.1 christos + (h->got.offset &~ (bfd_vma) 1));
3314 1.1.1.7.4.1 christos
3315 1.1.1.7.4.1 christos /* If this is a -Bsymbolic link, and the symbol is defined
3316 1.1.1.6 christos locally, we just want to emit a RELATIVE reloc. Likewise if
3317 1.1.1.7.4.1 christos the symbol was forced to be local because of a version file.
3318 1.1.1.6 christos The entry in the global offset table will already have been
3319 1.1.1.7.4.1 christos initialized in the relocate_section function. */
3320 1.1.1.7.4.1 christos if (bfd_link_pic (info)
3321 1.1.1.7 christos && ((info->symbolic && h->def_regular)
3322 1.1.1.7 christos || h->dynindx == -1))
3323 1.1.1.7 christos {
3324 1.1.1.7 christos asection *sec = h->root.u.def.section;
3325 1.1.1.7 christos bfd_vma value;
3326 1.1.1.7 christos
3327 1.1.1.7 christos value = h->root.u.def.value;
3328 1.1.1.7 christos if (sec->output_section != NULL)
3329 1.1.1.7 christos /* PR 21180: If the output section is NULL, then the symbol is no
3330 1.1.1.7.4.1 christos longer needed, and in theory the GOT entry is redundant. But
3331 1.1.1.7.4.1 christos it is too late to change our minds now... */
3332 1.1.1.7.4.1 christos value += sec->output_section->vma + sec->output_offset;
3333 1.1.1.7.4.1 christos
3334 1.1.1.7.4.1 christos microblaze_elf_output_dynamic_relocation (output_bfd,
3335 1.1.1.7.4.1 christos srela, srela->reloc_count++,
3336 1.1 christos /* symindex= */ 0,
3337 1.1.1.7.4.1 christos R_MICROBLAZE_REL, offset,
3338 1.1.1.7.4.1 christos value);
3339 1.1.1.7.4.1 christos }
3340 1.1.1.7.4.1 christos else
3341 1.1.1.7.4.1 christos {
3342 1.1.1.7.4.1 christos microblaze_elf_output_dynamic_relocation (output_bfd,
3343 1.1.1.7.4.1 christos srela, srela->reloc_count++,
3344 1.1 christos h->dynindx,
3345 1.1 christos R_MICROBLAZE_GLOB_DAT,
3346 1.1.1.7.4.1 christos offset, 0);
3347 1.1 christos }
3348 1.1 christos
3349 1.1 christos bfd_put_32 (output_bfd, (bfd_vma) 0,
3350 1.1 christos sgot->contents + (h->got.offset &~ (bfd_vma) 1));
3351 1.1 christos }
3352 1.1 christos
3353 1.1 christos if (h->needs_copy)
3354 1.1 christos {
3355 1.1 christos asection *s;
3356 1.1 christos Elf_Internal_Rela rela;
3357 1.1 christos bfd_byte *loc;
3358 1.1 christos
3359 1.1 christos /* This symbols needs a copy reloc. Set it up. */
3360 1.1.1.7.4.1 christos
3361 1.1.1.7.4.1 christos BFD_ASSERT (h->dynindx != -1);
3362 1.1 christos
3363 1.1 christos rela.r_offset = (h->root.u.def.value
3364 1.1.1.7 christos + h->root.u.def.section->output_section->vma
3365 1.1.1.7 christos + h->root.u.def.section->output_offset);
3366 1.1.1.7 christos rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_COPY);
3367 1.1.1.7 christos rela.r_addend = 0;
3368 1.1 christos if (h->root.u.def.section == htab->elf.sdynrelro)
3369 1.1 christos s = htab->elf.sreldynrelro;
3370 1.1 christos else
3371 1.1 christos s = htab->elf.srelbss;
3372 1.1 christos loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
3373 1.1.1.2 christos bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
3374 1.1.1.2 christos }
3375 1.1.1.2 christos
3376 1.1 christos /* Mark some specially defined symbols as absolute. */
3377 1.1 christos if (h == htab->elf.hdynamic
3378 1.1 christos || h == htab->elf.hgot
3379 1.1 christos || h == htab->elf.hplt)
3380 1.1 christos sym->st_shndx = SHN_ABS;
3381 1.1 christos
3382 1.1 christos return TRUE;
3383 1.1 christos }
3384 1.1 christos
3385 1.1 christos
3386 1.1 christos /* Finish up the dynamic sections. */
3387 1.1 christos
3388 1.1 christos static bfd_boolean
3389 1.1 christos microblaze_elf_finish_dynamic_sections (bfd *output_bfd,
3390 1.1 christos struct bfd_link_info *info)
3391 1.1 christos {
3392 1.1 christos bfd *dynobj;
3393 1.1 christos asection *sdyn, *sgot;
3394 1.1 christos struct elf32_mb_link_hash_table *htab;
3395 1.1 christos
3396 1.1 christos htab = elf32_mb_hash_table (info);
3397 1.1 christos if (htab == NULL)
3398 1.1.1.2 christos return FALSE;
3399 1.1 christos
3400 1.1 christos dynobj = htab->elf.dynobj;
3401 1.1 christos
3402 1.1 christos sdyn = bfd_get_linker_section (dynobj, ".dynamic");
3403 1.1 christos
3404 1.1 christos if (htab->elf.dynamic_sections_created)
3405 1.1 christos {
3406 1.1 christos asection *splt;
3407 1.1 christos Elf32_External_Dyn *dyncon, *dynconend;
3408 1.1.1.7.4.1 christos
3409 1.1.1.7.4.1 christos dyncon = (Elf32_External_Dyn *) sdyn->contents;
3410 1.1.1.7 christos dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
3411 1.1.1.7.4.1 christos for (; dyncon < dynconend; dyncon++)
3412 1.1 christos {
3413 1.1.1.7.4.1 christos Elf_Internal_Dyn dyn;
3414 1.1 christos asection *s;
3415 1.1.1.7.4.1 christos bfd_boolean size;
3416 1.1.1.7.4.1 christos
3417 1.1.1.7 christos bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
3418 1.1.1.7 christos
3419 1.1.1.7 christos switch (dyn.d_tag)
3420 1.1.1.7 christos {
3421 1.1 christos case DT_PLTGOT:
3422 1.1.1.7 christos s = htab->elf.sgotplt;
3423 1.1.1.7 christos size = FALSE;
3424 1.1.1.7 christos break;
3425 1.1.1.7 christos
3426 1.1 christos case DT_PLTRELSZ:
3427 1.1.1.7 christos s = htab->elf.srelplt;
3428 1.1.1.7 christos size = TRUE;
3429 1.1.1.7 christos break;
3430 1.1.1.7 christos
3431 1.1.1.7 christos case DT_JMPREL:
3432 1.1.1.7 christos s = htab->elf.srelplt;
3433 1.1.1.7 christos size = FALSE;
3434 1.1.1.7.4.1 christos break;
3435 1.1.1.7 christos
3436 1.1.1.7 christos default:
3437 1.1.1.7 christos continue;
3438 1.1.1.7 christos }
3439 1.1.1.7 christos
3440 1.1.1.7 christos if (s == NULL)
3441 1.1.1.7 christos dyn.d_un.d_val = 0;
3442 1.1.1.7 christos else
3443 1.1.1.7 christos {
3444 1.1.1.7 christos if (!size)
3445 1.1.1.7 christos dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
3446 1.1.1.7.4.1 christos else
3447 1.1 christos dyn.d_un.d_val = s->size;
3448 1.1.1.7 christos }
3449 1.1.1.7 christos bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
3450 1.1.1.7 christos }
3451 1.1 christos
3452 1.1 christos splt = htab->elf.splt;
3453 1.1 christos BFD_ASSERT (splt != NULL && sdyn != NULL);
3454 1.1.1.7.4.1 christos
3455 1.1.1.7.4.1 christos /* Clear the first entry in the procedure linkage table,
3456 1.1.1.7.4.1 christos and put a nop in the last four bytes. */
3457 1.1.1.7.4.1 christos if (splt->size > 0)
3458 1.1.1.7.4.1 christos {
3459 1.1 christos memset (splt->contents, 0, PLT_ENTRY_SIZE);
3460 1.1 christos bfd_put_32 (output_bfd, (bfd_vma) 0x80000000 /* nop. */,
3461 1.1 christos splt->contents + splt->size - 4);
3462 1.1 christos }
3463 1.1 christos
3464 1.1 christos elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
3465 1.1.1.7 christos }
3466 1.1 christos
3467 1.1 christos /* Set the first entry in the global offset table to the address of
3468 1.1 christos the dynamic section. */
3469 1.1.1.7.4.1 christos sgot = htab->elf.sgotplt;
3470 1.1 christos if (sgot && sgot->size > 0)
3471 1.1.1.7.4.1 christos {
3472 1.1.1.7.4.1 christos if (sdyn == NULL)
3473 1.1.1.7.4.1 christos bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
3474 1.1 christos else
3475 1.1 christos bfd_put_32 (output_bfd,
3476 1.1 christos sdyn->output_section->vma + sdyn->output_offset,
3477 1.1.1.7 christos sgot->contents);
3478 1.1.1.7 christos elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
3479 1.1 christos }
3480 1.1 christos
3481 1.1 christos if (htab->elf.sgot && htab->elf.sgot->size > 0)
3482 1.1 christos elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4;
3483 1.1 christos
3484 1.1 christos return TRUE;
3485 1.1 christos }
3486 1.1 christos
3487 1.1 christos /* Hook called by the linker routine which adds symbols from an object
3488 1.1.1.7.4.1 christos file. We use it to put .comm items in .sbss, and not .bss. */
3489 1.1.1.7.4.1 christos
3490 1.1.1.7.4.1 christos static bfd_boolean
3491 1.1.1.7.4.1 christos microblaze_elf_add_symbol_hook (bfd *abfd,
3492 1.1.1.7.4.1 christos struct bfd_link_info *info,
3493 1.1.1.7.4.1 christos Elf_Internal_Sym *sym,
3494 1.1 christos const char **namep ATTRIBUTE_UNUSED,
3495 1.1 christos flagword *flagsp ATTRIBUTE_UNUSED,
3496 1.1.1.6 christos asection **secp,
3497 1.1 christos bfd_vma *valp)
3498 1.1 christos {
3499 1.1 christos if (sym->st_shndx == SHN_COMMON
3500 1.1 christos && !bfd_link_relocatable (info)
3501 1.1.1.2 christos && sym->st_size <= elf_gp_size (abfd))
3502 1.1 christos {
3503 1.1.1.7.4.1 christos /* Common symbols less than or equal to -G nn bytes are automatically
3504 1.1.1.7.4.1 christos put into .sbss. */
3505 1.1 christos *secp = bfd_make_section_old_way (abfd, ".sbss");
3506 1.1 christos if (*secp == NULL
3507 1.1 christos || ! bfd_set_section_flags (abfd, *secp, SEC_IS_COMMON))
3508 1.1 christos return FALSE;
3509 1.1 christos
3510 1.1 christos *valp = sym->st_size;
3511 1.1 christos }
3512 1.1.1.4 christos
3513 1.1.1.2 christos return TRUE;
3514 1.1 christos }
3515 1.1.1.7.4.1 christos
3516 1.1 christos #define TARGET_LITTLE_SYM microblaze_elf32_le_vec
3517 1.1 christos #define TARGET_LITTLE_NAME "elf32-microblazeel"
3518 1.1 christos
3519 1.1 christos #define TARGET_BIG_SYM microblaze_elf32_vec
3520 1.1 christos #define TARGET_BIG_NAME "elf32-microblaze"
3521 1.1 christos
3522 1.1.1.2 christos #define ELF_ARCH bfd_arch_microblaze
3523 1.1 christos #define ELF_TARGET_ID MICROBLAZE_ELF_DATA
3524 1.1 christos #define ELF_MACHINE_CODE EM_MICROBLAZE
3525 1.1 christos #define ELF_MACHINE_ALT1 EM_MICROBLAZE_OLD
3526 1.1 christos #define ELF_MAXPAGESIZE 0x1000
3527 1.1.1.7.4.1 christos #define elf_info_to_howto microblaze_elf_info_to_howto
3528 1.1 christos #define elf_info_to_howto_rel NULL
3529 1.1.1.7.4.1 christos
3530 1.1.1.7.4.1 christos #define bfd_elf32_bfd_reloc_type_lookup microblaze_elf_reloc_type_lookup
3531 1.1 christos #define bfd_elf32_bfd_is_local_label_name microblaze_elf_is_local_label_name
3532 1.1 christos #define elf_backend_relocate_section microblaze_elf_relocate_section
3533 1.1 christos #define bfd_elf32_bfd_relax_section microblaze_elf_relax_section
3534 1.1.1.7.4.1 christos #define bfd_elf32_bfd_merge_private_bfd_data _bfd_generic_verify_endian_match
3535 1.1.1.7.4.1 christos #define bfd_elf32_bfd_reloc_name_lookup microblaze_elf_reloc_name_lookup
3536 1.1.1.7.4.1 christos
3537 1.1 christos #define elf_backend_gc_mark_hook microblaze_elf_gc_mark_hook
3538 1.1.1.7.4.1 christos #define elf_backend_check_relocs microblaze_elf_check_relocs
3539 1.1.1.7.4.1 christos #define elf_backend_copy_indirect_symbol microblaze_elf_copy_indirect_symbol
3540 1.1.1.7.4.1 christos #define bfd_elf32_bfd_link_hash_table_create microblaze_elf_link_hash_table_create
3541 1.1.1.7.4.1 christos #define elf_backend_can_gc_sections 1
3542 1.1.1.7 christos #define elf_backend_can_refcount 1
3543 1.1.1.7.4.1 christos #define elf_backend_want_got_plt 1
3544 1.1.1.7 christos #define elf_backend_plt_readonly 1
3545 1.1 christos #define elf_backend_got_header_size 12
3546 1.1.1.7.4.1 christos #define elf_backend_want_dynrelro 1
3547 1.1.1.7.4.1 christos #define elf_backend_rela_normal 1
3548 1.1.1.7.4.1 christos #define elf_backend_dtrel_excludes_plt 1
3549 1.1.1.7.4.1 christos
3550 1.1.1.7.4.1 christos #define elf_backend_adjust_dynamic_symbol microblaze_elf_adjust_dynamic_symbol
3551 1.1 christos #define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
3552 1.1 christos #define elf_backend_finish_dynamic_sections microblaze_elf_finish_dynamic_sections
3553 1.1 christos #define elf_backend_finish_dynamic_symbol microblaze_elf_finish_dynamic_symbol
3554 #define elf_backend_size_dynamic_sections microblaze_elf_size_dynamic_sections
3555 #define elf_backend_add_symbol_hook microblaze_elf_add_symbol_hook
3556
3557 #include "elf32-target.h"
3558