OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [bfd/] [elf32-cr16.c] - Blame information for rev 225

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 24 jeremybenn
/* BFD back-end for National Semiconductor's CR16 ELF
2 225 jeremybenn
   Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
3 24 jeremybenn
   Written by M R Swami Reddy.
4
 
5
   This file is part of BFD, the Binary File Descriptor library.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program; if not, write to the Free Software Foundation,
19
   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
20
 
21
#include "sysdep.h"
22
#include "bfd.h"
23
#include "bfdlink.h"
24
#include "libbfd.h"
25
#include "libiberty.h"
26
#include "elf-bfd.h"
27
#include "elf/cr16.h"
28
 
29 225 jeremybenn
/* The cr16 linker needs to keep track of the number of relocs that
30
   it decides to copy in check_relocs for each symbol.  This is so
31
   that it can discard PC relative relocs if it doesn't need them when
32
   linking with -Bsymbolic.  We store the information in a field
33
   extending the regular ELF linker hash table.  */
34
 
35
struct elf32_cr16_link_hash_entry {
36
  /* The basic elf link hash table entry.  */
37
  struct elf_link_hash_entry root;
38
 
39
  /* For function symbols, the number of times this function is
40
     called directly (ie by name).  */
41
  unsigned int direct_calls;
42
 
43
  /* For function symbols, the size of this function's stack
44
     (if <= 255 bytes).  We stuff this into "call" instructions
45
     to this target when it's valid and profitable to do so.
46
 
47
     This does not include stack allocated by movm!  */
48
  unsigned char stack_size;
49
 
50
  /* For function symbols, arguments (if any) for movm instruction
51
     in the prologue.  We stuff this value into "call" instructions
52
     to the target when it's valid and profitable to do so.  */
53
  unsigned char movm_args;
54
 
55
  /* For function symbols, the amount of stack space that would be allocated
56
     by the movm instruction.  This is redundant with movm_args, but we
57
     add it to the hash table to avoid computing it over and over.  */
58
  unsigned char movm_stack_size;
59
 
60
/* Used to mark functions which have had redundant parts of their
61
   prologue deleted.  */
62
#define CR16_DELETED_PROLOGUE_BYTES 0x1
63
  unsigned char flags;
64
 
65
  /* Calculated value.  */
66
  bfd_vma value;
67
};
68
 
69
/* We derive a hash table from the main elf linker hash table so
70
   we can store state variables and a secondary hash table without
71
   resorting to global variables.  */
72
struct elf32_cr16_link_hash_table {
73
  /* The main hash table.  */
74
  struct elf_link_hash_table root;
75
 
76
  /* A hash table for static functions.  We could derive a new hash table
77
     instead of using the full elf32_cr16_link_hash_table if we wanted
78
     to save some memory.  */
79
  struct elf32_cr16_link_hash_table *static_hash_table;
80
 
81
  /* Random linker state flags.  */
82
#define CR16_HASH_ENTRIES_INITIALIZED 0x1
83
  char flags;
84
};
85
 
86
/* For CR16 linker hash table.  */
87
 
88
/* Get the CR16 ELF linker hash table from a link_info structure.  */
89
 
90
#define elf32_cr16_hash_table(p) \
91
  ((struct elf32_cr16_link_hash_table *) ((p)->hash))
92
 
93
#define elf32_cr16_link_hash_traverse(table, func, info)                    \
94
 (elf_link_hash_traverse                                                    \
95
  (&(table)->root,                                                          \
96
   (bfd_boolean (*) ((struct elf_link_hash_entry *, void *))) (func), (info)))
97
 
98 24 jeremybenn
/* cr16_reloc_map array maps BFD relocation enum into a CRGAS relocation type.  */
99
 
100
struct cr16_reloc_map
101
{
102
  bfd_reloc_code_real_type bfd_reloc_enum; /* BFD relocation enum.  */
103
  unsigned short cr16_reloc_type;          /* CR16 relocation type.  */
104
};
105
 
106
static const struct cr16_reloc_map cr16_reloc_map[R_CR16_MAX] =
107
{
108
  {BFD_RELOC_NONE,           R_CR16_NONE},
109
  {BFD_RELOC_CR16_NUM8,      R_CR16_NUM8},
110
  {BFD_RELOC_CR16_NUM16,     R_CR16_NUM16},
111
  {BFD_RELOC_CR16_NUM32,     R_CR16_NUM32},
112
  {BFD_RELOC_CR16_NUM32a,    R_CR16_NUM32a},
113
  {BFD_RELOC_CR16_REGREL4,   R_CR16_REGREL4},
114
  {BFD_RELOC_CR16_REGREL4a,  R_CR16_REGREL4a},
115
  {BFD_RELOC_CR16_REGREL14,  R_CR16_REGREL14},
116
  {BFD_RELOC_CR16_REGREL14a, R_CR16_REGREL14a},
117
  {BFD_RELOC_CR16_REGREL16,  R_CR16_REGREL16},
118
  {BFD_RELOC_CR16_REGREL20,  R_CR16_REGREL20},
119
  {BFD_RELOC_CR16_REGREL20a, R_CR16_REGREL20a},
120
  {BFD_RELOC_CR16_ABS20,     R_CR16_ABS20},
121
  {BFD_RELOC_CR16_ABS24,     R_CR16_ABS24},
122
  {BFD_RELOC_CR16_IMM4,      R_CR16_IMM4},
123
  {BFD_RELOC_CR16_IMM8,      R_CR16_IMM8},
124
  {BFD_RELOC_CR16_IMM16,     R_CR16_IMM16},
125
  {BFD_RELOC_CR16_IMM20,     R_CR16_IMM20},
126
  {BFD_RELOC_CR16_IMM24,     R_CR16_IMM24},
127
  {BFD_RELOC_CR16_IMM32,     R_CR16_IMM32},
128
  {BFD_RELOC_CR16_IMM32a,    R_CR16_IMM32a},
129
  {BFD_RELOC_CR16_DISP4,     R_CR16_DISP4},
130
  {BFD_RELOC_CR16_DISP8,     R_CR16_DISP8},
131
  {BFD_RELOC_CR16_DISP16,    R_CR16_DISP16},
132
  {BFD_RELOC_CR16_DISP24,    R_CR16_DISP24},
133
  {BFD_RELOC_CR16_DISP24a,   R_CR16_DISP24a},
134
  {BFD_RELOC_CR16_SWITCH8,   R_CR16_SWITCH8},
135
  {BFD_RELOC_CR16_SWITCH16,  R_CR16_SWITCH16},
136 225 jeremybenn
  {BFD_RELOC_CR16_SWITCH32,  R_CR16_SWITCH32},
137
  {BFD_RELOC_CR16_GOT_REGREL20, R_CR16_GOT_REGREL20},
138
  {BFD_RELOC_CR16_GOTC_REGREL20, R_CR16_GOTC_REGREL20},
139
  {BFD_RELOC_CR16_GLOB_DAT,  R_CR16_GLOB_DAT}
140 24 jeremybenn
};
141
 
