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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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