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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [bfd/] [coff-or16.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 104 markom
/* BFD back-end for OpenRISC 1000 COFF binaries.
2
   Copyright 1990, 91, 92, 93, 94, 95, 1997 Free Software Foundation, Inc.
3
   Contributed by David Wood at New York University 7/8/91.
4
   Modified by Johan Rydberg, <johan.rydberg@netinsight.se>
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
#define OR16 1
23
 
24
#include "bfd.h"
25
#include "sysdep.h"
26
#include "libbfd.h"
27
#include "coff/or16.h"
28
#include "coff/internal.h"
29
#include "libcoff.h"
30
 
31
static long get_symbol_value PARAMS ((asymbol *));
32
static bfd_reloc_status_type or1_reloc
33
  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
34
static boolean coff_or1_relocate_section
35
  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
36
     struct internal_reloc *, struct internal_syment *, asection **));
37
static boolean coff_or1_adjust_symndx
38
  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
39
     struct internal_reloc *, boolean *));
40
 
41
static bfd_reloc_status_type or16_reloc
42
  PARAMS ((bfd *abfd, arelent *reloc_entry, asymbol *symbol_in,
43
          PTR data, asection *input_section, bfd *output_bfd, char **error_message));
44
 
45
#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
46
 
47
#define INSERT_HWORD(WORD,HWORD)              \
48
    (((WORD) & 0xff00ff00) | (((HWORD) & 0xff00) << 8) | ((HWORD)& 0xff))
49
#define EXTRACT_HWORD(WORD)                   \
50
    ((((WORD) & 0x00ff0000) >> 8) | ((WORD)& 0xff))
51
#define SIGN_EXTEND_HWORD(HWORD)              \
52
    ((HWORD) & 0x8000 ? (HWORD)|(~0xffffL) : (HWORD))
53
 
54
#define SIGN_EXTEND_12BIT(HWORD)              \
55
    ((HWORD) & 0x1000 ? (HWORD)|(~0xefffL) : (HWORD))
56
#define SIGN_EXTEND_26BIT(HWORD)              \
57
    ((HWORD) & 0x8000000 ? (HWORD)|(~0xfffffffL) : (HWORD))
58
 
59
#define EXTRACT_12BIT(WORD)     ((WORD) & 0x0fff)
60
#define EXTRACT_26BIT(WORD)     ((WORD) & 0x0fffffff)
61
 
62
#define INSERT_12BIT(WORD,HWORD)              \
63
    (((WORD) & 0xf000) | (((HWORD) & 0x0fff)))
64
#define INSERT_26BIT(WORD,HWORD)              \
65
    (((WORD) & 0xf0000000) | (((HWORD) & 0x0fffffff)))
66
 
67
static reloc_howto_type howto_table[] =
68
{
69
  HOWTO (R_OR16_ABS,            /* type */
70
         0,                     /* rightshift */
71
         3,                     /* size (0 = byte, 1 = short, 2 = long) */
72
         32,                    /* bitsize */
73
         false,                 /* pc_relative */
74
         0,                     /* bitpos */
75
         complain_overflow_signed, /* complain_on_overflow */
76
         or16_reloc,            /* special_function */
77
         "r_or16_abs",          /* name */
78
         true,                  /* partial_inplace */
79
         0xffffffff,            /* src_mask */
80
         0xffffffff,            /* dst_mask */
81
         false),                /* pcrel_offset */
82
 
83
  HOWTO (R_OR16_INSN_REL,       /* type */
84
         1,                     /* rightshift */
85
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
86
         12,                    /* bitsize */
87
         true,                  /* pc_relative */
88
         0,                     /* bitpos */
89
         complain_overflow_signed, /* complain_on_overflow */
90
         or16_reloc,            /* special_function */
91
         "r_or16_insn_rel",     /* name */
92
         true,                  /* partial_inplace */
93
         0x00003fff,            /* src_mask */
94
         0x00003fff,            /* dst_mask */
95
         false),                /* pcrel_offset */
96
 
97
  HOWTO (R_OR16_INSN_REL_12,    /* type */
98
         1,                     /* rightshift */
99
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
100
         12,                    /* bitsize */
101
         true,                  /* pc_relative */
102
         0,                     /* bitpos */
103
         complain_overflow_signed, /* complain_on_overflow */
104
         or16_reloc,            /* special_function */
105
         "r_or16_insn_rel_12",  /* name */
106
         true,                  /* partial_inplace */
107
         0x00003fff,            /* src_mask */
108
         0x00003fff,            /* dst_mask */
109
         false),                /* pcrel_offset */
110
 
