xref: /openbsd-src/gnu/usr.bin/binutils-2.17/bfd/coff-i960.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
1*3d8817e4Smiod /* BFD back-end for Intel 960 COFF files.
2*3d8817e4Smiod    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1997, 1999, 2000, 2001,
3*3d8817e4Smiod    2002, 2003, 2004 Free Software Foundation, Inc.
4*3d8817e4Smiod    Written by Cygnus Support.
5*3d8817e4Smiod 
6*3d8817e4Smiod This file is part of BFD, the Binary File Descriptor library.
7*3d8817e4Smiod 
8*3d8817e4Smiod This program is free software; you can redistribute it and/or modify
9*3d8817e4Smiod it under the terms of the GNU General Public License as published by
10*3d8817e4Smiod the Free Software Foundation; either version 2 of the License, or
11*3d8817e4Smiod (at your option) any later version.
12*3d8817e4Smiod 
13*3d8817e4Smiod This program is distributed in the hope that it will be useful,
14*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
15*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*3d8817e4Smiod GNU General Public License for more details.
17*3d8817e4Smiod 
18*3d8817e4Smiod You should have received a copy of the GNU General Public License
19*3d8817e4Smiod along with this program; if not, write to the Free Software
20*3d8817e4Smiod Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
21*3d8817e4Smiod 
22*3d8817e4Smiod #define I960 1
23*3d8817e4Smiod #define BADMAG(x) I960BADMAG(x)
24*3d8817e4Smiod 
25*3d8817e4Smiod #include "bfd.h"
26*3d8817e4Smiod #include "sysdep.h"
27*3d8817e4Smiod #include "libbfd.h"
28*3d8817e4Smiod #include "coff/i960.h"
29*3d8817e4Smiod #include "coff/internal.h"
30*3d8817e4Smiod #include "libcoff.h"		/* to allow easier abstraction-breaking */
31*3d8817e4Smiod 
32*3d8817e4Smiod static bfd_boolean coff_i960_is_local_label_name
33*3d8817e4Smiod   PARAMS ((bfd *, const char *));
34*3d8817e4Smiod static bfd_reloc_status_type optcall_callback
35*3d8817e4Smiod   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
36*3d8817e4Smiod static bfd_reloc_status_type coff_i960_relocate
37*3d8817e4Smiod   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
38*3d8817e4Smiod static reloc_howto_type *coff_i960_reloc_type_lookup
39*3d8817e4Smiod   PARAMS ((bfd *, bfd_reloc_code_real_type));
40*3d8817e4Smiod static bfd_boolean coff_i960_start_final_link
41*3d8817e4Smiod   PARAMS ((bfd *, struct bfd_link_info *));
42*3d8817e4Smiod static bfd_boolean coff_i960_relocate_section
43*3d8817e4Smiod   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
44*3d8817e4Smiod 	   struct internal_reloc *, struct internal_syment *, asection **));
45*3d8817e4Smiod static bfd_boolean coff_i960_adjust_symndx
46*3d8817e4Smiod   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
47*3d8817e4Smiod 	   struct internal_reloc *, bfd_boolean *));
48*3d8817e4Smiod 
49*3d8817e4Smiod #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
50*3d8817e4Smiod #define COFF_ALIGN_IN_SECTION_HEADER 1
51*3d8817e4Smiod 
52*3d8817e4Smiod #define GET_SCNHDR_ALIGN H_GET_32
53*3d8817e4Smiod #define PUT_SCNHDR_ALIGN H_PUT_32
54*3d8817e4Smiod 
55*3d8817e4Smiod /* The i960 does not support an MMU, so COFF_PAGE_SIZE can be
56*3d8817e4Smiod    arbitrarily small.  */
57*3d8817e4Smiod #define COFF_PAGE_SIZE 1
58*3d8817e4Smiod 
59*3d8817e4Smiod #define COFF_LONG_FILENAMES
60*3d8817e4Smiod 
61*3d8817e4Smiod /* This set of local label names is taken from gas.  */
62*3d8817e4Smiod 
63*3d8817e4Smiod static bfd_boolean
coff_i960_is_local_label_name(abfd,name)64*3d8817e4Smiod coff_i960_is_local_label_name (abfd, name)
65*3d8817e4Smiod      bfd *abfd ATTRIBUTE_UNUSED;
66*3d8817e4Smiod      const char *name;
67*3d8817e4Smiod {
68*3d8817e4Smiod   return (name[0] == 'L'
69*3d8817e4Smiod 	  || (name[0] == '.'
70*3d8817e4Smiod 	      && (name[1] == 'C'
71*3d8817e4Smiod 		  || name[1] == 'I'
72*3d8817e4Smiod 		  || name[1] == '.')));
73*3d8817e4Smiod }
74*3d8817e4Smiod 
75*3d8817e4Smiod /* This is just like the usual CALC_ADDEND, but it includes the
76*3d8817e4Smiod    section VMA for PC relative relocs.  */
77*3d8817e4Smiod #ifndef CALC_ADDEND
78*3d8817e4Smiod #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)                \
79*3d8817e4Smiod   {                                                             \
80*3d8817e4Smiod     coff_symbol_type *coffsym = (coff_symbol_type *) NULL;      \
81*3d8817e4Smiod     if (ptr && bfd_asymbol_bfd (ptr) != abfd)                   \
82*3d8817e4Smiod       coffsym = (obj_symbols (abfd)                             \
83*3d8817e4Smiod                  + (cache_ptr->sym_ptr_ptr - symbols));         \
84*3d8817e4Smiod     else if (ptr)                                               \
85*3d8817e4Smiod       coffsym = coff_symbol_from (abfd, ptr);                   \
86*3d8817e4Smiod     if (coffsym != (coff_symbol_type *) NULL                    \
87*3d8817e4Smiod         && coffsym->native->u.syment.n_scnum == 0)              \
88*3d8817e4Smiod       cache_ptr->addend = 0;                                    \
89*3d8817e4Smiod     else if (ptr && bfd_asymbol_bfd (ptr) == abfd               \
90*3d8817e4Smiod              && ptr->section != (asection *) NULL)              \
91*3d8817e4Smiod       cache_ptr->addend = - (ptr->section->vma + ptr->value);   \
92*3d8817e4Smiod     else                                                        \
93*3d8817e4Smiod       cache_ptr->addend = 0;                                    \
94*3d8817e4Smiod     if (ptr && (reloc.r_type == 25 || reloc.r_type == 27))	\
95*3d8817e4Smiod       cache_ptr->addend += asect->vma;				\
96*3d8817e4Smiod   }
97*3d8817e4Smiod #endif
98*3d8817e4Smiod 
99*3d8817e4Smiod #define CALLS	 0x66003800	/* Template for 'calls' instruction	*/
100*3d8817e4Smiod #define BAL	 0x0b000000	/* Template for 'bal' instruction	*/
101*3d8817e4Smiod #define BAL_MASK 0x00ffffff
102*3d8817e4Smiod 
103*3d8817e4Smiod static bfd_reloc_status_type
optcall_callback(abfd,reloc_entry,symbol_in,data,input_section,ignore_bfd,error_message)104*3d8817e4Smiod optcall_callback (abfd, reloc_entry, symbol_in, data,
105*3d8817e4Smiod 		  input_section, ignore_bfd, error_message)
106*3d8817e4Smiod      bfd *abfd;
107*3d8817e4Smiod      arelent *reloc_entry;
108*3d8817e4Smiod      asymbol *symbol_in;
109*3d8817e4Smiod      PTR data;
110*3d8817e4Smiod      asection *input_section;
111*3d8817e4Smiod      bfd *ignore_bfd ATTRIBUTE_UNUSED;
112*3d8817e4Smiod      char **error_message;
113*3d8817e4Smiod {
114*3d8817e4Smiod   /* This item has already been relocated correctly, but we may be
115*3d8817e4Smiod    * able to patch in yet better code - done by digging out the
116*3d8817e4Smiod    * correct info on this symbol */
117*3d8817e4Smiod   bfd_reloc_status_type result;
118*3d8817e4Smiod   coff_symbol_type *cs = coffsymbol(symbol_in);
119*3d8817e4Smiod 
120*3d8817e4Smiod   /* Don't do anything with symbols which aren't tied up yet,
121*3d8817e4Smiod      except move the reloc.  */
122*3d8817e4Smiod   if (bfd_is_und_section (cs->symbol.section)) {
123*3d8817e4Smiod     reloc_entry->address += input_section->output_offset;
124*3d8817e4Smiod     return bfd_reloc_ok;
125*3d8817e4Smiod   }
126*3d8817e4Smiod 
127*3d8817e4Smiod   /* So the target symbol has to be of coff type, and the symbol
128*3d8817e4Smiod      has to have the correct native information within it */
129*3d8817e4Smiod   if ((bfd_asymbol_flavour(&cs->symbol) != bfd_target_coff_flavour)
130*3d8817e4Smiod       || (cs->native == (combined_entry_type *)NULL))
131*3d8817e4Smiod     {
132*3d8817e4Smiod       /* This is interesting, consider the case where we're outputting coff
133*3d8817e4Smiod 	 from a mix n match input, linking from coff to a symbol defined in a
134*3d8817e4Smiod 	 bout file will cause this match to be true. Should I complain?  This
135*3d8817e4Smiod 	 will only work if the bout symbol is non leaf.  */
136*3d8817e4Smiod       *error_message =
137*3d8817e4Smiod 	(char *) _("uncertain calling convention for non-COFF symbol");
138*3d8817e4Smiod       result = bfd_reloc_dangerous;
139*3d8817e4Smiod     }
140*3d8817e4Smiod   else
141*3d8817e4Smiod     {
142*3d8817e4Smiod     switch (cs->native->u.syment.n_sclass)
143*3d8817e4Smiod       {
144*3d8817e4Smiod       case C_LEAFSTAT:
145*3d8817e4Smiod       case C_LEAFEXT:
146*3d8817e4Smiod   	/* This is a call to a leaf procedure, replace instruction with a bal
147*3d8817e4Smiod 	   to the correct location.  */
148*3d8817e4Smiod 	{
149*3d8817e4Smiod 	  union internal_auxent *aux = &((cs->native+2)->u.auxent);
150*3d8817e4Smiod 	  int word = bfd_get_32 (abfd, (bfd_byte *)data + reloc_entry->address);
151*3d8817e4Smiod 	  int olf = (aux->x_bal.x_balntry - cs->native->u.syment.n_value);
152*3d8817e4Smiod 	  BFD_ASSERT(cs->native->u.syment.n_numaux==2);
153*3d8817e4Smiod 
154*3d8817e4Smiod 	  /* We replace the original call instruction with a bal to
155*3d8817e4Smiod 	     the bal entry point - the offset of which is described in
156*3d8817e4Smiod 	     the 2nd auxent of the original symbol. We keep the native
157*3d8817e4Smiod 	     sym and auxents untouched, so the delta between the two
158*3d8817e4Smiod 	     is the offset of the bal entry point.  */
159*3d8817e4Smiod 	  word = ((word +  olf)  & BAL_MASK) | BAL;
160*3d8817e4Smiod   	  bfd_put_32 (abfd, (bfd_vma) word,
161*3d8817e4Smiod 		      (bfd_byte *) data + reloc_entry->address);
162*3d8817e4Smiod   	}
163*3d8817e4Smiod 	result = bfd_reloc_ok;
164*3d8817e4Smiod 	break;
165*3d8817e4Smiod       case C_SCALL:
166*3d8817e4Smiod 	/* This is a call to a system call, replace with a calls to # */
167*3d8817e4Smiod 	BFD_ASSERT(0);
168*3d8817e4Smiod 	result = bfd_reloc_ok;
169*3d8817e4Smiod 	break;
170*3d8817e4Smiod       default:
171*3d8817e4Smiod 	result = bfd_reloc_ok;
172*3d8817e4Smiod 	break;
173*3d8817e4Smiod       }
174*3d8817e4Smiod   }
175*3d8817e4Smiod   return result;
176*3d8817e4Smiod }
177*3d8817e4Smiod 
178*3d8817e4Smiod /* i960 COFF is used by VxWorks 5.1.  However, VxWorks 5.1 does not
179*3d8817e4Smiod    appear to correctly handle a reloc against a symbol defined in the
180*3d8817e4Smiod    same object file.  It appears to simply discard such relocs, rather
181*3d8817e4Smiod    than adding their values into the object file.  We handle this here
182*3d8817e4Smiod    by converting all relocs against defined symbols into relocs
183*3d8817e4Smiod    against the section symbol, when generating a relocatable output
184*3d8817e4Smiod    file.
185*3d8817e4Smiod 
186*3d8817e4Smiod    Note that this function is only called if we are not using the COFF
187*3d8817e4Smiod    specific backend linker.  It only does something when doing a
188*3d8817e4Smiod    relocatable link, which will almost certainly fail when not
189*3d8817e4Smiod    generating COFF i960 output, so this function is actually no longer
190*3d8817e4Smiod    useful.  It was used before this target was converted to use the
191*3d8817e4Smiod    COFF specific backend linker.  */
192*3d8817e4Smiod 
193*3d8817e4Smiod static bfd_reloc_status_type
coff_i960_relocate(abfd,reloc_entry,symbol,data,input_section,output_bfd,error_message)194*3d8817e4Smiod coff_i960_relocate (abfd, reloc_entry, symbol, data, input_section,
195*3d8817e4Smiod 		    output_bfd, error_message)
196*3d8817e4Smiod      bfd *abfd;
197*3d8817e4Smiod      arelent *reloc_entry;
198*3d8817e4Smiod      asymbol *symbol;
199*3d8817e4Smiod      PTR data ATTRIBUTE_UNUSED;
200*3d8817e4Smiod      asection *input_section ATTRIBUTE_UNUSED;
201*3d8817e4Smiod      bfd *output_bfd;
202*3d8817e4Smiod      char **error_message ATTRIBUTE_UNUSED;
203*3d8817e4Smiod {
204*3d8817e4Smiod   asection *osec;
205*3d8817e4Smiod 
206*3d8817e4Smiod   if (output_bfd == NULL)
207*3d8817e4Smiod     {
208*3d8817e4Smiod       /* Not generating relocatable output file.  */
209*3d8817e4Smiod       return bfd_reloc_continue;
210*3d8817e4Smiod     }
211*3d8817e4Smiod 
212*3d8817e4Smiod   if (bfd_is_und_section (bfd_get_section (symbol)))
213*3d8817e4Smiod     {
214*3d8817e4Smiod       /* Symbol is not defined, so no need to worry about it.  */
215*3d8817e4Smiod       return bfd_reloc_continue;
216*3d8817e4Smiod     }
217*3d8817e4Smiod 
218*3d8817e4Smiod   if (bfd_is_com_section (bfd_get_section (symbol)))
219*3d8817e4Smiod     {
220*3d8817e4Smiod       /* I don't really know what the right action is for a common
221*3d8817e4Smiod          symbol.  */
222*3d8817e4Smiod       return bfd_reloc_continue;
223*3d8817e4Smiod     }
224*3d8817e4Smiod 
225*3d8817e4Smiod   /* Convert the reloc to use the section symbol.  FIXME: This method
226*3d8817e4Smiod      is ridiculous.  */
227*3d8817e4Smiod   osec = bfd_get_section (symbol)->output_section;
228*3d8817e4Smiod   if (coff_section_data (output_bfd, osec) != NULL
229*3d8817e4Smiod       && coff_section_data (output_bfd, osec)->tdata != NULL)
230*3d8817e4Smiod     reloc_entry->sym_ptr_ptr =
231*3d8817e4Smiod       (asymbol **) coff_section_data (output_bfd, osec)->tdata;
232*3d8817e4Smiod   else
233*3d8817e4Smiod     {
234*3d8817e4Smiod       const char *sec_name;
235*3d8817e4Smiod       asymbol **syms, **sym_end;
236*3d8817e4Smiod 
237*3d8817e4Smiod       sec_name = bfd_get_section_name (output_bfd, osec);
238*3d8817e4Smiod       syms = bfd_get_outsymbols (output_bfd);
239*3d8817e4Smiod       sym_end = syms + bfd_get_symcount (output_bfd);
240*3d8817e4Smiod       for (; syms < sym_end; syms++)
241*3d8817e4Smiod 	{
242*3d8817e4Smiod 	  if (bfd_asymbol_name (*syms) != NULL
243*3d8817e4Smiod 	      && (*syms)->value == 0
244*3d8817e4Smiod 	      && strcmp ((*syms)->section->output_section->name,
245*3d8817e4Smiod 			 sec_name) == 0)
246*3d8817e4Smiod 	    break;
247*3d8817e4Smiod 	}
248*3d8817e4Smiod 
249*3d8817e4Smiod       if (syms >= sym_end)
250*3d8817e4Smiod 	abort ();
251*3d8817e4Smiod 
252*3d8817e4Smiod       reloc_entry->sym_ptr_ptr = syms;
253*3d8817e4Smiod 
254*3d8817e4Smiod       if (coff_section_data (output_bfd, osec) == NULL)
255*3d8817e4Smiod 	{
256*3d8817e4Smiod 	  bfd_size_type amt = sizeof (struct coff_section_tdata);
257*3d8817e4Smiod 	  osec->used_by_bfd = (PTR) bfd_zalloc (abfd, amt);
258*3d8817e4Smiod 	  if (osec->used_by_bfd == NULL)
259*3d8817e4Smiod 	    return bfd_reloc_overflow;
260*3d8817e4Smiod 	}
261*3d8817e4Smiod       coff_section_data (output_bfd, osec)->tdata = (PTR) syms;
262*3d8817e4Smiod     }
263*3d8817e4Smiod 
264*3d8817e4Smiod   /* Let bfd_perform_relocation do its thing, which will include
265*3d8817e4Smiod      stuffing the symbol addend into the object file.  */
266*3d8817e4Smiod   return bfd_reloc_continue;
267*3d8817e4Smiod }
268*3d8817e4Smiod 
269*3d8817e4Smiod static reloc_howto_type howto_rellong =
270*3d8817e4Smiod   HOWTO ((unsigned int) R_RELLONG, 0, 2, 32,FALSE, 0,
271*3d8817e4Smiod 	 complain_overflow_bitfield, coff_i960_relocate,"rellong", TRUE,
272*3d8817e4Smiod 	 0xffffffff, 0xffffffff, 0);
273*3d8817e4Smiod static reloc_howto_type howto_iprmed =
274*3d8817e4Smiod   HOWTO (R_IPRMED, 0, 2, 24,TRUE,0, complain_overflow_signed,
275*3d8817e4Smiod 	 coff_i960_relocate, "iprmed ", TRUE, 0x00ffffff, 0x00ffffff, 0);
276*3d8817e4Smiod static reloc_howto_type howto_optcall =
277*3d8817e4Smiod   HOWTO (R_OPTCALL, 0,2,24,TRUE,0, complain_overflow_signed,
278*3d8817e4Smiod 	 optcall_callback, "optcall", TRUE, 0x00ffffff, 0x00ffffff, 0);
279*3d8817e4Smiod 
280*3d8817e4Smiod static reloc_howto_type *
coff_i960_reloc_type_lookup(abfd,code)281*3d8817e4Smiod coff_i960_reloc_type_lookup (abfd, code)
282*3d8817e4Smiod      bfd *abfd ATTRIBUTE_UNUSED;
283*3d8817e4Smiod      bfd_reloc_code_real_type code;
284*3d8817e4Smiod {
285*3d8817e4Smiod   switch (code)
286*3d8817e4Smiod     {
287*3d8817e4Smiod     default:
288*3d8817e4Smiod       return 0;
289*3d8817e4Smiod     case BFD_RELOC_I960_CALLJ:
290*3d8817e4Smiod       return &howto_optcall;
291*3d8817e4Smiod     case BFD_RELOC_32:
292*3d8817e4Smiod     case BFD_RELOC_CTOR:
293*3d8817e4Smiod       return &howto_rellong;
294*3d8817e4Smiod     case BFD_RELOC_24_PCREL:
295*3d8817e4Smiod       return &howto_iprmed;
296*3d8817e4Smiod     }
297*3d8817e4Smiod }
298*3d8817e4Smiod 
299*3d8817e4Smiod /* The real code is in coffcode.h */
300*3d8817e4Smiod 
301*3d8817e4Smiod #define RTYPE2HOWTO(cache_ptr, dst) \
302*3d8817e4Smiod {							\
303*3d8817e4Smiod    reloc_howto_type *howto_ptr;				\
304*3d8817e4Smiod    switch ((dst)->r_type) {				\
305*3d8817e4Smiod      case 17: howto_ptr = &howto_rellong; break;	\
306*3d8817e4Smiod      case 25: howto_ptr = &howto_iprmed; break;		\
307*3d8817e4Smiod      case 27: howto_ptr = &howto_optcall; break;	\
308*3d8817e4Smiod      default: howto_ptr = 0; break;			\
309*3d8817e4Smiod      }							\
310*3d8817e4Smiod    (cache_ptr)->howto = howto_ptr;			\
311*3d8817e4Smiod  }
312*3d8817e4Smiod 
313*3d8817e4Smiod /* i960 COFF is used by VxWorks 5.1.  However, VxWorks 5.1 does not
314*3d8817e4Smiod    appear to correctly handle a reloc against a symbol defined in the
315*3d8817e4Smiod    same object file.  It appears to simply discard such relocs, rather
316*3d8817e4Smiod    than adding their values into the object file.  We handle this by
317*3d8817e4Smiod    converting all relocs against global symbols into relocs against
318*3d8817e4Smiod    internal symbols at the start of the section.  This routine is
319*3d8817e4Smiod    called at the start of the linking process, and it creates the
320*3d8817e4Smiod    necessary symbols.  */
321*3d8817e4Smiod 
322*3d8817e4Smiod static bfd_boolean
coff_i960_start_final_link(abfd,info)323*3d8817e4Smiod coff_i960_start_final_link (abfd, info)
324*3d8817e4Smiod      bfd *abfd;
325*3d8817e4Smiod      struct bfd_link_info *info;
326*3d8817e4Smiod {
327*3d8817e4Smiod   bfd_size_type symesz = bfd_coff_symesz (abfd);
328*3d8817e4Smiod   asection *o;
329*3d8817e4Smiod   bfd_byte *esym;
330*3d8817e4Smiod 
331*3d8817e4Smiod   if (! info->relocatable)
332*3d8817e4Smiod     return TRUE;
333*3d8817e4Smiod 
334*3d8817e4Smiod   esym = (bfd_byte *) bfd_malloc (symesz);
335*3d8817e4Smiod   if (esym == NULL)
336*3d8817e4Smiod     return FALSE;
337*3d8817e4Smiod 
338*3d8817e4Smiod   if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0)
339*3d8817e4Smiod     return FALSE;
340*3d8817e4Smiod 
341*3d8817e4Smiod   for (o = abfd->sections; o != NULL; o = o->next)
342*3d8817e4Smiod     {
343*3d8817e4Smiod       struct internal_syment isym;
344*3d8817e4Smiod 
345*3d8817e4Smiod       strncpy (isym._n._n_name, o->name, SYMNMLEN);
346*3d8817e4Smiod       isym.n_value = 0;
347*3d8817e4Smiod       isym.n_scnum = o->target_index;
348*3d8817e4Smiod       isym.n_type = T_NULL;
349*3d8817e4Smiod       isym.n_sclass = C_STAT;
350*3d8817e4Smiod       isym.n_numaux = 0;
351*3d8817e4Smiod 
352*3d8817e4Smiod       bfd_coff_swap_sym_out (abfd, (PTR) &isym, (PTR) esym);
353*3d8817e4Smiod 
354*3d8817e4Smiod       if (bfd_bwrite (esym, symesz, abfd) != symesz)
355*3d8817e4Smiod 	{
356*3d8817e4Smiod 	  free (esym);
357*3d8817e4Smiod 	  return FALSE;
358*3d8817e4Smiod 	}
359*3d8817e4Smiod 
360*3d8817e4Smiod       obj_raw_syment_count (abfd) += 1;
361*3d8817e4Smiod     }
362*3d8817e4Smiod 
363*3d8817e4Smiod   free (esym);
364*3d8817e4Smiod 
365*3d8817e4Smiod   return TRUE;
366*3d8817e4Smiod }
367*3d8817e4Smiod 
368*3d8817e4Smiod /* The reloc processing routine for the optimized COFF linker.  */
369*3d8817e4Smiod 
370*3d8817e4Smiod static bfd_boolean
coff_i960_relocate_section(output_bfd,info,input_bfd,input_section,contents,relocs,syms,sections)371*3d8817e4Smiod coff_i960_relocate_section (output_bfd, info, input_bfd, input_section,
372*3d8817e4Smiod 			    contents, relocs, syms, sections)
373*3d8817e4Smiod      bfd *output_bfd ATTRIBUTE_UNUSED;
374*3d8817e4Smiod      struct bfd_link_info *info;
375*3d8817e4Smiod      bfd *input_bfd;
376*3d8817e4Smiod      asection *input_section;
377*3d8817e4Smiod      bfd_byte *contents;
378*3d8817e4Smiod      struct internal_reloc *relocs;
379*3d8817e4Smiod      struct internal_syment *syms;
380*3d8817e4Smiod      asection **sections;
381*3d8817e4Smiod {
382*3d8817e4Smiod   struct internal_reloc *rel;
383*3d8817e4Smiod   struct internal_reloc *relend;
384*3d8817e4Smiod 
385*3d8817e4Smiod   rel = relocs;
386*3d8817e4Smiod   relend = rel + input_section->reloc_count;
387*3d8817e4Smiod   for (; rel < relend; rel++)
388*3d8817e4Smiod     {
389*3d8817e4Smiod       long symndx;
390*3d8817e4Smiod       struct coff_link_hash_entry *h;
391*3d8817e4Smiod       struct internal_syment *sym;
392*3d8817e4Smiod       bfd_vma addend;
393*3d8817e4Smiod       bfd_vma val;
394*3d8817e4Smiod       reloc_howto_type *howto;
395*3d8817e4Smiod       bfd_reloc_status_type rstat = bfd_reloc_ok;
396*3d8817e4Smiod       bfd_boolean done;
397*3d8817e4Smiod 
398*3d8817e4Smiod       symndx = rel->r_symndx;
399*3d8817e4Smiod 
400*3d8817e4Smiod       if (symndx == -1)
401*3d8817e4Smiod 	{
402*3d8817e4Smiod 	  h = NULL;
403*3d8817e4Smiod 	  sym = NULL;
404*3d8817e4Smiod 	}
405*3d8817e4Smiod       else
406*3d8817e4Smiod 	{
407*3d8817e4Smiod 	  h = obj_coff_sym_hashes (input_bfd)[symndx];
408*3d8817e4Smiod 	  sym = syms + symndx;
409*3d8817e4Smiod 	}
410*3d8817e4Smiod 
411*3d8817e4Smiod       if (sym != NULL && sym->n_scnum != 0)
412*3d8817e4Smiod 	addend = - sym->n_value;
413*3d8817e4Smiod       else
414*3d8817e4Smiod 	addend = 0;
415*3d8817e4Smiod 
416*3d8817e4Smiod       switch (rel->r_type)
417*3d8817e4Smiod 	{
418*3d8817e4Smiod 	case 17: howto = &howto_rellong; break;
419*3d8817e4Smiod 	case 25: howto = &howto_iprmed; break;
420*3d8817e4Smiod 	case 27: howto = &howto_optcall; break;
421*3d8817e4Smiod 	default:
422*3d8817e4Smiod 	  bfd_set_error (bfd_error_bad_value);
423*3d8817e4Smiod 	  return FALSE;
424*3d8817e4Smiod 	}
425*3d8817e4Smiod 
426*3d8817e4Smiod       val = 0;
427*3d8817e4Smiod 
428*3d8817e4Smiod       if (h == NULL)
429*3d8817e4Smiod 	{
430*3d8817e4Smiod 	  asection *sec;
431*3d8817e4Smiod 
432*3d8817e4Smiod 	  if (symndx == -1)
433*3d8817e4Smiod 	    {
434*3d8817e4Smiod 	      sec = bfd_abs_section_ptr;
435*3d8817e4Smiod 	      val = 0;
436*3d8817e4Smiod 	    }
437*3d8817e4Smiod 	  else
438*3d8817e4Smiod 	    {
439*3d8817e4Smiod 	      sec = sections[symndx];
440*3d8817e4Smiod               val = (sec->output_section->vma
441*3d8817e4Smiod 		     + sec->output_offset
442*3d8817e4Smiod 		     + sym->n_value
443*3d8817e4Smiod 		     - sec->vma);
444*3d8817e4Smiod 	    }
445*3d8817e4Smiod 	}
446*3d8817e4Smiod       else
447*3d8817e4Smiod 	{
448*3d8817e4Smiod 	  if (h->root.type == bfd_link_hash_defined
449*3d8817e4Smiod 	      || h->root.type == bfd_link_hash_defweak)
450*3d8817e4Smiod 	    {
451*3d8817e4Smiod 	      asection *sec;
452*3d8817e4Smiod 
453*3d8817e4Smiod 	      sec = h->root.u.def.section;
454*3d8817e4Smiod 	      val = (h->root.u.def.value
455*3d8817e4Smiod 		     + sec->output_section->vma
456*3d8817e4Smiod 		     + sec->output_offset);
457*3d8817e4Smiod 	    }
458*3d8817e4Smiod 	  else if (! info->relocatable)
459*3d8817e4Smiod 	    {
460*3d8817e4Smiod 	      if (! ((*info->callbacks->undefined_symbol)
461*3d8817e4Smiod 		     (info, h->root.root.string, input_bfd, input_section,
462*3d8817e4Smiod 		      rel->r_vaddr - input_section->vma, TRUE)))
463*3d8817e4Smiod 		return FALSE;
464*3d8817e4Smiod 	    }
465*3d8817e4Smiod 	}
466*3d8817e4Smiod 
467*3d8817e4Smiod       done = FALSE;
468*3d8817e4Smiod 
469*3d8817e4Smiod       if (howto->type == R_OPTCALL && ! info->relocatable && symndx != -1)
470*3d8817e4Smiod 	{
471*3d8817e4Smiod 	  int class;
472*3d8817e4Smiod 
473*3d8817e4Smiod 	  if (h != NULL)
474*3d8817e4Smiod 	    class = h->class;
475*3d8817e4Smiod 	  else
476*3d8817e4Smiod 	    class = sym->n_sclass;
477*3d8817e4Smiod 
478*3d8817e4Smiod 	  switch (class)
479*3d8817e4Smiod 	    {
480*3d8817e4Smiod 	    case C_NULL:
481*3d8817e4Smiod 	      /* This symbol is apparently not from a COFF input file.
482*3d8817e4Smiod                  We warn, and then assume that it is not a leaf
483*3d8817e4Smiod                  function.  */
484*3d8817e4Smiod 	      if (! ((*info->callbacks->reloc_dangerous)
485*3d8817e4Smiod 		     (info,
486*3d8817e4Smiod 		      _("uncertain calling convention for non-COFF symbol"),
487*3d8817e4Smiod 		      input_bfd, input_section,
488*3d8817e4Smiod 		      rel->r_vaddr - input_section->vma)))
489*3d8817e4Smiod 		return FALSE;
490*3d8817e4Smiod 	      break;
491*3d8817e4Smiod 	    case C_LEAFSTAT:
492*3d8817e4Smiod 	    case C_LEAFEXT:
493*3d8817e4Smiod 	      /* This is a call to a leaf procedure; use the bal
494*3d8817e4Smiod                  instruction.  */
495*3d8817e4Smiod 	      {
496*3d8817e4Smiod 		long olf;
497*3d8817e4Smiod 		unsigned long word;
498*3d8817e4Smiod 
499*3d8817e4Smiod 		if (h != NULL)
500*3d8817e4Smiod 		  {
501*3d8817e4Smiod 		    BFD_ASSERT (h->numaux == 2);
502*3d8817e4Smiod 		    olf = h->aux[1].x_bal.x_balntry;
503*3d8817e4Smiod 		  }
504*3d8817e4Smiod 		else
505*3d8817e4Smiod 		  {
506*3d8817e4Smiod 		    bfd_byte *esyms;
507*3d8817e4Smiod 		    union internal_auxent aux;
508*3d8817e4Smiod 
509*3d8817e4Smiod 		    BFD_ASSERT (sym->n_numaux == 2);
510*3d8817e4Smiod 		    esyms = (bfd_byte *) obj_coff_external_syms (input_bfd);
511*3d8817e4Smiod 		    esyms += (symndx + 2) * bfd_coff_symesz (input_bfd);
512*3d8817e4Smiod 		    bfd_coff_swap_aux_in (input_bfd, (PTR) esyms, sym->n_type,
513*3d8817e4Smiod 					  sym->n_sclass, 1, sym->n_numaux,
514*3d8817e4Smiod 					  (PTR) &aux);
515*3d8817e4Smiod 		    olf = aux.x_bal.x_balntry;
516*3d8817e4Smiod 		  }
517*3d8817e4Smiod 
518*3d8817e4Smiod 		word = bfd_get_32 (input_bfd,
519*3d8817e4Smiod 				   (contents
520*3d8817e4Smiod 				    + (rel->r_vaddr - input_section->vma)));
521*3d8817e4Smiod 		word = ((word + olf - val) & BAL_MASK) | BAL;
522*3d8817e4Smiod 		bfd_put_32 (input_bfd,
523*3d8817e4Smiod 			    (bfd_vma) word,
524*3d8817e4Smiod 			    contents + (rel->r_vaddr - input_section->vma));
525*3d8817e4Smiod 		done = TRUE;
526*3d8817e4Smiod 	      }
527*3d8817e4Smiod 	      break;
528*3d8817e4Smiod 	    case C_SCALL:
529*3d8817e4Smiod 	      BFD_ASSERT (0);
530*3d8817e4Smiod 	      break;
531*3d8817e4Smiod 	    }
532*3d8817e4Smiod 	}
533*3d8817e4Smiod 
534*3d8817e4Smiod       if (! done)
535*3d8817e4Smiod 	{
536*3d8817e4Smiod 	  if (howto->pc_relative)
537*3d8817e4Smiod 	    addend += input_section->vma;
538*3d8817e4Smiod 	  rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
539*3d8817e4Smiod 					    contents,
540*3d8817e4Smiod 					    rel->r_vaddr - input_section->vma,
541*3d8817e4Smiod 					    val, addend);
542*3d8817e4Smiod 	}
543*3d8817e4Smiod 
544*3d8817e4Smiod       switch (rstat)
545*3d8817e4Smiod 	{
546*3d8817e4Smiod 	default:
547*3d8817e4Smiod 	  abort ();
548*3d8817e4Smiod 	case bfd_reloc_ok:
549*3d8817e4Smiod 	  break;
550*3d8817e4Smiod 	case bfd_reloc_overflow:
551*3d8817e4Smiod 	  {
552*3d8817e4Smiod 	    const char *name;
553*3d8817e4Smiod 	    char buf[SYMNMLEN + 1];
554*3d8817e4Smiod 
555*3d8817e4Smiod 	    if (symndx == -1)
556*3d8817e4Smiod 	      name = "*ABS*";
557*3d8817e4Smiod 	    else if (h != NULL)
558*3d8817e4Smiod 	      name = NULL;
559*3d8817e4Smiod 	    else
560*3d8817e4Smiod 	      {
561*3d8817e4Smiod 		name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
562*3d8817e4Smiod 		if (name == NULL)
563*3d8817e4Smiod 		  return FALSE;
564*3d8817e4Smiod 	      }
565*3d8817e4Smiod 
566*3d8817e4Smiod 	    if (! ((*info->callbacks->reloc_overflow)
567*3d8817e4Smiod 		   (info, (h ? &h->root : NULL), name, howto->name,
568*3d8817e4Smiod 		    (bfd_vma) 0, input_bfd, input_section,
569*3d8817e4Smiod 		    rel->r_vaddr - input_section->vma)))
570*3d8817e4Smiod 	      return FALSE;
571*3d8817e4Smiod 	  }
572*3d8817e4Smiod 	}
573*3d8817e4Smiod     }
574*3d8817e4Smiod 
575*3d8817e4Smiod   return TRUE;
576*3d8817e4Smiod }
577*3d8817e4Smiod 
578*3d8817e4Smiod /* Adjust the symbol index of any reloc against a global symbol to
579*3d8817e4Smiod    instead be a reloc against the internal symbol we created specially
580*3d8817e4Smiod    for the section.  */
581*3d8817e4Smiod 
582*3d8817e4Smiod static bfd_boolean
coff_i960_adjust_symndx(obfd,info,ibfd,sec,irel,adjustedp)583*3d8817e4Smiod coff_i960_adjust_symndx (obfd, info, ibfd, sec, irel, adjustedp)
584*3d8817e4Smiod      bfd *obfd ATTRIBUTE_UNUSED;
585*3d8817e4Smiod      struct bfd_link_info *info ATTRIBUTE_UNUSED;
586*3d8817e4Smiod      bfd *ibfd;
587*3d8817e4Smiod      asection *sec ATTRIBUTE_UNUSED;
588*3d8817e4Smiod      struct internal_reloc *irel;
589*3d8817e4Smiod      bfd_boolean *adjustedp;
590*3d8817e4Smiod {
591*3d8817e4Smiod   struct coff_link_hash_entry *h;
592*3d8817e4Smiod 
593*3d8817e4Smiod   *adjustedp = FALSE;
594*3d8817e4Smiod 
595*3d8817e4Smiod   h = obj_coff_sym_hashes (ibfd)[irel->r_symndx];
596*3d8817e4Smiod   if (h == NULL
597*3d8817e4Smiod       || (h->root.type != bfd_link_hash_defined
598*3d8817e4Smiod 	  && h->root.type != bfd_link_hash_defweak))
599*3d8817e4Smiod     return TRUE;
600*3d8817e4Smiod 
601*3d8817e4Smiod   irel->r_symndx = h->root.u.def.section->output_section->target_index - 1;
602*3d8817e4Smiod   *adjustedp = TRUE;
603*3d8817e4Smiod 
604*3d8817e4Smiod   return TRUE;
605*3d8817e4Smiod }
606*3d8817e4Smiod 
607*3d8817e4Smiod #define coff_bfd_is_local_label_name coff_i960_is_local_label_name
608*3d8817e4Smiod 
609*3d8817e4Smiod #define coff_start_final_link coff_i960_start_final_link
610*3d8817e4Smiod 
611*3d8817e4Smiod #define coff_relocate_section coff_i960_relocate_section
612*3d8817e4Smiod 
613*3d8817e4Smiod #define coff_adjust_symndx coff_i960_adjust_symndx
614*3d8817e4Smiod 
615*3d8817e4Smiod #define coff_bfd_reloc_type_lookup coff_i960_reloc_type_lookup
616*3d8817e4Smiod 
617*3d8817e4Smiod #include "coffcode.h"
618*3d8817e4Smiod 
619*3d8817e4Smiod extern const bfd_target icoff_big_vec;
620*3d8817e4Smiod 
621*3d8817e4Smiod CREATE_LITTLE_COFF_TARGET_VEC (icoff_little_vec, "coff-Intel-little", 0, 0, '_', & icoff_big_vec, COFF_SWAP_TABLE)
622*3d8817e4Smiod 
623*3d8817e4Smiod const bfd_target icoff_big_vec =
624*3d8817e4Smiod {
625*3d8817e4Smiod   "coff-Intel-big",		/* name */
626*3d8817e4Smiod   bfd_target_coff_flavour,
627*3d8817e4Smiod   BFD_ENDIAN_LITTLE,		/* data byte order is little */
628*3d8817e4Smiod   BFD_ENDIAN_BIG,		/* header byte order is big */
629*3d8817e4Smiod 
630*3d8817e4Smiod   (HAS_RELOC | EXEC_P |		/* object flags */
631*3d8817e4Smiod    HAS_LINENO | HAS_DEBUG |
632*3d8817e4Smiod    HAS_SYMS | HAS_LOCALS | WP_TEXT),
633*3d8817e4Smiod 
634*3d8817e4Smiod   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
635*3d8817e4Smiod   '_',				/* leading underscore */
636*3d8817e4Smiod   '/',				/* ar_pad_char */
637*3d8817e4Smiod   15,				/* ar_max_namelen */
638*3d8817e4Smiod 
639*3d8817e4Smiod bfd_getl64, bfd_getl_signed_64, bfd_putl64,
640*3d8817e4Smiod      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
641*3d8817e4Smiod      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
642*3d8817e4Smiod bfd_getb64, bfd_getb_signed_64, bfd_putb64,
643*3d8817e4Smiod      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
644*3d8817e4Smiod      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
645*3d8817e4Smiod 
646*3d8817e4Smiod   {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
647*3d8817e4Smiod      bfd_generic_archive_p, _bfd_dummy_target},
648*3d8817e4Smiod   {bfd_false, coff_mkobject,	/* bfd_set_format */
649*3d8817e4Smiod      _bfd_generic_mkarchive, bfd_false},
650*3d8817e4Smiod   {bfd_false, coff_write_object_contents,	/* bfd_write_contents */
651*3d8817e4Smiod      _bfd_write_archive_contents, bfd_false},
652*3d8817e4Smiod 
653*3d8817e4Smiod      BFD_JUMP_TABLE_GENERIC (coff),
654*3d8817e4Smiod      BFD_JUMP_TABLE_COPY (coff),
655*3d8817e4Smiod      BFD_JUMP_TABLE_CORE (_bfd_nocore),
656*3d8817e4Smiod      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
657*3d8817e4Smiod      BFD_JUMP_TABLE_SYMBOLS (coff),
658*3d8817e4Smiod      BFD_JUMP_TABLE_RELOCS (coff),
659*3d8817e4Smiod      BFD_JUMP_TABLE_WRITE (coff),
660*3d8817e4Smiod      BFD_JUMP_TABLE_LINK (coff),
661*3d8817e4Smiod      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
662*3d8817e4Smiod 
663*3d8817e4Smiod   & icoff_little_vec,
664*3d8817e4Smiod 
665*3d8817e4Smiod   COFF_SWAP_TABLE
666*3d8817e4Smiod };
667