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