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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [bfd/] [elf32-d30v.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* D30V-specific support for 32-bit ELF
2
   Copyright 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
3
   Contributed by Martin Hunt (hunt@cygnus.com).
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 2 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
19
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
 
21
#include "bfd.h"
22
#include "sysdep.h"
23
#include "libbfd.h"
24
#include "elf-bfd.h"
25
#include "elf/d30v.h"
26
 
27
static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
28
  PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
29
static void d30v_info_to_howto_rel
30
  PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
31
static void d30v_info_to_howto_rela
32
  PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
33
static bfd_reloc_status_type bfd_elf_d30v_reloc PARAMS ((
34
     bfd *abfd,
35
     arelent *reloc_entry,
36
     asymbol *symbol,
37
     PTR data,
38
     asection *input_section,
39
     bfd *output_bfd,
40
     char **error_message));
41
static bfd_reloc_status_type bfd_elf_d30v_reloc_21 PARAMS ((
42
     bfd *abfd,
43
     arelent *reloc_entry,
44
     asymbol *symbol,
45
     PTR data,
46
     asection *input_section,
47
     bfd *output_bfd,
48
     char **error_message));
49
 
50
static reloc_howto_type elf_d30v_howto_table[] =
51
{
52
  /* This reloc does nothing.  */
53
  HOWTO (R_D30V_NONE,           /* type */
54
         0,                      /* rightshift */
55
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
56
         32,                    /* bitsize */
57
         false,                 /* pc_relative */
58
         0,                      /* bitpos */
59
         complain_overflow_bitfield, /* complain_on_overflow */
60
         bfd_elf_generic_reloc, /* special_function */
61
         "R_D30V_NONE",         /* name */
62
         false,                 /* partial_inplace */
63
         0,                      /* src_mask */
64
         0,                      /* dst_mask */
65
         false),                /* pcrel_offset */
66
 
67
  /* A 6 bit absolute relocation */
68
  HOWTO (R_D30V_6,              /* type */
69
         0,                      /* rightshift */
70
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
71
         6,                     /* bitsize */
72
         false,                 /* pc_relative */
73
         0,                      /* bitpos */
74
         complain_overflow_bitfield, /* complain_on_overflow */
75
         bfd_elf_generic_reloc, /* special_function */
76
         "R_D30V_6",            /* name */
77
         false,                 /* partial_inplace */
78
         0x3f,                  /* src_mask */
79
         0x3f,                  /* dst_mask */
80
         false),                /* pcrel_offset */
81
 
82
  /* A relative 9 bit relocation, right shifted by 3 */
83
  HOWTO (R_D30V_9_PCREL,        /* type */
84
         3,                     /* rightshift */
85
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
86
         6,                     /* bitsize */
87
         true,                  /* pc_relative */
88
         0,                      /* bitpos */
89
         complain_overflow_signed, /* complain_on_overflow */
90
         bfd_elf_d30v_reloc_21, /* special_function */
91
         "R_D30V_9_PCREL",      /* name */
92
         false,                 /* partial_inplace */
93
         0x3f,                  /* src_mask */
94
         0x3f,                  /* dst_mask */
95
         true),                 /* pcrel_offset */
96
 
97
  /* A relative 9 bit relocation, right shifted by 3 */
98
  HOWTO (R_D30V_9_PCREL_R,      /* type */
99
         3,                     /* rightshift */
100
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
101
         6,                     /* bitsize */
102
         true,                  /* pc_relative */
103
         0,                      /* bitpos */
104
         complain_overflow_signed, /* complain_on_overflow */
105
         bfd_elf_d30v_reloc_21, /* special_function */
106
         "R_D30V_9_PCREL_R",    /* name */
107
         false,                 /* partial_inplace */
108
         0x3f,                  /* src_mask */
109
         0x3f,                  /* dst_mask */
110
         true),                 /* pcrel_offset */
111
 
112
  /* An absolute 15 bit relocation, right shifted by 3 */
113
  HOWTO (R_D30V_15,             /* type */
114
         3,                     /* rightshift */
115
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
116
         12,                    /* bitsize */
117
         false,                 /* pc_relative */
118
         0,                      /* bitpos */
119
         complain_overflow_signed, /* complain_on_overflow */
120
         bfd_elf_generic_reloc, /* special_function */
121
         "R_D30V_15",           /* name */
122
         false,                 /* partial_inplace */
123
         0xfff,                 /* src_mask */
124
         0xfff,                 /* dst_mask */
125
         false),                /* pcrel_offset */
126
 
127
  /* A relative 15 bit relocation, right shifted by 3 */
128
  HOWTO (R_D30V_15_PCREL,       /* type */
129
         3,                     /* rightshift */
130
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
131
         12,                    /* bitsize */
132
         true,                  /* pc_relative */
133
         0,                      /* bitpos */
134
         complain_overflow_signed, /* complain_on_overflow */
135
         bfd_elf_d30v_reloc_21, /* special_function */
136
         "R_D30V_15_PCREL",     /* name */
137
         false,                 /* partial_inplace */
138
         0xfff,                 /* src_mask */
139
         0xfff,                 /* dst_mask */
140
         true),                 /* pcrel_offset */
141
 
142
  /* A relative 15 bit relocation, right shifted by 3 */
143
  HOWTO (R_D30V_15_PCREL_R,     /* type */
144
         3,                     /* rightshift */
145
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
146
         12,                    /* bitsize */
147
         true,                  /* pc_relative */
148
         0,                      /* bitpos */
149
         complain_overflow_signed, /* complain_on_overflow */
150
         bfd_elf_d30v_reloc_21, /* special_function */
151
         "R_D30V_15_PCREL_R",   /* name */
152
         false,                 /* partial_inplace */
153
         0xfff,                 /* src_mask */
154
         0xfff,                 /* dst_mask */
155
         true),                 /* pcrel_offset */
156
 
157
  /* An absolute 21 bit relocation, right shifted by 3 */
158
  HOWTO (R_D30V_21,             /* type */
159
         3,                     /* rightshift */
160
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
161
         18,                    /* bitsize */
162
         false,                 /* pc_relative */
163
         0,                      /* bitpos */
164
         complain_overflow_signed, /* complain_on_overflow */
165
         bfd_elf_generic_reloc, /* special_function */
166
         "R_D30V_21",           /* name */
167
         false,                 /* partial_inplace */
168
         0x3ffff,               /* src_mask */
169
         0x3ffff,               /* dst_mask */
170
         false),                /* pcrel_offset */
171
 
172
  /* A relative 21 bit relocation, right shifted by 3 */
173
  HOWTO (R_D30V_21_PCREL,       /* type */
174
         3,                     /* rightshift */
175
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
176
         18,                    /* bitsize */
177
         true,                  /* pc_relative */
178
         0,                      /* bitpos */
179
         complain_overflow_signed, /* complain_on_overflow */
180
         bfd_elf_d30v_reloc_21, /* special_function */
181
         "R_D30V_21_PCREL",     /* name */
182
         false,                 /* partial_inplace */
183
         0x3ffff,               /* src_mask */
184
         0x3ffff,               /* dst_mask */
185
         true),                 /* pcrel_offset */
186
 
187
  /* A relative 21 bit relocation, right shifted by 3, in the Right container */
188
  HOWTO (R_D30V_21_PCREL_R,     /* type */
189
         3,                     /* rightshift */
190
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
191
         18,                    /* bitsize */
192
         true,                  /* pc_relative */
193
         0,                      /* bitpos */
194
         complain_overflow_signed, /* complain_on_overflow */
195
         bfd_elf_d30v_reloc_21, /* special_function */
196
         "R_D30V_21_PCREL_R",   /* name */
197
         false,                 /* partial_inplace */
198
         0x3ffff,               /* src_mask */
199
         0x3ffff,               /* dst_mask */
200
         true),                 /* pcrel_offset */
201
 
202
  /* A D30V 32 bit absolute relocation */
203
  HOWTO (R_D30V_32,             /* type */
204
         0,                      /* rightshift */
205
         4,                     /* size (0 = byte, 1 = short, 2 = long) */
206
         32,                    /* bitsize */
207
         false,                 /* pc_relative */
208
         0,                      /* bitpos */
209
         complain_overflow_bitfield, /* complain_on_overflow */
210
         bfd_elf_d30v_reloc,    /* special_function */
211
         "R_D30V_32",           /* name */
212
         false,                 /* partial_inplace */
213
         0xffffffff,            /* src_mask */
214
         0xffffffff,            /* dst_mask */
215
         false),                /* pcrel_offset */
216
 
217
  /* A relative 32 bit relocation */
218
  HOWTO (R_D30V_32_PCREL,       /* type */
219
         0,                      /* rightshift */
220
         4,                     /* size (0 = byte, 1 = short, 2 = long) */
221
         32,                    /* bitsize */
222
         true,                  /* pc_relative */
223
         0,                      /* bitpos */
224
         complain_overflow_signed, /* complain_on_overflow */
225
         bfd_elf_d30v_reloc,    /* special_function */
226
         "R_D30V_32_PCREL",     /* name */
227
         false,                 /* partial_inplace */
228
         0xffffffff,            /* src_mask */
229
         0xffffffff,            /* dst_mask */
230
         true),                 /* pcrel_offset */
231
 
232
  /* A regular 32 bit absolute relocation */
233
  HOWTO (R_D30V_32_NORMAL,              /* type */
234
         0,                      /* rightshift */
235
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
236
         32,                    /* bitsize */
237
         false,                 /* pc_relative */
238
         0,                      /* bitpos */
239
         complain_overflow_bitfield, /* complain_on_overflow */
240
         bfd_elf_generic_reloc, /* special_function */
241
         "R_D30V_32_NORMAL",            /* name */
242
         false,                 /* partial_inplace */
243
         0xffffffff,            /* src_mask */
244
         0xffffffff,            /* dst_mask */
245
         false),                /* pcrel_offset */
246
 
247
};
248
 
249
#define MAX32 ((bfd_signed_vma) 0x7fffffff)
250
#define MIN32 (- MAX32 - 1)
251
 
252
static bfd_reloc_status_type
253
bfd_elf_d30v_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message)
254
     bfd *abfd;
