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