* bout.c: added support for relaxable alignment relocs.
[deliverable/binutils-gdb.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 };
This page took 0.059355 seconds and 5 git commands to generate.