1377e23a2Schristos /* Xilinx MicroBlaze-specific support for 32-bit ELF
2377e23a2Schristos 
3*1424dfb3Schristos    Copyright (C) 2009-2020 Free Software Foundation, Inc.
4377e23a2Schristos 
5377e23a2Schristos    This file is part of BFD, the Binary File Descriptor library.
6377e23a2Schristos 
7377e23a2Schristos    This program is free software; you can redistribute it and/or modify
8377e23a2Schristos    it under the terms of the GNU General Public License as published by
9377e23a2Schristos    the Free Software Foundation; either version 3 of the License, or
10377e23a2Schristos    (at your option) any later version.
11377e23a2Schristos 
12377e23a2Schristos    This program is distributed in the hope that it will be useful,
13377e23a2Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
14377e23a2Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15377e23a2Schristos    GNU General Public License for more details.
16377e23a2Schristos 
17377e23a2Schristos    You should have received a copy of the GNU General Public License
18377e23a2Schristos    along with this program; if not, write to the
19377e23a2Schristos    Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20377e23a2Schristos    Boston, MA 02110-1301, USA.  */
21377e23a2Schristos 
22377e23a2Schristos 
23377e23a2Schristos int dbg = 0;
24377e23a2Schristos 
25377e23a2Schristos #include "sysdep.h"
2648596154Schristos #include "bfd.h"
27377e23a2Schristos #include "bfdlink.h"
28377e23a2Schristos #include "libbfd.h"
29377e23a2Schristos #include "elf-bfd.h"
30377e23a2Schristos #include "elf/microblaze.h"
31377e23a2Schristos #include <assert.h>
32377e23a2Schristos 
33377e23a2Schristos #define	USE_RELA	/* Only USE_REL is actually significant, but this is
34377e23a2Schristos 			   here are a reminder...  */
35377e23a2Schristos #define INST_WORD_SIZE 4
36377e23a2Schristos 
37377e23a2Schristos static int ro_small_data_pointer = 0;
38377e23a2Schristos static int rw_small_data_pointer = 0;
39377e23a2Schristos 
40377e23a2Schristos static reloc_howto_type * microblaze_elf_howto_table [(int) R_MICROBLAZE_max];
41377e23a2Schristos 
42377e23a2Schristos static reloc_howto_type microblaze_elf_howto_raw[] =
43377e23a2Schristos {
44377e23a2Schristos    /* This reloc does nothing.  */
45377e23a2Schristos    HOWTO (R_MICROBLAZE_NONE,	/* Type.  */
46377e23a2Schristos 	  0,			/* Rightshift.  */
47ed6a76a9Schristos 	  3,			/* Size (0 = byte, 1 = short, 2 = long).  */
48ed6a76a9Schristos 	  0,			/* Bitsize.  */
49377e23a2Schristos 	  FALSE,		/* PC_relative.  */
50377e23a2Schristos 	  0,			/* Bitpos.  */
51ed6a76a9Schristos 	  complain_overflow_dont,  /* Complain on overflow.  */
52377e23a2Schristos 	  NULL,			 /* Special Function.  */
53377e23a2Schristos 	  "R_MICROBLAZE_NONE",	/* Name.  */
54377e23a2Schristos 	  FALSE,		/* Partial Inplace.  */
55377e23a2Schristos 	  0,			/* Source Mask.  */
56377e23a2Schristos 	  0,			/* Dest Mask.  */
57377e23a2Schristos 	  FALSE),		/* PC relative offset?  */
58377e23a2Schristos 
59377e23a2Schristos    /* A standard 32 bit relocation.  */
60377e23a2Schristos    HOWTO (R_MICROBLAZE_32,	/* Type.  */
61377e23a2Schristos 	  0,			/* Rightshift.  */
62377e23a2Schristos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
63377e23a2Schristos 	  32,			/* Bitsize.  */
64377e23a2Schristos 	  FALSE,		/* PC_relative.  */
65377e23a2Schristos 	  0,			/* Bitpos.  */
66377e23a2Schristos 	  complain_overflow_bitfield, /* Complain on overflow.  */
67377e23a2Schristos 	  bfd_elf_generic_reloc,/* Special Function.  */
68377e23a2Schristos 	  "R_MICROBLAZE_32",	/* Name.  */
69377e23a2Schristos 	  FALSE,		/* Partial Inplace.  */
70377e23a2Schristos 	  0,			/* Source Mask.  */
71377e23a2Schristos 	  0xffffffff,		/* Dest Mask.  */
72377e23a2Schristos 	  FALSE),		/* PC relative offset?  */
73377e23a2Schristos 
74377e23a2Schristos    /* A standard PCREL 32 bit relocation.  */
75377e23a2Schristos    HOWTO (R_MICROBLAZE_32_PCREL,/* Type.  */
76377e23a2Schristos 	  0,			/* Rightshift.  */
77377e23a2Schristos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
78377e23a2Schristos 	  32,			/* Bitsize.  */
79377e23a2Schristos 	  TRUE,			/* PC_relative.  */
80377e23a2Schristos 	  0,			/* Bitpos.  */
81377e23a2Schristos 	  complain_overflow_bitfield, /* Complain on overflow.  */
82377e23a2Schristos 	  bfd_elf_generic_reloc,/* Special Function.  */
83377e23a2Schristos 	  "R_MICROBLAZE_32_PCREL",	/* Name.  */
84377e23a2Schristos 	  TRUE,			/* Partial Inplace.  */
85377e23a2Schristos 	  0,			/* Source Mask.  */
86377e23a2Schristos 	  0xffffffff,		/* Dest Mask.  */
87377e23a2Schristos 	  TRUE),		/* PC relative offset?  */
88377e23a2Schristos 
89377e23a2Schristos    /* A 64 bit PCREL relocation.  Table-entry not really used.  */
90377e23a2Schristos    HOWTO (R_MICROBLAZE_64_PCREL,/* Type.  */
91377e23a2Schristos 	  0,			/* Rightshift.  */
92377e23a2Schristos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
93377e23a2Schristos 	  16,			/* Bitsize.  */
94377e23a2Schristos 	  TRUE,			/* PC_relative.  */
95377e23a2Schristos 	  0,			/* Bitpos.  */
96377e23a2Schristos 	  complain_overflow_dont, /* Complain on overflow.  */
97377e23a2Schristos 	  bfd_elf_generic_reloc,/* Special Function.  */
98377e23a2Schristos 	  "R_MICROBLAZE_64_PCREL",	/* Name.  */
99377e23a2Schristos 	  FALSE,		/* Partial Inplace.  */
100377e23a2Schristos 	  0,			/* Source Mask.  */
101377e23a2Schristos 	  0x0000ffff,		/* Dest Mask.  */
102377e23a2Schristos 	  TRUE),		/* PC relative offset?  */
103377e23a2Schristos 
104377e23a2Schristos    /* The low half of a PCREL 32 bit relocation.  */
105377e23a2Schristos    HOWTO (R_MICROBLAZE_32_PCREL_LO,	/* Type.  */
106377e23a2Schristos 	  0,			/* Rightshift.  */
107377e23a2Schristos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
108377e23a2Schristos 	  16,			/* Bitsize.  */
109377e23a2Schristos 	  TRUE,			/* PC_relative.  */
110377e23a2Schristos 	  0,			/* Bitpos.  */
111377e23a2Schristos 	  complain_overflow_signed, /* Complain on overflow.  */
112377e23a2Schristos 	  bfd_elf_generic_reloc,	/* Special Function.  */
113377e23a2Schristos 	  "R_MICROBLAZE_32_PCREL_LO",	/* Name.  */
114377e23a2Schristos 	  FALSE,		/* Partial Inplace.  */
115377e23a2Schristos 	  0,			/* Source Mask.  */
116377e23a2Schristos 	  0x0000ffff,		/* Dest Mask.  */
117377e23a2Schristos 	  TRUE),		/* PC relative offset?  */
118377e23a2Schristos 
119377e23a2Schristos    /* A 64 bit relocation.  Table entry not really used.  */
120377e23a2Schristos    HOWTO (R_MICROBLAZE_64,	/* Type.  */
121377e23a2Schristos 	  0,			/* Rightshift.  */
122377e23a2Schristos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
123377e23a2Schristos 	  16,			/* Bitsize.  */
124377e23a2Schristos 	  FALSE,		/* PC_relative.  */
125377e23a2Schristos 	  0,			/* Bitpos.  */
126377e23a2Schristos 	  complain_overflow_dont, /* Complain on overflow.  */
127377e23a2Schristos 	  bfd_elf_generic_reloc,/* Special Function.  */
128377e23a2Schristos 	  "R_MICROBLAZE_64",	/* Name.  */
129377e23a2Schristos 	  FALSE,		/* Partial Inplace.  */
130377e23a2Schristos 	  0,			/* Source Mask.  */
131377e23a2Schristos 	  0x0000ffff,		/* Dest Mask.  */
132377e23a2Schristos 	  FALSE),		/* PC relative offset?  */
133377e23a2Schristos 
134377e23a2Schristos    /* The low half of a 32 bit relocation.  */
135377e23a2Schristos    HOWTO (R_MICROBLAZE_32_LO,	/* Type.  */
136377e23a2Schristos 	  0,			/* Rightshift.  */
137377e23a2Schristos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
138377e23a2Schristos 	  16,			/* Bitsize.  */
139377e23a2Schristos 	  FALSE,		/* PC_relative.  */
140377e23a2Schristos 	  0,			/* Bitpos.  */
141377e23a2Schristos 	  complain_overflow_signed, /* Complain on overflow.  */
142377e23a2Schristos 	  bfd_elf_generic_reloc,/* Special Function.  */
143377e23a2Schristos 	  "R_MICROBLAZE_32_LO", /* Name.  */
144377e23a2Schristos 	  FALSE,		/* Partial Inplace.  */
145377e23a2Schristos 	  0,			/* Source Mask.  */
146377e23a2Schristos 	  0x0000ffff,		/* Dest Mask.  */
147377e23a2Schristos 	  FALSE),		/* PC relative offset?  */
148377e23a2Schristos 
149377e23a2Schristos    /* Read-only small data section relocation.  */
150377e23a2Schristos    HOWTO (R_MICROBLAZE_SRO32,	/* Type.  */
151377e23a2Schristos 	  0,			/* Rightshift.  */
152377e23a2Schristos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
153377e23a2Schristos 	  16,			/* Bitsize.  */
154377e23a2Schristos 	  FALSE,		/* PC_relative.  */
155377e23a2Schristos 	  0,			/* Bitpos.  */
156377e23a2Schristos 	  complain_overflow_bitfield, /* Complain on overflow.  */
157377e23a2Schristos 	  bfd_elf_generic_reloc,/* Special Function.  */
158377e23a2Schristos 	  "R_MICROBLAZE_SRO32", /* Name.  */
159377e23a2Schristos 	  FALSE,		/* Partial Inplace.  */
160377e23a2Schristos 	  0,			/* Source Mask.  */
161377e23a2Schristos 	  0x0000ffff,		/* Dest Mask.  */
162377e23a2Schristos 	  FALSE),		/* PC relative offset?  */
163377e23a2Schristos 
164377e23a2Schristos    /* Read-write small data area relocation.  */
165377e23a2Schristos    HOWTO (R_MICROBLAZE_SRW32,	/* Type.  */
166377e23a2Schristos 	  0,			/* Rightshift.  */
167377e23a2Schristos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
168377e23a2Schristos 	  16,			/* Bitsize.  */
169377e23a2Schristos 	  FALSE,		/* PC_relative.  */
170377e23a2Schristos 	  0,			/* Bitpos.  */
171377e23a2Schristos 	  complain_overflow_bitfield, /* Complain on overflow.  */
172377e23a2Schristos 	  bfd_elf_generic_reloc,/* Special Function.  */
173377e23a2Schristos 	  "R_MICROBLAZE_SRW32", /* Name.  */
174377e23a2Schristos 	  FALSE,		/* Partial Inplace.  */
175377e23a2Schristos 	  0,			/* Source Mask.  */
176377e23a2Schristos 	  0x0000ffff,		/* Dest Mask.  */
177377e23a2Schristos 	  FALSE),		/* PC relative offset?  */
178377e23a2Schristos 
179377e23a2Schristos    /* This reloc does nothing.	Used for relaxation.  */
180377e23a2Schristos    HOWTO (R_MICROBLAZE_64_NONE,	/* Type.  */
181377e23a2Schristos 	  0,			/* Rightshift.  */
182ed6a76a9Schristos 	  3,			/* Size (0 = byte, 1 = short, 2 = long).  */
183ed6a76a9Schristos 	  0,			/* Bitsize.  */
184377e23a2Schristos 	  TRUE,			/* PC_relative.  */
185377e23a2Schristos 	  0,			/* Bitpos.  */
186ed6a76a9Schristos 	  complain_overflow_dont, /* Complain on overflow.  */
187377e23a2Schristos 	  NULL,			 /* Special Function.  */
188377e23a2Schristos 	  "R_MICROBLAZE_64_NONE",/* Name.  */
189377e23a2Schristos 	  FALSE,		/* Partial Inplace.  */
190377e23a2Schristos 	  0,			/* Source Mask.  */
191377e23a2Schristos 	  0,			/* Dest Mask.  */
192377e23a2Schristos 	  FALSE),		/* PC relative offset?  */
193377e23a2Schristos 
194377e23a2Schristos    /* Symbol Op Symbol relocation.  */
195377e23a2Schristos    HOWTO (R_MICROBLAZE_32_SYM_OP_SYM,		/* Type.  */
196377e23a2Schristos 	  0,			/* Rightshift.  */
197377e23a2Schristos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
198377e23a2Schristos 	  32,			/* Bitsize.  */
199377e23a2Schristos 	  FALSE,		/* PC_relative.  */
200377e23a2Schristos 	  0,			/* Bitpos.  */
201377e23a2Schristos 	  complain_overflow_bitfield, /* Complain on overflow.  */
202377e23a2Schristos 	  bfd_elf_generic_reloc,/* Special Function.  */
203377e23a2Schristos 	  "R_MICROBLAZE_32_SYM_OP_SYM",		/* Name.  */
204377e23a2Schristos 	  FALSE,		/* Partial Inplace.  */
205377e23a2Schristos 	  0,			/* Source Mask.  */
206377e23a2Schristos 	  0xffffffff,		/* Dest Mask.  */
207377e23a2Schristos 	  FALSE),		/* PC relative offset?  */
208377e23a2Schristos 
209377e23a2Schristos    /* GNU extension to record C++ vtable hierarchy.  */
210377e23a2Schristos    HOWTO (R_MICROBLAZE_GNU_VTINHERIT, /* Type.  */
211377e23a2Schristos 	  0,			 /* Rightshift.  */
212377e23a2Schristos 	  2,			 /* Size (0 = byte, 1 = short, 2 = long).  */
213377e23a2Schristos 	  0,			 /* Bitsize.  */
214377e23a2Schristos 	  FALSE,		 /* PC_relative.  */
215377e23a2Schristos 	  0,			 /* Bitpos.  */
216377e23a2Schristos 	  complain_overflow_dont,/* Complain on overflow.  */
217377e23a2Schristos 	  NULL,			 /* Special Function.  */
218377e23a2Schristos 	  "R_MICROBLAZE_GNU_VTINHERIT", /* Name.  */
219377e23a2Schristos 	  FALSE,		 /* Partial Inplace.  */
220377e23a2Schristos 	  0,			 /* Source Mask.  */
221377e23a2Schristos 	  0,			 /* Dest Mask.  */
222377e23a2Schristos 	  FALSE),		 /* PC relative offset?  */
223377e23a2Schristos 
224377e23a2Schristos    /* GNU extension to record C++ vtable member usage.  */
225377e23a2Schristos    HOWTO (R_MICROBLAZE_GNU_VTENTRY,   /* Type.  */
226377e23a2Schristos 	  0,			 /* Rightshift.  */
227377e23a2Schristos 	  2,			 /* Size (0 = byte, 1 = short, 2 = long).  */
228377e23a2Schristos 	  0,			 /* Bitsize.  */
229377e23a2Schristos 	  FALSE,		 /* PC_relative.  */
230377e23a2Schristos 	  0,			 /* Bitpos.  */
231377e23a2Schristos 	  complain_overflow_dont,/* Complain on overflow.  */
232377e23a2Schristos 	  _bfd_elf_rel_vtable_reloc_fn,	 /* Special Function.  */
233377e23a2Schristos 	  "R_MICROBLAZE_GNU_VTENTRY", /* Name.  */
234377e23a2Schristos 	  FALSE,		 /* Partial Inplace.  */
235377e23a2Schristos 	  0,			 /* Source Mask.  */
236377e23a2Schristos 	  0,			 /* Dest Mask.  */
237377e23a2Schristos 	  FALSE),		 /* PC relative offset?  */
238377e23a2Schristos 
239377e23a2Schristos    /* A 64 bit GOTPC relocation.  Table-entry not really used.  */
240377e23a2Schristos    HOWTO (R_MICROBLAZE_GOTPC_64,	/* Type.  */
241377e23a2Schristos 	  0,			/* Rightshift.  */
242377e23a2Schristos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
243377e23a2Schristos 	  16,			/* Bitsize.  */
244377e23a2Schristos 	  TRUE,			/* PC_relative.  */
245377e23a2Schristos 	  0,			/* Bitpos.  */
246377e23a2Schristos 	  complain_overflow_dont, /* Complain on overflow.  */
247377e23a2Schristos 	  bfd_elf_generic_reloc,	/* Special Function.  */
248377e23a2Schristos 	  "R_MICROBLAZE_GOTPC_64",	/* Name.  */
249377e23a2Schristos 	  FALSE,		/* Partial Inplace.  */
250377e23a2Schristos 	  0,			/* Source Mask.  */
251377e23a2Schristos 	  0x0000ffff,		/* Dest Mask.  */
252377e23a2Schristos 	  TRUE),		/* PC relative offset?  */
253377e23a2Schristos 
25407163879Schristos      /* A 64 bit TEXTPCREL relocation.  Table-entry not really used.  */
25507163879Schristos    HOWTO (R_MICROBLAZE_TEXTPCREL_64,	/* Type.  */
25607163879Schristos 	  0,			/* Rightshift.  */
25707163879Schristos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
25807163879Schristos 	  16,			/* Bitsize.  */
25907163879Schristos 	  TRUE,			/* PC_relative.  */
26007163879Schristos 	  0,			/* Bitpos.  */
26107163879Schristos 	  complain_overflow_dont, /* Complain on overflow.  */
26207163879Schristos 	  bfd_elf_generic_reloc,	/* Special Function.  */
26307163879Schristos 	  "R_MICROBLAZE_TEXTPCREL_64",	/* Name.  */
26407163879Schristos 	  FALSE,		/* Partial Inplace.  */
26507163879Schristos 	  0,			/* Source Mask.  */
26607163879Schristos 	  0x0000ffff,		/* Dest Mask.  */
26707163879Schristos 	  TRUE),		/* PC relative offset?  */
26807163879Schristos 
269377e23a2Schristos    /* A 64 bit GOT relocation.  Table-entry not really used.  */
270377e23a2Schristos    HOWTO (R_MICROBLAZE_GOT_64,  /* Type.  */
271377e23a2Schristos 	  0,			/* Rightshift.  */
272377e23a2Schristos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
273377e23a2Schristos 	  16,			/* Bitsize.  */
274377e23a2Schristos 	  FALSE,		/* PC_relative.  */
275377e23a2Schristos 	  0,			/* Bitpos.  */
276377e23a2Schristos 	  complain_overflow_dont, /* Complain on overflow.  */
277377e23a2Schristos 	  bfd_elf_generic_reloc,/* Special Function.  */
278377e23a2Schristos 	  "R_MICROBLAZE_GOT_64",/* Name.  */
279377e23a2Schristos 	  FALSE,		/* Partial Inplace.  */
280377e23a2Schristos 	  0,			/* Source Mask.  */
281377e23a2Schristos 	  0x0000ffff,		/* Dest Mask.  */
282377e23a2Schristos 	  FALSE),		/* PC relative offset?  */
283377e23a2Schristos 
28407163879Schristos     /* A 64 bit TEXTREL relocation.  Table-entry not really used.  */
28507163879Schristos    HOWTO (R_MICROBLAZE_TEXTREL_64,  /* Type.  */
28607163879Schristos 	  0,			/* Rightshift.  */
28707163879Schristos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
28807163879Schristos 	  16,			/* Bitsize.  */
28907163879Schristos 	  FALSE,		/* PC_relative.  */
29007163879Schristos 	  0,			/* Bitpos.  */
29107163879Schristos 	  complain_overflow_dont, /* Complain on overflow.  */
29207163879Schristos 	  bfd_elf_generic_reloc,/* Special Function.  */
29307163879Schristos 	  "R_MICROBLAZE_TEXTREL_64",/* Name.  */
29407163879Schristos 	  FALSE,		/* Partial Inplace.  */
29507163879Schristos 	  0,			/* Source Mask.  */
29607163879Schristos 	  0x0000ffff,		/* Dest Mask.  */
29707163879Schristos 	  FALSE),		/* PC relative offset?  */
29807163879Schristos 
299377e23a2Schristos    /* A 64 bit PLT relocation.  Table-entry not really used.  */
300377e23a2Schristos    HOWTO (R_MICROBLAZE_PLT_64,  /* Type.  */
301377e23a2Schristos 	  0,			/* Rightshift.  */
302377e23a2Schristos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
303377e23a2Schristos 	  16,			/* Bitsize.  */
304377e23a2Schristos 	  TRUE,			/* PC_relative.  */
305377e23a2Schristos 	  0,			/* Bitpos.  */
306377e23a2Schristos 	  complain_overflow_dont, /* Complain on overflow.  */
307377e23a2Schristos 	  bfd_elf_generic_reloc,/* Special Function.  */
308377e23a2Schristos 	  "R_MICROBLAZE_PLT_64",/* Name.  */
309377e23a2Schristos 	  FALSE,		/* Partial Inplace.  */
310377e23a2Schristos 	  0,			/* Source Mask.  */
311377e23a2Schristos 	  0x0000ffff,		/* Dest Mask.  */
312377e23a2Schristos 	  TRUE),		/* PC relative offset?  */
313377e23a2Schristos 
314377e23a2Schristos    /*  Table-entry not really used.  */
315377e23a2Schristos    HOWTO (R_MICROBLAZE_REL,	/* Type.  */
316377e23a2Schristos 	  0,			/* Rightshift.  */
317377e23a2Schristos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
318377e23a2Schristos 	  16,			/* Bitsize.  */
319377e23a2Schristos 	  TRUE,			/* PC_relative.  */
320377e23a2Schristos 	  0,			/* Bitpos.  */
321377e23a2Schristos 	  complain_overflow_dont, /* Complain on overflow.  */
322377e23a2Schristos 	  bfd_elf_generic_reloc,/* Special Function.  */
323377e23a2Schristos 	  "R_MICROBLAZE_REL",	/* Name.  */
324377e23a2Schristos 	  FALSE,		/* Partial Inplace.  */
325377e23a2Schristos 	  0,			/* Source Mask.  */
326377e23a2Schristos 	  0x0000ffff,		/* Dest Mask.  */
327377e23a2Schristos 	  TRUE),		/* PC relative offset?  */
328377e23a2Schristos 
329377e23a2Schristos    /*  Table-entry not really used.  */
330377e23a2Schristos    HOWTO (R_MICROBLAZE_JUMP_SLOT,/* Type.  */
331377e23a2Schristos 	  0,			/* Rightshift.  */
332377e23a2Schristos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
333377e23a2Schristos 	  16,			/* Bitsize.  */
334377e23a2Schristos 	  TRUE,			/* PC_relative.  */
335377e23a2Schristos 	  0,			/* Bitpos.  */
336377e23a2Schristos 	  complain_overflow_dont, /* Complain on overflow.  */
337377e23a2Schristos 	  bfd_elf_generic_reloc,/* Special Function.  */
338377e23a2Schristos 	  "R_MICROBLAZE_JUMP_SLOT",	/* Name.  */
339377e23a2Schristos 	  FALSE,		/* Partial Inplace.  */
340377e23a2Schristos 	  0,			/* Source Mask.  */
341377e23a2Schristos 	  0x0000ffff,		/* Dest Mask.  */
342377e23a2Schristos 	  TRUE),		/* PC relative offset?  */
343377e23a2Schristos 
344377e23a2Schristos    /*  Table-entry not really used.  */
345377e23a2Schristos    HOWTO (R_MICROBLAZE_GLOB_DAT,/* Type.  */
346377e23a2Schristos 	  0,			/* Rightshift.  */
347377e23a2Schristos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
348377e23a2Schristos 	  16,			/* Bitsize.  */
349377e23a2Schristos 	  TRUE,			/* PC_relative.  */
350377e23a2Schristos 	  0,			/* Bitpos.  */
351377e23a2Schristos 	  complain_overflow_dont, /* Complain on overflow.  */
352377e23a2Schristos 	  bfd_elf_generic_reloc,/* Special Function.  */
353377e23a2Schristos 	  "R_MICROBLAZE_GLOB_DAT",	/* Name.  */
354377e23a2Schristos 	  FALSE,		/* Partial Inplace.  */
355377e23a2Schristos 	  0,			/* Source Mask.  */
356377e23a2Schristos 	  0x0000ffff,		/* Dest Mask.  */
357377e23a2Schristos 	  TRUE),		/* PC relative offset?  */
358377e23a2Schristos 
359377e23a2Schristos    /* A 64 bit GOT relative relocation.  Table-entry not really used.  */
360377e23a2Schristos    HOWTO (R_MICROBLAZE_GOTOFF_64,	/* Type.  */
361377e23a2Schristos 	  0,			/* Rightshift.  */
362377e23a2Schristos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
363377e23a2Schristos 	  16,			/* Bitsize.  */
364377e23a2Schristos 	  FALSE,		/* PC_relative.  */
365377e23a2Schristos 	  0,			/* Bitpos.  */
366377e23a2Schristos 	  complain_overflow_dont, /* Complain on overflow.  */
367377e23a2Schristos 	  bfd_elf_generic_reloc,/* Special Function.  */
368377e23a2Schristos 	  "R_MICROBLAZE_GOTOFF_64",	/* Name.  */
369377e23a2Schristos 	  FALSE,		/* Partial Inplace.  */
370377e23a2Schristos 	  0,			/* Source Mask.  */
371377e23a2Schristos 	  0x0000ffff,		/* Dest Mask.  */
372377e23a2Schristos 	  FALSE),		/* PC relative offset?  */
373377e23a2Schristos 
374377e23a2Schristos    /* A 32 bit GOT relative relocation.  Table-entry not really used.  */
375377e23a2Schristos    HOWTO (R_MICROBLAZE_GOTOFF_32,	/* Type.  */
376377e23a2Schristos 	  0,			/* Rightshift.  */
377377e23a2Schristos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
378377e23a2Schristos 	  16,			/* Bitsize.  */
379377e23a2Schristos 	  FALSE,		/* PC_relative.  */
380377e23a2Schristos 	  0,			/* Bitpos.  */
381377e23a2Schristos 	  complain_overflow_dont, /* Complain on overflow.  */
382377e23a2Schristos 	  bfd_elf_generic_reloc,	/* Special Function.  */
383377e23a2Schristos 	  "R_MICROBLAZE_GOTOFF_32",	/* Name.  */
384377e23a2Schristos 	  FALSE,		/* Partial Inplace.  */
385377e23a2Schristos 	  0,			/* Source Mask.  */
386377e23a2Schristos 	  0x0000ffff,		/* Dest Mask.  */
387377e23a2Schristos 	  FALSE),		/* PC relative offset?  */
388377e23a2Schristos 
389377e23a2Schristos    /* COPY relocation.  Table-entry not really used.  */
390377e23a2Schristos    HOWTO (R_MICROBLAZE_COPY,	/* Type.  */
391377e23a2Schristos 	  0,			/* Rightshift.  */
392377e23a2Schristos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
393377e23a2Schristos 	  16,			/* Bitsize.  */
394377e23a2Schristos 	  FALSE,		/* PC_relative.  */
395377e23a2Schristos 	  0,			/* Bitpos.  */
396377e23a2Schristos 	  complain_overflow_dont, /* Complain on overflow.  */
397377e23a2Schristos 	  bfd_elf_generic_reloc,/* Special Function.  */
398377e23a2Schristos 	  "R_MICROBLAZE_COPY",	/* Name.  */
399377e23a2Schristos 	  FALSE,		/* Partial Inplace.  */
400377e23a2Schristos 	  0,			/* Source Mask.  */
401377e23a2Schristos 	  0x0000ffff,		/* Dest Mask.  */
402377e23a2Schristos 	  FALSE),		/* PC relative offset?  */
40348596154Schristos 
40448596154Schristos    /* Marker relocs for TLS.  */
40548596154Schristos    HOWTO (R_MICROBLAZE_TLS,
40648596154Schristos 	 0,			/* rightshift */
40748596154Schristos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
40848596154Schristos 	 32,			/* bitsize */
40948596154Schristos 	 FALSE,			/* pc_relative */
41048596154Schristos 	 0,			/* bitpos */
41148596154Schristos 	 complain_overflow_dont, /* complain_on_overflow */
41248596154Schristos 	 bfd_elf_generic_reloc,	/* special_function */
41348596154Schristos 	 "R_MICROBLAZE_TLS",		/* name */
41448596154Schristos 	 FALSE,			/* partial_inplace */
41548596154Schristos 	 0,			/* src_mask */
41648596154Schristos 	 0x0000ffff,			/* dst_mask */
41748596154Schristos 	 FALSE),		/* pcrel_offset */
41848596154Schristos 
41948596154Schristos    HOWTO (R_MICROBLAZE_TLSGD,
42048596154Schristos 	 0,			/* rightshift */
42148596154Schristos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
42248596154Schristos 	 32,			/* bitsize */
42348596154Schristos 	 FALSE,			/* pc_relative */
42448596154Schristos 	 0,			/* bitpos */
42548596154Schristos 	 complain_overflow_dont, /* complain_on_overflow */
42648596154Schristos 	 bfd_elf_generic_reloc, /* special_function */
42748596154Schristos 	 "R_MICROBLAZE_TLSGD",		/* name */
42848596154Schristos 	 FALSE,			/* partial_inplace */
42948596154Schristos 	 0,			/* src_mask */
43048596154Schristos 	 0x0000ffff,			/* dst_mask */
43148596154Schristos 	 FALSE),		/* pcrel_offset */
43248596154Schristos 
43348596154Schristos    HOWTO (R_MICROBLAZE_TLSLD,
43448596154Schristos 	 0,			/* rightshift */
43548596154Schristos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
43648596154Schristos 	 32,			/* bitsize */
43748596154Schristos 	 FALSE,			/* pc_relative */
43848596154Schristos 	 0,			/* bitpos */
43948596154Schristos 	 complain_overflow_dont, /* complain_on_overflow */
44048596154Schristos 	 bfd_elf_generic_reloc, /* special_function */
44148596154Schristos 	 "R_MICROBLAZE_TLSLD",		/* name */
44248596154Schristos 	 FALSE,			/* partial_inplace */
44348596154Schristos 	 0,			/* src_mask */
44448596154Schristos 	 0x0000ffff,		/* dst_mask */
44548596154Schristos 	 FALSE),		/* pcrel_offset */
44648596154Schristos 
44748596154Schristos    /* Computes the load module index of the load module that contains the
44848596154Schristos       definition of its TLS sym.  */
44948596154Schristos    HOWTO (R_MICROBLAZE_TLSDTPMOD32,
45048596154Schristos 	 0,			/* rightshift */
45148596154Schristos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
45248596154Schristos 	 32,			/* bitsize */
45348596154Schristos 	 FALSE,			/* pc_relative */
45448596154Schristos 	 0,			/* bitpos */
45548596154Schristos 	 complain_overflow_dont, /* complain_on_overflow */
45648596154Schristos 	 bfd_elf_generic_reloc, /* special_function */
45748596154Schristos 	 "R_MICROBLAZE_TLSDTPMOD32",	/* name */
45848596154Schristos 	 FALSE,			/* partial_inplace */
45948596154Schristos 	 0,			/* src_mask */
46048596154Schristos 	 0x0000ffff,		/* dst_mask */
46148596154Schristos 	 FALSE),		/* pcrel_offset */
46248596154Schristos 
46348596154Schristos    /* Computes a dtv-relative displacement, the difference between the value
46448596154Schristos       of sym+add and the base address of the thread-local storage block that
46548596154Schristos       contains the definition of sym, minus 0x8000.  Used for initializing GOT */
46648596154Schristos    HOWTO (R_MICROBLAZE_TLSDTPREL32,
46748596154Schristos 	 0,			/* rightshift */
46848596154Schristos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
46948596154Schristos 	 32,			/* bitsize */
47048596154Schristos 	 FALSE,			/* pc_relative */
47148596154Schristos 	 0,			/* bitpos */
47248596154Schristos 	 complain_overflow_dont, /* complain_on_overflow */
47348596154Schristos 	 bfd_elf_generic_reloc, /* special_function */
47448596154Schristos 	 "R_MICROBLAZE_TLSDTPREL32",	/* name */
47548596154Schristos 	 FALSE,			/* partial_inplace */
47648596154Schristos 	 0,			/* src_mask */
47748596154Schristos 	 0x0000ffff,		/* dst_mask */
47848596154Schristos 	 FALSE),		/* pcrel_offset */
47948596154Schristos 
48048596154Schristos    /* Computes a dtv-relative displacement, the difference between the value
48148596154Schristos       of sym+add and the base address of the thread-local storage block that
48248596154Schristos       contains the definition of sym, minus 0x8000.  */
48348596154Schristos    HOWTO (R_MICROBLAZE_TLSDTPREL64,
48448596154Schristos 	 0,			/* rightshift */
48548596154Schristos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
48648596154Schristos 	 32,			/* bitsize */
48748596154Schristos 	 FALSE,			/* pc_relative */
48848596154Schristos 	 0,			/* bitpos */
48948596154Schristos 	 complain_overflow_dont, /* complain_on_overflow */
49048596154Schristos 	 bfd_elf_generic_reloc, /* special_function */
49148596154Schristos 	 "R_MICROBLAZE_TLSDTPREL64",	/* name */
49248596154Schristos 	 FALSE,			/* partial_inplace */
49348596154Schristos 	 0,			/* src_mask */
49448596154Schristos 	 0x0000ffff,		/* dst_mask */
49548596154Schristos 	 FALSE),		/* pcrel_offset */
49648596154Schristos 
49748596154Schristos    /* Computes a tp-relative displacement, the difference between the value of
49848596154Schristos       sym+add and the value of the thread pointer (r13).  */
49948596154Schristos    HOWTO (R_MICROBLAZE_TLSGOTTPREL32,
50048596154Schristos 	 0,			/* rightshift */
50148596154Schristos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
50248596154Schristos 	 32,			/* bitsize */
50348596154Schristos 	 FALSE,			/* pc_relative */
50448596154Schristos 	 0,			/* bitpos */
50548596154Schristos 	 complain_overflow_dont, /* complain_on_overflow */
50648596154Schristos 	 bfd_elf_generic_reloc, /* special_function */
50748596154Schristos 	 "R_MICROBLAZE_TLSGOTTPREL32",	/* name */
50848596154Schristos 	 FALSE,			/* partial_inplace */
50948596154Schristos 	 0,			/* src_mask */
51048596154Schristos 	 0x0000ffff,		/* dst_mask */
51148596154Schristos 	 FALSE),		/* pcrel_offset */
51248596154Schristos 
51348596154Schristos    /* Computes a tp-relative displacement, the difference between the value of
51448596154Schristos       sym+add and the value of the thread pointer (r13).  */
51548596154Schristos    HOWTO (R_MICROBLAZE_TLSTPREL32,
51648596154Schristos 	 0,			/* rightshift */
51748596154Schristos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
51848596154Schristos 	 32,			/* bitsize */
51948596154Schristos 	 FALSE,			/* pc_relative */
52048596154Schristos 	 0,			/* bitpos */
52148596154Schristos 	 complain_overflow_dont, /* complain_on_overflow */
52248596154Schristos 	 bfd_elf_generic_reloc, /* special_function */
52348596154Schristos 	 "R_MICROBLAZE_TLSTPREL32",	/* name */
52448596154Schristos 	 FALSE,			/* partial_inplace */
52548596154Schristos 	 0,			/* src_mask */
52648596154Schristos 	 0x0000ffff,		/* dst_mask */
52748596154Schristos 	 FALSE),		/* pcrel_offset */
52848596154Schristos 
529377e23a2Schristos };
530377e23a2Schristos 
531377e23a2Schristos #ifndef NUM_ELEM
532377e23a2Schristos #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
533377e23a2Schristos #endif
534377e23a2Schristos 
535377e23a2Schristos /* Initialize the microblaze_elf_howto_table, so that linear accesses can be done.  */
536377e23a2Schristos 
537377e23a2Schristos static void
microblaze_elf_howto_init(void)538377e23a2Schristos microblaze_elf_howto_init (void)
539377e23a2Schristos {
540377e23a2Schristos   unsigned int i;
541377e23a2Schristos 
542377e23a2Schristos   for (i = NUM_ELEM (microblaze_elf_howto_raw); i--;)
543377e23a2Schristos     {
544377e23a2Schristos       unsigned int type;
545377e23a2Schristos 
546377e23a2Schristos       type = microblaze_elf_howto_raw[i].type;
547377e23a2Schristos 
548377e23a2Schristos       BFD_ASSERT (type < NUM_ELEM (microblaze_elf_howto_table));
549377e23a2Schristos 
550377e23a2Schristos       microblaze_elf_howto_table [type] = & microblaze_elf_howto_raw [i];
551377e23a2Schristos     }
552377e23a2Schristos }
553377e23a2Schristos 
554377e23a2Schristos static reloc_howto_type *
microblaze_elf_reloc_type_lookup(bfd * abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type code)555377e23a2Schristos microblaze_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
556377e23a2Schristos 				  bfd_reloc_code_real_type code)
557377e23a2Schristos {
558377e23a2Schristos   enum elf_microblaze_reloc_type microblaze_reloc = R_MICROBLAZE_NONE;
559377e23a2Schristos 
560377e23a2Schristos   switch (code)
561377e23a2Schristos     {
562377e23a2Schristos     case BFD_RELOC_NONE:
563377e23a2Schristos       microblaze_reloc = R_MICROBLAZE_NONE;
564377e23a2Schristos       break;
565377e23a2Schristos     case BFD_RELOC_MICROBLAZE_64_NONE:
566377e23a2Schristos       microblaze_reloc = R_MICROBLAZE_64_NONE;
567377e23a2Schristos       break;
568377e23a2Schristos     case BFD_RELOC_32:
569377e23a2Schristos       microblaze_reloc = R_MICROBLAZE_32;
570377e23a2Schristos       break;
571377e23a2Schristos       /* RVA is treated the same as 32 */
572377e23a2Schristos     case BFD_RELOC_RVA:
573377e23a2Schristos       microblaze_reloc = R_MICROBLAZE_32;
574377e23a2Schristos       break;
575377e23a2Schristos     case BFD_RELOC_32_PCREL:
576377e23a2Schristos       microblaze_reloc = R_MICROBLAZE_32_PCREL;
577377e23a2Schristos       break;
578377e23a2Schristos     case BFD_RELOC_64_PCREL:
579377e23a2Schristos       microblaze_reloc = R_MICROBLAZE_64_PCREL;
580377e23a2Schristos       break;
581377e23a2Schristos     case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
582377e23a2Schristos       microblaze_reloc = R_MICROBLAZE_32_PCREL_LO;
583377e23a2Schristos       break;
584377e23a2Schristos     case BFD_RELOC_64:
585377e23a2Schristos       microblaze_reloc = R_MICROBLAZE_64;
586377e23a2Schristos       break;
587377e23a2Schristos     case BFD_RELOC_MICROBLAZE_32_LO:
588377e23a2Schristos       microblaze_reloc = R_MICROBLAZE_32_LO;
589377e23a2Schristos       break;
590377e23a2Schristos     case BFD_RELOC_MICROBLAZE_32_ROSDA:
591377e23a2Schristos       microblaze_reloc = R_MICROBLAZE_SRO32;
592377e23a2Schristos       break;
593377e23a2Schristos     case BFD_RELOC_MICROBLAZE_32_RWSDA:
594377e23a2Schristos       microblaze_reloc = R_MICROBLAZE_SRW32;
595377e23a2Schristos       break;
596377e23a2Schristos     case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
597377e23a2Schristos       microblaze_reloc = R_MICROBLAZE_32_SYM_OP_SYM;
598377e23a2Schristos       break;
599377e23a2Schristos     case BFD_RELOC_VTABLE_INHERIT:
600377e23a2Schristos       microblaze_reloc = R_MICROBLAZE_GNU_VTINHERIT;
601377e23a2Schristos       break;
602377e23a2Schristos     case BFD_RELOC_VTABLE_ENTRY:
603377e23a2Schristos       microblaze_reloc = R_MICROBLAZE_GNU_VTENTRY;
604377e23a2Schristos       break;
605377e23a2Schristos     case BFD_RELOC_MICROBLAZE_64_GOTPC:
606377e23a2Schristos       microblaze_reloc = R_MICROBLAZE_GOTPC_64;
607377e23a2Schristos       break;
608377e23a2Schristos     case BFD_RELOC_MICROBLAZE_64_GOT:
609377e23a2Schristos       microblaze_reloc = R_MICROBLAZE_GOT_64;
610377e23a2Schristos       break;
61107163879Schristos     case BFD_RELOC_MICROBLAZE_64_TEXTPCREL:
61207163879Schristos       microblaze_reloc = R_MICROBLAZE_TEXTPCREL_64;
61307163879Schristos       break;
61407163879Schristos     case BFD_RELOC_MICROBLAZE_64_TEXTREL:
61507163879Schristos       microblaze_reloc = R_MICROBLAZE_TEXTREL_64;
61607163879Schristos       break;
617377e23a2Schristos     case BFD_RELOC_MICROBLAZE_64_PLT:
618377e23a2Schristos       microblaze_reloc = R_MICROBLAZE_PLT_64;
619377e23a2Schristos       break;
620377e23a2Schristos     case BFD_RELOC_MICROBLAZE_64_GOTOFF:
621377e23a2Schristos       microblaze_reloc = R_MICROBLAZE_GOTOFF_64;
622377e23a2Schristos       break;
623377e23a2Schristos     case BFD_RELOC_MICROBLAZE_32_GOTOFF:
624377e23a2Schristos       microblaze_reloc = R_MICROBLAZE_GOTOFF_32;
625377e23a2Schristos       break;
62648596154Schristos     case BFD_RELOC_MICROBLAZE_64_TLSGD:
62748596154Schristos       microblaze_reloc = R_MICROBLAZE_TLSGD;
62848596154Schristos       break;
62948596154Schristos     case BFD_RELOC_MICROBLAZE_64_TLSLD:
63048596154Schristos       microblaze_reloc = R_MICROBLAZE_TLSLD;
63148596154Schristos       break;
63248596154Schristos     case BFD_RELOC_MICROBLAZE_32_TLSDTPREL:
63348596154Schristos       microblaze_reloc = R_MICROBLAZE_TLSDTPREL32;
63448596154Schristos       break;
63548596154Schristos     case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
63648596154Schristos       microblaze_reloc = R_MICROBLAZE_TLSDTPREL64;
63748596154Schristos       break;
63848596154Schristos     case BFD_RELOC_MICROBLAZE_32_TLSDTPMOD:
63948596154Schristos       microblaze_reloc = R_MICROBLAZE_TLSDTPMOD32;
64048596154Schristos       break;
64148596154Schristos     case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL:
64248596154Schristos       microblaze_reloc = R_MICROBLAZE_TLSGOTTPREL32;
64348596154Schristos       break;
64448596154Schristos     case BFD_RELOC_MICROBLAZE_64_TLSTPREL:
64548596154Schristos       microblaze_reloc = R_MICROBLAZE_TLSTPREL32;
64648596154Schristos       break;
647377e23a2Schristos     case BFD_RELOC_MICROBLAZE_COPY:
648377e23a2Schristos       microblaze_reloc = R_MICROBLAZE_COPY;
649377e23a2Schristos       break;
650377e23a2Schristos     default:
651377e23a2Schristos       return (reloc_howto_type *) NULL;
652377e23a2Schristos     }
653377e23a2Schristos 
654377e23a2Schristos   if (!microblaze_elf_howto_table [R_MICROBLAZE_32])
655377e23a2Schristos     /* Initialize howto table if needed.  */
656377e23a2Schristos     microblaze_elf_howto_init ();
657377e23a2Schristos 
658377e23a2Schristos   return microblaze_elf_howto_table [(int) microblaze_reloc];
659377e23a2Schristos };
660377e23a2Schristos 
661377e23a2Schristos static reloc_howto_type *
microblaze_elf_reloc_name_lookup(bfd * abfd ATTRIBUTE_UNUSED,const char * r_name)662377e23a2Schristos microblaze_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
663377e23a2Schristos 				  const char *r_name)
664377e23a2Schristos {
665377e23a2Schristos   unsigned int i;
666377e23a2Schristos 
667377e23a2Schristos   for (i = 0; i < NUM_ELEM (microblaze_elf_howto_raw); i++)
668377e23a2Schristos     if (microblaze_elf_howto_raw[i].name != NULL
669377e23a2Schristos 	&& strcasecmp (microblaze_elf_howto_raw[i].name, r_name) == 0)
670377e23a2Schristos       return &microblaze_elf_howto_raw[i];
671377e23a2Schristos 
672377e23a2Schristos   return NULL;
673377e23a2Schristos }
674377e23a2Schristos 
675377e23a2Schristos /* Set the howto pointer for a RCE ELF reloc.  */
676377e23a2Schristos 
67707163879Schristos static bfd_boolean
microblaze_elf_info_to_howto(bfd * abfd,arelent * cache_ptr,Elf_Internal_Rela * dst)67807163879Schristos microblaze_elf_info_to_howto (bfd * abfd,
679377e23a2Schristos 			      arelent * cache_ptr,
680377e23a2Schristos 			      Elf_Internal_Rela * dst)
681377e23a2Schristos {
682ed6a76a9Schristos   unsigned int r_type;
683ed6a76a9Schristos 
684377e23a2Schristos   if (!microblaze_elf_howto_table [R_MICROBLAZE_32])
685377e23a2Schristos     /* Initialize howto table if needed.  */
686377e23a2Schristos     microblaze_elf_howto_init ();
687377e23a2Schristos 
688ed6a76a9Schristos   r_type = ELF32_R_TYPE (dst->r_info);
689ed6a76a9Schristos   if (r_type >= R_MICROBLAZE_max)
690ed6a76a9Schristos     {
6911c468f90Schristos       /* xgettext:c-format */
69207163879Schristos       _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
693ed6a76a9Schristos 			  abfd, r_type);
694ed6a76a9Schristos       bfd_set_error (bfd_error_bad_value);
69507163879Schristos       return FALSE;
696ed6a76a9Schristos     }
697377e23a2Schristos 
698ed6a76a9Schristos   cache_ptr->howto = microblaze_elf_howto_table [r_type];
69907163879Schristos   return TRUE;
700377e23a2Schristos }
701377e23a2Schristos 
702377e23a2Schristos /* Microblaze ELF local labels start with 'L.' or '$L', not '.L'.  */
703377e23a2Schristos 
704377e23a2Schristos static bfd_boolean
microblaze_elf_is_local_label_name(bfd * abfd,const char * name)705377e23a2Schristos microblaze_elf_is_local_label_name (bfd *abfd, const char *name)
706377e23a2Schristos {
707377e23a2Schristos   if (name[0] == 'L' && name[1] == '.')
708377e23a2Schristos     return TRUE;
709377e23a2Schristos 
710377e23a2Schristos   if (name[0] == '$' && name[1] == 'L')
711377e23a2Schristos     return TRUE;
712377e23a2Schristos 
713377e23a2Schristos   /* With gcc, the labels go back to starting with '.', so we accept
714377e23a2Schristos      the generic ELF local label syntax as well.  */
715377e23a2Schristos   return _bfd_elf_is_local_label_name (abfd, name);
716377e23a2Schristos }
717377e23a2Schristos 
718377e23a2Schristos /* ELF linker hash entry.  */
719377e23a2Schristos 
720377e23a2Schristos struct elf32_mb_link_hash_entry
721377e23a2Schristos {
722377e23a2Schristos   struct elf_link_hash_entry elf;
723377e23a2Schristos 
72448596154Schristos   /* TLS Reference Types for the symbol; Updated by check_relocs */
72548596154Schristos #define TLS_GD     1  /* GD reloc. */
72648596154Schristos #define TLS_LD     2  /* LD reloc. */
72748596154Schristos #define TLS_TPREL  4  /* TPREL reloc, => IE. */
72848596154Schristos #define TLS_DTPREL 8  /* DTPREL reloc, => LD. */
72948596154Schristos #define TLS_TLS    16 /* Any TLS reloc.  */
73048596154Schristos   unsigned char tls_mask;
73148596154Schristos 
732377e23a2Schristos };
733377e23a2Schristos 
73448596154Schristos #define IS_TLS_GD(x)     (x == (TLS_TLS | TLS_GD))
73548596154Schristos #define IS_TLS_LD(x)     (x == (TLS_TLS | TLS_LD))
73648596154Schristos #define IS_TLS_DTPREL(x) (x == (TLS_TLS | TLS_DTPREL))
73748596154Schristos #define IS_TLS_NONE(x)   (x == 0)
73848596154Schristos 
739377e23a2Schristos #define elf32_mb_hash_entry(ent) ((struct elf32_mb_link_hash_entry *)(ent))
740377e23a2Schristos 
741377e23a2Schristos /* ELF linker hash table.  */
742377e23a2Schristos 
743377e23a2Schristos struct elf32_mb_link_hash_table
744377e23a2Schristos {
745377e23a2Schristos   struct elf_link_hash_table elf;
746377e23a2Schristos 
74748596154Schristos   /* TLS Local Dynamic GOT Entry */
74848596154Schristos   union {
74948596154Schristos     bfd_signed_vma refcount;
75048596154Schristos     bfd_vma offset;
75148596154Schristos   } tlsld_got;
752377e23a2Schristos };
753377e23a2Schristos 
75448596154Schristos /* Nonzero if this section has TLS related relocations.  */
75548596154Schristos #define has_tls_reloc sec_flg0
75648596154Schristos 
757377e23a2Schristos /* Get the ELF linker hash table from a link_info structure.  */
758377e23a2Schristos 
759377e23a2Schristos #define elf32_mb_hash_table(p) \
760*1424dfb3Schristos   ((is_elf_hash_table ((p)->hash)					\
761*1424dfb3Schristos     && elf_hash_table_id (elf_hash_table (p)) == MICROBLAZE_ELF_DATA)	\
762*1424dfb3Schristos    ? (struct elf32_mb_link_hash_table *) (p)->hash : NULL)
763377e23a2Schristos 
764377e23a2Schristos /* Create an entry in a microblaze ELF linker hash table.  */
765377e23a2Schristos 
766377e23a2Schristos static struct bfd_hash_entry *
link_hash_newfunc(struct bfd_hash_entry * entry,struct bfd_hash_table * table,const char * string)767377e23a2Schristos link_hash_newfunc (struct bfd_hash_entry *entry,
768377e23a2Schristos 		   struct bfd_hash_table *table,
769377e23a2Schristos 		   const char *string)
770377e23a2Schristos {
771377e23a2Schristos   /* Allocate the structure if it has not already been allocated by a
772377e23a2Schristos      subclass.  */
773377e23a2Schristos   if (entry == NULL)
774377e23a2Schristos     {
775377e23a2Schristos       entry = bfd_hash_allocate (table,
776377e23a2Schristos 				 sizeof (struct elf32_mb_link_hash_entry));
777377e23a2Schristos       if (entry == NULL)
778377e23a2Schristos 	return entry;
779377e23a2Schristos     }
780377e23a2Schristos 
781377e23a2Schristos   /* Call the allocation method of the superclass.  */
782377e23a2Schristos   entry = _bfd_elf_link_hash_newfunc (entry, table, string);
783377e23a2Schristos   if (entry != NULL)
784377e23a2Schristos     {
785377e23a2Schristos       struct elf32_mb_link_hash_entry *eh;
786377e23a2Schristos 
787377e23a2Schristos       eh = (struct elf32_mb_link_hash_entry *) entry;
78848596154Schristos       eh->tls_mask = 0;
789377e23a2Schristos     }
790377e23a2Schristos 
791377e23a2Schristos   return entry;
792377e23a2Schristos }
793377e23a2Schristos 
794377e23a2Schristos /* Create a mb ELF linker hash table.  */
795377e23a2Schristos 
796377e23a2Schristos static struct bfd_link_hash_table *
microblaze_elf_link_hash_table_create(bfd * abfd)797377e23a2Schristos microblaze_elf_link_hash_table_create (bfd *abfd)
798377e23a2Schristos {
799377e23a2Schristos   struct elf32_mb_link_hash_table *ret;
800*1424dfb3Schristos   size_t amt = sizeof (struct elf32_mb_link_hash_table);
801377e23a2Schristos 
802377e23a2Schristos   ret = (struct elf32_mb_link_hash_table *) bfd_zmalloc (amt);
803377e23a2Schristos   if (ret == NULL)
804377e23a2Schristos     return NULL;
805377e23a2Schristos 
806377e23a2Schristos   if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
807377e23a2Schristos 				      sizeof (struct elf32_mb_link_hash_entry),
808377e23a2Schristos 				      MICROBLAZE_ELF_DATA))
809377e23a2Schristos     {
810377e23a2Schristos       free (ret);
811377e23a2Schristos       return NULL;
812377e23a2Schristos     }
813377e23a2Schristos 
814377e23a2Schristos   return &ret->elf.root;
815377e23a2Schristos }
816377e23a2Schristos 
817377e23a2Schristos /* Set the values of the small data pointers.  */
818377e23a2Schristos 
819377e23a2Schristos static void
microblaze_elf_final_sdp(struct bfd_link_info * info)820377e23a2Schristos microblaze_elf_final_sdp (struct bfd_link_info *info)
821377e23a2Schristos {
822377e23a2Schristos   struct bfd_link_hash_entry *h;
823377e23a2Schristos 
824377e23a2Schristos   h = bfd_link_hash_lookup (info->hash, RO_SDA_ANCHOR_NAME, FALSE, FALSE, TRUE);
825377e23a2Schristos   if (h != (struct bfd_link_hash_entry *) NULL
826377e23a2Schristos       && h->type == bfd_link_hash_defined)
827377e23a2Schristos     ro_small_data_pointer = (h->u.def.value
828377e23a2Schristos 			     + h->u.def.section->output_section->vma
829377e23a2Schristos 			     + h->u.def.section->output_offset);
830377e23a2Schristos 
831377e23a2Schristos   h = bfd_link_hash_lookup (info->hash, RW_SDA_ANCHOR_NAME, FALSE, FALSE, TRUE);
832377e23a2Schristos   if (h != (struct bfd_link_hash_entry *) NULL
833377e23a2Schristos       && h->type == bfd_link_hash_defined)
834377e23a2Schristos     rw_small_data_pointer = (h->u.def.value
835377e23a2Schristos 			     + h->u.def.section->output_section->vma
836377e23a2Schristos 			     + h->u.def.section->output_offset);
837377e23a2Schristos }
838377e23a2Schristos 
83948596154Schristos static bfd_vma
dtprel_base(struct bfd_link_info * info)84048596154Schristos dtprel_base (struct bfd_link_info *info)
84148596154Schristos {
84248596154Schristos   /* If tls_sec is NULL, we should have signalled an error already.  */
84348596154Schristos   if (elf_hash_table (info)->tls_sec == NULL)
84448596154Schristos     return 0;
84548596154Schristos   return elf_hash_table (info)->tls_sec->vma;
84648596154Schristos }
84748596154Schristos 
84848596154Schristos /* The size of the thread control block.  */
84948596154Schristos #define TCB_SIZE	8
85048596154Schristos 
85148596154Schristos /* Output a simple dynamic relocation into SRELOC.  */
85248596154Schristos 
85348596154Schristos 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)85448596154Schristos microblaze_elf_output_dynamic_relocation (bfd *output_bfd,
85548596154Schristos 					  asection *sreloc,
85648596154Schristos 					  unsigned long reloc_index,
85748596154Schristos 					  unsigned long indx,
85848596154Schristos 					  int r_type,
85948596154Schristos 					  bfd_vma offset,
86048596154Schristos 					  bfd_vma addend)
86148596154Schristos {
86248596154Schristos 
86348596154Schristos   Elf_Internal_Rela rel;
86448596154Schristos 
86548596154Schristos   rel.r_info = ELF32_R_INFO (indx, r_type);
86648596154Schristos   rel.r_offset = offset;
86748596154Schristos   rel.r_addend = addend;
86848596154Schristos 
86948596154Schristos   bfd_elf32_swap_reloca_out (output_bfd, &rel,
87048596154Schristos 	      (sreloc->contents + reloc_index * sizeof (Elf32_External_Rela)));
87148596154Schristos }
87248596154Schristos 
873377e23a2Schristos /* This code is taken from elf32-m32r.c
874377e23a2Schristos    There is some attempt to make this function usable for many architectures,
875377e23a2Schristos    both USE_REL and USE_RELA ['twould be nice if such a critter existed],
876377e23a2Schristos    if only to serve as a learning tool.
877377e23a2Schristos 
878377e23a2Schristos    The RELOCATE_SECTION function is called by the new ELF backend linker
879377e23a2Schristos    to handle the relocations for a section.
880377e23a2Schristos 
881377e23a2Schristos    The relocs are always passed as Rela structures; if the section
882377e23a2Schristos    actually uses Rel structures, the r_addend field will always be
883377e23a2Schristos    zero.
884377e23a2Schristos 
885377e23a2Schristos    This function is responsible for adjust the section contents as
886377e23a2Schristos    necessary, and (if using Rela relocs and generating a
887377e23a2Schristos    relocatable output file) adjusting the reloc addend as
888377e23a2Schristos    necessary.
889377e23a2Schristos 
890377e23a2Schristos    This function does not have to worry about setting the reloc
891377e23a2Schristos    address or the reloc symbol index.
892377e23a2Schristos 
893377e23a2Schristos    LOCAL_SYMS is a pointer to the swapped in local symbols.
894377e23a2Schristos 
895377e23a2Schristos    LOCAL_SECTIONS is an array giving the section in the input file
896377e23a2Schristos    corresponding to the st_shndx field of each local symbol.
897377e23a2Schristos 
898377e23a2Schristos    The global hash table entry for the global symbols can be found
899377e23a2Schristos    via elf_sym_hashes (input_bfd).
900377e23a2Schristos 
901377e23a2Schristos    When generating relocatable output, this function must handle
902377e23a2Schristos    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
903377e23a2Schristos    going to be the section symbol corresponding to the output
904377e23a2Schristos    section, which means that the addend must be adjusted
905377e23a2Schristos    accordingly.  */
906377e23a2Schristos 
907377e23a2Schristos 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)908377e23a2Schristos microblaze_elf_relocate_section (bfd *output_bfd,
909377e23a2Schristos 				 struct bfd_link_info *info,
910377e23a2Schristos 				 bfd *input_bfd,
911377e23a2Schristos 				 asection *input_section,
912377e23a2Schristos 				 bfd_byte *contents,
913377e23a2Schristos 				 Elf_Internal_Rela *relocs,
914377e23a2Schristos 				 Elf_Internal_Sym *local_syms,
915377e23a2Schristos 				 asection **local_sections)
916377e23a2Schristos {
917377e23a2Schristos   struct elf32_mb_link_hash_table *htab;
918377e23a2Schristos   Elf_Internal_Shdr *symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
919377e23a2Schristos   struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
920377e23a2Schristos   Elf_Internal_Rela *rel, *relend;
92148596154Schristos   int endian = (bfd_little_endian (output_bfd)) ? 0 : 2;
922377e23a2Schristos   /* Assume success.  */
923377e23a2Schristos   bfd_boolean ret = TRUE;
924377e23a2Schristos   asection *sreloc;
925377e23a2Schristos   bfd_vma *local_got_offsets;
92648596154Schristos   unsigned int tls_type;
927377e23a2Schristos 
928377e23a2Schristos   if (!microblaze_elf_howto_table[R_MICROBLAZE_max-1])
929377e23a2Schristos     microblaze_elf_howto_init ();
930377e23a2Schristos 
931377e23a2Schristos   htab = elf32_mb_hash_table (info);
932377e23a2Schristos   if (htab == NULL)
933377e23a2Schristos     return FALSE;
934377e23a2Schristos 
935377e23a2Schristos   local_got_offsets = elf_local_got_offsets (input_bfd);
936377e23a2Schristos 
937377e23a2Schristos   sreloc = elf_section_data (input_section)->sreloc;
938377e23a2Schristos 
939377e23a2Schristos   rel = relocs;
940377e23a2Schristos   relend = relocs + input_section->reloc_count;
941377e23a2Schristos   for (; rel < relend; rel++)
942377e23a2Schristos     {
943377e23a2Schristos       int r_type;
944377e23a2Schristos       reloc_howto_type *howto;
945377e23a2Schristos       unsigned long r_symndx;
946377e23a2Schristos       bfd_vma addend = rel->r_addend;
947377e23a2Schristos       bfd_vma offset = rel->r_offset;
948377e23a2Schristos       struct elf_link_hash_entry *h;
949377e23a2Schristos       Elf_Internal_Sym *sym;
950377e23a2Schristos       asection *sec;
951377e23a2Schristos       const char *sym_name;
952377e23a2Schristos       bfd_reloc_status_type r = bfd_reloc_ok;
953377e23a2Schristos       const char *errmsg = NULL;
954377e23a2Schristos       bfd_boolean unresolved_reloc = FALSE;
955377e23a2Schristos 
956377e23a2Schristos       h = NULL;
957377e23a2Schristos       r_type = ELF32_R_TYPE (rel->r_info);
95848596154Schristos       tls_type = 0;
95948596154Schristos 
960377e23a2Schristos       if (r_type < 0 || r_type >= (int) R_MICROBLAZE_max)
961377e23a2Schristos 	{
9621c468f90Schristos 	  /* xgettext:c-format */
96307163879Schristos 	  _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
9641c468f90Schristos 			      input_bfd, (int) r_type);
965377e23a2Schristos 	  bfd_set_error (bfd_error_bad_value);
966377e23a2Schristos 	  ret = FALSE;
967377e23a2Schristos 	  continue;
968377e23a2Schristos 	}
969377e23a2Schristos 
970377e23a2Schristos       howto = microblaze_elf_howto_table[r_type];
971377e23a2Schristos       r_symndx = ELF32_R_SYM (rel->r_info);
972377e23a2Schristos 
973c03b94e9Schristos       if (bfd_link_relocatable (info))
974377e23a2Schristos 	{
975377e23a2Schristos 	  /* This is a relocatable link.  We don't have to change
976377e23a2Schristos 	     anything, unless the reloc is against a section symbol,
977377e23a2Schristos 	     in which case we have to adjust according to where the
978377e23a2Schristos 	     section symbol winds up in the output section.  */
979377e23a2Schristos 	  sec = NULL;
980377e23a2Schristos 	  if (r_symndx >= symtab_hdr->sh_info)
981377e23a2Schristos 	    /* External symbol.  */
982377e23a2Schristos 	    continue;
983377e23a2Schristos 
984377e23a2Schristos 	  /* Local symbol.  */
985377e23a2Schristos 	  sym = local_syms + r_symndx;
986377e23a2Schristos 	  sym_name = "<local symbol>";
987377e23a2Schristos 	  /* STT_SECTION: symbol is associated with a section.  */
988377e23a2Schristos 	  if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
989377e23a2Schristos 	    /* Symbol isn't associated with a section.  Nothing to do.  */
990377e23a2Schristos 	    continue;
991377e23a2Schristos 
992377e23a2Schristos 	  sec = local_sections[r_symndx];
993377e23a2Schristos 	  addend += sec->output_offset + sym->st_value;
994377e23a2Schristos #ifndef USE_REL
995377e23a2Schristos 	  /* This can't be done for USE_REL because it doesn't mean anything
996377e23a2Schristos 	     and elf_link_input_bfd asserts this stays zero.  */
997377e23a2Schristos 	  /* rel->r_addend = addend; */
998377e23a2Schristos #endif
999377e23a2Schristos 
1000377e23a2Schristos #ifndef USE_REL
1001377e23a2Schristos 	  /* Addends are stored with relocs.  We're done.  */
1002377e23a2Schristos 	  continue;
1003377e23a2Schristos #else /* USE_REL */
1004377e23a2Schristos 	  /* If partial_inplace, we need to store any additional addend
1005377e23a2Schristos 	     back in the section.  */
1006377e23a2Schristos 	  if (!howto->partial_inplace)
1007377e23a2Schristos 	    continue;
1008377e23a2Schristos 	  /* ??? Here is a nice place to call a special_function like handler.  */
1009377e23a2Schristos 	  r = _bfd_relocate_contents (howto, input_bfd, addend,
1010377e23a2Schristos 				      contents + offset);
1011377e23a2Schristos #endif /* USE_REL */
1012377e23a2Schristos 	}
1013377e23a2Schristos       else
1014377e23a2Schristos 	{
1015377e23a2Schristos 	  bfd_vma relocation;
101607163879Schristos 	  bfd_boolean resolved_to_zero;
1017377e23a2Schristos 
1018377e23a2Schristos 	  /* This is a final link.  */
1019377e23a2Schristos 	  sym = NULL;
1020377e23a2Schristos 	  sec = NULL;
1021377e23a2Schristos 	  unresolved_reloc = FALSE;
1022377e23a2Schristos 
1023377e23a2Schristos 	  if (r_symndx < symtab_hdr->sh_info)
1024377e23a2Schristos 	    {
1025377e23a2Schristos 	      /* Local symbol.  */
1026377e23a2Schristos 	      sym = local_syms + r_symndx;
1027377e23a2Schristos 	      sec = local_sections[r_symndx];
1028377e23a2Schristos 	      if (sec == 0)
1029377e23a2Schristos 		continue;
1030377e23a2Schristos 	      sym_name = "<local symbol>";
1031377e23a2Schristos 	      relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
1032377e23a2Schristos 	      /* r_addend may have changed if the reference section was
1033377e23a2Schristos 		 a merge section.  */
1034377e23a2Schristos 	      addend = rel->r_addend;
1035377e23a2Schristos 	    }
1036377e23a2Schristos 	  else
1037377e23a2Schristos 	    {
1038377e23a2Schristos 	      /* External symbol.  */
1039377e23a2Schristos 	      bfd_boolean warned ATTRIBUTE_UNUSED;
10407af5a897Schristos 	      bfd_boolean ignored ATTRIBUTE_UNUSED;
1041377e23a2Schristos 
1042377e23a2Schristos 	      RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
1043377e23a2Schristos 				       r_symndx, symtab_hdr, sym_hashes,
1044377e23a2Schristos 				       h, sec, relocation,
10457af5a897Schristos 				       unresolved_reloc, warned, ignored);
1046377e23a2Schristos 	      sym_name = h->root.root.string;
1047377e23a2Schristos 	    }
1048377e23a2Schristos 
1049377e23a2Schristos 	  /* Sanity check the address.  */
105048596154Schristos 	  if (offset > bfd_get_section_limit (input_bfd, input_section))
1051377e23a2Schristos 	    {
1052377e23a2Schristos 	      r = bfd_reloc_outofrange;
1053377e23a2Schristos 	      goto check_reloc;
1054377e23a2Schristos 	    }
1055377e23a2Schristos 
105607163879Schristos 	  resolved_to_zero = (h != NULL
105707163879Schristos 			      && UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
105807163879Schristos 
1059377e23a2Schristos 	  switch ((int) r_type)
1060377e23a2Schristos 	    {
1061377e23a2Schristos 	    case (int) R_MICROBLAZE_SRO32 :
1062377e23a2Schristos 	      {
1063377e23a2Schristos 		const char *name;
1064377e23a2Schristos 
1065377e23a2Schristos 		/* Only relocate if the symbol is defined.  */
1066377e23a2Schristos 		if (sec)
1067377e23a2Schristos 		  {
1068*1424dfb3Schristos 		    name = bfd_section_name (sec);
1069377e23a2Schristos 
1070377e23a2Schristos 		    if (strcmp (name, ".sdata2") == 0
1071377e23a2Schristos 			|| strcmp (name, ".sbss2") == 0)
1072377e23a2Schristos 		      {
1073377e23a2Schristos 			if (ro_small_data_pointer == 0)
1074377e23a2Schristos 			  microblaze_elf_final_sdp (info);
1075377e23a2Schristos 			if (ro_small_data_pointer == 0)
1076377e23a2Schristos 			  {
1077377e23a2Schristos 			    ret = FALSE;
1078377e23a2Schristos 			    r = bfd_reloc_undefined;
1079377e23a2Schristos 			    goto check_reloc;
1080377e23a2Schristos 			  }
1081377e23a2Schristos 
1082377e23a2Schristos 			/* At this point `relocation' contains the object's
1083377e23a2Schristos 			   address.  */
1084377e23a2Schristos 			relocation -= ro_small_data_pointer;
1085377e23a2Schristos 			/* Now it contains the offset from _SDA2_BASE_.  */
1086377e23a2Schristos 			r = _bfd_final_link_relocate (howto, input_bfd,
1087377e23a2Schristos 						      input_section,
1088377e23a2Schristos 						      contents, offset,
1089377e23a2Schristos 						      relocation, addend);
1090377e23a2Schristos 		      }
1091377e23a2Schristos 		    else
1092377e23a2Schristos 		      {
10931c468f90Schristos 			_bfd_error_handler
10941c468f90Schristos 			  /* xgettext:c-format */
109507163879Schristos 			  (_("%pB: the target (%s) of an %s relocation"
109607163879Schristos 			     " is in the wrong section (%pA)"),
10971c468f90Schristos 			   input_bfd,
1098377e23a2Schristos 			   sym_name,
1099377e23a2Schristos 			   microblaze_elf_howto_table[(int) r_type]->name,
11001c468f90Schristos 			   sec);
1101377e23a2Schristos 			/*bfd_set_error (bfd_error_bad_value); ??? why? */
1102377e23a2Schristos 			ret = FALSE;
1103377e23a2Schristos 			continue;
1104377e23a2Schristos 		      }
1105377e23a2Schristos 		  }
1106377e23a2Schristos 	      }
1107377e23a2Schristos 	      break;
1108377e23a2Schristos 
1109377e23a2Schristos 	    case (int) R_MICROBLAZE_SRW32 :
1110377e23a2Schristos 	      {
1111377e23a2Schristos 		const char *name;
1112377e23a2Schristos 
1113377e23a2Schristos 		/* Only relocate if the symbol is defined.  */
1114377e23a2Schristos 		if (sec)
1115377e23a2Schristos 		  {
1116*1424dfb3Schristos 		    name = bfd_section_name (sec);
1117377e23a2Schristos 
1118377e23a2Schristos 		    if (strcmp (name, ".sdata") == 0
1119377e23a2Schristos 			|| strcmp (name, ".sbss") == 0)
1120377e23a2Schristos 		      {
1121377e23a2Schristos 			if (rw_small_data_pointer == 0)
1122377e23a2Schristos 			  microblaze_elf_final_sdp (info);
1123377e23a2Schristos 			if (rw_small_data_pointer == 0)
1124377e23a2Schristos 			  {
1125377e23a2Schristos 			    ret = FALSE;
1126377e23a2Schristos 			    r = bfd_reloc_undefined;
1127377e23a2Schristos 			    goto check_reloc;
1128377e23a2Schristos 			  }
1129377e23a2Schristos 
1130377e23a2Schristos 			/* At this point `relocation' contains the object's
1131377e23a2Schristos 			   address.  */
1132377e23a2Schristos 			relocation -= rw_small_data_pointer;
1133377e23a2Schristos 			/* Now it contains the offset from _SDA_BASE_.  */
1134377e23a2Schristos 			r = _bfd_final_link_relocate (howto, input_bfd,
1135377e23a2Schristos 						      input_section,
1136377e23a2Schristos 						      contents, offset,
1137377e23a2Schristos 						      relocation, addend);
1138377e23a2Schristos 		      }
1139377e23a2Schristos 		    else
1140377e23a2Schristos 		      {
11411c468f90Schristos 			_bfd_error_handler
11421c468f90Schristos 			  /* xgettext:c-format */
114307163879Schristos 			  (_("%pB: the target (%s) of an %s relocation"
114407163879Schristos 			     " is in the wrong section (%pA)"),
11451c468f90Schristos 			   input_bfd,
1146377e23a2Schristos 			   sym_name,
1147377e23a2Schristos 			   microblaze_elf_howto_table[(int) r_type]->name,
11481c468f90Schristos 			   sec);
1149377e23a2Schristos 			/*bfd_set_error (bfd_error_bad_value); ??? why? */
1150377e23a2Schristos 			ret = FALSE;
1151377e23a2Schristos 			continue;
1152377e23a2Schristos 		      }
1153377e23a2Schristos 		  }
1154377e23a2Schristos 	      }
1155377e23a2Schristos 	      break;
1156377e23a2Schristos 
1157377e23a2Schristos 	    case (int) R_MICROBLAZE_32_SYM_OP_SYM:
1158377e23a2Schristos 	      break; /* Do nothing.  */
1159377e23a2Schristos 
1160377e23a2Schristos 	    case (int) R_MICROBLAZE_GOTPC_64:
11611c468f90Schristos 	      relocation = (htab->elf.sgotplt->output_section->vma
11621c468f90Schristos 			    + htab->elf.sgotplt->output_offset);
1163377e23a2Schristos 	      relocation -= (input_section->output_section->vma
1164377e23a2Schristos 			     + input_section->output_offset
1165377e23a2Schristos 			     + offset + INST_WORD_SIZE);
1166377e23a2Schristos 	      relocation += addend;
1167377e23a2Schristos 	      bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
116848596154Schristos 			  contents + offset + endian);
1169377e23a2Schristos 	      bfd_put_16 (input_bfd, relocation & 0xffff,
117048596154Schristos 			  contents + offset + endian + INST_WORD_SIZE);
1171377e23a2Schristos 	      break;
1172377e23a2Schristos 
117307163879Schristos 	    case (int) R_MICROBLAZE_TEXTPCREL_64:
117407163879Schristos 	      relocation = input_section->output_section->vma;
117507163879Schristos 	      relocation -= (input_section->output_section->vma
117607163879Schristos 			     + input_section->output_offset
117707163879Schristos 			     + offset + INST_WORD_SIZE);
117807163879Schristos 	      relocation += addend;
117907163879Schristos 	      bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
118007163879Schristos 			  contents + offset + endian);
118107163879Schristos 	      bfd_put_16 (input_bfd, relocation & 0xffff,
118207163879Schristos 			  contents + offset + endian + INST_WORD_SIZE);
118307163879Schristos 	      break;
118407163879Schristos 
1185377e23a2Schristos 	    case (int) R_MICROBLAZE_PLT_64:
1186377e23a2Schristos 	      {
1187377e23a2Schristos 		bfd_vma immediate;
11881c468f90Schristos 		if (htab->elf.splt != NULL && h != NULL
1189377e23a2Schristos 		    && h->plt.offset != (bfd_vma) -1)
1190377e23a2Schristos 		  {
11911c468f90Schristos 		    relocation = (htab->elf.splt->output_section->vma
11921c468f90Schristos 				  + htab->elf.splt->output_offset
1193377e23a2Schristos 				  + h->plt.offset);
1194377e23a2Schristos 		    unresolved_reloc = FALSE;
1195377e23a2Schristos 		    immediate = relocation - (input_section->output_section->vma
1196377e23a2Schristos 					      + input_section->output_offset
1197377e23a2Schristos 					      + offset + INST_WORD_SIZE);
1198377e23a2Schristos 		    bfd_put_16 (input_bfd, (immediate >> 16) & 0xffff,
119948596154Schristos 				contents + offset + endian);
1200377e23a2Schristos 		    bfd_put_16 (input_bfd, immediate & 0xffff,
120148596154Schristos 				contents + offset + endian + INST_WORD_SIZE);
1202377e23a2Schristos 		  }
1203377e23a2Schristos 		else
1204377e23a2Schristos 		  {
1205377e23a2Schristos 		    relocation -= (input_section->output_section->vma
1206377e23a2Schristos 				   + input_section->output_offset
1207377e23a2Schristos 				   + offset + INST_WORD_SIZE);
1208377e23a2Schristos 		    immediate = relocation;
1209377e23a2Schristos 		    bfd_put_16 (input_bfd, (immediate >> 16) & 0xffff,
121048596154Schristos 				contents + offset + endian);
1211377e23a2Schristos 		    bfd_put_16 (input_bfd, immediate & 0xffff,
121248596154Schristos 				contents + offset + endian + INST_WORD_SIZE);
1213377e23a2Schristos 		  }
1214377e23a2Schristos 		break;
1215377e23a2Schristos 	      }
1216377e23a2Schristos 
121748596154Schristos 	    case (int) R_MICROBLAZE_TLSGD:
121848596154Schristos 	      tls_type = (TLS_TLS | TLS_GD);
121948596154Schristos 	      goto dogot;
122048596154Schristos 	    case (int) R_MICROBLAZE_TLSLD:
122148596154Schristos 	      tls_type = (TLS_TLS | TLS_LD);
12221c468f90Schristos 	      /* Fall through.  */
122348596154Schristos 	    dogot:
1224377e23a2Schristos 	    case (int) R_MICROBLAZE_GOT_64:
1225377e23a2Schristos 	      {
122648596154Schristos 		bfd_vma *offp;
122748596154Schristos 		bfd_vma off, off2;
122848596154Schristos 		unsigned long indx;
122948596154Schristos 		bfd_vma static_value;
123048596154Schristos 
123148596154Schristos 		bfd_boolean need_relocs = FALSE;
12321c468f90Schristos 		if (htab->elf.sgot == NULL)
1233377e23a2Schristos 		  abort ();
123448596154Schristos 
123548596154Schristos 		indx = 0;
123648596154Schristos 		offp = NULL;
123748596154Schristos 
123848596154Schristos 		/* 1. Identify GOT Offset;
123948596154Schristos 		   2. Compute Static Values
124048596154Schristos 		   3. Process Module Id, Process Offset
124148596154Schristos 		   4. Fixup Relocation with GOT offset value. */
124248596154Schristos 
124348596154Schristos 		/* 1. Determine GOT Offset to use : TLS_LD, global, local */
124448596154Schristos 		if (IS_TLS_LD (tls_type))
124548596154Schristos 		  offp = &htab->tlsld_got.offset;
124648596154Schristos 		else if (h != NULL)
1247377e23a2Schristos 		  {
12481c468f90Schristos 		    if (htab->elf.sgotplt != NULL
12491c468f90Schristos 			&& h->got.offset != (bfd_vma) -1)
125048596154Schristos 		      offp = &h->got.offset;
125148596154Schristos 		    else
125248596154Schristos 		      abort ();
125348596154Schristos 		  }
125448596154Schristos 		else
125548596154Schristos 		  {
1256377e23a2Schristos 		    if (local_got_offsets == NULL)
1257377e23a2Schristos 		      abort ();
125848596154Schristos 		    offp = &local_got_offsets[r_symndx];
125948596154Schristos 		  }
1260377e23a2Schristos 
126148596154Schristos 		if (!offp)
1262377e23a2Schristos 		  abort ();
126348596154Schristos 
126448596154Schristos 		off = (*offp) & ~1;
126548596154Schristos 		off2 = off;
126648596154Schristos 
126748596154Schristos 		if (IS_TLS_LD(tls_type) || IS_TLS_GD(tls_type))
126848596154Schristos 		  off2 = off + 4;
126948596154Schristos 
127048596154Schristos 		/* Symbol index to use for relocs */
127148596154Schristos 		if (h != NULL)
127248596154Schristos 		  {
127348596154Schristos 		    bfd_boolean dyn =
127448596154Schristos 			elf_hash_table (info)->dynamic_sections_created;
127548596154Schristos 
1276c03b94e9Schristos 		    if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
1277c03b94e9Schristos 							 bfd_link_pic (info),
1278c03b94e9Schristos 							 h)
1279c03b94e9Schristos 			&& (!bfd_link_pic (info)
1280c03b94e9Schristos 			    || !SYMBOL_REFERENCES_LOCAL (info, h)))
128148596154Schristos 		      indx = h->dynindx;
128248596154Schristos 		  }
128348596154Schristos 
128448596154Schristos 		/* Need to generate relocs ? */
1285c03b94e9Schristos 		if ((bfd_link_pic (info) || indx != 0)
128648596154Schristos 		    && (h == NULL
128707163879Schristos 		    || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
128807163879Schristos 			&& !resolved_to_zero)
128948596154Schristos 		    || h->root.type != bfd_link_hash_undefweak))
129048596154Schristos 		  need_relocs = TRUE;
129148596154Schristos 
129248596154Schristos 		/* 2. Compute/Emit Static value of r-expression */
129348596154Schristos 		static_value = relocation + addend;
129448596154Schristos 
129548596154Schristos 		/* 3. Process module-id and offset */
129648596154Schristos 		if (! ((*offp) & 1) )
129748596154Schristos 		  {
129848596154Schristos 		    bfd_vma got_offset;
129948596154Schristos 
13001c468f90Schristos 		    got_offset = (htab->elf.sgot->output_section->vma
13011c468f90Schristos 				  + htab->elf.sgot->output_offset
1302377e23a2Schristos 				  + off);
130348596154Schristos 
130448596154Schristos 		    /* Process module-id */
130548596154Schristos 		    if (IS_TLS_LD(tls_type))
130648596154Schristos 		      {
1307c03b94e9Schristos 			if (! bfd_link_pic (info))
13081c468f90Schristos 			  bfd_put_32 (output_bfd, 1,
13091c468f90Schristos 				      htab->elf.sgot->contents + off);
1310377e23a2Schristos 			else
13111c468f90Schristos 			  microblaze_elf_output_dynamic_relocation
13121c468f90Schristos 			    (output_bfd,
13131c468f90Schristos 			     htab->elf.srelgot,
13141c468f90Schristos 			     htab->elf.srelgot->reloc_count++,
131548596154Schristos 			     /* symindex= */ 0, R_MICROBLAZE_TLSDTPMOD32,
131648596154Schristos 			     got_offset, 0);
131748596154Schristos 		      }
131848596154Schristos 		    else if (IS_TLS_GD(tls_type))
1319377e23a2Schristos 		      {
132048596154Schristos 			if (! need_relocs)
13211c468f90Schristos 			  bfd_put_32 (output_bfd, 1,
13221c468f90Schristos 				      htab->elf.sgot->contents + off);
132348596154Schristos 			else
13241c468f90Schristos 			  microblaze_elf_output_dynamic_relocation
13251c468f90Schristos 			    (output_bfd,
13261c468f90Schristos 			     htab->elf.srelgot,
13271c468f90Schristos 			     htab->elf.srelgot->reloc_count++,
132848596154Schristos 			     /* symindex= */ indx, R_MICROBLAZE_TLSDTPMOD32,
132948596154Schristos 			     got_offset, indx ? 0 : static_value);
133048596154Schristos 		      }
133148596154Schristos 
133248596154Schristos 		    /* Process Offset */
13331c468f90Schristos 		    if (htab->elf.srelgot == NULL)
133448596154Schristos 		      abort ();
133548596154Schristos 
13361c468f90Schristos 		    got_offset = (htab->elf.sgot->output_section->vma
13371c468f90Schristos 				  + htab->elf.sgot->output_offset
133848596154Schristos 				  + off2);
133948596154Schristos 		    if (IS_TLS_LD(tls_type))
134048596154Schristos 		      {
134148596154Schristos 			/* For LD, offset should be 0 */
134248596154Schristos 			*offp |= 1;
13431c468f90Schristos 			bfd_put_32 (output_bfd, 0,
13441c468f90Schristos 				    htab->elf.sgot->contents + off2);
134548596154Schristos 		      }
134648596154Schristos 		    else if (IS_TLS_GD(tls_type))
134748596154Schristos 		      {
134848596154Schristos 			*offp |= 1;
134948596154Schristos 			static_value -= dtprel_base(info);
135048596154Schristos 			if (need_relocs)
13511c468f90Schristos 			  microblaze_elf_output_dynamic_relocation
13521c468f90Schristos 			    (output_bfd,
13531c468f90Schristos 			     htab->elf.srelgot,
13541c468f90Schristos 			     htab->elf.srelgot->reloc_count++,
135548596154Schristos 			     /* symindex= */ indx, R_MICROBLAZE_TLSDTPREL32,
135648596154Schristos 			     got_offset, indx ? 0 : static_value);
13571c468f90Schristos 			else
13581c468f90Schristos 			  bfd_put_32 (output_bfd, static_value,
13591c468f90Schristos 				      htab->elf.sgot->contents + off2);
136048596154Schristos 		      }
136148596154Schristos 		    else
136248596154Schristos 		      {
136348596154Schristos 			bfd_put_32 (output_bfd, static_value,
13641c468f90Schristos 				    htab->elf.sgot->contents + off2);
136548596154Schristos 
136648596154Schristos 			/* Relocs for dyn symbols generated by
136748596154Schristos 			   finish_dynamic_symbols */
1368c03b94e9Schristos 			if (bfd_link_pic (info) && h == NULL)
136948596154Schristos 			  {
137048596154Schristos 			    *offp |= 1;
13711c468f90Schristos 			    microblaze_elf_output_dynamic_relocation
13721c468f90Schristos 			      (output_bfd,
13731c468f90Schristos 			       htab->elf.srelgot,
13741c468f90Schristos 			       htab->elf.srelgot->reloc_count++,
137548596154Schristos 			       /* symindex= */ indx, R_MICROBLAZE_REL,
137648596154Schristos 			       got_offset, static_value);
137748596154Schristos 			  }
137848596154Schristos 		      }
137948596154Schristos 		  }
138048596154Schristos 
138148596154Schristos 		/* 4. Fixup Relocation with GOT offset value
138248596154Schristos 		      Compute relative address of GOT entry for applying
138348596154Schristos 		      the current relocation */
13841c468f90Schristos 		relocation = htab->elf.sgot->output_section->vma
13851c468f90Schristos 			     + htab->elf.sgot->output_offset
138648596154Schristos 			     + off
13871c468f90Schristos 			     - htab->elf.sgotplt->output_section->vma
13881c468f90Schristos 			     - htab->elf.sgotplt->output_offset;
138948596154Schristos 
139048596154Schristos 		/* Apply Current Relocation */
1391377e23a2Schristos 		bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
139248596154Schristos 			    contents + offset + endian);
1393377e23a2Schristos 		bfd_put_16 (input_bfd, relocation & 0xffff,
139448596154Schristos 			    contents + offset + endian + INST_WORD_SIZE);
139548596154Schristos 
139648596154Schristos 		unresolved_reloc = FALSE;
1397377e23a2Schristos 		break;
1398377e23a2Schristos 	      }
1399377e23a2Schristos 
1400377e23a2Schristos 	    case (int) R_MICROBLAZE_GOTOFF_64:
1401377e23a2Schristos 	      {
1402377e23a2Schristos 		bfd_vma immediate;
1403377e23a2Schristos 		unsigned short lo, high;
1404377e23a2Schristos 		relocation += addend;
14051c468f90Schristos 		relocation -= (htab->elf.sgotplt->output_section->vma
14061c468f90Schristos 			       + htab->elf.sgotplt->output_offset);
1407377e23a2Schristos 		/* Write this value into correct location.  */
1408377e23a2Schristos 		immediate = relocation;
1409377e23a2Schristos 		lo = immediate & 0x0000ffff;
1410377e23a2Schristos 		high = (immediate >> 16) & 0x0000ffff;
141148596154Schristos 		bfd_put_16 (input_bfd, high, contents + offset + endian);
14121c468f90Schristos 		bfd_put_16 (input_bfd, lo,
14131c468f90Schristos 			    contents + offset + INST_WORD_SIZE + endian);
1414377e23a2Schristos 		break;
1415377e23a2Schristos 	      }
1416377e23a2Schristos 
1417377e23a2Schristos 	    case (int) R_MICROBLAZE_GOTOFF_32:
1418377e23a2Schristos 	      {
1419377e23a2Schristos 		relocation += addend;
14201c468f90Schristos 		relocation -= (htab->elf.sgotplt->output_section->vma
14211c468f90Schristos 			       + htab->elf.sgotplt->output_offset);
1422377e23a2Schristos 		/* Write this value into correct location.  */
1423377e23a2Schristos 		bfd_put_32 (input_bfd, relocation, contents + offset);
1424377e23a2Schristos 		break;
1425377e23a2Schristos 	      }
1426377e23a2Schristos 
142748596154Schristos 	    case (int) R_MICROBLAZE_TLSDTPREL64:
142848596154Schristos 	      relocation += addend;
142948596154Schristos 	      relocation -= dtprel_base(info);
143048596154Schristos 	      bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
143148596154Schristos 			  contents + offset + 2);
143248596154Schristos 	      bfd_put_16 (input_bfd, relocation & 0xffff,
143348596154Schristos 			  contents + offset + 2 + INST_WORD_SIZE);
143448596154Schristos 	      break;
143507163879Schristos 	    case (int) R_MICROBLAZE_TEXTREL_64:
143607163879Schristos 	    case (int) R_MICROBLAZE_TEXTREL_32_LO:
1437377e23a2Schristos 	    case (int) R_MICROBLAZE_64_PCREL :
1438377e23a2Schristos 	    case (int) R_MICROBLAZE_64:
1439377e23a2Schristos 	    case (int) R_MICROBLAZE_32:
1440377e23a2Schristos 	      {
1441377e23a2Schristos 		/* r_symndx will be STN_UNDEF (zero) only for relocs against symbols
1442377e23a2Schristos 		   from removed linkonce sections, or sections discarded by
1443377e23a2Schristos 		   a linker script.  */
1444377e23a2Schristos 		if (r_symndx == STN_UNDEF || (input_section->flags & SEC_ALLOC) == 0)
1445377e23a2Schristos 		  {
1446377e23a2Schristos 		    relocation += addend;
1447377e23a2Schristos 		    if (r_type == R_MICROBLAZE_32)
1448377e23a2Schristos 		      bfd_put_32 (input_bfd, relocation, contents + offset);
1449377e23a2Schristos 		    else
1450377e23a2Schristos 		      {
1451377e23a2Schristos 			if (r_type == R_MICROBLAZE_64_PCREL)
1452377e23a2Schristos 			  relocation -= (input_section->output_section->vma
1453377e23a2Schristos 					 + input_section->output_offset
1454377e23a2Schristos 					 + offset + INST_WORD_SIZE);
145507163879Schristos 			else if (r_type == R_MICROBLAZE_TEXTREL_64
145607163879Schristos 				 || r_type == R_MICROBLAZE_TEXTREL_32_LO)
145707163879Schristos 			  relocation -= input_section->output_section->vma;
145807163879Schristos 
145907163879Schristos 			if (r_type == R_MICROBLAZE_TEXTREL_32_LO)
146007163879Schristos 			  bfd_put_16 (input_bfd, relocation & 0xffff,
146107163879Schristos 				      contents + offset + endian);
146207163879Schristos 
146307163879Schristos 			else
146407163879Schristos 			  {
1465377e23a2Schristos 			    bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
146648596154Schristos 				    contents + offset + endian);
1467377e23a2Schristos 			    bfd_put_16 (input_bfd, relocation & 0xffff,
146848596154Schristos 				    contents + offset + endian + INST_WORD_SIZE);
1469377e23a2Schristos 		      }
147007163879Schristos 		    }
1471377e23a2Schristos 		    break;
1472377e23a2Schristos 		  }
1473377e23a2Schristos 
1474c03b94e9Schristos 		if ((bfd_link_pic (info)
1475377e23a2Schristos 		     && (h == NULL
147607163879Schristos 			 || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
147707163879Schristos 			     && !resolved_to_zero)
1478377e23a2Schristos 			 || h->root.type != bfd_link_hash_undefweak)
1479377e23a2Schristos 		     && (!howto->pc_relative
1480377e23a2Schristos 			 || (h != NULL
1481377e23a2Schristos 			     && h->dynindx != -1
1482377e23a2Schristos 			     && (!info->symbolic
1483377e23a2Schristos 				 || !h->def_regular))))
1484c03b94e9Schristos 		    || (!bfd_link_pic (info)
1485377e23a2Schristos 			&& h != NULL
1486377e23a2Schristos 			&& h->dynindx != -1
1487377e23a2Schristos 			&& !h->non_got_ref
1488377e23a2Schristos 			&& ((h->def_dynamic
1489377e23a2Schristos 			     && !h->def_regular)
1490377e23a2Schristos 			    || h->root.type == bfd_link_hash_undefweak
1491377e23a2Schristos 			    || h->root.type == bfd_link_hash_undefined)))
1492377e23a2Schristos 		  {
1493377e23a2Schristos 		    Elf_Internal_Rela outrel;
1494377e23a2Schristos 		    bfd_byte *loc;
1495377e23a2Schristos 		    bfd_boolean skip;
1496377e23a2Schristos 
1497377e23a2Schristos 		    /* When generating a shared object, these relocations
1498377e23a2Schristos 		       are copied into the output file to be resolved at run
1499377e23a2Schristos 		       time.  */
1500377e23a2Schristos 
1501377e23a2Schristos 		    BFD_ASSERT (sreloc != NULL);
1502377e23a2Schristos 
1503377e23a2Schristos 		    skip = FALSE;
1504377e23a2Schristos 
1505377e23a2Schristos 		    outrel.r_offset =
1506377e23a2Schristos 		      _bfd_elf_section_offset (output_bfd, info, input_section,
1507377e23a2Schristos 					       rel->r_offset);
1508377e23a2Schristos 		    if (outrel.r_offset == (bfd_vma) -1)
1509377e23a2Schristos 		      skip = TRUE;
1510377e23a2Schristos 		    else if (outrel.r_offset == (bfd_vma) -2)
1511377e23a2Schristos 		      skip = TRUE;
1512377e23a2Schristos 		    outrel.r_offset += (input_section->output_section->vma
1513377e23a2Schristos 					+ input_section->output_offset);
1514377e23a2Schristos 
1515377e23a2Schristos 		    if (skip)
1516377e23a2Schristos 		      memset (&outrel, 0, sizeof outrel);
1517377e23a2Schristos 		    /* h->dynindx may be -1 if the symbol was marked to
1518377e23a2Schristos 		       become local.  */
1519377e23a2Schristos 		    else if (h != NULL
1520377e23a2Schristos 			     && ((! info->symbolic && h->dynindx != -1)
1521377e23a2Schristos 				 || !h->def_regular))
1522377e23a2Schristos 		      {
1523377e23a2Schristos 			BFD_ASSERT (h->dynindx != -1);
1524377e23a2Schristos 			outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
1525377e23a2Schristos 			outrel.r_addend = addend;
1526377e23a2Schristos 		      }
1527377e23a2Schristos 		    else
1528377e23a2Schristos 		      {
1529377e23a2Schristos 			if (r_type == R_MICROBLAZE_32)
1530377e23a2Schristos 			  {
1531377e23a2Schristos 			    outrel.r_info = ELF32_R_INFO (0, R_MICROBLAZE_REL);
1532377e23a2Schristos 			    outrel.r_addend = relocation + addend;
1533377e23a2Schristos 			  }
1534377e23a2Schristos 			else
1535377e23a2Schristos 			  {
1536377e23a2Schristos 			    BFD_FAIL ();
15371c468f90Schristos 			    _bfd_error_handler
153807163879Schristos 			      (_("%pB: probably compiled without -fPIC?"),
1539377e23a2Schristos 			       input_bfd);
1540377e23a2Schristos 			    bfd_set_error (bfd_error_bad_value);
1541377e23a2Schristos 			    return FALSE;
1542377e23a2Schristos 			  }
1543377e23a2Schristos 		      }
1544377e23a2Schristos 
1545377e23a2Schristos 		    loc = sreloc->contents;
1546377e23a2Schristos 		    loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela);
1547377e23a2Schristos 		    bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
1548377e23a2Schristos 		    break;
1549377e23a2Schristos 		  }
1550377e23a2Schristos 		else
1551377e23a2Schristos 		  {
1552377e23a2Schristos 		    relocation += addend;
1553377e23a2Schristos 		    if (r_type == R_MICROBLAZE_32)
1554377e23a2Schristos 		      bfd_put_32 (input_bfd, relocation, contents + offset);
1555377e23a2Schristos 		    else
1556377e23a2Schristos 		      {
1557377e23a2Schristos 			if (r_type == R_MICROBLAZE_64_PCREL)
1558377e23a2Schristos 			  relocation -= (input_section->output_section->vma
1559377e23a2Schristos 					 + input_section->output_offset
1560377e23a2Schristos 					 + offset + INST_WORD_SIZE);
156107163879Schristos 			else if (r_type == R_MICROBLAZE_TEXTREL_64
156207163879Schristos 				 || r_type == R_MICROBLAZE_TEXTREL_32_LO)
156307163879Schristos 			  relocation -= input_section->output_section->vma;
156407163879Schristos 
156507163879Schristos 			if (r_type == R_MICROBLAZE_TEXTREL_32_LO)
156607163879Schristos 			  {
156707163879Schristos 			     bfd_put_16 (input_bfd, relocation & 0xffff,
156807163879Schristos 					 contents + offset + endian);
156907163879Schristos 			  }
157007163879Schristos 			else
157107163879Schristos 			  {
1572377e23a2Schristos 			    bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
157348596154Schristos 				        contents + offset + endian);
1574377e23a2Schristos 			    bfd_put_16 (input_bfd, relocation & 0xffff,
157507163879Schristos 					contents + offset + endian
157607163879Schristos 					+ INST_WORD_SIZE);
157707163879Schristos 			  }
1578377e23a2Schristos 		    }
1579377e23a2Schristos 		    break;
1580377e23a2Schristos 		  }
1581377e23a2Schristos 	      }
1582377e23a2Schristos 
1583377e23a2Schristos 	    default :
1584377e23a2Schristos 	      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
1585377e23a2Schristos 					    contents, offset,
1586377e23a2Schristos 					    relocation, addend);
1587377e23a2Schristos 	      break;
1588377e23a2Schristos 	    }
1589377e23a2Schristos 	}
1590377e23a2Schristos 
1591377e23a2Schristos     check_reloc:
1592377e23a2Schristos 
1593377e23a2Schristos       if (r != bfd_reloc_ok)
1594377e23a2Schristos 	{
1595377e23a2Schristos 	  /* FIXME: This should be generic enough to go in a utility.  */
1596377e23a2Schristos 	  const char *name;
1597377e23a2Schristos 
1598377e23a2Schristos 	  if (h != NULL)
1599377e23a2Schristos 	    name = h->root.root.string;
1600377e23a2Schristos 	  else
1601377e23a2Schristos 	    {
1602377e23a2Schristos 	      name = (bfd_elf_string_from_elf_section
1603377e23a2Schristos 		      (input_bfd, symtab_hdr->sh_link, sym->st_name));
1604377e23a2Schristos 	      if (name == NULL || *name == '\0')
1605*1424dfb3Schristos 		name = bfd_section_name (sec);
1606377e23a2Schristos 	    }
1607377e23a2Schristos 
1608377e23a2Schristos 	  if (errmsg != NULL)
1609377e23a2Schristos 	    goto common_error;
1610377e23a2Schristos 
1611377e23a2Schristos 	  switch (r)
1612377e23a2Schristos 	    {
1613377e23a2Schristos 	    case bfd_reloc_overflow:
1614c03b94e9Schristos 	      (*info->callbacks->reloc_overflow)
1615377e23a2Schristos 		(info, (h ? &h->root : NULL), name, howto->name,
1616c03b94e9Schristos 		 (bfd_vma) 0, input_bfd, input_section, offset);
1617377e23a2Schristos 	      break;
1618377e23a2Schristos 
1619377e23a2Schristos 	    case bfd_reloc_undefined:
1620c03b94e9Schristos 	      (*info->callbacks->undefined_symbol)
1621c03b94e9Schristos 		(info, name, input_bfd, input_section, offset, TRUE);
1622377e23a2Schristos 	      break;
1623377e23a2Schristos 
1624377e23a2Schristos 	    case bfd_reloc_outofrange:
1625377e23a2Schristos 	      errmsg = _("internal error: out of range error");
1626377e23a2Schristos 	      goto common_error;
1627377e23a2Schristos 
1628377e23a2Schristos 	    case bfd_reloc_notsupported:
1629377e23a2Schristos 	      errmsg = _("internal error: unsupported relocation error");
1630377e23a2Schristos 	      goto common_error;
1631377e23a2Schristos 
1632377e23a2Schristos 	    case bfd_reloc_dangerous:
1633377e23a2Schristos 	      errmsg = _("internal error: dangerous error");
1634377e23a2Schristos 	      goto common_error;
1635377e23a2Schristos 
1636377e23a2Schristos 	    default:
1637377e23a2Schristos 	      errmsg = _("internal error: unknown error");
1638377e23a2Schristos 	      /* Fall through.  */
1639377e23a2Schristos 	    common_error:
1640c03b94e9Schristos 	      (*info->callbacks->warning) (info, errmsg, name, input_bfd,
1641c03b94e9Schristos 					   input_section, offset);
1642377e23a2Schristos 	      break;
1643377e23a2Schristos 	    }
1644377e23a2Schristos 	}
1645377e23a2Schristos     }
1646377e23a2Schristos 
1647377e23a2Schristos   return ret;
1648377e23a2Schristos }
1649377e23a2Schristos 
1650377e23a2Schristos /* Calculate fixup value for reference.  */
1651377e23a2Schristos 
1652377e23a2Schristos static int
calc_fixup(bfd_vma start,bfd_vma size,asection * sec)165348596154Schristos calc_fixup (bfd_vma start, bfd_vma size, asection *sec)
1654377e23a2Schristos {
165548596154Schristos   bfd_vma end = start + size;
1656377e23a2Schristos   int i, fixup = 0;
1657377e23a2Schristos 
1658377e23a2Schristos   if (sec == NULL || sec->relax == NULL)
1659377e23a2Schristos     return 0;
1660377e23a2Schristos 
1661377e23a2Schristos   /* Look for addr in relax table, total fixup value.  */
1662377e23a2Schristos   for (i = 0; i < sec->relax_count; i++)
1663377e23a2Schristos     {
166448596154Schristos       if (end <= sec->relax[i].addr)
1665377e23a2Schristos 	break;
166648596154Schristos       if ((end != start) && (start > sec->relax[i].addr))
166748596154Schristos 	continue;
1668377e23a2Schristos       fixup += sec->relax[i].size;
1669377e23a2Schristos     }
1670377e23a2Schristos   return fixup;
1671377e23a2Schristos }
1672377e23a2Schristos 
167348596154Schristos /* Read-modify-write into the bfd, an immediate value into appropriate fields of
167448596154Schristos    a 32-bit instruction.  */
167548596154Schristos static void
microblaze_bfd_write_imm_value_32(bfd * abfd,bfd_byte * bfd_addr,bfd_vma val)167648596154Schristos microblaze_bfd_write_imm_value_32 (bfd *abfd, bfd_byte *bfd_addr, bfd_vma val)
167748596154Schristos {
167848596154Schristos     unsigned long instr = bfd_get_32 (abfd, bfd_addr);
167948596154Schristos     instr &= ~0x0000ffff;
168048596154Schristos     instr |= (val & 0x0000ffff);
168148596154Schristos     bfd_put_32 (abfd, instr, bfd_addr);
168248596154Schristos }
168348596154Schristos 
168448596154Schristos /* Read-modify-write into the bfd, an immediate value into appropriate fields of
168548596154Schristos    two consecutive 32-bit instructions.  */
168648596154Schristos static void
microblaze_bfd_write_imm_value_64(bfd * abfd,bfd_byte * bfd_addr,bfd_vma val)168748596154Schristos microblaze_bfd_write_imm_value_64 (bfd *abfd, bfd_byte *bfd_addr, bfd_vma val)
168848596154Schristos {
168948596154Schristos     unsigned long instr_hi;
169048596154Schristos     unsigned long instr_lo;
169148596154Schristos 
169248596154Schristos     instr_hi = bfd_get_32 (abfd, bfd_addr);
169348596154Schristos     instr_hi &= ~0x0000ffff;
169448596154Schristos     instr_hi |= ((val >> 16) & 0x0000ffff);
169548596154Schristos     bfd_put_32 (abfd, instr_hi, bfd_addr);
169648596154Schristos 
169748596154Schristos     instr_lo = bfd_get_32 (abfd, bfd_addr + INST_WORD_SIZE);
169848596154Schristos     instr_lo &= ~0x0000ffff;
169948596154Schristos     instr_lo |= (val & 0x0000ffff);
170048596154Schristos     bfd_put_32 (abfd, instr_lo, bfd_addr + INST_WORD_SIZE);
170148596154Schristos }
170248596154Schristos 
1703377e23a2Schristos static bfd_boolean
microblaze_elf_relax_section(bfd * abfd,asection * sec,struct bfd_link_info * link_info,bfd_boolean * again)1704377e23a2Schristos microblaze_elf_relax_section (bfd *abfd,
1705377e23a2Schristos 			      asection *sec,
1706377e23a2Schristos 			      struct bfd_link_info *link_info,
1707377e23a2Schristos 			      bfd_boolean *again)
1708377e23a2Schristos {
1709377e23a2Schristos   Elf_Internal_Shdr *symtab_hdr;
1710377e23a2Schristos   Elf_Internal_Rela *internal_relocs;
1711377e23a2Schristos   Elf_Internal_Rela *free_relocs = NULL;
1712377e23a2Schristos   Elf_Internal_Rela *irel, *irelend;
1713377e23a2Schristos   bfd_byte *contents = NULL;
1714377e23a2Schristos   bfd_byte *free_contents = NULL;
1715377e23a2Schristos   int rel_count;
1716377e23a2Schristos   unsigned int shndx;
1717377e23a2Schristos   int i, sym_index;
1718377e23a2Schristos   asection *o;
1719377e23a2Schristos   struct elf_link_hash_entry *sym_hash;
1720377e23a2Schristos   Elf_Internal_Sym *isymbuf, *isymend;
1721377e23a2Schristos   Elf_Internal_Sym *isym;
1722377e23a2Schristos   int symcount;
1723377e23a2Schristos   int offset;
1724377e23a2Schristos   bfd_vma src, dest;
1725377e23a2Schristos 
1726377e23a2Schristos   /* We only do this once per section.  We may be able to delete some code
1727377e23a2Schristos      by running multiple passes, but it is not worth it.  */
1728377e23a2Schristos   *again = FALSE;
1729377e23a2Schristos 
1730377e23a2Schristos   /* Only do this for a text section.  */
1731c03b94e9Schristos   if (bfd_link_relocatable (link_info)
1732377e23a2Schristos       || (sec->flags & SEC_RELOC) == 0
173348596154Schristos       || (sec->reloc_count == 0)
173448596154Schristos       || (sec->flags & SEC_CODE) == 0)
1735377e23a2Schristos     return TRUE;
1736377e23a2Schristos 
1737377e23a2Schristos   BFD_ASSERT ((sec->size > 0) || (sec->rawsize > 0));
1738377e23a2Schristos 
1739377e23a2Schristos   /* If this is the first time we have been called for this section,
1740377e23a2Schristos      initialize the cooked size.  */
1741377e23a2Schristos   if (sec->size == 0)
1742377e23a2Schristos     sec->size = sec->rawsize;
1743377e23a2Schristos 
1744377e23a2Schristos   /* Get symbols for this section.  */
1745377e23a2Schristos   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1746377e23a2Schristos   isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1747377e23a2Schristos   symcount =  symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
1748377e23a2Schristos   if (isymbuf == NULL)
1749377e23a2Schristos     isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, symcount,
1750377e23a2Schristos 				    0, NULL, NULL, NULL);
1751377e23a2Schristos   BFD_ASSERT (isymbuf != NULL);
1752377e23a2Schristos 
1753377e23a2Schristos   internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, link_info->keep_memory);
1754377e23a2Schristos   if (internal_relocs == NULL)
1755377e23a2Schristos     goto error_return;
1756377e23a2Schristos   if (! link_info->keep_memory)
1757377e23a2Schristos     free_relocs = internal_relocs;
1758377e23a2Schristos 
1759377e23a2Schristos   sec->relax = (struct relax_table *) bfd_malloc ((sec->reloc_count + 1)
1760377e23a2Schristos 						  * sizeof (struct relax_table));
1761377e23a2Schristos   if (sec->relax == NULL)
1762377e23a2Schristos     goto error_return;
1763377e23a2Schristos   sec->relax_count = 0;
1764377e23a2Schristos 
1765377e23a2Schristos   irelend = internal_relocs + sec->reloc_count;
1766377e23a2Schristos   rel_count = 0;
1767377e23a2Schristos   for (irel = internal_relocs; irel < irelend; irel++, rel_count++)
1768377e23a2Schristos     {
1769377e23a2Schristos       bfd_vma symval;
1770377e23a2Schristos       if ((ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64_PCREL)
177107163879Schristos 	  && (ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64)
177207163879Schristos 	  && (ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_TEXTREL_64))
1773377e23a2Schristos 	continue; /* Can't delete this reloc.  */
1774377e23a2Schristos 
1775377e23a2Schristos       /* Get the section contents.  */
1776377e23a2Schristos       if (contents == NULL)
1777377e23a2Schristos 	{
1778377e23a2Schristos 	  if (elf_section_data (sec)->this_hdr.contents != NULL)
1779377e23a2Schristos 	    contents = elf_section_data (sec)->this_hdr.contents;
1780377e23a2Schristos 	  else
1781377e23a2Schristos 	    {
1782377e23a2Schristos 	      contents = (bfd_byte *) bfd_malloc (sec->size);
1783377e23a2Schristos 	      if (contents == NULL)
1784377e23a2Schristos 		goto error_return;
1785377e23a2Schristos 	      free_contents = contents;
1786377e23a2Schristos 
1787377e23a2Schristos 	      if (!bfd_get_section_contents (abfd, sec, contents,
1788377e23a2Schristos 					     (file_ptr) 0, sec->size))
1789377e23a2Schristos 		goto error_return;
1790377e23a2Schristos 	      elf_section_data (sec)->this_hdr.contents = contents;
1791377e23a2Schristos 	    }
1792377e23a2Schristos 	}
1793377e23a2Schristos 
1794377e23a2Schristos       /* Get the value of the symbol referred to by the reloc.  */
1795377e23a2Schristos       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1796377e23a2Schristos 	{
1797377e23a2Schristos 	  /* A local symbol.  */
1798377e23a2Schristos 	  asection *sym_sec;
1799377e23a2Schristos 
1800377e23a2Schristos 	  isym = isymbuf + ELF32_R_SYM (irel->r_info);
1801377e23a2Schristos 	  if (isym->st_shndx == SHN_UNDEF)
1802377e23a2Schristos 	    sym_sec = bfd_und_section_ptr;
1803377e23a2Schristos 	  else if (isym->st_shndx == SHN_ABS)
1804377e23a2Schristos 	    sym_sec = bfd_abs_section_ptr;
1805377e23a2Schristos 	  else if (isym->st_shndx == SHN_COMMON)
1806377e23a2Schristos 	    sym_sec = bfd_com_section_ptr;
1807377e23a2Schristos 	  else
1808377e23a2Schristos 	    sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1809377e23a2Schristos 
1810377e23a2Schristos 	  symval = _bfd_elf_rela_local_sym (abfd, isym, &sym_sec, irel);
1811377e23a2Schristos 	}
1812377e23a2Schristos       else
1813377e23a2Schristos 	{
1814377e23a2Schristos 	  unsigned long indx;
1815377e23a2Schristos 	  struct elf_link_hash_entry *h;
1816377e23a2Schristos 
1817377e23a2Schristos 	  indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1818377e23a2Schristos 	  h = elf_sym_hashes (abfd)[indx];
1819377e23a2Schristos 	  BFD_ASSERT (h != NULL);
1820377e23a2Schristos 
1821377e23a2Schristos 	  if (h->root.type != bfd_link_hash_defined
1822377e23a2Schristos 	      && h->root.type != bfd_link_hash_defweak)
1823377e23a2Schristos 	    /* This appears to be a reference to an undefined
1824377e23a2Schristos 	       symbol.  Just ignore it--it will be caught by the
1825377e23a2Schristos 	       regular reloc processing.  */
1826377e23a2Schristos 	    continue;
1827377e23a2Schristos 
1828377e23a2Schristos 	  symval = (h->root.u.def.value
1829377e23a2Schristos 		    + h->root.u.def.section->output_section->vma
1830377e23a2Schristos 		    + h->root.u.def.section->output_offset);
1831377e23a2Schristos 	}
1832377e23a2Schristos 
1833377e23a2Schristos       /* If this is a PC-relative reloc, subtract the instr offset from
1834377e23a2Schristos 	 the symbol value.  */
1835377e23a2Schristos       if (ELF32_R_TYPE (irel->r_info) == (int) R_MICROBLAZE_64_PCREL)
1836377e23a2Schristos 	{
1837377e23a2Schristos 	  symval = symval + irel->r_addend
1838377e23a2Schristos 	    - (irel->r_offset
1839377e23a2Schristos 	       + sec->output_section->vma
1840377e23a2Schristos 	       + sec->output_offset);
1841377e23a2Schristos 	}
184207163879Schristos       else if (ELF32_R_TYPE (irel->r_info) == (int) R_MICROBLAZE_TEXTREL_64)
184307163879Schristos 	{
184407163879Schristos 	  symval = symval + irel->r_addend - (sec->output_section->vma);
184507163879Schristos 	}
1846377e23a2Schristos       else
1847377e23a2Schristos 	symval += irel->r_addend;
1848377e23a2Schristos 
1849377e23a2Schristos       if ((symval & 0xffff8000) == 0
1850377e23a2Schristos 	  || (symval & 0xffff8000) == 0xffff8000)
1851377e23a2Schristos 	{
1852377e23a2Schristos 	  /* We can delete this instruction.  */
1853377e23a2Schristos 	  sec->relax[sec->relax_count].addr = irel->r_offset;
1854377e23a2Schristos 	  sec->relax[sec->relax_count].size = INST_WORD_SIZE;
1855377e23a2Schristos 	  sec->relax_count++;
1856377e23a2Schristos 
1857377e23a2Schristos 	  /* Rewrite relocation type.  */
1858377e23a2Schristos 	  switch ((enum elf_microblaze_reloc_type) ELF32_R_TYPE (irel->r_info))
1859377e23a2Schristos 	    {
1860377e23a2Schristos 	    case R_MICROBLAZE_64_PCREL:
1861377e23a2Schristos 	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1862377e23a2Schristos 					   (int) R_MICROBLAZE_32_PCREL_LO);
1863377e23a2Schristos 	      break;
1864377e23a2Schristos 	    case R_MICROBLAZE_64:
1865377e23a2Schristos 	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1866377e23a2Schristos 					   (int) R_MICROBLAZE_32_LO);
1867377e23a2Schristos 	      break;
186807163879Schristos 	    case R_MICROBLAZE_TEXTREL_64:
186907163879Schristos 	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
187007163879Schristos 					   (int) R_MICROBLAZE_TEXTREL_32_LO);
187107163879Schristos 	      break;
1872377e23a2Schristos 	    default:
1873377e23a2Schristos 	      /* Cannot happen.  */
1874377e23a2Schristos 	      BFD_ASSERT (FALSE);
1875377e23a2Schristos 	    }
1876377e23a2Schristos 	}
1877377e23a2Schristos     } /* Loop through all relocations.  */
1878377e23a2Schristos 
1879377e23a2Schristos   /* Loop through the relocs again, and see if anything needs to change.  */
1880377e23a2Schristos   if (sec->relax_count > 0)
1881377e23a2Schristos     {
1882377e23a2Schristos       shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1883377e23a2Schristos       rel_count = 0;
1884377e23a2Schristos       sec->relax[sec->relax_count].addr = sec->size;
1885377e23a2Schristos 
1886377e23a2Schristos       for (irel = internal_relocs; irel < irelend; irel++, rel_count++)
1887377e23a2Schristos 	{
1888377e23a2Schristos 	  bfd_vma nraddr;
1889377e23a2Schristos 
1890377e23a2Schristos 	  /* Get the new reloc address.  */
189148596154Schristos 	  nraddr = irel->r_offset - calc_fixup (irel->r_offset, 0, sec);
1892377e23a2Schristos 	  switch ((enum elf_microblaze_reloc_type) ELF32_R_TYPE (irel->r_info))
1893377e23a2Schristos 	    {
1894377e23a2Schristos 	    default:
1895377e23a2Schristos 	      break;
1896377e23a2Schristos 	    case R_MICROBLAZE_64_PCREL:
1897377e23a2Schristos 	      break;
189807163879Schristos 	    case R_MICROBLAZE_TEXTREL_64:
189907163879Schristos 	    case R_MICROBLAZE_TEXTREL_32_LO:
1900377e23a2Schristos 	    case R_MICROBLAZE_64:
1901377e23a2Schristos 	    case R_MICROBLAZE_32_LO:
1902377e23a2Schristos 	      /* If this reloc is against a symbol defined in this
1903377e23a2Schristos 		 section, we must check the addend to see it will put the value in
1904377e23a2Schristos 		 range to be adjusted, and hence must be changed.  */
1905377e23a2Schristos 	      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1906377e23a2Schristos 		{
1907377e23a2Schristos 		  isym = isymbuf + ELF32_R_SYM (irel->r_info);
1908377e23a2Schristos 		  /* Only handle relocs against .text.  */
1909377e23a2Schristos 		  if (isym->st_shndx == shndx
1910377e23a2Schristos 		      && ELF32_ST_TYPE (isym->st_info) == STT_SECTION)
191148596154Schristos 		    irel->r_addend -= calc_fixup (irel->r_addend, 0, sec);
1912377e23a2Schristos 		}
1913377e23a2Schristos 	      break;
1914377e23a2Schristos 	    case R_MICROBLAZE_NONE:
1915377e23a2Schristos 	      {
1916377e23a2Schristos 		/* This was a PC-relative instruction that was
1917377e23a2Schristos 		   completely resolved.  */
1918377e23a2Schristos 		int sfix, efix;
1919377e23a2Schristos 		bfd_vma target_address;
1920377e23a2Schristos 		target_address = irel->r_addend + irel->r_offset;
192148596154Schristos 		sfix = calc_fixup (irel->r_offset, 0, sec);
192248596154Schristos 		efix = calc_fixup (target_address, 0, sec);
1923377e23a2Schristos 		irel->r_addend -= (efix - sfix);
1924377e23a2Schristos 		/* Should use HOWTO.  */
192548596154Schristos 		microblaze_bfd_write_imm_value_32 (abfd, contents + irel->r_offset,
192648596154Schristos 						   irel->r_addend);
1927377e23a2Schristos 	      }
1928377e23a2Schristos 	      break;
1929377e23a2Schristos 	    case R_MICROBLAZE_64_NONE:
1930377e23a2Schristos 	      {
1931377e23a2Schristos 		/* This was a PC-relative 64-bit instruction that was
1932377e23a2Schristos 		   completely resolved.  */
1933377e23a2Schristos 		int sfix, efix;
1934377e23a2Schristos 		bfd_vma target_address;
1935377e23a2Schristos 		target_address = irel->r_addend + irel->r_offset + INST_WORD_SIZE;
193648596154Schristos 		sfix = calc_fixup (irel->r_offset + INST_WORD_SIZE, 0, sec);
193748596154Schristos 		efix = calc_fixup (target_address, 0, sec);
1938377e23a2Schristos 		irel->r_addend -= (efix - sfix);
193948596154Schristos     microblaze_bfd_write_imm_value_32 (abfd, contents + irel->r_offset
194048596154Schristos 				       + INST_WORD_SIZE, irel->r_addend);
1941377e23a2Schristos 	      }
1942377e23a2Schristos 	      break;
1943377e23a2Schristos 	    }
1944377e23a2Schristos 	  irel->r_offset = nraddr;
1945377e23a2Schristos 	} /* Change all relocs in this section.  */
1946377e23a2Schristos 
1947377e23a2Schristos       /* Look through all other sections.  */
1948377e23a2Schristos       for (o = abfd->sections; o != NULL; o = o->next)
1949377e23a2Schristos 	{
1950377e23a2Schristos 	  Elf_Internal_Rela *irelocs;
1951377e23a2Schristos 	  Elf_Internal_Rela *irelscan, *irelscanend;
1952377e23a2Schristos 	  bfd_byte *ocontents;
1953377e23a2Schristos 
1954377e23a2Schristos 	  if (o == sec
1955377e23a2Schristos 	      || (o->flags & SEC_RELOC) == 0
1956377e23a2Schristos 	      || o->reloc_count == 0)
1957377e23a2Schristos 	    continue;
1958377e23a2Schristos 
1959377e23a2Schristos 	  /* We always cache the relocs.  Perhaps, if info->keep_memory is
1960377e23a2Schristos 	     FALSE, we should free them, if we are permitted to.  */
1961377e23a2Schristos 
1962377e23a2Schristos 	  irelocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, TRUE);
1963377e23a2Schristos 	  if (irelocs == NULL)
1964377e23a2Schristos 	    goto error_return;
1965377e23a2Schristos 
1966377e23a2Schristos 	  ocontents = NULL;
1967377e23a2Schristos 	  irelscanend = irelocs + o->reloc_count;
1968377e23a2Schristos 	  for (irelscan = irelocs; irelscan < irelscanend; irelscan++)
1969377e23a2Schristos 	    {
1970377e23a2Schristos 	      if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32)
1971377e23a2Schristos 		{
1972377e23a2Schristos 		  isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
1973377e23a2Schristos 
1974377e23a2Schristos 		  /* Look at the reloc only if the value has been resolved.  */
1975377e23a2Schristos 		  if (isym->st_shndx == shndx
1976377e23a2Schristos 		      && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
1977377e23a2Schristos 		    {
1978377e23a2Schristos 		      if (ocontents == NULL)
1979377e23a2Schristos 			{
1980377e23a2Schristos 			  if (elf_section_data (o)->this_hdr.contents != NULL)
1981377e23a2Schristos 			    ocontents = elf_section_data (o)->this_hdr.contents;
1982377e23a2Schristos 			  else
1983377e23a2Schristos 			    {
1984377e23a2Schristos 			      /* We always cache the section contents.
1985377e23a2Schristos 				 Perhaps, if info->keep_memory is FALSE, we
1986377e23a2Schristos 				 should free them, if we are permitted to.  */
1987377e23a2Schristos 			      if (o->rawsize == 0)
1988377e23a2Schristos 				o->rawsize = o->size;
1989377e23a2Schristos 			      ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
1990377e23a2Schristos 			      if (ocontents == NULL)
1991377e23a2Schristos 				goto error_return;
1992377e23a2Schristos 			      if (!bfd_get_section_contents (abfd, o, ocontents,
1993377e23a2Schristos 							     (file_ptr) 0,
1994377e23a2Schristos 							     o->rawsize))
1995377e23a2Schristos 				goto error_return;
1996377e23a2Schristos 			      elf_section_data (o)->this_hdr.contents = ocontents;
1997377e23a2Schristos 			    }
1998377e23a2Schristos 
1999377e23a2Schristos 			}
200048596154Schristos 		      irelscan->r_addend -= calc_fixup (irelscan->r_addend, 0, sec);
2001377e23a2Schristos 		    }
2002377e23a2Schristos 		  else if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_SYM_OP_SYM)
2003377e23a2Schristos 		    {
2004377e23a2Schristos 		      isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
2005377e23a2Schristos 
2006377e23a2Schristos 		      /* Look at the reloc only if the value has been resolved.  */
2007377e23a2Schristos 		      if (ocontents == NULL)
2008377e23a2Schristos 			{
2009377e23a2Schristos 			  if (elf_section_data (o)->this_hdr.contents != NULL)
2010377e23a2Schristos 			    ocontents = elf_section_data (o)->this_hdr.contents;
2011377e23a2Schristos 			  else
2012377e23a2Schristos 			    {
2013377e23a2Schristos 			      /* We always cache the section contents.
2014377e23a2Schristos 				 Perhaps, if info->keep_memory is FALSE, we
2015377e23a2Schristos 				 should free them, if we are permitted to.  */
2016377e23a2Schristos 
2017377e23a2Schristos 			      if (o->rawsize == 0)
2018377e23a2Schristos 				o->rawsize = o->size;
2019377e23a2Schristos 			      ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
2020377e23a2Schristos 			      if (ocontents == NULL)
2021377e23a2Schristos 				goto error_return;
2022377e23a2Schristos 			      if (!bfd_get_section_contents (abfd, o, ocontents,
2023377e23a2Schristos 							     (file_ptr) 0,
2024377e23a2Schristos 							     o->rawsize))
2025377e23a2Schristos 				goto error_return;
2026377e23a2Schristos 			      elf_section_data (o)->this_hdr.contents = ocontents;
2027377e23a2Schristos 			    }
2028377e23a2Schristos 			}
2029377e23a2Schristos 		      irelscan->r_addend -= calc_fixup (irel->r_addend
2030377e23a2Schristos 							+ isym->st_value,
203148596154Schristos 							0,
2032377e23a2Schristos 							sec);
2033377e23a2Schristos 		    }
2034377e23a2Schristos 		}
2035377e23a2Schristos 	      else if ((ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_PCREL_LO)
203607163879Schristos 		       || (ELF32_R_TYPE (irelscan->r_info)
203707163879Schristos 				   == (int) R_MICROBLAZE_32_LO)
203807163879Schristos 		       || (ELF32_R_TYPE (irelscan->r_info)
203907163879Schristos 				   == (int) R_MICROBLAZE_TEXTREL_32_LO))
2040377e23a2Schristos 		{
2041377e23a2Schristos 		  isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
2042377e23a2Schristos 
2043377e23a2Schristos 		  /* Look at the reloc only if the value has been resolved.  */
2044377e23a2Schristos 		  if (isym->st_shndx == shndx
2045377e23a2Schristos 		      && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
2046377e23a2Schristos 		    {
2047377e23a2Schristos 		      bfd_vma immediate;
2048377e23a2Schristos 		      bfd_vma target_address;
2049377e23a2Schristos 
2050377e23a2Schristos 		      if (ocontents == NULL)
2051377e23a2Schristos 			{
2052377e23a2Schristos 			  if (elf_section_data (o)->this_hdr.contents != NULL)
2053377e23a2Schristos 			    ocontents = elf_section_data (o)->this_hdr.contents;
2054377e23a2Schristos 			  else
2055377e23a2Schristos 			    {
2056377e23a2Schristos 			      /* We always cache the section contents.
2057377e23a2Schristos 				 Perhaps, if info->keep_memory is FALSE, we
2058377e23a2Schristos 				 should free them, if we are permitted to.  */
2059377e23a2Schristos 			      if (o->rawsize == 0)
2060377e23a2Schristos 				o->rawsize = o->size;
2061377e23a2Schristos 			      ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
2062377e23a2Schristos 			      if (ocontents == NULL)
2063377e23a2Schristos 				goto error_return;
2064377e23a2Schristos 			      if (!bfd_get_section_contents (abfd, o, ocontents,
2065377e23a2Schristos 							     (file_ptr) 0,
2066377e23a2Schristos 							     o->rawsize))
2067377e23a2Schristos 				goto error_return;
2068377e23a2Schristos 			      elf_section_data (o)->this_hdr.contents = ocontents;
2069377e23a2Schristos 			    }
2070377e23a2Schristos 			}
2071377e23a2Schristos 
207248596154Schristos 		      unsigned long instr = bfd_get_32 (abfd, ocontents + irelscan->r_offset);
207348596154Schristos 		      immediate = instr & 0x0000ffff;
2074377e23a2Schristos 		      target_address = immediate;
207548596154Schristos 		      offset = calc_fixup (target_address, 0, sec);
2076377e23a2Schristos 		      immediate -= offset;
2077377e23a2Schristos 		      irelscan->r_addend -= offset;
207848596154Schristos 	  microblaze_bfd_write_imm_value_32 (abfd, ocontents + irelscan->r_offset,
207948596154Schristos 					     irelscan->r_addend);
2080377e23a2Schristos 		    }
2081377e23a2Schristos 		}
2082377e23a2Schristos 
208307163879Schristos 	      if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64
208407163879Schristos 		  || (ELF32_R_TYPE (irelscan->r_info)
208507163879Schristos 			      == (int) R_MICROBLAZE_TEXTREL_64))
2086377e23a2Schristos 		{
2087377e23a2Schristos 		  isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
2088377e23a2Schristos 
2089377e23a2Schristos 		  /* Look at the reloc only if the value has been resolved.  */
2090377e23a2Schristos 		  if (isym->st_shndx == shndx
2091377e23a2Schristos 		      && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
2092377e23a2Schristos 		    {
2093377e23a2Schristos 		      bfd_vma immediate;
2094377e23a2Schristos 
2095377e23a2Schristos 		      if (ocontents == NULL)
2096377e23a2Schristos 			{
2097377e23a2Schristos 			  if (elf_section_data (o)->this_hdr.contents != NULL)
2098377e23a2Schristos 			    ocontents = elf_section_data (o)->this_hdr.contents;
2099377e23a2Schristos 			  else
2100377e23a2Schristos 			    {
2101377e23a2Schristos 			      /* We always cache the section contents.
2102377e23a2Schristos 				 Perhaps, if info->keep_memory is FALSE, we
2103377e23a2Schristos 				 should free them, if we are permitted to.  */
2104377e23a2Schristos 
2105377e23a2Schristos 			      if (o->rawsize == 0)
2106377e23a2Schristos 				o->rawsize = o->size;
2107377e23a2Schristos 			      ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
2108377e23a2Schristos 			      if (ocontents == NULL)
2109377e23a2Schristos 				goto error_return;
2110377e23a2Schristos 			      if (!bfd_get_section_contents (abfd, o, ocontents,
2111377e23a2Schristos 							     (file_ptr) 0,
2112377e23a2Schristos 							     o->rawsize))
2113377e23a2Schristos 				goto error_return;
2114377e23a2Schristos 			      elf_section_data (o)->this_hdr.contents = ocontents;
2115377e23a2Schristos 			    }
2116377e23a2Schristos 			}
211748596154Schristos 	  unsigned long instr_hi =  bfd_get_32 (abfd, ocontents
211848596154Schristos 						+ irelscan->r_offset);
211948596154Schristos 	  unsigned long instr_lo =  bfd_get_32 (abfd, ocontents
2120377e23a2Schristos 						+ irelscan->r_offset
212148596154Schristos 						+ INST_WORD_SIZE);
212248596154Schristos 	  immediate = (instr_hi & 0x0000ffff) << 16;
212348596154Schristos 	  immediate |= (instr_lo & 0x0000ffff);
212448596154Schristos 		      offset = calc_fixup (irelscan->r_addend, 0, sec);
2125377e23a2Schristos 		      immediate -= offset;
2126377e23a2Schristos 		      irelscan->r_addend -= offset;
2127377e23a2Schristos 		    }
2128377e23a2Schristos 		}
2129377e23a2Schristos 	      else if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64_PCREL)
2130377e23a2Schristos 		{
2131377e23a2Schristos 		  isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
2132377e23a2Schristos 
2133377e23a2Schristos 		  /* Look at the reloc only if the value has been resolved.  */
2134377e23a2Schristos 		  if (isym->st_shndx == shndx
2135377e23a2Schristos 		      && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
2136377e23a2Schristos 		    {
2137377e23a2Schristos 		      bfd_vma immediate;
2138377e23a2Schristos 		      bfd_vma target_address;
2139377e23a2Schristos 
2140377e23a2Schristos 		      if (ocontents == NULL)
2141377e23a2Schristos 			{
2142377e23a2Schristos 			  if (elf_section_data (o)->this_hdr.contents != NULL)
2143377e23a2Schristos 			    ocontents = elf_section_data (o)->this_hdr.contents;
2144377e23a2Schristos 			  else
2145377e23a2Schristos 			    {
2146377e23a2Schristos 			      /* We always cache the section contents.
2147377e23a2Schristos 				 Perhaps, if info->keep_memory is FALSE, we
2148377e23a2Schristos 				 should free them, if we are permitted to.  */
2149377e23a2Schristos 			      if (o->rawsize == 0)
2150377e23a2Schristos 				o->rawsize = o->size;
2151377e23a2Schristos 			      ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
2152377e23a2Schristos 			      if (ocontents == NULL)
2153377e23a2Schristos 				goto error_return;
2154377e23a2Schristos 			      if (!bfd_get_section_contents (abfd, o, ocontents,
2155377e23a2Schristos 							     (file_ptr) 0,
2156377e23a2Schristos 							     o->rawsize))
2157377e23a2Schristos 				goto error_return;
2158377e23a2Schristos 			      elf_section_data (o)->this_hdr.contents = ocontents;
2159377e23a2Schristos 			    }
2160377e23a2Schristos 			}
216148596154Schristos 	  unsigned long instr_hi =  bfd_get_32 (abfd, ocontents
216248596154Schristos 						+ irelscan->r_offset);
216348596154Schristos 	  unsigned long instr_lo =  bfd_get_32 (abfd, ocontents
216448596154Schristos 						+ irelscan->r_offset
216548596154Schristos 						+ INST_WORD_SIZE);
216648596154Schristos 	  immediate = (instr_hi & 0x0000ffff) << 16;
216748596154Schristos 	  immediate |= (instr_lo & 0x0000ffff);
2168377e23a2Schristos 		      target_address = immediate;
216948596154Schristos 		      offset = calc_fixup (target_address, 0, sec);
2170377e23a2Schristos 		      immediate -= offset;
2171377e23a2Schristos 		      irelscan->r_addend -= offset;
217248596154Schristos 	  microblaze_bfd_write_imm_value_64 (abfd, ocontents
217348596154Schristos 					     + irelscan->r_offset, immediate);
2174377e23a2Schristos 		    }
2175377e23a2Schristos 		}
2176377e23a2Schristos 	    }
2177377e23a2Schristos 	}
2178377e23a2Schristos 
2179377e23a2Schristos       /* Adjust the local symbols defined in this section.  */
2180377e23a2Schristos       isymend = isymbuf + symtab_hdr->sh_info;
2181377e23a2Schristos       for (isym = isymbuf; isym < isymend; isym++)
2182377e23a2Schristos 	{
2183377e23a2Schristos 	  if (isym->st_shndx == shndx)
218448596154Schristos 	    {
218548596154Schristos 	      isym->st_value -= calc_fixup (isym->st_value, 0, sec);
218648596154Schristos 	      if (isym->st_size)
218748596154Schristos 		isym->st_size -= calc_fixup (isym->st_value, isym->st_size, sec);
218848596154Schristos 	    }
2189377e23a2Schristos 	}
2190377e23a2Schristos 
2191377e23a2Schristos       /* Now adjust the global symbols defined in this section.  */
2192377e23a2Schristos       isym = isymbuf + symtab_hdr->sh_info;
219348596154Schristos       symcount =  (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)) - symtab_hdr->sh_info;
219448596154Schristos       for (sym_index = 0; sym_index < symcount; sym_index++)
2195377e23a2Schristos 	{
2196377e23a2Schristos 	  sym_hash = elf_sym_hashes (abfd)[sym_index];
219748596154Schristos 	  if ((sym_hash->root.type == bfd_link_hash_defined
2198377e23a2Schristos 		  || sym_hash->root.type == bfd_link_hash_defweak)
2199377e23a2Schristos 	      && sym_hash->root.u.def.section == sec)
2200377e23a2Schristos 	    {
2201377e23a2Schristos 	      sym_hash->root.u.def.value -= calc_fixup (sym_hash->root.u.def.value,
220248596154Schristos 							0, sec);
220348596154Schristos 	      if (sym_hash->size)
220448596154Schristos 		sym_hash->size -= calc_fixup (sym_hash->root.u.def.value,
220548596154Schristos 					      sym_hash->size, sec);
2206377e23a2Schristos 	    }
2207377e23a2Schristos 	}
2208377e23a2Schristos 
2209377e23a2Schristos       /* Physically move the code and change the cooked size.  */
2210377e23a2Schristos       dest = sec->relax[0].addr;
2211377e23a2Schristos       for (i = 0; i < sec->relax_count; i++)
2212377e23a2Schristos 	{
2213377e23a2Schristos 	  int len;
2214377e23a2Schristos 	  src = sec->relax[i].addr + sec->relax[i].size;
2215377e23a2Schristos 	  len = sec->relax[i+1].addr - sec->relax[i].addr - sec->relax[i].size;
2216377e23a2Schristos 
2217377e23a2Schristos 	  memmove (contents + dest, contents + src, len);
2218377e23a2Schristos 	  sec->size -= sec->relax[i].size;
2219377e23a2Schristos 	  dest += len;
2220377e23a2Schristos 	}
2221377e23a2Schristos 
2222377e23a2Schristos       elf_section_data (sec)->relocs = internal_relocs;
2223377e23a2Schristos       free_relocs = NULL;
2224377e23a2Schristos 
2225377e23a2Schristos       elf_section_data (sec)->this_hdr.contents = contents;
2226377e23a2Schristos       free_contents = NULL;
2227377e23a2Schristos 
2228377e23a2Schristos       symtab_hdr->contents = (bfd_byte *) isymbuf;
2229377e23a2Schristos     }
2230377e23a2Schristos 
2231377e23a2Schristos   free (free_relocs);
2232377e23a2Schristos   free_relocs = NULL;
2233377e23a2Schristos 
2234377e23a2Schristos   if (free_contents != NULL)
2235377e23a2Schristos     {
2236377e23a2Schristos       if (!link_info->keep_memory)
2237377e23a2Schristos 	free (free_contents);
2238377e23a2Schristos       else
2239377e23a2Schristos 	/* Cache the section contents for elf_link_input_bfd.  */
2240377e23a2Schristos 	elf_section_data (sec)->this_hdr.contents = contents;
2241377e23a2Schristos       free_contents = NULL;
2242377e23a2Schristos     }
2243377e23a2Schristos 
2244377e23a2Schristos   if (sec->relax_count == 0)
2245377e23a2Schristos     {
224648596154Schristos       *again = FALSE;
2247377e23a2Schristos       free (sec->relax);
2248377e23a2Schristos       sec->relax = NULL;
2249377e23a2Schristos     }
225048596154Schristos   else
225148596154Schristos     *again = TRUE;
2252377e23a2Schristos   return TRUE;
2253377e23a2Schristos 
2254377e23a2Schristos  error_return:
2255377e23a2Schristos   free (free_relocs);
2256377e23a2Schristos   free (free_contents);
2257377e23a2Schristos   free (sec->relax);
2258377e23a2Schristos   sec->relax = NULL;
2259377e23a2Schristos   sec->relax_count = 0;
2260377e23a2Schristos   return FALSE;
2261377e23a2Schristos }
2262377e23a2Schristos 
2263377e23a2Schristos /* Return the section that should be marked against GC for a given
2264377e23a2Schristos    relocation.  */
2265377e23a2Schristos 
2266377e23a2Schristos 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)2267377e23a2Schristos microblaze_elf_gc_mark_hook (asection *sec,
2268377e23a2Schristos 			     struct bfd_link_info * info,
2269377e23a2Schristos 			     Elf_Internal_Rela * rel,
2270377e23a2Schristos 			     struct elf_link_hash_entry * h,
2271377e23a2Schristos 			     Elf_Internal_Sym * sym)
2272377e23a2Schristos {
2273377e23a2Schristos   if (h != NULL)
2274377e23a2Schristos     switch (ELF32_R_TYPE (rel->r_info))
2275377e23a2Schristos       {
2276377e23a2Schristos       case R_MICROBLAZE_GNU_VTINHERIT:
2277377e23a2Schristos       case R_MICROBLAZE_GNU_VTENTRY:
2278377e23a2Schristos 	return NULL;
2279377e23a2Schristos       }
2280377e23a2Schristos 
2281377e23a2Schristos   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
2282377e23a2Schristos }
2283377e23a2Schristos 
2284377e23a2Schristos /* PIC support.  */
2285377e23a2Schristos 
2286377e23a2Schristos #define PLT_ENTRY_SIZE 16
2287377e23a2Schristos 
2288377e23a2Schristos #define PLT_ENTRY_WORD_0  0xb0000000	      /* "imm 0".  */
2289377e23a2Schristos #define PLT_ENTRY_WORD_1  0xe9940000	      /* "lwi r12,r20,0" - relocated to lwi r12,r20,func@GOT.  */
2290377e23a2Schristos #define PLT_ENTRY_WORD_1_NOPIC	0xe9800000    /* "lwi r12,r0,0" - non-PIC object.  */
2291377e23a2Schristos #define PLT_ENTRY_WORD_2  0x98186000	      /* "brad r12".  */
2292377e23a2Schristos #define PLT_ENTRY_WORD_3  0x80000000	      /* "nop".  */
2293377e23a2Schristos 
229448596154Schristos static bfd_boolean
update_local_sym_info(bfd * abfd,Elf_Internal_Shdr * symtab_hdr,unsigned long r_symndx,unsigned int tls_type)229548596154Schristos update_local_sym_info (bfd *abfd,
229648596154Schristos 		       Elf_Internal_Shdr *symtab_hdr,
229748596154Schristos 		       unsigned long r_symndx,
229848596154Schristos 		       unsigned int tls_type)
229948596154Schristos {
230048596154Schristos   bfd_signed_vma *local_got_refcounts = elf_local_got_refcounts (abfd);
230148596154Schristos   unsigned char *local_got_tls_masks;
230248596154Schristos 
230348596154Schristos   if (local_got_refcounts == NULL)
230448596154Schristos     {
230548596154Schristos       bfd_size_type size = symtab_hdr->sh_info;
230648596154Schristos 
230748596154Schristos       size *= (sizeof (*local_got_refcounts) + sizeof (*local_got_tls_masks));
230848596154Schristos       local_got_refcounts = bfd_zalloc (abfd, size);
230948596154Schristos       if (local_got_refcounts == NULL)
231048596154Schristos 	return FALSE;
231148596154Schristos       elf_local_got_refcounts (abfd) = local_got_refcounts;
231248596154Schristos     }
231348596154Schristos 
231448596154Schristos   local_got_tls_masks =
231548596154Schristos 	 (unsigned char *) (local_got_refcounts + symtab_hdr->sh_info);
231648596154Schristos   local_got_tls_masks[r_symndx] |= tls_type;
231748596154Schristos   local_got_refcounts[r_symndx] += 1;
231848596154Schristos 
231948596154Schristos   return TRUE;
232048596154Schristos }
2321377e23a2Schristos /* Look through the relocs for a section during the first phase.  */
2322377e23a2Schristos 
2323377e23a2Schristos static bfd_boolean
microblaze_elf_check_relocs(bfd * abfd,struct bfd_link_info * info,asection * sec,const Elf_Internal_Rela * relocs)2324377e23a2Schristos microblaze_elf_check_relocs (bfd * abfd,
2325377e23a2Schristos 			     struct bfd_link_info * info,
2326377e23a2Schristos 			     asection * sec,
2327377e23a2Schristos 			     const Elf_Internal_Rela * relocs)
2328377e23a2Schristos {
2329377e23a2Schristos   Elf_Internal_Shdr *		symtab_hdr;
2330377e23a2Schristos   struct elf_link_hash_entry ** sym_hashes;
2331377e23a2Schristos   struct elf_link_hash_entry ** sym_hashes_end;
2332377e23a2Schristos   const Elf_Internal_Rela *	rel;
2333377e23a2Schristos   const Elf_Internal_Rela *	rel_end;
2334377e23a2Schristos   struct elf32_mb_link_hash_table *htab;
2335377e23a2Schristos   asection *sreloc = NULL;
2336377e23a2Schristos 
2337c03b94e9Schristos   if (bfd_link_relocatable (info))
2338377e23a2Schristos     return TRUE;
2339377e23a2Schristos 
2340377e23a2Schristos   htab = elf32_mb_hash_table (info);
2341377e23a2Schristos   if (htab == NULL)
2342377e23a2Schristos     return FALSE;
2343377e23a2Schristos 
2344377e23a2Schristos   symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
2345377e23a2Schristos   sym_hashes = elf_sym_hashes (abfd);
2346377e23a2Schristos   sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
2347377e23a2Schristos   if (!elf_bad_symtab (abfd))
2348377e23a2Schristos     sym_hashes_end -= symtab_hdr->sh_info;
2349377e23a2Schristos 
2350377e23a2Schristos   rel_end = relocs + sec->reloc_count;
2351377e23a2Schristos 
2352377e23a2Schristos   for (rel = relocs; rel < rel_end; rel++)
2353377e23a2Schristos     {
2354377e23a2Schristos       unsigned int r_type;
2355377e23a2Schristos       struct elf_link_hash_entry * h;
2356377e23a2Schristos       unsigned long r_symndx;
235748596154Schristos       unsigned char tls_type = 0;
2358377e23a2Schristos 
2359377e23a2Schristos       r_symndx = ELF32_R_SYM (rel->r_info);
2360377e23a2Schristos       r_type = ELF32_R_TYPE (rel->r_info);
2361377e23a2Schristos 
2362377e23a2Schristos       if (r_symndx < symtab_hdr->sh_info)
2363377e23a2Schristos 	h = NULL;
2364377e23a2Schristos       else
23657af5a897Schristos 	{
2366377e23a2Schristos 	  h = sym_hashes [r_symndx - symtab_hdr->sh_info];
236707163879Schristos 	  while (h->root.type == bfd_link_hash_indirect
236807163879Schristos 		 || h->root.type == bfd_link_hash_warning)
236907163879Schristos 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
23707af5a897Schristos 	}
23717af5a897Schristos 
2372377e23a2Schristos       switch (r_type)
2373377e23a2Schristos 	{
2374377e23a2Schristos 	  /* This relocation describes the C++ object vtable hierarchy.
2375377e23a2Schristos 	     Reconstruct it for later use during GC.  */
2376377e23a2Schristos 	case R_MICROBLAZE_GNU_VTINHERIT:
2377377e23a2Schristos 	  if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
2378377e23a2Schristos 	    return FALSE;
2379377e23a2Schristos 	  break;
2380377e23a2Schristos 
2381377e23a2Schristos 	  /* This relocation describes which C++ vtable entries are actually
2382377e23a2Schristos 	     used.  Record for later use during GC.  */
2383377e23a2Schristos 	case R_MICROBLAZE_GNU_VTENTRY:
2384377e23a2Schristos 	  if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
2385377e23a2Schristos 	    return FALSE;
2386377e23a2Schristos 	  break;
2387377e23a2Schristos 
2388377e23a2Schristos 	  /* This relocation requires .plt entry.  */
2389377e23a2Schristos 	case R_MICROBLAZE_PLT_64:
2390377e23a2Schristos 	  if (h != NULL)
2391377e23a2Schristos 	    {
2392377e23a2Schristos 	      h->needs_plt = 1;
2393377e23a2Schristos 	      h->plt.refcount += 1;
2394377e23a2Schristos 	    }
2395377e23a2Schristos 	  break;
2396377e23a2Schristos 
2397377e23a2Schristos 	  /* This relocation requires .got entry.  */
239848596154Schristos 	case R_MICROBLAZE_TLSGD:
239948596154Schristos 	  tls_type |= (TLS_TLS | TLS_GD);
240048596154Schristos 	  goto dogottls;
240148596154Schristos 	case R_MICROBLAZE_TLSLD:
240248596154Schristos 	  tls_type |= (TLS_TLS | TLS_LD);
24031c468f90Schristos 	  /* Fall through.  */
240448596154Schristos 	dogottls:
240548596154Schristos 	  sec->has_tls_reloc = 1;
24061c468f90Schristos 	  /* Fall through.  */
2407377e23a2Schristos 	case R_MICROBLAZE_GOT_64:
24081c468f90Schristos 	  if (htab->elf.sgot == NULL)
2409377e23a2Schristos 	    {
2410377e23a2Schristos 	      if (htab->elf.dynobj == NULL)
2411377e23a2Schristos 		htab->elf.dynobj = abfd;
24121c468f90Schristos 	      if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
2413377e23a2Schristos 		return FALSE;
2414377e23a2Schristos 	    }
2415377e23a2Schristos 	  if (h != NULL)
2416377e23a2Schristos 	    {
2417377e23a2Schristos 	      h->got.refcount += 1;
241848596154Schristos 	      elf32_mb_hash_entry (h)->tls_mask |= tls_type;
2419377e23a2Schristos 	    }
2420377e23a2Schristos 	  else
2421377e23a2Schristos 	    {
242248596154Schristos 	      if (! update_local_sym_info(abfd, symtab_hdr, r_symndx, tls_type) )
2423377e23a2Schristos 		return FALSE;
2424377e23a2Schristos 	    }
2425377e23a2Schristos 	  break;
2426377e23a2Schristos 
242707163879Schristos 	case R_MICROBLAZE_GOTOFF_64:
242807163879Schristos 	case R_MICROBLAZE_GOTOFF_32:
242907163879Schristos 	  if (htab->elf.sgot == NULL)
243007163879Schristos 	    {
243107163879Schristos 	      if (htab->elf.dynobj == NULL)
243207163879Schristos 		htab->elf.dynobj = abfd;
243307163879Schristos 	      if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
243407163879Schristos 		return FALSE;
243507163879Schristos 	    }
243607163879Schristos 	  break;
243707163879Schristos 
2438377e23a2Schristos 	case R_MICROBLAZE_64:
2439377e23a2Schristos 	case R_MICROBLAZE_64_PCREL:
2440377e23a2Schristos 	case R_MICROBLAZE_32:
2441377e23a2Schristos 	  {
2442c03b94e9Schristos 	    if (h != NULL && !bfd_link_pic (info))
2443377e23a2Schristos 	      {
2444377e23a2Schristos 		/* we may need a copy reloc.  */
2445377e23a2Schristos 		h->non_got_ref = 1;
2446377e23a2Schristos 
2447377e23a2Schristos 		/* we may also need a .plt entry.  */
2448377e23a2Schristos 		h->plt.refcount += 1;
2449377e23a2Schristos 		if (ELF32_R_TYPE (rel->r_info) != R_MICROBLAZE_64_PCREL)
2450377e23a2Schristos 		  h->pointer_equality_needed = 1;
2451377e23a2Schristos 	      }
2452377e23a2Schristos 
2453377e23a2Schristos 
2454377e23a2Schristos 	    /* If we are creating a shared library, and this is a reloc
2455377e23a2Schristos 	       against a global symbol, or a non PC relative reloc
2456377e23a2Schristos 	       against a local symbol, then we need to copy the reloc
2457377e23a2Schristos 	       into the shared library.  However, if we are linking with
2458377e23a2Schristos 	       -Bsymbolic, we do not need to copy a reloc against a
2459377e23a2Schristos 	       global symbol which is defined in an object we are
2460377e23a2Schristos 	       including in the link (i.e., DEF_REGULAR is set).  At
2461377e23a2Schristos 	       this point we have not seen all the input files, so it is
2462377e23a2Schristos 	       possible that DEF_REGULAR is not set now but will be set
2463377e23a2Schristos 	       later (it is never cleared).  In case of a weak definition,
2464377e23a2Schristos 	       DEF_REGULAR may be cleared later by a strong definition in
2465377e23a2Schristos 	       a shared library.  We account for that possibility below by
2466377e23a2Schristos 	       storing information in the relocs_copied field of the hash
2467377e23a2Schristos 	       table entry.  A similar situation occurs when creating
2468377e23a2Schristos 	       shared libraries and symbol visibility changes render the
2469377e23a2Schristos 	       symbol local.
2470377e23a2Schristos 
2471377e23a2Schristos 	       If on the other hand, we are creating an executable, we
2472377e23a2Schristos 	       may need to keep relocations for symbols satisfied by a
2473377e23a2Schristos 	       dynamic library if we manage to avoid copy relocs for the
2474377e23a2Schristos 	       symbol.  */
2475377e23a2Schristos 
2476c03b94e9Schristos 	    if ((bfd_link_pic (info)
2477377e23a2Schristos 		 && (sec->flags & SEC_ALLOC) != 0
2478377e23a2Schristos 		 && (r_type != R_MICROBLAZE_64_PCREL
2479377e23a2Schristos 		     || (h != NULL
2480377e23a2Schristos 			 && (! info->symbolic
2481377e23a2Schristos 			     || h->root.type == bfd_link_hash_defweak
2482377e23a2Schristos 			     || !h->def_regular))))
2483c03b94e9Schristos 		|| (!bfd_link_pic (info)
2484377e23a2Schristos 		    && (sec->flags & SEC_ALLOC) != 0
2485377e23a2Schristos 		    && h != NULL
2486377e23a2Schristos 		    && (h->root.type == bfd_link_hash_defweak
2487377e23a2Schristos 			|| !h->def_regular)))
2488377e23a2Schristos 	      {
248907163879Schristos 		struct elf_dyn_relocs *p;
249007163879Schristos 		struct elf_dyn_relocs **head;
2491377e23a2Schristos 
2492377e23a2Schristos 		/* When creating a shared object, we must copy these
2493377e23a2Schristos 		   relocs into the output file.  We create a reloc
2494377e23a2Schristos 		   section in dynobj and make room for the reloc.  */
2495377e23a2Schristos 
2496377e23a2Schristos 		if (sreloc == NULL)
2497377e23a2Schristos 		  {
2498377e23a2Schristos 		    bfd *dynobj;
2499377e23a2Schristos 
2500377e23a2Schristos 		    if (htab->elf.dynobj == NULL)
2501377e23a2Schristos 		      htab->elf.dynobj = abfd;
2502377e23a2Schristos 		    dynobj = htab->elf.dynobj;
2503377e23a2Schristos 
250448596154Schristos 		    sreloc = _bfd_elf_make_dynamic_reloc_section (sec, dynobj,
250548596154Schristos 								  2, abfd, 1);
2506377e23a2Schristos 		    if (sreloc == NULL)
2507377e23a2Schristos 		      return FALSE;
2508377e23a2Schristos 		  }
2509377e23a2Schristos 
2510377e23a2Schristos 		/* If this is a global symbol, we count the number of
2511377e23a2Schristos 		   relocations we need for this symbol.  */
2512377e23a2Schristos 		if (h != NULL)
2513*1424dfb3Schristos 		  head = &h->dyn_relocs;
2514377e23a2Schristos 		else
2515377e23a2Schristos 		  {
2516377e23a2Schristos 		    /* Track dynamic relocs needed for local syms too.
2517377e23a2Schristos 		       We really need local syms available to do this
2518377e23a2Schristos 		       easily.  Oh well.  */
2519377e23a2Schristos 
2520377e23a2Schristos 		    asection *s;
2521377e23a2Schristos 		    Elf_Internal_Sym *isym;
2522377e23a2Schristos 		    void *vpp;
2523377e23a2Schristos 
2524*1424dfb3Schristos 		    isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
2525377e23a2Schristos 						  abfd, r_symndx);
2526377e23a2Schristos 		    if (isym == NULL)
2527377e23a2Schristos 		      return FALSE;
2528377e23a2Schristos 
2529377e23a2Schristos 		    s = bfd_section_from_elf_index (abfd, isym->st_shndx);
2530377e23a2Schristos 		    if (s == NULL)
2531377e23a2Schristos 		      return FALSE;
2532377e23a2Schristos 
2533377e23a2Schristos 		    vpp = &elf_section_data (s)->local_dynrel;
253407163879Schristos 		    head = (struct elf_dyn_relocs **) vpp;
2535377e23a2Schristos 		  }
2536377e23a2Schristos 
2537377e23a2Schristos 		p = *head;
2538377e23a2Schristos 		if (p == NULL || p->sec != sec)
2539377e23a2Schristos 		  {
2540*1424dfb3Schristos 		    size_t amt = sizeof *p;
254107163879Schristos 		    p = ((struct elf_dyn_relocs *)
2542377e23a2Schristos 			 bfd_alloc (htab->elf.dynobj, amt));
2543377e23a2Schristos 		    if (p == NULL)
2544377e23a2Schristos 		      return FALSE;
2545377e23a2Schristos 		    p->next = *head;
2546377e23a2Schristos 		    *head = p;
2547377e23a2Schristos 		    p->sec = sec;
2548377e23a2Schristos 		    p->count = 0;
2549377e23a2Schristos 		    p->pc_count = 0;
2550377e23a2Schristos 		  }
2551377e23a2Schristos 
2552377e23a2Schristos 		p->count += 1;
2553377e23a2Schristos 		if (r_type == R_MICROBLAZE_64_PCREL)
2554377e23a2Schristos 		  p->pc_count += 1;
2555377e23a2Schristos 	      }
2556377e23a2Schristos 	  }
2557377e23a2Schristos 	  break;
2558377e23a2Schristos 	}
2559377e23a2Schristos     }
2560377e23a2Schristos 
2561377e23a2Schristos   return TRUE;
2562377e23a2Schristos }
2563377e23a2Schristos 
2564377e23a2Schristos /* Copy the extra info we tack onto an elf_link_hash_entry.  */
2565377e23a2Schristos 
2566377e23a2Schristos static void
microblaze_elf_copy_indirect_symbol(struct bfd_link_info * info,struct elf_link_hash_entry * dir,struct elf_link_hash_entry * ind)2567377e23a2Schristos microblaze_elf_copy_indirect_symbol (struct bfd_link_info *info,
2568377e23a2Schristos 				     struct elf_link_hash_entry *dir,
2569377e23a2Schristos 				     struct elf_link_hash_entry *ind)
2570377e23a2Schristos {
2571377e23a2Schristos   struct elf32_mb_link_hash_entry *edir, *eind;
2572377e23a2Schristos 
2573377e23a2Schristos   edir = (struct elf32_mb_link_hash_entry *) dir;
2574377e23a2Schristos   eind = (struct elf32_mb_link_hash_entry *) ind;
2575377e23a2Schristos 
257648596154Schristos   edir->tls_mask |= eind->tls_mask;
257748596154Schristos 
2578377e23a2Schristos   _bfd_elf_link_hash_copy_indirect (info, dir, ind);
2579377e23a2Schristos }
2580377e23a2Schristos 
2581377e23a2Schristos static bfd_boolean
microblaze_elf_adjust_dynamic_symbol(struct bfd_link_info * info,struct elf_link_hash_entry * h)2582377e23a2Schristos microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
2583377e23a2Schristos 				      struct elf_link_hash_entry *h)
2584377e23a2Schristos {
2585377e23a2Schristos   struct elf32_mb_link_hash_table *htab;
25861c468f90Schristos   asection *s, *srel;
2587377e23a2Schristos   unsigned int power_of_two;
2588377e23a2Schristos 
2589377e23a2Schristos   htab = elf32_mb_hash_table (info);
2590377e23a2Schristos   if (htab == NULL)
2591377e23a2Schristos     return FALSE;
2592377e23a2Schristos 
2593377e23a2Schristos   /* If this is a function, put it in the procedure linkage table.  We
2594377e23a2Schristos      will fill in the contents of the procedure linkage table later,
2595377e23a2Schristos      when we know the address of the .got section.  */
2596377e23a2Schristos   if (h->type == STT_FUNC
2597377e23a2Schristos       || h->needs_plt)
2598377e23a2Schristos     {
2599377e23a2Schristos       if (h->plt.refcount <= 0
2600377e23a2Schristos 	  || SYMBOL_CALLS_LOCAL (info, h)
2601377e23a2Schristos 	  || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
2602377e23a2Schristos 	      && h->root.type == bfd_link_hash_undefweak))
2603377e23a2Schristos 	{
2604377e23a2Schristos 	  /* This case can occur if we saw a PLT reloc in an input
2605377e23a2Schristos 	     file, but the symbol was never referred to by a dynamic
2606377e23a2Schristos 	     object, or if all references were garbage collected.  In
2607377e23a2Schristos 	     such a case, we don't actually need to build a procedure
2608377e23a2Schristos 	     linkage table, and we can just do a PC32 reloc instead.  */
2609377e23a2Schristos 	  h->plt.offset = (bfd_vma) -1;
2610377e23a2Schristos 	  h->needs_plt = 0;
2611377e23a2Schristos 	}
2612377e23a2Schristos 
2613377e23a2Schristos       return TRUE;
2614377e23a2Schristos     }
2615377e23a2Schristos   else
2616377e23a2Schristos     /* It's possible that we incorrectly decided a .plt reloc was
2617377e23a2Schristos        needed for an R_MICROBLAZE_64_PCREL reloc to a non-function sym in
2618377e23a2Schristos        check_relocs.  We can't decide accurately between function and
2619377e23a2Schristos        non-function syms in check-relocs;  Objects loaded later in
2620377e23a2Schristos        the link may change h->type.  So fix it now.  */
2621377e23a2Schristos     h->plt.offset = (bfd_vma) -1;
2622377e23a2Schristos 
2623377e23a2Schristos   /* If this is a weak symbol, and there is a real definition, the
2624377e23a2Schristos      processor independent code will have arranged for us to see the
2625377e23a2Schristos      real definition first, and we can just use the same value.  */
262607163879Schristos   if (h->is_weakalias)
2627377e23a2Schristos     {
262807163879Schristos       struct elf_link_hash_entry *def = weakdef (h);
262907163879Schristos       BFD_ASSERT (def->root.type == bfd_link_hash_defined);
263007163879Schristos       h->root.u.def.section = def->root.u.def.section;
263107163879Schristos       h->root.u.def.value = def->root.u.def.value;
2632377e23a2Schristos       return TRUE;
2633377e23a2Schristos     }
2634377e23a2Schristos 
2635377e23a2Schristos   /* This is a reference to a symbol defined by a dynamic object which
2636377e23a2Schristos      is not a function.  */
2637377e23a2Schristos 
2638377e23a2Schristos   /* If we are creating a shared library, we must presume that the
2639377e23a2Schristos      only references to the symbol are via the global offset table.
2640377e23a2Schristos      For such cases we need not do anything here; the relocations will
2641377e23a2Schristos      be handled correctly by relocate_section.  */
2642c03b94e9Schristos   if (bfd_link_pic (info))
2643377e23a2Schristos     return TRUE;
2644377e23a2Schristos 
2645377e23a2Schristos   /* If there are no references to this symbol that do not use the
2646377e23a2Schristos      GOT, we don't need to generate a copy reloc.  */
2647377e23a2Schristos   if (!h->non_got_ref)
2648377e23a2Schristos     return TRUE;
2649377e23a2Schristos 
2650377e23a2Schristos   /* If -z nocopyreloc was given, we won't generate them either.  */
2651377e23a2Schristos   if (info->nocopyreloc)
2652377e23a2Schristos     {
2653377e23a2Schristos       h->non_got_ref = 0;
2654377e23a2Schristos       return TRUE;
2655377e23a2Schristos     }
2656377e23a2Schristos 
265707163879Schristos   /* If we don't find any dynamic relocs in read-only sections, then
2658377e23a2Schristos      we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
2659*1424dfb3Schristos   if (!_bfd_elf_readonly_dynrelocs (h))
2660377e23a2Schristos     {
2661377e23a2Schristos       h->non_got_ref = 0;
2662377e23a2Schristos       return TRUE;
2663377e23a2Schristos     }
2664377e23a2Schristos 
2665377e23a2Schristos   /* We must allocate the symbol in our .dynbss section, which will
2666377e23a2Schristos      become part of the .bss section of the executable.  There will be
2667377e23a2Schristos      an entry for this symbol in the .dynsym section.  The dynamic
2668377e23a2Schristos      object will contain position independent code, so all references
2669377e23a2Schristos      from the dynamic object to this symbol will go through the global
2670377e23a2Schristos      offset table.  The dynamic linker will use the .dynsym entry to
2671377e23a2Schristos      determine the address it must put in the global offset table, so
2672377e23a2Schristos      both the dynamic object and the regular object will refer to the
2673377e23a2Schristos      same memory location for the variable.  */
2674377e23a2Schristos 
2675377e23a2Schristos   /* We must generate a R_MICROBLAZE_COPY reloc to tell the dynamic linker
2676377e23a2Schristos      to copy the initial value out of the dynamic object and into the
2677377e23a2Schristos      runtime process image.  */
26781c468f90Schristos   if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
26791c468f90Schristos     {
26801c468f90Schristos       s = htab->elf.sdynrelro;
26811c468f90Schristos       srel = htab->elf.sreldynrelro;
26821c468f90Schristos     }
26831c468f90Schristos   else
26841c468f90Schristos     {
26851c468f90Schristos       s = htab->elf.sdynbss;
26861c468f90Schristos       srel = htab->elf.srelbss;
26871c468f90Schristos     }
2688377e23a2Schristos   if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
2689377e23a2Schristos     {
26901c468f90Schristos       srel->size += sizeof (Elf32_External_Rela);
2691377e23a2Schristos       h->needs_copy = 1;
2692377e23a2Schristos     }
2693377e23a2Schristos 
2694377e23a2Schristos   /* We need to figure out the alignment required for this symbol.  I
2695377e23a2Schristos      have no idea how ELF linkers handle this.  */
2696377e23a2Schristos   power_of_two = bfd_log2 (h->size);
2697377e23a2Schristos   if (power_of_two > 3)
2698377e23a2Schristos     power_of_two = 3;
2699377e23a2Schristos 
2700377e23a2Schristos   /* Apply the required alignment.  */
27011c468f90Schristos   s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
27021c468f90Schristos   if (power_of_two > s->alignment_power)
2703377e23a2Schristos     {
2704*1424dfb3Schristos       if (!bfd_set_section_alignment (s, power_of_two))
2705377e23a2Schristos 	return FALSE;
2706377e23a2Schristos     }
2707377e23a2Schristos 
2708377e23a2Schristos   /* Define the symbol as being at this point in the section.  */
27091c468f90Schristos   h->root.u.def.section = s;
27101c468f90Schristos   h->root.u.def.value = s->size;
2711377e23a2Schristos 
2712377e23a2Schristos   /* Increment the section size to make room for the symbol.  */
27131c468f90Schristos   s->size += h->size;
2714377e23a2Schristos   return TRUE;
2715377e23a2Schristos }
2716377e23a2Schristos 
2717377e23a2Schristos /* Allocate space in .plt, .got and associated reloc sections for
2718377e23a2Schristos    dynamic relocs.  */
2719377e23a2Schristos 
2720377e23a2Schristos static bfd_boolean
allocate_dynrelocs(struct elf_link_hash_entry * h,void * dat)2721377e23a2Schristos allocate_dynrelocs (struct elf_link_hash_entry *h, void * dat)
2722377e23a2Schristos {
2723377e23a2Schristos   struct bfd_link_info *info;
2724377e23a2Schristos   struct elf32_mb_link_hash_table *htab;
2725377e23a2Schristos   struct elf32_mb_link_hash_entry *eh;
272607163879Schristos   struct elf_dyn_relocs *p;
2727377e23a2Schristos 
2728377e23a2Schristos   if (h->root.type == bfd_link_hash_indirect)
2729377e23a2Schristos     return TRUE;
2730377e23a2Schristos 
2731377e23a2Schristos   info = (struct bfd_link_info *) dat;
2732377e23a2Schristos   htab = elf32_mb_hash_table (info);
2733377e23a2Schristos   if (htab == NULL)
2734377e23a2Schristos     return FALSE;
2735377e23a2Schristos 
2736377e23a2Schristos   if (htab->elf.dynamic_sections_created
2737377e23a2Schristos       && h->plt.refcount > 0)
2738377e23a2Schristos     {
2739377e23a2Schristos       /* Make sure this symbol is output as a dynamic symbol.
2740377e23a2Schristos 	 Undefined weak syms won't yet be marked as dynamic.  */
2741377e23a2Schristos       if (h->dynindx == -1
2742377e23a2Schristos 	  && !h->forced_local)
2743377e23a2Schristos 	{
2744377e23a2Schristos 	  if (! bfd_elf_link_record_dynamic_symbol (info, h))
2745377e23a2Schristos 	    return FALSE;
2746377e23a2Schristos 	}
2747377e23a2Schristos 
2748c03b94e9Schristos       if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h))
2749377e23a2Schristos 	{
27501c468f90Schristos 	  asection *s = htab->elf.splt;
2751377e23a2Schristos 
2752377e23a2Schristos 	  /* The first entry in .plt is reserved.  */
2753377e23a2Schristos 	  if (s->size == 0)
2754377e23a2Schristos 	    s->size = PLT_ENTRY_SIZE;
2755377e23a2Schristos 
2756377e23a2Schristos 	  h->plt.offset = s->size;
2757377e23a2Schristos 
2758377e23a2Schristos 	  /* If this symbol is not defined in a regular file, and we are
2759377e23a2Schristos 	     not generating a shared library, then set the symbol to this
2760377e23a2Schristos 	     location in the .plt.  This is required to make function
2761377e23a2Schristos 	     pointers compare as equal between the normal executable and
2762377e23a2Schristos 	     the shared library.  */
2763c03b94e9Schristos 	  if (! bfd_link_pic (info)
2764377e23a2Schristos 	      && !h->def_regular)
2765377e23a2Schristos 	    {
2766377e23a2Schristos 	      h->root.u.def.section = s;
2767377e23a2Schristos 	      h->root.u.def.value = h->plt.offset;
2768377e23a2Schristos 	    }
2769377e23a2Schristos 
2770377e23a2Schristos 	  /* Make room for this entry.  */
2771377e23a2Schristos 	  s->size += PLT_ENTRY_SIZE;
2772377e23a2Schristos 
2773377e23a2Schristos 	  /* We also need to make an entry in the .got.plt section, which
2774377e23a2Schristos 	     will be placed in the .got section by the linker script.  */
27751c468f90Schristos 	  htab->elf.sgotplt->size += 4;
2776377e23a2Schristos 
2777377e23a2Schristos 	  /* We also need to make an entry in the .rel.plt section.  */
27781c468f90Schristos 	  htab->elf.srelplt->size += sizeof (Elf32_External_Rela);
2779377e23a2Schristos 	}
2780377e23a2Schristos       else
2781377e23a2Schristos 	{
2782377e23a2Schristos 	  h->plt.offset = (bfd_vma) -1;
2783377e23a2Schristos 	  h->needs_plt = 0;
2784377e23a2Schristos 	}
2785377e23a2Schristos     }
2786377e23a2Schristos   else
2787377e23a2Schristos     {
2788377e23a2Schristos       h->plt.offset = (bfd_vma) -1;
2789377e23a2Schristos       h->needs_plt = 0;
2790377e23a2Schristos     }
2791377e23a2Schristos 
279248596154Schristos   eh = (struct elf32_mb_link_hash_entry *) h;
2793377e23a2Schristos   if (h->got.refcount > 0)
2794377e23a2Schristos     {
279548596154Schristos       unsigned int need;
2796377e23a2Schristos       asection *s;
2797377e23a2Schristos 
2798377e23a2Schristos       /* Make sure this symbol is output as a dynamic symbol.
2799377e23a2Schristos 	 Undefined weak syms won't yet be marked as dynamic.  */
2800377e23a2Schristos       if (h->dynindx == -1
2801377e23a2Schristos 	  && !h->forced_local)
2802377e23a2Schristos 	{
2803377e23a2Schristos 	  if (! bfd_elf_link_record_dynamic_symbol (info, h))
2804377e23a2Schristos 	    return FALSE;
2805377e23a2Schristos 	}
2806377e23a2Schristos 
280748596154Schristos       need = 0;
280848596154Schristos       if ((eh->tls_mask & TLS_TLS) != 0)
280948596154Schristos 	{
281048596154Schristos 	  /* Handle TLS Symbol */
281148596154Schristos 	  if ((eh->tls_mask & TLS_LD) != 0)
281248596154Schristos 	    {
281348596154Schristos 	      if (!eh->elf.def_dynamic)
281448596154Schristos 		/* We'll just use htab->tlsld_got.offset.  This should
281548596154Schristos 		   always be the case.  It's a little odd if we have
281648596154Schristos 		   a local dynamic reloc against a non-local symbol.  */
281748596154Schristos 		htab->tlsld_got.refcount += 1;
281848596154Schristos 	      else
281948596154Schristos 		need += 8;
282048596154Schristos 	    }
282148596154Schristos 	  if ((eh->tls_mask & TLS_GD) != 0)
282248596154Schristos 	    need += 8;
282348596154Schristos 	}
282448596154Schristos       else
282548596154Schristos 	{
282648596154Schristos 	  /* Regular (non-TLS) symbol */
282748596154Schristos 	  need += 4;
282848596154Schristos 	}
282948596154Schristos       if (need == 0)
283048596154Schristos 	{
283148596154Schristos 	  h->got.offset = (bfd_vma) -1;
283248596154Schristos 	}
283348596154Schristos       else
283448596154Schristos 	{
28351c468f90Schristos 	  s = htab->elf.sgot;
2836377e23a2Schristos 	  h->got.offset = s->size;
283748596154Schristos 	  s->size += need;
28381c468f90Schristos 	  htab->elf.srelgot->size += need * (sizeof (Elf32_External_Rela) / 4);
283948596154Schristos 	}
2840377e23a2Schristos     }
2841377e23a2Schristos   else
2842377e23a2Schristos     h->got.offset = (bfd_vma) -1;
2843377e23a2Schristos 
2844*1424dfb3Schristos   if (h->dyn_relocs == NULL)
2845377e23a2Schristos     return TRUE;
2846377e23a2Schristos 
2847377e23a2Schristos   /* In the shared -Bsymbolic case, discard space allocated for
2848377e23a2Schristos      dynamic pc-relative relocs against symbols which turn out to be
2849377e23a2Schristos      defined in regular objects.  For the normal shared case, discard
2850377e23a2Schristos      space for pc-relative relocs that have become local due to symbol
2851377e23a2Schristos      visibility changes.  */
2852377e23a2Schristos 
2853c03b94e9Schristos   if (bfd_link_pic (info))
2854377e23a2Schristos     {
2855377e23a2Schristos       if (h->def_regular
2856377e23a2Schristos 	  && (h->forced_local
2857377e23a2Schristos 	      || info->symbolic))
2858377e23a2Schristos 	{
285907163879Schristos 	  struct elf_dyn_relocs **pp;
2860377e23a2Schristos 
2861*1424dfb3Schristos 	  for (pp = &h->dyn_relocs; (p = *pp) != NULL; )
2862377e23a2Schristos 	    {
2863377e23a2Schristos 	      p->count -= p->pc_count;
2864377e23a2Schristos 	      p->pc_count = 0;
2865377e23a2Schristos 	      if (p->count == 0)
2866377e23a2Schristos 		*pp = p->next;
2867377e23a2Schristos 	      else
2868377e23a2Schristos 		pp = &p->next;
2869377e23a2Schristos 	    }
2870377e23a2Schristos 	}
287107163879Schristos       else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
2872*1424dfb3Schristos 	h->dyn_relocs = NULL;
2873377e23a2Schristos     }
2874377e23a2Schristos   else
2875377e23a2Schristos     {
2876377e23a2Schristos       /* For the non-shared case, discard space for relocs against
2877377e23a2Schristos 	 symbols which turn out to need copy relocs or are not
2878377e23a2Schristos 	 dynamic.  */
2879377e23a2Schristos 
2880377e23a2Schristos       if (!h->non_got_ref
2881377e23a2Schristos 	  && ((h->def_dynamic
2882377e23a2Schristos 	       && !h->def_regular)
2883377e23a2Schristos 	      || (htab->elf.dynamic_sections_created
2884377e23a2Schristos 		  && (h->root.type == bfd_link_hash_undefweak
2885377e23a2Schristos 		      || h->root.type == bfd_link_hash_undefined))))
2886377e23a2Schristos 	{
2887377e23a2Schristos 	  /* Make sure this symbol is output as a dynamic symbol.
2888377e23a2Schristos 	     Undefined weak syms won't yet be marked as dynamic.  */
2889377e23a2Schristos 	  if (h->dynindx == -1
2890377e23a2Schristos 	      && !h->forced_local)
2891377e23a2Schristos 	    {
2892377e23a2Schristos 	      if (! bfd_elf_link_record_dynamic_symbol (info, h))
2893377e23a2Schristos 		return FALSE;
2894377e23a2Schristos 	    }
2895377e23a2Schristos 
2896377e23a2Schristos 	  /* If that succeeded, we know we'll be keeping all the
2897377e23a2Schristos 	     relocs.  */
2898377e23a2Schristos 	  if (h->dynindx != -1)
2899377e23a2Schristos 	    goto keep;
2900377e23a2Schristos 	}
2901377e23a2Schristos 
2902*1424dfb3Schristos       h->dyn_relocs = NULL;
2903377e23a2Schristos 
2904377e23a2Schristos     keep: ;
2905377e23a2Schristos     }
2906377e23a2Schristos 
2907377e23a2Schristos   /* Finally, allocate space.  */
2908*1424dfb3Schristos   for (p = h->dyn_relocs; p != NULL; p = p->next)
2909377e23a2Schristos     {
2910377e23a2Schristos       asection *sreloc = elf_section_data (p->sec)->sreloc;
2911377e23a2Schristos       sreloc->size += p->count * sizeof (Elf32_External_Rela);
2912377e23a2Schristos     }
2913377e23a2Schristos 
2914377e23a2Schristos   return TRUE;
2915377e23a2Schristos }
2916377e23a2Schristos 
2917377e23a2Schristos /* Set the sizes of the dynamic sections.  */
2918377e23a2Schristos 
2919377e23a2Schristos static bfd_boolean
microblaze_elf_size_dynamic_sections(bfd * output_bfd ATTRIBUTE_UNUSED,struct bfd_link_info * info)2920377e23a2Schristos microblaze_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
2921377e23a2Schristos 				      struct bfd_link_info *info)
2922377e23a2Schristos {
2923377e23a2Schristos   struct elf32_mb_link_hash_table *htab;
2924377e23a2Schristos   bfd *dynobj;
2925377e23a2Schristos   asection *s;
2926377e23a2Schristos   bfd *ibfd;
2927377e23a2Schristos 
2928377e23a2Schristos   htab = elf32_mb_hash_table (info);
2929377e23a2Schristos   if (htab == NULL)
2930377e23a2Schristos     return FALSE;
2931377e23a2Schristos 
2932377e23a2Schristos   dynobj = htab->elf.dynobj;
2933377e23a2Schristos   BFD_ASSERT (dynobj != NULL);
2934377e23a2Schristos 
2935377e23a2Schristos   /* Set up .got offsets for local syms, and space for local dynamic
2936377e23a2Schristos      relocs.  */
29375e098073Schristos   for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
2938377e23a2Schristos     {
2939377e23a2Schristos       bfd_signed_vma *local_got;
2940377e23a2Schristos       bfd_signed_vma *end_local_got;
2941377e23a2Schristos       bfd_size_type locsymcount;
2942377e23a2Schristos       Elf_Internal_Shdr *symtab_hdr;
294348596154Schristos       unsigned char *lgot_masks;
2944377e23a2Schristos       asection *srel;
2945377e23a2Schristos 
2946377e23a2Schristos       if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
2947377e23a2Schristos 	continue;
2948377e23a2Schristos 
2949377e23a2Schristos       for (s = ibfd->sections; s != NULL; s = s->next)
2950377e23a2Schristos 	{
295107163879Schristos 	  struct elf_dyn_relocs *p;
2952377e23a2Schristos 
295307163879Schristos 	  for (p = ((struct elf_dyn_relocs *)
2954377e23a2Schristos 		    elf_section_data (s)->local_dynrel);
2955377e23a2Schristos 	       p != NULL;
2956377e23a2Schristos 	       p = p->next)
2957377e23a2Schristos 	    {
2958377e23a2Schristos 	      if (!bfd_is_abs_section (p->sec)
2959377e23a2Schristos 		  && bfd_is_abs_section (p->sec->output_section))
2960377e23a2Schristos 		{
2961377e23a2Schristos 		  /* Input section has been discarded, either because
2962377e23a2Schristos 		     it is a copy of a linkonce section or due to
2963377e23a2Schristos 		     linker script /DISCARD/, so we'll be discarding
2964377e23a2Schristos 		     the relocs too.  */
2965377e23a2Schristos 		}
2966377e23a2Schristos 	      else if (p->count != 0)
2967377e23a2Schristos 		{
2968377e23a2Schristos 		  srel = elf_section_data (p->sec)->sreloc;
2969377e23a2Schristos 		  srel->size += p->count * sizeof (Elf32_External_Rela);
2970377e23a2Schristos 		  if ((p->sec->output_section->flags & SEC_READONLY) != 0)
2971377e23a2Schristos 		    info->flags |= DF_TEXTREL;
2972377e23a2Schristos 		}
2973377e23a2Schristos 	    }
2974377e23a2Schristos 	}
2975377e23a2Schristos 
2976377e23a2Schristos       local_got = elf_local_got_refcounts (ibfd);
2977377e23a2Schristos       if (!local_got)
2978377e23a2Schristos 	continue;
2979377e23a2Schristos 
2980377e23a2Schristos       symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
2981377e23a2Schristos       locsymcount = symtab_hdr->sh_info;
2982377e23a2Schristos       end_local_got = local_got + locsymcount;
298348596154Schristos       lgot_masks = (unsigned char *) end_local_got;
29841c468f90Schristos       s = htab->elf.sgot;
29851c468f90Schristos       srel = htab->elf.srelgot;
2986377e23a2Schristos 
298748596154Schristos       for (; local_got < end_local_got; ++local_got, ++lgot_masks)
2988377e23a2Schristos 	{
2989377e23a2Schristos 	  if (*local_got > 0)
2990377e23a2Schristos 	    {
299148596154Schristos 	      unsigned int need = 0;
299248596154Schristos 	      if ((*lgot_masks & TLS_TLS) != 0)
299348596154Schristos 		{
299448596154Schristos 		  if ((*lgot_masks & TLS_GD) != 0)
299548596154Schristos 		    need += 8;
299648596154Schristos 		  if ((*lgot_masks & TLS_LD) != 0)
299748596154Schristos 		    htab->tlsld_got.refcount += 1;
299848596154Schristos 		}
299948596154Schristos 	      else
300048596154Schristos 		need += 4;
300148596154Schristos 
300248596154Schristos 	      if (need == 0)
300348596154Schristos 		{
300448596154Schristos 		  *local_got = (bfd_vma) -1;
300548596154Schristos 		}
300648596154Schristos 	      else
300748596154Schristos 		{
3008377e23a2Schristos 		  *local_got = s->size;
300948596154Schristos 		  s->size += need;
3010c03b94e9Schristos 		  if (bfd_link_pic (info))
301148596154Schristos 		    srel->size += need * (sizeof (Elf32_External_Rela) / 4);
301248596154Schristos 		}
3013377e23a2Schristos 	    }
3014377e23a2Schristos 	  else
3015377e23a2Schristos 	    *local_got = (bfd_vma) -1;
3016377e23a2Schristos 	}
3017377e23a2Schristos     }
3018377e23a2Schristos 
3019377e23a2Schristos   /* Allocate global sym .plt and .got entries, and space for global
3020377e23a2Schristos      sym dynamic relocs.  */
3021377e23a2Schristos   elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info);
3022377e23a2Schristos 
302348596154Schristos   if (htab->tlsld_got.refcount > 0)
302448596154Schristos     {
30251c468f90Schristos       htab->tlsld_got.offset = htab->elf.sgot->size;
30261c468f90Schristos       htab->elf.sgot->size += 8;
3027c03b94e9Schristos       if (bfd_link_pic (info))
30281c468f90Schristos 	htab->elf.srelgot->size += sizeof (Elf32_External_Rela);
302948596154Schristos     }
303048596154Schristos   else
303148596154Schristos     htab->tlsld_got.offset = (bfd_vma) -1;
303248596154Schristos 
3033377e23a2Schristos   if (elf_hash_table (info)->dynamic_sections_created)
3034377e23a2Schristos     {
3035377e23a2Schristos       /* Make space for the trailing nop in .plt.  */
30361c468f90Schristos       if (htab->elf.splt->size > 0)
30371c468f90Schristos 	htab->elf.splt->size += 4;
3038377e23a2Schristos     }
3039377e23a2Schristos 
3040377e23a2Schristos   /* The check_relocs and adjust_dynamic_symbol entry points have
3041377e23a2Schristos      determined the sizes of the various dynamic sections.  Allocate
3042377e23a2Schristos      memory for them.  */
3043377e23a2Schristos   for (s = dynobj->sections; s != NULL; s = s->next)
3044377e23a2Schristos     {
3045377e23a2Schristos       const char *name;
3046377e23a2Schristos       bfd_boolean strip = FALSE;
3047377e23a2Schristos 
3048377e23a2Schristos       if ((s->flags & SEC_LINKER_CREATED) == 0)
3049377e23a2Schristos 	continue;
3050377e23a2Schristos 
3051377e23a2Schristos       /* It's OK to base decisions on the section name, because none
3052377e23a2Schristos 	 of the dynobj section names depend upon the input files.  */
3053*1424dfb3Schristos       name = bfd_section_name (s);
3054377e23a2Schristos 
3055377e23a2Schristos       if (strncmp (name, ".rela", 5) == 0)
3056377e23a2Schristos 	{
3057377e23a2Schristos 	  if (s->size == 0)
3058377e23a2Schristos 	    {
3059377e23a2Schristos 	      /* If we don't need this section, strip it from the
3060377e23a2Schristos 		 output file.  This is to handle .rela.bss and
3061377e23a2Schristos 		 .rela.plt.  We must create it in
3062377e23a2Schristos 		 create_dynamic_sections, because it must be created
3063377e23a2Schristos 		 before the linker maps input sections to output
3064377e23a2Schristos 		 sections.  The linker does that before
3065377e23a2Schristos 		 adjust_dynamic_symbol is called, and it is that
3066377e23a2Schristos 		 function which decides whether anything needs to go
3067377e23a2Schristos 		 into these sections.  */
3068377e23a2Schristos 	      strip = TRUE;
3069377e23a2Schristos 	    }
3070377e23a2Schristos 	  else
3071377e23a2Schristos 	    {
3072377e23a2Schristos 	      /* We use the reloc_count field as a counter if we need
3073377e23a2Schristos 		 to copy relocs into the output file.  */
3074377e23a2Schristos 	      s->reloc_count = 0;
3075377e23a2Schristos 	    }
3076377e23a2Schristos 	}
30771c468f90Schristos       else if (s != htab->elf.splt
30781c468f90Schristos 	       && s != htab->elf.sgot
30791c468f90Schristos 	       && s != htab->elf.sgotplt
30801c468f90Schristos 	       && s != htab->elf.sdynbss
30811c468f90Schristos 	       && s != htab->elf.sdynrelro)
3082377e23a2Schristos 	{
3083377e23a2Schristos 	  /* It's not one of our sections, so don't allocate space.  */
3084377e23a2Schristos 	  continue;
3085377e23a2Schristos 	}
3086377e23a2Schristos 
3087377e23a2Schristos       if (strip)
3088377e23a2Schristos 	{
3089377e23a2Schristos 	  s->flags |= SEC_EXCLUDE;
3090377e23a2Schristos 	  continue;
3091377e23a2Schristos 	}
3092377e23a2Schristos 
3093377e23a2Schristos       /* Allocate memory for the section contents.  */
3094377e23a2Schristos       /* FIXME: This should be a call to bfd_alloc not bfd_zalloc.
3095377e23a2Schristos 	 Unused entries should be reclaimed before the section's contents
3096377e23a2Schristos 	 are written out, but at the moment this does not happen.  Thus in
3097377e23a2Schristos 	 order to prevent writing out garbage, we initialise the section's
3098377e23a2Schristos 	 contents to zero.  */
3099377e23a2Schristos       s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
3100377e23a2Schristos       if (s->contents == NULL && s->size != 0)
3101377e23a2Schristos 	return FALSE;
3102377e23a2Schristos     }
3103377e23a2Schristos 
3104*1424dfb3Schristos   /* ??? Force DF_BIND_NOW?  */
3105*1424dfb3Schristos   info->flags |= DF_BIND_NOW;
3106*1424dfb3Schristos   return _bfd_elf_add_dynamic_tags (output_bfd, info, TRUE);
3107377e23a2Schristos }
3108377e23a2Schristos 
3109377e23a2Schristos /* Finish up dynamic symbol handling.  We set the contents of various
3110377e23a2Schristos    dynamic sections here.  */
3111377e23a2Schristos 
3112377e23a2Schristos 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)3113377e23a2Schristos microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
3114377e23a2Schristos 				      struct bfd_link_info *info,
3115377e23a2Schristos 				      struct elf_link_hash_entry *h,
3116377e23a2Schristos 				      Elf_Internal_Sym *sym)
3117377e23a2Schristos {
3118377e23a2Schristos   struct elf32_mb_link_hash_table *htab;
311948596154Schristos   struct elf32_mb_link_hash_entry *eh = elf32_mb_hash_entry(h);
3120377e23a2Schristos 
3121377e23a2Schristos   htab = elf32_mb_hash_table (info);
3122377e23a2Schristos   if (htab == NULL)
3123377e23a2Schristos     return FALSE;
3124377e23a2Schristos 
3125377e23a2Schristos   if (h->plt.offset != (bfd_vma) -1)
3126377e23a2Schristos     {
3127377e23a2Schristos       asection *splt;
3128377e23a2Schristos       asection *srela;
3129377e23a2Schristos       asection *sgotplt;
3130377e23a2Schristos       Elf_Internal_Rela rela;
3131377e23a2Schristos       bfd_byte *loc;
3132377e23a2Schristos       bfd_vma plt_index;
3133377e23a2Schristos       bfd_vma got_offset;
3134377e23a2Schristos       bfd_vma got_addr;
3135377e23a2Schristos 
3136377e23a2Schristos       /* This symbol has an entry in the procedure linkage table.  Set
3137377e23a2Schristos 	 it up.  */
3138377e23a2Schristos       BFD_ASSERT (h->dynindx != -1);
3139377e23a2Schristos 
31401c468f90Schristos       splt = htab->elf.splt;
31411c468f90Schristos       srela = htab->elf.srelplt;
31421c468f90Schristos       sgotplt = htab->elf.sgotplt;
3143377e23a2Schristos       BFD_ASSERT (splt != NULL && srela != NULL && sgotplt != NULL);
3144377e23a2Schristos 
3145377e23a2Schristos       plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; /* first entry reserved.  */
3146377e23a2Schristos       got_offset = (plt_index + 3) * 4; /* 3 reserved ???  */
3147377e23a2Schristos       got_addr = got_offset;
3148377e23a2Schristos 
3149377e23a2Schristos       /* For non-PIC objects we need absolute address of the GOT entry.  */
3150c03b94e9Schristos       if (!bfd_link_pic (info))
31511c468f90Schristos 	got_addr += sgotplt->output_section->vma + sgotplt->output_offset;
3152377e23a2Schristos 
3153377e23a2Schristos       /* Fill in the entry in the procedure linkage table.  */
3154377e23a2Schristos       bfd_put_32 (output_bfd, PLT_ENTRY_WORD_0 + ((got_addr >> 16) & 0xffff),
3155377e23a2Schristos 		  splt->contents + h->plt.offset);
3156c03b94e9Schristos       if (bfd_link_pic (info))
3157377e23a2Schristos 	bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1 + (got_addr & 0xffff),
3158377e23a2Schristos 		    splt->contents + h->plt.offset + 4);
3159377e23a2Schristos       else
3160377e23a2Schristos 	bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1_NOPIC + (got_addr & 0xffff),
3161377e23a2Schristos 		    splt->contents + h->plt.offset + 4);
3162377e23a2Schristos       bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD_2,
3163377e23a2Schristos 		  splt->contents + h->plt.offset + 8);
3164377e23a2Schristos       bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD_3,
3165377e23a2Schristos 		  splt->contents + h->plt.offset + 12);
3166377e23a2Schristos 
3167377e23a2Schristos       /* Any additions to the .got section??? */
3168377e23a2Schristos       /*      bfd_put_32 (output_bfd,
3169377e23a2Schristos 	      splt->output_section->vma + splt->output_offset + h->plt.offset + 4,
3170377e23a2Schristos 	      sgotplt->contents + got_offset); */
3171377e23a2Schristos 
3172377e23a2Schristos       /* Fill in the entry in the .rela.plt section.  */
3173377e23a2Schristos       rela.r_offset = (sgotplt->output_section->vma
3174377e23a2Schristos 		       + sgotplt->output_offset
3175377e23a2Schristos 		       + got_offset);
3176377e23a2Schristos       rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_JUMP_SLOT);
3177377e23a2Schristos       rela.r_addend = 0;
3178377e23a2Schristos       loc = srela->contents;
3179377e23a2Schristos       loc += plt_index * sizeof (Elf32_External_Rela);
3180377e23a2Schristos       bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
3181377e23a2Schristos 
3182377e23a2Schristos       if (!h->def_regular)
3183377e23a2Schristos 	{
3184377e23a2Schristos 	  /* Mark the symbol as undefined, rather than as defined in
3185377e23a2Schristos 	     the .plt section.  Zero the value.  */
3186377e23a2Schristos 	  sym->st_shndx = SHN_UNDEF;
3187377e23a2Schristos 	  sym->st_value = 0;
3188377e23a2Schristos 	}
3189377e23a2Schristos     }
3190377e23a2Schristos 
319148596154Schristos   /* h->got.refcount to be checked ? */
319248596154Schristos   if (h->got.offset != (bfd_vma) -1 &&
319348596154Schristos       ! ((h->got.offset & 1) ||
319448596154Schristos 	  IS_TLS_LD(eh->tls_mask) || IS_TLS_GD(eh->tls_mask)))
3195377e23a2Schristos     {
3196377e23a2Schristos       asection *sgot;
3197377e23a2Schristos       asection *srela;
319848596154Schristos       bfd_vma offset;
3199377e23a2Schristos 
3200377e23a2Schristos       /* This symbol has an entry in the global offset table.  Set it
3201377e23a2Schristos 	 up.  */
3202377e23a2Schristos 
32031c468f90Schristos       sgot = htab->elf.sgot;
32041c468f90Schristos       srela = htab->elf.srelgot;
3205377e23a2Schristos       BFD_ASSERT (sgot != NULL && srela != NULL);
3206377e23a2Schristos 
320748596154Schristos       offset = (sgot->output_section->vma + sgot->output_offset
3208377e23a2Schristos 		+ (h->got.offset &~ (bfd_vma) 1));
3209377e23a2Schristos 
3210377e23a2Schristos       /* If this is a -Bsymbolic link, and the symbol is defined
3211377e23a2Schristos 	 locally, we just want to emit a RELATIVE reloc.  Likewise if
3212377e23a2Schristos 	 the symbol was forced to be local because of a version file.
3213377e23a2Schristos 	 The entry in the global offset table will already have been
3214377e23a2Schristos 	 initialized in the relocate_section function.  */
3215c03b94e9Schristos       if (bfd_link_pic (info)
3216c03b94e9Schristos 	  && ((info->symbolic && h->def_regular)
3217c03b94e9Schristos 	      || h->dynindx == -1))
3218377e23a2Schristos 	{
3219377e23a2Schristos 	  asection *sec = h->root.u.def.section;
32201c468f90Schristos 	  bfd_vma value;
32211c468f90Schristos 
32221c468f90Schristos 	  value = h->root.u.def.value;
32231c468f90Schristos 	  if (sec->output_section != NULL)
32241c468f90Schristos 	    /* PR 21180: If the output section is NULL, then the symbol is no
32251c468f90Schristos 	       longer needed, and in theory the GOT entry is redundant.  But
32261c468f90Schristos 	       it is too late to change our minds now...  */
32271c468f90Schristos 	    value += sec->output_section->vma + sec->output_offset;
32281c468f90Schristos 
322948596154Schristos 	  microblaze_elf_output_dynamic_relocation (output_bfd,
323048596154Schristos 						    srela, srela->reloc_count++,
323148596154Schristos 						    /* symindex= */ 0,
323248596154Schristos 						    R_MICROBLAZE_REL, offset,
32331c468f90Schristos 						    value);
3234377e23a2Schristos 	}
3235377e23a2Schristos       else
3236377e23a2Schristos 	{
323748596154Schristos 	  microblaze_elf_output_dynamic_relocation (output_bfd,
323848596154Schristos 						    srela, srela->reloc_count++,
323948596154Schristos 						    h->dynindx,
324048596154Schristos 						    R_MICROBLAZE_GLOB_DAT,
324148596154Schristos 						    offset, 0);
3242377e23a2Schristos 	}
3243377e23a2Schristos 
3244377e23a2Schristos       bfd_put_32 (output_bfd, (bfd_vma) 0,
3245377e23a2Schristos 		  sgot->contents + (h->got.offset &~ (bfd_vma) 1));
3246377e23a2Schristos     }
3247377e23a2Schristos 
3248377e23a2Schristos   if (h->needs_copy)
3249377e23a2Schristos     {
3250377e23a2Schristos       asection *s;
3251377e23a2Schristos       Elf_Internal_Rela rela;
3252377e23a2Schristos       bfd_byte *loc;
3253377e23a2Schristos 
3254377e23a2Schristos       /* This symbols needs a copy reloc.  Set it up.  */
3255377e23a2Schristos 
3256377e23a2Schristos       BFD_ASSERT (h->dynindx != -1);
3257377e23a2Schristos 
3258377e23a2Schristos       rela.r_offset = (h->root.u.def.value
3259377e23a2Schristos 		       + h->root.u.def.section->output_section->vma
3260377e23a2Schristos 		       + h->root.u.def.section->output_offset);
3261377e23a2Schristos       rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_COPY);
3262377e23a2Schristos       rela.r_addend = 0;
32631c468f90Schristos       if (h->root.u.def.section == htab->elf.sdynrelro)
32641c468f90Schristos 	s = htab->elf.sreldynrelro;
32651c468f90Schristos       else
32661c468f90Schristos 	s = htab->elf.srelbss;
3267377e23a2Schristos       loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
3268377e23a2Schristos       bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
3269377e23a2Schristos     }
3270377e23a2Schristos 
3271377e23a2Schristos   /* Mark some specially defined symbols as absolute.  */
327248596154Schristos   if (h == htab->elf.hdynamic
327348596154Schristos       || h == htab->elf.hgot
327448596154Schristos       || h == htab->elf.hplt)
3275377e23a2Schristos     sym->st_shndx = SHN_ABS;
3276377e23a2Schristos 
3277377e23a2Schristos   return TRUE;
3278377e23a2Schristos }
3279377e23a2Schristos 
3280377e23a2Schristos 
3281377e23a2Schristos /* Finish up the dynamic sections.  */
3282377e23a2Schristos 
3283377e23a2Schristos static bfd_boolean
microblaze_elf_finish_dynamic_sections(bfd * output_bfd,struct bfd_link_info * info)3284377e23a2Schristos microblaze_elf_finish_dynamic_sections (bfd *output_bfd,
3285377e23a2Schristos 					struct bfd_link_info *info)
3286377e23a2Schristos {
3287377e23a2Schristos   bfd *dynobj;
3288377e23a2Schristos   asection *sdyn, *sgot;
3289377e23a2Schristos   struct elf32_mb_link_hash_table *htab;
3290377e23a2Schristos 
3291377e23a2Schristos   htab = elf32_mb_hash_table (info);
3292377e23a2Schristos   if (htab == NULL)
3293377e23a2Schristos     return FALSE;
3294377e23a2Schristos 
3295377e23a2Schristos   dynobj = htab->elf.dynobj;
3296377e23a2Schristos 
329748596154Schristos   sdyn = bfd_get_linker_section (dynobj, ".dynamic");
3298377e23a2Schristos 
3299377e23a2Schristos   if (htab->elf.dynamic_sections_created)
3300377e23a2Schristos     {
3301377e23a2Schristos       asection *splt;
3302377e23a2Schristos       Elf32_External_Dyn *dyncon, *dynconend;
3303377e23a2Schristos 
3304377e23a2Schristos       dyncon = (Elf32_External_Dyn *) sdyn->contents;
3305377e23a2Schristos       dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
3306377e23a2Schristos       for (; dyncon < dynconend; dyncon++)
3307377e23a2Schristos 	{
3308377e23a2Schristos 	  Elf_Internal_Dyn dyn;
33091c468f90Schristos 	  asection *s;
3310377e23a2Schristos 	  bfd_boolean size;
3311377e23a2Schristos 
3312377e23a2Schristos 	  bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
3313377e23a2Schristos 
3314377e23a2Schristos 	  switch (dyn.d_tag)
3315377e23a2Schristos 	    {
33161c468f90Schristos 	    case DT_PLTGOT:
33171c468f90Schristos 	      s = htab->elf.sgotplt;
33181c468f90Schristos 	      size = FALSE;
33191c468f90Schristos 	      break;
33201c468f90Schristos 
33211c468f90Schristos 	    case DT_PLTRELSZ:
33221c468f90Schristos 	      s = htab->elf.srelplt;
33231c468f90Schristos 	      size = TRUE;
33241c468f90Schristos 	      break;
33251c468f90Schristos 
33261c468f90Schristos 	    case DT_JMPREL:
33271c468f90Schristos 	      s = htab->elf.srelplt;
33281c468f90Schristos 	      size = FALSE;
33291c468f90Schristos 	      break;
33301c468f90Schristos 
33311c468f90Schristos 	    default:
33321c468f90Schristos 	      continue;
3333377e23a2Schristos 	    }
3334377e23a2Schristos 
3335377e23a2Schristos 	  if (s == NULL)
3336377e23a2Schristos 	    dyn.d_un.d_val = 0;
3337377e23a2Schristos 	  else
3338377e23a2Schristos 	    {
3339377e23a2Schristos 	      if (!size)
3340c03b94e9Schristos 		dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
3341377e23a2Schristos 	      else
3342377e23a2Schristos 		dyn.d_un.d_val = s->size;
3343377e23a2Schristos 	    }
3344377e23a2Schristos 	  bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
3345377e23a2Schristos 	}
33461c468f90Schristos 
33471c468f90Schristos       splt = htab->elf.splt;
33481c468f90Schristos       BFD_ASSERT (splt != NULL && sdyn != NULL);
3349377e23a2Schristos 
3350377e23a2Schristos       /* Clear the first entry in the procedure linkage table,
3351377e23a2Schristos 	 and put a nop in the last four bytes.  */
3352377e23a2Schristos       if (splt->size > 0)
3353377e23a2Schristos 	{
3354377e23a2Schristos 	  memset (splt->contents, 0, PLT_ENTRY_SIZE);
3355377e23a2Schristos 	  bfd_put_32 (output_bfd, (bfd_vma) 0x80000000 /* nop.  */,
3356377e23a2Schristos 		      splt->contents + splt->size - 4);
3357377e23a2Schristos 
3358*1424dfb3Schristos 	  if (splt->output_section != bfd_abs_section_ptr)
3359377e23a2Schristos 	    elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
3360377e23a2Schristos 	}
3361*1424dfb3Schristos     }
3362377e23a2Schristos 
3363377e23a2Schristos   /* Set the first entry in the global offset table to the address of
3364377e23a2Schristos      the dynamic section.  */
33651c468f90Schristos   sgot = htab->elf.sgotplt;
3366377e23a2Schristos   if (sgot && sgot->size > 0)
3367377e23a2Schristos     {
3368377e23a2Schristos       if (sdyn == NULL)
3369377e23a2Schristos 	bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
3370377e23a2Schristos       else
3371377e23a2Schristos 	bfd_put_32 (output_bfd,
3372377e23a2Schristos 		    sdyn->output_section->vma + sdyn->output_offset,
3373377e23a2Schristos 		    sgot->contents);
3374377e23a2Schristos       elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
3375377e23a2Schristos     }
3376377e23a2Schristos 
33771c468f90Schristos   if (htab->elf.sgot && htab->elf.sgot->size > 0)
33781c468f90Schristos     elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4;
3379377e23a2Schristos 
3380377e23a2Schristos   return TRUE;
3381377e23a2Schristos }
3382377e23a2Schristos 
3383377e23a2Schristos /* Hook called by the linker routine which adds symbols from an object
3384377e23a2Schristos    file.  We use it to put .comm items in .sbss, and not .bss.  */
3385377e23a2Schristos 
3386377e23a2Schristos 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)3387377e23a2Schristos microblaze_elf_add_symbol_hook (bfd *abfd,
3388377e23a2Schristos 				struct bfd_link_info *info,
3389377e23a2Schristos 				Elf_Internal_Sym *sym,
3390377e23a2Schristos 				const char **namep ATTRIBUTE_UNUSED,
3391377e23a2Schristos 				flagword *flagsp ATTRIBUTE_UNUSED,
3392377e23a2Schristos 				asection **secp,
3393377e23a2Schristos 				bfd_vma *valp)
3394377e23a2Schristos {
3395377e23a2Schristos   if (sym->st_shndx == SHN_COMMON
3396c03b94e9Schristos       && !bfd_link_relocatable (info)
3397377e23a2Schristos       && sym->st_size <= elf_gp_size (abfd))
3398377e23a2Schristos     {
3399377e23a2Schristos       /* Common symbols less than or equal to -G nn bytes are automatically
3400377e23a2Schristos 	 put into .sbss.  */
340148596154Schristos       *secp = bfd_make_section_old_way (abfd, ".sbss");
3402377e23a2Schristos       if (*secp == NULL
3403*1424dfb3Schristos 	  || !bfd_set_section_flags (*secp, SEC_IS_COMMON | SEC_SMALL_DATA))
3404377e23a2Schristos 	return FALSE;
3405377e23a2Schristos 
3406377e23a2Schristos       *valp = sym->st_size;
3407377e23a2Schristos     }
3408377e23a2Schristos 
3409377e23a2Schristos   return TRUE;
3410377e23a2Schristos }
3411377e23a2Schristos 
34125e098073Schristos #define TARGET_LITTLE_SYM      microblaze_elf32_le_vec
341348596154Schristos #define TARGET_LITTLE_NAME     "elf32-microblazeel"
3414377e23a2Schristos 
34155e098073Schristos #define TARGET_BIG_SYM		microblaze_elf32_vec
3416377e23a2Schristos #define TARGET_BIG_NAME		"elf32-microblaze"
3417377e23a2Schristos 
3418377e23a2Schristos #define ELF_ARCH		bfd_arch_microblaze
3419377e23a2Schristos #define ELF_TARGET_ID		MICROBLAZE_ELF_DATA
3420377e23a2Schristos #define ELF_MACHINE_CODE	EM_MICROBLAZE
3421377e23a2Schristos #define ELF_MACHINE_ALT1	EM_MICROBLAZE_OLD
342248596154Schristos #define ELF_MAXPAGESIZE		0x1000
3423377e23a2Schristos #define elf_info_to_howto	microblaze_elf_info_to_howto
3424377e23a2Schristos #define elf_info_to_howto_rel	NULL
3425377e23a2Schristos 
3426377e23a2Schristos #define bfd_elf32_bfd_reloc_type_lookup		microblaze_elf_reloc_type_lookup
3427377e23a2Schristos #define bfd_elf32_bfd_is_local_label_name	microblaze_elf_is_local_label_name
3428377e23a2Schristos #define elf_backend_relocate_section		microblaze_elf_relocate_section
3429377e23a2Schristos #define bfd_elf32_bfd_relax_section		microblaze_elf_relax_section
34301c468f90Schristos #define bfd_elf32_bfd_merge_private_bfd_data	_bfd_generic_verify_endian_match
3431377e23a2Schristos #define bfd_elf32_bfd_reloc_name_lookup		microblaze_elf_reloc_name_lookup
3432377e23a2Schristos 
3433377e23a2Schristos #define elf_backend_gc_mark_hook		microblaze_elf_gc_mark_hook
3434377e23a2Schristos #define elf_backend_check_relocs		microblaze_elf_check_relocs
3435377e23a2Schristos #define elf_backend_copy_indirect_symbol	microblaze_elf_copy_indirect_symbol
3436377e23a2Schristos #define bfd_elf32_bfd_link_hash_table_create	microblaze_elf_link_hash_table_create
3437377e23a2Schristos #define elf_backend_can_gc_sections		1
3438377e23a2Schristos #define elf_backend_can_refcount		1
3439377e23a2Schristos #define elf_backend_want_got_plt		1
3440377e23a2Schristos #define elf_backend_plt_readonly		1
3441377e23a2Schristos #define elf_backend_got_header_size		12
34421c468f90Schristos #define elf_backend_want_dynrelro		1
3443377e23a2Schristos #define elf_backend_rela_normal			1
34441c468f90Schristos #define elf_backend_dtrel_excludes_plt		1
3445377e23a2Schristos 
3446377e23a2Schristos #define elf_backend_adjust_dynamic_symbol	microblaze_elf_adjust_dynamic_symbol
34471c468f90Schristos #define elf_backend_create_dynamic_sections	_bfd_elf_create_dynamic_sections
3448377e23a2Schristos #define elf_backend_finish_dynamic_sections	microblaze_elf_finish_dynamic_sections
3449377e23a2Schristos #define elf_backend_finish_dynamic_symbol	microblaze_elf_finish_dynamic_symbol
3450377e23a2Schristos #define elf_backend_size_dynamic_sections	microblaze_elf_size_dynamic_sections
3451377e23a2Schristos #define elf_backend_add_symbol_hook		microblaze_elf_add_symbol_hook
3452377e23a2Schristos 
3453377e23a2Schristos #include "elf32-target.h"
3454