111
  HOWTO (R_OR16_INSN_REL_26,      /* type */
112
         1,                     /* rightshift */
113
         3,                     /* size (0 = byte, 1 = short, 2 = long) */
114
         26,                    /* bitsize */
115
         true,                  /* pc_relative */
116
         0,                     /* bitpos */
117
         complain_overflow_signed, /* complain_on_overflow */
118
         or16_reloc,            /* special_function */
119
         "r_or16_insn_rel_26",  /* name */
120
         true,                  /* partial_inplace */
121
         0x1fffffff,            /* src_mask */
122
         0x1fffffff,            /* dst_mask */
123
         false),                /* pcrel_offset */
124
 
125
  HOWTO (R_OR16_INSN_ABS,       /* type */
126
         0,                     /* rightshift */
127
         3,                     /* size (0 = byte, 1 = short, 2 = long) */
128
         32,                    /* bitsize */
129
         false,                 /* pc_relative */
130
         0,                     /* bitpos */
131
         complain_overflow_signed, /* complain_on_overflow */
132
         or16_reloc,            /* special_function */
133
         "r_or16_insn_abs",     /* name */
134
         true,                  /* partial_inplace */
135
         0xffffffff,            /* src_mask */
136
         0xffffffff,            /* dst_mask */
137
         false),                /* pcrel_offset */
138
 
139
  HOWTO (R_OR16_INSN_LO,        /* type */
140
         0,                     /* rightshift */
141
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
142
         16,                    /* bitsize */
143
         false,                 /* pc_relative */
144
         0,                     /* bitpos */
145
         complain_overflow_signed, /* complain_on_overflow */
146
         or16_reloc,            /* special_function */
147
         "r_or16_insn_rel",     /* name */
148
         true,                  /* partial_inplace */
149
         0x0000ffff,            /* src_mask */
150
         0x0000ffff,            /* dst_mask */
151
         false),                /* pcrel_offset */
152
 
153
  HOWTO (R_OR16_INSN_HI,        /* type */
154
         0,                     /* rightshift */
155
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
156
         16,                    /* bitsize */
157
         false,                 /* pc_relative */
158
         16,                    /* bitpos */
159
         complain_overflow_signed, /* complain_on_overflow */
160
         or16_reloc,            /* special_function */
161
         "r_or16_insn_rel",     /* name */
162
         true,                  /* partial_inplace */
163
         0xffff0000,            /* src_mask */
164
         0xffff0000,            /* dst_mask */
165
         false),                /* pcrel_offset */
166
 
167
  HOWTO (R_OR16_8,              /* type */
168
         0,                     /* rightshift */
169
         0,                     /* size (0 = byte, 1 = short, 2 = long) */
170
         8,                     /* bitsize */
171
         false,                 /* pc_relative */
172
         0,                     /* bitpos */
173
         complain_overflow_signed, /* complain_on_overflow */
174
         or16_reloc,            /* special_function */
175
         "r_or16_insn_rel",     /* name */
176
         true,                  /* partial_inplace */
177
         0x000000ff,            /* src_mask */
178
         0x000000ff,            /* dst_mask */
179
         false),                /* pcrel_offset */
180
 
181
  HOWTO (R_OR16_16,             /* type */
182
         0,                     /* rightshift */
183
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
184
         16,                    /* bitsize */
185
         false,                 /* pc_relative */
186
         0,                     /* bitpos */
187
         complain_overflow_signed, /* complain_on_overflow */
188
         or16_reloc,            /* special_function */
189
         "r_or16_insn_rel",     /* name */
190
         true,                  /* partial_inplace */
191
         0x0000ffff,            /* src_mask */
192
         0x0000ffff,            /* dst_mask */
193
         false),                /* pcrel_offset */
194
 
195
  HOWTO (R_OR16_32,             /* type */
196
         0,                     /* rightshift */
197
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
198
         32,                    /* bitsize */
199
         false,                 /* pc_relative */
200
         0,                     /* bitpos */
201
         complain_overflow_signed, /* complain_on_overflow */
202
         or16_reloc,            /* special_function */
203
         "r_or16_insn_rel",     /* name */
204
         true,                  /* partial_inplace */
205
         0xffffffff,            /* src_mask */
206
         0xffffffff,            /* dst_mask */
207
         false),                /* pcrel_offset */
208
};
209
 
