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