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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [bfd/] [coff-m68k.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* BFD back-end for Motorola 68000 COFF binaries.
2
   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1999,
3
   2000, 2001
4
   Free Software Foundation, Inc.
5
   Written by Cygnus Support.
6
 
7
This file is part of BFD, the Binary File Descriptor library.
8
 
9
This program is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 2 of the License, or
12
(at your option) any later version.
13
 
14
This program is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
GNU General Public License for more details.
18
 
19
You should have received a copy of the GNU General Public License
20
along with this program; if not, write to the Free Software
21
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
22
 
23
#include "bfd.h"
24
#include "sysdep.h"
25
#include "libbfd.h"
26
#include "coff/m68k.h"
27
#include "coff/internal.h"
28
#include "libcoff.h"
29
 
30
/* This source file is compiled multiple times for various m68k COFF
31
   variants.  The following macros control its behaviour:
32
 
33
   TARGET_SYM
34
     The C name of the BFD target vector.  The default is m68kcoff_vec.
35
   TARGET_NAME
36
     The user visible target name.  The default is "coff-m68k".
37
   NAMES_HAVE_UNDERSCORE
38
     Whether symbol names have an underscore.
39
   ONLY_DECLARE_RELOCS
40
     Only declare the relocation howto array.  Don't actually compile
41
     it.  The actual array will be picked up in another version of the
42
     file.
43
   STATIC_RELOCS
44
     Make the relocation howto array, and associated functions, static.
45
   COFF_COMMON_ADDEND
46
     If this is defined, then, for a relocation against a common
47
     symbol, the object file holds the value (the size) of the common
48
     symbol.  If this is not defined, then, for a relocation against a
49
     common symbol, the object file holds zero.  */
50
 
51
#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
52
 
53
#ifndef COFF_PAGE_SIZE
54
/* The page size is a guess based on ELF.  */
55
#define COFF_PAGE_SIZE 0x2000
56
#endif
57
 
58
#ifndef COFF_COMMON_ADDEND
59
#define RELOC_SPECIAL_FN 0
60
#else
61
static bfd_reloc_status_type m68kcoff_common_addend_special_fn
62
  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
63
static reloc_howto_type *m68kcoff_common_addend_rtype_to_howto
64
  PARAMS ((bfd *, asection *, struct internal_reloc *,
65
           struct coff_link_hash_entry *, struct internal_syment *,
66
           bfd_vma *));
67
#define RELOC_SPECIAL_FN m68kcoff_common_addend_special_fn
68
#endif
69
 
70
static boolean m68k_coff_is_local_label_name PARAMS ((bfd *, const char *));
71
 
72
/* On the delta, a symbol starting with L% is local.  We won't see
73
   such a symbol on other platforms, so it should be safe to always
74
   consider it local here.  */
75
 
76
static boolean
77
m68k_coff_is_local_label_name (abfd, name)
78
     bfd *abfd;
79
     const char *name;
80
{
81
  if (name[0] == 'L' && name[1] == '%')
82
    return true;
83
 
84
  return _bfd_coff_is_local_label_name (abfd, name);
85
}
86
 
87
#ifndef STATIC_RELOCS
88
/* Clean up namespace.  */
89
#define m68kcoff_howto_table    _bfd_m68kcoff_howto_table
90
#define m68k_rtype2howto        _bfd_m68kcoff_rtype2howto
91
#define m68k_howto2rtype        _bfd_m68kcoff_howto2rtype
92
#define m68k_reloc_type_lookup  _bfd_m68kcoff_reloc_type_lookup
93
#endif
94
 
95
#ifdef ONLY_DECLARE_RELOCS
96
extern reloc_howto_type m68kcoff_howto_table[];
97
#else
98
#ifdef STATIC_RELOCS
99
static
100
#endif
101
reloc_howto_type m68kcoff_howto_table[] =
102
  {
103
    HOWTO (R_RELBYTE,          0,  0,     8,  false, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "8", true, 0x000000ff,0x000000ff, false),
104
    HOWTO (R_RELWORD,          0,  1,    16, false, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "16",        true, 0x0000ffff,0x0000ffff, false),
105
    HOWTO (R_RELLONG,          0,  2,    32, false, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "32",        true, 0xffffffff,0xffffffff, false),
106
    HOWTO (R_PCRBYTE,          0,  0,     8,  true,  0, complain_overflow_signed,   RELOC_SPECIAL_FN, "DISP8",    true, 0x000000ff,0x000000ff, false),
107
    HOWTO (R_PCRWORD,          0,  1,    16, true,  0, complain_overflow_signed,   RELOC_SPECIAL_FN, "DISP16",   true, 0x0000ffff,0x0000ffff, false),
108
    HOWTO (R_PCRLONG,          0,  2,    32, true,  0, complain_overflow_signed,   RELOC_SPECIAL_FN, "DISP32",   true, 0xffffffff,0xffffffff, false),
109
    HOWTO (R_RELLONG_NEG,      0, -2,    32, false, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "-32",       true, 0xffffffff,0xffffffff, false),
110
  };
111
#endif /* not ONLY_DECLARE_RELOCS */
112
 
113
#ifndef BADMAG
114
#define BADMAG(x) M68KBADMAG(x)
115
#endif
116
#define M68 1           /* Customize coffcode.h */
117
 
118
/* Turn a howto into a reloc number */
119
 
120
#ifdef ONLY_DECLARE_RELOCS
121
extern void m68k_rtype2howto PARAMS ((arelent *internal, int relocentry));
122
extern int m68k_howto2rtype PARAMS ((reloc_howto_type *));
123
extern reloc_howto_type *m68k_reloc_type_lookup
124
  PARAMS ((bfd *, bfd_reloc_code_real_type));
125
#else
126
 
127
#ifdef STATIC_RELOCS
128
#define STAT_REL static
129
#else
130
#define STAT_REL
131
#endif
132
 
133
STAT_REL reloc_howto_type * m68k_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));
134
STAT_REL int m68k_howto2rtype PARAMS ((reloc_howto_type *));
135
STAT_REL void m68k_rtype2howto PARAMS ((arelent *, int));
136
 
