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