-
-
-/* For some reason when using m68k COFF the value stored in the .text
- section for a reference to a common symbol is the value itself plus
- any desired offset. (taken from work done by Ian Taylor, Cygnus Support,
- for I386 COFF). */
-
-/* If we are producing relocateable output, we need to do some
- adjustments to the object file that are not done by the
- bfd_perform_relocation function. This function is called by every
- reloc type to make any required adjustments. */
-
-static bfd_reloc_status_type
-_bfd_m68kaux_special_fn (abfd, reloc_entry, symbol, data, input_section,
- output_bfd, error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section;
- bfd *output_bfd;
- char **error_message;
-{
- symvalue diff;
-
- if (output_bfd == (bfd *) NULL)
- return bfd_reloc_continue;
-
- if (bfd_is_com_section (symbol->section))
- {
- /* We are relocating a common symbol. The current value in the
- object file is ORIG + OFFSET, where ORIG is the value of the
- common symbol as seen by the object file when it was compiled
- (this may be zero if the symbol was undefined) and OFFSET is
- the offset into the common symbol (normally zero, but may be
- non-zero when referring to a field in a common structure).
- ORIG is the negative of reloc_entry->addend, which is set by
- the CALC_ADDEND macro below. We want to replace the value in
- the object file with NEW + OFFSET, where NEW is the value of
- the common symbol which we are going to put in the final
- object file. NEW is symbol->value. */
- diff = symbol->value + reloc_entry->addend;
- }
- else
- {
- /* For some reason bfd_perform_relocation always effectively
- ignores the addend for a COFF target when producing
- relocateable output. This seems to be always wrong for 386
- COFF, so we handle the addend here instead. */
- diff = reloc_entry->addend;
- }
-
-#define DOIT(x) \
- x = ((x & ~howto->dst_mask) | \
- (((x & howto->src_mask) + diff) & howto->dst_mask))
-
- if (diff != 0)
- {
- reloc_howto_type *howto = reloc_entry->howto;
- unsigned char *addr = (unsigned char *) data + reloc_entry->address;
-
- switch (howto->size)
- {
- case 0:
- {
- char x = bfd_get_8 (abfd, addr);
- DOIT (x);
- bfd_put_8 (abfd, x, addr);
- }
- break;
-
- case 1:
- {
- short x = bfd_get_16 (abfd, addr);
- DOIT (x);
- bfd_put_16 (abfd, x, addr);
- }
- break;
-
- case 2:
- {
- long x = bfd_get_32 (abfd, addr);
- DOIT (x);
- bfd_put_32 (abfd, x, addr);
- }
- break;
-
- default:
- abort ();
- }
- }
-
- /* Now let bfd_perform_relocation finish everything up. */
- return bfd_reloc_continue;
-}
-
-
-/* coff-m68k.c uses the special COFF backend linker. We need to
- adjust common symbols. */
-
-/*ARGSUSED*/
-static reloc_howto_type *
-coff_m68k_aux_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
- bfd *abfd;
- asection *sec;
- struct internal_reloc *rel;
- struct coff_link_hash_entry *h;
- struct internal_syment *sym;
- bfd_vma *addendp;
-{
- arelent relent;
- reloc_howto_type *howto;
-
- RTYPE2HOWTO (&relent, rel);
-
- howto = relent.howto;
-
- if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
- {
- /* This is a common symbol. The section contents include the
- size (sym->n_value) as an addend. The relocate_section
- function will be adding in the final value of the symbol. We
- need to subtract out the current size in order to get the
- correct result. */
- BFD_ASSERT (h != NULL);
- *addendp -= sym->n_value;
- }
-
- /* If the output symbol is common (in which case this must be a
- relocateable link), we need to add in the final size of the
- common symbol. */
- if (h != NULL && h->root.type == bfd_link_hash_common)
- *addendp += h->root.u.c.size;
-
- return howto;
-}
-
-