* config/tc-sparc.c: Reorganize file.
[deliverable/binutils-gdb.git] / bfd / elf32-v850.c
CommitLineData
01b49cb3 1/* V850-specific support for 32-bit ELF
de224d6a 2 Copyright (C) 1996, 1997 Free Software Foundation, Inc.
01b49cb3
C
3
4This file is part of BFD, the Binary File Descriptor library.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
90ffe48b
JL
20
21
22/* XXX FIXME: This code is littered with 32bit int, 16bit short, 8bit char
23 dependencies. As is the gas & simulator code or the v850. */
24
25
01b49cb3
C
26#include "bfd.h"
27#include "sysdep.h"
725b96f5 28#include "bfdlink.h"
01b49cb3
C
29#include "libbfd.h"
30#include "elf-bfd.h"
de224d6a 31#include "elf/v850.h"
01b49cb3 32
de224d6a 33static reloc_howto_type *v850_elf_reloc_type_lookup
01b49cb3 34 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
de224d6a 35static void v850_elf_info_to_howto_rel
01b49cb3 36 PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
de224d6a 37static bfd_reloc_status_type v850_elf_reloc
e73b6ae6 38 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
8988d935 39static boolean v850_elf_is_local_label_name PARAMS ((bfd *, const char *));
de224d6a
MM
40static boolean v850_elf_relocate_section PARAMS((bfd *,
41 struct bfd_link_info *,
42 bfd *,
43 asection *,
44 bfd_byte *,
45 Elf_Internal_Rela *,
46 Elf_Internal_Sym *,
47 asection **));
01b49cb3
C
48/* Try to minimize the amount of space occupied by relocation tables
49 on the ROM (not that the ROM won't be swamped by other ELF overhead). */
50#define USE_REL
51
def31039
NC
52/* Note: It is REQUIRED that the 'type' value of each entry in this array
53 match the index of the entry in the array. */
de224d6a 54static reloc_howto_type v850_elf_howto_table[] =
01b49cb3
C
55{
56 /* This reloc does nothing. */
de224d6a
MM
57 HOWTO (R_V850_NONE, /* type */
58 0, /* rightshift */
59 2, /* size (0 = byte, 1 = short, 2 = long) */
60 32, /* bitsize */
61 false, /* pc_relative */
62 0, /* bitpos */
63 complain_overflow_bitfield, /* complain_on_overflow */
64 bfd_elf_generic_reloc, /* special_function */
65 "R_V850_NONE", /* name */
66 false, /* partial_inplace */
67 0, /* src_mask */
68 0, /* dst_mask */
69 false), /* pcrel_offset */
01b49cb3
C
70
71 /* A PC relative 9 bit branch. */
de224d6a
MM
72 HOWTO (R_V850_9_PCREL, /* type */
73 2, /* rightshift */
74 2, /* size (0 = byte, 1 = short, 2 = long) */
75 26, /* bitsize */
76 true, /* pc_relative */
77 0, /* bitpos */
78 complain_overflow_bitfield, /* complain_on_overflow */
79 v850_elf_reloc, /* special_function */
80 "R_V850_9_PCREL", /* name */
81 false, /* partial_inplace */
82 0x00ffffff, /* src_mask */
83 0x00ffffff, /* dst_mask */
84 true), /* pcrel_offset */
01b49cb3
C
85
86 /* A PC relative 22 bit branch. */
de224d6a
MM
87 HOWTO (R_V850_22_PCREL, /* type */
88 2, /* rightshift */
89 2, /* size (0 = byte, 1 = short, 2 = long) */
90 22, /* bitsize */
91 true, /* pc_relative */
92 7, /* bitpos */
93 complain_overflow_signed, /* complain_on_overflow */
94 v850_elf_reloc, /* special_function */
95 "R_V850_22_PCREL", /* name */
96 false, /* partial_inplace */
97 0x07ffff80, /* src_mask */
98 0x07ffff80, /* dst_mask */
99 true), /* pcrel_offset */
01b49cb3
C
100
101 /* High 16 bits of symbol value. */
de224d6a
MM
102 HOWTO (R_V850_HI16_S, /* type */
103 0, /* rightshift */
104 1, /* size (0 = byte, 1 = short, 2 = long) */
105 16, /* bitsize */
106 false, /* pc_relative */
107 0, /* bitpos */
108 complain_overflow_dont, /* complain_on_overflow */
109 v850_elf_reloc, /* special_function */
110 "R_V850_HI16_S", /* name */
111 true, /* partial_inplace */
112 0xffff, /* src_mask */
113 0xffff, /* dst_mask */
114 false), /* pcrel_offset */
01b49cb3
C
115
116 /* High 16 bits of symbol value. */
de224d6a
MM
117 HOWTO (R_V850_HI16, /* type */
118 0, /* rightshift */
119 1, /* size (0 = byte, 1 = short, 2 = long) */
120 16, /* bitsize */
121 false, /* pc_relative */
122 0, /* bitpos */
123 complain_overflow_dont, /* complain_on_overflow */
124 v850_elf_reloc, /* special_function */
125 "R_V850_HI16", /* name */
126 true, /* partial_inplace */
127 0xffff, /* src_mask */
128 0xffff, /* dst_mask */
129 false), /* pcrel_offset */
01b49cb3
C
130
131 /* Low 16 bits of symbol value. */
de224d6a
MM
132 HOWTO (R_V850_LO16, /* type */
133 0, /* rightshift */
134 1, /* size (0 = byte, 1 = short, 2 = long) */
135 16, /* bitsize */
136 false, /* pc_relative */
137 0, /* bitpos */
138 complain_overflow_dont, /* complain_on_overflow */
8988d935 139 v850_elf_reloc, /* special_function */
de224d6a
MM
140 "R_V850_LO16", /* name */
141 true, /* partial_inplace */
142 0xffff, /* src_mask */
143 0xffff, /* dst_mask */
144 false), /* pcrel_offset */
237b5c4c
JL
145
146 /* Simple 32bit reloc. */
de224d6a
MM
147 HOWTO (R_V850_32, /* type */
148 0, /* rightshift */
149 2, /* size (0 = byte, 1 = short, 2 = long) */
150 32, /* bitsize */
151 false, /* pc_relative */
152 0, /* bitpos */
153 complain_overflow_dont, /* complain_on_overflow */
154 bfd_elf_generic_reloc, /* special_function */
155 "R_V850_32", /* name */
156 true, /* partial_inplace */
157 0xffffffff, /* src_mask */
158 0xffffffff, /* dst_mask */
159 false), /* pcrel_offset */
237b5c4c
JL
160
161 /* Simple 16bit reloc. */
de224d6a
MM
162 HOWTO (R_V850_16, /* type */
163 0, /* rightshift */
164 1, /* size (0 = byte, 1 = short, 2 = long) */
165 16, /* bitsize */
166 false, /* pc_relative */
167 0, /* bitpos */
168 complain_overflow_dont, /* complain_on_overflow */
169 bfd_elf_generic_reloc, /* special_function */
170 "R_V850_16", /* name */
171 true, /* partial_inplace */
172 0xffff, /* src_mask */
173 0xffff, /* dst_mask */
174 false), /* pcrel_offset */
afaed5e9
MM
175
176 /* Simple 8bit reloc. */
de224d6a
MM
177 HOWTO (R_V850_8, /* type */
178 0, /* rightshift */
179 0, /* size (0 = byte, 1 = short, 2 = long) */
180 8, /* bitsize */
181 false, /* pc_relative */
182 0, /* bitpos */
183 complain_overflow_dont, /* complain_on_overflow */
184 bfd_elf_generic_reloc, /* special_function */
185 "R_V850_8", /* name */
186 true, /* partial_inplace */
187 0xff, /* src_mask */
188 0xff, /* dst_mask */
189 false), /* pcrel_offset */
b6d08fce 190
def31039
NC
191 /* 16 bit offset from the short data area pointer. */
192 HOWTO (R_V850_SDA_16_16_OFFSET, /* type */
de224d6a
MM
193 0, /* rightshift */
194 1, /* size (0 = byte, 1 = short, 2 = long) */
195 16, /* bitsize */
196 false, /* pc_relative */
197 0, /* bitpos */
198 complain_overflow_dont, /* complain_on_overflow */
8988d935 199 v850_elf_reloc, /* special_function */
def31039
NC
200 "R_V850_SDA_16_16_OFFSET", /* name */
201 false, /* partial_inplace */
de224d6a
MM
202 0xffff, /* src_mask */
203 0xffff, /* dst_mask */
204 false), /* pcrel_offset */
b6d08fce 205
def31039
NC
206 /* 15 bit offset from the short data area pointer. */
207 HOWTO (R_V850_SDA_15_16_OFFSET, /* type */
208 1, /* rightshift */
209 1, /* size (0 = byte, 1 = short, 2 = long) */
210 16, /* bitsize */
211 false, /* pc_relative */
212 1, /* bitpos */
213 complain_overflow_dont, /* complain_on_overflow */
214 v850_elf_reloc, /* special_function */
215 "R_V850_SDA_15_16_OFFSET", /* name */
216 false, /* partial_inplace */
217 0xfffe, /* src_mask */
218 0xfffe, /* dst_mask */
219 false), /* pcrel_offset */
220
221 /* 16 bit offset from the zero data area pointer. */
222 HOWTO (R_V850_ZDA_16_16_OFFSET, /* type */
de224d6a
MM
223 0, /* rightshift */
224 1, /* size (0 = byte, 1 = short, 2 = long) */
225 16, /* bitsize */
226 false, /* pc_relative */
227 0, /* bitpos */
228 complain_overflow_dont, /* complain_on_overflow */
8988d935 229 v850_elf_reloc, /* special_function */
def31039
NC
230 "R_V850_ZDA_16_16_OFFSET", /* name */
231 false, /* partial_inplace */
de224d6a
MM
232 0xffff, /* src_mask */
233 0xffff, /* dst_mask */
234 false), /* pcrel_offset */
b6d08fce 235
def31039
NC
236 /* 15 bit offset from the zero data area pointer. */
237 HOWTO (R_V850_ZDA_15_16_OFFSET, /* type */
238 1, /* rightshift */
239 1, /* size (0 = byte, 1 = short, 2 = long) */
240 16, /* bitsize */
241 false, /* pc_relative */
242 1, /* bitpos */
243 complain_overflow_dont, /* complain_on_overflow */
244 v850_elf_reloc, /* special_function */
245 "R_V850_ZDA_15_16_OFFSET", /* name */
246 false, /* partial_inplace */
247 0xfffe, /* src_mask */
248 0xfffe, /* dst_mask */
249 false), /* pcrel_offset */
250
251 /* 6 bit offset from the tiny data area pointer. */
252 HOWTO (R_V850_TDA_6_8_OFFSET, /* type */
253 2, /* rightshift */
254 1, /* size (0 = byte, 1 = short, 2 = long) */
255 8, /* bitsize */
256 false, /* pc_relative */
257 1, /* bitpos */
258 complain_overflow_dont, /* complain_on_overflow */
259 v850_elf_reloc, /* special_function */
260 "R_V850_TDA_6_8_OFFSET", /* name */
261 false, /* partial_inplace */
262 0x7e, /* src_mask */
263 0x7e, /* dst_mask */
264 false), /* pcrel_offset */
265
266 /* 8 bit offset from the tiny data area pointer. */
267 HOWTO (R_V850_TDA_7_8_OFFSET, /* type */
268 1, /* rightshift */
269 1, /* size (0 = byte, 1 = short, 2 = long) */
270 8, /* bitsize */
271 false, /* pc_relative */
272 0, /* bitpos */
273 complain_overflow_dont, /* complain_on_overflow */
274 v850_elf_reloc, /* special_function */
275 "R_V850_TDA_7_8_OFFSET", /* name */
276 false, /* partial_inplace */
277 0x7f, /* src_mask */
278 0x7f, /* dst_mask */
279 false), /* pcrel_offset */
280
281 /* 7 bit offset from the tiny data area pointer. */
282 HOWTO (R_V850_TDA_7_7_OFFSET, /* type */
283 0, /* rightshift */
284 1, /* size (0 = byte, 1 = short, 2 = long) */
285 7, /* bitsize */
286 false, /* pc_relative */
287 0, /* bitpos */
288 complain_overflow_dont, /* complain_on_overflow */
289 v850_elf_reloc, /* special_function */
290 "R_V850_TDA_7_7_OFFSET", /* name */
291 false, /* partial_inplace */
292 0x7f, /* src_mask */
293 0x7f, /* dst_mask */
294 false), /* pcrel_offset */
295
5bb28764
NC
296 /* 16 bit offset from the tiny data area pointer! */
297 HOWTO (R_V850_TDA_16_16_OFFSET, /* type */
298 0, /* rightshift */
299 1, /* size (0 = byte, 1 = short, 2 = long) */
300 16, /* bitsize */
301 false, /* pc_relative */
302 0, /* bitpos */
303 complain_overflow_dont, /* complain_on_overflow */
304 v850_elf_reloc, /* special_function */
305 "R_V850_TDA_16_16_OFFSET", /* name */
306 false, /* partial_inplace */
307 0xffff, /* src_mask */
308 0xfff, /* dst_mask */
309 false), /* pcrel_offset */
310
def31039
NC
311/* start-sanitize-v850e */
312
313 /* 5 bit offset from the tiny data area pointer. */
314 HOWTO (R_V850_TDA_4_5_OFFSET, /* type */
315 1, /* rightshift */
316 1, /* size (0 = byte, 1 = short, 2 = long) */
317 5, /* bitsize */
318 false, /* pc_relative */
319 0, /* bitpos */
320 complain_overflow_dont, /* complain_on_overflow */
321 v850_elf_reloc, /* special_function */
322 "R_V850_TDA_4_5_OFFSET", /* name */
323 false, /* partial_inplace */
324 0x0f, /* src_mask */
325 0x0f, /* dst_mask */
326 false), /* pcrel_offset */
327
328 /* 4 bit offset from the tiny data area pointer. */
329 HOWTO (R_V850_TDA_4_4_OFFSET, /* type */
330 0, /* rightshift */
331 1, /* size (0 = byte, 1 = short, 2 = long) */
332 4, /* bitsize */
333 false, /* pc_relative */
334 0, /* bitpos */
335 complain_overflow_dont, /* complain_on_overflow */
336 v850_elf_reloc, /* special_function */
337 "R_V850_TDA_4_4_OFFSET", /* name */
338 false, /* partial_inplace */
339 0x0f, /* src_mask */
340 0x0f, /* dst_mask */
341 false), /* pcrel_offset */
342
343 /* 16 bit offset from the short data area pointer. */
344 HOWTO (R_V850_SDA_16_16_SPLIT_OFFSET, /* type */
de224d6a
MM
345 0, /* rightshift */
346 2, /* size (0 = byte, 1 = short, 2 = long) */
def31039 347 16, /* bitsize */
de224d6a
MM
348 false, /* pc_relative */
349 0, /* bitpos */
350 complain_overflow_dont, /* complain_on_overflow */
8988d935 351 v850_elf_reloc, /* special_function */
def31039
NC
352 "R_V850_SDA_16_16_SPLIT_OFFSET",/* name */
353 false, /* partial_inplace */
354 0xfffe0020, /* src_mask */
355 0xfffe0020, /* dst_mask */
de224d6a 356 false), /* pcrel_offset */
b6d08fce 357
def31039
NC
358 /* 16 bit offset from the zero data area pointer. */
359 HOWTO (R_V850_ZDA_16_16_SPLIT_OFFSET, /* type */
360 0, /* rightshift */
361 2, /* size (0 = byte, 1 = short, 2 = long) */
362 16, /* bitsize */
363 false, /* pc_relative */
364 0, /* bitpos */
365 complain_overflow_dont, /* complain_on_overflow */
366 v850_elf_reloc, /* special_function */
367 "R_V850_ZDA_16_16_SPLIT_OFFSET",/* name */
368 false, /* partial_inplace */
369 0xfffe0020, /* src_mask */
370 0xfffe0020, /* dst_mask */
371 false), /* pcrel_offset */
372
9420c20a
NC
373 /* 6 bit offset from the call table base pointer. */
374 HOWTO (R_V850_CALLT_6_7_OFFSET, /* type */
375 0, /* rightshift */
376 1, /* size (0 = byte, 1 = short, 2 = long) */
377 7, /* bitsize */
378 false, /* pc_relative */
379 0, /* bitpos */
380 complain_overflow_dont, /* complain_on_overflow */
381 v850_elf_reloc, /* special_function */
382 "R_V850_CALLT_6_7_OFFSET", /* name */
383 false, /* partial_inplace */
384 0x3f, /* src_mask */
385 0x3f, /* dst_mask */
386 false), /* pcrel_offset */
387
388 /* 16 bit offset from the call table base pointer. */
389 HOWTO (R_V850_CALLT_16_16_OFFSET, /* type */
390 0, /* rightshift */
391 1, /* size (0 = byte, 1 = short, 2 = long) */
392 16, /* bitsize */
393 false, /* pc_relative */
394 0, /* bitpos */
395 complain_overflow_dont, /* complain_on_overflow */
396 v850_elf_reloc, /* special_function */
397 "R_V850_CALLT_16_16_OFFSET", /* name */
398 false, /* partial_inplace */
399 0xffff, /* src_mask */
400 0xffff, /* dst_mask */
401 false), /* pcrel_offset */
402
def31039 403/* end-sanitize-v850e */
01b49cb3
C
404};
405
406/* Map BFD reloc types to V850 ELF reloc types. */
407
de224d6a 408struct v850_elf_reloc_map
01b49cb3
C
409{
410 unsigned char bfd_reloc_val;
411 unsigned char elf_reloc_val;
412};
413
de224d6a 414static const struct v850_elf_reloc_map v850_elf_reloc_map[] =
01b49cb3 415{
def31039
NC
416 { BFD_RELOC_NONE, R_V850_NONE },
417 { BFD_RELOC_V850_9_PCREL, R_V850_9_PCREL },
def31039
NC
418 { BFD_RELOC_V850_22_PCREL, R_V850_22_PCREL },
419 { BFD_RELOC_HI16_S, R_V850_HI16_S },
420 { BFD_RELOC_HI16, R_V850_HI16 },
421 { BFD_RELOC_LO16, R_V850_LO16 },
422 { BFD_RELOC_32, R_V850_32 },
423 { BFD_RELOC_16, R_V850_16 },
424 { BFD_RELOC_8, R_V850_8 },
425 { BFD_RELOC_V850_SDA_16_16_OFFSET, R_V850_SDA_16_16_OFFSET },
426 { BFD_RELOC_V850_SDA_15_16_OFFSET, R_V850_SDA_15_16_OFFSET },
427 { BFD_RELOC_V850_ZDA_16_16_OFFSET, R_V850_ZDA_16_16_OFFSET },
428 { BFD_RELOC_V850_ZDA_15_16_OFFSET, R_V850_ZDA_15_16_OFFSET },
9420c20a
NC
429 { BFD_RELOC_V850_TDA_6_8_OFFSET, R_V850_TDA_6_8_OFFSET },
430 { BFD_RELOC_V850_TDA_7_8_OFFSET, R_V850_TDA_7_8_OFFSET },
431 { BFD_RELOC_V850_TDA_7_7_OFFSET, R_V850_TDA_7_7_OFFSET },
5bb28764 432 { BFD_RELOC_V850_TDA_16_16_OFFSET, R_V850_TDA_16_16_OFFSET },
def31039 433/* start-sanitize-v850e */
9420c20a
NC
434 { BFD_RELOC_V850_TDA_4_5_OFFSET, R_V850_TDA_4_5_OFFSET },
435 { BFD_RELOC_V850_TDA_4_4_OFFSET, R_V850_TDA_4_4_OFFSET },
def31039
NC
436 { BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET, R_V850_SDA_16_16_SPLIT_OFFSET },
437 { BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET, R_V850_ZDA_16_16_SPLIT_OFFSET },
9420c20a
NC
438 { BFD_RELOC_V850_CALLT_6_7_OFFSET, R_V850_CALLT_6_7_OFFSET },
439 { BFD_RELOC_V850_CALLT_16_16_OFFSET, R_V850_CALLT_16_16_OFFSET },
def31039 440/* end-sanitize-v850e */
01b49cb3
C
441};
442
de224d6a
MM
443\f
444/* Map a bfd relocation into the appropriate howto structure */
01b49cb3 445static reloc_howto_type *
de224d6a 446v850_elf_reloc_type_lookup (abfd, code)
9420c20a
NC
447 bfd * abfd;
448 bfd_reloc_code_real_type code;
01b49cb3
C
449{
450 unsigned int i;
451
452 for (i = 0;
de224d6a 453 i < sizeof (v850_elf_reloc_map) / sizeof (struct v850_elf_reloc_map);
01b49cb3
C
454 i++)
455 {
de224d6a 456 if (v850_elf_reloc_map[i].bfd_reloc_val == code)
def31039
NC
457 {
458 BFD_ASSERT (v850_elf_howto_table[v850_elf_reloc_map[i].elf_reloc_val].type == v850_elf_reloc_map[i].elf_reloc_val);
459
460 return & v850_elf_howto_table[v850_elf_reloc_map[i].elf_reloc_val];
461 }
01b49cb3
C
462 }
463
464 return NULL;
465}
466
de224d6a 467\f
01b49cb3 468/* Set the howto pointer for an V850 ELF reloc. */
01b49cb3 469static void
de224d6a 470v850_elf_info_to_howto_rel (abfd, cache_ptr, dst)
9420c20a
NC
471 bfd * abfd;
472 arelent * cache_ptr;
473 Elf32_Internal_Rel * dst;
01b49cb3
C
474{
475 unsigned int r_type;
476
477 r_type = ELF32_R_TYPE (dst->r_info);
478 BFD_ASSERT (r_type < (unsigned int) R_V850_max);
de224d6a
MM
479 cache_ptr->howto = &v850_elf_howto_table[r_type];
480}
481
482\f
483/* Look through the relocs for a section during the first phase, and
484 allocate space in the global offset table or procedure linkage
485 table. */
486
487static boolean
488v850_elf_check_relocs (abfd, info, sec, relocs)
9420c20a
NC
489 bfd * abfd;
490 struct bfd_link_info * info;
491 asection * sec;
492 const Elf_Internal_Rela * relocs;
de224d6a
MM
493{
494 boolean ret = true;
495 bfd *dynobj;
496 Elf_Internal_Shdr *symtab_hdr;
497 struct elf_link_hash_entry **sym_hashes;
498 const Elf_Internal_Rela *rel;
499 const Elf_Internal_Rela *rel_end;
500 asection *sreloc;
501 enum reloc_type r_type;
502 int other = 0;
503 const char *common = (const char *)0;
504
505 if (info->relocateable)
506 return true;
507
508#ifdef DEBUG
509 fprintf (stderr, "v850_elf_check_relocs called for section %s in %s\n",
510 bfd_get_section_name (abfd, sec),
511 bfd_get_filename (abfd));
512#endif
513
514 dynobj = elf_hash_table (info)->dynobj;
515 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
516 sym_hashes = elf_sym_hashes (abfd);
517 sreloc = NULL;
518
519 rel_end = relocs + sec->reloc_count;
520 for (rel = relocs; rel < rel_end; rel++)
521 {
522 unsigned long r_symndx;
523 struct elf_link_hash_entry *h;
524
525 r_symndx = ELF32_R_SYM (rel->r_info);
526 if (r_symndx < symtab_hdr->sh_info)
527 h = NULL;
528 else
529 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
530
531 r_type = (enum reloc_type) ELF32_R_TYPE (rel->r_info);
532 switch (r_type)
533 {
534 default:
535 case R_V850_NONE:
536 case R_V850_9_PCREL:
537 case R_V850_22_PCREL:
538 case R_V850_HI16_S:
539 case R_V850_HI16:
540 case R_V850_LO16:
541 case R_V850_32:
542 case R_V850_16:
543 case R_V850_8:
9420c20a
NC
544/* start-sanitize-v850e */
545 case R_V850_CALLT_6_7_OFFSET:
546 case R_V850_CALLT_16_16_OFFSET:
547/* end-sanitize-v850e */
de224d6a
MM
548 break;
549
def31039
NC
550/* start-sanitize-v850e */
551 case R_V850_SDA_16_16_SPLIT_OFFSET:
552/* end-sanitize-v850e */
553 case R_V850_SDA_16_16_OFFSET:
554 case R_V850_SDA_15_16_OFFSET:
de224d6a
MM
555 other = V850_OTHER_SDA;
556 common = ".scommon";
557 goto small_data_common;
def31039
NC
558
559/* start-sanitize-v850e */
560 case R_V850_ZDA_16_16_SPLIT_OFFSET:
561/* end-sanitize-v850e */
562 case R_V850_ZDA_16_16_OFFSET:
563 case R_V850_ZDA_15_16_OFFSET:
de224d6a
MM
564 other = V850_OTHER_ZDA;
565 common = ".zcommon";
566 goto small_data_common;
def31039
NC
567
568/* start-sanitize-v850e */
569 case R_V850_TDA_4_5_OFFSET:
570 case R_V850_TDA_4_4_OFFSET:
2cf9a0d0 571/* end-sanitize-v850e */
def31039
NC
572 case R_V850_TDA_6_8_OFFSET:
573 case R_V850_TDA_7_8_OFFSET:
574 case R_V850_TDA_7_7_OFFSET:
5bb28764 575 case R_V850_TDA_16_16_OFFSET:
de224d6a
MM
576 other = V850_OTHER_TDA;
577 common = ".tcommon";
578 /* fall through */
579
580#define V850_OTHER_MASK (V850_OTHER_TDA | V850_OTHER_SDA | V850_OTHER_ZDA)
581
582 small_data_common:
583 if (h)
584 {
585 h->other |= other; /* flag which type of relocation was used */
586 if ((h->other & V850_OTHER_MASK) != (other & V850_OTHER_MASK)
587 && (h->other & V850_OTHER_ERROR) == 0)
588 {
589 const char *msg;
590
591 switch (h->other & V850_OTHER_MASK)
592 {
593 default:
594 msg = "Variable cannot occupy in multiple small data regions";
595 break;
596 case V850_OTHER_SDA | V850_OTHER_ZDA | V850_OTHER_TDA:
597 msg = "Variable can only be in one of the small, zero, and tiny data regions";
598 break;
599 case V850_OTHER_SDA | V850_OTHER_ZDA:
600 msg = "Variable cannot be in both small and zero data regions simultaneously";
601 break;
602 case V850_OTHER_SDA | V850_OTHER_TDA:
603 msg = "Variable cannot be in both small and tiny data regions simultaneously";
604 break;
605 case V850_OTHER_ZDA | V850_OTHER_TDA:
606 msg = "Variable cannot be in both zero and tiny data regions simultaneously";
607 break;
608 }
609
610 (*info->callbacks->warning) (info, msg, h->root.root.string,
611 abfd, h->root.u.def.section, 0);
612
613 bfd_set_error (bfd_error_bad_value);
614 h->other |= V850_OTHER_ERROR;
615 ret = false;
616 }
617 }
618
8988d935 619 if (h && h->root.type == bfd_link_hash_common
de224d6a
MM
620 && h->root.u.c.p
621 && !strcmp (bfd_get_section_name (abfd, h->root.u.c.p->section), "COMMON"))
622 {
623 asection *section = h->root.u.c.p->section = bfd_make_section_old_way (abfd, common);
624 section->flags |= SEC_IS_COMMON;
625 }
626
627#ifdef DEBUG
628 fprintf (stderr, "v850_elf_check_relocs, found %s relocation for %s%s\n",
629 v850_elf_howto_table[ (int)r_type ].name,
630 (h && h->root.root.string) ? h->root.root.string : "<unknown>",
631 (h->root.type == bfd_link_hash_common) ? ", symbol is common" : "");
632#endif
633 break;
634 }
635 }
636
637 return ret;
01b49cb3
C
638}
639
de224d6a 640\f
def31039 641/* Insert the addend into the instruction. */
e73b6ae6 642static bfd_reloc_status_type
de224d6a 643v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err)
def31039
NC
644 bfd * abfd;
645 arelent * reloc;
646 asymbol * symbol;
647 PTR data;
648 asection * isection;
649 bfd * obfd;
650 char ** err;
e73b6ae6 651{
5ddf2a9e
NC
652 long relocation;
653 long insn;
654
655
def31039
NC
656 /* If there is an output BFD,
657 and the symbol is not a section name (which is only defined at final link time),
658 and either we are not putting the addend into the instruction
659 or the addend is zero, so there is nothing to add into the instruction
660 then just fixup the address and return. */
e73b6ae6
JL
661 if (obfd != (bfd *) NULL
662 && (symbol->flags & BSF_SECTION_SYM) == 0
663 && (! reloc->howto->partial_inplace
664 || reloc->addend == 0))
665 {
666 reloc->address += isection->output_offset;
667 return bfd_reloc_ok;
668 }
def31039 669#if 0
e73b6ae6
JL
670 else if (obfd != NULL)
671 {
672 return bfd_reloc_continue;
673 }
def31039
NC
674#endif
675
05f1baaa
JL
676 /* Catch relocs involving undefined symbols. */
677 if (bfd_is_und_section (symbol->section)
678 && (symbol->flags & BSF_WEAK) == 0
679 && obfd == NULL)
680 return bfd_reloc_undefined;
681
e73b6ae6 682 /* We handle final linking of some relocs ourselves. */
8988d935 683
5ddf2a9e
NC
684 /* Is the address of the relocation really within the section? */
685 if (reloc->address > isection->_cooked_size)
686 return bfd_reloc_outofrange;
687
688 /* Work out which section the relocation is targetted at and the
689 initial relocation command value. */
690
691 /* Get symbol value. (Common symbols are special.) */
692 if (bfd_is_com_section (symbol->section))
693 relocation = 0;
694 else
695 relocation = symbol->value;
696
697 /* Convert input-section-relative symbol value to absolute + addend. */
698 relocation += symbol->section->output_section->vma;
699 relocation += symbol->section->output_offset;
700 relocation += reloc->addend;
701
702 if (reloc->howto->pc_relative == true)
703 {
704 /* Here the variable relocation holds the final address of the
705 symbol we are relocating against, plus any addend. */
706 relocation -= isection->output_section->vma + isection->output_offset;
707
708 /* Deal with pcrel_offset */
709 relocation -= reloc->address;
710 }
711
712 /* I've got no clue... */
713 reloc->addend = 0;
714
715 switch (reloc->howto->type)
716 {
717 default:
718 /* fprintf (stderr, "reloc type %d not SUPPORTED\n", reloc->howto->type ); */
719 return bfd_reloc_notsupported;
720
721 case R_V850_22_PCREL:
722 if (relocation > 0x1ffff || relocation < -0x200000)
723 return bfd_reloc_overflow;
724
725 if ((relocation % 2) != 0)
726 return bfd_reloc_dangerous;
727
728 insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc->address);
729 insn &= ~0xfffe003f;
730 insn |= (((relocation & 0xfffe) << 16)
731 | ((relocation & 0x3f0000) >> 16));
732 bfd_put_32 (abfd, insn, (bfd_byte *)data + reloc->address);
733 return bfd_reloc_ok;
734
735 case R_V850_9_PCREL:
736 if (relocation > 0xff || relocation < -0x100)
737 return bfd_reloc_overflow;
738
739 if ((relocation % 2) != 0)
740 return bfd_reloc_dangerous;
741
742 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
743 insn &= ~ 0xf870;
744 insn |= ((relocation & 0x1f0) << 7) | ((relocation & 0x0e) << 3);
745 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
746 return bfd_reloc_ok;
747
748 case R_V850_HI16_S:
749 relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
750 relocation = (relocation >> 16) + ((relocation & 0x8000) != 0);
751 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
752 return bfd_reloc_ok;
753
754 case R_V850_HI16:
755 relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
756 relocation = (relocation >> 16);
757 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
758 return bfd_reloc_ok;
759
760 case R_V850_LO16:
761 relocation += (short)bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
762 /* Do not complain if value has top bit set, as this has been anticipated. */
5ddf2a9e
NC
763 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
764 return bfd_reloc_ok;
def31039 765
5ddf2a9e
NC
766 case R_V850_16:
767 relocation += (short)bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
768 /* drop through */
769
770 case R_V850_SDA_16_16_OFFSET:
771 case R_V850_ZDA_16_16_OFFSET:
5bb28764 772 case R_V850_TDA_16_16_OFFSET:
5ddf2a9e
NC
773 if ((long)relocation > 0x7fff || (long)relocation < -0x8000)
774 return bfd_reloc_overflow;
775 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
776 return bfd_reloc_ok;
777
778 case R_V850_SDA_15_16_OFFSET:
779 case R_V850_ZDA_15_16_OFFSET:
780 if ((long)relocation > 0x7ffe || (long)relocation < -0x8000)
781 return bfd_reloc_overflow;
782
783 if (relocation & 1)
784 return bfd_reloc_dangerous;
785
786 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
787 insn &= 1;
788 insn |= (relocation >> 1) & ~1;
789
790 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
791 return bfd_reloc_ok;
792
793 case R_V850_TDA_6_8_OFFSET:
794 if ((long) relocation > 0xfc || (long) relocation < 0)
795 return bfd_reloc_overflow;
796
797 if (relocation & 3)
798 return bfd_reloc_dangerous;
799
800 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
801 insn &= 0xff81;
802 insn |= (relocation >> 1);
803
804 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
805 return bfd_reloc_ok;
806
807 case R_V850_TDA_7_8_OFFSET:
808 if ((long) relocation > 0xfe || (long) relocation < 0)
809 return bfd_reloc_overflow;
810
811 if (relocation & 1)
812 return bfd_reloc_dangerous;
813
814 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
815 insn &= 0xff80;
816 insn |= (relocation >> 1);
817
818 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
819 return bfd_reloc_ok;
820
821 case R_V850_TDA_7_7_OFFSET:
822 if ((long) relocation > 0x7f || (long) relocation < 0)
823 return bfd_reloc_overflow;
824
825 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
826 insn &= 0xff80;
827 insn |= relocation;
828
829 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
830 return bfd_reloc_ok;
831
def31039 832/* start-sanitize-v850e */
5ddf2a9e
NC
833 case R_V850_TDA_4_5_OFFSET:
834 if ((long) relocation > 0x1e || (long) relocation < 0)
835 return bfd_reloc_overflow;
836
837 if (relocation & 1)
838 return bfd_reloc_dangerous;
839
840 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
841 insn &= 0xfff0;
842 insn |= (relocation >> 1);
843
844 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
845 return bfd_reloc_ok;
846
847 case R_V850_TDA_4_4_OFFSET:
848 if ((long) relocation > 0xf || (long) relocation < 0)
849 return bfd_reloc_overflow;
850
851 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
852 insn &= 0xfff0;
853 insn |= relocation;
854
855 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
856 return bfd_reloc_ok;
857
858 case R_V850_ZDA_16_16_SPLIT_OFFSET:
859 case R_V850_SDA_16_16_SPLIT_OFFSET:
860 if ((long) relocation > 0xffff || (long) relocation < 0)
861 return bfd_reloc_overflow;
862
863 insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc->address);
864
865 insn &= 0x0001ffdf;
866 insn |= (relocation & 1) << 5;
867 insn |= (relocation & ~1) << 16;
868
869 bfd_put_32 (abfd, insn, (bfd_byte *)data + reloc->address);
870 return bfd_reloc_ok;
9420c20a
NC
871
872 case R_V850_CALLT_6_7_OFFSET:
873 if ((long) relocation > 0x7e || (long) relocation < 0)
874 return bfd_reloc_overflow;
875
876 if (relocation & 1)
877 return bfd_reloc_dangerous;
878
879 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
880 insn &= 0xff80;
881 insn |= (relocation >> 1);
882
883 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
884 return bfd_reloc_ok;
885
886 case R_V850_CALLT_16_16_OFFSET:
887 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
888 return bfd_reloc_ok;
889
def31039 890/* end-sanitize-v850e */
e73b6ae6
JL
891 }
892
893 return bfd_reloc_continue;
894}
895
de224d6a 896\f
1336da39
SG
897/*ARGSUSED*/
898static boolean
8988d935 899v850_elf_is_local_label_name (abfd, name)
9420c20a
NC
900 bfd * abfd;
901 const char * name;
1336da39 902{
8988d935
NC
903 return ((name[0] == '.' && (name[1] == 'L' || name[1] == '.'))
904 || (name[0] == '_' && name[1] == '.' && name[2] == 'L'
905 && name[3] == '_'));
1336da39
SG
906}
907
de224d6a 908\f
725b96f5
JL
909/* Perform a relocation as part of a final link. */
910static bfd_reloc_status_type
de224d6a 911v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
725b96f5
JL
912 input_section, contents, offset, value,
913 addend, info, sym_sec, is_local)
def31039
NC
914 reloc_howto_type * howto;
915 bfd * input_bfd;
916 bfd * output_bfd;
917 asection * input_section;
918 bfd_byte * contents;
919 bfd_vma offset;
920 bfd_vma value;
921 bfd_vma addend;
922 struct bfd_link_info * info;
923 asection * sym_sec;
924 int is_local;
725b96f5 925{
def31039
NC
926 unsigned long insn;
927 unsigned long r_type = howto->type;
928 bfd_byte * hit_data = contents + offset;
725b96f5
JL
929
930 switch (r_type)
931 {
932 case R_V850_9_PCREL:
933 value -= (input_section->output_section->vma
934 + input_section->output_offset);
935 value -= offset;
936
937 if ((long)value > 0xff || (long)value < -0x100)
938 return bfd_reloc_overflow;
939
940 if ((value % 2) != 0)
941 return bfd_reloc_dangerous;
942
943 insn = bfd_get_16 (input_bfd, hit_data);
c322f1b5 944 insn &= 0x078f;
725b96f5
JL
945 insn |= ((value & 0x1f0) << 7) | ((value & 0x0e) << 3);
946 bfd_put_16 (input_bfd, insn, hit_data);
947 return bfd_reloc_ok;
948
949 case R_V850_22_PCREL:
950 value -= (input_section->output_section->vma
951 + input_section->output_offset);
952 value -= offset;
953
954 if ((long)value > 0x1ffff || (long)value < -0x200000)
955 return bfd_reloc_overflow;
956
957 if ((value % 2) != 0)
958 return bfd_reloc_dangerous;
959
960 insn = bfd_get_32 (input_bfd, hit_data);
c322f1b5 961 insn &= 0x1ffc0;
725b96f5
JL
962 insn |= (((value & 0xfffe) << 16) | ((value & 0x3f0000) >> 16));
963 bfd_put_32 (input_bfd, insn, hit_data);
964 return bfd_reloc_ok;
965
966 case R_V850_HI16_S:
90ffe48b 967 value += (short)bfd_get_16 (input_bfd, hit_data);
725b96f5
JL
968 value = (value >> 16) + ((value & 0x8000) != 0);
969
970 if ((long)value > 0x7fff || (long)value < -0x8000)
971 return bfd_reloc_overflow;
972
973 bfd_put_16 (input_bfd, value, hit_data);
974 return bfd_reloc_ok;
975
976 case R_V850_HI16:
90ffe48b 977 value += (short)bfd_get_16 (input_bfd, hit_data);
725b96f5
JL
978 value >>= 16;
979
980 if ((long)value > 0x7fff || (long)value < -0x8000)
981 return bfd_reloc_overflow;
982
983 bfd_put_16 (input_bfd, value, hit_data);
984 return bfd_reloc_ok;
985
986 case R_V850_LO16:
90ffe48b 987 value += (short)bfd_get_16 (input_bfd, hit_data);
725b96f5
JL
988 value &= 0xffff;
989
990 bfd_put_16 (input_bfd, value, hit_data);
991 return bfd_reloc_ok;
992
993 case R_V850_16:
def31039 994 value += (short) bfd_get_16 (input_bfd, hit_data);
725b96f5 995
def31039
NC
996 if ((long) value > 0x7fff || (long) value < -0x8000)
997 return bfd_reloc_overflow;
998
999 bfd_put_16 (input_bfd, value, hit_data);
1000 return bfd_reloc_ok;
1001
1002 case R_V850_ZDA_16_16_OFFSET:
db1fa6ab
NC
1003 if (sym_sec == NULL)
1004 return bfd_reloc_undefined;
1005
def31039
NC
1006 value -= sym_sec->output_section->vma;
1007 value += (short) bfd_get_16 (input_bfd, hit_data);
1008
1009 if ((long) value > 0x7fff || (long) value < -0x8000)
725b96f5
JL
1010 return bfd_reloc_overflow;
1011
1012 bfd_put_16 (input_bfd, value, hit_data);
1013 return bfd_reloc_ok;
1014
def31039 1015 case R_V850_ZDA_15_16_OFFSET:
db1fa6ab
NC
1016 if (sym_sec == NULL)
1017 return bfd_reloc_undefined;
1018
def31039
NC
1019 insn = bfd_get_16 (input_bfd, hit_data);
1020
1021 value -= sym_sec->output_section->vma;
1022 value += ((insn & 0xfffe) << 1);
1023
1024 if ((long) value > 0x7ffe || (long) value < -0x8000)
1025 return bfd_reloc_overflow;
1026
1027 value &= ~1;
1028 value |= (insn & 1);
1029
1030 bfd_put_16 (input_bfd, value, hit_data);
1031 return bfd_reloc_ok;
1032
725b96f5
JL
1033 case R_V850_32:
1034 value += bfd_get_32 (input_bfd, hit_data);
1035 bfd_put_32 (input_bfd, value, hit_data);
1036 return bfd_reloc_ok;
1037
1038 case R_V850_8:
90ffe48b 1039 value += (char)bfd_get_8 (input_bfd, hit_data);
725b96f5
JL
1040
1041 if ((long)value > 0x7f || (long)value < -0x80)
1042 return bfd_reloc_overflow;
1043
1044 bfd_put_8 (input_bfd, value, hit_data);
1045 return bfd_reloc_ok;
1046
def31039 1047 case R_V850_SDA_16_16_OFFSET:
db1fa6ab
NC
1048 if (sym_sec == NULL)
1049 return bfd_reloc_undefined;
1050
725b96f5 1051 {
def31039
NC
1052 unsigned long gp;
1053 struct bfd_link_hash_entry * h;
725b96f5
JL
1054
1055 /* Get the value of __gp. */
def31039 1056 h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true);
725b96f5
JL
1057 if (h == (struct bfd_link_hash_entry *) NULL
1058 || h->type != bfd_link_hash_defined)
def31039 1059 return bfd_reloc_other;
725b96f5
JL
1060
1061 gp = (h->u.def.value
1062 + h->u.def.section->output_section->vma
1063 + h->u.def.section->output_offset);
def31039
NC
1064
1065 value -= sym_sec->output_section->vma;
1066 value -= (gp - sym_sec->output_section->vma);
1067 value += (short) bfd_get_16 (input_bfd, hit_data);
725b96f5
JL
1068
1069 if ((long)value > 0x7fff || (long)value < -0x8000)
1070 return bfd_reloc_overflow;
1071
1072 bfd_put_16 (input_bfd, value, hit_data);
1073 return bfd_reloc_ok;
1074 }
1075
def31039 1076 case R_V850_SDA_15_16_OFFSET:
db1fa6ab
NC
1077 if (sym_sec == NULL)
1078 return bfd_reloc_undefined;
1079
725b96f5 1080 {
def31039
NC
1081 unsigned long gp;
1082 struct bfd_link_hash_entry * h;
1083
1084 /* Get the value of __gp. */
1085 h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true);
1086 if (h == (struct bfd_link_hash_entry *) NULL
1087 || h->type != bfd_link_hash_defined)
1088 return bfd_reloc_other;
1089
1090 gp = (h->u.def.value
1091 + h->u.def.section->output_section->vma
1092 + h->u.def.section->output_offset);
1093
1094 value -= sym_sec->output_section->vma;
1095 value -= (gp - sym_sec->output_section->vma);
725b96f5 1096
def31039
NC
1097 insn = bfd_get_16 (input_bfd, hit_data);
1098
1099 value += ((insn & 0xfffe) << 1);
1100
1101 if ((long)value > 0x7ffe || (long)value < -0x8000)
1102 return bfd_reloc_overflow;
1103
1104 value &= ~1;
1105 value |= (insn & 1);
1106
1107 bfd_put_16 (input_bfd, value, hit_data);
1108 return bfd_reloc_ok;
1109 }
1110
1111 case R_V850_TDA_6_8_OFFSET:
1112 {
1113 unsigned long ep;
1114 struct bfd_link_hash_entry * h;
1115
c322f1b5 1116 insn = bfd_get_16 (input_bfd, hit_data);
725b96f5
JL
1117
1118 /* Get the value of __ep. */
def31039 1119 h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
725b96f5
JL
1120 if (h == (struct bfd_link_hash_entry *) NULL
1121 || h->type != bfd_link_hash_defined)
def31039 1122 return bfd_reloc_continue; /* Actually this indicates that __ep could not be found. */
725b96f5
JL
1123
1124 ep = (h->u.def.value
1125 + h->u.def.section->output_section->vma
1126 + h->u.def.section->output_offset);
def31039 1127
725b96f5 1128 value -= ep;
def31039
NC
1129 value += ((insn & 0x7e) << 2);
1130
1131 if ((long) value > 0xfc || (long) value < 0)
1132 return bfd_reloc_overflow;
1133
1134 if ((value % 2) != 0)
1135 return bfd_reloc_dangerous;
1136
1137 insn &= 0xff81;
1138 insn |= (value >> 1);
725b96f5 1139
def31039
NC
1140 bfd_put_16 (input_bfd, insn, hit_data);
1141 return bfd_reloc_ok;
1142 }
1143
1144 case R_V850_TDA_7_8_OFFSET:
1145 {
1146 unsigned long ep;
1147 struct bfd_link_hash_entry * h;
1148
1149 insn = bfd_get_16 (input_bfd, hit_data);
725b96f5 1150
def31039
NC
1151 /* Get the value of __ep. */
1152 h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1153 if (h == (struct bfd_link_hash_entry *) NULL
1154 || h->type != bfd_link_hash_defined)
1155 return bfd_reloc_continue; /* Actually this indicates that __ep could not be found. */
c322f1b5 1156
def31039
NC
1157 ep = (h->u.def.value
1158 + h->u.def.section->output_section->vma
1159 + h->u.def.section->output_offset);
1160
1161 value -= ep;
1162 value += ((insn & 0x7f) << 1);
1163
1164 if ((long) value > 0xfe || (long) value < 0)
1165 return bfd_reloc_overflow;
1166
1167 insn &= 0xff80;
1168 insn |= (value >> 1);
1169
1170 bfd_put_16 (input_bfd, insn, hit_data);
1171 return bfd_reloc_ok;
1172 }
1173
1174 case R_V850_TDA_7_7_OFFSET:
1175 {
1176 unsigned long ep;
1177 struct bfd_link_hash_entry * h;
1178
1179 insn = bfd_get_16 (input_bfd, hit_data);
c322f1b5 1180
def31039
NC
1181 /* Get the value of __ep. */
1182 h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1183 if (h == (struct bfd_link_hash_entry *) NULL
1184 || h->type != bfd_link_hash_defined)
1185 return bfd_reloc_continue; /* Actually this indicates that __ep could not be found. */
c322f1b5 1186
def31039
NC
1187 ep = (h->u.def.value
1188 + h->u.def.section->output_section->vma
1189 + h->u.def.section->output_offset);
1190 value -= ep;
1191
1192 value += insn & 0x7f;
1193
1194 if ((long) value > 0x7f || (long) value < 0)
1195 return bfd_reloc_overflow;
1196
1197 insn &= 0xff80;
1198 insn |= value;
1199 bfd_put_16 (input_bfd, insn, hit_data);
1200 return bfd_reloc_ok;
1201 }
1202
5bb28764
NC
1203 case R_V850_TDA_16_16_OFFSET:
1204 {
1205 unsigned long ep;
1206 struct bfd_link_hash_entry * h;
1207
1208 /* Get the value of __ep. */
1209 h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1210 if (h == (struct bfd_link_hash_entry *) NULL
1211 || h->type != bfd_link_hash_defined)
1212 return bfd_reloc_other;
1213
1214 ep = (h->u.def.value
1215 + h->u.def.section->output_section->vma
1216 + h->u.def.section->output_offset);
1217 value -= ep;
1218
1219 value += (short) bfd_get_16 (input_bfd, hit_data);
1220
1221 if ((long)value > 0x7fff || (long)value < -0x8000)
1222 return bfd_reloc_overflow;
1223
1224 bfd_put_16 (input_bfd, value, hit_data);
1225 return bfd_reloc_ok;
1226 }
1227
def31039
NC
1228/* start-sanitize-v850e */
1229 case R_V850_TDA_4_5_OFFSET:
1230 {
1231 unsigned long ep;
1232 struct bfd_link_hash_entry * h;
1233
1234 /* Get the value of __ep. */
1235 h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1236 if (h == (struct bfd_link_hash_entry *) NULL
1237 || h->type != bfd_link_hash_defined)
1238 return bfd_reloc_continue; /* Actually this indicates that __ep could not be found. */
c322f1b5 1239
def31039
NC
1240 ep = (h->u.def.value
1241 + h->u.def.section->output_section->vma
1242 + h->u.def.section->output_offset);
1243 value -= ep;
1244
1245 insn = bfd_get_16 (input_bfd, hit_data);
c322f1b5 1246
def31039
NC
1247 value += ((insn & 0xf) << 1);
1248
1249 if ((long) value > 0x1e || (long) value < 0)
1250 return bfd_reloc_overflow;
1251
1252 insn &= 0xfff0;
1253 insn |= (value >> 1);
1254 bfd_put_16 (input_bfd, insn, hit_data);
1255 return bfd_reloc_ok;
1256 }
1257
1258 case R_V850_TDA_4_4_OFFSET:
1259 {
1260 unsigned long ep;
1261 struct bfd_link_hash_entry * h;
1262
1263 /* Get the value of __ep. */
1264 h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1265 if (h == (struct bfd_link_hash_entry *) NULL
1266 || h->type != bfd_link_hash_defined)
1267 return bfd_reloc_continue; /* Actually this indicates that __ep could not be found. */
c322f1b5 1268
def31039
NC
1269 ep = (h->u.def.value
1270 + h->u.def.section->output_section->vma
1271 + h->u.def.section->output_offset);
1272 value -= ep;
1273
1274 insn = bfd_get_16 (input_bfd, hit_data);
c322f1b5 1275
def31039
NC
1276 value += insn & 0xf;
1277
1278 if ((long) value > 0xf || (long) value < 0)
1279 return bfd_reloc_overflow;
1280
1281 insn &= 0xfff0;
1282 insn |= value;
1283 bfd_put_16 (input_bfd, insn, hit_data);
1284 return bfd_reloc_ok;
1285 }
1286
1287 case R_V850_SDA_16_16_SPLIT_OFFSET:
db1fa6ab
NC
1288 if (sym_sec == NULL)
1289 return bfd_reloc_undefined;
1290
def31039
NC
1291 {
1292 unsigned long gp;
1293 struct bfd_link_hash_entry * h;
c322f1b5 1294
def31039
NC
1295 /* Get the value of __gp. */
1296 h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true);
1297 if (h == (struct bfd_link_hash_entry *) NULL
1298 || h->type != bfd_link_hash_defined)
1299 return bfd_reloc_other;
c322f1b5 1300
def31039
NC
1301 gp = (h->u.def.value
1302 + h->u.def.section->output_section->vma
1303 + h->u.def.section->output_offset);
1304
1305 value -= sym_sec->output_section->vma;
1306 value -= (gp - sym_sec->output_section->vma);
c322f1b5 1307
def31039
NC
1308 insn = bfd_get_32 (input_bfd, hit_data);
1309
1310 value += ((insn & 0xfffe0000) >> 16);
1311 value += ((insn & 0x20) >> 5);
1312
1313 if ((long)value > 0x7fff || (long)value < -0x8000)
1314 return bfd_reloc_overflow;
1315
1316 insn &= 0x0001ffdf;
1317 insn |= (value & 1) << 5;
1318 insn |= (value & ~1) << 16;
1319
1320 bfd_put_32 (input_bfd, insn, hit_data);
1321 return bfd_reloc_ok;
725b96f5 1322 }
def31039
NC
1323
1324 case R_V850_ZDA_16_16_SPLIT_OFFSET:
db1fa6ab
NC
1325 if (sym_sec == NULL)
1326 return bfd_reloc_undefined;
1327
def31039
NC
1328 insn = bfd_get_32 (input_bfd, hit_data);
1329
1330 value -= sym_sec->output_section->vma;
1331 value += ((insn & 0xfffe0000) >> 16);
1332 value += ((insn & 0x20) >> 5);
1333
1334 if ((long)value > 0x7fff || (long)value < -0x8000)
1335 return bfd_reloc_overflow;
1336
1337 insn &= 0x0001ffdf;
1338 insn |= (value & 1) << 5;
1339 insn |= (value & ~1) << 16;
1340
1341 bfd_put_32 (input_bfd, insn, hit_data);
1342 return bfd_reloc_ok;
1343
9420c20a
NC
1344 case R_V850_CALLT_6_7_OFFSET:
1345 {
1346 unsigned long ctbp;
1347 struct bfd_link_hash_entry * h;
1348
1349 /* Get the value of __ctbp. */
1350 h = bfd_link_hash_lookup (info->hash, "__ctbp", false, false, true);
1351 if (h == (struct bfd_link_hash_entry *) NULL
1352 || h->type != bfd_link_hash_defined)
1353 return bfd_reloc_continue; /* Actually this indicates that __ctbp could not be found. */
1354
1355 ctbp = (h->u.def.value
1356 + h->u.def.section->output_section->vma
1357 + h->u.def.section->output_offset);
1358 value -= ctbp;
1359
1360 insn = bfd_get_16 (input_bfd, hit_data);
1361
1362 value += ((insn & 0x3f) << 1);
1363
1364 if ((long) value > 0x7e || (long) value < 0)
1365 return bfd_reloc_overflow;
1366
1367 insn &= 0xff80;
1368 insn |= (value >> 1);
1369 bfd_put_16 (input_bfd, insn, hit_data);
1370 return bfd_reloc_ok;
1371 }
def31039 1372
9420c20a
NC
1373 case R_V850_CALLT_16_16_OFFSET:
1374 if (sym_sec == NULL)
1375 return bfd_reloc_undefined;
1376
1377 {
1378 unsigned long ctbp;
1379 struct bfd_link_hash_entry * h;
1380
1381 /* Get the value of __ctbp. */
1382 h = bfd_link_hash_lookup (info->hash, "__ctbp", false, false, true);
1383 if (h == (struct bfd_link_hash_entry *) NULL
1384 || h->type != bfd_link_hash_defined)
1385 return bfd_reloc_other;
1386
1387 ctbp = (h->u.def.value
1388 + h->u.def.section->output_section->vma
1389 + h->u.def.section->output_offset);
1390
1391 value -= sym_sec->output_section->vma;
1392 value -= (ctbp - sym_sec->output_section->vma);
1393 value += (short) bfd_get_16 (input_bfd, hit_data);
1394
1395 if ((long) value > 0xffff || (long) value < 0)
1396 return bfd_reloc_overflow;
1397
1398 bfd_put_16 (input_bfd, value, hit_data);
1399 return bfd_reloc_ok;
1400 }
1401
1402/* end-sanitize-v850e */
725b96f5
JL
1403
1404 case R_V850_NONE:
8988d935
NC
1405 return bfd_reloc_ok;
1406
725b96f5 1407 default:
8988d935 1408 return bfd_reloc_notsupported;
725b96f5 1409 }
725b96f5
JL
1410}
1411
de224d6a 1412\f
725b96f5 1413/* Relocate an V850 ELF section. */
725b96f5
JL
1414static boolean
1415v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
de224d6a 1416 contents, relocs, local_syms, local_sections)
def31039
NC
1417 bfd * output_bfd;
1418 struct bfd_link_info * info;
1419 bfd * input_bfd;
1420 asection * input_section;
1421 bfd_byte * contents;
1422 Elf_Internal_Rela * relocs;
1423 Elf_Internal_Sym * local_syms;
1424 asection ** local_sections;
725b96f5 1425{
def31039
NC
1426 Elf_Internal_Shdr * symtab_hdr;
1427 struct elf_link_hash_entry ** sym_hashes;
1428 Elf_Internal_Rela * rel;
1429 Elf_Internal_Rela * relend;
725b96f5 1430
def31039 1431 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
725b96f5
JL
1432 sym_hashes = elf_sym_hashes (input_bfd);
1433
def31039 1434 rel = relocs;
725b96f5
JL
1435 relend = relocs + input_section->reloc_count;
1436 for (; rel < relend; rel++)
1437 {
def31039
NC
1438 int r_type;
1439 reloc_howto_type * howto;
1440 unsigned long r_symndx;
1441 Elf_Internal_Sym * sym;
1442 asection * sec;
1443 struct elf_link_hash_entry * h;
1444 bfd_vma relocation;
1445 bfd_reloc_status_type r;
725b96f5 1446
8988d935 1447 r_symndx = ELF32_R_SYM (rel->r_info);
def31039
NC
1448 r_type = ELF32_R_TYPE (rel->r_info);
1449 howto = v850_elf_howto_table + r_type;
8988d935 1450
725b96f5
JL
1451 if (info->relocateable)
1452 {
1453 /* This is a relocateable link. We don't have to change
1454 anything, unless the reloc is against a section symbol,
1455 in which case we have to adjust according to where the
1456 section symbol winds up in the output section. */
1457 if (r_symndx < symtab_hdr->sh_info)
1458 {
1459 sym = local_syms + r_symndx;
1460 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
1461 {
1462 sec = local_sections[r_symndx];
1463 rel->r_addend += sec->output_offset + sym->st_value;
1464 }
1465 }
1466
1467 continue;
1468 }
1469
725b96f5
JL
1470 /* This is a final link. */
1471 h = NULL;
1472 sym = NULL;
1473 sec = NULL;
1474 if (r_symndx < symtab_hdr->sh_info)
1475 {
1476 sym = local_syms + r_symndx;
1477 sec = local_sections[r_symndx];
1478 relocation = (sec->output_section->vma
1479 + sec->output_offset
1480 + sym->st_value);
def31039
NC
1481#if 0
1482 {
1483 char * name;
1484 name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name);
1485 name = (name == NULL) ? "<none>" : name;
1486fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x rel %x\n", sec->name, name, sym->st_name,
1487 sec->output_section->vma, sec->output_offset, sym->st_value, rel->r_addend, rel);
1488 }
1489#endif
725b96f5
JL
1490 }
1491 else
1492 {
1493 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
def31039 1494
725b96f5
JL
1495 while (h->root.type == bfd_link_hash_indirect
1496 || h->root.type == bfd_link_hash_warning)
1497 h = (struct elf_link_hash_entry *) h->root.u.i.link;
def31039 1498
725b96f5
JL
1499 if (h->root.type == bfd_link_hash_defined
1500 || h->root.type == bfd_link_hash_defweak)
1501 {
1502 sec = h->root.u.def.section;
1503 relocation = (h->root.u.def.value
1504 + sec->output_section->vma
1505 + sec->output_offset);
1506 }
1507 else if (h->root.type == bfd_link_hash_undefweak)
1508 relocation = 0;
1509 else
1510 {
1511 if (! ((*info->callbacks->undefined_symbol)
1512 (info, h->root.root.string, input_bfd,
1513 input_section, rel->r_offset)))
1514 return false;
1515 relocation = 0;
1516 }
1517 }
1518
1519 /* FIXME: We should use the addend, but the COFF relocations
1520 don't. */
de224d6a
MM
1521 r = v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
1522 input_section,
1523 contents, rel->r_offset,
1524 relocation, rel->r_addend,
1525 info, sec, h == NULL);
725b96f5
JL
1526
1527 if (r != bfd_reloc_ok)
1528 {
def31039
NC
1529 const char * name;
1530 const char * msg = (const char *)0;
8988d935
NC
1531
1532 if (h != NULL)
1533 name = h->root.root.string;
1534 else
1535 {
1536 name = (bfd_elf_string_from_elf_section
1537 (input_bfd, symtab_hdr->sh_link, sym->st_name));
1538 if (name == NULL || *name == '\0')
1539 name = bfd_section_name (input_bfd, sec);
1540 }
1541
725b96f5
JL
1542 switch (r)
1543 {
725b96f5 1544 case bfd_reloc_overflow:
8988d935
NC
1545 if (! ((*info->callbacks->reloc_overflow)
1546 (info, name, howto->name, (bfd_vma) 0,
1547 input_bfd, input_section, rel->r_offset)))
1548 return false;
1549 break;
1550
1551 case bfd_reloc_undefined:
def31039 1552 fprintf (stderr, "undef2 %s\n", name );
8988d935
NC
1553 if (! ((*info->callbacks->undefined_symbol)
1554 (info, name, input_bfd, input_section,
1555 rel->r_offset)))
1556 return false;
1557 break;
1558
1559 case bfd_reloc_outofrange:
1560 msg = "internal error: out of range error";
1561 goto common_error;
1562
1563 case bfd_reloc_notsupported:
1564 msg = "internal error: unsupported relocation error";
1565 goto common_error;
1566
1567 case bfd_reloc_dangerous:
def31039
NC
1568 msg = "internal error: dangerous relocation";
1569 goto common_error;
1570
1571 case bfd_reloc_other:
1572 msg = "could not locate special linker symbol __gp";
1573 goto common_error;
1574
1575 case bfd_reloc_continue:
1576 msg = "could not locate special linker symbol __ep";
8988d935
NC
1577 goto common_error;
1578
1579 default:
1580 msg = "internal error: unknown error";
1581 /* fall through */
1582
1583 common_error:
1584 if (!((*info->callbacks->warning)
1585 (info, msg, name, input_bfd, input_section,
1586 rel->r_offset)))
1587 return false;
725b96f5
JL
1588 break;
1589 }
1590 }
1591 }
1592
1593 return true;
1594}
01b49cb3 1595
8988d935 1596/* Set the right machine number. */
8988d935
NC
1597static boolean
1598v850_elf_object_p (abfd)
1599 bfd *abfd;
1600{
8bef8c30 1601 switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH)
8988d935
NC
1602 {
1603 default:
8bef8c30 1604 case E_V850_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, 0); break;
8988d935 1605/* start-sanitize-v850e */
8bef8c30 1606 case E_V850E_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e); break;
8988d935
NC
1607/* end-sanitize-v850e */
1608/* start-sanitize-v850eq */
8bef8c30 1609 case E_V850EQ_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850eq); break;
f2dbbf95 1610/* end-sanitize-v850eq */
8988d935
NC
1611 }
1612}
1613
8bef8c30
NC
1614/* Store the machine number in the flags field. */
1615void
1616v850_elf_final_write_processing (abfd, linker)
1617 bfd * abfd;
1618 boolean linker;
1619{
1620 unsigned long val;
1621
1622 switch (bfd_get_mach (abfd))
1623 {
1624 default:
1625 case 0: val = E_V850_ARCH; break;
8988d935 1626/* start-sanitize-v850e */
8bef8c30 1627 case bfd_mach_v850e: val = E_V850E_ARCH; break;
8988d935
NC
1628/* end-sanitize-v850e */
1629/* start-sanitize-v850eq */
8bef8c30 1630 case bfd_mach_v850eq: val = E_V850EQ_ARCH; break;
8988d935 1631/* end-sanitize-v850eq */
8bef8c30
NC
1632 }
1633
1634 elf_elfheader (abfd)->e_flags &=~ EF_V850_ARCH;
1635 elf_elfheader (abfd)->e_flags |= val;
1636}
1637
1638/* Function to keep V850 specific file flags. */
1639boolean
1640v850_elf_set_private_flags (abfd, flags)
1641 bfd * abfd;
1642 flagword flags;
1643{
1644 BFD_ASSERT (!elf_flags_init (abfd)
1645 || elf_elfheader (abfd)->e_flags == flags);
1646
1647 elf_elfheader (abfd)->e_flags = flags;
1648 elf_flags_init (abfd) = true;
1649 return true;
1650}
1651
1652/* Copy backend specific data from one object module to another */
1653boolean
1654v850_elf_copy_private_bfd_data (ibfd, obfd)
1655 bfd * ibfd;
1656 bfd * obfd;
1657{
1658 if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1659 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1660 return true;
1661
1662 BFD_ASSERT (!elf_flags_init (obfd)
1663 || (elf_elfheader (obfd)->e_flags
1664 == elf_elfheader (ibfd)->e_flags));
1665
1666 elf_gp (obfd) = elf_gp (ibfd);
1667 elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
1668 elf_flags_init (obfd) = true;
1669 return true;
1670}
1671
1672/* Merge backend specific data from an object file to the output
1673 object file when linking. */
1674boolean
1675v850_elf_merge_private_bfd_data (ibfd, obfd)
1676 bfd * ibfd;
1677 bfd * obfd;
1678{
1679 flagword old_flags;
1680 flagword new_flags;
1681
1682 if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1683 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1684 return true;
1685
1686 new_flags = elf_elfheader (ibfd)->e_flags;
1687 old_flags = elf_elfheader (obfd)->e_flags;
1688
1689 if (! elf_flags_init (obfd))
1690 {
1691 elf_flags_init (obfd) = true;
1692 elf_elfheader (obfd)->e_flags = new_flags;
1693
1694 if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
1695 && bfd_get_arch_info (obfd)->the_default)
1696 {
1697 return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
1698 }
1699
1700 return true;
1701 }
1702
1703 /* Check flag compatibility. */
8988d935 1704
8bef8c30
NC
1705 if (new_flags == old_flags)
1706 return true;
1707
1708 if ((new_flags & EF_V850_ARCH) != (old_flags & EF_V850_ARCH))
1709 {
1710 _bfd_error_handler ("%s: Architecture mismatch with previous modules",
1711 bfd_get_filename (ibfd));
1712 bfd_set_error (bfd_error_bad_value);
1713 return false;
1714 }
1715
1716 return true;
1717}
1718/* Display the flags field */
1719
1720static boolean
1721v850_elf_print_private_bfd_data (abfd, ptr)
1722 bfd * abfd;
1723 PTR ptr;
1724{
1725 FILE * file = (FILE *) ptr;
1726
1727 BFD_ASSERT (abfd != NULL && ptr != NULL)
1728
1729 fprintf (file, "private flags = %x", elf_elfheader (abfd)->e_flags);
1730
1731 switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH)
1732 {
1733 default:
98ab32a5 1734 case E_V850_ARCH: fprintf (file, ": v850 architecture"); break;
8bef8c30 1735/* start-sanitize-v850e */
98ab32a5 1736 case E_V850E_ARCH: fprintf (file, ": v850e architecture"); break;
8bef8c30
NC
1737/* end-sanitize-v850e */
1738/* start-sanitize-v850eq */
98ab32a5 1739 case E_V850EQ_ARCH: fprintf (file, ": v850eq architecture"); break;
8bef8c30
NC
1740/* end-sanitize-v850eq */
1741 }
1742
1743 fputc ('\n', file);
1744
1745 return true;
1746}
1747\f
1748#define TARGET_LITTLE_SYM bfd_elf32_v850_vec
1749#define TARGET_LITTLE_NAME "elf32-v850"
1750#define ELF_ARCH bfd_arch_v850
1751#define ELF_MACHINE_CODE EM_CYGNUS_V850
de224d6a
MM
1752#define ELF_MAXPAGESIZE 0x1000
1753
1754#define elf_info_to_howto 0
1755#define elf_info_to_howto_rel v850_elf_info_to_howto_rel
1756#define elf_backend_check_relocs v850_elf_check_relocs
1757#define elf_backend_relocate_section v850_elf_relocate_section
8988d935 1758#define elf_backend_object_p v850_elf_object_p
8bef8c30 1759#define elf_backend_final_write_processing v850_elf_final_write_processing
8988d935 1760#define bfd_elf32_bfd_is_local_label_name v850_elf_is_local_label_name
de224d6a 1761#define bfd_elf32_bfd_reloc_type_lookup v850_elf_reloc_type_lookup
8bef8c30
NC
1762#define bfd_elf32_bfd_copy_private_bfd_data v850_elf_copy_private_bfd_data
1763#define bfd_elf32_bfd_merge_private_bfd_data v850_elf_merge_private_bfd_data
1764#define bfd_elf32_bfd_set_private_flags v850_elf_set_private_flags
1765#define bfd_elf32_bfd_print_private_bfd_data v850_elf_print_private_bfd_data
de224d6a
MM
1766
1767#define elf_symbol_leading_char '_'
1336da39 1768
01b49cb3 1769#include "elf32-target.h"
This page took 0.130439 seconds and 4 git commands to generate.