142
static reloc_howto_type cr16_elf_howto_table[] =
143
{
144
  HOWTO (R_CR16_NONE,              /* type */
145
         0,                        /* rightshift */
146
         2,                        /* size */
147
         32,                       /* bitsize */
148
         FALSE,                    /* pc_relative */
149
         0,                        /* bitpos */
150
         complain_overflow_dont,   /* complain_on_overflow */
151
         bfd_elf_generic_reloc,    /* special_function */
152
         "R_CR16_NONE",            /* name */
153
         FALSE,                    /* partial_inplace */
154
         0,                        /* src_mask */
155
         0,                        /* dst_mask */
156
         FALSE),                   /* pcrel_offset */
157
 
158
  HOWTO (R_CR16_NUM8,              /* type */
159
         0,                        /* rightshift */
160
         0,                        /* size */
161
         8,                        /* bitsize */
162
         FALSE,                    /* pc_relative */
163
         0,                        /* bitpos */
164
         complain_overflow_bitfield,/* complain_on_overflow */
165
         bfd_elf_generic_reloc,    /* special_function */
166
         "R_CR16_NUM8",            /* name */
167
         FALSE,                    /* partial_inplace */
168 225 jeremybenn
         0x0,                      /* src_mask */
169 24 jeremybenn
         0xff,                     /* dst_mask */
170
         FALSE),                   /* pcrel_offset */
171
 
172
  HOWTO (R_CR16_NUM16,             /* type */
173
         0,                        /* rightshift */
174
         1,                        /* size */
175
         16,                       /* bitsize */
176
         FALSE,                    /* pc_relative */
177
         0,                        /* bitpos */
178
         complain_overflow_bitfield,/* complain_on_overflow */
179
         bfd_elf_generic_reloc,    /* special_function */
180
         "R_CR16_NUM16",           /* name */
181
         FALSE,                    /* partial_inplace */
182 225 jeremybenn
         0x0,                      /* src_mask */
183 24 jeremybenn
         0xffff,                   /* dst_mask */
184
         FALSE),                   /* pcrel_offset */
185
 
186
  HOWTO (R_CR16_NUM32,             /* type */
187
         0,                        /* rightshift */
188
         2,                        /* size */
189
         32,                       /* bitsize */
190
         FALSE,                    /* pc_relative */
191
         0,                        /* bitpos */
192
         complain_overflow_bitfield,/* complain_on_overflow */
193
         bfd_elf_generic_reloc,    /* special_function */
194
         "R_CR16_NUM32",           /* name */
195
         FALSE,                    /* partial_inplace */
196 225 jeremybenn
         0x0,                      /* src_mask */
197 24 jeremybenn
         0xffffffff,               /* dst_mask */
198
         FALSE),                   /* pcrel_offset */
199
 
200
  HOWTO (R_CR16_NUM32a,            /* type */
201
         1,                        /* rightshift */
202
         2,                        /* size */
203
         32,                       /* bitsize */
204
         FALSE,                    /* pc_relative */
205
         0,                        /* bitpos */
206
         complain_overflow_bitfield,/* complain_on_overflow */
207
         bfd_elf_generic_reloc,    /* special_function */
208
         "R_CR16_NUM32a",          /* name */
209
         FALSE,                    /* partial_inplace */
210 225 jeremybenn
         0x0,                      /* src_mask */
211 24 jeremybenn
         0xffffffff,               /* dst_mask */
212
         FALSE),                   /* pcrel_offset */
213
 
214
  HOWTO (R_CR16_REGREL4,           /* type */
215
         0,                        /* rightshift */
216
         0,                        /* size */
217
         4,                        /* bitsize */
218
         FALSE,                    /* pc_relative */
219
         0,                        /* bitpos */
220
         complain_overflow_bitfield,/* complain_on_overflow */
221
         bfd_elf_generic_reloc,    /* special_function */
222
         "R_CR16_REGREL4",         /* name */
223
         FALSE,                    /* partial_inplace */
224 225 jeremybenn
         0x0,                      /* src_mask */
225 24 jeremybenn
         0xf,                      /* dst_mask */
226
         FALSE),                   /* pcrel_offset */
227
 
228
  HOWTO (R_CR16_REGREL4a,          /* type */
229
         0,                        /* rightshift */
230
         0,                        /* size */
231
         4,                        /* bitsize */
232
         FALSE,                    /* pc_relative */
233
         0,                        /* bitpos */
234
         complain_overflow_bitfield,/* complain_on_overflow */
235
         bfd_elf_generic_reloc,    /* special_function */
236
         "R_CR16_REGREL4a",        /* name */
237
         FALSE,                    /* partial_inplace */
238 225 jeremybenn
         0x0,                      /* src_mask */
239 24 jeremybenn
         0xf,                      /* dst_mask */
240
         FALSE),                   /* pcrel_offset */
241
 
242
  HOWTO (R_CR16_REGREL14,          /* type */
243
         0,                        /* rightshift */
244
         1,                        /* size */
245
         14,                       /* bitsize */
246
         FALSE,                    /* pc_relative */
247
         0,                        /* bitpos */
248
         complain_overflow_bitfield,/* complain_on_overflow */
249
         bfd_elf_generic_reloc,    /* special_function */
250
         "R_CR16_REGREL14",        /* name */
251
         FALSE,                    /* partial_inplace */
252 225 jeremybenn
         0x0,                      /* src_mask */
253 24 jeremybenn
         0x3fff,                   /* dst_mask */
254
         FALSE),                   /* pcrel_offset */
255
 
256
  HOWTO (R_CR16_REGREL14a,         /* type */
257
         0,                        /* rightshift */
258
         1,                        /* size */
259
         14,                       /* bitsize */
260
         FALSE,                    /* pc_relative */
261
         0,                        /* bitpos */
262
         complain_overflow_bitfield,/* complain_on_overflow */
263
         bfd_elf_generic_reloc,    /* special_function */
264
         "R_CR16_REGREL14a",       /* name */
265
         FALSE,                    /* partial_inplace */
266 225 jeremybenn
         0x0,                      /* src_mask */
267 24 jeremybenn
         0x3fff,                   /* dst_mask */
268
         FALSE),                   /* pcrel_offset */
269
 
270
  HOWTO (R_CR16_REGREL16,          /* type */
271
         0,                        /* rightshift */
272
         1,                        /* size */
273
         16,                       /* bitsize */
274
         FALSE,                    /* pc_relative */
275
         0,                        /* bitpos */
276
         complain_overflow_bitfield,/* complain_on_overflow */
277
         bfd_elf_generic_reloc,    /* special_function */
278
         "R_CR16_REGREL16",        /* name */
279
         FALSE,                    /* partial_inplace */
280 225 jeremybenn
         0x0,                      /* src_mask */
281 24 jeremybenn
         0xffff,                   /* dst_mask */
282
         FALSE),                   /* pcrel_offset */
283
 
284
  HOWTO (R_CR16_REGREL20,          /* type */
285
         0,                        /* rightshift */
286
         2,                        /* size */
287
         20,                       /* bitsize */
288
         FALSE,                    /* pc_relative */
289
         0,                        /* bitpos */
290
         complain_overflow_bitfield,/* complain_on_overflow */
291
         bfd_elf_generic_reloc,    /* special_function */
292
         "R_CR16_REGREL20",        /* name */
293
         FALSE,                    /* partial_inplace */
294 225 jeremybenn
         0x0,                      /* src_mask */
295 24 jeremybenn
         0xfffff,                  /* dst_mask */
296
         FALSE),                   /* pcrel_offset */
297
 
298
  HOWTO (R_CR16_REGREL20a,         /* type */
299
         0,                        /* rightshift */
300
         2,                        /* size */
301
         20,                       /* bitsize */
302
         FALSE,                    /* pc_relative */
303
         0,                        /* bitpos */
304
         complain_overflow_bitfield,/* complain_on_overflow */
305
         bfd_elf_generic_reloc,    /* special_function */
306
         "R_CR16_REGREL20a",       /* name */
307
         FALSE,                    /* partial_inplace */
308 225 jeremybenn
         0x0,                      /* src_mask */
309 24 jeremybenn
         0xfffff,                  /* dst_mask */
310
         FALSE),                   /* pcrel_offset */
311
 
312
  HOWTO (R_CR16_ABS20,             /* type */
313
         0,                        /* rightshift */
314
         2,                        /* size */
315
         20,                       /* bitsize */
316
         FALSE,                    /* pc_relative */
317
         0,                        /* bitpos */
318
         complain_overflow_bitfield,/* complain_on_overflow */
319
         bfd_elf_generic_reloc,    /* special_function */
320
         "R_CR16_ABS20",           /* name */
321
         FALSE,                    /* partial_inplace */
322 225 jeremybenn
         0x0,                      /* src_mask */
323 24 jeremybenn
         0xfffff,                  /* dst_mask */
324
         FALSE),                   /* pcrel_offset */
325
 
326
  HOWTO (R_CR16_ABS24,             /* type */
327
         0,                        /* rightshift */
328
         2,                        /* size */
329
         24,                       /* bitsize */
330
         FALSE,                    /* pc_relative */
331
         0,                        /* bitpos */
332
         complain_overflow_bitfield,/* complain_on_overflow */
333
         bfd_elf_generic_reloc,    /* special_function */
334
         "R_CR16_ABS24",           /* name */
335
         FALSE,                    /* partial_inplace */
336 225 jeremybenn
         0x0,                      /* src_mask */
337 24 jeremybenn
         0xffffff,                 /* dst_mask */
338
         FALSE),                   /* pcrel_offset */
339
 
340
  HOWTO (R_CR16_IMM4,              /* type */
341
         0,                        /* rightshift */
342
         0,                        /* size */
343
         4,                        /* bitsize */
344
         FALSE,                    /* pc_relative */
345
         0,                        /* bitpos */
346
         complain_overflow_bitfield,/* complain_on_overflow */
347
         bfd_elf_generic_reloc,    /* special_function */
348
         "R_CR16_IMM4",            /* name */
349
         FALSE,                    /* partial_inplace */
350 225 jeremybenn
         0x0,                      /* src_mask */
351 24 jeremybenn
         0xf,                      /* dst_mask */
352
         FALSE),                   /* pcrel_offset */
353
 
354
  HOWTO (R_CR16_IMM8,              /* type */
355
         0,                        /* rightshift */
356
         0,                        /* size */
357
         8,                        /* bitsize */
358
         FALSE,                    /* pc_relative */
359
         0,                        /* bitpos */
360
         complain_overflow_bitfield,/* complain_on_overflow */
361
         bfd_elf_generic_reloc,    /* special_function */
362
         "R_CR16_IMM8",            /* name */
363
         FALSE,                    /* partial_inplace */
364 225 jeremybenn
         0x0,                      /* src_mask */
365 24 jeremybenn
         0xff,                     /* dst_mask */
366
         FALSE),                   /* pcrel_offset */
367
 
368
  HOWTO (R_CR16_IMM16,             /* type */
369
         0,                        /* rightshift */
370
         1,                        /* size */
371
         16,                       /* bitsize */
372
         FALSE,                    /* pc_relative */
373
         0,                        /* bitpos */
374
         complain_overflow_bitfield,/* complain_on_overflow */
375
         bfd_elf_generic_reloc,    /* special_function */
376
         "R_CR16_IMM16",           /* name */
377
         FALSE,                    /* partial_inplace */
378 225 jeremybenn
         0x0,                      /* src_mask */
379 24 jeremybenn
         0xffff,                   /* dst_mask */
380
         FALSE),                   /* pcrel_offset */
381
 
382
  HOWTO (R_CR16_IMM20,             /* type */
383
         0,                        /* rightshift */
384
         2,                        /* size */
385
         20,                       /* bitsize */
386
         FALSE,                    /* pc_relative */
387
         0,                        /* bitpos */
388
         complain_overflow_bitfield,/* complain_on_overflow */
389
         bfd_elf_generic_reloc,    /* special_function */
390
         "R_CR16_IMM20",           /* name */
391
         FALSE,                    /* partial_inplace */
392 225 jeremybenn
         0x0,                      /* src_mask */
393 24 jeremybenn
         0xfffff,                  /* dst_mask */
394
         FALSE),                   /* pcrel_offset */
395
 
396
  HOWTO (R_CR16_IMM24,             /* type */
397
         0,                        /* rightshift */
398
         2,                        /* size */
399
         24,                       /* bitsize */
400
         FALSE,                    /* pc_relative */
401
         0,                        /* bitpos */
402
         complain_overflow_bitfield,/* complain_on_overflow */
403
         bfd_elf_generic_reloc,    /* special_function */
404
         "R_CR16_IMM24",           /* name */
405
         FALSE,                    /* partial_inplace */
406 225 jeremybenn
         0x0,                      /* src_mask */
407 24 jeremybenn
         0xffffff,                 /* dst_mask */
408
         FALSE),                   /* pcrel_offset */
409
 
410
  HOWTO (R_CR16_IMM32,             /* type */
411
         0,                        /* rightshift */
412
         2,                        /* size */
413
         32,                       /* bitsize */
414
         FALSE,                    /* pc_relative */
415
         0,                        /* bitpos */
416
         complain_overflow_bitfield,/* complain_on_overflow */
417
         bfd_elf_generic_reloc,    /* special_function */
418
         "R_CR16_IMM32",           /* name */
419
         FALSE,                    /* partial_inplace */
420 225 jeremybenn
         0x0,                      /* src_mask */
421 24 jeremybenn
         0xffffffff,               /* dst_mask */
422
         FALSE),                   /* pcrel_offset */
423
 
424
  HOWTO (R_CR16_IMM32a,            /* type */
425
         1,                        /* rightshift */
426
         2,                        /* size */
427
         32,                       /* bitsize */
428
         FALSE,                    /* pc_relative */
429
         0,                        /* bitpos */
430
         complain_overflow_bitfield,/* complain_on_overflow */
431
         bfd_elf_generic_reloc,    /* special_function */
432
         "R_CR16_IMM32a",          /* name */
433
         FALSE,                    /* partial_inplace */
434 225 jeremybenn
         0x0,                      /* src_mask */
435 24 jeremybenn
         0xffffffff,               /* dst_mask */
436
         FALSE),                   /* pcrel_offset */
437
 
438
  HOWTO (R_CR16_DISP4,             /* type */
439
         1,                        /* rightshift */
440
         0,                        /* size (0 = byte, 1 = short, 2 = long) */
441
         4,                        /* bitsize */
442
         TRUE,                     /* pc_relative */
443
         0,                        /* bitpos */
444
         complain_overflow_unsigned, /* complain_on_overflow */
445
         bfd_elf_generic_reloc,    /* special_function */
446
         "R_CR16_DISP4",           /* name */
447
         FALSE,                    /* partial_inplace */
448 225 jeremybenn
         0x0,                      /* src_mask */
449 24 jeremybenn
         0xf,                      /* dst_mask */
450
         FALSE),                   /* pcrel_offset */
451
 
452
  HOWTO (R_CR16_DISP8,             /* type */
453
         1,                        /* rightshift */
454
         0,                        /* size (0 = byte, 1 = short, 2 = long) */
455
         8,                        /* bitsize */
456
         TRUE,                     /* pc_relative */
457
         0,                        /* bitpos */
458
         complain_overflow_unsigned, /* complain_on_overflow */
459
         bfd_elf_generic_reloc,    /* special_function */
460
         "R_CR16_DISP8",           /* name */
461
         FALSE,                    /* partial_inplace */
462 225 jeremybenn
         0x0,                      /* src_mask */
463 24 jeremybenn
         0x1ff,                    /* dst_mask */
464
         FALSE),                   /* pcrel_offset */
465
 
466
  HOWTO (R_CR16_DISP16,            /* type */
467
         0,                        /* rightshift REVIITS: To sync with WinIDEA*/
468
         1,                        /* size (0 = byte, 1 = short, 2 = long) */
469
         16,                       /* bitsize */
470
         TRUE,                     /* pc_relative */
471
         0,                        /* bitpos */
472
         complain_overflow_unsigned, /* complain_on_overflow */
473
         bfd_elf_generic_reloc,    /* special_function */
474
         "R_CR16_DISP16",          /* name */
475
         FALSE,                    /* partial_inplace */
476 225 jeremybenn
         0x0,                      /* src_mask */
477 24 jeremybenn
         0x1ffff,                  /* dst_mask */
478
         FALSE),                   /* pcrel_offset */
479
  /* REVISIT: DISP24 should be left-shift by 2 as per ISA doc
480
     but its not done, to sync with WinIDEA and CR16 4.1 tools */
481
  HOWTO (R_CR16_DISP24,            /* type */
482
         0,                        /* rightshift */
483
         2,                        /* size (0 = byte, 1 = short, 2 = long) */
484
         24,                       /* bitsize */
485
         TRUE,                     /* pc_relative */
486
         0,                        /* bitpos */
487
         complain_overflow_unsigned, /* complain_on_overflow */
488
         bfd_elf_generic_reloc,    /* special_function */
489
         "R_CR16_DISP24",          /* name */
490
         FALSE,                    /* partial_inplace */
491 225 jeremybenn
         0x0,                      /* src_mask */
492 24 jeremybenn
         0x1ffffff,                /* dst_mask */
493
         FALSE),                   /* pcrel_offset */
494
 
495
  HOWTO (R_CR16_DISP24a,           /* type */
496
         0,                        /* rightshift */
497
         2,                        /* size (0 = byte, 1 = short, 2 = long) */
498
         24,                       /* bitsize */
499
         TRUE,                     /* pc_relative */
500
         0,                        /* bitpos */
501
         complain_overflow_unsigned, /* complain_on_overflow */
502
         bfd_elf_generic_reloc,    /* special_function */
503
         "R_CR16_DISP24a",         /* name */
504
         FALSE,                    /* partial_inplace */
505 225 jeremybenn
         0x0,                      /* src_mask */
506 24 jeremybenn
         0xffffff,                 /* dst_mask */
507
         FALSE),                   /* pcrel_offset */
508
 
509
  /* An 8 bit switch table entry.  This is generated for an expression
510
     such as ``.byte L1 - L2''.  The offset holds the difference
511
     between the reloc address and L2.  */
512
  HOWTO (R_CR16_SWITCH8,           /* type */
513
         0,                        /* rightshift */
514
         0,                        /* size (0 = byte, 1 = short, 2 = long) */
515
         8,                        /* bitsize */
516
         FALSE,                    /* pc_relative */
517
         0,                        /* bitpos */
518
         complain_overflow_unsigned, /* complain_on_overflow */
519
         bfd_elf_generic_reloc,    /* special_function */
520
         "R_CR16_SWITCH8",         /* name */
521
         FALSE,                    /* partial_inplace */
522 225 jeremybenn
         0x0,                      /* src_mask */
523 24 jeremybenn
         0xff,                     /* dst_mask */
524
         TRUE),                    /* pcrel_offset */
525
 
526
  /* A 16 bit switch table entry.  This is generated for an expression
527
     such as ``.word L1 - L2''.  The offset holds the difference
528
     between the reloc address and L2.  */
529
  HOWTO (R_CR16_SWITCH16,          /* type */
530
         0,                        /* rightshift */
531
         1,                        /* size (0 = byte, 1 = short, 2 = long) */
532
         16,                       /* bitsize */
533
         FALSE,                    /* pc_relative */
534
         0,                        /* bitpos */
535
         complain_overflow_unsigned, /* complain_on_overflow */
536
         bfd_elf_generic_reloc,    /* special_function */
537
         "R_CR16_SWITCH16",        /* name */
538
         FALSE,                    /* partial_inplace */
539 225 jeremybenn
         0x0,                      /* src_mask */
540 24 jeremybenn
         0xffff,                   /* dst_mask */
541
         TRUE),                    /* pcrel_offset */
542
 
543
  /* A 32 bit switch table entry.  This is generated for an expression
544
     such as ``.long L1 - L2''.  The offset holds the difference
545
     between the reloc address and L2.  */
546
  HOWTO (R_CR16_SWITCH32,          /* type */
547
         0,                        /* rightshift */
548
         2,                        /* size (0 = byte, 1 = short, 2 = long) */
549
         32,                       /* bitsize */
550
         FALSE,                    /* pc_relative */
551
         0,                        /* bitpos */
552
         complain_overflow_unsigned, /* complain_on_overflow */
553
         bfd_elf_generic_reloc,    /* special_function */
554
         "R_CR16_SWITCH32",        /* name */
555
         FALSE,                    /* partial_inplace */
556 225 jeremybenn
         0x0,                      /* src_mask */
557 24 jeremybenn
         0xffffffff,               /* dst_mask */
558 225 jeremybenn
         TRUE),                    /* pcrel_offset */
559
 
560
  HOWTO (R_CR16_GOT_REGREL20,      /* type */
561
         0,                        /* rightshift */
562
         2,                        /* size */
563
         20,                       /* bitsize */
564
         FALSE,                    /* pc_relative */
565
         0,                        /* bitpos */
566
         complain_overflow_bitfield,/* complain_on_overflow */
567
         bfd_elf_generic_reloc,    /* special_function */
568
         "R_CR16_GOT_REGREL20",    /* name */
569
         TRUE,                     /* partial_inplace */
570
         0x0,                      /* src_mask */
571
         0xfffff,                  /* dst_mask */
572
         FALSE),                   /* pcrel_offset */
573
 
574
  HOWTO (R_CR16_GOTC_REGREL20,     /* type */
575
         0,                        /* rightshift */
576
         2,                        /* size */
577
         20,                       /* bitsize */
578
         FALSE,                    /* pc_relative */
579
         0,                        /* bitpos */
580
         complain_overflow_bitfield,/* complain_on_overflow */
581
         bfd_elf_generic_reloc,    /* special_function */
582
         "R_CR16_GOTC_REGREL20",   /* name */
583
         TRUE,                     /* partial_inplace */
584
         0x0,                      /* src_mask */
585
         0xfffff,                  /* dst_mask */
586
         FALSE),                   /* pcrel_offset */
587
 
588
  HOWTO (R_CR16_GLOB_DAT,          /* type */
589
         0,                        /* rightshift */
590
         2,                        /* size (0 = byte, 1 = short, 2 = long) */
591
         32,                       /* bitsize */
592
         FALSE,                    /* pc_relative */
593
         0,                        /* bitpos */
594
         complain_overflow_unsigned, /* complain_on_overflow */
595
         bfd_elf_generic_reloc,    /* special_function */
596
         "R_CR16_GLOB_DAT",        /* name */
597
         FALSE,                    /* partial_inplace */
598
         0x0,                      /* src_mask */
599
         0xffffffff,               /* dst_mask */
600 24 jeremybenn
         TRUE)                     /* pcrel_offset */
601
};
602
 
603 225 jeremybenn
 
604
/* Create the GOT section.  */
605
 
606
static bfd_boolean
607
_bfd_cr16_elf_create_got_section (bfd * abfd, struct bfd_link_info * info)
608
{
609
  flagword   flags;
610
  asection * s;
611
  struct elf_link_hash_entry * h;
612
  const struct elf_backend_data * bed = get_elf_backend_data (abfd);
613
  int ptralign;
614
 
615
  /* This function may be called more than once.  */
616
  if (bfd_get_section_by_name (abfd, ".got") != NULL)
617
    return TRUE;
618
 
619
  switch (bed->s->arch_size)
620
    {
621
    case 16:
622
      ptralign = 1;
623
      break;
624
 
625
    case 32:
626
      ptralign = 2;
627
      break;
628
 
629
    default:
630
      bfd_set_error (bfd_error_bad_value);
631
      return FALSE;
632
    }
633
 
634
  flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
635
           | SEC_LINKER_CREATED);
636
 
637
  s = bfd_make_section_with_flags (abfd, ".got", flags);
638
  if (s == NULL
639
      || ! bfd_set_section_alignment (abfd, s, ptralign))
640
    return FALSE;
641
 
642
  if (bed->want_got_plt)
643
    {
644
      s = bfd_make_section_with_flags (abfd, ".got.plt", flags);
645
      if (s == NULL
646
          || ! bfd_set_section_alignment (abfd, s, ptralign))
647
        return FALSE;
648
    }
649
 
650
  /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
651
     (or .got.plt) section.  We don't do this in the linker script
652
     because we don't want to define the symbol if we are not creating
653
     a global offset table.  */
654
  h = _bfd_elf_define_linkage_sym (abfd, info, s, "_GLOBAL_OFFSET_TABLE_");
655
  elf_hash_table (info)->hgot = h;
656
  if (h == NULL)
657
    return FALSE;
658
 
659
  /* The first bit of the global offset table is the header.  */
660
  s->size += bed->got_header_size;
661
 
662
  return TRUE;
663
}
664
 
665
 
666 24 jeremybenn
/* Retrieve a howto ptr using a BFD reloc_code.  */
667
 
668
static reloc_howto_type *
669
elf_cr16_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
670
                            bfd_reloc_code_real_type code)
671
{
672
  unsigned int i;
673
 
674
  for (i = 0; i < R_CR16_MAX; i++)
675
    if (code == cr16_reloc_map[i].bfd_reloc_enum)
676
      return &cr16_elf_howto_table[cr16_reloc_map[i].cr16_reloc_type];
677
 
678
  _bfd_error_handler ("Unsupported CR16 relocation type: 0x%x\n", code);
679
  return NULL;
680
}
681
 
682
static reloc_howto_type *
683
elf_cr16_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
684
                            const char *r_name)
685
{
686
  unsigned int i;
687
 
688
  for (i = 0; ARRAY_SIZE (cr16_elf_howto_table); i++)
689
    if (cr16_elf_howto_table[i].name != NULL
690
        && strcasecmp (cr16_elf_howto_table[i].name, r_name) == 0)
691
      return cr16_elf_howto_table + i;
692
 
693
  return NULL;
694
}
695
 
696
/* Retrieve a howto ptr using an internal relocation entry.  */
697
 
698
static void
699
elf_cr16_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
700
                        Elf_Internal_Rela *dst)
701
{
702
  unsigned int r_type = ELF32_R_TYPE (dst->r_info);
703
 
704
  BFD_ASSERT (r_type < (unsigned int) R_CR16_MAX);
705 225 jeremybenn
  cache_ptr->howto = cr16_elf_howto_table + r_type;
706 24 jeremybenn
}
707
 