210
#if 0
211
/*FIXME: I'm not real sure about this table; */
212
static reloc_howto_type howto_table[] =
213
{
214
  { R_ABS,      0, 3, 32, false,  0, complain_overflow_bitfield,  or16_reloc, "ABS",     true, 0xffffffff,0xffffffff, false },
215
  {1},  {2},  {3},   {4},  {5},  {6},  {7},  {8},  {9}, {10},
216
  {11}, {12}, {13}, {14}, {15}, {16}, {17}, {18}, {19}, {20},
217
  {21}, {22}, {23},
218
  { R_IREL,     0, 3, 32, true,   0, complain_overflow_signed,    or16_reloc, "IREL",    true, 0xffffffff,0xffffffff, false },
219
  { R_IABS,     0, 3, 32, false,  0, complain_overflow_bitfield,  or16_reloc, "IABS",    true, 0xffffffff,0xffffffff, false },
220
  { R_ILOHALF,  0, 3, 16, true,   0, complain_overflow_signed,    or16_reloc, "ILOHALF", true, 0x0000ffff,0x0000ffff, false },
221
  { R_IHIHALF,  0, 3, 16, true,   16,complain_overflow_signed,    or16_reloc, "IHIHALF", true, 0xffff0000,0xffff0000, false },
222
  { R_IHCONST,  0, 3, 16, true,   0, complain_overflow_signed,    or16_reloc, "IHCONST", true, 0xffff0000,0xffff0000, false },
223
  { R_BYTE,     0, 0, 8,  false,  0, complain_overflow_bitfield,  or16_reloc, "BYTE",    true, 0x000000ff,0x000000ff, false },
224
  { R_HWORD,    0, 1, 16, false,  0, complain_overflow_bitfield,  or16_reloc, "HWORD",   true, 0x0000ffff,0x0000ffff, false },
225
  { R_WORD,     0, 2, 32, false,  0, complain_overflow_bitfield,  or16_reloc, "WORD",    true, 0xffffffff,0xffffffff, false },
226
};
227
#endif
228
 
229
 
230
 
231
/* Provided the symbol, returns the value reffed.  */
232
static long
233
get_symbol_value (symbol)
234
     asymbol *symbol;
235
{
236
  long relocation = 0;
237
 
238
  if (bfd_is_com_section (symbol->section))
239
    {
240
      relocation = 0;
241
    }
242
  else
243
    {
244
      relocation = symbol->value +
245
        symbol->section->output_section->vma +
246
        symbol->section->output_offset;
247
    }
248
  return(relocation);
249
}
250
 
251
/* This function is in charge of performing all the or16 relocations.  */
252
static bfd_reloc_status_type
253
or16_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
254
            error_message)
255
     bfd *abfd;
256
     arelent *reloc_entry;
257
     asymbol *symbol_in;
258
     PTR data;
259
     asection *input_section;
260
     bfd *output_bfd;
261
     char **error_message;