255
     arelent *reloc_entry;
256
     asymbol *symbol;
257
     PTR data;
258
     asection *input_section;
259
     bfd *output_bfd;
260
     char **error_message;
261
{
262
  bfd_signed_vma relocation;
263
  bfd_vma in1, in2, num;
264
  bfd_vma tmp_addr = 0;
265
  bfd_reloc_status_type r;
266
  asection *reloc_target_output_section;
267
  bfd_size_type addr = reloc_entry->address;
268
  bfd_reloc_status_type flag = bfd_reloc_ok;
269
  bfd_vma output_base = 0;
270
  reloc_howto_type *howto = reloc_entry->howto;
271
  int make_absolute = 0;
272
 
273
  if (output_bfd != (bfd *) NULL)
274
    {
275
      /* Partial linking -- do nothing.  */
276
      reloc_entry->address += input_section->output_offset;
277
      return bfd_reloc_ok;
278
    }
279
 
280
  r = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
281
                             input_section, output_bfd, error_message);
282
  if (r != bfd_reloc_continue)
283
    return r;
284
 
285
  /* a hacked-up version of bfd_perform_reloc() follows */
286
 if (bfd_is_und_section (symbol->section)
287
      && (symbol->flags & BSF_WEAK) == 0
288
      && output_bfd == (bfd *) NULL)