708 225 jeremybenn
/* Look through the relocs for a section during the first phase.
709
   Since we don't do .gots or .plts, we just need to consider the
710
   virtual table relocs for gc.  */
711
 
712
static bfd_boolean
713
cr16_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
714
                       const Elf_Internal_Rela *relocs)
715
{
716
  Elf_Internal_Shdr *symtab_hdr;
717
  Elf_Internal_Sym * isymbuf = NULL;
718
  struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
719
  const Elf_Internal_Rela *rel;
720
  const Elf_Internal_Rela *rel_end;
721
  bfd *      dynobj;
722
  bfd_vma *  local_got_offsets;
723
  asection * sgot;
724
  asection * srelgot;
725
 
726
  sgot    = NULL;
727
  srelgot = NULL;
728
  bfd_boolean result = FALSE;
729
 
730
  if (info->relocatable)
731
    return TRUE;
732
 
733
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
734
  sym_hashes = elf_sym_hashes (abfd);
735
  sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
736
  if (!elf_bad_symtab (abfd))
737
    sym_hashes_end -= symtab_hdr->sh_info;
738
 
739
  dynobj = elf_hash_table (info)->dynobj;
740
  local_got_offsets = elf_local_got_offsets (abfd);
741
  rel_end = relocs + sec->reloc_count;
742
  for (rel = relocs; rel < rel_end; rel++)
743
    {
744
      struct elf_link_hash_entry *h;
745
      unsigned long r_symndx;
746
 
747
      r_symndx = ELF32_R_SYM (rel->r_info);
748
      if (r_symndx < symtab_hdr->sh_info)
749
        h = NULL;
750
      else
751
        {
752
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
753
          while (h->root.type == bfd_link_hash_indirect
754
                 || h->root.type == bfd_link_hash_warning)
755
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
756
        }
757
 
758
      /* Some relocs require a global offset table.  */
759
      if (dynobj == NULL)
760
        {
761
          switch (ELF32_R_TYPE (rel->r_info))
762
            {
763
            case R_CR16_GOT_REGREL20:
764
            case R_CR16_GOTC_REGREL20:
765
              elf_hash_table (info)->dynobj = dynobj = abfd;
766
              if (! _bfd_cr16_elf_create_got_section (dynobj, info))
767
                goto fail;
768
              break;
769
 
770
            default:
771
              break;
772
            }
773
        }
774
 
775
      switch (ELF32_R_TYPE (rel->r_info))
776
        {
777
        case R_CR16_GOT_REGREL20:
778
        case R_CR16_GOTC_REGREL20:
779
          /* This symbol requires a global offset table entry.  */
780
 
781
          if (sgot == NULL)
782
            {
783
              sgot = bfd_get_section_by_name (dynobj, ".got");
784
              BFD_ASSERT (sgot != NULL);
785
            }
786
 
787
          if (srelgot == NULL
788
              && (h != NULL || info->executable))
789
            {
790
              srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
791
              if (srelgot == NULL)
792
                {
793
                  srelgot = bfd_make_section_with_flags (dynobj,
794
                                                         ".rela.got",
795
                                                         (SEC_ALLOC
796
                                                          | SEC_LOAD
797
                                                          | SEC_HAS_CONTENTS
798
                                                          | SEC_IN_MEMORY
799
                                                          | SEC_LINKER_CREATED
800
                                                          | SEC_READONLY));
801
                  if (srelgot == NULL
802
                      || ! bfd_set_section_alignment (dynobj, srelgot, 2))
803
                    goto fail;
804
                }
805
            }
806
 
807
          if (h != NULL)
808
            {
809
              if (h->got.offset != (bfd_vma) -1)
810
                /* We have already allocated space in the .got.  */
811
                break;
812
 
813
              h->got.offset = sgot->size;
814
 
815
              /* Make sure this symbol is output as a dynamic symbol.  */
816
              if (h->dynindx == -1)
817
                {
818
                  if (! bfd_elf_link_record_dynamic_symbol (info, h))
819
                    goto fail;
820
                }
821
 
822
              srelgot->size += sizeof (Elf32_External_Rela);
823
            }
824
          else
825
            {
826
              /* This is a global offset table entry for a local
827
                 symbol.  */
828
              if (local_got_offsets == NULL)
829
                {
830
                  size_t       size;
831
                  unsigned int i;
832
 
833
                  size = symtab_hdr->sh_info * sizeof (bfd_vma);
834
                  local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size);
835
 
836
                  if (local_got_offsets == NULL)
837
                    goto fail;
838
 
839
                  elf_local_got_offsets (abfd) = local_got_offsets;
840
 
841
                  for (i = 0; i < symtab_hdr->sh_info; i++)
842
                    local_got_offsets[i] = (bfd_vma) -1;
843
                }
844
 
845
              if (local_got_offsets[r_symndx] != (bfd_vma) -1)
846
                /* We have already allocated space in the .got.  */
847
                break;
848
 
849
              local_got_offsets[r_symndx] = sgot->size;
850
 
851
              if (info->executable)
852
                /* If we are generating a shared object, we need to
853
                   output a R_CR16_RELATIVE reloc so that the dynamic
854
                   linker can adjust this GOT entry.  */
855
                srelgot->size += sizeof (Elf32_External_Rela);
856
            }
857
 
858
          sgot->size += 4;
859
          break;
860
 
861
        }
862
    }
863
 
864
   result = TRUE;
865
  fail:
866
    if (isymbuf != NULL)
867
      free (isymbuf);
868
 
869
  return result;
870
}
871
 
872 24 jeremybenn
/* Perform a relocation as part of a final link.  */
873
 
874
static bfd_reloc_status_type
875
cr16_elf_final_link_relocate (reloc_howto_type *howto,
876
                              bfd *input_bfd,
877
                              bfd *output_bfd ATTRIBUTE_UNUSED,
878
                              asection *input_section,
879
                              bfd_byte *contents,
880
                              bfd_vma offset,
881
                              bfd_vma Rvalue,
882
                              bfd_vma addend,
883 225 jeremybenn
                              struct elf_link_hash_entry * h,
884
                              unsigned long symndx  ATTRIBUTE_UNUSED,
885 24 jeremybenn
                              struct bfd_link_info *info ATTRIBUTE_UNUSED,
886
                              asection *sec ATTRIBUTE_UNUSED,
887
                              int is_local ATTRIBUTE_UNUSED)
888
{
889
  unsigned short r_type = howto->type;
890
  bfd_byte *hit_data = contents + offset;
891
  bfd_vma reloc_bits, check, Rvalue1;
892
 
893 225 jeremybenn
  bfd *      dynobj;
894
  bfd_vma *  local_got_offsets;
895
  asection * sgot;
896
 
897
  dynobj = elf_hash_table (info)->dynobj;
898
  local_got_offsets = elf_local_got_offsets (input_bfd);
899
 
900
  sgot   = NULL;
901
 
902
 
903 24 jeremybenn
  switch (r_type)
904
    {
905
     case R_CR16_IMM4:
906
     case R_CR16_IMM20:
907
     case R_CR16_ABS20:
908
       break;
909
 
910
     case R_CR16_IMM8:
911
     case R_CR16_IMM16:
912
     case R_CR16_IMM32:
913
     case R_CR16_IMM32a:
914
     case R_CR16_REGREL4:
915
     case R_CR16_REGREL4a:
916
     case R_CR16_REGREL14:
917
     case R_CR16_REGREL14a:
918
     case R_CR16_REGREL16:
919
     case R_CR16_REGREL20:
920 225 jeremybenn
     case R_CR16_REGREL20a:
921
     case R_CR16_GOT_REGREL20:
922
     case R_CR16_GOTC_REGREL20:
923 24 jeremybenn
     case R_CR16_ABS24:
924
     case R_CR16_DISP16:
925
     case R_CR16_DISP24:
926
       /* 'hit_data' is relative to the start of the instruction, not the
927
           relocation offset. Advance it to account for the exact offset.  */
928
       hit_data += 2;
929
       break;
930
 
931
     case R_CR16_NONE:
932
       return bfd_reloc_ok;
933
       break;
934
 
935
     case R_CR16_DISP4:
936
       if (is_local)
937 225 jeremybenn
        Rvalue += -1;
938 24 jeremybenn
       break;
939
 
940
     case R_CR16_DISP8:
941
     case R_CR16_DISP24a:
942
       if (is_local)
943 225 jeremybenn
        Rvalue -= -1;
944 24 jeremybenn
       break;
945
 
946
     case R_CR16_SWITCH8:
947
     case R_CR16_SWITCH16:
948
     case R_CR16_SWITCH32:
949
       /* We only care about the addend, where the difference between
950
          expressions is kept.  */
951
       Rvalue = 0;
952 225 jeremybenn
 
953 24 jeremybenn
     default:
954
       break;
955
    }
956
 
957
  if (howto->pc_relative)
958
    {
959
      /* Subtract the address of the section containing the location.  */
960
      Rvalue -= (input_section->output_section->vma
961
                 + input_section->output_offset);
962
      /* Subtract the position of the location within the section.  */
963
      Rvalue -= offset;
964
    }
965
 
966
  /* Add in supplied addend.  */
967
  Rvalue += addend;
968
 
969
  /* Complain if the bitfield overflows, whether it is considered
970
     as signed or unsigned.  */
971
  check = Rvalue >> howto->rightshift;
972
 
973
  /* Assumes two's complement.  This expression avoids
974
     overflow if howto->bitsize is the number of bits in
975
     bfd_vma.  */
976
  reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
977
 
978 225 jeremybenn
  /* For GOT and GOTC relocs no boundary checks applied.  */
979
  if (!((r_type == R_CR16_GOT_REGREL20)
980
      || (r_type == R_CR16_GOTC_REGREL20)))
981 24 jeremybenn
    {
982 225 jeremybenn
      if (((bfd_vma) check & ~reloc_bits) != 0
983
          && (((bfd_vma) check & ~reloc_bits)
984
          != (-(bfd_vma) 1 & ~reloc_bits)))
985 24 jeremybenn
        {
986 225 jeremybenn
          /* The above right shift is incorrect for a signed
987
             value.  See if turning on the upper bits fixes the
988
             overflow.  */
989
          if (howto->rightshift && (bfd_signed_vma) Rvalue < 0)
990
            {
991
              check |= ((bfd_vma) - 1
992
                        & ~((bfd_vma) - 1
993
                         >> howto->rightshift));
994 24 jeremybenn
 
995 225 jeremybenn
              if (((bfd_vma) check & ~reloc_bits)
996
                  != (-(bfd_vma) 1 & ~reloc_bits))
997
                 return bfd_reloc_overflow;
998
            }
999
          else
1000
            return bfd_reloc_overflow;
1001 24 jeremybenn
        }
1002
 
1003 225 jeremybenn
      /* Drop unwanted bits from the value we are relocating to.  */
1004
      Rvalue >>= (bfd_vma) howto->rightshift;
1005 24 jeremybenn
 
1006 225 jeremybenn
      /* Apply dst_mask to select only relocatable part of the insn.  */
1007
      Rvalue &= howto->dst_mask;
1008
    }
1009 24 jeremybenn
 
1010
  switch (howto->size)
1011
    {
1012
      case 0:
1013
        if (r_type == R_CR16_DISP8)
1014
          {
1015
             Rvalue1 = bfd_get_16 (input_bfd, hit_data);
1016
             Rvalue = ((Rvalue1 & 0xf000) | ((Rvalue << 4) & 0xf00)
1017
                       | (Rvalue1 & 0x00f0) | (Rvalue & 0xf));
1018
             bfd_put_16 (input_bfd, Rvalue, hit_data);
1019
          }
1020
        else if (r_type == R_CR16_IMM4)
1021
          {
1022
             Rvalue1 = bfd_get_16 (input_bfd, hit_data);
1023
             Rvalue = (((Rvalue1 & 0xff) << 8) | ((Rvalue << 4) & 0xf0)
1024
                       | ((Rvalue1 & 0x0f00) >> 8));
1025
             bfd_put_16 (input_bfd, Rvalue, hit_data);
1026
          }
1027
        else if (r_type == R_CR16_DISP4)
1028
          {
1029
             Rvalue1 = bfd_get_16 (input_bfd, hit_data);
1030
             Rvalue = (Rvalue1 | ((Rvalue & 0xf) << 4));
1031
             bfd_put_16 (input_bfd, Rvalue, hit_data);
1032
          }
1033 225 jeremybenn
        else
1034 24 jeremybenn
          {
1035
             bfd_put_8 (input_bfd, (unsigned char) Rvalue, hit_data);
1036
          }
1037
        break;
1038
 
1039
      case 1:
1040
        if (r_type == R_CR16_DISP16)
1041
          {
1042
            Rvalue |= (bfd_get_16 (input_bfd, hit_data));
1043
            Rvalue = ((Rvalue & 0xfffe) | ((Rvalue >> 16) & 0x1));
1044
          }
1045 225 jeremybenn
        if (r_type == R_CR16_IMM16)
1046
          {
1047
            Rvalue1 = bfd_get_16 (input_bfd, hit_data);
1048 24 jeremybenn
 
1049 225 jeremybenn
            /* Add or subtract the offset value.  */
1050
            if (Rvalue1 & 0x8000)
1051
              Rvalue -= (~Rvalue1 + 1) & 0xffff;
1052
            else
1053
              Rvalue += Rvalue1;
1054
 
1055
             /* Check for range.  */
1056
             if ((long) Rvalue > 0xffff || (long) Rvalue < 0x0)
1057
              return bfd_reloc_overflow;
1058
          }
1059
 
1060
        bfd_put_16 (input_bfd, Rvalue, hit_data);
1061 24 jeremybenn
        break;
1062
 
1063
      case 2:
1064
        if ((r_type == R_CR16_ABS20) || (r_type == R_CR16_IMM20))
1065
          {
1066 225 jeremybenn
             Rvalue1 = (bfd_get_16 (input_bfd, hit_data + 2)
1067
                        | (((bfd_get_16 (input_bfd, hit_data) & 0xf) <<16)));
1068
 
1069
             /* Add or subtract the offset value.  */
1070
             if (Rvalue1 & 0x80000)
1071
                Rvalue -= (~Rvalue1 + 1) & 0xfffff;
1072
              else
1073
                Rvalue += Rvalue1;
1074
 
1075
              /* Check for range.  */
1076
              if ((long) Rvalue > 0xfffff || (long) Rvalue < 0x0)
1077
               return bfd_reloc_overflow;
1078
 
1079
            bfd_put_16 (input_bfd, ((bfd_get_16 (input_bfd, hit_data) & 0xfff0)
1080
                        | ((Rvalue >> 16) & 0xf)), hit_data);
1081
            bfd_put_16 (input_bfd, (Rvalue) & 0xffff, hit_data + 2);
1082
          }
1083
        else if (r_type == R_CR16_GOT_REGREL20)
1084
          {
1085
            asection * sgot = bfd_get_section_by_name (dynobj, ".got");
1086
 
1087
            if (h != NULL)
1088
              {
1089
                bfd_vma off;
1090
 
1091
                off = h->got.offset;
1092
                BFD_ASSERT (off != (bfd_vma) -1);
1093
 
1094
                if (! elf_hash_table (info)->dynamic_sections_created
1095
                     || SYMBOL_REFERENCES_LOCAL (info, h))
1096
                    /* This is actually a static link, or it is a
1097
                       -Bsymbolic link and the symbol is defined
1098
                       locally, or the symbol was forced to be local
1099
                       because of a version file.  We must initialize
1100
                       this entry in the global offset table.
1101
                       When doing a dynamic link, we create a .rela.got
1102
                       relocation entry to initialize the value.  This
1103
                       is done in the finish_dynamic_symbol routine.  */
1104
                  bfd_put_32 (output_bfd, Rvalue, sgot->contents + off);
1105
 
1106
                  Rvalue = sgot->output_offset + off;
1107
                }
1108
              else
1109
                {
1110
                   bfd_vma off;
1111
 
1112
                   off = elf_local_got_offsets (input_bfd)[symndx];
1113
                   bfd_put_32 (output_bfd,Rvalue, sgot->contents + off);
1114
 
1115
                   Rvalue = sgot->output_offset + off;
1116
                }
1117
 
1118
             Rvalue += addend;
1119
 
1120
             /* REVISIT: if ((long) Rvalue > 0xffffff ||
1121
                                    (long) Rvalue < -0x800000).  */
1122
             if ((long) Rvalue > 0xffffff || (long) Rvalue < 0)
1123
               return bfd_reloc_overflow;
1124
 
1125
 
1126 24 jeremybenn
             bfd_put_16 (input_bfd, (bfd_get_16 (input_bfd, hit_data))
1127 225 jeremybenn
                         | (((Rvalue >> 16) & 0xf) << 8), hit_data);
1128 24 jeremybenn
             bfd_put_16 (input_bfd, (Rvalue) & 0xffff, hit_data + 2);
1129 225 jeremybenn
 
1130 24 jeremybenn
          }
1131 225 jeremybenn
        else if (r_type == R_CR16_GOTC_REGREL20)
1132 24 jeremybenn
          {
1133 225 jeremybenn
             asection * sgot;
1134
             sgot = bfd_get_section_by_name (dynobj, ".got");
1135
 
1136
             if (h != NULL)
1137
               {
1138
                 bfd_vma off;
1139
 
1140
                 off = h->got.offset;
1141
                 BFD_ASSERT (off != (bfd_vma) -1);
1142
 
1143
                  Rvalue >>=1; /* For code symbols.  */
1144
 
1145
                 if (! elf_hash_table (info)->dynamic_sections_created
1146
                      || SYMBOL_REFERENCES_LOCAL (info, h))
1147
                 /* This is actually a static link, or it is a
1148
                    -Bsymbolic link and the symbol is defined
1149
                     locally, or the symbol was forced to be local
1150
                     because of a version file.  We must initialize
1151
                     this entry in the global offset table.
1152
                     When doing a dynamic link, we create a .rela.got
1153
                     relocation entry to initialize the value.  This
1154
                     is done in the finish_dynamic_symbol routine.  */
1155
                  bfd_put_32 (output_bfd, Rvalue, sgot->contents + off);
1156
 
1157
                  Rvalue = sgot->output_offset + off;
1158
               }
1159
             else
1160
               {
1161
                  bfd_vma off;
1162
 
1163
                  off = elf_local_got_offsets (input_bfd)[symndx];
1164
                  Rvalue >>= 1;
1165
                  bfd_put_32 (output_bfd,Rvalue, sgot->contents + off);
1166
                  Rvalue = sgot->output_offset + off;
1167
               }
1168
 
1169
             Rvalue += addend;
1170
 
1171
             /* Check if any value in DISP.  */
1172
             Rvalue1 =((bfd_get_32 (input_bfd, hit_data) >>16)
1173
                       | (((bfd_get_32 (input_bfd, hit_data) & 0xfff) >> 8) <<16));
1174
 
1175
             /* Add or subtract the offset value.  */
1176
             if (Rvalue1 & 0x80000)
1177
               Rvalue -= (~Rvalue1 + 1) & 0xfffff;
1178
             else
1179
               Rvalue += Rvalue1;
1180
 
1181
              /* Check for range.  */
1182
             /* REVISIT: if ((long) Rvalue > 0xffffff
1183
                             || (long) Rvalue < -0x800000).  */
1184
             if ((long) Rvalue > 0xffffff || (long) Rvalue < 0)
1185
               return bfd_reloc_overflow;
1186
 
1187
             bfd_put_16 (input_bfd, (bfd_get_16 (input_bfd, hit_data))
1188
                         | (((Rvalue >> 16) & 0xf) << 8), hit_data);
1189
             bfd_put_16 (input_bfd, (Rvalue) & 0xffff, hit_data + 2);
1190
          }
1191
        else
1192
          {
1193
             if (r_type == R_CR16_ABS24)
1194
               {
1195
                  Rvalue1 = ((bfd_get_32 (input_bfd, hit_data) >> 16)
1196
                             | (((bfd_get_32 (input_bfd, hit_data) & 0xfff) >> 8) <<16)
1197
                             | (((bfd_get_32 (input_bfd, hit_data) & 0xf) <<20)));
1198
 
1199
                  /* Add or subtract the offset value.  */
1200
                  if (Rvalue1 & 0x800000)
1201
                    Rvalue -= (~Rvalue1 + 1) & 0xffffff;
1202
                  else
1203
                    Rvalue += Rvalue1;
1204
 
1205
                 /* Check for Range.  */
1206
                 if ((long) Rvalue > 0xffffff || (long) Rvalue < 0x0)
1207
                   return bfd_reloc_overflow;
1208
 
1209
                 Rvalue = ((((Rvalue >> 20) & 0xf) | (((Rvalue >> 16) & 0xf)<<8)
1210
                           | (bfd_get_32 (input_bfd, hit_data) & 0xf0f0))
1211
                           | ((Rvalue & 0xffff) << 16));
1212
               }
1213
             else if (r_type == R_CR16_DISP24)
1214
               {
1215
                  Rvalue = ((((Rvalue >> 20)& 0xf) | (((Rvalue >>16) & 0xf)<<8)
1216
                            | (bfd_get_16 (input_bfd, hit_data)))
1217
                            | (((Rvalue & 0xfffe) | ((Rvalue >> 24) & 0x1)) << 16));
1218
               }
1219
             else if ((r_type == R_CR16_IMM32) || (r_type == R_CR16_IMM32a))
1220
               {
1221
                  Rvalue1 =((((bfd_get_32 (input_bfd, hit_data)) >> 16) &0xffff)
1222
                            | (((bfd_get_32 (input_bfd, hit_data)) &0xffff)) << 16);
1223
 
1224
                 /* Add or subtract the offset value.  */
1225
                 if (Rvalue1 & 0x80000000)
1226
                   Rvalue -= (~Rvalue1 + 1) & 0xffffffff;
1227
                 else
1228
                   Rvalue += Rvalue1;
1229
 
1230
                 /* Check for range.  */
1231
                 if (Rvalue > 0xffffffff || (long) Rvalue < 0x0)
1232
                   return bfd_reloc_overflow;
1233
 
1234
                 Rvalue = (((Rvalue >> 16)& 0xffff) | (Rvalue & 0xffff) << 16);
1235
               }
1236
             else if (r_type == R_CR16_DISP24a)
1237
               {
1238
                  Rvalue = (((Rvalue & 0xfffffe) | (Rvalue >> 23)));
1239
                  Rvalue = ((Rvalue >> 16) & 0xff) | ((Rvalue & 0xffff) << 16)
1240
                            | (bfd_get_32 (input_bfd, hit_data));
1241
               }
1242
             else if ((r_type == R_CR16_REGREL20)
1243
                      || (r_type == R_CR16_REGREL20a))
1244
               {
1245
                  Rvalue1 = ((bfd_get_32 (input_bfd, hit_data) >> 16)
1246
                             | (((bfd_get_32 (input_bfd, hit_data) & 0xfff) >> 8) <<16));
1247
                  /* Add or subtract the offset value.  */
1248
                  if (Rvalue1 & 0x80000)
1249
                     Rvalue -= (~Rvalue1 + 1) & 0xfffff;
1250
                  else
1251
                     Rvalue += Rvalue1;
1252
 
1253
                  /* Check for range.  */
1254
                  if ((long) Rvalue > 0xfffff || (long) Rvalue < 0x0)
1255
                    return bfd_reloc_overflow;
1256
 
1257
                  Rvalue = (((((Rvalue >> 20)& 0xf) | (((Rvalue >>16) & 0xf)<<8)
1258
                            | ((Rvalue & 0xffff) << 16)))
1259
                            | (bfd_get_32 (input_bfd, hit_data) & 0xf0ff));
1260
 
1261 24 jeremybenn
              }
1262 225 jeremybenn
            else if (r_type == R_CR16_NUM32)
1263 24 jeremybenn
              {
1264 225 jeremybenn
                 Rvalue1 = (bfd_get_32 (input_bfd, hit_data));
1265
 
1266
                 /* Add or subtract the offset value */
1267
                 if (Rvalue1 & 0x80000000)
1268
                   Rvalue -= (~Rvalue1 + 1) & 0xffffffff;
1269
                 else
1270
                   Rvalue += Rvalue1;
1271
 
1272
                /* Check for Ranga */
1273
                if (Rvalue > 0xffffffff)
1274
                  return bfd_reloc_overflow;
1275 24 jeremybenn
              }
1276
 
1277
            bfd_put_32 (input_bfd, Rvalue, hit_data);
1278
          }
1279
        break;
1280
 
1281
      default:
1282
        return bfd_reloc_notsupported;
1283
    }
1284
 
1285
  return bfd_reloc_ok;
1286
}
1287
 
