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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [coff-x86_64.c] - Blame information for rev 53

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

Line No. Rev Author Line
1 14 khays
/* BFD back-end for AMD 64 COFF files.
2
   Copyright 2006, 2007, 2008, 2009  Free Software Foundation, Inc.
3
 
4
   This file is part of BFD, the Binary File Descriptor library.
5
 
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3 of the License, or
9
   (at your option) any later version.
10
 
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
 
16
   You should have received a copy of the GNU General Public License
17
   along with this program; if not, write to the Free Software
18
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19
   MA 02110-1301, USA.
20
 
21
   Written by Kai Tietz, OneVision Software GmbH&CoKg.  */
22
 
23
#ifndef COFF_WITH_pex64
24
#define COFF_WITH_pex64
25
#endif
26
 
27
/* Note we have to make sure not to include headers twice.
28
   Not all headers are wrapped in #ifdef guards, so we define
29
   PEI_HEADERS to prevent double including here.  */
30
#ifndef PEI_HEADERS
31
#include "sysdep.h"
32
#include "bfd.h"
33
#include "libbfd.h"
34
#include "coff/x86_64.h"
35
#include "coff/internal.h"
36
#include "coff/pe.h"
37
#include "libcoff.h"
38
#include "libiberty.h"
39
#endif
40
 
41
#define BADMAG(x) AMD64BADMAG(x)
42
 
43
#ifdef COFF_WITH_pex64
44
# undef  AOUTSZ
45
# define AOUTSZ         PEPAOUTSZ
46
# define PEAOUTHDR      PEPAOUTHDR
47
#endif
48
 
49
#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
50
 
51
/* The page size is a guess based on ELF.  */
52
 
53
#define COFF_PAGE_SIZE 0x1000
54
 
55
/* For some reason when using AMD COFF the value stored in the .text
56
   section for a reference to a common symbol is the value itself plus
57
   any desired offset.  Ian Taylor, Cygnus Support.  */
58
 
59
/* If we are producing relocatable output, we need to do some
60
   adjustments to the object file that are not done by the
61
   bfd_perform_relocation function.  This function is called by every
62
   reloc type to make any required adjustments.  */
63
 
64
static bfd_reloc_status_type
65
coff_amd64_reloc (bfd *abfd,
66
                  arelent *reloc_entry,
67
                  asymbol *symbol,
68
                  void * data,
69
                  asection *input_section ATTRIBUTE_UNUSED,
70
                  bfd *output_bfd,
71
                  char **error_message ATTRIBUTE_UNUSED)