289
    flag = bfd_reloc_undefined;
290
 
291
  /* Is the address of the relocation really within the section?  */
292
  if (reloc_entry->address > input_section->_cooked_size)
293
    return bfd_reloc_outofrange;
294
 
295
  /* Work out which section the relocation is targetted at and the
296
     initial relocation command value.  */
297
 
298
  /* Get symbol value.  (Common symbols are special.)  */
299
  if (bfd_is_com_section (symbol->section))
300
    relocation = 0;
301
  else
302
    relocation = symbol->value;
303
 
304
  reloc_target_output_section = symbol->section->output_section;
305
 
306
  /* Convert input-section-relative symbol value to absolute.  */
307
  output_base = reloc_target_output_section->vma;
308
  relocation += output_base + symbol->section->output_offset;
309
 
310
  /* Add in supplied addend.  */
311
  relocation += reloc_entry->addend;
312
 
313
  /* Here the variable relocation holds the final address of the
314
     symbol we are relocating against, plus any addend.  */
315
 
316
  if (howto->pc_relative == true)
317
    {
318
      tmp_addr = input_section->output_section->vma + input_section->output_offset
319
        + reloc_entry->address;
320
      relocation -= tmp_addr;
321
    }
322
 
323
  in1 = bfd_get_32 (abfd, (bfd_byte *) data + addr);
324
  in2 = bfd_get_32 (abfd, (bfd_byte *) data + addr + 4);
325
 
326
  /* extract the addend */
327
  num = ((in2 & 0x3FFFF)
328
         | ((in2 & 0xFF00000) >> 2)
329
         | ((in1 & 0x3F) << 26));
330
  in1 &= 0xFFFFFFC0;
331
  in2 = 0x80000000;
332
 
333
  relocation += num;
334
 
335
  if (howto->pc_relative == true && howto->bitsize == 32)