137
 
138
STAT_REL void
139
m68k_rtype2howto(internal, relocentry)
140
     arelent *internal;
141
     int relocentry;
142
{
143
  switch (relocentry)
144
    {
145
    case R_RELBYTE:     internal->howto = m68kcoff_howto_table + 0; break;
146
    case R_RELWORD:     internal->howto = m68kcoff_howto_table + 1; break;
147
    case R_RELLONG:     internal->howto = m68kcoff_howto_table + 2; break;
148
    case R_PCRBYTE:     internal->howto = m68kcoff_howto_table + 3; break;
149
    case R_PCRWORD:     internal->howto = m68kcoff_howto_table + 4; break;
150
    case R_PCRLONG:     internal->howto = m68kcoff_howto_table + 5; break;
151
    case R_RELLONG_NEG: internal->howto = m68kcoff_howto_table + 6; break;
152
    }
153
}
154
 
155
STAT_REL int
156
m68k_howto2rtype (internal)
157
     reloc_howto_type *internal;
158
{
159
  if (internal->pc_relative)
160
    {
161
      switch (internal->bitsize)
162
        {
163
        case 32: return R_PCRLONG;
164
        case 16: return R_PCRWORD;
165
        case 8: return R_PCRBYTE;
166
        }
167
    }
168
  else
169
    {
170
      switch (internal->bitsize)
171
        {
172
        case 32: return R_RELLONG;
173
        case 16: return R_RELWORD;
174
        case 8: return R_RELBYTE;
175
        }
176
    }
177
  return R_RELLONG;
178
}
179
 
180
STAT_REL reloc_howto_type *
181
m68k_reloc_type_lookup (abfd, code)
182
     bfd *abfd ATTRIBUTE_UNUSED;
183
     bfd_reloc_code_real_type code;
184
{
185
  switch (code)
186
    {
187
    default:                    return NULL;
188
    case BFD_RELOC_8:           return m68kcoff_howto_table + 0;
189
    case BFD_RELOC_16:          return m68kcoff_howto_table + 1;
190
    case BFD_RELOC_CTOR:
191
    case BFD_RELOC_32:          return m68kcoff_howto_table + 2;
192
    case BFD_RELOC_8_PCREL:     return m68kcoff_howto_table + 3;
193
    case BFD_RELOC_16_PCREL:    return m68kcoff_howto_table + 4;
194
    case BFD_RELOC_32_PCREL:    return m68kcoff_howto_table + 5;
195
      /* FIXME: There doesn't seem to be a code for R_RELLONG_NEG.  */
196
    }
197
  /*NOTREACHED*/
198
}
199
 
200
#endif /* not ONLY_DECLARE_RELOCS */
201
 