72
{
73
  symvalue diff;
74
 
75
#if !defined(COFF_WITH_PE)
76
  if (output_bfd == NULL)
77
    return bfd_reloc_continue;
78
#endif
79
 
80
  if (bfd_is_com_section (symbol->section))
81
    {
82
#if !defined(COFF_WITH_PE)
83
      /* We are relocating a common symbol.  The current value in the
84
         object file is ORIG + OFFSET, where ORIG is the value of the
85
         common symbol as seen by the object file when it was compiled
86
         (this may be zero if the symbol was undefined) and OFFSET is
87
         the offset into the common symbol (normally zero, but may be
88
         non-zero when referring to a field in a common structure).
89
         ORIG is the negative of reloc_entry->addend, which is set by
90
         the CALC_ADDEND macro below.  We want to replace the value in
91
         the object file with NEW + OFFSET, where NEW is the value of
92
         the common symbol which we are going to put in the final
93
         object file.  NEW is symbol->value.  */
94
      diff = symbol->value + reloc_entry->addend;
95
#else
96
      /* In PE mode, we do not offset the common symbol.  */
97
      diff = reloc_entry->addend;
98
#endif
99
    }
100
  else
101
    {
102
      /* For some reason bfd_perform_relocation always effectively
103
         ignores the addend for a COFF target when producing
104
         relocatable output.  This seems to be always wrong for 386
105
         COFF, so we handle the addend here instead.  */
106
#if defined(COFF_WITH_PE)
107
      if (output_bfd == NULL)
108
        {
109
          reloc_howto_type *howto = reloc_entry->howto;
110
 
111
          /* Although PC relative relocations are very similar between
112
             PE and non-PE formats, but they are off by 1 << howto->size
113
             bytes. For the external relocation, PE is very different
114
             from others. See md_apply_fix3 () in gas/config/tc-amd64.c.
115
             When we link PE and non-PE object files together to
116
             generate a non-PE executable, we have to compensate it
117
             here.  */
118
          if(howto->pc_relative && howto->pcrel_offset)
119
            diff = -(1 << howto->size);
120
          else if(symbol->flags & BSF_WEAK)
121
            diff = reloc_entry->addend - symbol->value;
122
          else
123
            diff = -reloc_entry->addend;
124
        }
125
      else
126
#endif
127
        diff = reloc_entry->addend;
128
    }
129
 
130
#if defined(COFF_WITH_PE)
131
  /* FIXME: How should this case be handled?  */
132
  if (reloc_entry->howto->type == R_AMD64_IMAGEBASE
133
      && output_bfd != NULL
134
      && bfd_get_flavour (output_bfd) == bfd_target_coff_flavour)
135
    diff -= pe_data (output_bfd)->pe_opthdr.ImageBase;
136
#endif
137
 
138
#define DOIT(x) \
139
  x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
140
 
141
    if (diff != 0)
142
      {
143
        reloc_howto_type *howto = reloc_entry->howto;
144
        unsigned char *addr = (unsigned char *) data + reloc_entry->address;
145
 
146
        switch (howto->size)
147
          {
148
          case 0:
149
            {
150
              char x = bfd_get_8 (abfd, addr);
151
              DOIT (x);
152
              bfd_put_8 (abfd, x, addr);
153
            }
154
            break;
155
 
156
          case 1:
157
            {
158
              short x = bfd_get_16 (abfd, addr);
159
              DOIT (x);
160
              bfd_put_16 (abfd, (bfd_vma) x, addr);
161
            }
162
            break;
163
 
164
          case 2:
165
            {
166
              long x = bfd_get_32 (abfd, addr);
167
              DOIT (x);
168
              bfd_put_32 (abfd, (bfd_vma) x, addr);
169
            }
170
            break;
171
          case 4:
172
            {
173
              long long x = bfd_get_64 (abfd, addr);
174
              DOIT (x);
175
              bfd_put_64 (abfd, (bfd_vma) x, addr);
176
            }
177
            break;
178
 
179
          default:
180
            abort ();
181
          }
182
      }
183
 
184
  /* Now let bfd_perform_relocation finish everything up.  */
185
  return bfd_reloc_continue;
186
}
187
 
188
#if defined(COFF_WITH_PE)
189
/* Return TRUE if this relocation should appear in the output .reloc
190
   section.  */
191
 
192
static bfd_boolean
193
in_reloc_p (bfd *abfd ATTRIBUTE_UNUSED, reloc_howto_type *howto)
194
{
195
  return ! howto->pc_relative && howto->type != R_AMD64_IMAGEBASE
196
         && howto->type != R_AMD64_SECREL;
197
}
198
#endif /* COFF_WITH_PE */
199
 
200
#ifndef PCRELOFFSET
201
#define PCRELOFFSET TRUE
202
#endif
203
 
