Remove bfd stub function casts.
[deliverable/binutils-gdb.git] / bfd / bout.c
CommitLineData
252b5132 1/* BFD back-end for Intel 960 b.out binaries.
219d1afa 2 Copyright (C) 1990-2018 Free Software Foundation, Inc.
252b5132
RH
3 Written by Cygnus Support.
4
116c20d2 5 This file is part of BFD, the Binary File Descriptor library.
252b5132 6
116c20d2
NC
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
cd123cb7 9 the Free Software Foundation; either version 3 of the License, or
116c20d2 10 (at your option) any later version.
252b5132 11
116c20d2
NC
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.
252b5132 16
116c20d2
NC
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
cd123cb7
NC
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
252b5132 21
252b5132 22#include "sysdep.h"
3db64b00 23#include "bfd.h"
252b5132
RH
24#include "libbfd.h"
25#include "bfdlink.h"
26#include "genlink.h"
27#include "bout.h"
116c20d2 28#include "libiberty.h"
252b5132
RH
29
30#include "aout/stab_gnu.h"
67a374a5
NC
31#include "libaout.h" /* BFD a.out internal data structures. */
32
116c20d2
NC
33#define ABS32CODE 0
34#define ABS32CODE_SHRUNK 1
35#define PCREL24 2
36#define CALLJ 3
37#define ABS32 4
38#define PCREL13 5
39#define ABS32_MAYBE_RELAXABLE 1
40#define ABS32_WAS_RELAXABLE 2
41
42#define ALIGNER 10
43#define ALIGNDONE 11
44
45static reloc_howto_type howto_reloc_callj =
46 HOWTO (CALLJ, 0, 2, 24, TRUE, 0, complain_overflow_signed, 0,"callj", TRUE, 0x00ffffff, 0x00ffffff,FALSE);
47static reloc_howto_type howto_reloc_abs32 =
48 HOWTO (ABS32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,0,"abs32", TRUE, 0xffffffff,0xffffffff,FALSE);
49static reloc_howto_type howto_reloc_pcrel24 =
50 HOWTO (PCREL24, 0, 2, 24, TRUE, 0, complain_overflow_signed,0,"pcrel24", TRUE, 0x00ffffff,0x00ffffff,FALSE);
51static reloc_howto_type howto_reloc_pcrel13 =
52 HOWTO (PCREL13, 0, 2, 13, TRUE, 0, complain_overflow_signed,0,"pcrel13", TRUE, 0x00001fff,0x00001fff,FALSE);
53static reloc_howto_type howto_reloc_abs32codeshrunk =
54 HOWTO (ABS32CODE_SHRUNK, 0, 2, 24, TRUE, 0, complain_overflow_signed, 0,"callx->callj", TRUE, 0x00ffffff, 0x00ffffff,FALSE);
55static reloc_howto_type howto_reloc_abs32code =
56 HOWTO (ABS32CODE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,0,"callx", TRUE, 0xffffffff,0xffffffff,FALSE);
57
58static reloc_howto_type howto_align_table[] =
59{
60 HOWTO (ALIGNER, 0, 0x1, 0, FALSE, 0, complain_overflow_dont, 0, "align16", FALSE, 0, 0, FALSE),
61 HOWTO (ALIGNER, 0, 0x3, 0, FALSE, 0, complain_overflow_dont, 0, "align32", FALSE, 0, 0, FALSE),
62 HOWTO (ALIGNER, 0, 0x7, 0, FALSE, 0, complain_overflow_dont, 0, "align64", FALSE, 0, 0, FALSE),
63 HOWTO (ALIGNER, 0, 0xf, 0, FALSE, 0, complain_overflow_dont, 0, "align128", FALSE, 0, 0, FALSE),
64};
65
66static reloc_howto_type howto_done_align_table[] =
67{
68 HOWTO (ALIGNDONE, 0x1, 0x1, 0, FALSE, 0, complain_overflow_dont, 0, "donealign16", FALSE, 0, 0, FALSE),
69 HOWTO (ALIGNDONE, 0x3, 0x3, 0, FALSE, 0, complain_overflow_dont, 0, "donealign32", FALSE, 0, 0, FALSE),
70 HOWTO (ALIGNDONE, 0x7, 0x7, 0, FALSE, 0, complain_overflow_dont, 0, "donealign64", FALSE, 0, 0, FALSE),
71 HOWTO (ALIGNDONE, 0xf, 0xf, 0, FALSE, 0, complain_overflow_dont, 0, "donealign128", FALSE, 0, 0, FALSE),
72};
252b5132
RH
73
74/* Swaps the information in an executable header taken from a raw byte
75 stream memory image, into the internal exec_header structure. */
76
116c20d2
NC
77static void
78bout_swap_exec_header_in (bfd *abfd,
79 struct external_exec *bytes,
80 struct internal_exec *execp)
252b5132 81{
252b5132 82 /* Now fill in fields in the execp, from the bytes in the raw data. */
116c20d2
NC
83 execp->a_info = H_GET_32 (abfd, bytes->e_info);
84 execp->a_text = GET_WORD (abfd, bytes->e_text);
85 execp->a_data = GET_WORD (abfd, bytes->e_data);
86 execp->a_bss = GET_WORD (abfd, bytes->e_bss);
87 execp->a_syms = GET_WORD (abfd, bytes->e_syms);
88 execp->a_entry = GET_WORD (abfd, bytes->e_entry);
89 execp->a_trsize = GET_WORD (abfd, bytes->e_trsize);
90 execp->a_drsize = GET_WORD (abfd, bytes->e_drsize);
91 execp->a_tload = GET_WORD (abfd, bytes->e_tload);
92 execp->a_dload = GET_WORD (abfd, bytes->e_dload);
93 execp->a_talign = bytes->e_talign[0];
94 execp->a_dalign = bytes->e_dalign[0];
95 execp->a_balign = bytes->e_balign[0];
252b5132
RH
96 execp->a_relaxable = bytes->e_relaxable[0];
97}
98
99/* Swaps the information in an internal exec header structure into the
100 supplied buffer ready for writing to disk. */
101
116c20d2
NC
102static void
103bout_swap_exec_header_out (bfd *abfd,
104 struct internal_exec *execp,
105 struct external_exec *bytes)
252b5132 106{
aebad5fe 107 /* Now fill in fields in the raw data, from the fields in the exec struct. */
dc810e39 108 H_PUT_32 (abfd, execp->a_info , bytes->e_info);
252b5132
RH
109 PUT_WORD (abfd, execp->a_text , bytes->e_text);
110 PUT_WORD (abfd, execp->a_data , bytes->e_data);
111 PUT_WORD (abfd, execp->a_bss , bytes->e_bss);
112 PUT_WORD (abfd, execp->a_syms , bytes->e_syms);
113 PUT_WORD (abfd, execp->a_entry , bytes->e_entry);
114 PUT_WORD (abfd, execp->a_trsize, bytes->e_trsize);
115 PUT_WORD (abfd, execp->a_drsize, bytes->e_drsize);
116 PUT_WORD (abfd, execp->a_tload , bytes->e_tload);
117 PUT_WORD (abfd, execp->a_dload , bytes->e_dload);
116c20d2
NC
118 bytes->e_talign[0] = execp->a_talign;
119 bytes->e_dalign[0] = execp->a_dalign;
120 bytes->e_balign[0] = execp->a_balign;
252b5132
RH
121 bytes->e_relaxable[0] = execp->a_relaxable;
122}
123
252b5132
RH
124/* Finish up the opening of a b.out file for reading. Fill in all the
125 fields that are not handled by common code. */
126
127static const bfd_target *
116c20d2 128b_out_callback (bfd *abfd)
252b5132
RH
129{
130 struct internal_exec *execp = exec_hdr (abfd);
131 unsigned long bss_start;
132
67a374a5 133 /* Architecture and machine type. */
116c20d2
NC
134 bfd_set_arch_mach (abfd,
135 bfd_arch_i960, /* B.out only used on i960. */
136 bfd_mach_i960_core /* Default. */
137 );
252b5132
RH
138
139 /* The positions of the string table and symbol table. */
bbb1afc8
AM
140 obj_str_filepos (abfd) = N_STROFF (execp);
141 obj_sym_filepos (abfd) = N_SYMOFF (execp);
252b5132 142
67a374a5 143 /* The alignments of the sections. */
252b5132
RH
144 obj_textsec (abfd)->alignment_power = execp->a_talign;
145 obj_datasec (abfd)->alignment_power = execp->a_dalign;
146 obj_bsssec (abfd)->alignment_power = execp->a_balign;
147
148 /* The starting addresses of the sections. */
149 obj_textsec (abfd)->vma = execp->a_tload;
150 obj_datasec (abfd)->vma = execp->a_dload;
151
152 obj_textsec (abfd)->lma = obj_textsec (abfd)->vma;
153 obj_datasec (abfd)->lma = obj_datasec (abfd)->vma;
154
67a374a5 155 /* And reload the sizes, since the aout module zaps them. */
eea6121a 156 obj_textsec (abfd)->size = execp->a_text;
252b5132 157
116c20d2 158 bss_start = execp->a_dload + execp->a_data; /* BSS = end of data section. */
252b5132
RH
159 obj_bsssec (abfd)->vma = align_power (bss_start, execp->a_balign);
160
161 obj_bsssec (abfd)->lma = obj_bsssec (abfd)->vma;
162
67a374a5 163 /* The file positions of the sections. */
bbb1afc8
AM
164 obj_textsec (abfd)->filepos = N_TXTOFF (execp);
165 obj_datasec (abfd)->filepos = N_DATOFF (execp);
252b5132 166
67a374a5 167 /* The file positions of the relocation info. */
bbb1afc8
AM
168 obj_textsec (abfd)->rel_filepos = N_TROFF (execp);
169 obj_datasec (abfd)->rel_filepos = N_DROFF (execp);
252b5132 170
116c20d2
NC
171 adata (abfd).page_size = 1; /* Not applicable. */
172 adata (abfd).segment_size = 1; /* Not applicable. */
173 adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE;
252b5132
RH
174
175 if (execp->a_relaxable)
176 abfd->flags |= BFD_IS_RELAXABLE;
177 return abfd->xvec;
178}
179
116c20d2
NC
180static const bfd_target *
181b_out_object_p (bfd *abfd)
182{
183 struct internal_exec anexec;
184 struct external_exec exec_bytes;
185 bfd_size_type amt = EXEC_BYTES_SIZE;
186
187 if (bfd_bread ((void *) &exec_bytes, amt, abfd) != amt)
188 {
189 if (bfd_get_error () != bfd_error_system_call)
190 bfd_set_error (bfd_error_wrong_format);
191 return 0;
192 }
193
194 anexec.a_info = H_GET_32 (abfd, exec_bytes.e_info);
195
bbb1afc8 196 if (N_BADMAG (&anexec))
116c20d2
NC
197 {
198 bfd_set_error (bfd_error_wrong_format);
199 return 0;
200 }
201
202 bout_swap_exec_header_in (abfd, &exec_bytes, &anexec);
203 return aout_32_some_aout_object_p (abfd, &anexec, b_out_callback);
204}
205
67a374a5
NC
206struct bout_data_struct
207 {
252b5132
RH
208 struct aoutdata a;
209 struct internal_exec e;
67a374a5 210 };
252b5132 211
b34976b6 212static bfd_boolean
116c20d2 213b_out_mkobject (bfd *abfd)
252b5132
RH
214{
215 struct bout_data_struct *rawptr;
dc810e39 216 bfd_size_type amt = sizeof (struct bout_data_struct);
252b5132 217
116c20d2 218 rawptr = bfd_zalloc (abfd, amt);
252b5132 219 if (rawptr == NULL)
b34976b6 220 return FALSE;
252b5132
RH
221
222 abfd->tdata.bout_data = rawptr;
223 exec_hdr (abfd) = &rawptr->e;
224
116c20d2
NC
225 obj_textsec (abfd) = NULL;
226 obj_datasec (abfd) = NULL;
227 obj_bsssec (abfd) = NULL;
252b5132 228
b34976b6 229 return TRUE;
252b5132
RH
230}
231
232static int
116c20d2 233b_out_symbol_cmp (const void * a_ptr, const void * b_ptr)
252b5132 234{
67a374a5
NC
235 struct aout_symbol ** a = (struct aout_symbol **) a_ptr;
236 struct aout_symbol ** b = (struct aout_symbol **) b_ptr;
252b5132
RH
237 asection *sec;
238 bfd_vma av, bv;
239
67a374a5 240 /* Primary key is address. */
252b5132
RH
241 sec = bfd_get_section (&(*a)->symbol);
242 av = sec->output_section->vma + sec->output_offset + (*a)->symbol.value;
243 sec = bfd_get_section (&(*b)->symbol);
244 bv = sec->output_section->vma + sec->output_offset + (*b)->symbol.value;
245
246 if (av < bv)
247 return -1;
248 if (av > bv)
249 return 1;
250
116c20d2
NC
251 /* Secondary key puts CALLNAME syms last and BALNAME syms first,
252 so that they have the best chance of being contiguous. */
252b5132
RH
253 if (IS_BALNAME ((*a)->other) || IS_CALLNAME ((*b)->other))
254 return -1;
255 if (IS_CALLNAME ((*a)->other) || IS_BALNAME ((*b)->other))
256 return 1;
257
258 return 0;
259}
260
b34976b6 261static bfd_boolean
116c20d2
NC
262b_out_squirt_out_relocs (bfd *abfd, asection *section)
263{
264 arelent **generic;
265 int r_extern = 0;
266 int r_idx;
267 int incode_mask;
268 int len_1;
269 unsigned int count = section->reloc_count;
270 struct relocation_info *native, *natptr;
271 bfd_size_type natsize;
272 int extern_mask, pcrel_mask, len_2, callj_mask;
273
274 if (count == 0)
275 return TRUE;
276
277 generic = section->orelocation;
278 natsize = (bfd_size_type) count * sizeof (struct relocation_info);
279 native = bfd_malloc (natsize);
280 if (!native && natsize != 0)
281 return FALSE;
282
283 if (bfd_header_big_endian (abfd))
284 {
285 /* Big-endian bit field allocation order. */
286 pcrel_mask = 0x80;
287 extern_mask = 0x10;
288 len_2 = 0x40;
289 len_1 = 0x20;
290 callj_mask = 0x02;
291 incode_mask = 0x08;
292 }
293 else
294 {
295 /* Little-endian bit field allocation order. */
296 pcrel_mask = 0x01;
297 extern_mask = 0x08;
298 len_2 = 0x04;
299 len_1 = 0x02;
300 callj_mask = 0x40;
301 incode_mask = 0x10;
302 }
303
304 for (natptr = native; count > 0; --count, ++natptr, ++generic)
305 {
306 arelent *g = *generic;
307 unsigned char *raw = (unsigned char *) natptr;
308 asymbol *sym = *(g->sym_ptr_ptr);
309 asection *output_section = sym->section->output_section;
310
311 H_PUT_32 (abfd, g->address, raw);
312 /* Find a type in the output format which matches the input howto -
313 at the moment we assume input format == output format FIXME!! */
314 r_idx = 0;
315 /* FIXME: Need callj stuff here, and to check the howto entries to
316 be sure they are real for this architecture. */
317 if (g->howto== &howto_reloc_callj)
318 raw[7] = callj_mask + pcrel_mask + len_2;
319 else if (g->howto == &howto_reloc_pcrel24)
320 raw[7] = pcrel_mask + len_2;
321 else if (g->howto == &howto_reloc_pcrel13)
322 raw[7] = pcrel_mask + len_1;
323 else if (g->howto == &howto_reloc_abs32code)
324 raw[7] = len_2 + incode_mask;
325 else if (g->howto >= howto_align_table
326 && g->howto <= (howto_align_table + ARRAY_SIZE (howto_align_table) - 1))
327 {
328 /* symnum == -2; extern_mask not set, pcrel_mask set. */
329 r_idx = -2;
330 r_extern = 0;
331 raw[7] = (pcrel_mask
332 | ((g->howto - howto_align_table) << 1));
333 }
334 else
335 raw[7] = len_2;
336
337 if (r_idx != 0)
338 /* Already mucked with r_extern, r_idx. */;
339 else if (bfd_is_com_section (output_section)
340 || bfd_is_abs_section (output_section)
341 || bfd_is_und_section (output_section))
342 {
343 if (bfd_abs_section_ptr->symbol == sym)
344 {
345 /* Whoops, looked like an abs symbol, but is really an offset
346 from the abs section. */
347 r_idx = 0;
348 r_extern = 0;
349 }
350 else
351 {
352 /* Fill in symbol. */
353 r_extern = 1;
354 r_idx = (*g->sym_ptr_ptr)->udata.i;
355 }
356 }
357 else
358 {
359 /* Just an ordinary section. */
360 r_extern = 0;
361 r_idx = output_section->target_index;
362 }
363
364 if (bfd_header_big_endian (abfd))
365 {
366 raw[4] = (unsigned char) (r_idx >> 16);
367 raw[5] = (unsigned char) (r_idx >> 8);
368 raw[6] = (unsigned char) (r_idx );
369 }
370 else
371 {
372 raw[6] = (unsigned char) (r_idx >> 16);
373 raw[5] = (unsigned char) (r_idx>> 8);
374 raw[4] = (unsigned char) (r_idx );
375 }
376
377 if (r_extern)
378 raw[7] |= extern_mask;
379 }
380
381 if (bfd_bwrite ((void *) native, natsize, abfd) != natsize)
382 {
383 free (native);
384 return FALSE;
385 }
386
387 free (native);
388
389 return TRUE;
390}
391
392static bfd_boolean
393b_out_write_object_contents (bfd *abfd)
252b5132
RH
394{
395 struct external_exec swapped_hdr;
dc810e39 396 bfd_size_type amt;
252b5132
RH
397
398 if (! aout_32_make_sections (abfd))
b34976b6 399 return FALSE;
252b5132
RH
400
401 exec_hdr (abfd)->a_info = BMAGIC;
402
eea6121a
AM
403 exec_hdr (abfd)->a_text = obj_textsec (abfd)->size;
404 exec_hdr (abfd)->a_data = obj_datasec (abfd)->size;
405 exec_hdr (abfd)->a_bss = obj_bsssec (abfd)->size;
70bfecec 406 exec_hdr (abfd)->a_syms = bfd_get_symcount (abfd) * 12;
252b5132 407 exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);
70bfecec
AM
408 exec_hdr (abfd)->a_trsize = (obj_textsec (abfd)->reloc_count) * 8;
409 exec_hdr (abfd)->a_drsize = (obj_datasec (abfd)->reloc_count) * 8;
252b5132
RH
410
411 exec_hdr (abfd)->a_talign = obj_textsec (abfd)->alignment_power;
412 exec_hdr (abfd)->a_dalign = obj_datasec (abfd)->alignment_power;
413 exec_hdr (abfd)->a_balign = obj_bsssec (abfd)->alignment_power;
414
415 exec_hdr (abfd)->a_tload = obj_textsec (abfd)->vma;
416 exec_hdr (abfd)->a_dload = obj_datasec (abfd)->vma;
417
418 bout_swap_exec_header_out (abfd, exec_hdr (abfd), &swapped_hdr);
419
dc810e39 420 amt = EXEC_BYTES_SIZE;
252b5132 421 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
116c20d2 422 || bfd_bwrite ((void *) &swapped_hdr, amt, abfd) != amt)
b34976b6 423 return FALSE;
252b5132
RH
424
425 /* Now write out reloc info, followed by syms and strings */
426 if (bfd_get_symcount (abfd) != 0)
427 {
428 /* Make sure {CALL,BAL}NAME symbols remain adjacent on output
429 by sorting. This is complicated by the fact that stabs are
430 also ordered. Solve this by shifting all stabs to the end
431 in order, then sorting the rest. */
432
433 asymbol **outsyms, **p, **q;
434
435 outsyms = bfd_get_outsymbols (abfd);
436 p = outsyms + bfd_get_symcount (abfd);
437
438 for (q = p--; p >= outsyms; p--)
439 {
440 if ((*p)->flags & BSF_DEBUGGING)
441 {
442 asymbol *t = *--q;
443 *q = *p;
444 *p = t;
445 }
446 }
447
448 if (q > outsyms)
dc810e39
AM
449 qsort (outsyms, (size_t) (q - outsyms), sizeof (asymbol*),
450 b_out_symbol_cmp);
252b5132
RH
451
452 /* Back to your regularly scheduled program. */
bbb1afc8 453 if (bfd_seek (abfd, (file_ptr) (N_SYMOFF (exec_hdr (abfd))), SEEK_SET)
252b5132 454 != 0)
b34976b6 455 return FALSE;
252b5132
RH
456
457 if (! aout_32_write_syms (abfd))
b34976b6 458 return FALSE;
252b5132 459
bbb1afc8 460 if (bfd_seek (abfd, (file_ptr) (N_TROFF (exec_hdr (abfd))), SEEK_SET)
dc810e39 461 != 0)
b34976b6 462 return FALSE;
252b5132 463
b34976b6
AM
464 if (!b_out_squirt_out_relocs (abfd, obj_textsec (abfd)))
465 return FALSE;
bbb1afc8 466 if (bfd_seek (abfd, (file_ptr) (N_DROFF (exec_hdr (abfd))), SEEK_SET)
252b5132 467 != 0)
b34976b6 468 return FALSE;
252b5132 469
b34976b6
AM
470 if (!b_out_squirt_out_relocs (abfd, obj_datasec (abfd)))
471 return FALSE;
252b5132 472 }
b34976b6 473 return TRUE;
252b5132
RH
474}
475\f
67a374a5 476/* Some reloc hackery. */
252b5132
RH
477
478#define CALLS 0x66003800 /* Template for 'calls' instruction */
07d6d2b8 479#define BAL 0x0b000000 /* Template for 'bal' instruction */
252b5132
RH
480#define BAL_MASK 0x00ffffff
481#define BALX 0x85f00000 /* Template for 'balx' instruction */
482#define BALX_MASK 0x0007ffff
483#define CALL 0x09000000
484#define PCREL13_MASK 0x1fff
485
252b5132
RH
486#define output_addr(sec) ((sec)->output_offset+(sec)->output_section->vma)
487
116c20d2
NC
488static bfd_vma
489get_value (arelent *reloc,
490 struct bfd_link_info *link_info,
491 asection *input_section)
492{
493 bfd_vma value;
494 asymbol *symbol = *(reloc->sym_ptr_ptr);
495
496 /* A symbol holds a pointer to a section, and an offset from the
497 base of the section. To relocate, we find where the section will
498 live in the output and add that in. */
499 if (bfd_is_und_section (symbol->section))
500 {
501 struct bfd_link_hash_entry *h;
502
503 /* The symbol is undefined in this BFD. Look it up in the
504 global linker hash table. FIXME: This should be changed when
505 we convert b.out to use a specific final_link function and
506 change the interface to bfd_relax_section to not require the
507 generic symbols. */
508 h = bfd_wrapped_link_hash_lookup (input_section->owner, link_info,
509 bfd_asymbol_name (symbol),
510 FALSE, FALSE, TRUE);
511 if (h != (struct bfd_link_hash_entry *) NULL
512 && (h->type == bfd_link_hash_defined
513 || h->type == bfd_link_hash_defweak))
514 value = h->u.def.value + output_addr (h->u.def.section);
515 else if (h != (struct bfd_link_hash_entry *) NULL
516 && h->type == bfd_link_hash_common)
517 value = h->u.c.size;
518 else
519 {
1a72702b
AM
520 (*link_info->callbacks->undefined_symbol)
521 (link_info, bfd_asymbol_name (symbol),
522 input_section->owner, input_section, reloc->address, TRUE);
116c20d2
NC
523 value = 0;
524 }
525 }
526 else
527 value = symbol->value + output_addr (symbol->section);
528
529 /* Add the value contained in the relocation. */
530 value += reloc->addend;
531
532 return value;
533}
534
67a374a5
NC
535/* Magic to turn callx into calljx. */
536
252b5132 537static bfd_reloc_status_type
116c20d2
NC
538calljx_callback (bfd *abfd,
539 struct bfd_link_info *link_info,
540 arelent *reloc_entry,
541 void * src,
542 void * dst,
543 asection *input_section)
252b5132
RH
544{
545 int word = bfd_get_32 (abfd, src);
546 asymbol *symbol_in = *(reloc_entry->sym_ptr_ptr);
547 aout_symbol_type *symbol = aout_symbol (symbol_in);
548 bfd_vma value;
549
550 value = get_value (reloc_entry, link_info, input_section);
551
552 if (IS_CALLNAME (symbol->other))
553 {
554 aout_symbol_type *balsym = symbol+1;
555 int inst = bfd_get_32 (abfd, (bfd_byte *) src-4);
116c20d2 556
67a374a5 557 /* The next symbol should be an N_BALNAME. */
252b5132
RH
558 BFD_ASSERT (IS_BALNAME (balsym->other));
559 inst &= BALX_MASK;
560 inst |= BALX;
dc810e39 561 bfd_put_32 (abfd, (bfd_vma) inst, (bfd_byte *) dst-4);
252b5132
RH
562 symbol = balsym;
563 value = (symbol->symbol.value
564 + output_addr (symbol->symbol.section));
565 }
566
567 word += value + reloc_entry->addend;
568
dc810e39 569 bfd_put_32 (abfd, (bfd_vma) word, dst);
252b5132
RH
570 return bfd_reloc_ok;
571}
572
67a374a5
NC
573/* Magic to turn call into callj. */
574
252b5132 575static bfd_reloc_status_type
116c20d2
NC
576callj_callback (bfd *abfd,
577 struct bfd_link_info *link_info,
578 arelent *reloc_entry,
579 void * data,
580 unsigned int srcidx,
581 unsigned int dstidx,
582 asection *input_section,
583 bfd_boolean shrinking)
252b5132
RH
584{
585 int word = bfd_get_32 (abfd, (bfd_byte *) data + srcidx);
586 asymbol *symbol_in = *(reloc_entry->sym_ptr_ptr);
587 aout_symbol_type *symbol = aout_symbol (symbol_in);
588 bfd_vma value;
589
590 value = get_value (reloc_entry, link_info, input_section);
591
116c20d2
NC
592 if (IS_OTHER (symbol->other))
593 /* Call to a system procedure - replace code with system
594 procedure number. */
595 word = CALLS | (symbol->other - 1);
596
597 else if (IS_CALLNAME (symbol->other))
252b5132
RH
598 {
599 aout_symbol_type *balsym = symbol+1;
600
601 /* The next symbol should be an N_BALNAME. */
116c20d2 602 BFD_ASSERT (IS_BALNAME (balsym->other));
aebad5fe 603
252b5132
RH
604 /* We are calling a leaf, so replace the call instruction with a
605 bal. */
606 word = BAL | ((word
607 + output_addr (balsym->symbol.section)
608 + balsym->symbol.value + reloc_entry->addend
609 - dstidx
610 - output_addr (input_section))
611 & BAL_MASK);
612 }
613 else if ((symbol->symbol.flags & BSF_SECTION_SYM) != 0)
614 {
615 /* A callj against a symbol in the same section is a fully
07d6d2b8
AM
616 resolved relative call. We don't need to do anything here.
617 If the symbol is not in the same section, I'm not sure what
618 to do; fortunately, this case will probably never arise. */
252b5132
RH
619 BFD_ASSERT (! shrinking);
620 BFD_ASSERT (symbol->symbol.section == input_section);
621 }
622 else
116c20d2
NC
623 word = CALL | (((word & BAL_MASK)
624 + value
625 + reloc_entry->addend
626 - (shrinking ? dstidx : 0)
627 - output_addr (input_section))
628 & BAL_MASK);
629
dc810e39 630 bfd_put_32 (abfd, (bfd_vma) word, (bfd_byte *) data + dstidx);
252b5132
RH
631 return bfd_reloc_ok;
632}
633
252b5132 634static reloc_howto_type *
157090f7
AM
635b_out_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
636 bfd_reloc_code_real_type code)
252b5132
RH
637{
638 switch (code)
639 {
640 default:
641 return 0;
642 case BFD_RELOC_I960_CALLJ:
643 return &howto_reloc_callj;
644 case BFD_RELOC_32:
645 case BFD_RELOC_CTOR:
646 return &howto_reloc_abs32;
647 case BFD_RELOC_24_PCREL:
648 return &howto_reloc_pcrel24;
649 }
650}
651
157090f7
AM
652static reloc_howto_type *
653b_out_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
654 const char *r_name)
655{
656 if (strcasecmp (howto_reloc_callj.name, r_name) == 0)
657 return &howto_reloc_callj;
658 if (strcasecmp (howto_reloc_abs32.name, r_name) == 0)
659 return &howto_reloc_abs32;
660 if (strcasecmp (howto_reloc_pcrel24.name, r_name) == 0)
661 return &howto_reloc_pcrel24;
662
663 return NULL;
664}
665
67a374a5 666/* Allocate enough room for all the reloc entries, plus pointers to them all. */
252b5132 667
b34976b6 668static bfd_boolean
116c20d2 669b_out_slurp_reloc_table (bfd *abfd, sec_ptr asect, asymbol **symbols)
252b5132 670{
116c20d2 671 struct relocation_info *rptr;
dc810e39
AM
672 unsigned int counter;
673 arelent *cache_ptr;
252b5132
RH
674 int extern_mask, pcrel_mask, callj_mask, length_shift;
675 int incode_mask;
676 int size_mask;
677 bfd_vma prev_addr = 0;
678 unsigned int count;
dc810e39 679 bfd_size_type reloc_size, amt;
252b5132
RH
680 struct relocation_info *relocs;
681 arelent *reloc_cache;
682
683 if (asect->relocation)
b34976b6 684 return TRUE;
67a374a5 685
252b5132 686 if (!aout_32_slurp_symbol_table (abfd))
b34976b6 687 return FALSE;
252b5132 688
67a374a5 689 if (asect == obj_datasec (abfd))
116c20d2
NC
690 reloc_size = exec_hdr (abfd)->a_drsize;
691 else if (asect == obj_textsec (abfd))
692 reloc_size = exec_hdr (abfd)->a_trsize;
693 else if (asect == obj_bsssec (abfd))
694 reloc_size = 0;
695 else
67a374a5 696 {
116c20d2
NC
697 bfd_set_error (bfd_error_invalid_operation);
698 return FALSE;
67a374a5 699 }
252b5132 700
dc810e39 701 if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
b34976b6 702 return FALSE;
252b5132
RH
703 count = reloc_size / sizeof (struct relocation_info);
704
116c20d2 705 relocs = bfd_malloc (reloc_size);
252b5132 706 if (!relocs && reloc_size != 0)
b34976b6 707 return FALSE;
67a374a5 708
dc810e39 709 amt = ((bfd_size_type) count + 1) * sizeof (arelent);
116c20d2 710 reloc_cache = bfd_malloc (amt);
67a374a5
NC
711 if (!reloc_cache)
712 {
713 if (relocs != NULL)
dc810e39 714 free (relocs);
b34976b6 715 return FALSE;
67a374a5 716 }
252b5132 717
116c20d2 718 if (bfd_bread ((void *) relocs, reloc_size, abfd) != reloc_size)
67a374a5
NC
719 {
720 free (reloc_cache);
721 if (relocs != NULL)
722 free (relocs);
b34976b6 723 return FALSE;
67a374a5 724 }
252b5132 725
67a374a5
NC
726 if (bfd_header_big_endian (abfd))
727 {
728 /* Big-endian bit field allocation order. */
729 pcrel_mask = 0x80;
730 extern_mask = 0x10;
731 incode_mask = 0x08;
732 callj_mask = 0x02;
733 size_mask = 0x20;
734 length_shift = 5;
735 }
736 else
737 {
738 /* Little-endian bit field allocation order. */
739 pcrel_mask = 0x01;
740 extern_mask = 0x08;
741 incode_mask = 0x10;
742 callj_mask = 0x40;
743 size_mask = 0x02;
744 length_shift = 1;
745 }
252b5132
RH
746
747 for (rptr = relocs, cache_ptr = reloc_cache, counter = 0;
748 counter < count;
749 counter++, rptr++, cache_ptr++)
750 {
751 unsigned char *raw = (unsigned char *)rptr;
752 unsigned int symnum;
67a374a5 753
dc810e39 754 cache_ptr->address = H_GET_32 (abfd, raw + 0);
252b5132 755 cache_ptr->howto = 0;
67a374a5 756
252b5132 757 if (bfd_header_big_endian (abfd))
252b5132 758 symnum = (raw[4] << 16) | (raw[5] << 8) | raw[6];
252b5132 759 else
252b5132 760 symnum = (raw[6] << 16) | (raw[5] << 8) | raw[4];
252b5132
RH
761
762 if (raw[7] & extern_mask)
67a374a5 763 {
08da05b0 764 /* If this is set then the r_index is an index into the symbol table;
67a374a5
NC
765 if the bit is not set then r_index contains a section map.
766 We either fill in the sym entry with a pointer to the symbol,
767 or point to the correct section. */
252b5132
RH
768 cache_ptr->sym_ptr_ptr = symbols + symnum;
769 cache_ptr->addend = 0;
67a374a5
NC
770 }
771 else
252b5132 772 {
67a374a5
NC
773 /* In a.out symbols are relative to the beginning of the
774 file rather than sections ?
775 (look in translate_from_native_sym_flags)
776 The reloc entry addend has added to it the offset into the
777 file of the data, so subtract the base to make the reloc
778 section relative. */
779 int s;
780
781 /* Sign-extend symnum from 24 bits to whatever host uses. */
252b5132
RH
782 s = symnum;
783 if (s & (1 << 23))
b6518b38 784 s |= (~0U) << 24;
67a374a5
NC
785
786 cache_ptr->sym_ptr_ptr = (asymbol **)NULL;
787 switch (s)
252b5132 788 {
67a374a5
NC
789 case N_TEXT:
790 case N_TEXT | N_EXT:
791 cache_ptr->sym_ptr_ptr = obj_textsec (abfd)->symbol_ptr_ptr;
792 cache_ptr->addend = - obj_textsec (abfd)->vma;
793 break;
794 case N_DATA:
795 case N_DATA | N_EXT:
796 cache_ptr->sym_ptr_ptr = obj_datasec (abfd)->symbol_ptr_ptr;
797 cache_ptr->addend = - obj_datasec (abfd)->vma;
798 break;
799 case N_BSS:
800 case N_BSS | N_EXT:
801 cache_ptr->sym_ptr_ptr = obj_bsssec (abfd)->symbol_ptr_ptr;
802 cache_ptr->addend = - obj_bsssec (abfd)->vma;
803 break;
804 case N_ABS:
805 case N_ABS | N_EXT:
806 cache_ptr->sym_ptr_ptr = obj_bsssec (abfd)->symbol_ptr_ptr;
807 cache_ptr->addend = 0;
808 break;
809 case -2: /* .align */
810 if (raw[7] & pcrel_mask)
811 {
812 cache_ptr->howto = &howto_align_table[(raw[7] >> length_shift) & 3];
813 cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
814 }
815 else
816 {
817 /* .org? */
818 abort ();
819 }
820 cache_ptr->addend = 0;
821 break;
822 default:
116c20d2 823 BFD_ASSERT (FALSE);
67a374a5 824 break;
252b5132 825 }
252b5132
RH
826 }
827
67a374a5 828 /* The i960 only has a few relocation types:
252b5132
RH
829 abs 32-bit and pcrel 24bit. except for callj's! */
830 if (cache_ptr->howto != 0)
831 ;
832 else if (raw[7] & callj_mask)
67a374a5
NC
833 {
834 cache_ptr->howto = &howto_reloc_callj;
835 }
252b5132 836 else if ( raw[7] & pcrel_mask)
252b5132 837 {
67a374a5
NC
838 if (raw[7] & size_mask)
839 cache_ptr->howto = &howto_reloc_pcrel13;
840 else
841 cache_ptr->howto = &howto_reloc_pcrel24;
252b5132 842 }
67a374a5 843 else
252b5132 844 {
67a374a5
NC
845 if (raw[7] & incode_mask)
846 cache_ptr->howto = &howto_reloc_abs32code;
847 else
848 cache_ptr->howto = &howto_reloc_abs32;
252b5132 849 }
67a374a5 850
252b5132 851 if (cache_ptr->address < prev_addr)
252b5132 852 {
67a374a5
NC
853 /* Ouch! this reloc is out of order, insert into the right place. */
854 arelent tmp;
855 arelent *cursor = cache_ptr-1;
856 bfd_vma stop = cache_ptr->address;
857
858 tmp = *cache_ptr;
859 while (cursor->address > stop && cursor >= reloc_cache)
860 {
861 cursor[1] = cursor[0];
862 cursor--;
863 }
864
865 cursor[1] = tmp;
252b5132 866 }
252b5132 867 else
116c20d2 868 prev_addr = cache_ptr->address;
252b5132
RH
869 }
870
252b5132
RH
871 if (relocs != NULL)
872 free (relocs);
873 asect->relocation = reloc_cache;
874 asect->reloc_count = count;
875
b34976b6 876 return TRUE;
252b5132
RH
877}
878
67a374a5
NC
879/* This is stupid. This function should be a boolean predicate. */
880
252b5132 881static long
116c20d2
NC
882b_out_canonicalize_reloc (bfd *abfd,
883 sec_ptr section,
884 arelent **relptr,
885 asymbol **symbols)
252b5132
RH
886{
887 arelent *tblptr;
888 unsigned int count;
889
890 if ((section->flags & SEC_CONSTRUCTOR) != 0)
891 {
892 arelent_chain *chain = section->constructor_chain;
67a374a5 893
252b5132
RH
894 for (count = 0; count < section->reloc_count; count++)
895 {
896 *relptr++ = &chain->relent;
897 chain = chain->next;
898 }
899 }
900 else
901 {
902 if (section->relocation == NULL
903 && ! b_out_slurp_reloc_table (abfd, section, symbols))
904 return -1;
905
906 tblptr = section->relocation;
907 for (count = 0; count++ < section->reloc_count;)
908 *relptr++ = tblptr++;
909 }
910
911 *relptr = NULL;
912
913 return section->reloc_count;
914}
915
916static long
116c20d2 917b_out_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
252b5132 918{
67a374a5
NC
919 if (bfd_get_format (abfd) != bfd_object)
920 {
921 bfd_set_error (bfd_error_invalid_operation);
922 return -1;
923 }
252b5132
RH
924
925 if (asect->flags & SEC_CONSTRUCTOR)
926 return sizeof (arelent *) * (asect->reloc_count + 1);
927
928 if (asect == obj_datasec (abfd))
929 return (sizeof (arelent *) *
116c20d2
NC
930 ((exec_hdr (abfd)->a_drsize / sizeof (struct relocation_info))
931 + 1));
252b5132
RH
932
933 if (asect == obj_textsec (abfd))
934 return (sizeof (arelent *) *
116c20d2
NC
935 ((exec_hdr (abfd)->a_trsize / sizeof (struct relocation_info))
936 + 1));
252b5132
RH
937
938 if (asect == obj_bsssec (abfd))
939 return 0;
940
941 bfd_set_error (bfd_error_invalid_operation);
942 return -1;
943}
67a374a5 944
252b5132 945\f
b34976b6 946static bfd_boolean
116c20d2
NC
947b_out_set_section_contents (bfd *abfd,
948 asection *section,
949 const void * location,
950 file_ptr offset,
951 bfd_size_type count)
252b5132 952{
82e51918 953 if (! abfd->output_has_begun)
67a374a5
NC
954 {
955 /* Set by bfd.c handler. */
956 if (! aout_32_make_sections (abfd))
b34976b6 957 return FALSE;
252b5132 958
70bfecec 959 obj_textsec (abfd)->filepos = sizeof (struct external_exec);
116c20d2 960 obj_datasec (abfd)->filepos = obj_textsec (abfd)->filepos
eea6121a 961 + obj_textsec (abfd)->size;
67a374a5 962 }
252b5132 963
67a374a5 964 /* Regardless, once we know what we're doing, we might as well get going. */
252b5132 965 if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0)
b34976b6 966 return FALSE;
252b5132 967
dc810e39 968 if (count == 0)
b34976b6 969 return TRUE;
67a374a5 970
116c20d2 971 return bfd_bwrite ((void *) location, count, abfd) == count;
252b5132
RH
972}
973
b34976b6 974static bfd_boolean
116c20d2
NC
975b_out_set_arch_mach (bfd *abfd,
976 enum bfd_architecture arch,
977 unsigned long machine)
252b5132 978{
116c20d2 979 bfd_default_set_arch_mach (abfd, arch, machine);
252b5132 980
67a374a5 981 if (arch == bfd_arch_unknown) /* Unknown machine arch is OK. */
b34976b6 982 return TRUE;
67a374a5
NC
983
984 if (arch == bfd_arch_i960) /* i960 default is OK. */
985 switch (machine)
986 {
987 case bfd_mach_i960_core:
988 case bfd_mach_i960_kb_sb:
989 case bfd_mach_i960_mc:
990 case bfd_mach_i960_xa:
991 case bfd_mach_i960_ca:
992 case bfd_mach_i960_ka_sa:
993 case bfd_mach_i960_jx:
994 case bfd_mach_i960_hx:
995 case 0:
b34976b6 996 return TRUE;
67a374a5 997 default:
b34976b6 998 return FALSE;
67a374a5 999 }
252b5132 1000
b34976b6 1001 return FALSE;
252b5132
RH
1002}
1003
1004static int
a6b96beb
AM
1005b_out_sizeof_headers (bfd *ignore_abfd ATTRIBUTE_UNUSED,
1006 struct bfd_link_info *info ATTRIBUTE_UNUSED)
252b5132 1007{
70bfecec 1008 return sizeof (struct external_exec);
252b5132 1009}
67a374a5 1010\f
252b5132 1011static void
116c20d2
NC
1012perform_slip (bfd *abfd,
1013 unsigned int slip,
1014 asection *input_section,
1015 bfd_vma value)
252b5132
RH
1016{
1017 asymbol **s;
1018
1019 s = _bfd_generic_link_get_symbols (abfd);
1020 BFD_ASSERT (s != (asymbol **) NULL);
1021
1022 /* Find all symbols past this point, and make them know
67a374a5 1023 what's happened. */
252b5132 1024 while (*s)
252b5132 1025 {
67a374a5 1026 asymbol *p = *s;
252b5132 1027
67a374a5
NC
1028 if (p->section == input_section)
1029 {
1030 /* This was pointing into this section, so mangle it. */
1031 if (p->value > value)
1032 {
1033 p->value -=slip;
252b5132 1034
67a374a5
NC
1035 if (p->udata.p != NULL)
1036 {
1037 struct generic_link_hash_entry *h;
1038
1039 h = (struct generic_link_hash_entry *) p->udata.p;
1040 BFD_ASSERT (h->root.type == bfd_link_hash_defined);
1041 h->root.u.def.value -= slip;
1042 BFD_ASSERT (h->root.u.def.value == p->value);
1043 }
1044 }
1045 }
1046 s++;
1047 }
252b5132
RH
1048}
1049
1050/* This routine works out if the thing we want to get to can be
1051 reached with a 24bit offset instead of a 32 bit one.
67a374a5 1052 If it can, then it changes the amode. */
252b5132
RH
1053
1054static int
116c20d2
NC
1055abs32code (bfd *abfd,
1056 asection *input_section,
1057 arelent *r,
1058 unsigned int shrink,
1059 struct bfd_link_info *link_info)
252b5132
RH
1060{
1061 bfd_vma value = get_value (r, link_info, input_section);
1062 bfd_vma dot = output_addr (input_section) + r->address;
1063 bfd_vma gap;
1064
1065 /* See if the address we're looking at within 2^23 bytes of where
1066 we are, if so then we can use a small branch rather than the
67a374a5 1067 jump we were going to. */
252b5132
RH
1068 gap = value - (dot - shrink);
1069
b6518b38 1070 if ((long)(-1UL << 23) < (long)gap && (long)gap < 1L << 23)
67a374a5
NC
1071 {
1072 /* Change the reloc type from 32bitcode possible 24, to 24bit
1073 possible 32. */
1074 r->howto = &howto_reloc_abs32codeshrunk;
1075 /* The place to relc moves back by four bytes. */
1076 r->address -=4;
1077
1078 /* This will be four bytes smaller in the long run. */
1079 shrink += 4 ;
1080 perform_slip (abfd, 4, input_section, r->address-shrink + 4);
1081 }
252b5132 1082
252b5132
RH
1083 return shrink;
1084}
1085
1086static int
116c20d2
NC
1087aligncode (bfd *abfd,
1088 asection *input_section,
1089 arelent *r,
1090 unsigned int shrink)
252b5132
RH
1091{
1092 bfd_vma dot = output_addr (input_section) + r->address;
252b5132
RH
1093 bfd_vma old_end;
1094 bfd_vma new_end;
dc810e39 1095 unsigned int shrink_delta;
252b5132
RH
1096 int size = r->howto->size;
1097
1098 /* Reduce the size of the alignment so that it's still aligned but
1099 smaller - the current size is already the same size as or bigger
1100 than the alignment required. */
1101
67a374a5 1102 /* Calculate the first byte following the padding before we optimize. */
252b5132 1103 old_end = ((dot + size ) & ~size) + size+1;
67a374a5
NC
1104 /* Work out where the new end will be - remember that we're smaller
1105 than we used to be. */
252b5132
RH
1106 new_end = ((dot - shrink + size) & ~size);
1107
252b5132
RH
1108 shrink_delta = (old_end - new_end) - shrink;
1109
1110 if (shrink_delta)
67a374a5
NC
1111 {
1112 /* Change the reloc so that it knows how far to align to. */
1113 r->howto = howto_done_align_table + (r->howto - howto_align_table);
252b5132 1114
67a374a5
NC
1115 /* Encode the stuff into the addend - for future use we need to
1116 know how big the reloc used to be. */
1117 r->addend = old_end - dot + r->address;
1118
1119 /* This will be N bytes smaller in the long run, adjust all the symbols. */
1120 perform_slip (abfd, shrink_delta, input_section, r->address - shrink);
1121 shrink += shrink_delta;
1122 }
252b5132 1123
252b5132
RH
1124 return shrink;
1125}
1126
b34976b6 1127static bfd_boolean
116c20d2
NC
1128b_out_bfd_relax_section (bfd *abfd,
1129 asection *i,
1130 struct bfd_link_info *link_info,
1131 bfd_boolean *again)
252b5132 1132{
67a374a5 1133 /* Get enough memory to hold the stuff. */
252b5132
RH
1134 bfd *input_bfd = i->owner;
1135 asection *input_section = i;
dc810e39 1136 unsigned int shrink = 0 ;
252b5132 1137 arelent **reloc_vector = NULL;
116c20d2 1138 long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
252b5132 1139
0e1862bb 1140 if (bfd_link_relocatable (link_info))
c8a1f254
NS
1141 (*link_info->callbacks->einfo)
1142 (_("%P%F: --relax and -r may not be used together\n"));
1143
252b5132 1144 if (reloc_size < 0)
b34976b6 1145 return FALSE;
252b5132
RH
1146
1147 /* We only run this relaxation once. It might work to run it
1148 multiple times, but it hasn't been tested. */
b34976b6 1149 *again = FALSE;
252b5132
RH
1150
1151 if (reloc_size)
1152 {
1153 long reloc_count;
1154
116c20d2 1155 reloc_vector = bfd_malloc ((bfd_size_type) reloc_size);
252b5132
RH
1156 if (reloc_vector == NULL && reloc_size != 0)
1157 goto error_return;
1158
67a374a5 1159 /* Get the relocs and think about them. */
252b5132
RH
1160 reloc_count =
1161 bfd_canonicalize_reloc (input_bfd, input_section, reloc_vector,
1162 _bfd_generic_link_get_symbols (input_bfd));
1163 if (reloc_count < 0)
1164 goto error_return;
1165 if (reloc_count > 0)
1166 {
1167 arelent **parent;
67a374a5 1168
252b5132
RH
1169 for (parent = reloc_vector; *parent; parent++)
1170 {
1171 arelent *r = *parent;
67a374a5 1172
252b5132
RH
1173 switch (r->howto->type)
1174 {
1175 case ALIGNER:
67a374a5 1176 /* An alignment reloc. */
252b5132
RH
1177 shrink = aligncode (abfd, input_section, r, shrink);
1178 break;
1179 case ABS32CODE:
67a374a5 1180 /* A 32bit reloc in an addressing mode. */
252b5132
RH
1181 shrink = abs32code (input_bfd, input_section, r, shrink,
1182 link_info);
1183 break;
1184 case ABS32CODE_SHRUNK:
dc810e39 1185 shrink += 4;
252b5132
RH
1186 break;
1187 }
1188 }
1189 }
1190 }
eea6121a 1191 input_section->size -= shrink;
252b5132
RH
1192
1193 if (reloc_vector != NULL)
1194 free (reloc_vector);
b34976b6 1195 return TRUE;
252b5132
RH
1196 error_return:
1197 if (reloc_vector != NULL)
1198 free (reloc_vector);
b34976b6 1199 return FALSE;
252b5132
RH
1200}
1201
1202static bfd_byte *
116c20d2
NC
1203b_out_bfd_get_relocated_section_contents (bfd *output_bfd,
1204 struct bfd_link_info *link_info,
1205 struct bfd_link_order *link_order,
1206 bfd_byte *data,
1207 bfd_boolean relocatable,
1208 asymbol **symbols)
252b5132 1209{
67a374a5 1210 /* Get enough memory to hold the stuff. */
252b5132
RH
1211 bfd *input_bfd = link_order->u.indirect.section->owner;
1212 asection *input_section = link_order->u.indirect.section;
116c20d2 1213 long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
252b5132
RH
1214 arelent **reloc_vector = NULL;
1215 long reloc_count;
1216
1217 if (reloc_size < 0)
1218 goto error_return;
1219
1049f94e
AM
1220 /* If producing relocatable output, don't bother to relax. */
1221 if (relocatable)
252b5132
RH
1222 return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
1223 link_order,
1049f94e 1224 data, relocatable,
252b5132
RH
1225 symbols);
1226
116c20d2 1227 reloc_vector = bfd_malloc ((bfd_size_type) reloc_size);
252b5132
RH
1228 if (reloc_vector == NULL && reloc_size != 0)
1229 goto error_return;
1230
67a374a5 1231 /* Read in the section. */
b34976b6
AM
1232 BFD_ASSERT (bfd_get_section_contents (input_bfd,
1233 input_section,
1234 data,
1235 (bfd_vma) 0,
eea6121a 1236 input_section->size));
252b5132
RH
1237
1238 reloc_count = bfd_canonicalize_reloc (input_bfd,
1239 input_section,
1240 reloc_vector,
1241 symbols);
1242 if (reloc_count < 0)
1243 goto error_return;
1244 if (reloc_count > 0)
1245 {
1246 arelent **parent = reloc_vector;
1247 arelent *reloc ;
252b5132
RH
1248 unsigned int dst_address = 0;
1249 unsigned int src_address = 0;
1250 unsigned int run;
1251 unsigned int idx;
1252
67a374a5 1253 /* Find how long a run we can do. */
252b5132
RH
1254 while (dst_address < link_order->size)
1255 {
1256 reloc = *parent;
1257 if (reloc)
1258 {
1259 /* Note that the relaxing didn't tie up the addresses in the
1260 relocation, so we use the original address to work out the
67a374a5 1261 run of non-relocated data. */
252b5132
RH
1262 BFD_ASSERT (reloc->address >= src_address);
1263 run = reloc->address - src_address;
1264 parent++;
1265 }
1266 else
116c20d2 1267 run = link_order->size - dst_address;
252b5132 1268
67a374a5
NC
1269 /* Copy the bytes. */
1270 for (idx = 0; idx < run; idx++)
1271 data[dst_address++] = data[src_address++];
252b5132 1272
67a374a5 1273 /* Now do the relocation. */
252b5132
RH
1274 if (reloc)
1275 {
1276 switch (reloc->howto->type)
1277 {
1278 case ABS32CODE:
1279 calljx_callback (input_bfd, link_info, reloc,
1280 src_address + data, dst_address + data,
1281 input_section);
67a374a5
NC
1282 src_address += 4;
1283 dst_address += 4;
252b5132
RH
1284 break;
1285 case ABS32:
1286 bfd_put_32 (input_bfd,
1287 (bfd_get_32 (input_bfd, data + src_address)
1288 + get_value (reloc, link_info, input_section)),
1289 data + dst_address);
67a374a5
NC
1290 src_address += 4;
1291 dst_address += 4;
252b5132
RH
1292 break;
1293 case CALLJ:
1294 callj_callback (input_bfd, link_info, reloc, data,
1295 src_address, dst_address, input_section,
b34976b6 1296 FALSE);
67a374a5
NC
1297 src_address += 4;
1298 dst_address += 4;
252b5132
RH
1299 break;
1300 case ALIGNDONE:
1301 BFD_ASSERT (reloc->addend >= src_address);
dc810e39 1302 BFD_ASSERT ((bfd_vma) reloc->addend
eea6121a 1303 <= input_section->size);
252b5132
RH
1304 src_address = reloc->addend;
1305 dst_address = ((dst_address + reloc->howto->size)
1306 & ~reloc->howto->size);
1307 break;
1308 case ABS32CODE_SHRUNK:
1309 /* This used to be a callx, but we've found out that a
1310 callj will reach, so do the right thing. */
1311 callj_callback (input_bfd, link_info, reloc, data,
1312 src_address + 4, dst_address, input_section,
b34976b6 1313 TRUE);
67a374a5
NC
1314 dst_address += 4;
1315 src_address += 8;
252b5132
RH
1316 break;
1317 case PCREL24:
1318 {
1319 long int word = bfd_get_32 (input_bfd,
1320 data + src_address);
1321 bfd_vma value;
1322
1323 value = get_value (reloc, link_info, input_section);
1324 word = ((word & ~BAL_MASK)
1325 | (((word & BAL_MASK)
1326 + value
1327 - output_addr (input_section)
1328 + reloc->addend)
1329 & BAL_MASK));
1330
dc810e39 1331 bfd_put_32 (input_bfd, (bfd_vma) word, data + dst_address);
67a374a5
NC
1332 dst_address += 4;
1333 src_address += 4;
252b5132
RH
1334
1335 }
1336 break;
252b5132
RH
1337 case PCREL13:
1338 {
1339 long int word = bfd_get_32 (input_bfd,
1340 data + src_address);
1341 bfd_vma value;
1342
1343 value = get_value (reloc, link_info, input_section);
1344 word = ((word & ~PCREL13_MASK)
1345 | (((word & PCREL13_MASK)
1346 + value
1347 + reloc->addend
1348 - output_addr (input_section))
1349 & PCREL13_MASK));
1350
dc810e39 1351 bfd_put_32 (input_bfd, (bfd_vma) word, data + dst_address);
67a374a5
NC
1352 dst_address += 4;
1353 src_address += 4;
252b5132
RH
1354 }
1355 break;
1356
1357 default:
eb6e10cb 1358 abort ();
252b5132
RH
1359 }
1360 }
1361 }
1362 }
1363 if (reloc_vector != NULL)
1364 free (reloc_vector);
1365 return data;
1366 error_return:
1367 if (reloc_vector != NULL)
1368 free (reloc_vector);
1369 return NULL;
1370}
67a374a5 1371\f
252b5132
RH
1372
1373/* Build the transfer vectors for Big and Little-Endian B.OUT files. */
1374
07d6d2b8 1375#define aout_32_find_line _bfd_nosymbols_find_line
60bb06bc 1376#define aout_32_get_symbol_version_string _bfd_nosymbols_get_symbol_version_string
07d6d2b8
AM
1377#define aout_32_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
1378#define aout_32_close_and_cleanup aout_32_bfd_free_cached_info
116c20d2 1379#define b_out_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
07d6d2b8
AM
1380#define b_out_bfd_link_add_symbols _bfd_generic_link_add_symbols
1381#define b_out_bfd_link_just_syms _bfd_generic_link_just_syms
1338dd10
PB
1382#define b_out_bfd_copy_link_hash_symbol_type \
1383 _bfd_generic_copy_link_hash_symbol_type
07d6d2b8
AM
1384#define b_out_bfd_final_link _bfd_generic_final_link
1385#define b_out_bfd_link_split_section _bfd_generic_link_split_section
1386#define b_out_bfd_gc_sections bfd_generic_gc_sections
1387#define b_out_bfd_lookup_section_flags bfd_generic_lookup_section_flags
1388#define b_out_bfd_merge_sections bfd_generic_merge_sections
1389#define b_out_bfd_is_group_section bfd_generic_is_group_section
1390#define b_out_bfd_discard_group bfd_generic_discard_group
1391#define b_out_section_already_linked _bfd_generic_section_already_linked
1392#define b_out_bfd_define_common_symbol bfd_generic_define_common_symbol
1393#define b_out_bfd_define_start_stop bfd_generic_define_start_stop
116c20d2 1394#define aout_32_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
07d6d2b8 1395#define b_out_bfd_link_check_relocs _bfd_generic_link_check_relocs
23186865 1396#define b_out_set_reloc _bfd_generic_set_reloc
252b5132 1397
6d00b590 1398extern const bfd_target bout_le_vec;
c3c89269 1399
6d00b590 1400const bfd_target bout_be_vec =
252b5132 1401{
116c20d2 1402 "b.out.big", /* Name. */
252b5132 1403 bfd_target_aout_flavour,
116c20d2
NC
1404 BFD_ENDIAN_LITTLE, /* Data byte order. */
1405 BFD_ENDIAN_BIG, /* Header byte order. */
1406 (HAS_RELOC | EXEC_P | /* Object flags. */
252b5132
RH
1407 HAS_LINENO | HAS_DEBUG |
1408 HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE ),
1409 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
116c20d2
NC
1410 '_', /* Symbol leading char. */
1411 ' ', /* AR_pad_char. */
1412 16, /* AR_max_namelen. */
0aabe54e 1413 0, /* match priority. */
252b5132
RH
1414 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1415 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
116c20d2 1416 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data. */
252b5132
RH
1417 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1418 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
116c20d2 1419 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Headers. */
d00dd7dc
AM
1420
1421 { /* bfd_check_format. */
1422 _bfd_dummy_target,
1423 b_out_object_p,
1424 bfd_generic_archive_p,
1425 _bfd_dummy_target
1426 },
1427 { /* bfd_set_format. */
1428 _bfd_bool_bfd_false_error,
1429 b_out_mkobject,
1430 _bfd_generic_mkarchive,
1431 _bfd_bool_bfd_false_error
1432 },
1433 { /* bfd_write_contents. */
1434 _bfd_bool_bfd_false_error,
1435 b_out_write_object_contents,
1436 _bfd_write_archive_contents,
1437 _bfd_bool_bfd_false_error
1438 },
1439
1440 BFD_JUMP_TABLE_GENERIC (aout_32),
1441 BFD_JUMP_TABLE_COPY (_bfd_generic),
1442 BFD_JUMP_TABLE_CORE (_bfd_nocore),
1443 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd),
1444 BFD_JUMP_TABLE_SYMBOLS (aout_32),
1445 BFD_JUMP_TABLE_RELOCS (b_out),
1446 BFD_JUMP_TABLE_WRITE (b_out),
1447 BFD_JUMP_TABLE_LINK (b_out),
1448 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1449
1450 &bout_le_vec,
aebad5fe 1451
116c20d2 1452 NULL
252b5132
RH
1453};
1454
6d00b590 1455const bfd_target bout_le_vec =
252b5132 1456{
116c20d2 1457 "b.out.little", /* Name. */
252b5132 1458 bfd_target_aout_flavour,
116c20d2
NC
1459 BFD_ENDIAN_LITTLE, /* Data byte order. */
1460 BFD_ENDIAN_LITTLE, /* Header byte order. */
1461 (HAS_RELOC | EXEC_P | /* Object flags. */
252b5132
RH
1462 HAS_LINENO | HAS_DEBUG |
1463 HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE ),
1464 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
116c20d2
NC
1465 '_', /* Symbol leading char. */
1466 ' ', /* AR_pad_char. */
1467 16, /* AR_max_namelen. */
0aabe54e 1468 0, /* match priority. */
252b5132
RH
1469 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1470 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
116c20d2 1471 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data. */
252b5132
RH
1472 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1473 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
116c20d2 1474 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Headers. */
252b5132 1475
d00dd7dc
AM
1476 { /* bfd_check_format. */
1477 _bfd_dummy_target,
1478 b_out_object_p,
1479 bfd_generic_archive_p,
1480 _bfd_dummy_target
1481 },
1482 { /* bfd_set_format. */
1483 _bfd_bool_bfd_false_error,
1484 b_out_mkobject,
1485 _bfd_generic_mkarchive,
1486 _bfd_bool_bfd_false_error
1487 },
1488 { /* bfd_write_contents. */
1489 _bfd_bool_bfd_false_error,
1490 b_out_write_object_contents,
1491 _bfd_write_archive_contents,
1492 _bfd_bool_bfd_false_error
1493 },
1494
1495 BFD_JUMP_TABLE_GENERIC (aout_32),
1496 BFD_JUMP_TABLE_COPY (_bfd_generic),
1497 BFD_JUMP_TABLE_CORE (_bfd_nocore),
1498 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd),
1499 BFD_JUMP_TABLE_SYMBOLS (aout_32),
1500 BFD_JUMP_TABLE_RELOCS (b_out),
1501 BFD_JUMP_TABLE_WRITE (b_out),
1502 BFD_JUMP_TABLE_LINK (b_out),
1503 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1504
1505 &bout_be_vec,
aebad5fe 1506
116c20d2 1507 NULL
252b5132 1508};
This page took 0.865256 seconds and 4 git commands to generate.