202
#define RTYPE2HOWTO(internal, relocentry) \
203
  m68k_rtype2howto(internal, (relocentry)->r_type)
204
 
205
#define SELECT_RELOC(external, internal) \
206
  external.r_type = m68k_howto2rtype (internal)
207
 
208
#define coff_bfd_reloc_type_lookup m68k_reloc_type_lookup
209
 
210
#ifndef COFF_COMMON_ADDEND
211
#ifndef coff_rtype_to_howto
212
 
213
#define coff_rtype_to_howto m68kcoff_rtype_to_howto
214
 
215
static reloc_howto_type *m68kcoff_rtype_to_howto
216
  PARAMS ((bfd *, asection *, struct internal_reloc *,
217
           struct coff_link_hash_entry *, struct internal_syment *,
218
           bfd_vma *));
219
 
220
static reloc_howto_type *
221
m68kcoff_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
222
     bfd *abfd ATTRIBUTE_UNUSED;
223
     asection *sec;
224
     struct internal_reloc *rel;
225
     struct coff_link_hash_entry *h ATTRIBUTE_UNUSED;
226
     struct internal_syment *sym ATTRIBUTE_UNUSED;
227
     bfd_vma *addendp;
228
{
229
  arelent relent;
230
  reloc_howto_type *howto;
231
 
232
  RTYPE2HOWTO (&relent, rel);
233
 
234
  howto = relent.howto;
235
 
236
  if (howto->pc_relative)
237
    *addendp += sec->vma;
238
 
239
  return howto;
240
}
241
 
242
#endif /* ! defined (coff_rtype_to_howto) */
243
#endif /* ! defined (COFF_COMMON_ADDEND) */
244
 
245
#ifdef COFF_COMMON_ADDEND
246
 
247
/* If COFF_COMMON_ADDEND is defined, then when using m68k COFF the
248
   value stored in the .text section for a reference to a common
249
   symbol is the value itself plus any desired offset.  (taken from
250
   work done by Ian Taylor, Cygnus Support, for I386 COFF).  */
251
 
252
/* If we are producing relocateable output, we need to do some
253
   adjustments to the object file that are not done by the
254
   bfd_perform_relocation function.  This function is called by every
255
   reloc type to make any required adjustments.  */
256
 
257
static bfd_reloc_status_type
258
m68kcoff_common_addend_special_fn (abfd, reloc_entry, symbol, data,
259
                                   input_section, output_bfd, error_message)
260
     bfd *abfd;
261
     arelent *reloc_entry;
262
     asymbol *symbol;
263
     PTR data;
264
     asection *input_section ATTRIBUTE_UNUSED;
265
     bfd *output_bfd;
266
     char **error_message ATTRIBUTE_UNUSED;
267
{
268
  symvalue diff;
269
 
270
  if (output_bfd == (bfd *) NULL)
271
    return bfd_reloc_continue;
272
 
273
  if (bfd_is_com_section (symbol->section))
274
    {
275
      /* We are relocating a common symbol.  The current value in the
276
         object file is ORIG + OFFSET, where ORIG is the value of the
277
         common symbol as seen by the object file when it was compiled
278
         (this may be zero if the symbol was undefined) and OFFSET is
279
         the offset into the common symbol (normally zero, but may be
280
         non-zero when referring to a field in a common structure).
281
         ORIG is the negative of reloc_entry->addend, which is set by
282
         the CALC_ADDEND macro below.  We want to replace the value in
283
         the object file with NEW + OFFSET, where NEW is the value of
284
         the common symbol which we are going to put in the final
285
         object file.  NEW is symbol->value.  */
286
      diff = symbol->value + reloc_entry->addend;
287
    }
288
  else
289
    {
290
      /* For some reason bfd_perform_relocation always effectively
291
         ignores the addend for a COFF target when producing
292
         relocateable output.  This seems to be always wrong for 386
293
         COFF, so we handle the addend here instead.  */
294
      diff = reloc_entry->addend;
295
    }
296
 
297
#define DOIT(x) \
298
  x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
299
 
300
  if (diff != 0)
301
    {
302
      reloc_howto_type *howto = reloc_entry->howto;
303
      unsigned char *addr = (unsigned char *) data + reloc_entry->address;
304
 
305
      switch (howto->size)
306
        {
307
        case 0:
308
          {
309
            char x = bfd_get_8 (abfd, addr);
310
            DOIT (x);
311
            bfd_put_8 (abfd, x, addr);
312
          }
313
          break;
314
 
315
        case 1:
316
          {
317
            short x = bfd_get_16 (abfd, addr);
318
            DOIT (x);
319
            bfd_put_16 (abfd, (bfd_vma) x, addr);
320
          }
321
          break;
322
 
323
        case 2:
324
          {
325
            long x = bfd_get_32 (abfd, addr);
326
            DOIT (x);
327
            bfd_put_32 (abfd, (bfd_vma) x, addr);
328
          }
329
          break;
330
 
331
        default:
332
          abort ();
333
        }
334
    }
335
 
336
  /* Now let bfd_perform_relocation finish everything up.  */
337
  return bfd_reloc_continue;
338
}
339
 