204
static reloc_howto_type howto_table[] =
205
{
206
  EMPTY_HOWTO (0),
207
  HOWTO (R_AMD64_DIR64,         /* type  1*/
208
         0,                      /* rightshift */
209
         4,                     /* size (0 = byte, 1 = short, 2 = long, 4 = long long) */
210
         64,                    /* bitsize */
211
         FALSE,                 /* pc_relative */
212
         0,                      /* bitpos */
213
         complain_overflow_bitfield, /* complain_on_overflow */
214
         coff_amd64_reloc,      /* special_function */
215
         "R_X86_64_64",         /* name */
216
         TRUE,                  /* partial_inplace */
217
         0xffffffffffffffffll,  /* src_mask */
218
         0xffffffffffffffffll,  /* dst_mask */
219
         TRUE),                 /* pcrel_offset */
220
  HOWTO (R_AMD64_DIR32,         /* type 2 */
221
         0,                      /* rightshift */
222
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
223
         32,                    /* bitsize */
224
         FALSE,                 /* pc_relative */
225
         0,                      /* bitpos */
226
         complain_overflow_bitfield, /* complain_on_overflow */
227
         coff_amd64_reloc,      /* special_function */
228
         "R_X86_64_32",         /* name */
229
         TRUE,                  /* partial_inplace */
230
         0xffffffff,            /* src_mask */
231
         0xffffffff,            /* dst_mask */
232
         TRUE),                 /* pcrel_offset */
233
  /* PE IMAGE_REL_AMD64_ADDR32NB relocation (3).        */
234
  HOWTO (R_AMD64_IMAGEBASE,     /* 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
         coff_amd64_reloc,      /* special_function */
242
         "rva32",               /* name */
243
         TRUE,                  /* partial_inplace */
244
         0xffffffff,            /* src_mask */
245
         0xffffffff,            /* dst_mask */
246
         FALSE),                /* pcrel_offset */
247
  /* 32-bit longword PC relative relocation (4).  */
248
  HOWTO (R_AMD64_PCRLONG,       /* type 4 */
249
         0,                      /* rightshift */
250
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
251
         32,                    /* bitsize */
252
         TRUE,                  /* pc_relative */
253
         0,                      /* bitpos */
254
         complain_overflow_signed, /* complain_on_overflow */
255
         coff_amd64_reloc,      /* special_function */
256
         "R_X86_64_PC32",       /* name */
257
         TRUE,                  /* partial_inplace */
258
         0xffffffff,            /* src_mask */
259
         0xffffffff,            /* dst_mask */
260
         PCRELOFFSET),          /* pcrel_offset */
261
 
262
 HOWTO (R_AMD64_PCRLONG_1,      /* type 5 */
263
         0,                      /* rightshift */
264
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
265
         32,                    /* bitsize */
266
         TRUE,                  /* pc_relative */
267
         0,                      /* bitpos */
268
         complain_overflow_signed, /* complain_on_overflow */
269
         coff_amd64_reloc,      /* special_function */
270
         "DISP32+1",            /* name */
271
         TRUE,                  /* partial_inplace */
272
         0xffffffff,            /* src_mask */
273
         0xffffffff,            /* dst_mask */
274
         PCRELOFFSET),          /* pcrel_offset */
275
 HOWTO (R_AMD64_PCRLONG_2,      /* type 6 */
276
         0,                      /* rightshift */
277
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
278
         32,                    /* bitsize */
279
         TRUE,                  /* pc_relative */
280
         0,                      /* bitpos */
281
         complain_overflow_signed, /* complain_on_overflow */
282
         coff_amd64_reloc,      /* special_function */
283
         "DISP32+2",            /* name */
284
         TRUE,                  /* partial_inplace */
285
         0xffffffff,            /* src_mask */
286
         0xffffffff,            /* dst_mask */
287
         PCRELOFFSET),          /* pcrel_offset */
288
 HOWTO (R_AMD64_PCRLONG_3,      /* type 7 */
289
         0,                      /* rightshift */
290
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
291
         32,                    /* bitsize */
292
         TRUE,                  /* pc_relative */
293
         0,                      /* bitpos */
294
         complain_overflow_signed, /* complain_on_overflow */
295
         coff_amd64_reloc,      /* special_function */
296
         "DISP32+3",            /* name */
297
         TRUE,                  /* partial_inplace */
298
         0xffffffff,            /* src_mask */
299
         0xffffffff,            /* dst_mask */
300
         PCRELOFFSET),          /* pcrel_offset */
301
 HOWTO (R_AMD64_PCRLONG_4,      /* type 8 */
302
         0,                      /* rightshift */
303
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
304
         32,                    /* bitsize */
305
         TRUE,                  /* pc_relative */
306
         0,                      /* bitpos */
307
         complain_overflow_signed, /* complain_on_overflow */
308
         coff_amd64_reloc,      /* special_function */
309
         "DISP32+4",            /* name */
310
         TRUE,                  /* partial_inplace */
311
         0xffffffff,            /* src_mask */
312
         0xffffffff,            /* dst_mask */
313
         PCRELOFFSET),          /* pcrel_offset */
314
 HOWTO (R_AMD64_PCRLONG_5,      /* type 9 */
315
         0,                      /* rightshift */
316
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
317
         32,                    /* bitsize */
318
         TRUE,                  /* pc_relative */
319
         0,                      /* bitpos */
320
         complain_overflow_signed, /* complain_on_overflow */
321
         coff_amd64_reloc,      /* special_function */
322
         "DISP32+5",            /* name */
323
         TRUE,                  /* partial_inplace */
324
         0xffffffff,            /* src_mask */
325
         0xffffffff,            /* dst_mask */
326
         PCRELOFFSET),          /* pcrel_offset */
327
  EMPTY_HOWTO (10), /* R_AMD64_SECTION 10  */
328
#if defined(COFF_WITH_PE)
329
  /* 32-bit longword section relative relocation (11).  */
330
  HOWTO (R_AMD64_SECREL,        /* type */
331
         0,                      /* rightshift */
332
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
333
         32,                    /* bitsize */
334
         FALSE,                 /* pc_relative */
335
         0,                      /* bitpos */
336
         complain_overflow_bitfield, /* complain_on_overflow */
337
         coff_amd64_reloc,      /* special_function */
338
         "secrel32",            /* name */
339
         TRUE,                  /* partial_inplace */
340
         0xffffffff,            /* src_mask */
341
         0xffffffff,            /* dst_mask */
342
         TRUE),                 /* pcrel_offset */
343
#else
344
  EMPTY_HOWTO (11),
345
#endif
346
  EMPTY_HOWTO (12),
347
  EMPTY_HOWTO (13),
348
#ifndef DONT_EXTEND_AMD64
349
  HOWTO (R_AMD64_PCRQUAD,
350
         0,                     /* rightshift */
351
         4,                     /* size (0 = byte, 1 = short, 2 = long) */
352
         64,                    /* bitsize */
353
         TRUE,                  /* pc_relative */
354
         0,                     /* bitpos */
355
         complain_overflow_signed, /* complain_on_overflow */
356
         coff_amd64_reloc,      /* special_function */
357
         "R_X86_64_PC64",       /* name */
358
         TRUE,                  /* partial_inplace */
359
         0xffffffffffffffffll,  /* src_mask */
360
         0xffffffffffffffffll,  /* dst_mask */
361
         PCRELOFFSET),           /* pcrel_offset */
362
#else
363
  EMPTY_HOWTO (14),
364
#endif
365
  /* Byte relocation (15).  */
366
  HOWTO (R_RELBYTE,             /* type */
367
         0,                      /* rightshift */
368
         0,                      /* size (0 = byte, 1 = short, 2 = long) */
369
         8,                     /* bitsize */
370
         FALSE,                 /* pc_relative */
371
         0,                      /* bitpos */
372
         complain_overflow_bitfield, /* complain_on_overflow */
373
         coff_amd64_reloc,      /* special_function */
374
         "R_X86_64_8",          /* name */
375
         TRUE,                  /* partial_inplace */
376
         0x000000ff,            /* src_mask */
377
         0x000000ff,            /* dst_mask */
378
         PCRELOFFSET),          /* pcrel_offset */
379
  /* 16-bit word relocation (16).  */
380
  HOWTO (R_RELWORD,             /* type */
381
         0,                      /* rightshift */
382
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
383
         16,                    /* bitsize */
384
         FALSE,                 /* pc_relative */
385
         0,                      /* bitpos */
386
         complain_overflow_bitfield, /* complain_on_overflow */
387
         coff_amd64_reloc,      /* special_function */
388
         "R_X86_64_16",         /* name */
389
         TRUE,                  /* partial_inplace */
390
         0x0000ffff,            /* src_mask */
391
         0x0000ffff,            /* dst_mask */
392
         PCRELOFFSET),          /* pcrel_offset */
393
  /* 32-bit longword relocation (17).   */
394
  HOWTO (R_RELLONG,             /* type */
395
         0,                      /* rightshift */
396
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
397
         32,                    /* bitsize */
398
         FALSE,                 /* pc_relative */
399
         0,                      /* bitpos */
400
         complain_overflow_bitfield, /* complain_on_overflow */
401
         coff_amd64_reloc,      /* special_function */
402
         "R_X86_64_32S",        /* name */
403
         TRUE,                  /* partial_inplace */
404
         0xffffffff,            /* src_mask */
405
         0xffffffff,            /* dst_mask */
406
         PCRELOFFSET),          /* pcrel_offset */
407
  /* Byte PC relative relocation (18).   */
408
  HOWTO (R_PCRBYTE,             /* type */
409
         0,                      /* rightshift */
410
         0,                      /* size (0 = byte, 1 = short, 2 = long) */
411
         8,                     /* bitsize */
412
         TRUE,                  /* pc_relative */
413
         0,                      /* bitpos */
414
         complain_overflow_signed, /* complain_on_overflow */
415
         coff_amd64_reloc,      /* special_function */
416
         "R_X86_64_PC8",        /* name */
417
         TRUE,                  /* partial_inplace */
418
         0x000000ff,            /* src_mask */
419
         0x000000ff,            /* dst_mask */
420
         PCRELOFFSET),          /* pcrel_offset */
421
  /* 16-bit word PC relative relocation (19).   */
422
  HOWTO (R_PCRWORD,             /* type */
423
         0,                      /* rightshift */
424
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
425
         16,                    /* bitsize */
426
         TRUE,                  /* pc_relative */
427
         0,                      /* bitpos */
428
         complain_overflow_signed, /* complain_on_overflow */
429
         coff_amd64_reloc,      /* special_function */
430
         "R_X86_64_PC16",       /* name */
431
         TRUE,                  /* partial_inplace */
432
         0x0000ffff,            /* src_mask */
433
         0x0000ffff,            /* dst_mask */
434
         PCRELOFFSET),          /* pcrel_offset */
435
  /* 32-bit longword PC relative relocation (20).  */
436
  HOWTO (R_PCRLONG,             /* type */
437
         0,                      /* rightshift */
438
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
439
         32,                    /* bitsize */
440
         TRUE,                  /* pc_relative */
441
         0,                      /* bitpos */
442
         complain_overflow_signed, /* complain_on_overflow */
443
         coff_amd64_reloc,      /* special_function */
444
         "R_X86_64_PC32",       /* name */
445
         TRUE,                  /* partial_inplace */
446
         0xffffffff,            /* src_mask */
447
         0xffffffff,            /* dst_mask */
448
         PCRELOFFSET)           /* pcrel_offset */
449
};
450
 
