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