262
{
263
  /* The consth relocation comes in two parts, we have to remember
264
     the state between calls, in these variables.  */
265
  static boolean part1_consth_active = false;
266
  static unsigned long part1_consth_value;
267
 
268
  unsigned long insn;
269
  unsigned long sym_value;
270
  unsigned long unsigned_value;
271
  unsigned short r_type;
272
  long signed_value;
273
 
274
  unsigned long addr = reloc_entry->address ;   /*+ input_section->vma*/
275
  bfd_byte *hit_data =addr + (bfd_byte *)(data);
276
 
277
  r_type = reloc_entry->howto->type;
278
 
279
  if (output_bfd)
280
    {
281
      /* Partial linking - do nothing */
282
      reloc_entry->address += input_section->output_offset;
283
      return bfd_reloc_ok;
284
    }
285
 
286
  if (symbol_in != NULL
287
      && bfd_is_und_section (symbol_in->section))
288
    {
289
      /* Keep the state machine happy in case we're called again */
290
      if (r_type == R_OR16_INSN_HI)
291
        {
292
          part1_consth_active = true;
293
          part1_consth_value  = 0;
294
        }
295
      return(bfd_reloc_undefined);
296
    }
297
 
298
  if ((part1_consth_active) && (r_type != R_OR16_INSN_HI))
299
    {
300
      part1_consth_active = false;
301
      *error_message = (char *) "Missing IHCONST";
302
      return(bfd_reloc_dangerous);
303
    }
304
 
305
  sym_value = get_symbol_value(symbol_in);
306
 
307
  switch (r_type)
308
    {
309
    case R_OR16_INSN_REL:
310
      insn = bfd_get_32(abfd, hit_data);
311
 
312
      /* Take the value in the field and sign extend it.  */
313
      signed_value = EXTRACT_HWORD(insn);
314
      signed_value = SIGN_EXTEND_HWORD(signed_value);
315
      signed_value <<= 2;
316
 
317
      /* See the note on the R_IREL reloc in coff_or16_relocate_section.  */
318
      if (signed_value == - (long) reloc_entry->address)
319
        signed_value = 0;
320
 
321
      signed_value += sym_value + reloc_entry->addend;
322
      if ((signed_value & ~0x3ffff) == 0)
323
        {                     /* Absolute jmp/call */
324
          insn |= (1<<24);    /* Make it absolute */
325
          /* FIXME: Should we change r_type to R_IABS */
326
        }
327
      else
328
        {
329
          /* Relative jmp/call, so subtract from the value the
330
             address of the place we're coming from */
331
          signed_value -= (reloc_entry->address
332
                           + input_section->output_section->vma
333
                           + input_section->output_offset);
334
          if (signed_value>0x1ffff || signed_value<-0x20000)
335
            return(bfd_reloc_overflow);
336
        }
337
      signed_value >>= 2;
338
      insn = INSERT_HWORD(insn, signed_value);
339
      bfd_put_32(abfd, insn ,hit_data);
340
      break;
341
 
342
    case R_OR16_INSN_REL_12:
343
      insn = bfd_get_16(abfd, hit_data);
344
 
345
      /* Take the value in the field and sign extend it.  */
346
      signed_value = EXTRACT_12BIT(insn);
347
      signed_value = SIGN_EXTEND_12BIT(signed_value);
348
      signed_value <<= 1;
349
 
350
      /* See the note on the R_IREL reloc in coff_or16_relocate_section.  */
351
      if (signed_value == - (long) reloc_entry->address)
352
        signed_value = 0;
353
 
354
      signed_value += sym_value + reloc_entry->addend;
355
 
356
      /* Relative jmp/call, so subtract from the value the
357
         address of the place we're coming from */
358
      signed_value -= (reloc_entry->address
359
                       + input_section->output_section->vma
360
                       + input_section->output_offset);
361
      if (signed_value>0x1ffff || signed_value<-0x20000)
362
        return(bfd_reloc_overflow);
363
 
364
      signed_value >>= 1;
365
      insn = INSERT_12BIT(insn, signed_value);
366
      bfd_put_16(abfd, insn ,hit_data);
367
      break;
368
 
369
    case R_OR16_INSN_REL_26:
370
      insn = bfd_get_32(abfd, hit_data);
371
 
372
      /* Take the value in the field and sign extend it.  */
373
      signed_value = EXTRACT_26BIT(insn);
374
      signed_value = SIGN_EXTEND_26BIT(signed_value);
375
      signed_value <<= 1;
376
 
377
#if 0
378
      /* See the note on the R_IREL reloc in coff_or16_relocate_section.  */
379
      if (signed_value == - (long) reloc_entry->address)
380
        signed_value = 0;
381
#endif
382
 
383
      signed_value += sym_value + reloc_entry->addend;
384
 
385
      /* Relative jmp/call, so subtract from the value the
386
         address of the place we're coming from */
387
      signed_value -= (reloc_entry->address
388
                       + input_section->output_section->vma
389
                       + input_section->output_offset);
390
 
391
      /* CHECK FOR OVERFLOW HERE */
392
 
393
      signed_value >>= 1;
394
      insn = INSERT_26BIT(insn, signed_value);
395
      bfd_put_32(abfd, insn ,hit_data);
396
      break;
397
 
398
    case R_OR16_INSN_LO:
399
      insn = bfd_get_32(abfd, hit_data);
400
      unsigned_value = EXTRACT_HWORD(insn);
401
      unsigned_value +=  sym_value + reloc_entry->addend;
402
      insn = INSERT_HWORD(insn, unsigned_value);
403
      bfd_put_32(abfd, insn, hit_data);
404
      break;
405
 
406
    case R_OR16_INSN_HI:
407
      insn = bfd_get_32(abfd, hit_data);
408
 
409
      /* consth, part 1
410
         Just get the symbol value that is referenced */
411
      part1_consth_active = true;
412
      part1_consth_value = sym_value + reloc_entry->addend;
413
 
414
      /* Don't modify insn until R_OR16_INSN_IHI */
415
      break;
416
 
417
    case R_OR16_INSN_IHI:
418
      insn = bfd_get_32(abfd, hit_data);
419
 
420
      /* consth, part 2
421
         Now relocate the reference */
422
      if (part1_consth_active == false)
423
        {
424
          *error_message = (char *) "Missing IHIHALF";
425
          return(bfd_reloc_dangerous);
426
        }
427
 
428
      /* sym_ptr_ptr = r_symndx, in coff_slurp_reloc_table() */
429
      unsigned_value = 0;   /*EXTRACT_HWORD(insn) << 16;*/
430
      unsigned_value += reloc_entry->addend; /* r_symndx */
431
      unsigned_value += part1_consth_value;
432
      unsigned_value = unsigned_value >> 16;
433
      insn = INSERT_HWORD(insn, unsigned_value);
434
      part1_consth_active = false;
435
      bfd_put_32(abfd, insn, hit_data);
436
      break;
437
 
438
    case R_OR16_8:
439
      insn = bfd_get_8(abfd, hit_data);
440
      unsigned_value = insn + sym_value + reloc_entry->addend;
441
      if (unsigned_value & 0xffffff00)
442
        return(bfd_reloc_overflow);
443
      bfd_put_8(abfd, unsigned_value, hit_data);
444
      break;
445
 
446
    case R_OR16_16:
447
      insn = bfd_get_16(abfd, hit_data);
448
      unsigned_value = insn + sym_value + reloc_entry->addend;
449
      if (unsigned_value & 0xffff0000)
450
        return(bfd_reloc_overflow);
451
      bfd_put_16(abfd, insn, hit_data);
452
      break;
453
 
454
    case R_OR16_32:
455
      insn = bfd_get_32(abfd, hit_data);
456
      insn += sym_value + reloc_entry->addend;
457
      bfd_put_32(abfd, insn, hit_data);
458
      break;
459
 
460
    default:
461
      *error_message = "Unrecognized reloc";
462
      return (bfd_reloc_dangerous);
463
    }
464
  return(bfd_reloc_ok);
465
}
466
 