451
/* Turn a howto into a reloc  nunmber */
452
 
453
#define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
454
#define I386  1                 /* Customize coffcode.h */
455
#define AMD64 1
456
 
457
#define RTYPE2HOWTO(cache_ptr, dst)             \
458
  ((cache_ptr)->howto =                         \
459
   ((dst)->r_type < ARRAY_SIZE (howto_table))   \
460
    ? howto_table + (dst)->r_type               \
461
    : NULL)
462
 
463
/* For 386 COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
464
   library.  On some other COFF targets STYP_BSS is normally
465
   STYP_NOLOAD.  */
466
#define BSS_NOLOAD_IS_SHARED_LIBRARY
467
 
468
/* Compute the addend of a reloc.  If the reloc is to a common symbol,
469
   the object file contains the value of the common symbol.  By the
470
   time this is called, the linker may be using a different symbol
471
   from a different object file with a different value.  Therefore, we
472
   hack wildly to locate the original symbol from this file so that we
473
   can make the correct adjustment.  This macro sets coffsym to the
474
   symbol from the original file, and uses it to set the addend value
475
   correctly.  If this is not a common symbol, the usual addend
476
   calculation is done, except that an additional tweak is needed for
477
   PC relative relocs.
478
   FIXME: This macro refers to symbols and asect; these are from the
479
   calling function, not the macro arguments.  */