340
/* Compute the addend of a reloc.  If the reloc is to a common symbol,
341
   the object file contains the value of the common symbol.  By the
342
   time this is called, the linker may be using a different symbol
343
   from a different object file with a different value.  Therefore, we
344
   hack wildly to locate the original symbol from this file so that we
345
   can make the correct adjustment.  This macro sets coffsym to the
346
   symbol from the original file, and uses it to set the addend value
347
   correctly.  If this is not a common symbol, the usual addend
348
   calculation is done, except that an additional tweak is needed for
349
   PC relative relocs.
350
   FIXME: This macro refers to symbols and asect; these are from the
351
   calling function, not the macro arguments.  */
352
 
353
#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)                \
354
  {                                                             \
355
    coff_symbol_type *coffsym = (coff_symbol_type *) NULL;      \
356
    if (ptr && bfd_asymbol_bfd (ptr) != abfd)                   \
357
      coffsym = (obj_symbols (abfd)                             \
358
                 + (cache_ptr->sym_ptr_ptr - symbols));         \
359
    else if (ptr)                                               \
360
      coffsym = coff_symbol_from (abfd, ptr);                   \
361
    if (coffsym != (coff_symbol_type *) NULL                    \
362
        && coffsym->native->u.syment.n_scnum == 0)               \
363
      cache_ptr->addend = - coffsym->native->u.syment.n_value;  \
364
    else if (ptr && bfd_asymbol_bfd (ptr) == abfd               \
365
             && ptr->section != (asection *) NULL)              \
366
      cache_ptr->addend = - (ptr->section->vma + ptr->value);   \
367
    else                                                        \
368
      cache_ptr->addend = 0;                                     \
369
    if (ptr && (reloc.r_type == R_PCRBYTE                       \
370
                || reloc.r_type == R_PCRWORD                    \
371
                || reloc.r_type == R_PCRLONG))                  \
372
      cache_ptr->addend += asect->vma;                          \
373
  }
374
 
375
#ifndef coff_rtype_to_howto
376
 
377
/* coff-m68k.c uses the special COFF backend linker.  We need to
378
   adjust common symbols.  */
379
 
380
static reloc_howto_type *
381
m68kcoff_common_addend_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
382
     bfd *abfd ATTRIBUTE_UNUSED;
383
     asection *sec;
384
     struct internal_reloc *rel;
385
     struct coff_link_hash_entry *h;
386
     struct internal_syment *sym;
387
     bfd_vma *addendp;
388
{
389
  arelent relent;
390
  reloc_howto_type *howto;
391
 
392
  RTYPE2HOWTO (&relent, rel);
393
 
394
  howto = relent.howto;
395
 
396
  if (howto->pc_relative)
397
    *addendp += sec->vma;
398
 
399
  if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
400
    {
401
      /* This is a common symbol.  The section contents include the
402
         size (sym->n_value) as an addend.  The relocate_section
403
         function will be adding in the final value of the symbol.  We
404
         need to subtract out the current size in order to get the
405
         correct result.  */
406
      BFD_ASSERT (h != NULL);
407
      *addendp -= sym->n_value;
408
    }
409
 
410
  /* If the output symbol is common (in which case this must be a
411
     relocateable link), we need to add in the final size of the
412
     common symbol.  */
413
  if (h != NULL && h->root.type == bfd_link_hash_common)
414
    *addendp += h->root.u.c.size;
415
 
416
  return howto;
417
}
418
 
419
#define coff_rtype_to_howto m68kcoff_common_addend_rtype_to_howto
420
 
421
#endif /* ! defined (coff_rtype_to_howto) */
422
 
423
#endif /* COFF_COMMON_ADDEND */
424
 