467
#define BADMAG(x) OR16BADMAG(x)
468
 
469
#define RELOC_PROCESSING(relent, reloc, symbols, abfd, section) \
470
  reloc_processing(relent, reloc, symbols, abfd, section)
471
 
472
static void
473
reloc_processing (relent,reloc, symbols, abfd, section)
474
     arelent *relent;
475
     struct internal_reloc *reloc;
476
     asymbol **symbols;
477
     bfd *abfd;
478
     asection *section;
479
{
480
    static bfd_vma ihihalf_vaddr = (bfd_vma) -1;
481
 
482
    relent->address = reloc->r_vaddr;
483
    relent->howto = howto_table + reloc->r_type;
484
    if (reloc->r_type == R_OR16_INSN_IHI)
485
      {
486
        /* The address of an R_OR16_INSN_IHI should always be the address of
487
           the immediately preceding R_IHIHALF.  relocs generated by gas
488
           are correct, but relocs generated by High C are different (I
489
           can't figure out what the address means for High C).  We can
490
           handle both gas and High C by ignoring the address here, and
491
           simply reusing the address saved for R_IHIHALF.  */
492
        if (ihihalf_vaddr == (bfd_vma) -1)
493
          abort ();
494
 
495
        relent->address = ihihalf_vaddr;
496
        ihihalf_vaddr = (bfd_vma) -1;
497
        relent->addend = reloc->r_symndx;
498
        relent->sym_ptr_ptr= bfd_abs_section_ptr->symbol_ptr_ptr;
499
      }
500
    else
501
      {
502
        asymbol *ptr;
503
        relent->sym_ptr_ptr = symbols + obj_convert(abfd)[reloc->r_symndx];
504
 
505
        ptr = *(relent->sym_ptr_ptr);
506
 
507
        if (ptr
508
            && bfd_asymbol_bfd(ptr) == abfd
509
            && ((ptr->flags & BSF_OLD_COMMON)== 0))
510
          {
511
            relent->addend = 0;
512
          }
513
        else
514
          {
515
            relent->addend = 0;
516
          }
517
        relent->address-= section->vma;
518
        if (reloc->r_type == R_OR16_INSN_HI)
519
          ihihalf_vaddr = relent->address;
520
        else
521
          if (ihihalf_vaddr != (bfd_vma) -1)
522
            abort ();
523
      }
524
}
525
 
526
/* The reloc processing routine for the optimized COFF linker:  */
527
static boolean
528
coff_or16_relocate_section (output_bfd, info, input_bfd, input_section,
529
                            contents, relocs, syms, sections)
530
     bfd *output_bfd;
531
     struct bfd_link_info *info;
532
     bfd *input_bfd;
533
     asection *input_section;
534
     bfd_byte *contents;
535
     struct internal_reloc *relocs;
536
     struct internal_syment *syms;
537
     asection **sections;