480
 
481
#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)                \
482
  {                                                             \
483
    coff_symbol_type *coffsym = NULL;                           \
484
                                                                \
485
    if (ptr && bfd_asymbol_bfd (ptr) != abfd)                   \
486
      coffsym = (obj_symbols (abfd)                             \
487
                 + (cache_ptr->sym_ptr_ptr - symbols));         \
488
    else if (ptr)                                               \
489
      coffsym = coff_symbol_from (abfd, ptr);                   \
490
                                                                \
491
    if (coffsym != NULL                                         \
492
        && coffsym->native->u.syment.n_scnum == 0)               \
493
      cache_ptr->addend = - coffsym->native->u.syment.n_value;  \
494
    else if (ptr && bfd_asymbol_bfd (ptr) == abfd               \
495
             && ptr->section != NULL)                           \
496
      cache_ptr->addend = - (ptr->section->vma + ptr->value);   \
497
    else                                                        \
498
      cache_ptr->addend = 0;                                     \
499
    if (ptr && howto_table[reloc.r_type].pc_relative)           \
500
      cache_ptr->addend += asect->vma;                          \
501
  }
502
 
503
/* We use the special COFF backend linker.  For normal AMD64 COFF, we
504
   can use the generic relocate_section routine.  For PE, we need our
505
   own routine.  */