336
    {
337
      /* The D30V has a PC that doesn't wrap and PC-relative jumps are
338
         signed, so a PC-relative jump can't be more than +/- 2^31 bytes.
339
         If one exceeds this, change it to an absolute jump.  */
340
      if (relocation > MAX32 || relocation < MIN32)
341
        {
342
          relocation = (relocation + tmp_addr) & 0xffffffff;
343
          make_absolute = 1;
344
        }
345
    }
346
 
347
  in1 |= (relocation >> 26) & 0x3F;     /* top 6 bits */
348
  in2 |= ((relocation & 0x03FC0000) << 2);  /* next 8 bits */
349
  in2 |= relocation & 0x0003FFFF;               /* bottom 18 bits */
350
 
351
  /* change a PC-relative instruction to its absolute equivalent */
352
  /* with this simple hack */
353
  if (make_absolute)
354
    in1 |= 0x00100000;
355
 
356
  bfd_put_32 (abfd, in1, (bfd_byte *) data + addr);
357
  bfd_put_32 (abfd, in2, (bfd_byte *) data + addr + 4);
358
 
359
  return flag;
360
}
361
 
362
static bfd_reloc_status_type
363
bfd_elf_d30v_reloc_21 (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message)
364
     bfd *abfd;
365
     arelent *reloc_entry;
366
     asymbol *symbol;
367
     PTR data;
368
     asection *input_section;
369
     bfd *output_bfd;
370
     char **error_message;
371
{
372
  bfd_vma relocation;
373
  bfd_vma in1, num;
374
  bfd_reloc_status_type r;
375
  asection *reloc_target_output_section;
376
  bfd_size_type addr = reloc_entry->address;
377
  bfd_reloc_status_type flag = bfd_reloc_ok;
378
  bfd_vma output_base = 0;
379
  reloc_howto_type *howto = reloc_entry->howto;
380
  int mask, max;
381
 
382
  if (output_bfd != (bfd *) NULL)
383
    {
384
      /* Partial linking -- do nothing.  */
385
      reloc_entry->address += input_section->output_offset;
386
      return bfd_reloc_ok;
387
    }
388
 
389
  r = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
390
                             input_section, output_bfd, error_message);
391
  if (r != bfd_reloc_continue)
392
    return r;
393
 
394
  /* a hacked-up version of bfd_perform_reloc() follows */
395
 if (bfd_is_und_section (symbol->section)
396
      && (symbol->flags & BSF_WEAK) == 0
397
      && output_bfd == (bfd *) NULL)
398
    flag = bfd_reloc_undefined;
399
 
400
  /* Is the address of the relocation really within the section?  */
401
  if (reloc_entry->address > input_section->_cooked_size)
402
    return bfd_reloc_outofrange;
403
 
404
  /* Work out which section the relocation is targetted at and the
405
     initial relocation command value.  */
406
 
407
  /* Get symbol value.  (Common symbols are special.)  */
408
  if (bfd_is_com_section (symbol->section))
409
    relocation = 0;
410
  else
411
    relocation = symbol->value;
412
 
413
  reloc_target_output_section = symbol->section->output_section;
414
 
415
  /* Convert input-section-relative symbol value to absolute.  */
416
  output_base = reloc_target_output_section->vma;
417
  relocation += output_base + symbol->section->output_offset;
418
 
419
  /* Add in supplied addend.  */
420
  relocation += reloc_entry->addend;
421
 
422
  /* Here the variable relocation holds the final address of the
423
     symbol we are relocating against, plus any addend.  */
424
 
425
  if (howto->pc_relative == true)
426
    {
427
      relocation -= (input_section->output_section->vma
428
                     + input_section->output_offset);
429
      if (howto->pcrel_offset == true)
430
        relocation -= reloc_entry->address;
431
    }
432
 
433
  in1 = bfd_get_32 (abfd, (bfd_byte *) data + addr);
434
 
435
  mask =  (1 << howto->bitsize) - 1;
436
  if (howto->bitsize == 6)
437
    mask <<= 12;
438
  max = (1 << (howto->bitsize + 2)) - 1;
439
 
440
  /* extract the addend */
441
  num = in1 & mask;  /* 18 bits */
442
  if (howto->bitsize == 6)
443
    num >>= 12;
444
  num <<= 3; /* shift left 3 */
445
  in1 &= ~mask;  /* mask out addend */
446
 
447
  relocation += num;
448
  if (howto->type == R_D30V_21_PCREL_R || howto->type == R_D30V_15_PCREL_R ||
449
      howto->type == R_D30V_9_PCREL_R )
450
    {
451
      relocation += 4;
452
    }
453
 
454
  if ((int)relocation < 0 )
455
    {
456
      if (~(int)relocation > max)
457
        flag = bfd_reloc_overflow;
458
    }
