Touches most files in bfd/, so likely will be blamed for everything..
[deliverable/binutils-gdb.git] / bfd / mipsbsd.c
CommitLineData
252b5132 1/* BFD backend for MIPS BSD (a.out) binaries.
e4b17274 2 Copyright 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001
7898deda 3 Free Software Foundation, Inc.
252b5132
RH
4 Written by Ralph Campbell.
5
6This file is part of BFD, the Binary File Descriptor library.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2 of the License, or
11(at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program; if not, write to the Free Software
20Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21
22#define BYTES_IN_WORD 4
23/* #define ENTRY_CAN_BE_ZERO */
24#define N_HEADER_IN_TEXT(x) 1
25#define N_SHARED_LIB(x) 0
26#define N_TXTADDR(x) \
27 (N_MAGIC(x) != ZMAGIC ? (x).a_entry : /* object file or NMAGIC */\
28 TEXT_START_ADDR + EXEC_BYTES_SIZE /* no padding */\
29 )
30#define N_DATADDR(x) (N_TXTADDR(x)+N_TXTSIZE(x))
31#define TEXT_START_ADDR 4096
32#define TARGET_PAGE_SIZE 4096
33#define SEGMENT_SIZE TARGET_PAGE_SIZE
34#define DEFAULT_ARCH bfd_arch_mips
35#define MACHTYPE_OK(mtype) ((mtype) == M_UNKNOWN \
36 || (mtype) == M_MIPS1 || (mtype) == M_MIPS2)
37#define MY_symbol_leading_char '\0'
38
39#define MY(OP) CAT(mipsbsd_,OP)
40
41#include "bfd.h"
42#include "sysdep.h"
43#include "libbfd.h"
44#include "libaout.h"
45
46#define SET_ARCH_MACH(ABFD, EXEC) \
1518639e
KH
47 MY(set_arch_mach) (ABFD, N_MACHTYPE (EXEC)); \
48 MY(choose_reloc_size) (ABFD);
dc810e39 49static void MY(set_arch_mach) PARAMS ((bfd *abfd, unsigned long machtype));
252b5132
RH
50static void MY(choose_reloc_size) PARAMS ((bfd *abfd));
51
52#define MY_write_object_contents MY(write_object_contents)
53static boolean MY(write_object_contents) PARAMS ((bfd *abfd));
54
55/* We can't use MY(x) here because it leads to a recursive call to CAT
56 when expanded inside JUMP_TABLE. */
57#define MY_bfd_reloc_type_lookup mipsbsd_reloc_howto_type_lookup
58#define MY_canonicalize_reloc mipsbsd_canonicalize_reloc
59
60#define MY_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
61#define MY_bfd_link_add_symbols _bfd_generic_link_add_symbols
62#define MY_final_link_callback unused
63#define MY_bfd_final_link _bfd_generic_final_link
64
65#define MY_backend_data &MY(backend_data)
66#define MY_BFD_TARGET
67
68#include "aout-target.h"
69
dc810e39
AM
70static bfd_reloc_status_type mips_fix_jmp_addr
71 PARAMS ((bfd *, arelent *, struct symbol_cache_entry *, PTR, asection *,
72 bfd *, char **));
73static reloc_howto_type *MY(reloc_howto_type_lookup)
74 PARAMS ((bfd *, bfd_reloc_code_real_type));
e4b17274
NC
75
76long MY(canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));
77
252b5132
RH
78static void
79MY(set_arch_mach) (abfd, machtype)
80 bfd *abfd;
dc810e39 81 unsigned long machtype;
252b5132
RH
82{
83 enum bfd_architecture arch;
dc810e39 84 unsigned int machine;
252b5132 85
1518639e 86 /* Determine the architecture and machine type of the object file. */
e4b17274
NC
87 switch (machtype)
88 {
89 case M_MIPS1:
90 arch = bfd_arch_mips;
91 machine = 3000;
92 break;
93
94 case M_MIPS2:
95 arch = bfd_arch_mips;
96 machine = 4000;
97 break;
98
99 default:
100 arch = bfd_arch_obscure;
101 machine = 0;
102 break;
103 }
104
105 bfd_set_arch_mach (abfd, arch, machine);
252b5132
RH
106}
107
108/* Determine the size of a relocation entry, based on the architecture */
109static void
e4b17274 110MY (choose_reloc_size) (abfd)
252b5132
RH
111 bfd *abfd;
112{
e4b17274
NC
113 switch (bfd_get_arch (abfd))
114 {
115 case bfd_arch_sparc:
116 case bfd_arch_a29k:
117 case bfd_arch_mips:
118 obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE;
119 break;
120 default:
121 obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
122 break;
123 }
252b5132
RH
124}
125
126/* Write an object file in BSD a.out format.
127 Section contents have already been written. We write the
128 file header, symbols, and relocation. */
129
130static boolean
e4b17274 131MY (write_object_contents) (abfd)
252b5132
RH
132 bfd *abfd;
133{
134 struct external_exec exec_bytes;
135 struct internal_exec *execp = exec_hdr (abfd);
136
137 /* Magic number, maestro, please! */
e4b17274
NC
138 switch (bfd_get_arch (abfd))
139 {
140 case bfd_arch_m68k:
141 switch (bfd_get_mach (abfd))
142 {
143 case bfd_mach_m68010:
144 N_SET_MACHTYPE (*execp, M_68010);
145 break;
146 default:
147 case bfd_mach_m68020:
148 N_SET_MACHTYPE (*execp, M_68020);
149 break;
150 }
252b5132 151 break;
e4b17274
NC
152 case bfd_arch_sparc:
153 N_SET_MACHTYPE (*execp, M_SPARC);
252b5132 154 break;
e4b17274
NC
155 case bfd_arch_i386:
156 N_SET_MACHTYPE (*execp, M_386);
252b5132 157 break;
e4b17274
NC
158 case bfd_arch_a29k:
159 N_SET_MACHTYPE (*execp, M_29K);
160 break;
161 case bfd_arch_mips:
162 switch (bfd_get_mach (abfd))
163 {
164 case 4000:
165 case 6000:
166 N_SET_MACHTYPE (*execp, M_MIPS2);
167 break;
168 default:
169 N_SET_MACHTYPE (*execp, M_MIPS1);
170 break;
171 }
252b5132 172 break;
e4b17274
NC
173 default:
174 N_SET_MACHTYPE (*execp, M_UNKNOWN);
252b5132 175 }
252b5132 176
e4b17274 177 MY (choose_reloc_size) (abfd);
252b5132 178
e4b17274 179 WRITE_HEADERS (abfd, execp);
252b5132
RH
180
181 return true;
182}
183
e4b17274 184/* MIPS relocation types. */
252b5132
RH
185#define MIPS_RELOC_32 0
186#define MIPS_RELOC_JMP 1
187#define MIPS_RELOC_WDISP16 2
188#define MIPS_RELOC_HI16 3
189#define MIPS_RELOC_HI16_S 4
190#define MIPS_RELOC_LO16 5
191
e4b17274
NC
192/* This is only called when performing a BFD_RELOC_MIPS_JMP relocation.
193 The jump destination address is formed from the upper 4 bits of the
194 "current" program counter concatenated with the jump instruction's
195 26 bit field and two trailing zeros.
196 If the destination address is not in the same segment as the "current"
197 program counter, then we need to signal an error. */
198
252b5132 199static bfd_reloc_status_type
dc810e39
AM
200mips_fix_jmp_addr (abfd, reloc_entry, symbol, data, input_section, output_bfd,
201 error_message)
5f771d47 202 bfd *abfd ATTRIBUTE_UNUSED;
252b5132
RH
203 arelent *reloc_entry;
204 struct symbol_cache_entry *symbol;
5f771d47 205 PTR data ATTRIBUTE_UNUSED;
252b5132
RH
206 asection *input_section;
207 bfd *output_bfd;
dc810e39 208 char **error_message ATTRIBUTE_UNUSED;
252b5132
RH
209{
210 bfd_vma relocation, pc;
1518639e
KH
211
212 /* If this is a partial relocation, just continue. */
252b5132
RH
213 if (output_bfd != (bfd *)NULL)
214 return bfd_reloc_continue;
215
216 /* If this is an undefined symbol, return error */
217 if (bfd_is_und_section (symbol->section)
218 && (symbol->flags & BSF_WEAK) == 0)
219 return bfd_reloc_undefined;
220
e4b17274
NC
221 /* Work out which section the relocation is targetted at and the
222 initial relocation command value. */
252b5132
RH
223 if (bfd_is_com_section (symbol->section))
224 relocation = 0;
225 else
226 relocation = symbol->value;
227
228 relocation += symbol->section->output_section->vma;
229 relocation += symbol->section->output_offset;
230 relocation += reloc_entry->addend;
231
232 pc = input_section->output_section->vma + input_section->output_offset +
233 reloc_entry->address + 4;
234
235 if ((relocation & 0xF0000000) != (pc & 0xF0000000))
236 return bfd_reloc_overflow;
237
238 return bfd_reloc_continue;
239}
240
e4b17274
NC
241/* This is only called when performing a BFD_RELOC_HI16_S relocation.
242 We need to see if bit 15 is set in the result. If it is, we add
243 0x10000 and continue normally. This will compensate for the sign extension
244 when the low bits are added at run time. */
245
252b5132
RH
246static bfd_reloc_status_type
247mips_fix_hi16_s PARAMS ((bfd *, arelent *, asymbol *, PTR,
248 asection *, bfd *, char **));
249
250static bfd_reloc_status_type
251mips_fix_hi16_s (abfd, reloc_entry, symbol, data, input_section,
252 output_bfd, error_message)
5f771d47 253 bfd *abfd ATTRIBUTE_UNUSED;
252b5132
RH
254 arelent *reloc_entry;
255 asymbol *symbol;
5f771d47
ILT
256 PTR data ATTRIBUTE_UNUSED;
257 asection *input_section ATTRIBUTE_UNUSED;
252b5132 258 bfd *output_bfd;
5f771d47 259 char **error_message ATTRIBUTE_UNUSED;
252b5132
RH
260{
261 bfd_vma relocation;
1518639e
KH
262
263 /* If this is a partial relocation, just continue. */
252b5132
RH
264 if (output_bfd != (bfd *)NULL)
265 return bfd_reloc_continue;
266
e4b17274 267 /* If this is an undefined symbol, return error. */
252b5132
RH
268 if (bfd_is_und_section (symbol->section)
269 && (symbol->flags & BSF_WEAK) == 0)
270 return bfd_reloc_undefined;
271
e4b17274
NC
272 /* Work out which section the relocation is targetted at and the
273 initial relocation command value. */
252b5132
RH
274 if (bfd_is_com_section (symbol->section))
275 relocation = 0;
276 else
277 relocation = symbol->value;
278
279 relocation += symbol->section->output_section->vma;
280 relocation += symbol->section->output_offset;
281 relocation += reloc_entry->addend;
282
283 if (relocation & 0x8000)
284 reloc_entry->addend += 0x10000;
285
286 return bfd_reloc_continue;
287}
288
289static reloc_howto_type mips_howto_table_ext[] = {
290 {MIPS_RELOC_32, 0, 2, 32, false, 0, complain_overflow_bitfield, 0,
291 "32", false, 0, 0xffffffff, false},
292 {MIPS_RELOC_JMP, 2, 2, 26, false, 0, complain_overflow_dont,
293 mips_fix_jmp_addr,
294 "MIPS_JMP", false, 0, 0x03ffffff, false},
295 {MIPS_RELOC_WDISP16, 2, 2, 16, true, 0, complain_overflow_signed, 0,
296 "WDISP16", false, 0, 0x0000ffff, false},
297 {MIPS_RELOC_HI16, 16, 2, 16, false, 0, complain_overflow_bitfield, 0,
298 "HI16", false, 0, 0x0000ffff, false},
299 {MIPS_RELOC_HI16_S, 16, 2, 16, false, 0, complain_overflow_bitfield,
300 mips_fix_hi16_s,
301 "HI16_S", false, 0, 0x0000ffff, false},
302 {MIPS_RELOC_LO16, 0, 2, 16, false, 0, complain_overflow_dont, 0,
303 "LO16", false, 0, 0x0000ffff, false},
304};
305
306static reloc_howto_type *
307MY(reloc_howto_type_lookup) (abfd, code)
308 bfd *abfd;
309 bfd_reloc_code_real_type code;
310{
311
312 if (bfd_get_arch (abfd) != bfd_arch_mips)
313 return 0;
314
315 switch (code)
316 {
317 case BFD_RELOC_CTOR:
318 case BFD_RELOC_32:
319 return (&mips_howto_table_ext[MIPS_RELOC_32]);
320 case BFD_RELOC_MIPS_JMP:
321 return (&mips_howto_table_ext[MIPS_RELOC_JMP]);
322 case BFD_RELOC_16_PCREL_S2:
323 return (&mips_howto_table_ext[MIPS_RELOC_WDISP16]);
324 case BFD_RELOC_HI16:
325 return (&mips_howto_table_ext[MIPS_RELOC_HI16]);
326 case BFD_RELOC_HI16_S:
327 return (&mips_howto_table_ext[MIPS_RELOC_HI16_S]);
328 case BFD_RELOC_LO16:
329 return (&mips_howto_table_ext[MIPS_RELOC_LO16]);
330 default:
331 return 0;
332 }
333}
334
e4b17274
NC
335/* This is just like the standard aoutx.h version but we need to do our
336 own mapping of external reloc type values to howto entries. */
252b5132 337long
1518639e 338MY(canonicalize_reloc) (abfd, section, relptr, symbols)
252b5132
RH
339 bfd *abfd;
340 sec_ptr section;
341 arelent **relptr;
342 asymbol **symbols;
343{
344 arelent *tblptr = section->relocation;
345 unsigned int count, c;
346 extern reloc_howto_type NAME(aout,ext_howto_table)[];
347
1518639e 348 /* If we have already read in the relocation table, return the values. */
e4b17274
NC
349 if (section->flags & SEC_CONSTRUCTOR)
350 {
351 arelent_chain *chain = section->constructor_chain;
352
353 for (count = 0; count < section->reloc_count; count++)
354 {
355 *relptr++ = &chain->relent;
356 chain = chain->next;
357 }
358 *relptr = 0;
359 return section->reloc_count;
360 }
252b5132 361
e4b17274
NC
362 if (tblptr && section->reloc_count)
363 {
364 for (count = 0; count++ < section->reloc_count;)
365 *relptr++ = tblptr++;
366 *relptr = 0;
367 return section->reloc_count;
252b5132 368 }
252b5132 369
1518639e 370 if (!NAME(aout,slurp_reloc_table) (abfd, section, symbols))
252b5132
RH
371 return -1;
372 tblptr = section->relocation;
373
e4b17274 374 /* fix up howto entries. */
1518639e 375 for (count = 0; count++ < section->reloc_count;)
252b5132
RH
376 {
377 c = tblptr->howto - NAME(aout,ext_howto_table);
378 tblptr->howto = &mips_howto_table_ext[c];
379
380 *relptr++ = tblptr++;
381 }
382 *relptr = 0;
383 return section->reloc_count;
384}
385
dc810e39 386static const struct aout_backend_data MY(backend_data) = {
252b5132
RH
387 0, /* zmagic contiguous */
388 1, /* text incl header */
389 0, /* entry is text address */
390 0, /* exec_hdr_flags */
391 TARGET_PAGE_SIZE, /* text vma */
392 MY_set_sizes,
393 0, /* text size includes exec header */
394 0, /* add_dynamic_symbols */
395 0, /* add_one_symbol */
396 0, /* link_dynamic_object */
397 0, /* write_dynamic_symbol */
398 0, /* check_dynamic_reloc */
399 0 /* finish_dynamic_link */
400};
401
c3c89269
NC
402extern const bfd_target aout_mips_big_vec;
403
252b5132 404const bfd_target aout_mips_little_vec =
e4b17274
NC
405 {
406 "a.out-mips-little", /* name */
407 bfd_target_aout_flavour,
408 BFD_ENDIAN_LITTLE, /* target byte order (little) */
409 BFD_ENDIAN_LITTLE, /* target headers byte order (little) */
410 (HAS_RELOC | EXEC_P | /* object flags */
411 HAS_LINENO | HAS_DEBUG |
412 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
413 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
414 MY_symbol_leading_char,
415 ' ', /* ar_pad_char */
416 15, /* ar_max_namelen */
417 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
418 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
419 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
420 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
421 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
422 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
252b5132 423 {_bfd_dummy_target, MY_object_p, /* bfd_check_format */
e4b17274 424 bfd_generic_archive_p, MY_core_file_p},
252b5132 425 {bfd_false, MY_mkobject, /* bfd_set_format */
e4b17274 426 _bfd_generic_mkarchive, bfd_false},
252b5132 427 {bfd_false, MY_write_object_contents, /* bfd_write_contents */
e4b17274 428 _bfd_write_archive_contents, bfd_false},
252b5132 429
e4b17274
NC
430 BFD_JUMP_TABLE_GENERIC (MY),
431 BFD_JUMP_TABLE_COPY (MY),
432 BFD_JUMP_TABLE_CORE (MY),
433 BFD_JUMP_TABLE_ARCHIVE (MY),
434 BFD_JUMP_TABLE_SYMBOLS (MY),
435 BFD_JUMP_TABLE_RELOCS (MY),
436 BFD_JUMP_TABLE_WRITE (MY),
437 BFD_JUMP_TABLE_LINK (MY),
438 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
252b5132 439
e4b17274 440 & aout_mips_big_vec,
1518639e 441
e4b17274
NC
442 (PTR) MY_backend_data
443 };
252b5132
RH
444
445const bfd_target aout_mips_big_vec =
e4b17274
NC
446 {
447 "a.out-mips-big", /* name */
448 bfd_target_aout_flavour,
449 BFD_ENDIAN_BIG, /* target byte order (big) */
450 BFD_ENDIAN_BIG, /* target headers byte order (big) */
451 (HAS_RELOC | EXEC_P | /* object flags */
452 HAS_LINENO | HAS_DEBUG |
453 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
454 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
455 MY_symbol_leading_char,
456 ' ', /* ar_pad_char */
457 15, /* ar_max_namelen */
458 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
459 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
460 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
461 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
462 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
463 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
252b5132 464 {_bfd_dummy_target, MY_object_p, /* bfd_check_format */
e4b17274 465 bfd_generic_archive_p, MY_core_file_p},
252b5132 466 {bfd_false, MY_mkobject, /* bfd_set_format */
e4b17274 467 _bfd_generic_mkarchive, bfd_false},
252b5132 468 {bfd_false, MY_write_object_contents, /* bfd_write_contents */
e4b17274
NC
469 _bfd_write_archive_contents, bfd_false},
470
471 BFD_JUMP_TABLE_GENERIC (MY),
472 BFD_JUMP_TABLE_COPY (MY),
473 BFD_JUMP_TABLE_CORE (MY),
474 BFD_JUMP_TABLE_ARCHIVE (MY),
475 BFD_JUMP_TABLE_SYMBOLS (MY),
476 BFD_JUMP_TABLE_RELOCS (MY),
477 BFD_JUMP_TABLE_WRITE (MY),
478 BFD_JUMP_TABLE_LINK (MY),
479 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
480
481 & aout_mips_little_vec,
482
483 (PTR) MY_backend_data
484 };
This page took 0.127618 seconds and 4 git commands to generate.