506
 
507
#if !defined(COFF_WITH_PE)
508
 
509
#define coff_relocate_section _bfd_coff_generic_relocate_section
510
 
511
#else /* COFF_WITH_PE */
512
 
513
/* The PE relocate section routine.  The only difference between this
514
   and the regular routine is that we don't want to do anything for a
515
   relocatable link.  */
516
 
517
static bfd_boolean
518
coff_pe_amd64_relocate_section (bfd *output_bfd,
519
                                struct bfd_link_info *info,
520
                                bfd *input_bfd,
521
                                asection *input_section,
522
                                bfd_byte *contents,
523
                                struct internal_reloc *relocs,
524
                                struct internal_syment *syms,
525
                                asection **sections)
526
{
527
  if (info->relocatable)
528
    return TRUE;
529
 
530
  return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,input_section, contents,relocs, syms, sections);
531
}
532
 
533
#define coff_relocate_section coff_pe_amd64_relocate_section
534
 
535
#endif /* COFF_WITH_PE */
536
 
537
/* Convert an rtype to howto for the COFF backend linker.  */
538
 
539
static reloc_howto_type *
540
coff_amd64_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
541
                           asection *sec,
542
                           struct internal_reloc *rel,
543
                           struct coff_link_hash_entry *h,
544
                           struct internal_syment *sym,
545
                           bfd_vma *addendp)
