Touches most files in bfd/, so likely will be blamed for everything..
[deliverable/binutils-gdb.git] / bfd / mipsbsd.c
1 /* BFD backend for MIPS BSD (a.out) binaries.
2 Copyright 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
4 Written by Ralph Campbell.
5
6 This file is part of BFD, the Binary File Descriptor library.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 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) \
47 MY(set_arch_mach) (ABFD, N_MACHTYPE (EXEC)); \
48 MY(choose_reloc_size) (ABFD);
49 static void MY(set_arch_mach) PARAMS ((bfd *abfd, unsigned long machtype));
50 static void MY(choose_reloc_size) PARAMS ((bfd *abfd));
51
52 #define MY_write_object_contents MY(write_object_contents)
53 static 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
70 static bfd_reloc_status_type mips_fix_jmp_addr
71 PARAMS ((bfd *, arelent *, struct symbol_cache_entry *, PTR, asection *,
72 bfd *, char **));
73 static reloc_howto_type *MY(reloc_howto_type_lookup)
74 PARAMS ((bfd *, bfd_reloc_code_real_type));
75
76 long MY(canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));
77
78 static void
79 MY(set_arch_mach) (abfd, machtype)
80 bfd *abfd;
81 unsigned long machtype;
82 {
83 enum bfd_architecture arch;
84 unsigned int machine;
85
86 /* Determine the architecture and machine type of the object file. */
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);
106 }
107
108 /* Determine the size of a relocation entry, based on the architecture */
109 static void
110 MY (choose_reloc_size) (abfd)
111 bfd *abfd;
112 {
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 }
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
130 static boolean
131 MY (write_object_contents) (abfd)
132 bfd *abfd;
133 {
134 struct external_exec exec_bytes;
135 struct internal_exec *execp = exec_hdr (abfd);
136
137 /* Magic number, maestro, please! */
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 }
151 break;
152 case bfd_arch_sparc:
153 N_SET_MACHTYPE (*execp, M_SPARC);
154 break;
155 case bfd_arch_i386:
156 N_SET_MACHTYPE (*execp, M_386);
157 break;
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 }
172 break;
173 default:
174 N_SET_MACHTYPE (*execp, M_UNKNOWN);
175 }
176
177 MY (choose_reloc_size) (abfd);
178
179 WRITE_HEADERS (abfd, execp);
180
181 return true;
182 }
183
184 /* MIPS relocation types. */
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
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
199 static bfd_reloc_status_type
200 mips_fix_jmp_addr (abfd, reloc_entry, symbol, data, input_section, output_bfd,
201 error_message)
202 bfd *abfd ATTRIBUTE_UNUSED;
203 arelent *reloc_entry;
204 struct symbol_cache_entry *symbol;
205 PTR data ATTRIBUTE_UNUSED;
206 asection *input_section;
207 bfd *output_bfd;
208 char **error_message ATTRIBUTE_UNUSED;
209 {
210 bfd_vma relocation, pc;
211
212 /* If this is a partial relocation, just continue. */
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
221 /* Work out which section the relocation is targetted at and the
222 initial relocation command value. */
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
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
246 static bfd_reloc_status_type
247 mips_fix_hi16_s PARAMS ((bfd *, arelent *, asymbol *, PTR,
248 asection *, bfd *, char **));
249
250 static bfd_reloc_status_type
251 mips_fix_hi16_s (abfd, reloc_entry, symbol, data, input_section,
252 output_bfd, error_message)
253 bfd *abfd ATTRIBUTE_UNUSED;
254 arelent *reloc_entry;
255 asymbol *symbol;
256 PTR data ATTRIBUTE_UNUSED;
257 asection *input_section ATTRIBUTE_UNUSED;
258 bfd *output_bfd;
259 char **error_message ATTRIBUTE_UNUSED;
260 {
261 bfd_vma relocation;
262
263 /* If this is a partial relocation, just continue. */
264 if (output_bfd != (bfd *)NULL)
265 return bfd_reloc_continue;
266
267 /* If this is an undefined symbol, return error. */
268 if (bfd_is_und_section (symbol->section)
269 && (symbol->flags & BSF_WEAK) == 0)
270 return bfd_reloc_undefined;
271
272 /* Work out which section the relocation is targetted at and the
273 initial relocation command value. */
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
289 static 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
306 static reloc_howto_type *
307 MY(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
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. */
337 long
338 MY(canonicalize_reloc) (abfd, section, relptr, symbols)
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
348 /* If we have already read in the relocation table, return the values. */
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 }
361
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;
368 }
369
370 if (!NAME(aout,slurp_reloc_table) (abfd, section, symbols))
371 return -1;
372 tblptr = section->relocation;
373
374 /* fix up howto entries. */
375 for (count = 0; count++ < section->reloc_count;)
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
386 static const struct aout_backend_data MY(backend_data) = {
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
402 extern const bfd_target aout_mips_big_vec;
403
404 const bfd_target aout_mips_little_vec =
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 */
423 {_bfd_dummy_target, MY_object_p, /* bfd_check_format */
424 bfd_generic_archive_p, MY_core_file_p},
425 {bfd_false, MY_mkobject, /* bfd_set_format */
426 _bfd_generic_mkarchive, bfd_false},
427 {bfd_false, MY_write_object_contents, /* bfd_write_contents */
428 _bfd_write_archive_contents, bfd_false},
429
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),
439
440 & aout_mips_big_vec,
441
442 (PTR) MY_backend_data
443 };
444
445 const bfd_target aout_mips_big_vec =
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 */
464 {_bfd_dummy_target, MY_object_p, /* bfd_check_format */
465 bfd_generic_archive_p, MY_core_file_p},
466 {bfd_false, MY_mkobject, /* bfd_set_format */
467 _bfd_generic_mkarchive, bfd_false},
468 {bfd_false, MY_write_object_contents, /* bfd_write_contents */
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.06314 seconds and 4 git commands to generate.