1288
/* Delete some bytes from a section while relaxing.  */
1289
 
1290
static bfd_boolean
1291
elf32_cr16_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
1292
                               asection *sec, bfd_vma addr, int count)
1293
{
1294
  Elf_Internal_Shdr *symtab_hdr;
1295
  unsigned int sec_shndx;
1296
  bfd_byte *contents;
1297
  Elf_Internal_Rela *irel, *irelend;
1298
  Elf_Internal_Rela *irelalign;
1299
  bfd_vma toaddr;
1300
  Elf_Internal_Sym *isym;
1301
  Elf_Internal_Sym *isymend;
1302
  struct elf_link_hash_entry **sym_hashes;
1303
  struct elf_link_hash_entry **end_hashes;
1304
  struct elf_link_hash_entry **start_hashes;
1305
  unsigned int symcount;
1306
 
1307
  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1308
 
1309
  contents = elf_section_data (sec)->this_hdr.contents;
1310
 
1311
  /* The deletion must stop at the next ALIGN reloc for an aligment
1312
     power larger than the number of bytes we are deleting.  */
1313
  irelalign = NULL;
1314
  toaddr = sec->size;
1315
 
1316
  irel = elf_section_data (sec)->relocs;
1317
  irelend = irel + sec->reloc_count;
1318
 
1319
  /* Actually delete the bytes.  */
1320
  memmove (contents + addr, contents + addr + count,
1321
           (size_t) (toaddr - addr - count));
1322
  sec->size -= count;
1323
 
1324
  /* Adjust all the relocs.  */
1325
  for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
1326
    /* Get the new reloc address.  */
1327
    if ((irel->r_offset > addr && irel->r_offset < toaddr))
1328
        irel->r_offset -= count;
1329
 
1330
  /* Adjust the local symbols defined in this section.  */
1331
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1332
  isym = (Elf_Internal_Sym *) symtab_hdr->contents;
1333
  for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
1334
    {
1335
      if (isym->st_shndx == sec_shndx
1336
          && isym->st_value > addr
1337
          && isym->st_value < toaddr)
1338
        {
1339
          /* Adjust the addend of SWITCH relocations in this section,
1340
             which reference this local symbol.  */
1341 225 jeremybenn
#if 0
1342 24 jeremybenn
          for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
1343
            {
1344
              unsigned long r_symndx;
1345
              Elf_Internal_Sym *rsym;
1346
              bfd_vma addsym, subsym;
1347
 
1348
              /* Skip if not a SWITCH relocation.  */
1349
              if (ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH8
1350 225 jeremybenn
                  && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH16
1351
                  && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH32)
1352
                 continue;
1353
 
1354 24 jeremybenn
              r_symndx = ELF32_R_SYM (irel->r_info);
1355
              rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx;
1356
 
1357
              /* Skip if not the local adjusted symbol.  */
1358
              if (rsym != isym)
1359
                continue;
1360
 
1361
              addsym = isym->st_value;
1362
              subsym = addsym - irel->r_addend;
1363
 
1364
              /* Fix the addend only when -->> (addsym > addr >= subsym).  */
1365
              if (subsym <= addr)
1366
                irel->r_addend -= count;
1367
              else
1368
                continue;
1369
            }
1370 225 jeremybenn
#endif
1371 24 jeremybenn
 
1372
          isym->st_value -= count;
1373
        }
1374
    }
1375
 
1376
  /* Now adjust the global symbols defined in this section.  */
1377
  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1378
               - symtab_hdr->sh_info);
1379
  sym_hashes = start_hashes = elf_sym_hashes (abfd);
1380
  end_hashes = sym_hashes + symcount;
1381
 
1382
  for (; sym_hashes < end_hashes; sym_hashes++)
1383
    {
1384
      struct elf_link_hash_entry *sym_hash = *sym_hashes;
1385
 
1386
      /* The '--wrap SYMBOL' option is causing a pain when the object file,
1387
         containing the definition of __wrap_SYMBOL, includes a direct
1388
         call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
1389
         the same symbol (which is __wrap_SYMBOL), but still exist as two
1390
         different symbols in 'sym_hashes', we don't want to adjust
1391
         the global symbol __wrap_SYMBOL twice.
1392
         This check is only relevant when symbols are being wrapped.  */
1393
      if (link_info->wrap_hash != NULL)
1394
        {
1395
          struct elf_link_hash_entry **cur_sym_hashes;
1396
 
1397
          /* Loop only over the symbols whom been already checked.  */
1398
          for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
1399
               cur_sym_hashes++)
1400
            /* If the current symbol is identical to 'sym_hash', that means
1401
               the symbol was already adjusted (or at least checked).  */
1402
            if (*cur_sym_hashes == sym_hash)
1403
              break;
1404
 
1405
          /* Don't adjust the symbol again.  */
1406
          if (cur_sym_hashes < sym_hashes)
1407
            continue;
1408
        }
1409
 
1410
      if ((sym_hash->root.type == bfd_link_hash_defined
1411
          || sym_hash->root.type == bfd_link_hash_defweak)
1412
          && sym_hash->root.u.def.section == sec
1413
          && sym_hash->root.u.def.value > addr
1414
          && sym_hash->root.u.def.value < toaddr)
1415
        sym_hash->root.u.def.value -= count;
1416
    }
1417
 
1418
  return TRUE;
1419
}
1420
 
1421
/* Relocate a CR16 ELF section.  */
1422
 
1423
static bfd_boolean
1424
elf32_cr16_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
1425 225 jeremybenn
                             bfd *input_bfd, asection *input_section,
1426
                             bfd_byte *contents, Elf_Internal_Rela *relocs,
1427
                             Elf_Internal_Sym *local_syms,
1428
                             asection **local_sections)
1429 24 jeremybenn
{
1430
  Elf_Internal_Shdr *symtab_hdr;
1431
  struct elf_link_hash_entry **sym_hashes;
1432
  Elf_Internal_Rela *rel, *relend;
1433
 
1434
  if (info->relocatable)
1435
    return TRUE;
1436
 
1437
  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
1438
  sym_hashes = elf_sym_hashes (input_bfd);
1439
 
1440
  rel = relocs;
1441
  relend = relocs + input_section->reloc_count;
1442
  for (; rel < relend; rel++)
1443
    {
1444
      int r_type;
1445
      reloc_howto_type *howto;
1446
      unsigned long r_symndx;
1447
      Elf_Internal_Sym *sym;
1448
      asection *sec;
1449
      struct elf_link_hash_entry *h;
1450
      bfd_vma relocation;
1451
      bfd_reloc_status_type r;
1452
 
1453
      r_symndx = ELF32_R_SYM (rel->r_info);
1454
      r_type = ELF32_R_TYPE (rel->r_info);
1455
      howto = cr16_elf_howto_table + (r_type);
1456
 
1457
      h = NULL;
1458
      sym = NULL;
1459
      sec = NULL;
1460
      if (r_symndx < symtab_hdr->sh_info)
1461
        {
1462
          sym = local_syms + r_symndx;
1463
          sec = local_sections[r_symndx];
1464
          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
1465
        }
1466
      else
1467
        {
1468
          bfd_boolean unresolved_reloc, warned;
1469
 
1470
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
1471
                                   r_symndx, symtab_hdr, sym_hashes,
1472
                                   h, sec, relocation,
1473
                                   unresolved_reloc, warned);
1474
        }
1475
 
1476
      r = cr16_elf_final_link_relocate (howto, input_bfd, output_bfd,
1477
                                        input_section,
1478
                                        contents, rel->r_offset,
1479
                                        relocation, rel->r_addend,
1480 225 jeremybenn
                                        (struct elf_link_hash_entry *) h,
1481
                                        r_symndx,
1482 24 jeremybenn
                                        info, sec, h == NULL);
1483
 
1484
      if (r != bfd_reloc_ok)
1485
        {
1486
          const char *name;
1487
          const char *msg = NULL;
1488
 
1489
          if (h != NULL)
1490
            name = h->root.root.string;
1491
          else
1492
            {
1493
              name = (bfd_elf_string_from_elf_section
1494
                      (input_bfd, symtab_hdr->sh_link, sym->st_name));
1495
              if (name == NULL || *name == '\0')
1496
                name = bfd_section_name (input_bfd, sec);
1497
            }
1498
 
1499
          switch (r)
1500
            {
1501
             case bfd_reloc_overflow:
1502
               if (!((*info->callbacks->reloc_overflow)
1503
                     (info, (h ? &h->root : NULL), name, howto->name,
1504
                      (bfd_vma) 0, input_bfd, input_section,
1505
                      rel->r_offset)))
1506
                 return FALSE;
1507
               break;
1508
 
1509
             case bfd_reloc_undefined:
1510
               if (!((*info->callbacks->undefined_symbol)
1511
                     (info, name, input_bfd, input_section,
1512
                      rel->r_offset, TRUE)))
1513
                 return FALSE;
1514
               break;
1515
 
1516
             case bfd_reloc_outofrange:
1517
               msg = _("internal error: out of range error");
1518
               goto common_error;
1519
 
1520
             case bfd_reloc_notsupported:
1521
               msg = _("internal error: unsupported relocation error");
1522
               goto common_error;
1523
 
1524
             case bfd_reloc_dangerous:
1525
               msg = _("internal error: dangerous error");
1526
               goto common_error;
1527
 
1528
             default:
1529
               msg = _("internal error: unknown error");
1530
               /* Fall through.  */
1531
 
1532
             common_error:
1533
               if (!((*info->callbacks->warning)
1534
                     (info, msg, name, input_bfd, input_section,
1535
                      rel->r_offset)))
1536
                 return FALSE;
1537
               break;
1538
            }
1539
        }
1540
    }
