1 /* BFD back-end for Intel arm COFF files.
2 Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3 Written by Cygnus Support.
5 This file is part of BFD, the Binary File Descriptor library.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
28 #include "coff/internal.h"
36 static bfd_reloc_status_type
37 aoutarm_fix_pcrel_26_done
PARAMS ((bfd
*, arelent
*, asymbol
*, PTR
,
38 asection
*, bfd
*, char **));
40 static bfd_reloc_status_type
41 aoutarm_fix_pcrel_26
PARAMS ((bfd
*, arelent
*, asymbol
*, PTR
,
42 asection
*, bfd
*, char **));
45 static bfd_reloc_status_type coff_arm_reloc
46 PARAMS ((bfd
*, arelent
*, asymbol
*, PTR
, asection
*, bfd
*, char **));
49 /* Used by the assembler. */
50 static bfd_reloc_status_type
51 coff_arm_reloc (abfd
, reloc_entry
, symbol
, data
, input_section
, output_bfd
,
57 asection
*input_section
;
62 if (output_bfd
== (bfd
*) NULL
)
63 return bfd_reloc_continue
;
65 if (bfd_is_com_section (symbol
->section
))
67 /* We are relocating a common symbol. The current value in the
68 object file is ORIG + OFFSET, where ORIG is the value of the
69 common symbol as seen by the object file when it was compiled
70 (this may be zero if the symbol was undefined) and OFFSET is
71 the offset into the common symbol (normally zero, but may be
72 non-zero when referring to a field in a common structure).
73 ORIG is the negative of reloc_entry->addend, which is set by
74 the CALC_ADDEND macro below. We want to replace the value in
75 the object file with NEW + OFFSET, where NEW is the value of
76 the common symbol which we are going to put in the final
77 object file. NEW is symbol->value. */
78 diff
= symbol
->value
+ reloc_entry
->addend
;
82 /* For some reason bfd_perform_relocation always effectively
83 ignores the addend for a COFF target when producing
84 relocateable output. This seems to be always wrong for 386
85 COFF, so we handle the addend here instead. */
86 diff
= reloc_entry
->addend
;
90 x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
94 reloc_howto_type
*howto
= reloc_entry
->howto
;
95 unsigned char *addr
= (unsigned char *) data
+ reloc_entry
->address
;
101 char x
= bfd_get_8 (abfd
, addr
);
103 bfd_put_8 (abfd
, x
, addr
);
109 short x
= bfd_get_16 (abfd
, addr
);
111 bfd_put_16 (abfd
, x
, addr
);
117 long x
= bfd_get_32 (abfd
, addr
);
119 bfd_put_32 (abfd
, x
, addr
);
128 /* Now let bfd_perform_relocation finish everything up. */
129 return bfd_reloc_continue
;
133 #define PCRELOFFSET true
136 static reloc_howto_type aoutarm_std_reloc_howto
[] =
138 /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */
145 complain_overflow_bitfield
, /* ovf */
146 coff_arm_reloc
, /* sf */
149 0x000000ff, /*read mask */
150 0x000000ff, /* setmask */
151 PCRELOFFSET
/* pcdone */),
158 complain_overflow_bitfield
,
171 complain_overflow_bitfield
,
184 complain_overflow_signed
,
185 aoutarm_fix_pcrel_26
,
197 complain_overflow_signed
,
210 complain_overflow_signed
,
223 complain_overflow_signed
,
236 complain_overflow_signed
,
237 aoutarm_fix_pcrel_26_done
,
250 complain_overflow_bitfield
,
263 complain_overflow_bitfield
,
276 complain_overflow_bitfield
,
286 #define RTYPE2HOWTO(cache_ptr, dst) \
287 (cache_ptr)->howto = aoutarm_std_reloc_howto + (dst)->r_type;
289 #define coff_rtype_to_howto coff_arm_rtype_to_howto
290 static reloc_howto_type
*
291 coff_arm_rtype_to_howto (abfd
, sec
, rel
, h
, sym
, addendp
)
294 struct internal_reloc
*rel
;
295 struct coff_link_hash_entry
*h
;
296 struct internal_syment
*sym
;
299 reloc_howto_type
*howto
;
301 howto
= aoutarm_std_reloc_howto
+ rel
->r_type
;
303 if (rel
->r_type
== 11)
305 /* Gross, where can I get this from ?? */
306 struct bfd_link_info
*link_info
= coff_data(sec
->output_section
->owner
)->link_info
;
307 *addendp
-= link_info
->pe_info
->image_base
.value
;
312 /* Used by the assembler. */
314 static bfd_reloc_status_type
315 aoutarm_fix_pcrel_26_done (abfd
, reloc_entry
, symbol
, data
, input_section
,
316 output_bfd
, error_message
)
318 arelent
*reloc_entry
;
321 asection
*input_section
;
323 char **error_message
;
325 /* This is dead simple at present. */
329 /* Used by the assembler. */
331 static bfd_reloc_status_type
332 aoutarm_fix_pcrel_26 (abfd
, reloc_entry
, symbol
, data
, input_section
,
333 output_bfd
, error_message
)
335 arelent
*reloc_entry
;
338 asection
*input_section
;
340 char **error_message
;
343 bfd_size_type addr
= reloc_entry
->address
;
344 long target
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ addr
);
345 bfd_reloc_status_type flag
= bfd_reloc_ok
;
347 /* If this is an undefined symbol, return error */
348 if (symbol
->section
== &bfd_und_section
349 && (symbol
->flags
& BSF_WEAK
) == 0)
350 return output_bfd
? bfd_reloc_continue
: bfd_reloc_undefined
;
352 /* If the sections are different, and we are doing a partial relocation,
353 just ignore it for now. */
354 if (symbol
->section
->name
!= input_section
->name
355 && output_bfd
!= (bfd
*)NULL
)
356 return bfd_reloc_continue
;
358 relocation
= (target
& 0x00ffffff) << 2;
359 relocation
= (relocation
^ 0x02000000) - 0x02000000; /* Sign extend */
360 relocation
+= symbol
->value
;
361 relocation
+= symbol
->section
->output_section
->vma
;
362 relocation
+= symbol
->section
->output_offset
;
363 relocation
+= reloc_entry
->addend
;
364 relocation
-= input_section
->output_section
->vma
;
365 relocation
-= input_section
->output_offset
;
368 return bfd_reloc_overflow
;
370 /* Check for overflow */
371 if (relocation
& 0x02000000)
373 if ((relocation
& ~0x03ffffff) != ~0x03ffffff)
374 flag
= bfd_reloc_overflow
;
376 else if (relocation
& ~0x03ffffff)
377 flag
= bfd_reloc_overflow
;
379 target
&= ~0x00ffffff;
380 target
|= (relocation
>> 2) & 0x00ffffff;
381 bfd_put_32 (abfd
, target
, (bfd_byte
*) data
+ addr
);
383 /* Now the ARM magic... Change the reloc type so that it is marked as done.
384 Strictly this is only necessary if we are doing a partial relocation. */
385 reloc_entry
->howto
= &aoutarm_std_reloc_howto
[7];
391 static CONST
struct reloc_howto_struct
*
392 arm_reloc_type_lookup(abfd
,code
)
394 bfd_reloc_code_real_type code
;
396 #define ASTD(i,j) case i: return &aoutarm_std_reloc_howto[j]
397 if (code
== BFD_RELOC_CTOR
)
398 switch (bfd_get_arch_info (abfd
)->bits_per_address
)
403 default: return (CONST
struct reloc_howto_struct
*) 0;
408 ASTD (BFD_RELOC_16
, 1);
409 ASTD (BFD_RELOC_32
, 2);
410 ASTD (BFD_RELOC_ARM_PCREL_BRANCH
, 3);
411 ASTD (BFD_RELOC_8_PCREL
, 4);
412 ASTD (BFD_RELOC_16_PCREL
, 5);
413 ASTD (BFD_RELOC_32_PCREL
, 6);
414 ASTD (BFD_RELOC_RVA
, 11);
415 default: return (CONST
struct reloc_howto_struct
*) 0;
420 #define coff_bfd_reloc_type_lookup arm_reloc_type_lookup
422 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
423 /* The page size is a guess based on ELF. */
424 #define COFF_PAGE_SIZE 0x1000
428 /* Turn a howto into a reloc nunmber */
430 #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
431 #define BADMAG(x) ARMBADMAG(x)
432 #define ARM 1 /* Customize coffcode.h */
435 /* On SCO Unix 3.2.2 the native assembler generates two .data
436 sections. We handle that by renaming the second one to .data2. It
437 does no harm to do this for any arm COFF target. */
438 #define TWO_DATA_SECS
440 /* For arm COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
441 library. On some other COFF targets STYP_BSS is normally
443 #define BSS_NOLOAD_IS_SHARED_LIBRARY
446 /* We use the special COFF backend linker. */
447 #define coff_relocate_section _bfd_coff_generic_relocate_section
449 #include "coffcode.h"
451 static const bfd_target
*
455 return coff_object_p(a
);
458 #ifdef TARGET_LITTLE_SYM
459 const bfd_target TARGET_LITTLE_SYM
=
461 TARGET_LITTLE_NAME
, /* name or coff-arm-little */
462 bfd_target_coff_flavour
,
463 false, /* data byte order is little */
464 false, /* header byte order is little */
466 (HAS_RELOC
| EXEC_P
| /* object flags */
467 HAS_LINENO
| HAS_DEBUG
|
468 HAS_SYMS
| HAS_LOCALS
| WP_TEXT
| D_PAGED
),
470 (SEC_HAS_CONTENTS
| SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
), /* section flags */
471 #ifdef TARGET_UNDERSCORE
472 TARGET_UNDERSCORE
, /* leading underscore */
474 0, /* leading underscore */
476 '/', /* ar_pad_char */
477 15, /* ar_max_namelen */
479 2, /* minimum alignment power */
480 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
481 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
482 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
, /* data */
483 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
484 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
485 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
, /* hdrs */
487 /* Note that we allow an object file to be treated as a core file as well. */
488 {_bfd_dummy_target
, i3coff_object_p
, /* bfd_check_format */
489 bfd_generic_archive_p
, i3coff_object_p
},
490 {bfd_false
, coff_mkobject
, _bfd_generic_mkarchive
, /* bfd_set_format */
492 {bfd_false
, coff_write_object_contents
, /* bfd_write_contents */
493 _bfd_write_archive_contents
, bfd_false
},
495 BFD_JUMP_TABLE_GENERIC (coff
),
496 BFD_JUMP_TABLE_COPY (coff
),
497 BFD_JUMP_TABLE_CORE (_bfd_nocore
),
498 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff
),
499 BFD_JUMP_TABLE_SYMBOLS (coff
),
500 BFD_JUMP_TABLE_RELOCS (coff
),
501 BFD_JUMP_TABLE_WRITE (coff
),
502 BFD_JUMP_TABLE_LINK (coff
),
503 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic
),
509 #ifdef TARGET_BIG_SYM
510 const bfd_target TARGET_BIG_SYM
=
512 TARGET_BIG_NAME
, /* name or coff-arm-big */
513 bfd_target_coff_flavour
,
514 true, /* data byte order is big */
515 true, /* header byte order is big */
517 (HAS_RELOC
| EXEC_P
| /* object flags */
518 HAS_LINENO
| HAS_DEBUG
|
519 HAS_SYMS
| HAS_LOCALS
| WP_TEXT
| D_PAGED
),
521 (SEC_HAS_CONTENTS
| SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
), /* section flags */
522 #ifdef TARGET_UNDERSCORE
523 TARGET_UNDERSCORE
, /* leading underscore */
525 0, /* leading underscore */
527 '/', /* ar_pad_char */
528 15, /* ar_max_namelen */
530 2, /* minimum alignment power */
531 bfd_getb64
, bfd_getb_signed_64
, bfd_putb64
,
532 bfd_getb32
, bfd_getb_signed_32
, bfd_putb32
,
533 bfd_getb16
, bfd_getb_signed_16
, bfd_putb16
, /* data */
534 bfd_getb64
, bfd_getb_signed_64
, bfd_putb64
,
535 bfd_getb32
, bfd_getb_signed_32
, bfd_putb32
,
536 bfd_getb16
, bfd_getb_signed_16
, bfd_putb16
, /* hdrs */
538 /* Note that we allow an object file to be treated as a core file as well. */
539 {_bfd_dummy_target
, i3coff_object_p
, /* bfd_check_format */
540 bfd_generic_archive_p
, i3coff_object_p
},
541 {bfd_false
, coff_mkobject
, _bfd_generic_mkarchive
, /* bfd_set_format */
543 {bfd_false
, coff_write_object_contents
, /* bfd_write_contents */
544 _bfd_write_archive_contents
, bfd_false
},
546 BFD_JUMP_TABLE_GENERIC (coff
),
547 BFD_JUMP_TABLE_COPY (coff
),
548 BFD_JUMP_TABLE_CORE (_bfd_nocore
),
549 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff
),
550 BFD_JUMP_TABLE_SYMBOLS (coff
),
551 BFD_JUMP_TABLE_RELOCS (coff
),
552 BFD_JUMP_TABLE_WRITE (coff
),
553 BFD_JUMP_TABLE_LINK (coff
),
554 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic
),