538
{
539
  struct internal_reloc *rel;
540
  struct internal_reloc *relend;
541
  boolean hihalf;
542
  bfd_vma hihalf_val;
543
 
544
  /* If we are performing a relocateable link, we don't need to do a
545
     thing.  The caller will take care of adjusting the reloc
546
     addresses and symbol indices.  */
547
  if (info->relocateable)
548
    return true;
549
 
550
  hihalf = false;
551
  hihalf_val = 0;
552
 
553
  rel = relocs;
554
  relend = rel + input_section->reloc_count;
555
  for (; rel < relend; rel++)
556
    {
557
      long symndx;
558
      bfd_byte *loc;
559
      struct coff_link_hash_entry *h;
560
      struct internal_syment *sym;
561
      asection *sec;
562
      bfd_vma val;
563
      boolean overflow;
564
      unsigned long insn;
565
      long signed_value;
566
      unsigned long unsigned_value;
567
      bfd_reloc_status_type rstat;
568
 
569
      symndx = rel->r_symndx;
570
      loc = contents + rel->r_vaddr - input_section->vma;
571
 
572
      if (symndx == -1 || rel->r_type == R_OR16_INSN_IHI)
573
        h = NULL;
574
      else
575
        h = obj_coff_sym_hashes (input_bfd)[symndx];
576
 
577
      sym = NULL;
578
      sec = NULL;
579
      val = 0;
580
 
581
      /* An R_OR16_INSN_IHI reloc does not have a symbol.  Instead, the
582
         symbol index is an addend.  R_OR16_INSN_IHI is always used in
583
         conjunction with R_IHHALF.  */
584
      if (rel->r_type != R_OR16_INSN_IHI)
585
        {
586
          if (h == NULL)
587
            {
588
              if (symndx == -1)
589
                sec = bfd_abs_section_ptr;
590
              else
591
                {
592
                  sym = syms + symndx;
593
                  sec = sections[symndx];
594
                  val = (sec->output_section->vma
595
                         + sec->output_offset
596
                         + sym->n_value
597
                         - sec->vma);
598
                }
599
            }
600
          else
601
            {
602
              if (h->root.type == bfd_link_hash_defined
603
                  || h->root.type == bfd_link_hash_defweak)
604
                {
605
                  sec = h->root.u.def.section;
606
                  val = (h->root.u.def.value
607
                         + sec->output_section->vma
608
                         + sec->output_offset);
609
                }
610
              else
611
                {
612
                  if (! ((*info->callbacks->undefined_symbol)
613
                         (info, h->root.root.string, input_bfd, input_section,
614
                          rel->r_vaddr - input_section->vma)))
615
                    return false;
616
                }
617
            }
618
 
619
          if (hihalf)
620
            {
621
              if (! ((*info->callbacks->reloc_dangerous)
622
                     (info, "missing IHCONST reloc", input_bfd,
623
                      input_section, rel->r_vaddr - input_section->vma)))
624
                return false;
625
              hihalf = false;
626
            }
627
        }
628
 
629
      overflow = false;
630
 
631
      switch (rel->r_type)
632
        {
633
        default:
634
          bfd_set_error (bfd_error_bad_value);
635
          return false;
636
 
637
        case R_OR16_INSN_REL_12:
638
          insn = bfd_get_16 (input_bfd, loc);
639
 
640
          /* Extract the addend.  */
641
          signed_value = EXTRACT_12BIT (insn);
642
          signed_value = SIGN_EXTEND_12BIT (signed_value);
643
          signed_value <<= 1;
644
 
645
 
646
          /* Unfortunately, there are two different versions of COFF
647
             or16.  In the original AMD version, the value stored in
648
             the field for the R_IREL reloc is a simple addend.  In
649
             the GNU version, the value is the negative of the address
650
             of the reloc within section.  We try to cope here by
651
             assuming the AMD version, unless the addend is exactly
652
             the negative of the address; in the latter case we assume
653
             the GNU version.  This means that something like
654
 
655
                .text
656
                 nop
657
                jmp i-4
658
 
659
             will fail, because the addend of -4 will happen to equal
660
             the negative of the address within the section.  The
661
             compiler will never generate code like this.
662
 
663
             At some point in the future we may want to take out this
664
             check.  */
665
          if (signed_value == - (long) (rel->r_vaddr - input_section->vma))
666
            signed_value = 0;
667
 
668
          /* Determine the destination of the jump.  */
669
          signed_value += val;
670
 
671
          if ((signed_value & ~0x3ffff) == 0)
672
            {
673
              /* We can use an absolute jump.  */
674
              insn |= (1 << 24);
675
            }
676
          else
677
            {
678
              /* Make the destination PC relative.  */
679
              signed_value -= (input_section->output_section->vma
680
                               + input_section->output_offset
681
                               + (rel->r_vaddr - input_section->vma));
682
              if (signed_value > 0x1ffff || signed_value < - 0x20000)
683
                {
684
                  overflow = true;
685
                  signed_value = 0;
686
                }
687
            }
688
 
689
          /* Put the adjusted value back into the instruction.  */
690
          signed_value >>= 1;
691
          insn = INSERT_12BIT (insn, signed_value);
692
 
693
          bfd_put_16 (input_bfd, (bfd_vma) insn, loc);
694
          break;
695
 
696
        case R_OR16_INSN_REL_26:
697
          insn = bfd_get_32 (input_bfd, loc);
698
 
699
          /* Extract the addend.  */
700
          signed_value = EXTRACT_26BIT (insn);
701
          signed_value = SIGN_EXTEND_26BIT (signed_value);
702
          signed_value <<= 1;
703
 
704
          /* Make the destination PC relative.  */
705
          signed_value -= (input_section->output_section->vma
706
                           + input_section->output_offset
707
                           + (rel->r_vaddr - input_section->vma));
708
 
709
          /* Put the adjusted value back into the instruction.  */
710
          signed_value >>= 1;
711
          insn = INSERT_26BIT (insn, signed_value);
712
 
713
          bfd_put_32 (input_bfd, (bfd_vma) insn, loc);
714
          break;
715
 
716
        case R_OR16_INSN_REL:
717
          insn = bfd_get_32 (input_bfd, loc);
718
 
719
          /* Extract the addend.  */
720
          signed_value = EXTRACT_HWORD (insn);
721
          signed_value = SIGN_EXTEND_HWORD (signed_value);
722
          signed_value <<= 2;
723
 
724
          /* Unfortunately, there are two different versions of COFF
725
             or16.  In the original AMD version, the value stored in
726
             the field for the R_IREL reloc is a simple addend.  In
727
             the GNU version, the value is the negative of the address
728
             of the reloc within section.  We try to cope here by
729
             assuming the AMD version, unless the addend is exactly
730
             the negative of the address; in the latter case we assume
731
             the GNU version.  This means that something like
732
 
733
                .text
734
                 nop
735
                jmp i-4
736
 
737
             will fail, because the addend of -4 will happen to equal
738
             the negative of the address within the section.  The
739
             compiler will never generate code like this.
740
 
741
             At some point in the future we may want to take out this
742
             check.  */
743
          if (signed_value == - (long) (rel->r_vaddr - input_section->vma))
744
            signed_value = 0;
745
 
746
          /* Determine the destination of the jump.  */
747
          signed_value += val;
748
 
749
          if ((signed_value & ~0x3ffff) == 0)
750
            {
751
              /* We can use an absolute jump.  */
752
              insn |= (1 << 24);
753
            }
754
          else
755
            {
756
              /* Make the destination PC relative.  */
757
              signed_value -= (input_section->output_section->vma
758
                               + input_section->output_offset
759
                               + (rel->r_vaddr - input_section->vma));
760
              if (signed_value > 0x1ffff || signed_value < - 0x20000)
761
                {
762
                  overflow = true;
763
                  signed_value = 0;
764
                }
765
            }
766
 
767
          /* Put the adjusted value back into the instruction.  */
768
          signed_value >>= 2;
769
          insn = INSERT_HWORD (insn, signed_value);
770
 
771
          bfd_put_32 (input_bfd, (bfd_vma) insn, loc);
772
          break;
773
 
774
 
775
        case R_OR16_INSN_LO:
776
          printf ("val = %#x\n", val);
777
 
778
          insn = bfd_get_32 (input_bfd, loc);
779
          unsigned_value = EXTRACT_HWORD (insn);
780
          unsigned_value += val;
781
          insn = INSERT_HWORD (insn, unsigned_value);
782
          bfd_put_32 (input_bfd, insn, loc);
783
          break;
784
 
785
        case R_OR16_INSN_HI:
786
          /* Save the value for the R_OR16_INSN_IHI reloc.  */
787
          hihalf = true;
788
          hihalf_val = val;
789
          break;
790
 
791
        case R_OR16_INSN_IHI:
792
          if (! hihalf)
793
            {
794
              if (! ((*info->callbacks->reloc_dangerous)
795
                     (info, "missing IHIHALF reloc", input_bfd,
796
                      input_section, rel->r_vaddr - input_section->vma)))
797
                return false;
798
              hihalf_val = 0;
799
            }
800
 
801
          insn = bfd_get_32 (input_bfd, loc);
802
          unsigned_value = rel->r_symndx + hihalf_val;
803
          unsigned_value >>= 16;
804
          insn = INSERT_HWORD (insn, unsigned_value);
805
          bfd_put_32 (input_bfd, (bfd_vma) insn, loc);
806
 
807
          hihalf = false;
808
          break;
809
 
810
        case R_OR16_8:
811
        case R_OR16_16:
812
        case R_OR16_32:
813
          rstat = _bfd_relocate_contents (howto_table + rel->r_type,
814
                                          input_bfd, val, loc);
815
          if (rstat == bfd_reloc_overflow)
816
            overflow = true;
817
          else if (rstat != bfd_reloc_ok)
818
            abort ();
819
          break;
820
        }
821
 
822
      if (overflow)
823
        {
824
          const char *name;
825
          char buf[SYMNMLEN + 1];
826
 
827
          if (symndx == -1)
828
            name = "*ABS*";
829
          else if (h != NULL)
830
            name = h->root.root.string;
831
          else if (sym == NULL)
832
            name = "*unknown*";
833
          else if (sym->_n._n_n._n_zeroes == 0
834
                   && sym->_n._n_n._n_offset != 0)
835
            name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
836
          else
837
            {
838
              strncpy (buf, sym->_n._n_name, SYMNMLEN);
839
              buf[SYMNMLEN] = '\0';
840
              name = buf;
841
            }
842
 
843
          if (! ((*info->callbacks->reloc_overflow)
844
                 (info, name, howto_table[rel->r_type].name, (bfd_vma) 0,
845
                  input_bfd, input_section,
846
                  rel->r_vaddr - input_section->vma)))
847
            return false;
848
        }
849
    }
850
  return true;
851
}
852
 