1541
 
1542
  return TRUE;
1543
}
1544
 
1545
/* This is a version of bfd_generic_get_relocated_section_contents
1546
   which uses elf32_cr16_relocate_section.  */
1547
 
1548
static bfd_byte *
1549
elf32_cr16_get_relocated_section_contents (bfd *output_bfd,
1550
                                           struct bfd_link_info *link_info,
1551
                                           struct bfd_link_order *link_order,
1552
                                           bfd_byte *data,
1553
                                           bfd_boolean relocatable,
1554
                                           asymbol **symbols)
1555
{
1556
  Elf_Internal_Shdr *symtab_hdr;
1557
  asection *input_section = link_order->u.indirect.section;
1558
  bfd *input_bfd = input_section->owner;
1559
  asection **sections = NULL;
1560
  Elf_Internal_Rela *internal_relocs = NULL;
1561
  Elf_Internal_Sym *isymbuf = NULL;
1562
 
1563
  /* We only need to handle the case of relaxing, or of having a
1564
     particular set of section contents, specially.  */
1565
  if (relocatable
1566
      || elf_section_data (input_section)->this_hdr.contents == NULL)
1567
    return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
1568
                                                       link_order, data,
1569
                                                       relocatable,
1570
                                                       symbols);
1571
 
1572
  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
1573
 
1574
  memcpy (data, elf_section_data (input_section)->this_hdr.contents,
1575
          (size_t) input_section->size);
1576
 
1577
  if ((input_section->flags & SEC_RELOC) != 0
1578
      && input_section->reloc_count > 0)
1579
    {
1580
      Elf_Internal_Sym *isym;
1581
      Elf_Internal_Sym *isymend;
1582
      asection **secpp;
1583
      bfd_size_type amt;
1584
 
1585
      internal_relocs = _bfd_elf_link_read_relocs (input_bfd, input_section,
1586
                                                   NULL, NULL, FALSE);
1587
      if (internal_relocs == NULL)
1588
        goto error_return;
1589
 
1590
      if (symtab_hdr->sh_info != 0)
1591
        {
1592
          isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1593
          if (isymbuf == NULL)
1594
            isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
1595
                                            symtab_hdr->sh_info, 0,
1596
                                            NULL, NULL, NULL);
1597
          if (isymbuf == NULL)
1598
            goto error_return;
1599
        }
1600
 
1601
      amt = symtab_hdr->sh_info;
1602
      amt *= sizeof (asection *);
1603
      sections = bfd_malloc (amt);
1604
      if (sections == NULL && amt != 0)
1605
        goto error_return;
1606
 
1607
      isymend = isymbuf + symtab_hdr->sh_info;
1608
      for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
1609
        {
1610
          asection *isec;
1611
 
1612
          if (isym->st_shndx == SHN_UNDEF)
1613
            isec = bfd_und_section_ptr;
1614
          else if (isym->st_shndx == SHN_ABS)
1615
            isec = bfd_abs_section_ptr;
1616
          else if (isym->st_shndx == SHN_COMMON)
1617
            isec = bfd_com_section_ptr;
1618
          else
1619
            isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
1620
 
1621
          *secpp = isec;
1622
        }
1623
 
1624
      if (! elf32_cr16_relocate_section (output_bfd, link_info, input_bfd,
1625
                                     input_section, data, internal_relocs,
1626
                                     isymbuf, sections))
1627
        goto error_return;
1628
 
1629
      if (sections != NULL)
1630
        free (sections);
1631
      if (isymbuf != NULL
1632
          && symtab_hdr->contents != (unsigned char *) isymbuf)
1633
        free (isymbuf);
1634
      if (elf_section_data (input_section)->relocs != internal_relocs)
1635
        free (internal_relocs);
1636
    }
1637
 
1638
  return data;
1639
 
1640
 error_return:
1641
  if (sections != NULL)
1642
    free (sections);
1643
  if (isymbuf != NULL
1644
      && symtab_hdr->contents != (unsigned char *) isymbuf)
1645
    free (isymbuf);
1646
  if (internal_relocs != NULL
1647
      && elf_section_data (input_section)->relocs != internal_relocs)
1648
    free (internal_relocs);
1649
  return NULL;
1650
}
1651
 
1652 225 jeremybenn
/* Assorted hash table functions.  */
1653
 
1654
/* Initialize an entry in the link hash table.  */
1655
 
1656
/* Create an entry in an CR16 ELF linker hash table.  */
1657
 
1658
static struct bfd_hash_entry *
1659
elf32_cr16_link_hash_newfunc (struct bfd_hash_entry *entry,
1660
                              struct bfd_hash_table *table,
1661
                              const char *string)
1662
{
1663
  struct elf32_cr16_link_hash_entry *ret =
1664
    (struct elf32_cr16_link_hash_entry *) entry;
1665
 
1666
  /* Allocate the structure if it has not already been allocated by a
1667
     subclass.  */
1668
  if (ret == (struct elf32_cr16_link_hash_entry *) NULL)
1669
    ret = ((struct elf32_cr16_link_hash_entry *)
1670
           bfd_hash_allocate (table,
1671
                              sizeof (struct elf32_cr16_link_hash_entry)));
1672
  if (ret == (struct elf32_cr16_link_hash_entry *) NULL)
1673
    return (struct bfd_hash_entry *) ret;
1674
 
1675
  /* Call the allocation method of the superclass.  */
1676
  ret = ((struct elf32_cr16_link_hash_entry *)
1677
         _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
1678
                                     table, string));
1679
  if (ret != (struct elf32_cr16_link_hash_entry *) NULL)
1680
    {
1681
      ret->direct_calls = 0;
1682
      ret->stack_size = 0;
1683
      ret->movm_args = 0;
1684
      ret->movm_stack_size = 0;
1685
      ret->flags = 0;
1686
      ret->value = 0;
1687
    }
1688
 
1689
  return (struct bfd_hash_entry *) ret;
1690
}
1691
 
1692
/* Create an cr16 ELF linker hash table.  */
1693
 
1694
static struct bfd_link_hash_table *
1695
elf32_cr16_link_hash_table_create (bfd *abfd)
1696
{
1697
  struct elf32_cr16_link_hash_table *ret;
1698
  bfd_size_type amt = sizeof (struct elf32_cr16_link_hash_table);
1699
 
1700
  ret = (struct elf32_cr16_link_hash_table *) bfd_malloc (amt);
1701
  if (ret == (struct elf32_cr16_link_hash_table *) NULL)
1702
    return NULL;
1703
 
1704
  if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
1705
                                      elf32_cr16_link_hash_newfunc,
1706
                                      sizeof (struct elf32_cr16_link_hash_entry)))
1707
    {
1708
      free (ret);
1709
      return NULL;
1710
    }
1711
 
1712
  ret->flags = 0;
1713
  amt = sizeof (struct elf_link_hash_table);
1714
  ret->static_hash_table
1715
    = (struct elf32_cr16_link_hash_table *) bfd_malloc (amt);
1716
  if (ret->static_hash_table == NULL)
1717
    {
1718
      free (ret);
1719
      return NULL;
1720
    }
1721
 
1722
  if (!_bfd_elf_link_hash_table_init (&ret->static_hash_table->root, abfd,
1723
                                      elf32_cr16_link_hash_newfunc,
1724
                                      sizeof (struct elf32_cr16_link_hash_entry)))
1725
    {
1726
      free (ret->static_hash_table);
1727
      free (ret);
1728
      return NULL;
1729
    }
1730
  return &ret->root.root;
1731
}
1732
 
1733
/* Free an cr16 ELF linker hash table.  */
1734
 
1735
static void
1736
elf32_cr16_link_hash_table_free (struct bfd_link_hash_table *hash)
1737
{
1738
  struct elf32_cr16_link_hash_table *ret
1739
    = (struct elf32_cr16_link_hash_table *) hash;
1740
 
1741
  _bfd_generic_link_hash_table_free
1742
    ((struct bfd_link_hash_table *) ret->static_hash_table);
1743
  _bfd_generic_link_hash_table_free
1744
    ((struct bfd_link_hash_table *) ret);
1745
}
1746
 
1747
static unsigned long
1748
elf_cr16_mach (flagword flags)
1749
{
1750
  switch (flags)
1751
    {
1752
      case EM_CR16:
1753
      default:
1754
      return bfd_mach_cr16;
1755
    }
1756
}
1757
 
1758
/* The final processing done just before writing out a CR16 ELF object
1759
   file.  This gets the CR16 architecture right based on the machine
1760
   number.  */
1761
 
1762
static void
1763
_bfd_cr16_elf_final_write_processing (bfd *abfd,
1764
                                      bfd_boolean linker ATTRIBUTE_UNUSED)
1765
{
1766
  unsigned long val;
1767
  switch (bfd_get_mach (abfd))
1768
    {
1769
     default:
1770
     case bfd_mach_cr16:
1771
        val = EM_CR16;
1772
        break;
1773
    }
1774
 
1775
 
1776
 elf_elfheader (abfd)->e_flags |= val;
1777
}
1778
 
1779
 
1780
static bfd_boolean
1781
_bfd_cr16_elf_object_p (bfd *abfd)
1782
{
1783
  bfd_default_set_arch_mach (abfd, bfd_arch_cr16,
1784
                             elf_cr16_mach (elf_elfheader (abfd)->e_flags));
1785
  return TRUE;
1786
}
1787
 
1788
/* Merge backend specific data from an object file to the output
1789
   object file when linking.  */
1790
 
1791
static bfd_boolean
1792
_bfd_cr16_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
1793
{
1794
  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1795
      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1796
    return TRUE;
1797
 
1798
  if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
1799
      && bfd_get_mach (obfd) < bfd_get_mach (ibfd))
1800
    {
1801
      if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
1802
                               bfd_get_mach (ibfd)))
1803
         return FALSE;
1804
     }
1805
 
1806
  return TRUE;
1807
}
1808
 
1809
 
1810 24 jeremybenn
/* This function handles relaxing for the CR16.
1811
 
1812
   There's quite a few relaxing opportunites available on the CR16:
1813
 
1814 225 jeremybenn
        * bcond:24 -> bcond:16                                1 byte
1815
        * bcond:16 -> bcond:8                                 1 byte
1816
        * arithmetic imm32 -> arithmetic imm20                12 bits
1817
        * arithmetic imm20/imm16 -> arithmetic imm4           12/16 bits
1818 24 jeremybenn
 
1819
   Symbol- and reloc-reading infrastructure copied from elf-m10200.c.  */
1820
 
1821
static bfd_boolean
1822
elf32_cr16_relax_section (bfd *abfd, asection *sec,
1823 225 jeremybenn
                          struct bfd_link_info *link_info, bfd_boolean *again)
1824 24 jeremybenn
{
1825
  Elf_Internal_Shdr *symtab_hdr;
1826
  Elf_Internal_Rela *internal_relocs;
1827
  Elf_Internal_Rela *irel, *irelend;
1828
  bfd_byte *contents = NULL;
1829
  Elf_Internal_Sym *isymbuf = NULL;
1830
 
1831
  /* Assume nothing changes.  */
1832
  *again = FALSE;
1833
 
1834
  /* We don't have to do anything for a relocatable link, if
1835
     this section does not have relocs, or if this is not a
1836
     code section.  */
1837
  if (link_info->relocatable
1838
      || (sec->flags & SEC_RELOC) == 0
1839
      || sec->reloc_count == 0
1840
      || (sec->flags & SEC_CODE) == 0)
1841
    return TRUE;
1842
 
1843
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1844
 
1845
  /* Get a copy of the native relocations.  */
1846
  internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
1847
                                               link_info->keep_memory);
1848
  if (internal_relocs == NULL)
1849
    goto error_return;
1850
 
1851
  /* Walk through them looking for relaxing opportunities.  */
1852
  irelend = internal_relocs + sec->reloc_count;
1853
  for (irel = internal_relocs; irel < irelend; irel++)
1854
    {
1855
      bfd_vma symval;
1856
 
1857
      /* If this isn't something that can be relaxed, then ignore
1858
         this reloc.  */
1859
      if (ELF32_R_TYPE (irel->r_info) != (int) R_CR16_DISP16
1860
          && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_DISP24
1861
          && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_IMM32
1862
          && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_IMM20
1863
          && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_IMM16)
1864
        continue;
1865
 
1866
      /* Get the section contents if we haven't done so already.  */
1867
      if (contents == NULL)
1868
        {
1869
          /* Get cached copy if it exists.  */
1870
          if (elf_section_data (sec)->this_hdr.contents != NULL)
1871
            contents = elf_section_data (sec)->this_hdr.contents;
1872
          /* Go get them off disk.  */
1873
          else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
1874
            goto error_return;
1875
        }
1876
 
1877
      /* Read this BFD's local symbols if we haven't done so already.  */
1878
      if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1879
        {
1880
          isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1881
          if (isymbuf == NULL)
1882
            isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1883
                                            symtab_hdr->sh_info, 0,
1884
                                            NULL, NULL, NULL);
1885
          if (isymbuf == NULL)
1886
            goto error_return;
1887
        }
1888
 
1889
      /* Get the value of the symbol referred to by the reloc.  */
1890
      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1891
        {
1892
          /* A local symbol.  */
1893
          Elf_Internal_Sym *isym;
1894
          asection *sym_sec;
1895
 
1896
          isym = isymbuf + ELF32_R_SYM (irel->r_info);
1897
          if (isym->st_shndx == SHN_UNDEF)
1898
            sym_sec = bfd_und_section_ptr;
1899
          else if (isym->st_shndx == SHN_ABS)
1900
            sym_sec = bfd_abs_section_ptr;
1901
          else if (isym->st_shndx == SHN_COMMON)
1902
            sym_sec = bfd_com_section_ptr;
1903
          else
1904
            sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1905
          symval = (isym->st_value
1906
                    + sym_sec->output_section->vma
1907
                    + sym_sec->output_offset);
1908
        }
1909
      else
1910
        {
1911
          unsigned long indx;
1912
          struct elf_link_hash_entry *h;
1913
 
1914
          /* An external symbol.  */
1915
          indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1916
          h = elf_sym_hashes (abfd)[indx];
1917
          BFD_ASSERT (h != NULL);
1918
 
1919
          if (h->root.type != bfd_link_hash_defined
1920
              && h->root.type != bfd_link_hash_defweak)
1921
            /* This appears to be a reference to an undefined
1922
               symbol.  Just ignore it--it will be caught by the
1923
               regular reloc processing.  */
1924
            continue;
1925
 
1926
          symval = (h->root.u.def.value
1927
                    + h->root.u.def.section->output_section->vma
1928
                    + h->root.u.def.section->output_offset);
1929
        }
1930
 
1931
      /* For simplicity of coding, we are going to modify the section
1932
         contents, the section relocs, and the BFD symbol table.  We
1933
         must tell the rest of the code not to free up this
1934
         information.  It would be possible to instead create a table
1935
         of changes which have to be made, as is done in coff-mips.c;
1936
         that would be more work, but would require less memory when
1937
         the linker is run.  */
1938
 
1939
      /* Try to turn a 24  branch/call into a 16bit relative
1940
         branch/call.  */
1941
      if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_DISP24)
