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 **));
48 static bfd_reloc_status_type
49 coff_arm_reloc (abfd
, reloc_entry
, symbol
, data
, input_section
, output_bfd
,
55 asection
*input_section
;
61 if (output_bfd
== (bfd
*) NULL
)
62 return bfd_reloc_continue
;
64 if (bfd_is_com_section (symbol
->section
))
66 /* We are relocating a common symbol. The current value in the
67 object file is ORIG + OFFSET, where ORIG is the value of the
68 common symbol as seen by the object file when it was compiled
69 (this may be zero if the symbol was undefined) and OFFSET is
70 the offset into the common symbol (normally zero, but may be
71 non-zero when referring to a field in a common structure).
72 ORIG is the negative of reloc_entry->addend, which is set by
73 the CALC_ADDEND macro below. We want to replace the value in
74 the object file with NEW + OFFSET, where NEW is the value of
75 the common symbol which we are going to put in the final
76 object file. NEW is symbol->value. */
77 diff
= symbol
->value
+ reloc_entry
->addend
;
81 /* For some reason bfd_perform_relocation always effectively
82 ignores the addend for a COFF target when producing
83 relocateable output. This seems to be always wrong for 386
84 COFF, so we handle the addend here instead. */
85 diff
= reloc_entry
->addend
;
89 x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
93 reloc_howto_type
*howto
= reloc_entry
->howto
;
94 unsigned char *addr
= (unsigned char *) data
+ reloc_entry
->address
;
100 char x
= bfd_get_8 (abfd
, addr
);
102 bfd_put_8 (abfd
, x
, addr
);
108 short x
= bfd_get_16 (abfd
, addr
);
110 bfd_put_16 (abfd
, x
, addr
);
116 long x
= bfd_get_32 (abfd
, addr
);
118 bfd_put_32 (abfd
, x
, addr
);
127 /* Now let bfd_perform_relocation finish everything up. */
128 return bfd_reloc_continue
;
132 #define PCRELOFFSET true
135 static reloc_howto_type aoutarm_std_reloc_howto
[] =
137 /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */
144 complain_overflow_bitfield
, /* ovf */
145 coff_arm_reloc
, /* sf */
148 0x000000ff, /*read mask */
149 0x000000ff, /* setmask */
150 PCRELOFFSET
/* pcdone */),
157 complain_overflow_bitfield
,
170 complain_overflow_bitfield
,
183 complain_overflow_signed
,
184 aoutarm_fix_pcrel_26
,
196 complain_overflow_signed
,
209 complain_overflow_signed
,
222 complain_overflow_signed
,
235 complain_overflow_signed
,
236 aoutarm_fix_pcrel_26_done
,
249 complain_overflow_bitfield
,
262 complain_overflow_bitfield
,
275 complain_overflow_bitfield
,
286 #define RTYPE2HOWTO(cache_ptr, dst) \
287 (cache_ptr)->howto = aoutarm_std_reloc_howto + (dst)->r_type;
289 static bfd_reloc_status_type
290 aoutarm_fix_pcrel_26_done (abfd
, reloc_entry
, symbol
, data
, input_section
,
291 output_bfd
, error_message
)
293 arelent
*reloc_entry
;
296 asection
*input_section
;
298 char **error_message
;
300 /* This is dead simple at present. */
304 static bfd_reloc_status_type
305 aoutarm_fix_pcrel_26 (abfd
, reloc_entry
, symbol
, data
, input_section
,
306 output_bfd
, error_message
)
308 arelent
*reloc_entry
;
311 asection
*input_section
;
313 char **error_message
;
316 bfd_size_type addr
= reloc_entry
->address
;
317 long target
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ addr
);
318 bfd_reloc_status_type flag
= bfd_reloc_ok
;
320 /* If this is an undefined symbol, return error */
321 if (symbol
->section
== &bfd_und_section
322 && (symbol
->flags
& BSF_WEAK
) == 0)
323 return output_bfd
? bfd_reloc_continue
: bfd_reloc_undefined
;
325 /* If the sections are different, and we are doing a partial relocation,
326 just ignore it for now. */
327 if (symbol
->section
->name
!= input_section
->name
328 && output_bfd
!= (bfd
*)NULL
)
329 return bfd_reloc_continue
;
331 relocation
= (target
& 0x00ffffff) << 2;
332 relocation
= (relocation
^ 0x02000000) - 0x02000000; /* Sign extend */
333 relocation
+= symbol
->value
;
334 relocation
+= symbol
->section
->output_section
->vma
;
335 relocation
+= symbol
->section
->output_offset
;
336 relocation
+= reloc_entry
->addend
;
337 relocation
-= input_section
->output_section
->vma
;
338 relocation
-= input_section
->output_offset
;
341 return bfd_reloc_overflow
;
343 /* Check for overflow */
344 if (relocation
& 0x02000000)
346 if ((relocation
& ~0x03ffffff) != ~0x03ffffff)
347 flag
= bfd_reloc_overflow
;
349 else if (relocation
& ~0x03ffffff)
350 flag
= bfd_reloc_overflow
;
352 target
&= ~0x00ffffff;
353 target
|= (relocation
>> 2) & 0x00ffffff;
354 bfd_put_32 (abfd
, target
, (bfd_byte
*) data
+ addr
);
356 /* Now the ARM magic... Change the reloc type so that it is marked as done.
357 Strictly this is only necessary if we are doing a partial relocation. */
358 reloc_entry
->howto
= &aoutarm_std_reloc_howto
[7];
363 static CONST
struct reloc_howto_struct
*
364 arm_reloc_type_lookup(abfd
,code
)
366 bfd_reloc_code_real_type code
;
368 #define ASTD(i,j) case i: return &aoutarm_std_reloc_howto[j]
369 if (code
== BFD_RELOC_CTOR
)
370 switch (bfd_get_arch_info (abfd
)->bits_per_address
)
375 default: return (CONST
struct reloc_howto_struct
*) 0;
380 ASTD (BFD_RELOC_16
, 1);
381 ASTD (BFD_RELOC_32
, 2);
382 ASTD (BFD_RELOC_ARM_PCREL_BRANCH
, 3);
383 ASTD (BFD_RELOC_8_PCREL
, 4);
384 ASTD (BFD_RELOC_16_PCREL
, 5);
385 ASTD (BFD_RELOC_32_PCREL
, 6);
386 ASTD (BFD_RELOC_RVA
, 11);
387 default: return (CONST
struct reloc_howto_struct
*) 0;
392 #define coff_bfd_reloc_type_lookup arm_reloc_type_lookup
394 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
395 /* The page size is a guess based on ELF. */
396 #define COFF_PAGE_SIZE 0x1000
398 /* For some reason when using arm COFF the value stored in the .text
399 section for a reference to a common symbol is the value itself plus
400 any desired offset. Ian Taylor, Cygnus Support. */
402 /* If we are producing relocateable output, we need to do some
403 adjustments to the object file that are not done by the
404 bfd_perform_relocation function. This function is called by every
405 reloc type to make any required adjustments. */
407 static bfd_reloc_status_type
408 aacoff_arm_reloc (abfd
, reloc_entry
, symbol
, data
, input_section
, output_bfd
,
411 arelent
*reloc_entry
;
414 asection
*input_section
;
416 char **error_message
;
420 if (output_bfd
== (bfd
*) NULL
)
421 return bfd_reloc_continue
;
423 if (bfd_is_com_section (symbol
->section
))
425 /* We are relocating a common symbol. The current value in the
426 object file is ORIG + OFFSET, where ORIG is the value of the
427 common symbol as seen by the object file when it was compiled
428 (this may be zero if the symbol was undefined) and OFFSET is
429 the offset into the common symbol (normally zero, but may be
430 non-zero when referring to a field in a common structure).
431 ORIG is the negative of reloc_entry->addend, which is set by
432 the CALC_ADDEND macro below. We want to replace the value in
433 the object file with NEW + OFFSET, where NEW is the value of
434 the common symbol which we are going to put in the final
435 object file. NEW is symbol->value. */
436 diff
= symbol
->value
+ reloc_entry
->addend
;
440 /* For some reason bfd_perform_relocation always effectively
441 ignores the addend for a COFF target when producing
442 relocateable output. This seems to be always wrong for arm
443 COFF, so we handle the addend here instead. */
444 diff
= reloc_entry
->addend
;
448 x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
452 reloc_howto_type
*howto
= reloc_entry
->howto
;
453 unsigned char *addr
= (unsigned char *) data
+ reloc_entry
->address
;
459 char x
= bfd_get_8 (abfd
, addr
);
461 bfd_put_8 (abfd
, x
, addr
);
467 short x
= bfd_get_16 (abfd
, addr
);
469 bfd_put_16 (abfd
, x
, addr
);
475 long x
= bfd_get_32 (abfd
, addr
);
477 bfd_put_32 (abfd
, x
, addr
);
486 /* Now let bfd_perform_relocation finish everything up. */
487 return bfd_reloc_continue
;
494 /* Turn a howto into a reloc nunmber */
496 #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
497 #define BADMAG(x) ARMBADMAG(x)
498 #define ARM 1 /* Customize coffcode.h */
501 /* On SCO Unix 3.2.2 the native assembler generates two .data
502 sections. We handle that by renaming the second one to .data2. It
503 does no harm to do this for any arm COFF target. */
504 #define TWO_DATA_SECS
506 /* For arm COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
507 library. On some other COFF targets STYP_BSS is normally
509 #define BSS_NOLOAD_IS_SHARED_LIBRARY
512 /* We use the special COFF backend linker. */
513 #define coff_relocate_section _bfd_coff_generic_relocate_section
517 #include "coffcode.h"
519 static const bfd_target
*
523 return coff_object_p(a
);
526 #ifdef TARGET_LITTLE_SYM
527 const bfd_target TARGET_LITTLE_SYM
=
529 TARGET_LITTLE_NAME
, /* name or coff-arm-little */
530 bfd_target_coff_flavour
,
531 false, /* data byte order is little */
532 false, /* header byte order is little */
534 (HAS_RELOC
| EXEC_P
| /* object flags */
535 HAS_LINENO
| HAS_DEBUG
|
536 HAS_SYMS
| HAS_LOCALS
| WP_TEXT
| D_PAGED
),
538 (SEC_HAS_CONTENTS
| SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
), /* section flags */
539 #ifdef TARGET_UNDERSCORE
540 TARGET_UNDERSCORE
, /* leading underscore */
542 0, /* leading underscore */
544 '/', /* ar_pad_char */
545 15, /* ar_max_namelen */
547 2, /* minimum alignment power */
548 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
549 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
550 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
, /* data */
551 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
552 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
553 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
, /* hdrs */
555 /* Note that we allow an object file to be treated as a core file as well. */
556 {_bfd_dummy_target
, i3coff_object_p
, /* bfd_check_format */
557 bfd_generic_archive_p
, i3coff_object_p
},
558 {bfd_false
, coff_mkobject
, _bfd_generic_mkarchive
, /* bfd_set_format */
560 {bfd_false
, coff_write_object_contents
, /* bfd_write_contents */
561 _bfd_write_archive_contents
, bfd_false
},
563 BFD_JUMP_TABLE_GENERIC (coff
),
564 BFD_JUMP_TABLE_COPY (coff
),
565 BFD_JUMP_TABLE_CORE (_bfd_nocore
),
566 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff
),
567 BFD_JUMP_TABLE_SYMBOLS (coff
),
568 BFD_JUMP_TABLE_RELOCS (coff
),
569 BFD_JUMP_TABLE_WRITE (coff
),
570 BFD_JUMP_TABLE_LINK (coff
),
571 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic
),
577 #ifdef TARGET_BIG_SYM
578 const bfd_target TARGET_BIG_SYM
=
580 TARGET_BIG_NAME
, /* name or coff-arm-big */
581 bfd_target_coff_flavour
,
582 true, /* data byte order is big */
583 true, /* header byte order is big */
585 (HAS_RELOC
| EXEC_P
| /* object flags */
586 HAS_LINENO
| HAS_DEBUG
|
587 HAS_SYMS
| HAS_LOCALS
| WP_TEXT
| D_PAGED
),
589 (SEC_HAS_CONTENTS
| SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
), /* section flags */
590 #ifdef TARGET_UNDERSCORE
591 TARGET_UNDERSCORE
, /* leading underscore */
593 0, /* leading underscore */
595 '/', /* ar_pad_char */
596 15, /* ar_max_namelen */
598 2, /* minimum alignment power */
599 bfd_getb64
, bfd_getb_signed_64
, bfd_putb64
,
600 bfd_getb32
, bfd_getb_signed_32
, bfd_putb32
,
601 bfd_getb16
, bfd_getb_signed_16
, bfd_putb16
, /* data */
602 bfd_getb64
, bfd_getb_signed_64
, bfd_putb64
,
603 bfd_getb32
, bfd_getb_signed_32
, bfd_putb32
,
604 bfd_getb16
, bfd_getb_signed_16
, bfd_putb16
, /* hdrs */
606 /* Note that we allow an object file to be treated as a core file as well. */
607 {_bfd_dummy_target
, i3coff_object_p
, /* bfd_check_format */
608 bfd_generic_archive_p
, i3coff_object_p
},
609 {bfd_false
, coff_mkobject
, _bfd_generic_mkarchive
, /* bfd_set_format */
611 {bfd_false
, coff_write_object_contents
, /* bfd_write_contents */
612 _bfd_write_archive_contents
, bfd_false
},
614 BFD_JUMP_TABLE_GENERIC (coff
),
615 BFD_JUMP_TABLE_COPY (coff
),
616 BFD_JUMP_TABLE_CORE (_bfd_nocore
),
617 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff
),
618 BFD_JUMP_TABLE_SYMBOLS (coff
),
619 BFD_JUMP_TABLE_RELOCS (coff
),
620 BFD_JUMP_TABLE_WRITE (coff
),
621 BFD_JUMP_TABLE_LINK (coff
),
622 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic
),