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