1942
        {
1943
          bfd_vma value = symval;
1944
 
1945
          /* Deal with pc-relative gunk.  */
1946
          value -= (sec->output_section->vma + sec->output_offset);
1947
          value -= irel->r_offset;
1948
          value += irel->r_addend;
1949
 
1950
          /* See if the value will fit in 16 bits, note the high value is
1951
             0xfffe + 2 as the target will be two bytes closer if we are
1952
             able to relax.  */
1953
          if ((long) value < 0x10000 && (long) value > -0x10002)
1954
            {
1955
              unsigned int code;
1956
 
1957
              /* Get the opcode.  */
1958
              code = (unsigned int) bfd_get_32 (abfd, contents + irel->r_offset);
1959
 
1960
              /* Verify it's a 'bcond' and fix the opcode.  */
1961
              if ((code  & 0xffff) == 0x0010)
1962 225 jeremybenn
                bfd_put_16 (abfd, 0x1800 | ((0xf & (code >> 20)) << 4), contents + irel->r_offset);
1963 24 jeremybenn
              else
1964
                continue;
1965
 
1966
              /* Note that we've changed the relocs, section contents, etc.  */
1967
              elf_section_data (sec)->relocs = internal_relocs;
1968
              elf_section_data (sec)->this_hdr.contents = contents;
1969
              symtab_hdr->contents = (unsigned char *) isymbuf;
1970
 
1971
              /* Fix the relocation's type.  */
1972
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1973
                                           R_CR16_DISP16);
1974
 
1975
              /* Delete two bytes of data.  */
1976
              if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1977
                                                   irel->r_offset + 2, 2))
1978
                goto error_return;
1979
 
1980
              /* That will change things, so, we should relax again.
1981
                 Note that this is not required, and it may be slow.  */
1982
              *again = TRUE;
1983
            }
1984
        }
1985
 
1986 225 jeremybenn
      /* Try to turn a 16bit pc-relative branch into an
1987
         8bit pc-relative branch.  */
1988 24 jeremybenn
      if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_DISP16)
1989
        {
1990
          bfd_vma value = symval;
1991
 
1992
          /* Deal with pc-relative gunk.  */
1993
          value -= (sec->output_section->vma + sec->output_offset);
1994
          value -= irel->r_offset;
1995
          value += irel->r_addend;
1996
 
1997
          /* See if the value will fit in 8 bits, note the high value is
1998
             0xfc + 2 as the target will be two bytes closer if we are
1999
             able to relax.  */
2000 225 jeremybenn
          /*if ((long) value < 0x1fa && (long) value > -0x100) REVISIT:range */
2001
          if ((long) value < 0xfa && (long) value > -0x100)
2002 24 jeremybenn
            {
2003
              unsigned short code;
2004
 
2005
              /* Get the opcode.  */
2006
              code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
2007
 
2008 225 jeremybenn
              /* Verify it's a 'bcond' and fix the opcode.  */
2009
              if ((code & 0xff0f) == 0x1800)
2010
                bfd_put_16 (abfd, (code & 0xf0f0), contents + irel->r_offset);
2011 24 jeremybenn
              else
2012
                continue;
2013
 
2014
              /* Note that we've changed the relocs, section contents, etc.  */
2015
              elf_section_data (sec)->relocs = internal_relocs;
2016
              elf_section_data (sec)->this_hdr.contents = contents;
2017
              symtab_hdr->contents = (unsigned char *) isymbuf;
2018
 
2019
              /* Fix the relocation's type.  */
2020
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
2021
                                           R_CR16_DISP8);
2022
 
2023
              /* Delete two bytes of data.  */
2024
              if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
2025
                                                   irel->r_offset + 2, 2))
2026
                goto error_return;
2027
 
2028
              /* That will change things, so, we should relax again.
2029
                 Note that this is not required, and it may be slow.  */
2030
              *again = TRUE;
2031
            }
2032
        }
2033
 
2034 225 jeremybenn
      /* Try to turn a 32-bit IMM address into a 20/16-bit IMM address */
2035 24 jeremybenn
      if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM32)
2036
        {
2037
          bfd_vma value = symval;
2038
          unsigned short is_add_mov = 0;
2039 225 jeremybenn
          bfd_vma value1 = 0;
2040
 
2041
          /* Get the existing value from the mcode */
2042
          value1 = ((bfd_get_32 (abfd, contents + irel->r_offset + 2) >> 16)
2043
                   |(((bfd_get_32 (abfd, contents + irel->r_offset + 2) & 0xffff) << 16)));
2044 24 jeremybenn
 
2045
          /* See if the value will fit in 20 bits.  */
2046 225 jeremybenn
          if ((long) (value + value1) < 0xfffff && (long) (value + value1) > 0)
2047 24 jeremybenn
            {
2048
              unsigned short code;
2049
 
2050
              /* Get the opcode.  */
2051
              code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
2052
 
2053 225 jeremybenn
              /* Verify it's a 'arithmetic ADDD or MOVD instruction'.
2054 24 jeremybenn
                 For ADDD and MOVD only, convert to IMM32 -> IMM20.  */
2055 225 jeremybenn
 
2056 24 jeremybenn
              if (((code & 0xfff0) == 0x0070) || ((code & 0xfff0) == 0x0020))
2057 225 jeremybenn
                 is_add_mov = 1;
2058 24 jeremybenn
 
2059
              if (is_add_mov)
2060
                {
2061 225 jeremybenn
                  /* Note that we've changed the relocs, section contents,
2062 24 jeremybenn
                     etc.  */
2063
                  elf_section_data (sec)->relocs = internal_relocs;
2064
                  elf_section_data (sec)->this_hdr.contents = contents;
2065
                  symtab_hdr->contents = (unsigned char *) isymbuf;
2066
 
2067
                  /* Fix the opcode.  */
2068
                  if ((code & 0xfff0) == 0x0070) /* For movd.  */
2069
                    bfd_put_8 (abfd, 0x05, contents + irel->r_offset + 1);
2070 225 jeremybenn
                  else                           /* code == 0x0020 for addd.  */
2071 24 jeremybenn
                    bfd_put_8 (abfd, 0x04, contents + irel->r_offset + 1);
2072 225 jeremybenn
 
2073 24 jeremybenn
                  bfd_put_8 (abfd, (code & 0xf) << 4, contents + irel->r_offset);
2074
 
2075 225 jeremybenn
                  /* If existing value is nagavive adjust approriately
2076
                     place the 16-20bits (ie 4 bit) in new opcode,
2077
                     as the 0xffffxxxx, the higher 2 byte values removed. */
2078
                  if (value1 & 0x80000000)
2079
                    bfd_put_8 (abfd, (0x0f | (bfd_get_8(abfd, contents + irel->r_offset))), contents + irel->r_offset);
2080
                  else
2081
                    bfd_put_8 (abfd, (((value1 >> 16)&0xf) | (bfd_get_8(abfd, contents + irel->r_offset))), contents + irel->r_offset);
2082 24 jeremybenn
 
2083
                  /* Fix the relocation's type.  */
2084
                  irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
2085 225 jeremybenn
                                               R_CR16_IMM20);
2086
 
2087 24 jeremybenn
                  /* Delete two bytes of data.  */
2088
                  if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
2089 225 jeremybenn
                                                      irel->r_offset + 2, 2))
2090 24 jeremybenn
                    goto error_return;
2091
 
2092
                  /* That will change things, so, we should relax again.
2093
                     Note that this is not required, and it may be slow.  */
2094
                  *again = TRUE;
2095
                }
2096
            }
2097 225 jeremybenn
 
2098
          /* See if the value will fit in 16 bits.  */
2099
          if ((!is_add_mov)
2100
              && ((long)(value + value1) < 0x7fff && (long)(value + value1) > 0))
2101 24 jeremybenn
            {
2102
              unsigned short code;
2103
 
2104
              /* Get the opcode.  */
2105
              code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
2106
 
2107
              /* Note that we've changed the relocs, section contents, etc.  */
2108
              elf_section_data (sec)->relocs = internal_relocs;
2109
              elf_section_data (sec)->this_hdr.contents = contents;
2110
              symtab_hdr->contents = (unsigned char *) isymbuf;
2111
 
2112
              /* Fix the opcode.  */
2113
              if ((code & 0xf0) == 0x70)          /* For movd.  */
2114
                bfd_put_8 (abfd, 0x54, contents + irel->r_offset + 1);
2115
              else if ((code & 0xf0) == 0x20)     /* For addd.  */
2116
                bfd_put_8 (abfd, 0x60, contents + irel->r_offset + 1);
2117
              else if ((code & 0xf0) == 0x90)     /* For cmpd.  */
2118
                bfd_put_8 (abfd, 0x56, contents + irel->r_offset + 1);
2119
              else
2120
                continue;
2121
 
2122
              bfd_put_8 (abfd, 0xb0 | (code & 0xf), contents + irel->r_offset);
2123
 
2124 225 jeremybenn
              /* If existing value is nagavive adjust approriately
2125
                 place the 12-16bits (ie 4 bit) in new opcode,
2126
                 as the 0xfffffxxx, the higher 2 byte values removed. */
2127
              if (value1 & 0x80000000)
2128
                bfd_put_8 (abfd, (0x0f | (bfd_get_8(abfd, contents + irel->r_offset))), contents + irel->r_offset);
2129
              else
2130
                bfd_put_16 (abfd, value1, contents + irel->r_offset + 2);
2131
 
2132
 
2133 24 jeremybenn
              /* Fix the relocation's type.  */
2134
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
2135
                                           R_CR16_IMM16);
2136
 
2137
              /* Delete two bytes of data.  */
2138
              if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
2139
                                                  irel->r_offset + 2, 2))
2140 225 jeremybenn
                goto error_return;
2141 24 jeremybenn
 
2142
              /* That will change things, so, we should relax again.
2143
                 Note that this is not required, and it may be slow.  */
2144 225 jeremybenn
              *again = TRUE;
2145 24 jeremybenn
            }
2146
        }
2147
 
2148 225 jeremybenn
#if 0
2149
      /* Try to turn a 16bit immediate address into a 4bit
2150
         immediate address.  */
2151
      if ((ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM20)
2152 24 jeremybenn
          || (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM16))
2153
        {
2154
          bfd_vma value = symval;
2155 225 jeremybenn
          bfd_vma value1 = 0;
2156 24 jeremybenn
 
2157 225 jeremybenn
          /* Get the existing value from the mcode */
2158
          value1 = ((bfd_get_16 (abfd, contents + irel->r_offset + 2) & 0xffff));
2159
 
2160
          if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM20)
2161
            {
2162
              value1 |= ((bfd_get_16 (abfd, contents + irel->r_offset + 1) & 0xf000) << 0x4);
2163
            }
2164
 
2165 24 jeremybenn
          /* See if the value will fit in 4 bits.  */
2166 225 jeremybenn
          if ((((long) (value + value1)) < 0xf)
2167
              && (((long) (value + value1)) > 0))
2168 24 jeremybenn
            {
2169
              unsigned short code;
2170
 
2171
              /* Get the opcode.  */
2172
              code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
2173
 
2174
              /* Note that we've changed the relocs, section contents, etc.  */
2175
              elf_section_data (sec)->relocs = internal_relocs;
2176
              elf_section_data (sec)->this_hdr.contents = contents;
2177
              symtab_hdr->contents = (unsigned char *) isymbuf;
2178
 
2179
              /* Fix the opcode.  */
2180
              if (((code & 0x0f00) == 0x0400) || ((code & 0x0f00) == 0x0500))
2181
                {
2182
                  if ((code & 0x0f00) == 0x0400)      /* For movd imm20.  */
2183
                    bfd_put_8 (abfd, 0x60, contents + irel->r_offset);
2184
                  else                                /* For addd imm20.  */
2185
                    bfd_put_8 (abfd, 0x54, contents + irel->r_offset);
2186
                  bfd_put_8 (abfd, (code & 0xf0) >> 4, contents + irel->r_offset + 1);
2187
                }
2188
              else
2189
                {
2190
                  if ((code & 0xfff0) == 0x56b0)       /*  For cmpd imm16.  */
2191
                    bfd_put_8 (abfd, 0x56, contents + irel->r_offset);
2192
                  else if ((code & 0xfff0) == 0x54b0)  /*  For movd imm16.  */
2193
                    bfd_put_8 (abfd, 0x54, contents + irel->r_offset);
2194
                  else if ((code & 0xfff0) == 0x58b0)  /*  For movb imm16.  */
2195
                    bfd_put_8 (abfd, 0x58, contents + irel->r_offset);
2196
                  else if ((code & 0xfff0) == 0x5Ab0)  /*  For movw imm16.  */
2197
                    bfd_put_8 (abfd, 0x5A, contents + irel->r_offset);
2198
                  else if ((code & 0xfff0) == 0x60b0)  /*  For addd imm16.  */
2199
                    bfd_put_8 (abfd, 0x60, contents + irel->r_offset);
2200
                  else if ((code & 0xfff0) == 0x30b0)  /*  For addb imm16.  */
2201
                    bfd_put_8 (abfd, 0x30, contents + irel->r_offset);
2202
                  else if ((code & 0xfff0) == 0x2Cb0)  /*  For addub imm16.  */
2203
                    bfd_put_8 (abfd, 0x2C, contents + irel->r_offset);
2204
                  else if ((code & 0xfff0) == 0x32b0)  /*  For adduw imm16.  */
2205
                    bfd_put_8 (abfd, 0x32, contents + irel->r_offset);
2206
                  else if ((code & 0xfff0) == 0x38b0)  /*  For subb imm16.  */
2207
                    bfd_put_8 (abfd, 0x38, contents + irel->r_offset);
2208 225 jeremybenn
                  else if ((code & 0xfff0) == 0x3Cb0)  /*  For subcb imm16.  */
2209
                    bfd_put_8 (abfd, 0x3C, contents + irel->r_offset);
2210
                  else if ((code & 0xfff0) == 0x3Fb0)  /*  For subcw imm16.  */
2211
                    bfd_put_8 (abfd, 0x3F, contents + irel->r_offset);
2212 24 jeremybenn
                  else if ((code & 0xfff0) == 0x3Ab0)  /*  For subw imm16.  */
2213
                    bfd_put_8 (abfd, 0x3A, contents + irel->r_offset);
2214
                  else if ((code & 0xfff0) == 0x50b0)  /*  For cmpb imm16.  */
2215
                    bfd_put_8 (abfd, 0x50, contents + irel->r_offset);
2216
                  else if ((code & 0xfff0) == 0x52b0)  /*  For cmpw imm16.  */
2217
                    bfd_put_8 (abfd, 0x52, contents + irel->r_offset);
2218
                  else
2219
                    continue;
2220 225 jeremybenn
 
2221 24 jeremybenn
                  bfd_put_8 (abfd, (code & 0xf), contents + irel->r_offset + 1);
2222
                }
2223
 
2224
              /* Fix the relocation's type.  */
2225
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
2226
                                           R_CR16_IMM4);
2227
 
2228
              /* Delete two bytes of data.  */
2229
              if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
2230 225 jeremybenn
                                                  irel->r_offset + 2, 2))
2231 24 jeremybenn
                goto error_return;
2232
 
2233
              /* That will change things, so, we should relax again.
2234
                 Note that this is not required, and it may be slow.  */
2235
              *again = TRUE;
2236
            }
2237
        }
2238 225 jeremybenn
#endif
2239 24 jeremybenn
    }
2240
 
2241
  if (isymbuf != NULL
2242
      && symtab_hdr->contents != (unsigned char *) isymbuf)
2243
    {
2244
      if (! link_info->keep_memory)
2245
        free (isymbuf);
2246
      else
2247 225 jeremybenn
       /* Cache the symbols for elf_link_input_bfd.  */
2248
       symtab_hdr->contents = (unsigned char *) isymbuf;
2249 24 jeremybenn
    }
2250
 
2251
  if (contents != NULL
2252
      && elf_section_data (sec)->this_hdr.contents != contents)
2253
    {
2254
      if (! link_info->keep_memory)
2255
        free (contents);
2256
      else
2257 225 jeremybenn
       /* Cache the section contents for elf_link_input_bfd.  */
2258
       elf_section_data (sec)->this_hdr.contents = contents;
2259
 
2260 24 jeremybenn
    }
2261
 
2262
  if (internal_relocs != NULL
2263
      && elf_section_data (sec)->relocs != internal_relocs)
2264
    free (internal_relocs);
2265
 
2266
  return TRUE;
2267
 
2268
 error_return:
2269
  if (isymbuf != NULL
2270
      && symtab_hdr->contents != (unsigned char *) isymbuf)
2271
    free (isymbuf);
2272
  if (contents != NULL
2273
      && elf_section_data (sec)->this_hdr.contents != contents)
