* bout.c: added support for relaxable alignment relocs.
[external/binutils.git] / bfd / bout.c
1 /* BFD back-end for Intel 960 b.out binaries.
2    Copyright (C) 1990-1991 Free Software Foundation, Inc.
3    Written by Cygnus Support.
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21
22 #include "bfd.h"
23 #include "sysdep.h"
24 #include "libbfd.h"
25 #include "seclet.h"
26 #include "bout.h"
27
28 #include "aout/stab_gnu.h"
29 #include "libaout.h"            /* BFD a.out internal data structures */
30
31
32 extern bfd_error_vector_type bfd_error_vector;
33 PROTO (static boolean, b_out_squirt_out_relocs,(bfd *abfd, asection *section));
34 PROTO (static bfd_target *, b_out_callback, (bfd *));
35
36 PROTO (boolean, aout_32_slurp_symbol_table, (bfd *abfd));
37 PROTO (void , aout_32_write_syms, ());
38
39 /* Swaps the information in an executable header taken from a raw byte
40    stream memory image, into the internal exec_header structure.  */
41
42 PROTO(void, bout_swap_exec_header_in,
43       (bfd *abfd,
44       struct external_exec *raw_bytes,
45       struct internal_exec *execp));
46          
47 void
48 DEFUN(bout_swap_exec_header_in,(abfd, raw_bytes, execp),
49       bfd *abfd AND
50       struct external_exec *raw_bytes AND
51       struct internal_exec *execp)
52 {
53   struct external_exec *bytes = (struct external_exec *)raw_bytes;
54
55   /* Now fill in fields in the execp, from the bytes in the raw data.  */
56   execp->a_info   = bfd_h_get_32 (abfd, bytes->e_info);
57   execp->a_text   = GET_WORD (abfd, bytes->e_text);
58   execp->a_data   = GET_WORD (abfd, bytes->e_data);
59   execp->a_bss    = GET_WORD (abfd, bytes->e_bss);
60   execp->a_syms   = GET_WORD (abfd, bytes->e_syms);
61   execp->a_entry  = GET_WORD (abfd, bytes->e_entry);
62   execp->a_trsize = GET_WORD (abfd, bytes->e_trsize);
63   execp->a_drsize = GET_WORD (abfd, bytes->e_drsize);
64   execp->a_tload  = GET_WORD (abfd, bytes->e_tload);
65   execp->a_dload  = GET_WORD (abfd, bytes->e_dload);
66   execp->a_talign = bytes->e_talign[0];
67   execp->a_dalign = bytes->e_dalign[0];
68   execp->a_balign = bytes->e_balign[0];
69   execp->a_relaxable = bytes->e_relaxable[0];
70 }
71
72 /* Swaps the information in an internal exec header structure into the
73    supplied buffer ready for writing to disk.  */
74
75 PROTO(void, bout_swap_exec_header_out,
76           (bfd *abfd,
77            struct internal_exec *execp,
78            struct external_exec *raw_bytes));
79 void
80 DEFUN(bout_swap_exec_header_out,(abfd, execp, raw_bytes),
81      bfd *abfd AND
82      struct internal_exec *execp AND 
83      struct external_exec *raw_bytes)
84 {
85   struct external_exec *bytes = (struct external_exec *)raw_bytes;
86
87   /* Now fill in fields in the raw data, from the fields in the exec struct. */
88   bfd_h_put_32 (abfd, execp->a_info  , bytes->e_info);
89   PUT_WORD (abfd, execp->a_text  , bytes->e_text);
90   PUT_WORD (abfd, execp->a_data  , bytes->e_data);
91   PUT_WORD (abfd, execp->a_bss   , bytes->e_bss);
92   PUT_WORD (abfd, execp->a_syms  , bytes->e_syms);
93   PUT_WORD (abfd, execp->a_entry , bytes->e_entry);
94   PUT_WORD (abfd, execp->a_trsize, bytes->e_trsize);
95   PUT_WORD (abfd, execp->a_drsize, bytes->e_drsize);
96   PUT_WORD (abfd, execp->a_tload , bytes->e_tload);
97   PUT_WORD (abfd, execp->a_dload , bytes->e_dload);
98   bytes->e_talign[0] = execp->a_talign;
99   bytes->e_dalign[0] = execp->a_dalign;
100   bytes->e_balign[0] = execp->a_balign;
101   bytes->e_relaxable[0] = execp->a_relaxable;
102 }
103
104
105 static bfd_target *
106 b_out_object_p (abfd)
107      bfd *abfd;
108 {
109   struct internal_exec anexec;
110   struct external_exec exec_bytes;
111
112   if (bfd_read ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd)
113       != EXEC_BYTES_SIZE) {
114     bfd_error = wrong_format;
115     return 0;
116   }
117
118   anexec.a_info = bfd_h_get_32 (abfd, exec_bytes.e_info);
119
120   if (N_BADMAG (anexec)) {
121     bfd_error = wrong_format;
122     return 0;
123   }
124
125   bout_swap_exec_header_in (abfd, &exec_bytes, &anexec);
126   return aout_32_some_aout_object_p (abfd, &anexec, b_out_callback);
127 }
128
129
130 /* Finish up the opening of a b.out file for reading.  Fill in all the
131    fields that are not handled by common code.  */
132
133 static bfd_target *
134 b_out_callback (abfd)
135      bfd *abfd;
136 {
137   struct internal_exec *execp = exec_hdr (abfd);
138   unsigned long bss_start;
139
140   /* Architecture and machine type */
141   bfd_set_arch_mach(abfd, 
142                     bfd_arch_i960, /* B.out only used on i960 */
143                     bfd_mach_i960_core /* Default */
144                     );
145
146   /* The positions of the string table and symbol table.  */
147   obj_str_filepos (abfd) = N_STROFF (*execp);
148   obj_sym_filepos (abfd) = N_SYMOFF (*execp);
149
150   /* The alignments of the sections */
151   obj_textsec (abfd)->alignment_power = execp->a_talign;
152   obj_datasec (abfd)->alignment_power = execp->a_dalign;
153   obj_bsssec  (abfd)->alignment_power = execp->a_balign;
154
155   /* The starting addresses of the sections.  */
156   obj_textsec (abfd)->vma = execp->a_tload;
157   obj_datasec (abfd)->vma = execp->a_dload;
158
159   /* And reload the sizes, since the aout module zaps them */
160   obj_textsec (abfd)->_raw_size = execp->a_text;
161
162   bss_start = execp->a_dload + execp->a_data; /* BSS = end of data section */
163   obj_bsssec (abfd)->vma = align_power (bss_start, execp->a_balign);
164
165   /* The file positions of the sections */
166   obj_textsec (abfd)->filepos = N_TXTOFF(*execp);
167   obj_datasec (abfd)->filepos = N_DATOFF(*execp);
168
169   /* The file positions of the relocation info */
170   obj_textsec (abfd)->rel_filepos = N_TROFF(*execp);
171   obj_datasec (abfd)->rel_filepos =  N_DROFF(*execp);
172
173   adata(abfd).page_size = 1;    /* Not applicable. */
174   adata(abfd).segment_size = 1; /* Not applicable. */
175   adata(abfd).exec_bytes_size = EXEC_BYTES_SIZE;
176
177   if (execp->a_relaxable)
178    abfd->flags |= BFD_IS_RELAXABLE;
179   return abfd->xvec;
180 }
181
182 struct bout_data_struct {
183     struct aoutdata a;
184     struct internal_exec e;
185 };
186
187 static boolean
188 b_out_mkobject (abfd)
189      bfd *abfd;
190 {
191   struct bout_data_struct *rawptr;
192
193   rawptr = (struct bout_data_struct *) bfd_zalloc (abfd, sizeof (struct bout_data_struct));
194   if (rawptr == NULL) {
195       bfd_error = no_memory;
196       return false;
197     }
198
199   abfd->tdata.bout_data = rawptr;
200   exec_hdr (abfd) = &rawptr->e;
201
202   /* For simplicity's sake we just make all the sections right here. */
203   obj_textsec (abfd) = (asection *)NULL;
204   obj_datasec (abfd) = (asection *)NULL;
205   obj_bsssec (abfd) = (asection *)NULL;
206
207   bfd_make_section (abfd, ".text");
208   bfd_make_section (abfd, ".data");
209   bfd_make_section (abfd, ".bss");
210
211   return true;
212 }
213
214 static boolean
215 b_out_write_object_contents (abfd)
216      bfd *abfd;
217 {
218   struct external_exec swapped_hdr;
219
220   exec_hdr (abfd)->a_info = BMAGIC;
221
222   exec_hdr (abfd)->a_text = obj_textsec (abfd)->_raw_size;
223   exec_hdr (abfd)->a_data = obj_datasec (abfd)->_raw_size;
224   exec_hdr (abfd)->a_bss = obj_bsssec (abfd)->_raw_size;
225   exec_hdr (abfd)->a_syms = bfd_get_symcount (abfd) * sizeof (struct nlist);
226   exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);
227   exec_hdr (abfd)->a_trsize = ((obj_textsec (abfd)->reloc_count) *
228                                sizeof (struct relocation_info));
229   exec_hdr (abfd)->a_drsize = ((obj_datasec (abfd)->reloc_count) *
230                                sizeof (struct relocation_info));
231
232   exec_hdr (abfd)->a_talign = obj_textsec (abfd)->alignment_power;
233   exec_hdr (abfd)->a_dalign = obj_datasec (abfd)->alignment_power;
234   exec_hdr (abfd)->a_balign = obj_bsssec (abfd)->alignment_power;
235
236   exec_hdr (abfd)->a_tload = obj_textsec (abfd)->vma;
237   exec_hdr (abfd)->a_dload = obj_datasec (abfd)->vma;
238
239   bout_swap_exec_header_out (abfd, exec_hdr (abfd), &swapped_hdr);
240
241   bfd_seek (abfd, 0L, SEEK_SET);
242   bfd_write ((PTR) &swapped_hdr, 1, EXEC_BYTES_SIZE, abfd);
243
244   /* Now write out reloc info, followed by syms and strings */
245   if (bfd_get_symcount (abfd) != 0) 
246     {
247       bfd_seek (abfd,
248                 (long)(N_SYMOFF(*exec_hdr(abfd))), SEEK_SET);
249
250       aout_32_write_syms (abfd);
251
252       bfd_seek (abfd,   (long)(N_TROFF(*exec_hdr(abfd))), SEEK_SET);
253
254       if (!b_out_squirt_out_relocs (abfd, obj_textsec (abfd))) return false;
255       bfd_seek (abfd, (long)(N_DROFF(*exec_hdr(abfd))), SEEK_SET);
256
257       if (!b_out_squirt_out_relocs (abfd, obj_datasec (abfd))) return false;
258     }
259   return true;
260 }
261 \f
262 /** Some reloc hackery */
263
264 #define CALLS    0x66003800     /* Template for 'calls' instruction     */
265 #define BAL      0x0b000000     /* Template for 'bal' instruction */
266 #define BALX     0x85000000     /* Template for 'balx' instruction      */
267 #define BAL_MASK 0x00ffffff
268 #define CALL     0x09000000
269 #define PCREL13_MASK 0x1fff
270 /* Magic to turn callx into calljx */
271 static bfd_reloc_status_type 
272 DEFUN (calljx_callback, (abfd, reloc_entry,  src, dst, input_section),
273        bfd *abfd AND
274        arelent *reloc_entry AND
275        PTR src AND
276        PTR dst AND
277
278        asection *input_section)
279 {
280   int  word = bfd_get_32(abfd, src);
281   asymbol *symbol_in = *(reloc_entry->sym_ptr_ptr);
282   aout_symbol_type  *symbol = aout_symbol(symbol_in);
283
284   if (IS_CALLNAME(symbol->other)) 
285   {
286
287     aout_symbol_type *balsym = symbol+1;
288     int inst = bfd_get_32(abfd, (bfd_byte *) src-4);
289     /* The next symbol should be an N_BALNAME */
290     BFD_ASSERT(IS_BALNAME(balsym->other));
291     inst &= BAL_MASK;
292     inst |= BALX;
293     bfd_put_32(abfd, inst, (bfd_byte *) dst-4);
294     symbol = balsym;
295   }
296
297     word += symbol->symbol.section->output_offset +
298      symbol->symbol.section->output_section->vma +
299       symbol->symbol.value + reloc_entry->addend;
300
301   bfd_put_32(abfd, word, dst);
302   return bfd_reloc_ok;
303 }
304
305
306 /* Magic to turn call into callj */
307 static bfd_reloc_status_type 
308 DEFUN (callj_callback, (abfd, reloc_entry,  data, srcidx,dstidx, input_section),
309        bfd *abfd AND
310        arelent *reloc_entry AND
311        PTR data AND
312        unsigned int srcidx AND
313        unsigned int dstidx AND
314        asection *input_section )
315 {
316   int  word = bfd_get_32(abfd, (bfd_byte *) data + srcidx);
317   asymbol *symbol_in = *(reloc_entry->sym_ptr_ptr);
318
319   aout_symbol_type  *symbol = aout_symbol(symbol_in);
320
321   if (IS_OTHER(symbol->other)) 
322   {
323     /* Call to a system procedure - replace code with system
324        procedure number */
325     word = CALLS | (symbol->other - 1);
326
327   }
328
329   else  if (IS_CALLNAME(symbol->other)) 
330   {
331     aout_symbol_type *balsym = symbol+1;
332     /* The next symbol should be an N_BALNAME */
333     BFD_ASSERT(IS_BALNAME(balsym->other));
334
335     /* We are calling a leaf - so replace the call instruction
336        with a bal */
337
338     word = BAL |
339      (((word & BAL_MASK) +
340        balsym->symbol.section->output_offset +
341        balsym->symbol.section->output_section->vma+
342        balsym->symbol.value + reloc_entry->addend - dstidx -
343        ( input_section->output_section->vma + input_section->output_offset))
344       & BAL_MASK);
345
346
347   }
348   else 
349   {
350
351     word = CALL |
352      (((word & BAL_MASK) + 
353        symbol->symbol.section->output_offset +
354        symbol->symbol.section->output_section->vma+
355        symbol->symbol.value + reloc_entry->addend - dstidx -
356        ( input_section->output_section->vma + input_section->output_offset))
357       & BAL_MASK);
358   }
359   bfd_put_32(abfd, word, (bfd_byte *) data + dstidx);
360   return bfd_reloc_ok;
361 }
362
363 /* type rshift size  bitsize    pcrel   bitpos  absolute overflow check*/
364
365 #define ABS32CODE 0
366 #define ABS32CODE_SHRUNK 1 
367 #define PCREL24 2
368 #define CALLJ 3
369 #define ABS32 4
370 #define PCREL13 5
371 #define ABS32_MAYBE_RELAXABLE 1
372 #define ABS32_WAS_RELAXABLE 2
373
374 #define ALIGN 10
375 #define ALIGNDONE 11
376 static reloc_howto_type howto_reloc_callj =
377 HOWTO(CALLJ, 0, 2, 24, true, 0, true, true, 0,"callj", true, 0x00ffffff, 0x00ffffff,false);
378 static  reloc_howto_type howto_reloc_abs32 =
379 HOWTO(ABS32, 0, 2, 32, false, 0, true, true,0,"abs32", true, 0xffffffff,0xffffffff,false);
380 static reloc_howto_type howto_reloc_pcrel24 =
381 HOWTO(PCREL24, 0, 2, 24, true, 0, true, true,0,"pcrel24", true, 0x00ffffff,0x00ffffff,false);
382
383 static reloc_howto_type howto_reloc_pcrel13 =
384 HOWTO(PCREL13, 0, 2, 13, true, 0, true, true,0,"pcrel13", true, 0x00001fff,0x00001fff,false);
385
386
387 static reloc_howto_type howto_reloc_abs32codeshrunk = 
388 HOWTO(ABS32CODE_SHRUNK, 0, 2, 24, true, 0, true, true, 0,"callx->callj", true, 0x00ffffff, 0x00ffffff,false);
389
390 static  reloc_howto_type howto_reloc_abs32code =
391 HOWTO(ABS32CODE, 0, 2, 32, false, 0, true, true,0,"callx", true, 0xffffffff,0xffffffff,false);
392
393 static reloc_howto_type howto_align_table[] = {
394   HOWTO (ALIGN, 0, 0x1, 0, 0, 0, 0, 0, 0, "align16", 0, 0, 0, 0),
395   HOWTO (ALIGN, 0, 0x3, 0, 0, 0, 0, 0, 0, "align32", 0, 0, 0, 0),
396   HOWTO (ALIGN, 0, 0x7, 0, 0, 0, 0, 0, 0, "align64", 0, 0, 0, 0),
397   HOWTO (ALIGN, 0, 0xf, 0, 0, 0, 0, 0, 0, "align128", 0, 0, 0, 0),
398 };
399
400 static reloc_howto_type howto_done_align_table[] = {
401   HOWTO (ALIGNDONE, 0x1, 0x1, 0, 0, 0, 0, 0, 0, "donealign16", 0, 0, 0,0),
402   HOWTO (ALIGNDONE, 0x3, 0x3, 0, 0, 0, 0, 0, 0, "donealign32", 0, 0, 0,0),
403   HOWTO (ALIGNDONE, 0x7, 0x7, 0, 0, 0, 0, 0, 0, "donealign64", 0, 0, 0,0),
404   HOWTO (ALIGNDONE, 0xf, 0xf, 0, 0, 0, 0, 0, 0, "donealign128", 0, 0, 0,0),
405
406 };
407
408 static reloc_howto_type *
409 b_out_reloc_type_lookup (abfd, code)
410      bfd *abfd;
411      bfd_reloc_code_real_type code;
412 {
413   switch (code)
414     {
415     default:
416       return 0;
417     case BFD_RELOC_I960_CALLJ:
418       return &howto_reloc_callj;
419     case BFD_RELOC_32:
420       return &howto_reloc_abs32;
421     case BFD_RELOC_24_PCREL:
422       return &howto_reloc_pcrel24;
423     }
424 }
425
426 /* Allocate enough room for all the reloc entries, plus pointers to them all */
427
428 static boolean
429 b_out_slurp_reloc_table (abfd, asect, symbols)
430      bfd *abfd;
431      sec_ptr asect;
432      asymbol **symbols;
433 {
434   register struct relocation_info *rptr;
435   unsigned int counter ;
436   arelent *cache_ptr ;
437   int extern_mask, pcrel_mask, callj_mask, length_shift;
438   int incode_mask;
439   int size_mask;
440   bfd_vma prev_addr = 0;
441   unsigned int count;
442   size_t  reloc_size;
443   struct relocation_info *relocs;
444   arelent *reloc_cache;
445
446   if (asect->relocation) return true;
447   if (!aout_32_slurp_symbol_table (abfd)) return false;
448
449   if (asect == obj_datasec (abfd)) {
450     reloc_size = exec_hdr(abfd)->a_drsize;
451     goto doit;
452   }
453
454   if (asect == obj_textsec (abfd)) {
455     reloc_size = exec_hdr(abfd)->a_trsize;
456     goto doit;
457   }
458
459   bfd_error = invalid_operation;
460   return false;
461
462  doit:
463   bfd_seek (abfd, (long)(asect->rel_filepos),  SEEK_SET);
464   count = reloc_size / sizeof (struct relocation_info);
465
466   relocs = (struct relocation_info *) bfd_xmalloc (reloc_size);
467   if (!relocs) {
468     bfd_error = no_memory;
469     return false;
470   }
471   reloc_cache = (arelent *) bfd_xmalloc ((count+1) * sizeof (arelent));
472   if (!reloc_cache) {
473     free ((char*)relocs);
474     bfd_error = no_memory;
475     return false;
476   }
477
478   if (bfd_read ((PTR) relocs, 1, reloc_size, abfd) != reloc_size) {
479     bfd_error = system_call_error;
480     free (reloc_cache);
481     free (relocs);
482     return false;
483   }
484
485
486   
487   if (abfd->xvec->header_byteorder_big_p) {
488     /* big-endian bit field allocation order */
489     pcrel_mask  = 0x80;
490     extern_mask = 0x10;
491     incode_mask = 0x08;
492     callj_mask  = 0x02;
493     size_mask =   0x20;
494     length_shift = 5;
495   } else {
496     /* little-endian bit field allocation order */
497     pcrel_mask  = 0x01;
498     extern_mask = 0x08;
499     incode_mask = 0x10;
500     callj_mask  = 0x40;
501     size_mask   = 0x02;
502     length_shift = 1;
503   }
504
505   for (rptr = relocs, cache_ptr = reloc_cache, counter = 0;
506        counter < count;
507        counter++, rptr++, cache_ptr++) 
508   {
509     unsigned char *raw = (unsigned char *)rptr;
510     unsigned int symnum;
511     cache_ptr->address = bfd_h_get_32 (abfd, raw + 0);
512     if (abfd->xvec->header_byteorder_big_p) 
513     {
514       symnum = (raw[4] << 16) | (raw[5] << 8) | raw[6];
515     } 
516     else
517     {
518       symnum = (raw[6] << 16) | (raw[5] << 8) | raw[4];
519     }
520
521     if (raw[7] & extern_mask) 
522     {
523       /* if this is set then the r_index is a index into the symbol table;
524        * if the bit is not set then r_index contains a section map.
525        * we either fill in the sym entry with a pointer to the symbol,
526        * or point to the correct section
527        */
528       cache_ptr->sym_ptr_ptr = symbols + symnum;
529       cache_ptr->addend = 0;
530     } else 
531     {
532       /* in a.out symbols are relative to the beginning of the
533        * file rather than sections ?
534        * (look in translate_from_native_sym_flags)
535        * the reloc entry addend has added to it the offset into the
536        * file of the data, so subtract the base to make the reloc
537        * section relative */
538       int s;
539       {
540         /* sign-extend symnum from 24 bits to whatever host uses */
541         s = symnum;
542         if (s & (1 << 23))
543           s |= (~0) << 24;
544       }
545       cache_ptr->sym_ptr_ptr = (asymbol **)NULL;
546       switch (s)
547       {
548        case N_TEXT:
549        case N_TEXT | N_EXT:
550         cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr;
551         cache_ptr->addend = - obj_textsec(abfd)->vma;
552         break;
553        case N_DATA:
554        case N_DATA | N_EXT:
555         cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr;
556         cache_ptr->addend = - obj_datasec(abfd)->vma;
557         break;
558        case N_BSS:
559        case N_BSS | N_EXT:
560         cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr;
561         cache_ptr->addend =  - obj_bsssec(abfd)->vma;
562         break;
563        case N_ABS:
564        case N_ABS | N_EXT:
565         cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr;
566         cache_ptr->addend = 0;
567         break;
568       case -2: /* .align */
569         if (raw[7] & pcrel_mask)
570           {
571             cache_ptr->howto = &howto_align_table[(raw[7] >> length_shift) & 3];
572             cache_ptr->sym_ptr_ptr = &bfd_abs_symbol;
573           }
574         else
575           {
576             /* .org? */
577             abort ();
578           }
579         cache_ptr->addend = 0;
580         break;
581        default:
582         BFD_ASSERT(0);
583         break;
584       }
585         
586     }
587
588     /* the i960 only has a few relocation types:
589        abs 32-bit and pcrel 24bit.   except for callj's!  */
590     if (cache_ptr->howto != 0)
591       ;
592     else if (raw[7] & callj_mask)
593     {
594       cache_ptr->howto = &howto_reloc_callj;
595     }
596     else if ( raw[7] & pcrel_mask)
597     {
598       if (raw[7] & size_mask)
599        cache_ptr->howto = &howto_reloc_pcrel13;
600       else
601        cache_ptr->howto = &howto_reloc_pcrel24;
602     }
603     else 
604     {
605       if (raw[7] & incode_mask) 
606       {
607         cache_ptr->howto = &howto_reloc_abs32code;
608       }
609       else 
610       {
611         cache_ptr->howto = &howto_reloc_abs32;
612       }
613     }
614     if (cache_ptr->address < prev_addr) 
615     {
616       /* Ouch! this reloc is out of order, insert into the right place
617        */
618       arelent tmp;
619       arelent *cursor = cache_ptr-1;
620       unsigned int where = counter;
621       bfd_vma stop = cache_ptr->address;
622       tmp  = *cache_ptr;
623       while (cursor->address > stop && cursor >= reloc_cache)
624       {
625         cursor[1] = cursor[0];
626         cursor--;
627       } 
628       cursor[1] = tmp;
629     }
630     else 
631     {
632       prev_addr = cache_ptr->address;
633     }
634   }
635
636
637   free (relocs);
638   asect->relocation = reloc_cache;
639   asect->reloc_count = count;
640
641
642   return true;
643 }
644
645
646 static boolean
647 b_out_squirt_out_relocs (abfd, section)
648      bfd *abfd;
649      asection *section;
650 {
651
652   arelent **generic;
653   int r_extern;
654   int r_idx;
655   int r_addend;
656   int incode_mask;  
657   int len_1;
658   unsigned int count = section->reloc_count;
659   struct relocation_info *native, *natptr;
660   size_t natsize = count * sizeof (struct relocation_info);
661   int extern_mask, pcrel_mask,  len_2, callj_mask;
662   int len1;
663   if (count == 0) return true;
664   generic   = section->orelocation;
665   native = ((struct relocation_info *) bfd_xmalloc (natsize));
666   if (!native) {
667       bfd_error = no_memory;
668       return false;
669     }
670
671   if (abfd->xvec->header_byteorder_big_p) 
672   {
673     /* Big-endian bit field allocation order */
674     pcrel_mask  = 0x80;
675     extern_mask = 0x10;
676     len_2       = 0x40;
677     len_1       = 0x20;
678     callj_mask  = 0x02;
679     incode_mask = 0x08;
680   } 
681 else 
682   {
683     /* Little-endian bit field allocation order */
684     pcrel_mask  = 0x01;
685     extern_mask = 0x08;
686     len_2       = 0x04;
687     len_1       = 0x02;
688     callj_mask  = 0x40;
689     incode_mask = 0x10;
690   }
691
692   for (natptr = native; count > 0; --count, ++natptr, ++generic) 
693   {
694     arelent *g = *generic;
695     unsigned char *raw = (unsigned char *)natptr;
696     asymbol *sym = *(g->sym_ptr_ptr);
697       
698     asection *output_section = sym->section->output_section;
699     bfd_h_put_32(abfd, g->address, raw);  
700     /* Find a type in the output format which matches the input howto - 
701      * at the moment we assume input format == output format FIXME!!
702      */
703     /* FIXME:  Need callj stuff here, and to check the howto entries to
704        be sure they are real for this architecture.  */
705     if (g->howto== &howto_reloc_callj) 
706     {
707       raw[7] = callj_mask + pcrel_mask + len_2;
708     }
709     else if (g->howto == &howto_reloc_pcrel24) 
710     {
711       raw[7] = pcrel_mask + len_2;
712     }
713     else if (g->howto == &howto_reloc_pcrel13) 
714     {
715       raw[7] = pcrel_mask + len_1;
716     }
717     else if (g->howto == &howto_reloc_abs32code) 
718     {
719       raw[7] = len_2 + incode_mask;
720     }
721     else {
722         raw[7] = len_2;
723       }
724     if (output_section == &bfd_com_section 
725         || output_section == &bfd_abs_section
726         || output_section == &bfd_und_section) 
727     {
728       /* Fill in symbol */
729       r_extern = 1;
730       r_idx =  stoi((*(g->sym_ptr_ptr))->flags);
731     }
732     else 
733     {
734       /* Just an ordinary section */
735       r_extern = 0;
736       r_idx  = output_section->target_index;      
737     }
738
739     if (abfd->xvec->header_byteorder_big_p) {
740         raw[4] = (unsigned char) (r_idx >> 16);
741         raw[5] = (unsigned char) (r_idx >>  8);
742         raw[6] = (unsigned char) (r_idx     );
743       } else {
744           raw[6] = (unsigned char) (r_idx >> 16);
745           raw[5] = (unsigned char) (r_idx>>  8);
746           raw[4] = (unsigned char) (r_idx     );
747         }  
748 if (r_extern)
749     raw[7] |= extern_mask; 
750   }
751
752   if (bfd_write ((PTR) native, 1, natsize, abfd) != natsize) {
753       free((PTR)native);
754       return false;
755     }
756   free ((PTR)native);
757
758   return true;
759 }
760
761 /* This is stupid.  This function should be a boolean predicate */
762 static unsigned int
763 b_out_canonicalize_reloc (abfd, section, relptr, symbols)
764      bfd *abfd;
765      sec_ptr section;
766      arelent **relptr;
767      asymbol **symbols;
768 {
769   arelent *tblptr = section->relocation;
770   unsigned int count = 0;
771
772  if (!(tblptr || b_out_slurp_reloc_table (abfd, section, symbols))) return 0;
773   tblptr = section->relocation;
774  if (!tblptr) return 0;
775
776   for (; count++ < section->reloc_count;)
777     *relptr++ = tblptr++;
778
779   *relptr = 0;
780
781   return section->reloc_count;
782 }
783
784 static unsigned int
785 b_out_get_reloc_upper_bound (abfd, asect)
786      bfd *abfd;
787      sec_ptr asect;
788 {
789   if (bfd_get_format (abfd) != bfd_object) {
790     bfd_error = invalid_operation;
791     return 0;
792   }
793
794   if (asect == obj_datasec (abfd))
795     return (sizeof (arelent *) *
796             ((exec_hdr(abfd)->a_drsize / sizeof (struct relocation_info))
797              +1));
798
799   if (asect == obj_textsec (abfd))
800     return (sizeof (arelent *) *
801             ((exec_hdr(abfd)->a_trsize / sizeof (struct relocation_info))
802              +1));
803
804   bfd_error = invalid_operation;
805   return 0;
806 }
807 \f
808 static boolean
809 b_out_set_section_contents (abfd, section, location, offset, count)
810      bfd *abfd;
811      sec_ptr section;
812      unsigned char *location;
813      file_ptr offset;
814       int count;
815 {
816
817   if (abfd->output_has_begun == false) { /* set by bfd.c handler */
818     if ((obj_textsec (abfd) == NULL) || (obj_datasec (abfd) == NULL) /*||
819         (obj_textsec (abfd)->_cooked_size == 0) || (obj_datasec (abfd)->_cooked_size == 0)*/) {
820       bfd_error = invalid_operation;
821       return false;
822     }
823
824     obj_textsec (abfd)->filepos = sizeof(struct internal_exec);
825     obj_datasec(abfd)->filepos = obj_textsec(abfd)->filepos 
826                                  +  obj_textsec (abfd)->_raw_size;
827
828   }
829   /* regardless, once we know what we're doing, we might as well get going */
830   bfd_seek (abfd, section->filepos + offset, SEEK_SET);
831
832   if (count != 0) {
833     return (bfd_write ((PTR)location, 1, count, abfd) == count) ?true:false;
834   }
835   return true;
836 }
837
838 static boolean
839 b_out_set_arch_mach (abfd, arch, machine)
840      bfd *abfd;
841      enum bfd_architecture arch;
842      unsigned long machine;
843 {
844   bfd_default_set_arch_mach(abfd, arch, machine);
845
846   if (arch == bfd_arch_unknown) /* Unknown machine arch is OK */
847     return true;
848   if (arch == bfd_arch_i960)    /* i960 default is OK */
849     switch (machine) {
850     case bfd_mach_i960_core:
851     case bfd_mach_i960_kb_sb:
852     case bfd_mach_i960_mc:
853     case bfd_mach_i960_xa:
854     case bfd_mach_i960_ca:
855     case bfd_mach_i960_ka_sa:
856     case 0:
857       return true;
858     default:
859       return false;
860     }
861
862   return false;
863 }
864
865 static int 
866 DEFUN(b_out_sizeof_headers,(ignore_abfd, ignore),
867       bfd *ignore_abfd AND
868       boolean ignore)
869 {
870   return sizeof(struct internal_exec);
871 }
872
873
874
875 /************************************************************************/
876 static bfd_vma 
877 DEFUN(get_value,(reloc, seclet),
878       arelent  *reloc AND
879       bfd_seclet_type *seclet)
880 {
881   bfd_vma value;
882   asymbol *symbol = *(reloc->sym_ptr_ptr);
883   /* A symbol holds a pointer to a section, and an offset from the
884      base of the section.  To relocate, we find where the section will
885      live in the output and add that in */
886
887   if (symbol->section == &bfd_und_section)
888   {
889     /* Ouch, this is an undefined symbol.. */
890     bfd_error_vector.undefined_symbol(reloc, seclet);
891     value = symbol->value;
892   }
893   else 
894   {
895     value = symbol->value +
896      symbol->section->output_offset +
897       symbol->section->output_section->vma;
898   }
899   
900   
901   /* Add the value contained in the relocation */
902   value += (short)((reloc->addend) & 0xffff);
903   
904   return value;
905 }
906
907 static void
908 DEFUN(perform_slip,(s, slip, input_section, value),
909       asymbol **s AND
910       unsigned int slip AND
911       asection *input_section AND
912       bfd_vma value)
913 {
914   
915   /* Find all symbols past this point, and make them know
916      what's happened */
917   while (*s) 
918   {
919     asymbol *p = *s;
920     if (p->section == input_section) 
921     {
922       /* This was pointing into this section, so mangle it */
923       if (p->value > value)
924       {
925         p->value -=slip;
926       }
927     }
928     s++;
929         
930   }    
931 }
932 #if 1
933 /* This routine works out if the thing we want to get to can be
934    reached with a 24bit offset instead of a 32 bit one.
935    If it can, then it changes the amode */
936
937 static int 
938 DEFUN(abs32code,(input_section, symbols, r, shrink),
939       asection *input_section AND
940       asymbol **symbols AND
941       arelent *r AND
942       unsigned int shrink) 
943 {
944   bfd_vma value = get_value(r,0);
945   bfd_vma dot = input_section->output_section->vma +  input_section->output_offset + r->address;        
946   bfd_vma gap;
947   
948   /* See if the address we're looking at within 2^23 bytes of where
949      we are, if so then we can use a small branch rather than the
950      jump we were going to */
951
952   gap = value - (dot - shrink);
953   
954
955   if (-1<<23 < (long)gap && (long)gap < 1<<23 )
956   { 
957
958     /* Change the reloc type from 32bitcode possible 24, to 24bit
959        possible 32 */
960
961     r->howto = &howto_reloc_abs32codeshrunk;
962     /* The place to relc moves back by four bytes */
963     r->address -=4;
964           
965     /* This will be four bytes smaller in the long run */
966     shrink += 4 ;
967     perform_slip(symbols, 4, input_section, r->address-shrink +4);
968
969           
970   }      
971   return shrink;      
972 }
973
974 static int 
975 DEFUN(aligncode,(input_section, symbols, r, shrink),
976       asection *input_section AND
977       asymbol **symbols AND
978       arelent *r AND
979       unsigned int shrink) 
980 {
981   bfd_vma value = get_value(r,0);
982         
983
984   bfd_vma dot = input_section->output_section->vma +  input_section->output_offset + r->address;        
985   bfd_vma gap;
986   bfd_vma this_dot;
987   bfd_vma old_end;
988   bfd_vma new_end;
989     int shrink_delta;
990 int size = r->howto->size;
991   /* Reduce the size of the alignment so that it's still aligned but
992      smaller  - the current size is already the same size as or bigger
993      than the alignment required.  */
994
995
996
997   /* calculate the first byte following the padding before we optimize */
998   old_end = ((dot + size ) & ~size) + size+1;
999   /* work out where the new end will be - remember that we're smaller
1000      than we used to be */
1001   new_end = ((dot - shrink + size) & ~size);
1002
1003   /* This is the new end */
1004   gap = old_end - ((dot + size) & ~size);
1005
1006   shrink_delta = (old_end - new_end) - shrink;
1007
1008   if (shrink_delta)
1009   { 
1010
1011     /* Change the reloc so that it knows how far to align to */
1012     r->howto = howto_done_align_table + (r->howto - howto_align_table);
1013
1014     /* Encode the stuff into the addend - for future use we need to
1015        know how big the reloc used to be */
1016     r->addend = old_end ;
1017
1018     /* This will be N bytes smaller in the long run, adjust all the symbols */
1019
1020     
1021
1022     perform_slip(symbols, shrink_delta, input_section, r->address - shrink );
1023     shrink += shrink_delta;
1024   }      
1025   return shrink;      
1026 }
1027
1028
1029 static boolean 
1030 DEFUN(b_out_relax_section,(abfd, i, symbols),
1031       bfd *abfd AND
1032       asection *i AND
1033       asymbol **symbols)
1034 {
1035   
1036   /* Get enough memory to hold the stuff */
1037   bfd *input_bfd = i->owner;
1038   asection *input_section = i;
1039   int shrink = 0 ;
1040   boolean new = false;
1041   
1042   bfd_size_type reloc_size = bfd_get_reloc_upper_bound(input_bfd,
1043                                                        input_section);
1044   arelent **reloc_vector = (arelent **)alloca(reloc_size);
1045
1046   /* Get the relocs and think about them */
1047   if (bfd_canonicalize_reloc(input_bfd, 
1048                              input_section,
1049                              reloc_vector,
1050                              symbols))
1051   {
1052     arelent **parent;
1053     for (parent = reloc_vector; *parent; parent++) 
1054     {
1055       arelent *r = *parent;
1056       switch (r->howto->type) {
1057        case ALIGN:
1058         /* An alignment reloc */
1059         shrink = aligncode(input_section, symbols, r,shrink);
1060         new=true;
1061         break;
1062        case ABS32CODE:
1063         /* A 32bit reloc in an addressing mode */
1064         shrink = abs32code(input_section, symbols, r,shrink);
1065         new=true;
1066         break;
1067        case ABS32CODE_SHRUNK:
1068         shrink+=4;
1069         break;
1070       }
1071     }
1072   }
1073   input_section->_cooked_size = input_section->_raw_size - shrink;  
1074
1075   return new;
1076 }
1077
1078 #endif
1079 static bfd_byte *
1080 DEFUN(b_out_get_relocated_section_contents,(in_abfd, seclet, data),
1081       bfd *in_abfd AND
1082       bfd_seclet_type *seclet AND
1083       bfd_byte *data)
1084
1085 {
1086   /* Get enough memory to hold the stuff */
1087   bfd *input_bfd = seclet->u.indirect.section->owner;
1088   asection *input_section = seclet->u.indirect.section;
1089   bfd_size_type reloc_size = bfd_get_reloc_upper_bound(input_bfd,
1090                                                        input_section);
1091   arelent **reloc_vector = (arelent **)alloca(reloc_size);
1092   
1093   /* read in the section */
1094   bfd_get_section_contents(input_bfd,
1095                            input_section,
1096                            data,
1097                            0,
1098                            input_section->_raw_size);
1099   
1100   
1101   if (bfd_canonicalize_reloc(input_bfd, 
1102                              input_section,
1103                              reloc_vector,
1104                              seclet->u.indirect.symbols) )
1105   {
1106     arelent **parent = reloc_vector;
1107     arelent *reloc ;
1108     
1109
1110
1111     unsigned int dst_address = 0;
1112     unsigned int src_address = 0;
1113     unsigned int run;
1114     unsigned int idx;
1115     
1116     /* Find how long a run we can do */
1117     while (dst_address < seclet->size) 
1118     {
1119       
1120       reloc = *parent;
1121       if (reloc) 
1122       {
1123         /* Note that the relaxing didn't tie up the addresses in the
1124            relocation, so we use the original address to work out the
1125            run of non-relocated data */
1126         run = reloc->address - src_address;
1127         parent++;
1128         
1129       }
1130       else 
1131       {
1132         run = seclet->size - dst_address;
1133       }
1134       /* Copy the bytes */
1135       for (idx = 0; idx < run; idx++)
1136       {
1137         data[dst_address++] = data[src_address++];
1138       }
1139     
1140       /* Now do the relocation */
1141     
1142       if (reloc) 
1143       {
1144         switch (reloc->howto->type) 
1145         {
1146          case ABS32CODE:
1147           calljx_callback(in_abfd, reloc, src_address + data, dst_address+data, input_section);
1148           src_address+=4;
1149           dst_address+=4;
1150           break;
1151          case ABS32:
1152           bfd_put_32(in_abfd, get_value(reloc, seclet), data+dst_address);
1153           src_address+=4;
1154           dst_address+=4;
1155           break;
1156          case CALLJ:
1157           callj_callback(in_abfd, reloc ,data,src_address,dst_address,input_section);
1158           src_address+=4;
1159           dst_address+=4;
1160           break;
1161          case ALIGNDONE:
1162           src_address = reloc->addend;
1163           dst_address = (dst_address + reloc->howto->size) & ~reloc->howto->size;
1164           break;
1165          case ABS32CODE_SHRUNK: 
1166           /* This used to be a callx, but we've found out that a
1167              callj will reach, so do the right thing */
1168           callj_callback(in_abfd, reloc,data,src_address+4, dst_address,input_section);
1169
1170           dst_address+=4;
1171           src_address+=8;
1172           break;
1173          case PCREL24:
1174          {
1175            long int word = bfd_get_32(in_abfd, data+src_address);
1176            asymbol *symbol = *(reloc->sym_ptr_ptr);
1177            word = (word & ~BAL_MASK) |
1178             (((word & BAL_MASK) +
1179               symbol->section->output_offset +
1180               symbol->section->output_section->vma+
1181               symbol->value + reloc->addend - dst_address -
1182               ( input_section->output_section->vma + input_section->output_offset))
1183              & BAL_MASK);
1184
1185            bfd_put_32(in_abfd,word,  data+dst_address);
1186            dst_address+=4;
1187            src_address+=4;
1188
1189          }
1190           break;
1191
1192          case PCREL13:
1193          {
1194            long int word = bfd_get_32(in_abfd, data+src_address);
1195            asymbol *symbol = *(reloc->sym_ptr_ptr);
1196            word = (word & ~PCREL13_MASK) |
1197             (((word & PCREL13_MASK) +
1198               symbol->section->output_offset +
1199               symbol->section->output_section->vma+
1200               symbol->value + reloc->addend - dst_address -
1201               ( input_section->output_section->vma + input_section->output_offset))
1202              & PCREL13_MASK);
1203
1204            bfd_put_32(in_abfd,word,  data+dst_address);
1205            dst_address+=4;
1206            src_address+=4;
1207
1208          }
1209           break;
1210
1211          default:
1212
1213           abort();
1214         }
1215       }    
1216     }
1217   }
1218   return data;
1219 }
1220 /***********************************************************************/
1221
1222 /* Build the transfer vectors for Big and Little-Endian B.OUT files.  */
1223
1224 /* We don't have core files.  */
1225 #define aout_32_core_file_failing_command _bfd_dummy_core_file_failing_command
1226 #define aout_32_core_file_failing_signal _bfd_dummy_core_file_failing_signal
1227 #define aout_32_core_file_matches_executable_p  \
1228                                 _bfd_dummy_core_file_matches_executable_p
1229
1230 /* We use BSD-Unix generic archive files.  */
1231 #define aout_32_openr_next_archived_file        bfd_generic_openr_next_archived_file
1232 #define aout_32_generic_stat_arch_elt   bfd_generic_stat_arch_elt
1233 #define aout_32_slurp_armap             bfd_slurp_bsd_armap
1234 #define aout_32_slurp_extended_name_table       bfd_true
1235 #define aout_32_write_armap             bsd_write_armap
1236 #define aout_32_truncate_arname         bfd_bsd_truncate_arname
1237
1238 /* We override these routines from the usual a.out file routines.  */
1239 #define aout_32_canonicalize_reloc      b_out_canonicalize_reloc
1240 #define aout_32_get_reloc_upper_bound   b_out_get_reloc_upper_bound
1241 #define aout_32_set_section_contents    b_out_set_section_contents
1242 #define aout_32_set_arch_mach           b_out_set_arch_mach
1243 #define aout_32_sizeof_headers          b_out_sizeof_headers
1244
1245 #define aout_32_bfd_debug_info_start            bfd_void
1246 #define aout_32_bfd_debug_info_end              bfd_void
1247 #define aout_32_bfd_debug_info_accumulate       (PROTO(void,(*),(bfd*, struct sec *))) bfd_void
1248
1249 #define aout_32_bfd_get_relocated_section_contents  b_out_get_relocated_section_contents
1250 #define aout_32_bfd_relax_section                   b_out_relax_section
1251
1252 bfd_target b_out_vec_big_host =
1253 {
1254   "b.out.big",                  /* name */
1255   bfd_target_aout_flavour,
1256   false,                        /* data byte order is little */
1257   true,                         /* hdr byte order is big */
1258   (HAS_RELOC | EXEC_P |         /* object flags */
1259    HAS_LINENO | HAS_DEBUG |
1260    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT ),
1261   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1262   ' ',                          /* ar_pad_char */
1263   16,                           /* ar_max_namelen */
1264      2,                         /* minumum alignment power */
1265
1266 _do_getl64, _do_putl64,  _do_getl32, _do_putl32, _do_getl16, _do_putl16, /* data */
1267 _do_getb64, _do_putb64,  _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* hdrs */
1268     {_bfd_dummy_target, b_out_object_p, /* bfd_check_format */
1269        bfd_generic_archive_p, _bfd_dummy_target},
1270     {bfd_false, b_out_mkobject, /* bfd_set_format */
1271        _bfd_generic_mkarchive, bfd_false},
1272     {bfd_false, b_out_write_object_contents,    /* bfd_write_contents */
1273        _bfd_write_archive_contents, bfd_false},
1274
1275   JUMP_TABLE(aout_32),
1276   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* COFF stuff?! */
1277   b_out_reloc_type_lookup,
1278 };
1279
1280
1281 bfd_target b_out_vec_little_host =
1282 {
1283   "b.out.little",               /* name */
1284   bfd_target_aout_flavour,
1285   false,                        /* data byte order is little */
1286   false,                        /* header byte order is little */
1287   (HAS_RELOC | EXEC_P |         /* object flags */
1288    HAS_LINENO | HAS_DEBUG |
1289    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT ),
1290   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1291   ' ',                          /* ar_pad_char */
1292   16,                           /* ar_max_namelen */
1293      2,                         /* minum align */
1294 _do_getl64, _do_putl64, _do_getl32, _do_putl32, _do_getl16, _do_putl16, /* data */
1295 _do_getl64, _do_putl64, _do_getl32, _do_putl32, _do_getl16, _do_putl16, /* hdrs */
1296          
1297     {_bfd_dummy_target, b_out_object_p, /* bfd_check_format */
1298        bfd_generic_archive_p, _bfd_dummy_target},
1299     {bfd_false, b_out_mkobject, /* bfd_set_format */
1300        _bfd_generic_mkarchive, bfd_false},
1301     {bfd_false, b_out_write_object_contents,    /* bfd_write_contents */
1302        _bfd_write_archive_contents, bfd_false},
1303   JUMP_TABLE(aout_32),
1304   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* COFF stuff?! */
1305   b_out_reloc_type_lookup,
1306 };