459
  else
460
    {
461
      if ((int)relocation > max)
462
        flag = bfd_reloc_overflow;
463
    }
464
  relocation >>= 3;
465
  if (howto->bitsize == 6)
466
    in1 |= ((relocation & (mask >> 12)) << 12);
467
  else
468
    in1 |= relocation & mask;
469
 
470
  bfd_put_32 (abfd, in1, (bfd_byte *) data + addr);
471
 
472
  return flag;
473
}
474
 
475
/* Map BFD reloc types to D30V ELF reloc types.  */
476
 
477
struct d30v_reloc_map
478
{
479
  bfd_reloc_code_real_type bfd_reloc_val;
480
  unsigned char elf_reloc_val;
481
};
482
 
483
static const struct d30v_reloc_map d30v_reloc_map[] =
484
{
485
  { BFD_RELOC_NONE, R_D30V_NONE, },
486
  { BFD_RELOC_D30V_6, R_D30V_6 },
487
  { BFD_RELOC_D30V_9_PCREL, R_D30V_9_PCREL },
488
  { BFD_RELOC_D30V_9_PCREL_R, R_D30V_9_PCREL_R },
489
  { BFD_RELOC_D30V_15, R_D30V_15 },
490
  { BFD_RELOC_D30V_15_PCREL, R_D30V_15_PCREL },
491
  { BFD_RELOC_D30V_15_PCREL_R, R_D30V_15_PCREL_R },
492
  { BFD_RELOC_D30V_21, R_D30V_21 },
493
  { BFD_RELOC_D30V_21_PCREL, R_D30V_21_PCREL },
494
  { BFD_RELOC_D30V_21_PCREL_R, R_D30V_21_PCREL_R },
495
  { BFD_RELOC_D30V_32, R_D30V_32 },
496
  { BFD_RELOC_D30V_32_PCREL, R_D30V_32_PCREL },
497
  { BFD_RELOC_32, R_D30V_32_NORMAL },
498
};
499
 
500
static reloc_howto_type *
501
bfd_elf32_bfd_reloc_type_lookup (abfd, code)
502
     bfd *abfd ATTRIBUTE_UNUSED;
503
     bfd_reloc_code_real_type code;
504
{
505
  unsigned int i;
506
 
507
  for (i = 0;
508
       i < sizeof (d30v_reloc_map) / sizeof (struct d30v_reloc_map);
509
       i++)
510
    {
511
      if (d30v_reloc_map[i].bfd_reloc_val == code)
512
        return &elf_d30v_howto_table[d30v_reloc_map[i].elf_reloc_val];
513
    }
514
 
515
  return NULL;
516
}
517
 
518
/* Set the howto pointer for an D30V ELF reloc (type REL).  */
519
 
520
static void
521
d30v_info_to_howto_rel (abfd, cache_ptr, dst)
522
     bfd *abfd ATTRIBUTE_UNUSED;
523
     arelent *cache_ptr;
524
     Elf32_Internal_Rel *dst;
525
{
526
  unsigned int r_type;
527
 
528
  r_type = ELF32_R_TYPE (dst->r_info);
529
  BFD_ASSERT (r_type < (unsigned int) R_D30V_max);
530
  cache_ptr->howto = &elf_d30v_howto_table[r_type];
531
}
532
 
533
/* Set the howto pointer for an D30V ELF reloc (type RELA).  */
534
 
535
static void
536
d30v_info_to_howto_rela (abfd, cache_ptr, dst)
537
     bfd *abfd ATTRIBUTE_UNUSED;
538
     arelent *cache_ptr;
539
     Elf32_Internal_Rela *dst;
540
{
541
  unsigned int r_type;
542
 
543
  r_type = ELF32_R_TYPE (dst->r_info);
544
  BFD_ASSERT (r_type < (unsigned int) R_D30V_max);
545
  cache_ptr->howto = &elf_d30v_howto_table[r_type];
546
}
547
 
548
#define ELF_ARCH                bfd_arch_d30v
549
#define ELF_MACHINE_CODE        EM_CYGNUS_D30V
550
#define ELF_MAXPAGESIZE         0x1000
551
 
552
#define TARGET_BIG_SYM          bfd_elf32_d30v_vec
553
#define TARGET_BIG_NAME         "elf32-d30v"
554
 
555
#define elf_info_to_howto       d30v_info_to_howto_rela
556
#define elf_info_to_howto_rel   d30v_info_to_howto_rel
557
#define elf_backend_object_p    0
558
#define elf_backend_final_write_processing      0
559
 
560
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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