2274
    free (contents);
2275
  if (internal_relocs != NULL
2276
      && elf_section_data (sec)->relocs != internal_relocs)
2277
    free (internal_relocs);
2278
 
2279
  return FALSE;
2280
}
2281
 
2282
static asection *
2283
elf32_cr16_gc_mark_hook (asection *sec,
2284 225 jeremybenn
                         struct bfd_link_info *info ATTRIBUTE_UNUSED,
2285
                         Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
2286
                         struct elf_link_hash_entry *h,
2287
                         Elf_Internal_Sym *sym)
2288 24 jeremybenn
{
2289
  if (h == NULL)
2290
    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
2291
 
2292
  switch (h->root.type)
2293
    {
2294
      case bfd_link_hash_defined:
2295
      case bfd_link_hash_defweak:
2296
        return h->root.u.def.section;
2297
 
2298
      case bfd_link_hash_common:
2299
        return h->root.u.c.p->section;
2300
 
2301
      default:
2302
        return NULL;
2303
    }
2304
}
2305
 
2306
/* Update the got entry reference counts for the section being removed.  */
2307
 
2308
static bfd_boolean
2309
elf32_cr16_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
2310 225 jeremybenn
                          struct bfd_link_info *info ATTRIBUTE_UNUSED,
2311
                          asection *sec ATTRIBUTE_UNUSED,
2312
                          const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
2313 24 jeremybenn
{
2314
  /* We don't support garbage collection of GOT and PLT relocs yet.  */
2315
  return TRUE;
2316
}
2317
 
2318 225 jeremybenn
/* Create dynamic sections when linking against a dynamic object.  */
2319
 
2320
static bfd_boolean
2321
_bfd_cr16_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
2322
{
2323
  flagword   flags;
2324
  asection * s;
2325
  const struct elf_backend_data * bed = get_elf_backend_data (abfd);
2326
  int ptralign = 0;
2327
 
2328
  switch (bed->s->arch_size)
2329
    {
2330
    case 16:
2331
      ptralign = 1;
2332
      break;
2333
 
2334
    case 32:
2335
      ptralign = 2;
2336
      break;
2337
 
2338
    default:
2339
      bfd_set_error (bfd_error_bad_value);
2340
      return FALSE;
2341
    }
2342
 
2343
  /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
2344
     .rel[a].bss sections.  */
2345
 
2346
  flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
2347
           | SEC_LINKER_CREATED);
2348
 
2349
  s = bfd_make_section_with_flags (abfd,
2350
                                   (bed->default_use_rela_p
2351
                                    ? ".rela.plt" : ".rel.plt"),
2352
                                   flags | SEC_READONLY);
2353
  if (s == NULL
2354
      || ! bfd_set_section_alignment (abfd, s, ptralign))
2355
    return FALSE;
2356
 
2357
  if (! _bfd_cr16_elf_create_got_section (abfd, info))
2358
    return FALSE;
2359
 
2360
  {
2361
    const char * secname;
2362
    char *       relname;
2363
    flagword     secflags;
2364
    asection *   sec;
2365
 
2366
    for (sec = abfd->sections; sec; sec = sec->next)
2367
      {
2368
        secflags = bfd_get_section_flags (abfd, sec);
2369
        if ((secflags & (SEC_DATA | SEC_LINKER_CREATED))
2370
            || ((secflags & SEC_HAS_CONTENTS) != SEC_HAS_CONTENTS))
2371
          continue;
2372
 
2373
        secname = bfd_get_section_name (abfd, sec);
2374
        relname = (char *) bfd_malloc (strlen (secname) + 6);
2375
        strcpy (relname, ".rela");
2376
        strcat (relname, secname);
2377
 
2378
        s = bfd_make_section_with_flags (abfd, relname,
2379
                                         flags | SEC_READONLY);
2380
        if (s == NULL
2381
            || ! bfd_set_section_alignment (abfd, s, ptralign))
2382
          return FALSE;
2383
      }
2384
  }
2385
 
2386
  if (bed->want_dynbss)
2387
    {
2388
      /* The .dynbss section is a place to put symbols which are defined
2389
         by dynamic objects, are referenced by regular objects, and are
2390
         not functions.  We must allocate space for them in the process
2391
         image and use a R_*_COPY reloc to tell the dynamic linker to
2392
         initialize them at run time.  The linker script puts the .dynbss
2393
         section into the .bss section of the final image.  */
2394
      s = bfd_make_section_with_flags (abfd, ".dynbss",
2395
                                       SEC_ALLOC | SEC_LINKER_CREATED);
2396
      if (s == NULL)
2397
        return FALSE;
2398
 
2399
      /* The .rel[a].bss section holds copy relocs.  This section is not
2400
         normally needed.  We need to create it here, though, so that the
2401
         linker will map it to an output section.  We can't just create it
2402
         only if we need it, because we will not know whether we need it
2403
         until we have seen all the input files, and the first time the
2404
         main linker code calls BFD after examining all the input files
2405
         (size_dynamic_sections) the input sections have already been
2406
         mapped to the output sections.  If the section turns out not to
2407
         be needed, we can discard it later.  We will never need this
2408
         section when generating a shared object, since they do not use
2409
         copy relocs.  */
2410
      if (! info->executable)
2411
        {
2412
          s = bfd_make_section_with_flags (abfd,
2413
                                           (bed->default_use_rela_p
2414
                                            ? ".rela.bss" : ".rel.bss"),
2415
                                           flags | SEC_READONLY);
2416
          if (s == NULL
2417
              || ! bfd_set_section_alignment (abfd, s, ptralign))
2418
            return FALSE;
2419
        }
2420
    }
2421
 
2422
  return TRUE;
2423
}
2424
 
2425
/* Adjust a symbol defined by a dynamic object and referenced by a
2426
   regular object.  The current definition is in some section of the
2427
   dynamic object, but we're not including those sections.  We have to
2428
   change the definition to something the rest of the link can
2429
   understand.  */
2430
 
2431
static bfd_boolean
2432
_bfd_cr16_elf_adjust_dynamic_symbol (struct bfd_link_info * info,
2433
                                     struct elf_link_hash_entry * h)
2434
{
2435
  bfd * dynobj;
2436
  asection * s;
2437
 
2438
  dynobj = elf_hash_table (info)->dynobj;
2439
 
2440
  /* Make sure we know what is going on here.  */
2441
  BFD_ASSERT (dynobj != NULL
2442
              && (h->needs_plt
2443
                  || h->u.weakdef != NULL
2444
                  || (h->def_dynamic
2445
                      && h->ref_regular
2446
                      && !h->def_regular)));
2447
 
2448
  /* If this is a function, put it in the procedure linkage table.  We
2449
     will fill in the contents of the procedure linkage table later,
2450
     when we know the address of the .got section.  */
2451
  if (h->type == STT_FUNC
2452
      || h->needs_plt)
2453
    {
2454
      if (! info->executable
2455
          && !h->def_dynamic
2456
          && !h->ref_dynamic)
2457
        {
2458
          /* This case can occur if we saw a PLT reloc in an input
2459
             file, but the symbol was never referred to by a dynamic
2460
             object.  In such a case, we don't actually need to build
2461
             a procedure linkage table, and we can just do a REL32
2462
             reloc instead.  */
2463
          BFD_ASSERT (h->needs_plt);
2464
          return TRUE;
2465
        }
2466
 
2467
      /* Make sure this symbol is output as a dynamic symbol.  */
2468
      if (h->dynindx == -1)
2469
        {
2470
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
2471
            return FALSE;
2472
        }
2473
 
2474
      /* We also need to make an entry in the .got.plt section, which
2475
         will be placed in the .got section by the linker script.  */
2476
 
2477
      s = bfd_get_section_by_name (dynobj, ".got.plt");
2478
      BFD_ASSERT (s != NULL);
2479
      s->size += 4;
2480
 
2481
      /* We also need to make an entry in the .rela.plt section.  */
2482
 
2483
      s = bfd_get_section_by_name (dynobj, ".rela.plt");
2484
      BFD_ASSERT (s != NULL);
2485
      s->size += sizeof (Elf32_External_Rela);
2486
 
2487
      return TRUE;
2488
    }
2489
 
2490
  /* If this is a weak symbol, and there is a real definition, the
2491
     processor independent code will have arranged for us to see the
2492
     real definition first, and we can just use the same value.  */
2493
  if (h->u.weakdef != NULL)
2494
    {
2495
      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
2496
                  || h->u.weakdef->root.type == bfd_link_hash_defweak);
2497
      h->root.u.def.section = h->u.weakdef->root.u.def.section;
2498
      h->root.u.def.value = h->u.weakdef->root.u.def.value;
2499
      return TRUE;
2500
    }
2501
 
2502
  /* This is a reference to a symbol defined by a dynamic object which
2503
     is not a function.  */
2504
 
2505
  /* If we are creating a shared library, we must presume that the
2506
     only references to the symbol are via the global offset table.
2507
     For such cases we need not do anything here; the relocations will
2508
     be handled correctly by relocate_section.  */
2509
  if (info->executable)
2510
    return TRUE;
2511
 
2512
  /* If there are no references to this symbol that do not use the
2513
     GOT, we don't need to generate a copy reloc.  */
2514
  if (!h->non_got_ref)
2515
    return TRUE;
2516
 
2517
  if (h->size == 0)
2518
    {
2519
      (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
2520
                             h->root.root.string);
2521
      return TRUE;
2522
    }
2523
 
2524
  /* We must allocate the symbol in our .dynbss section, which will
2525
     become part of the .bss section of the executable.  There will be
2526
     an entry for this symbol in the .dynsym section.  The dynamic
2527
     object will contain position independent code, so all references
2528
     from the dynamic object to this symbol will go through the global
2529
     offset table.  The dynamic linker will use the .dynsym entry to
2530
     determine the address it must put in the global offset table, so
2531
     both the dynamic object and the regular object will refer to the
2532
     same memory location for the variable.  */
2533
 
2534
  s = bfd_get_section_by_name (dynobj, ".dynbss");
2535
  BFD_ASSERT (s != NULL);
2536
 
2537
  /* We must generate a R_CR16_COPY reloc to tell the dynamic linker to
2538
     copy the initial value out of the dynamic object and into the
2539
     runtime process image.  We need to remember the offset into the
2540
     .rela.bss section we are going to use.  */
2541
  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
2542
    {
2543
      asection * srel;
2544
 
2545
      srel = bfd_get_section_by_name (dynobj, ".rela.bss");
2546
      BFD_ASSERT (srel != NULL);
2547
      srel->size += sizeof (Elf32_External_Rela);
2548
      h->needs_copy = 1;
2549
    }
2550
 
2551
  return _bfd_elf_adjust_dynamic_copy (h, s);
2552
}
2553
 
2554
/* Set the sizes of the dynamic sections.  */
2555
 
2556
static bfd_boolean
2557
_bfd_cr16_elf_size_dynamic_sections (bfd * output_bfd,
2558
                                     struct bfd_link_info * info)
2559
{
2560
  bfd * dynobj;
2561
  asection * s;
2562
  bfd_boolean plt;
2563
  bfd_boolean relocs;
2564
  bfd_boolean reltext;
2565
 
2566
  dynobj = elf_hash_table (info)->dynobj;
2567
  BFD_ASSERT (dynobj != NULL);
2568
 
2569
  if (elf_hash_table (info)->dynamic_sections_created)
2570
    {
2571
      /* Set the contents of the .interp section to the interpreter.  */
2572
      if (info->executable)
2573
        {
2574
#if 0
2575
          s = bfd_get_section_by_name (dynobj, ".interp");
2576
          BFD_ASSERT (s != NULL);
2577
          s->size = sizeof ELF_DYNAMIC_INTERPRETER;
2578
          s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
2579
#endif
2580
        }
2581
    }
2582
  else
2583
    {
2584
      /* We may have created entries in the .rela.got section.
2585
         However, if we are not creating the dynamic sections, we will
2586
         not actually use these entries.  Reset the size of .rela.got,
2587
         which will cause it to get stripped from the output file
2588
         below.  */
2589
      s = bfd_get_section_by_name (dynobj, ".rela.got");
2590
      if (s != NULL)
2591
        s->size = 0;
2592
    }
2593
 
2594
  /* The check_relocs and adjust_dynamic_symbol entry points have
2595
     determined the sizes of the various dynamic sections.  Allocate
2596
     memory for them.  */
2597
  plt = FALSE;
2598
  relocs = FALSE;
2599
  reltext = FALSE;
2600
  for (s = dynobj->sections; s != NULL; s = s->next)
2601
    {
2602
      const char * name;
2603
 
2604
      if ((s->flags & SEC_LINKER_CREATED) == 0)
2605
        continue;
2606
 
2607
      /* It's OK to base decisions on the section name, because none
2608
         of the dynobj section names depend upon the input files.  */
2609
      name = bfd_get_section_name (dynobj, s);
2610
 
2611
      if (strcmp (name, ".plt") == 0)
2612
        {
2613
          /* Remember whether there is a PLT.  */
2614
          plt = s->size != 0;
2615
        }
2616
      else if (CONST_STRNEQ (name, ".rela"))
2617
        {
2618
          if (s->size != 0)
2619
            {
2620
              asection * target;
2621
 
2622
              /* Remember whether there are any reloc sections other
2623
                 than .rela.plt.  */
2624
              if (strcmp (name, ".rela.plt") != 0)
2625
                {
2626
                  const char * outname;
2627
 
2628
                  relocs = TRUE;
2629
 
2630
                  /* If this relocation section applies to a read only
2631
                     section, then we probably need a DT_TEXTREL
2632
                     entry.  The entries in the .rela.plt section
2633
                     really apply to the .got section, which we
2634
                     created ourselves and so know is not readonly.  */
2635
                  outname = bfd_get_section_name (output_bfd,
2636
                                                  s->output_section);
2637
                  target = bfd_get_section_by_name (output_bfd, outname + 5);
2638
                  if (target != NULL
2639
                      && (target->flags & SEC_READONLY) != 0
2640
                      && (target->flags & SEC_ALLOC) != 0)
2641
                    reltext = TRUE;
2642
                }
2643
 
2644
              /* We use the reloc_count field as a counter if we need
2645
                 to copy relocs into the output file.  */
2646
              s->reloc_count = 0;
2647
            }
2648
        }
2649
      else if (! CONST_STRNEQ (name, ".got")
2650
               && strcmp (name, ".dynbss") != 0)
2651
        /* It's not one of our sections, so don't allocate space.  */
2652
        continue;
2653
 
2654
      if (s->size == 0)
2655
        {
2656
          /* If we don't need this section, strip it from the
2657
             output file.  This is mostly to handle .rela.bss and
2658
             .rela.plt.  We must create both sections in
2659
             create_dynamic_sections, because they must be created
2660
             before the linker maps input sections to output
2661
             sections.  The linker does that before
2662
             adjust_dynamic_symbol is called, and it is that
2663
             function which decides whether anything needs to go
2664
             into these sections.  */
2665
          s->flags |= SEC_EXCLUDE;
2666
          continue;
2667
        }
2668
 
2669
        if ((s->flags & SEC_HAS_CONTENTS) == 0)
2670
          continue;
2671
 
2672
      /* Allocate memory for the section contents.  We use bfd_zalloc
2673
         here in case unused entries are not reclaimed before the
2674
         section's contents are written out.  This should not happen,
2675
         but this way if it does, we get a R_CR16_NONE reloc
2676
         instead of garbage.  */
2677
      s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
2678
      if (s->contents == NULL)
2679
        return FALSE;
2680
    }
2681
 
2682
  if (elf_hash_table (info)->dynamic_sections_created)
2683
    {
2684
      /* Add some entries to the .dynamic section.  We fill in the
2685
         values later, in _bfd_cr16_elf_finish_dynamic_sections,
2686
         but we must add the entries now so that we get the correct
2687
         size for the .dynamic section.  The DT_DEBUG entry is filled
2688
         in by the dynamic linker and used by the debugger.  */
2689
      if (! info->executable)
2690
        {
2691
          if (!_bfd_elf_add_dynamic_entry (info, DT_DEBUG, 0))
2692
            return FALSE;
2693
        }
2694
 
2695
      if (plt)
2696
        {
2697
          if (!_bfd_elf_add_dynamic_entry (info, DT_PLTGOT, 0)
2698
              || !_bfd_elf_add_dynamic_entry (info, DT_PLTRELSZ, 0)
2699
              || !_bfd_elf_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
2700
              || !_bfd_elf_add_dynamic_entry (info, DT_JMPREL, 0))
2701
            return FALSE;
2702
        }
2703
 
2704
      if (relocs)
2705
        {
2706
          if (!_bfd_elf_add_dynamic_entry (info, DT_RELA, 0)
2707
              || !_bfd_elf_add_dynamic_entry (info, DT_RELASZ, 0)
2708
              || !_bfd_elf_add_dynamic_entry (info, DT_RELAENT,
2709
                                              sizeof (Elf32_External_Rela)))
2710
            return FALSE;
2711
        }
2712
 
2713
      if (reltext)
2714
        {
2715
          if (!_bfd_elf_add_dynamic_entry (info, DT_TEXTREL, 0))
2716
            return FALSE;
2717
        }
2718
    }
2719
 
2720
  return TRUE;
2721
}
2722
 