853
#define coff_relocate_section coff_or16_relocate_section
854
 
855
/* We don't want to change the symndx of a R_OR16_INSN_IHI reloc, since it
856
   is actually an addend, not a symbol index at all.  */
857
 
858
/*ARGSUSED*/
859
static boolean
860
coff_or16_adjust_symndx (obfd, info, ibfd, sec, irel, adjustedp)
861
     bfd *obfd;
862
     struct bfd_link_info *info;
863
     bfd *ibfd;
864
     asection *sec;
865
     struct internal_reloc *irel;
866
     boolean *adjustedp;
867
{
868
  if (irel->r_type == R_OR16_INSN_IHI)
869
    *adjustedp = true;
870
  else
871
    *adjustedp = false;
872
  return true;
873
}
874
 
875
#define coff_adjust_symndx coff_or16_adjust_symndx
876
 
877
#include "coffcode.h"
878
 
879
const bfd_target or16coff_big_vec =
880
{
881
  "coff-or16-big",  /* name */
882
  bfd_target_coff_flavour,
883
  BFD_ENDIAN_BIG,   /* data byte order is big */
884
  BFD_ENDIAN_BIG,   /* header byte order is big */
885
 
886
  (HAS_RELOC  | EXEC_P |    /* object flags */
887
   HAS_LINENO | HAS_DEBUG |
888
   HAS_SYMS   | HAS_LOCALS | WP_TEXT),
889
 
890
  (SEC_HAS_CONTENTS | SEC_ALLOC | /* section flags */
891
   SEC_LOAD | SEC_RELOC |
892
   SEC_READONLY ),
893
  '_',        /* leading underscore */
894
  '/',        /* ar_pad_char */
895
  15,       /* ar_max_namelen */
896
 
897
  /* data */
898
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
899
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
900
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,
901
 
902
  /* hdrs */
903
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
904
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
905
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,
906
 
907
  {
908
    _bfd_dummy_target,
909
    coff_object_p,
910
    bfd_generic_archive_p,
911
    _bfd_dummy_target
912
  },
913
  {
914
    bfd_false,
915
    coff_mkobject,
916
    _bfd_generic_mkarchive,
917
    bfd_false
918
  },
919
  {
920
    bfd_false,
921
    coff_write_object_contents,
922
    _bfd_write_archive_contents,
923
    bfd_false
924
  },
925
 
926
  BFD_JUMP_TABLE_GENERIC (coff),
927
  BFD_JUMP_TABLE_COPY (coff),
928
  BFD_JUMP_TABLE_CORE (_bfd_nocore),
929
  BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
930
  BFD_JUMP_TABLE_SYMBOLS (coff),
931
  BFD_JUMP_TABLE_RELOCS (coff),
932
  BFD_JUMP_TABLE_WRITE (coff),
933
  BFD_JUMP_TABLE_LINK (coff),
934
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
935
 
936
  COFF_SWAP_TABLE
937
};

powered by: WebSVN 2.1.0

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