* configure: Regenerate.
[external/binutils.git] / bfd / mipsbsd.c
1 /* BFD backend for MIPS BSD (a.out) binaries.
2    Copyright 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3    2005, 2007, 2009, 2011, 2012 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
21    MA 02110-1301, USA.  */
22
23
24 /* #define ENTRY_CAN_BE_ZERO */
25 #define N_HEADER_IN_TEXT(x) 1
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 /* Do not "beautify" the CONCAT* macro args.  Traditional C will not
40    remove whitespace added here, and thus will fail to concatenate
41    the tokens.  */
42 #define MY(OP) CONCAT2 (mipsbsd_,OP)
43
44 #include "sysdep.h"
45 #include "bfd.h"
46 #include "libbfd.h"
47 #include "libaout.h"
48
49 #define SET_ARCH_MACH(ABFD, EXEC) \
50   MY(set_arch_mach) (ABFD, N_MACHTYPE (EXEC)); \
51   MY(choose_reloc_size) (ABFD);
52 static void MY(set_arch_mach) (bfd *, unsigned long);
53 static void MY(choose_reloc_size) (bfd *);
54
55 #define MY_write_object_contents MY(write_object_contents)
56 static bfd_boolean MY(write_object_contents) (bfd *);
57
58 /* We can't use MY(x) here because it leads to a recursive call to CONCAT2
59    when expanded inside JUMP_TABLE.  */
60 #define MY_bfd_reloc_type_lookup mipsbsd_reloc_type_lookup
61 #define MY_bfd_reloc_name_lookup mipsbsd_reloc_name_lookup
62 #define MY_canonicalize_reloc mipsbsd_canonicalize_reloc
63
64 #define MY_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
65 #define MY_bfd_link_add_symbols _bfd_generic_link_add_symbols
66 #define MY_final_link_callback unused
67 #define MY_bfd_final_link _bfd_generic_final_link
68
69 #define MY_backend_data &MY(backend_data)
70 #define MY_BFD_TARGET
71
72 #include "aout-target.h"
73
74 static bfd_reloc_status_type mips_fix_jmp_addr
75   (bfd *, arelent *, struct bfd_symbol *, void *, asection *,
76    bfd *, char **);
77
78 long MY(canonicalize_reloc) (bfd *, sec_ptr, arelent **, asymbol **);
79
80 static void
81 MY(set_arch_mach) (bfd *abfd, 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 = bfd_mach_mips3000;
92       break;
93
94     case M_MIPS2:
95       arch = bfd_arch_mips;
96       machine = bfd_mach_mips4000;
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) (bfd *abfd)
111 {
112   switch (bfd_get_arch (abfd))
113     {
114     case bfd_arch_sparc:
115     case bfd_arch_mips:
116       obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE;
117       break;
118     default:
119       obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
120       break;
121     }
122 }
123
124 /* Write an object file in BSD a.out format.
125   Section contents have already been written.  We write the
126   file header, symbols, and relocation.  */
127
128 static bfd_boolean
129 MY (write_object_contents) (bfd *abfd)
130 {
131   struct external_exec exec_bytes;
132   struct internal_exec *execp = exec_hdr (abfd);
133
134   /* Magic number, maestro, please!  */
135   switch (bfd_get_arch (abfd))
136     {
137     case bfd_arch_m68k:
138       switch (bfd_get_mach (abfd))
139         {
140         case bfd_mach_m68010:
141           N_SET_MACHTYPE (*execp, M_68010);
142           break;
143         default:
144         case bfd_mach_m68020:
145           N_SET_MACHTYPE (*execp, M_68020);
146           break;
147         }
148       break;
149     case bfd_arch_sparc:
150       N_SET_MACHTYPE (*execp, M_SPARC);
151       break;
152     case bfd_arch_i386:
153       N_SET_MACHTYPE (*execp, M_386);
154       break;
155     case bfd_arch_mips:
156       switch (bfd_get_mach (abfd))
157         {
158         case bfd_mach_mips4000:
159         case bfd_mach_mips6000:
160           N_SET_MACHTYPE (*execp, M_MIPS2);
161           break;
162         default:
163           N_SET_MACHTYPE (*execp, M_MIPS1);
164           break;
165         }
166       break;
167     default:
168       N_SET_MACHTYPE (*execp, M_UNKNOWN);
169     }
170
171   MY (choose_reloc_size) (abfd);
172
173   WRITE_HEADERS (abfd, execp);
174
175   return TRUE;
176 }
177
178 /* MIPS relocation types.  */
179 #define MIPS_RELOC_32           0
180 #define MIPS_RELOC_JMP          1
181 #define MIPS_RELOC_WDISP16      2
182 #define MIPS_RELOC_HI16         3
183 #define MIPS_RELOC_HI16_S       4
184 #define MIPS_RELOC_LO16         5
185
186 /* This is only called when performing a BFD_RELOC_MIPS_JMP relocation.
187    The jump destination address is formed from the upper 4 bits of the
188    "current" program counter concatenated with the jump instruction's
189    26 bit field and two trailing zeros.
190    If the destination address is not in the same segment as the "current"
191    program counter, then we need to signal an error.  */
192
193 static bfd_reloc_status_type
194 mips_fix_jmp_addr (bfd *abfd ATTRIBUTE_UNUSED,
195                    arelent *reloc_entry,
196                    struct bfd_symbol *symbol,
197                    void * data ATTRIBUTE_UNUSED,
198                    asection *input_section,
199                    bfd *output_bfd,
200                    char **error_message ATTRIBUTE_UNUSED)
201 {
202   bfd_vma relocation, pc;
203
204   /* If this is a partial relocation, just continue.  */
205   if (output_bfd != (bfd *) NULL)
206     return bfd_reloc_continue;
207
208   /* If this is an undefined symbol, return error */
209   if (bfd_is_und_section (symbol->section)
210       && (symbol->flags & BSF_WEAK) == 0)
211     return bfd_reloc_undefined;
212
213   /* Work out which section the relocation is targeted at and the
214      initial relocation command value.  */
215   if (bfd_is_com_section (symbol->section))
216     relocation = 0;
217   else
218     relocation = symbol->value;
219
220   relocation += symbol->section->output_section->vma;
221   relocation += symbol->section->output_offset;
222   relocation += reloc_entry->addend;
223
224   pc = input_section->output_section->vma + input_section->output_offset +
225     reloc_entry->address + 4;
226
227   if ((relocation & 0xF0000000) != (pc & 0xF0000000))
228     return bfd_reloc_overflow;
229
230   return bfd_reloc_continue;
231 }
232
233 /* This is only called when performing a BFD_RELOC_HI16_S relocation.
234    We need to see if bit 15 is set in the result. If it is, we add
235    0x10000 and continue normally. This will compensate for the sign extension
236    when the low bits are added at run time.  */
237
238 static bfd_reloc_status_type
239 mips_fix_hi16_s (bfd *abfd ATTRIBUTE_UNUSED,
240                  arelent *reloc_entry,
241                  asymbol *symbol,
242                  void * data ATTRIBUTE_UNUSED,
243                  asection *input_section ATTRIBUTE_UNUSED,
244                  bfd *output_bfd,
245                  char **error_message ATTRIBUTE_UNUSED)
246 {
247   bfd_vma relocation;
248
249   /* If this is a partial relocation, just continue.  */
250   if (output_bfd != (bfd *)NULL)
251     return bfd_reloc_continue;
252
253   /* If this is an undefined symbol, return error.  */
254   if (bfd_is_und_section (symbol->section)
255       && (symbol->flags & BSF_WEAK) == 0)
256     return bfd_reloc_undefined;
257
258   /* Work out which section the relocation is targeted at and the
259      initial relocation command value.  */
260   if (bfd_is_com_section (symbol->section))
261     relocation = 0;
262   else
263     relocation = symbol->value;
264
265   relocation += symbol->section->output_section->vma;
266   relocation += symbol->section->output_offset;
267   relocation += reloc_entry->addend;
268
269   if (relocation & 0x8000)
270     reloc_entry->addend += 0x10000;
271
272   return bfd_reloc_continue;
273 }
274
275 static reloc_howto_type mips_howto_table_ext[] =
276 {
277   {MIPS_RELOC_32,      0, 2, 32, FALSE, 0,  complain_overflow_bitfield, 0,
278         "32",       FALSE, 0, 0xffffffff, FALSE},
279   {MIPS_RELOC_JMP,     2, 2, 26, FALSE, 0, complain_overflow_dont,
280         mips_fix_jmp_addr,
281         "MIPS_JMP", FALSE, 0, 0x03ffffff, FALSE},
282   {MIPS_RELOC_WDISP16, 2, 2, 16, TRUE,  0, complain_overflow_signed, 0,
283         "WDISP16",  FALSE, 0, 0x0000ffff, FALSE},
284   {MIPS_RELOC_HI16,   16, 2, 16, FALSE, 0, complain_overflow_bitfield, 0,
285         "HI16",     FALSE, 0, 0x0000ffff, FALSE},
286   {MIPS_RELOC_HI16_S, 16, 2, 16, FALSE, 0, complain_overflow_bitfield,
287         mips_fix_hi16_s,
288         "HI16_S",   FALSE, 0, 0x0000ffff, FALSE},
289   {MIPS_RELOC_LO16,    0, 2, 16, FALSE, 0, complain_overflow_dont, 0,
290         "LO16",     FALSE, 0, 0x0000ffff, FALSE},
291 };
292
293 static reloc_howto_type *
294 MY(reloc_type_lookup) (bfd *abfd, bfd_reloc_code_real_type code)
295 {
296   if (bfd_get_arch (abfd) != bfd_arch_mips)
297     return NULL;
298
299   switch (code)
300     {
301     case BFD_RELOC_CTOR:
302     case BFD_RELOC_32:
303       return (&mips_howto_table_ext[MIPS_RELOC_32]);
304     case BFD_RELOC_MIPS_JMP:
305       return (&mips_howto_table_ext[MIPS_RELOC_JMP]);
306     case BFD_RELOC_16_PCREL_S2:
307       return (&mips_howto_table_ext[MIPS_RELOC_WDISP16]);
308     case BFD_RELOC_HI16:
309       return (&mips_howto_table_ext[MIPS_RELOC_HI16]);
310     case BFD_RELOC_HI16_S:
311       return (&mips_howto_table_ext[MIPS_RELOC_HI16_S]);
312     case BFD_RELOC_LO16:
313       return (&mips_howto_table_ext[MIPS_RELOC_LO16]);
314     default:
315       return NULL;
316     }
317 }
318
319 static reloc_howto_type *
320 MY(reloc_name_lookup) (bfd *abfd ATTRIBUTE_UNUSED,
321                        const char *r_name)
322 {
323   unsigned int i;
324
325   for (i = 0;
326        i < sizeof (mips_howto_table_ext) / sizeof (mips_howto_table_ext[0]);
327        i++)
328     if (mips_howto_table_ext[i].name != NULL
329         && strcasecmp (mips_howto_table_ext[i].name, r_name) == 0)
330       return &mips_howto_table_ext[i];
331
332   return NULL;
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) (bfd *abfd,
339                         sec_ptr section,
340                         arelent **relptr,
341                         asymbol **symbols)
342 {
343   arelent *tblptr = section->relocation;
344   unsigned int count, c;
345   extern reloc_howto_type NAME(aout,ext_howto_table)[];
346
347   /* If we have already read in the relocation table, return the values.  */
348   if (section->flags & SEC_CONSTRUCTOR)
349     {
350       arelent_chain *chain = section->constructor_chain;
351
352       for (count = 0; count < section->reloc_count; count++)
353         {
354           *relptr++ = &chain->relent;
355           chain = chain->next;
356         }
357       *relptr = 0;
358       return section->reloc_count;
359     }
360
361   if (tblptr && section->reloc_count)
362     {
363       for (count = 0; count++ < section->reloc_count;)
364         *relptr++ = tblptr++;
365       *relptr = 0;
366       return section->reloc_count;
367     }
368
369   if (!NAME(aout,slurp_reloc_table) (abfd, section, symbols))
370     return -1;
371   tblptr = section->relocation;
372
373   /* fix up howto entries.  */
374   for (count = 0; count++ < section->reloc_count;)
375     {
376       c = tblptr->howto - NAME(aout,ext_howto_table);
377       tblptr->howto = &mips_howto_table_ext[c];
378
379       *relptr++ = tblptr++;
380     }
381   *relptr = 0;
382   return section->reloc_count;
383 }
384
385 static const struct aout_backend_data MY(backend_data) =
386 {
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     0,                          /* match priority.  */
418     bfd_getl64, bfd_getl_signed_64, bfd_putl64,
419     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
420     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
421     bfd_getl64, bfd_getl_signed_64, bfd_putl64,
422     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
423     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
424     {_bfd_dummy_target, MY_object_p, /* bfd_check_format */
425      bfd_generic_archive_p, MY_core_file_p},
426     {bfd_false, MY_mkobject,    /* bfd_set_format */
427      _bfd_generic_mkarchive, bfd_false},
428     {bfd_false, MY_write_object_contents, /* bfd_write_contents */
429      _bfd_write_archive_contents, bfd_false},
430
431     BFD_JUMP_TABLE_GENERIC (MY),
432     BFD_JUMP_TABLE_COPY (MY),
433     BFD_JUMP_TABLE_CORE (MY),
434     BFD_JUMP_TABLE_ARCHIVE (MY),
435     BFD_JUMP_TABLE_SYMBOLS (MY),
436     BFD_JUMP_TABLE_RELOCS (MY),
437     BFD_JUMP_TABLE_WRITE (MY),
438     BFD_JUMP_TABLE_LINK (MY),
439     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
440
441     & aout_mips_big_vec,
442
443     MY_backend_data
444   };
445
446 const bfd_target aout_mips_big_vec =
447   {
448     "a.out-mips-big",           /* name */
449     bfd_target_aout_flavour,
450     BFD_ENDIAN_BIG,             /* target byte order (big) */
451     BFD_ENDIAN_BIG,             /* target headers byte order (big) */
452     (HAS_RELOC | EXEC_P |               /* object flags */
453      HAS_LINENO | HAS_DEBUG |
454      HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
455     (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
456     MY_symbol_leading_char,
457     ' ',                                /* ar_pad_char */
458     15,                         /* ar_max_namelen */
459     0,                          /* match priority.  */
460     bfd_getb64, bfd_getb_signed_64, bfd_putb64,
461     bfd_getb32, bfd_getb_signed_32, bfd_putb32,
462     bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
463     bfd_getb64, bfd_getb_signed_64, bfd_putb64,
464     bfd_getb32, bfd_getb_signed_32, bfd_putb32,
465     bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
466     {_bfd_dummy_target, MY_object_p, /* bfd_check_format */
467      bfd_generic_archive_p, MY_core_file_p},
468     {bfd_false, MY_mkobject,    /* bfd_set_format */
469      _bfd_generic_mkarchive, bfd_false},
470     {bfd_false, MY_write_object_contents, /* bfd_write_contents */
471      _bfd_write_archive_contents, bfd_false},
472
473     BFD_JUMP_TABLE_GENERIC (MY),
474     BFD_JUMP_TABLE_COPY (MY),
475     BFD_JUMP_TABLE_CORE (MY),
476     BFD_JUMP_TABLE_ARCHIVE (MY),
477     BFD_JUMP_TABLE_SYMBOLS (MY),
478     BFD_JUMP_TABLE_RELOCS (MY),
479     BFD_JUMP_TABLE_WRITE (MY),
480     BFD_JUMP_TABLE_LINK (MY),
481     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
482
483     & aout_mips_little_vec,
484
485     MY_backend_data
486   };