546
{
547
  reloc_howto_type *howto;
548
 
549
  if (rel->r_type >= ARRAY_SIZE (howto_table))
550
    {
551
      bfd_set_error (bfd_error_bad_value);
552
      return NULL;
553
    }
554
  howto = howto_table + rel->r_type;
555
 
556
#if defined(COFF_WITH_PE)
557
  /* Cancel out code in _bfd_coff_generic_relocate_section.  */
558
  *addendp = 0;
559
  if (rel->r_type >= R_AMD64_PCRLONG_1 && rel->r_type <= R_AMD64_PCRLONG_5)
560
    {
561
      *addendp -= (bfd_vma)(rel->r_type - R_AMD64_PCRLONG);
562
      rel->r_type = R_AMD64_PCRLONG;
563
    }
564
#endif
565
 
566
  if (howto->pc_relative)
567
    *addendp += sec->vma;
568
 
569
  if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
570
    {
571
      /* This is a common symbol.  The section contents include the
572
         size (sym->n_value) as an addend.  The relocate_section
573
         function will be adding in the final value of the symbol.  We
574
         need to subtract out the current size in order to get the
575
         correct result.  */
576
      BFD_ASSERT (h != NULL);
577
 
578
#if !defined(COFF_WITH_PE)
579
      /* I think we *do* want to bypass this.  If we don't, I have
580
         seen some data parameters get the wrong relocation address.
581
         If I link two versions with and without this section bypassed
582
         and then do a binary comparison, the addresses which are
583
         different can be looked up in the map.  The case in which
584
         this section has been bypassed has addresses which correspond
585
         to values I can find in the map.  */
586
      *addendp -= sym->n_value;
587
#endif
588
    }
589
 
590
#if !defined(COFF_WITH_PE)
591
  /* If the output symbol is common (in which case this must be a
592
     relocatable link), we need to add in the final size of the
593
     common symbol.  */
594
  if (h != NULL && h->root.type == bfd_link_hash_common)
595
    *addendp += h->root.u.c.size;
596
#endif
597
 
598
#if defined(COFF_WITH_PE)
599
  if (howto->pc_relative)
600
    {
601
      *addendp -= 4;
602
 
603
      /* If the symbol is defined, then the generic code is going to
604
         add back the symbol value in order to cancel out an
605
         adjustment it made to the addend.  However, we set the addend
606
         to 0 at the start of this function.  We need to adjust here,
607
         to avoid the adjustment the generic code will make.  FIXME:
608
         This is getting a bit hackish.  */
609
      if (sym != NULL && sym->n_scnum != 0)
610
        *addendp -= sym->n_value;
611
    }
612
 
613
  if (rel->r_type == R_AMD64_IMAGEBASE
614
      && (bfd_get_flavour (sec->output_section->owner) == bfd_target_coff_flavour))
615
    *addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
616
 
617
  if (rel->r_type == R_AMD64_SECREL)
618
    {
619
      bfd_vma osect_vma;
620
 
621
      if (h && (h->type == bfd_link_hash_defined || h->type == bfd_link_hash_defweak))
622
        osect_vma = h->root.u.def.section->output_section->vma;
623
      else
624
        {
625
          asection *s;
626
          int i;
627
 
628
          /* Sigh, the only way to get the section to offset against
629
             is to find it the hard way.  */
630
          for (s = abfd->sections, i = 1; i < sym->n_scnum; i++)
631
            s = s->next;
632
 
633
          osect_vma = s->output_section->vma;
634
        }
635
 
636
      *addendp -= osect_vma;
637
    }
638
#endif
639
 
640
  return howto;
641
}
642
 
643
#define coff_bfd_reloc_type_lookup coff_amd64_reloc_type_lookup
644
#define coff_bfd_reloc_name_lookup coff_amd64_reloc_name_lookup
645
 
646
static reloc_howto_type *
647
coff_amd64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
648
{
649
  switch (code)
650
    {
651
    case BFD_RELOC_RVA:
652
      return howto_table + R_AMD64_IMAGEBASE;
653
    case BFD_RELOC_32:
654
      return howto_table + R_AMD64_DIR32;
655
    case BFD_RELOC_64:
656
      return howto_table + R_AMD64_DIR64;
657
    case BFD_RELOC_64_PCREL:
658
#ifndef DONT_EXTEND_AMD64
659
      return howto_table + R_AMD64_PCRQUAD;
660
#else
661
      /* Fall through.  */
662
#endif
663
    case BFD_RELOC_32_PCREL:
664
      return howto_table + R_AMD64_PCRLONG;
665
    case BFD_RELOC_X86_64_32S:
666
      return howto_table + R_RELLONG;
667
    case BFD_RELOC_16:
668
      return howto_table + R_RELWORD;
669
    case BFD_RELOC_16_PCREL:
670
      return howto_table + R_PCRWORD;
671
    case BFD_RELOC_8:
672
      return howto_table + R_RELBYTE;
673
    case BFD_RELOC_8_PCREL:
674
      return howto_table + R_PCRBYTE;
675
#if defined(COFF_WITH_PE)
676
    case BFD_RELOC_32_SECREL:
677
      return howto_table + R_AMD64_SECREL;
678
#endif
679
    default:
680
      BFD_FAIL ();
681
      return 0;
682
    }
683
}
684
 