2723
/* Finish up dynamic symbol handling.  We set the contents of various
2724
   dynamic sections here.  */
2725
 
2726
static bfd_boolean
2727
_bfd_cr16_elf_finish_dynamic_symbol (bfd * output_bfd,
2728
                                     struct bfd_link_info * info,
2729
                                     struct elf_link_hash_entry * h,
2730
                                     Elf_Internal_Sym * sym)
2731
{
2732
  bfd * dynobj;
2733
 
2734
  dynobj = elf_hash_table (info)->dynobj;
2735
 
2736
  if (h->got.offset != (bfd_vma) -1)
2737
    {
2738
      asection *        sgot;
2739
      asection *        srel;
2740
      Elf_Internal_Rela rel;
2741
 
2742
      /* This symbol has an entry in the global offset table.  Set it up.  */
2743
 
2744
      sgot = bfd_get_section_by_name (dynobj, ".got");
2745
      srel = bfd_get_section_by_name (dynobj, ".rela.got");
2746
      BFD_ASSERT (sgot != NULL && srel != NULL);
2747
 
2748
      rel.r_offset = (sgot->output_section->vma
2749
                      + sgot->output_offset
2750
                      + (h->got.offset & ~1));
2751
 
2752
      /* If this is a -Bsymbolic link, and the symbol is defined
2753
         locally, we just want to emit a RELATIVE reloc.  Likewise if
2754
         the symbol was forced to be local because of a version file.
2755
         The entry in the global offset table will already have been
2756
         initialized in the relocate_section function.  */
2757
      if (info->executable
2758
          && (info->symbolic || h->dynindx == -1)
2759
          && h->def_regular)
2760
        {
2761
          rel.r_info = ELF32_R_INFO (0, R_CR16_GOT_REGREL20);
2762
          rel.r_addend = (h->root.u.def.value
2763
                          + h->root.u.def.section->output_section->vma
2764
                          + h->root.u.def.section->output_offset);
2765
        }
2766
      else
2767
        {
2768
          bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset);
2769
          rel.r_info = ELF32_R_INFO (h->dynindx, R_CR16_GOT_REGREL20);
2770
          rel.r_addend = 0;
2771
        }
2772
 
2773
      bfd_elf32_swap_reloca_out (output_bfd, &rel,
2774
                                 (bfd_byte *) ((Elf32_External_Rela *) srel->contents
2775
                                               + srel->reloc_count));
2776
      ++ srel->reloc_count;
2777
    }
2778
 
2779
  if (h->needs_copy)
2780
    {
2781
      asection *        s;
2782
      Elf_Internal_Rela rel;
2783
 
2784
      /* This symbol needs a copy reloc.  Set it up.  */
2785
      BFD_ASSERT (h->dynindx != -1
2786
                  && (h->root.type == bfd_link_hash_defined
2787
                      || h->root.type == bfd_link_hash_defweak));
2788
 
2789
      s = bfd_get_section_by_name (h->root.u.def.section->owner,
2790
                                   ".rela.bss");
2791
      BFD_ASSERT (s != NULL);
2792
 
2793
      rel.r_offset = (h->root.u.def.value
2794
                      + h->root.u.def.section->output_section->vma
2795
                      + h->root.u.def.section->output_offset);
2796
      rel.r_info = ELF32_R_INFO (h->dynindx, R_CR16_GOT_REGREL20);
2797
      rel.r_addend = 0;
2798
      bfd_elf32_swap_reloca_out (output_bfd, &rel,
2799
                                 (bfd_byte *) ((Elf32_External_Rela *) s->contents
2800
                                               + s->reloc_count));
2801
     ++ s->reloc_count;
2802
    }
2803
 
2804
  /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
2805
  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
2806
      || h == elf_hash_table (info)->hgot)
2807
    sym->st_shndx = SHN_ABS;
2808
 
2809
  return TRUE;
2810
}
2811
 
2812
/* Finish up the dynamic sections.  */
2813
 
2814
static bfd_boolean
2815
_bfd_cr16_elf_finish_dynamic_sections (bfd * output_bfd,
2816
                                       struct bfd_link_info * info)
2817
{
2818
  bfd *      dynobj;
2819
  asection * sgot;
2820
  asection * sdyn;
2821
 
2822
  dynobj = elf_hash_table (info)->dynobj;
2823
 
2824
  sgot = bfd_get_section_by_name (dynobj, ".got.plt");
2825
  BFD_ASSERT (sgot != NULL);
2826
  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
2827
 
2828
  if (elf_hash_table (info)->dynamic_sections_created)
2829
    {
2830
      Elf32_External_Dyn * dyncon;
2831
      Elf32_External_Dyn * dynconend;
2832
 
2833
      BFD_ASSERT (sdyn != NULL);
2834
 
2835
      dyncon = (Elf32_External_Dyn *) sdyn->contents;
2836
      dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
2837
 
2838
      for (; dyncon < dynconend; dyncon++)
2839
        {
2840
          Elf_Internal_Dyn dyn;
2841
          const char * name;
2842
          asection * s;
2843
 
2844
          bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
2845
 
2846
          switch (dyn.d_tag)
2847
            {
2848
            default:
2849
              break;
2850
 
2851
            case DT_PLTGOT:
2852
              name = ".got";
2853
              goto get_vma;
2854
 
2855
            case DT_JMPREL:
2856
              name = ".rela.plt";
2857
            get_vma:
2858
              s = bfd_get_section_by_name (output_bfd, name);
2859
              BFD_ASSERT (s != NULL);
2860
              dyn.d_un.d_ptr = s->vma;
2861
              bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
2862
              break;
2863
 
2864
            case DT_PLTRELSZ:
2865
              s = bfd_get_section_by_name (output_bfd, ".rela.plt");
2866
              BFD_ASSERT (s != NULL);
2867
              dyn.d_un.d_val = s->size;
2868
              bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
2869
              break;
2870
 
2871
            case DT_RELASZ:
2872
              /* My reading of the SVR4 ABI indicates that the
2873
                 procedure linkage table relocs (DT_JMPREL) should be
2874
                 included in the overall relocs (DT_RELA).  This is
2875
                 what Solaris does.  However, UnixWare can not handle
2876
                 that case.  Therefore, we override the DT_RELASZ entry
2877
                 here to make it not include the JMPREL relocs.  Since
2878
                 the linker script arranges for .rela.plt to follow all
2879
                 other relocation sections, we don't have to worry
2880
                 about changing the DT_RELA entry.  */
2881
              s = bfd_get_section_by_name (output_bfd, ".rela.plt");
2882
              if (s != NULL)
2883
                dyn.d_un.d_val -= s->size;
2884
              bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
2885
              break;
2886
            }
2887
        }
2888
 
2889
    }
2890
 
2891
  /* Fill in the first three entries in the global offset table.  */
2892
  if (sgot->size > 0)
2893
    {
2894
      if (sdyn == NULL)
2895
        bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
2896
      else
2897
        bfd_put_32 (output_bfd,
2898
                    sdyn->output_section->vma + sdyn->output_offset,
2899
                    sgot->contents);
2900
    }
2901
 
2902
  elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
2903
 
2904
  return TRUE;
2905
}
2906
 
2907
/* Given a .data.rel section and a .emreloc in-memory section, store
2908
   relocation information into the .emreloc section which can be
2909
   used at runtime to relocate the section.  This is called by the
2910
   linker when the --embedded-relocs switch is used.  This is called
2911
   after the add_symbols entry point has been called for all the
2912
   objects, and before the final_link entry point is called.  */
2913
 
2914
bfd_boolean
2915
bfd_cr16_elf32_create_embedded_relocs (bfd *abfd,
2916
                                       struct bfd_link_info *info,
2917
                                       asection *datasec,
2918
                                       asection *relsec,
2919
                                       char **errmsg)
2920
{
2921
  Elf_Internal_Shdr *symtab_hdr;
2922
  Elf_Internal_Sym *isymbuf = NULL;
2923
  Elf_Internal_Rela *internal_relocs = NULL;
2924
  Elf_Internal_Rela *irel, *irelend;
2925
  bfd_byte *p;
2926
  bfd_size_type amt;
2927
 
2928
  BFD_ASSERT (! info->relocatable);
2929
 
2930
  *errmsg = NULL;
2931
 
2932
  if (datasec->reloc_count == 0)
2933
    return TRUE;
2934
 
2935
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
2936
 
2937
  /* Get a copy of the native relocations.  */
2938
  internal_relocs = (_bfd_elf_link_read_relocs
2939
                     (abfd, datasec, NULL, NULL, info->keep_memory));
2940
  if (internal_relocs == NULL)
2941
    goto error_return;
2942
 
2943
  amt = (bfd_size_type) datasec->reloc_count * 8;
2944
  relsec->contents = (bfd_byte *) bfd_alloc (abfd, amt);
2945
  if (relsec->contents == NULL)
2946
    goto error_return;
2947
 
2948
  p = relsec->contents;
2949
 
2950
  irelend = internal_relocs + datasec->reloc_count;
2951
  for (irel = internal_relocs; irel < irelend; irel++, p += 8)
2952
    {
2953
      asection *targetsec;
2954
 
2955
      /* We are going to write a four byte longword into the runtime
2956
       reloc section.  The longword will be the address in the data
2957
       section which must be relocated.  It is followed by the name
2958
       of the target section NUL-padded or truncated to 8
2959
       characters.  */
2960
 
2961
      /* We can only relocate absolute longword relocs at run time.  */
2962
      if (!((ELF32_R_TYPE (irel->r_info) == (int) R_CR16_NUM32a)
2963
          || (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_NUM32)))
2964
        {
2965
          *errmsg = _("unsupported reloc type");
2966
          bfd_set_error (bfd_error_bad_value);
2967
          goto error_return;
2968
        }
2969
 
2970
      /* Get the target section referred to by the reloc.  */
2971
      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
2972
        {
2973
          /* A local symbol.  */
2974
          Elf_Internal_Sym *isym;
2975
 
2976
          /* Read this BFD's local symbols if we haven't done so already.  */
2977
          if (isymbuf == NULL)
2978
            {
2979
              isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
2980
              if (isymbuf == NULL)
2981
                isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
2982
                                                symtab_hdr->sh_info, 0,
2983
                                                NULL, NULL, NULL);
2984
              if (isymbuf == NULL)
2985
                goto error_return;
2986
            }
2987
 
2988
          isym = isymbuf + ELF32_R_SYM (irel->r_info);
2989
          targetsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
2990
        }
2991
      else
2992
        {
2993
          unsigned long indx;
2994
          struct elf_link_hash_entry *h;
2995
 
2996
          /* An external symbol.  */
2997
          indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
2998
          h = elf_sym_hashes (abfd)[indx];
2999
          BFD_ASSERT (h != NULL);
3000
          if (h->root.type == bfd_link_hash_defined
3001
              || h->root.type == bfd_link_hash_defweak)
3002
            targetsec = h->root.u.def.section;
3003
          else
3004
            targetsec = NULL;
3005
        }
3006
 
3007
      bfd_put_32 (abfd, irel->r_offset + datasec->output_offset, p);
3008
      memset (p + 4, 0, 4);
3009
      if ((ELF32_R_TYPE (irel->r_info) == (int) R_CR16_NUM32a)
3010
          && (targetsec != NULL) )
3011
         strncpy ((char *) p + 4, targetsec->output_section->name, 4);
3012
    }
3013
 
3014
  if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
3015
    free (isymbuf);
3016
  if (internal_relocs != NULL
3017
      && elf_section_data (datasec)->relocs != internal_relocs)
3018
    free (internal_relocs);
3019
  return TRUE;
3020
 
3021
error_return:
3022
  if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
3023
    free (isymbuf);
3024
  if (internal_relocs != NULL
3025
      && elf_section_data (datasec)->relocs != internal_relocs)
3026
    free (internal_relocs);
3027
  return FALSE;
3028
}
3029
 
3030
 
3031
/* Classify relocation types, such that combreloc can sort them
3032
   properly.  */
3033
 
3034
static enum elf_reloc_type_class
3035
_bfd_cr16_elf_reloc_type_class (const Elf_Internal_Rela *rela)
3036
{
3037
  switch ((int) ELF32_R_TYPE (rela->r_info))
3038
    {
3039
    case R_CR16_GOT_REGREL20:
3040
    case R_CR16_GOTC_REGREL20:
3041
      return reloc_class_relative;
3042
    default:
3043
      return reloc_class_normal;
3044
    }
3045
}
3046
 
3047 24 jeremybenn
/* Definitions for setting CR16 target vector.  */
3048
#define TARGET_LITTLE_SYM                 bfd_elf32_cr16_vec
3049
#define TARGET_LITTLE_NAME                "elf32-cr16"
3050
#define ELF_ARCH                          bfd_arch_cr16
3051
#define ELF_MACHINE_CODE                  EM_CR16
3052 225 jeremybenn
#define ELF_MACHINE_ALT1                  EM_CR16_OLD
3053 24 jeremybenn
#define ELF_MAXPAGESIZE                   0x1
3054
#define elf_symbol_leading_char           '_'
3055
 
3056
#define bfd_elf32_bfd_reloc_type_lookup   elf_cr16_reloc_type_lookup
3057
#define bfd_elf32_bfd_reloc_name_lookup   elf_cr16_reloc_name_lookup
3058
#define elf_info_to_howto                 elf_cr16_info_to_howto
3059
#define elf_info_to_howto_rel             0
3060
#define elf_backend_relocate_section      elf32_cr16_relocate_section
3061
#define bfd_elf32_bfd_relax_section       elf32_cr16_relax_section
3062
#define bfd_elf32_bfd_get_relocated_section_contents \
3063
                                elf32_cr16_get_relocated_section_contents
3064
#define elf_backend_gc_mark_hook          elf32_cr16_gc_mark_hook
3065
#define elf_backend_gc_sweep_hook         elf32_cr16_gc_sweep_hook
3066
#define elf_backend_can_gc_sections       1
3067
#define elf_backend_rela_normal           1
3068 225 jeremybenn
#define elf_backend_check_relocs          cr16_elf_check_relocs
3069
/* So we can set bits in e_flags.  */
3070
#define elf_backend_final_write_processing \
3071
                                 _bfd_cr16_elf_final_write_processing
3072
#define elf_backend_object_p     _bfd_cr16_elf_object_p
3073 24 jeremybenn
 
3074 225 jeremybenn
#define bfd_elf32_bfd_merge_private_bfd_data \
3075
                                 _bfd_cr16_elf_merge_private_bfd_data
3076
 
3077
 
3078
#define bfd_elf32_bfd_link_hash_table_create \
3079
                                  elf32_cr16_link_hash_table_create
3080
#define bfd_elf32_bfd_link_hash_table_free \
3081
                                  elf32_cr16_link_hash_table_free
3082
 
3083
#define elf_backend_create_dynamic_sections \
3084
                                  _bfd_cr16_elf_create_dynamic_sections
3085
#define elf_backend_adjust_dynamic_symbol \
3086
                                  _bfd_cr16_elf_adjust_dynamic_symbol
3087
#define elf_backend_size_dynamic_sections \
3088
                                  _bfd_cr16_elf_size_dynamic_sections
3089
#define elf_backend_omit_section_dynsym \
3090
      ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
3091
#define elf_backend_finish_dynamic_symbol \
3092
                                   _bfd_cr16_elf_finish_dynamic_symbol
3093
#define elf_backend_finish_dynamic_sections \
3094
                                   _bfd_cr16_elf_finish_dynamic_sections
3095
 
3096
#define elf_backend_reloc_type_class   _bfd_cr16_elf_reloc_type_class
3097
 
3098
 
3099
#define elf_backend_want_got_plt        1
3100
#define elf_backend_plt_readonly        1
3101
#define elf_backend_want_plt_sym        0
3102
#define elf_backend_got_header_size     12
3103
 
3104 24 jeremybenn
#include "elf32-target.h"

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.