425
#if !defined ONLY_DECLARE_RELOCS && ! defined STATIC_RELOCS
426
/* Given a .data section and a .emreloc in-memory section, store
427
   relocation information into the .emreloc section which can be
428
   used at runtime to relocate the section.  This is called by the
429
   linker when the --embedded-relocs switch is used.  This is called
430
   after the add_symbols entry point has been called for all the
431
   objects, and before the final_link entry point is called.  */
432
 
433
boolean
434
bfd_m68k_coff_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
435
     bfd *abfd;
436
     struct bfd_link_info *info;
437
     asection *datasec;
438
     asection *relsec;
439
     char **errmsg;
440
{
441
  char *extsyms;
442
  bfd_size_type symesz;
443
  struct internal_reloc *irel, *irelend;
444
  bfd_byte *p;
445
  bfd_size_type amt;
446
 
447
  BFD_ASSERT (! info->relocateable);
448
 
449
  *errmsg = NULL;
450
 
451
  if (datasec->reloc_count == 0)
452
    return true;
453
 
454
  extsyms = obj_coff_external_syms (abfd);
455
  symesz = bfd_coff_symesz (abfd);
456
 
457
  irel = _bfd_coff_read_internal_relocs (abfd, datasec, true, NULL, false,
458
                                         NULL);
459
  irelend = irel + datasec->reloc_count;
460
 
461
  amt = (bfd_size_type) datasec->reloc_count * 12;
462
  relsec->contents = (bfd_byte *) bfd_alloc (abfd, amt);
463
  if (relsec->contents == NULL)
464
    return false;
465
 
466
  p = relsec->contents;
467
 
468
  for (; irel < irelend; irel++, p += 12)
469
    {
470
      asection *targetsec;
471
 
472
      /* We are going to write a four byte longword into the runtime
473
       reloc section.  The longword will be the address in the data
474
       section which must be relocated.  It is followed by the name
475
       of the target section NUL-padded or truncated to 8
476
       characters.  */
477
 
478
      /* We can only relocate absolute longword relocs at run time.  */
479
      if (irel->r_type != R_RELLONG)
480
        {
481
          *errmsg = _("unsupported reloc type");
482
          bfd_set_error (bfd_error_bad_value);
483
          return false;
484
        }
485
 
486
      if (irel->r_symndx == -1)
487
        targetsec = bfd_abs_section_ptr;
488
      else
489
        {
490
          struct coff_link_hash_entry *h;
491
 
492
          h = obj_coff_sym_hashes (abfd)[irel->r_symndx];
493
          if (h == NULL)
494
            {
495
              struct internal_syment isym;
496
 
497
              bfd_coff_swap_sym_in (abfd, extsyms + symesz * irel->r_symndx,
498
                                    &isym);
499
              targetsec = coff_section_from_bfd_index (abfd, isym.n_scnum);
500
            }
501
          else if (h->root.type == bfd_link_hash_defined
502
                   || h->root.type == bfd_link_hash_defweak)
503
            targetsec = h->root.u.def.section;
504
          else
505
            targetsec = NULL;
506
        }
507
 
508
      bfd_put_32 (abfd,
509
                  (irel->r_vaddr - datasec->vma + datasec->output_offset), p);
510
      memset (p + 4, 0, 8);
511
      if (targetsec != NULL)
512
        strncpy (p + 4, targetsec->output_section->name, 8);
513
    }
514
 
515
  return true;
516
}
517
#endif /* neither ONLY_DECLARE_RELOCS not STATIC_RELOCS  */
518
 
519
#define coff_bfd_is_local_label_name m68k_coff_is_local_label_name
520
 
521
#define coff_relocate_section _bfd_coff_generic_relocate_section
522
 
523
#include "coffcode.h"
524
 
525
#ifndef TARGET_SYM
526
#define TARGET_SYM m68kcoff_vec
527
#endif
528
 
529
#ifndef TARGET_NAME
530
#define TARGET_NAME "coff-m68k"
531
#endif
532
 
533
#ifdef NAMES_HAVE_UNDERSCORE
534
CREATE_BIG_COFF_TARGET_VEC (TARGET_SYM, TARGET_NAME, D_PAGED, 0, '_', NULL)
535
#else
536
CREATE_BIG_COFF_TARGET_VEC (TARGET_SYM, TARGET_NAME, D_PAGED, 0, 0, NULL)
537
#endif

powered by: WebSVN 2.1.0

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