685
static reloc_howto_type *
686
coff_amd64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
687
                              const char *r_name)
688
{
689
  unsigned int i;
690
 
691
  for (i = 0; i < sizeof (howto_table) / sizeof (howto_table[0]); i++)
692
    if (howto_table[i].name != NULL
693
        && strcasecmp (howto_table[i].name, r_name) == 0)
694
      return &howto_table[i];
695
 
696
  return NULL;
697
}
698
 
699
#define coff_rtype_to_howto coff_amd64_rtype_to_howto
700
 
701
#ifdef TARGET_UNDERSCORE
702
 
703
/* If amd64 gcc uses underscores for symbol names, then it does not use
704
   a leading dot for local labels, so if TARGET_UNDERSCORE is defined
705
   we treat all symbols starting with L as local.  */
706
 
707
static bfd_boolean
708
coff_amd64_is_local_label_name (bfd *abfd, const char *name)
709
{
710
  if (name[0] == 'L')
711
    return TRUE;
712
 
713
  return _bfd_coff_is_local_label_name (abfd, name);
714
}
715
 
716
#define coff_bfd_is_local_label_name coff_amd64_is_local_label_name
717
 
718
#endif /* TARGET_UNDERSCORE */
719
 
720
#ifndef bfd_pe_print_pdata
721
#define bfd_pe_print_pdata   NULL
722
#endif
723
 
724
#include "coffcode.h"
725
 
726
#ifdef PE
727
#define amd64coff_object_p pe_bfd_object_p
728
#else
729
#define amd64coff_object_p coff_object_p
730
#endif
731
 
732
const bfd_target
733
#ifdef TARGET_SYM
734
  TARGET_SYM =
735
#else
736
  x86_64coff_vec =
737
#endif
738
{
739
#ifdef TARGET_NAME
740
  TARGET_NAME,
741
#else
742
 "coff-x86-64",                 /* Name.  */
743
#endif
744
  bfd_target_coff_flavour,
745
  BFD_ENDIAN_LITTLE,            /* Data byte order is little.  */
746
  BFD_ENDIAN_LITTLE,            /* Header byte order is little.  */
747
 
748
  (HAS_RELOC | EXEC_P |         /* Object flags.  */
749
   HAS_LINENO | HAS_DEBUG |
750
   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
751
 
752
  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* Section flags.  */
753
#if defined(COFF_WITH_PE)
754
   | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY
755
#endif
756
   | SEC_CODE | SEC_DATA),
757
 
758
#ifdef TARGET_UNDERSCORE
759
  TARGET_UNDERSCORE,            /* Leading underscore.  */
760
#else
761
  0,                             /* Leading underscore.  */
762
#endif
763
  '/',                          /* Ar_pad_char.  */
764
  15,                           /* Ar_max_namelen.  */
765
 
766
  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
767
     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
768
     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data.  */
769
  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
770
     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
771
     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs.  */
772
 
773
  /* Note that we allow an object file to be treated as a core file as well.  */
774
  { _bfd_dummy_target, amd64coff_object_p, /* BFD_check_format.  */
775
    bfd_generic_archive_p, amd64coff_object_p },
776
  { bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format.  */
777
    bfd_false },
778
  { bfd_false, coff_write_object_contents, /* bfd_write_contents.  */
779
   _bfd_write_archive_contents, bfd_false },
780
 
781
  BFD_JUMP_TABLE_GENERIC (coff),
782
  BFD_JUMP_TABLE_COPY (coff),
783
  BFD_JUMP_TABLE_CORE (_bfd_nocore),
784
  BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
785
  BFD_JUMP_TABLE_SYMBOLS (coff),
786
  BFD_JUMP_TABLE_RELOCS (coff),
787
  BFD_JUMP_TABLE_WRITE (coff),
788
  BFD_JUMP_TABLE_LINK (coff),
789
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
790
 
791
  NULL,
792
 
793
  COFF_SWAP_TABLE
794
};

powered by: WebSVN 2.1.0

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