1130561Sobrien/* BFD back-end for Intel 960 b.out binaries.
2130561Sobrien   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3218822Sdim   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
4130561Sobrien   Free Software Foundation, Inc.
5130561Sobrien   Written by Cygnus Support.
6130561Sobrien
7218822Sdim   This file is part of BFD, the Binary File Descriptor library.
8130561Sobrien
9218822Sdim   This program is free software; you can redistribute it and/or modify
10218822Sdim   it under the terms of the GNU General Public License as published by
11218822Sdim   the Free Software Foundation; either version 2 of the License, or
12218822Sdim   (at your option) any later version.
13130561Sobrien
14218822Sdim   This program is distributed in the hope that it will be useful,
15218822Sdim   but WITHOUT ANY WARRANTY; without even the implied warranty of
16218822Sdim   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17218822Sdim   GNU General Public License for more details.
18130561Sobrien
19218822Sdim   You should have received a copy of the GNU General Public License
20218822Sdim   along with this program; if not, write to the Free Software
21218822Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
22130561Sobrien
23218822Sdim#include "sysdep.h"
24130561Sobrien#include "bfd.h"
25130561Sobrien#include "libbfd.h"
26130561Sobrien#include "bfdlink.h"
27130561Sobrien#include "genlink.h"
28130561Sobrien#include "bout.h"
29218822Sdim#include "libiberty.h"
30130561Sobrien
31130561Sobrien#include "aout/stab_gnu.h"
32130561Sobrien#include "libaout.h"		/* BFD a.out internal data structures.  */
33130561Sobrien
34218822Sdim#define ABS32CODE 0
35218822Sdim#define ABS32CODE_SHRUNK 1
36218822Sdim#define PCREL24 2
37218822Sdim#define CALLJ 3
38218822Sdim#define ABS32 4
39218822Sdim#define PCREL13 5
40218822Sdim#define ABS32_MAYBE_RELAXABLE 1
41218822Sdim#define ABS32_WAS_RELAXABLE 2
42130561Sobrien
43218822Sdim#define ALIGNER 10
44218822Sdim#define ALIGNDONE 11
45130561Sobrien
46218822Sdimstatic reloc_howto_type howto_reloc_callj =
47218822Sdim  HOWTO (CALLJ, 0, 2, 24, TRUE, 0, complain_overflow_signed, 0,"callj", TRUE, 0x00ffffff, 0x00ffffff,FALSE);
48218822Sdimstatic  reloc_howto_type howto_reloc_abs32 =
49218822Sdim  HOWTO (ABS32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,0,"abs32", TRUE, 0xffffffff,0xffffffff,FALSE);
50218822Sdimstatic reloc_howto_type howto_reloc_pcrel24 =
51218822Sdim  HOWTO (PCREL24, 0, 2, 24, TRUE, 0, complain_overflow_signed,0,"pcrel24", TRUE, 0x00ffffff,0x00ffffff,FALSE);
52218822Sdimstatic reloc_howto_type howto_reloc_pcrel13 =
53218822Sdim  HOWTO (PCREL13, 0, 2, 13, TRUE, 0, complain_overflow_signed,0,"pcrel13", TRUE, 0x00001fff,0x00001fff,FALSE);
54218822Sdimstatic reloc_howto_type howto_reloc_abs32codeshrunk =
55218822Sdim  HOWTO (ABS32CODE_SHRUNK, 0, 2, 24, TRUE, 0, complain_overflow_signed, 0,"callx->callj", TRUE, 0x00ffffff, 0x00ffffff,FALSE);
56218822Sdimstatic  reloc_howto_type howto_reloc_abs32code =
57218822Sdim  HOWTO (ABS32CODE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,0,"callx", TRUE, 0xffffffff,0xffffffff,FALSE);
58218822Sdim
59218822Sdimstatic reloc_howto_type howto_align_table[] =
60218822Sdim{
61218822Sdim  HOWTO (ALIGNER, 0, 0x1, 0, FALSE, 0, complain_overflow_dont, 0, "align16", FALSE, 0, 0, FALSE),
62218822Sdim  HOWTO (ALIGNER, 0, 0x3, 0, FALSE, 0, complain_overflow_dont, 0, "align32", FALSE, 0, 0, FALSE),
63218822Sdim  HOWTO (ALIGNER, 0, 0x7, 0, FALSE, 0, complain_overflow_dont, 0, "align64", FALSE, 0, 0, FALSE),
64218822Sdim  HOWTO (ALIGNER, 0, 0xf, 0, FALSE, 0, complain_overflow_dont, 0, "align128", FALSE, 0, 0, FALSE),
65218822Sdim};
66218822Sdim
67218822Sdimstatic reloc_howto_type howto_done_align_table[] =
68218822Sdim{
69218822Sdim  HOWTO (ALIGNDONE, 0x1, 0x1, 0, FALSE, 0, complain_overflow_dont, 0, "donealign16", FALSE, 0, 0, FALSE),
70218822Sdim  HOWTO (ALIGNDONE, 0x3, 0x3, 0, FALSE, 0, complain_overflow_dont, 0, "donealign32", FALSE, 0, 0, FALSE),
71218822Sdim  HOWTO (ALIGNDONE, 0x7, 0x7, 0, FALSE, 0, complain_overflow_dont, 0, "donealign64", FALSE, 0, 0, FALSE),
72218822Sdim  HOWTO (ALIGNDONE, 0xf, 0xf, 0, FALSE, 0, complain_overflow_dont, 0, "donealign128", FALSE, 0, 0, FALSE),
73218822Sdim};
74218822Sdim
75130561Sobrien/* Swaps the information in an executable header taken from a raw byte
76130561Sobrien   stream memory image, into the internal exec_header structure.  */
77130561Sobrien
78218822Sdimstatic void
79218822Sdimbout_swap_exec_header_in (bfd *abfd,
80218822Sdim			  struct external_exec *bytes,
81218822Sdim			  struct internal_exec *execp)
82130561Sobrien{
83130561Sobrien  /* Now fill in fields in the execp, from the bytes in the raw data.  */
84218822Sdim  execp->a_info      = H_GET_32 (abfd, bytes->e_info);
85218822Sdim  execp->a_text      = GET_WORD (abfd, bytes->e_text);
86218822Sdim  execp->a_data      = GET_WORD (abfd, bytes->e_data);
87218822Sdim  execp->a_bss       = GET_WORD (abfd, bytes->e_bss);
88218822Sdim  execp->a_syms      = GET_WORD (abfd, bytes->e_syms);
89218822Sdim  execp->a_entry     = GET_WORD (abfd, bytes->e_entry);
90218822Sdim  execp->a_trsize    = GET_WORD (abfd, bytes->e_trsize);
91218822Sdim  execp->a_drsize    = GET_WORD (abfd, bytes->e_drsize);
92218822Sdim  execp->a_tload     = GET_WORD (abfd, bytes->e_tload);
93218822Sdim  execp->a_dload     = GET_WORD (abfd, bytes->e_dload);
94218822Sdim  execp->a_talign    = bytes->e_talign[0];
95218822Sdim  execp->a_dalign    = bytes->e_dalign[0];
96218822Sdim  execp->a_balign    = bytes->e_balign[0];
97130561Sobrien  execp->a_relaxable = bytes->e_relaxable[0];
98130561Sobrien}
99130561Sobrien
100130561Sobrien/* Swaps the information in an internal exec header structure into the
101130561Sobrien   supplied buffer ready for writing to disk.  */
102130561Sobrien
103218822Sdimstatic void
104218822Sdimbout_swap_exec_header_out (bfd *abfd,
105218822Sdim			   struct internal_exec *execp,
106218822Sdim			   struct external_exec *bytes)
107130561Sobrien{
108130561Sobrien  /* Now fill in fields in the raw data, from the fields in the exec struct.  */
109130561Sobrien  H_PUT_32 (abfd, execp->a_info  , bytes->e_info);
110130561Sobrien  PUT_WORD (abfd, execp->a_text  , bytes->e_text);
111130561Sobrien  PUT_WORD (abfd, execp->a_data  , bytes->e_data);
112130561Sobrien  PUT_WORD (abfd, execp->a_bss   , bytes->e_bss);
113130561Sobrien  PUT_WORD (abfd, execp->a_syms  , bytes->e_syms);
114130561Sobrien  PUT_WORD (abfd, execp->a_entry , bytes->e_entry);
115130561Sobrien  PUT_WORD (abfd, execp->a_trsize, bytes->e_trsize);
116130561Sobrien  PUT_WORD (abfd, execp->a_drsize, bytes->e_drsize);
117130561Sobrien  PUT_WORD (abfd, execp->a_tload , bytes->e_tload);
118130561Sobrien  PUT_WORD (abfd, execp->a_dload , bytes->e_dload);
119218822Sdim  bytes->e_talign[0]    = execp->a_talign;
120218822Sdim  bytes->e_dalign[0]    = execp->a_dalign;
121218822Sdim  bytes->e_balign[0]    = execp->a_balign;
122130561Sobrien  bytes->e_relaxable[0] = execp->a_relaxable;
123130561Sobrien}
124130561Sobrien
125130561Sobrien/* Finish up the opening of a b.out file for reading.  Fill in all the
126130561Sobrien   fields that are not handled by common code.  */
127130561Sobrien
128130561Sobrienstatic const bfd_target *
129218822Sdimb_out_callback (bfd *abfd)
130130561Sobrien{
131130561Sobrien  struct internal_exec *execp = exec_hdr (abfd);
132130561Sobrien  unsigned long bss_start;
133130561Sobrien
134130561Sobrien  /* Architecture and machine type.  */
135218822Sdim  bfd_set_arch_mach (abfd,
136218822Sdim		     bfd_arch_i960,     /* B.out only used on i960.  */
137218822Sdim		     bfd_mach_i960_core /* Default.  */
138218822Sdim		     );
139130561Sobrien
140130561Sobrien  /* The positions of the string table and symbol table.  */
141130561Sobrien  obj_str_filepos (abfd) = N_STROFF (*execp);
142130561Sobrien  obj_sym_filepos (abfd) = N_SYMOFF (*execp);
143130561Sobrien
144130561Sobrien  /* The alignments of the sections.  */
145130561Sobrien  obj_textsec (abfd)->alignment_power = execp->a_talign;
146130561Sobrien  obj_datasec (abfd)->alignment_power = execp->a_dalign;
147130561Sobrien  obj_bsssec  (abfd)->alignment_power = execp->a_balign;
148130561Sobrien
149130561Sobrien  /* The starting addresses of the sections.  */
150130561Sobrien  obj_textsec (abfd)->vma = execp->a_tload;
151130561Sobrien  obj_datasec (abfd)->vma = execp->a_dload;
152130561Sobrien
153130561Sobrien  obj_textsec (abfd)->lma = obj_textsec (abfd)->vma;
154130561Sobrien  obj_datasec (abfd)->lma = obj_datasec (abfd)->vma;
155130561Sobrien
156130561Sobrien  /* And reload the sizes, since the aout module zaps them.  */
157218822Sdim  obj_textsec (abfd)->size = execp->a_text;
158130561Sobrien
159218822Sdim  bss_start = execp->a_dload + execp->a_data; /* BSS = end of data section.  */
160130561Sobrien  obj_bsssec (abfd)->vma = align_power (bss_start, execp->a_balign);
161130561Sobrien
162130561Sobrien  obj_bsssec (abfd)->lma = obj_bsssec (abfd)->vma;
163130561Sobrien
164130561Sobrien  /* The file positions of the sections.  */
165218822Sdim  obj_textsec (abfd)->filepos = N_TXTOFF (*execp);
166218822Sdim  obj_datasec (abfd)->filepos = N_DATOFF (*execp);
167130561Sobrien
168130561Sobrien  /* The file positions of the relocation info.  */
169218822Sdim  obj_textsec (abfd)->rel_filepos = N_TROFF (*execp);
170218822Sdim  obj_datasec (abfd)->rel_filepos =  N_DROFF (*execp);
171130561Sobrien
172218822Sdim  adata (abfd).page_size = 1;	/* Not applicable.  */
173218822Sdim  adata (abfd).segment_size = 1; /* Not applicable.  */
174218822Sdim  adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE;
175130561Sobrien
176130561Sobrien  if (execp->a_relaxable)
177130561Sobrien   abfd->flags |= BFD_IS_RELAXABLE;
178130561Sobrien  return abfd->xvec;
179130561Sobrien}
180130561Sobrien
181218822Sdimstatic const bfd_target *
182218822Sdimb_out_object_p (bfd *abfd)
183218822Sdim{
184218822Sdim  struct internal_exec anexec;
185218822Sdim  struct external_exec exec_bytes;
186218822Sdim  bfd_size_type amt = EXEC_BYTES_SIZE;
187218822Sdim
188218822Sdim  if (bfd_bread ((void *) &exec_bytes, amt, abfd) != amt)
189218822Sdim    {
190218822Sdim      if (bfd_get_error () != bfd_error_system_call)
191218822Sdim	bfd_set_error (bfd_error_wrong_format);
192218822Sdim      return 0;
193218822Sdim    }
194218822Sdim
195218822Sdim  anexec.a_info = H_GET_32 (abfd, exec_bytes.e_info);
196218822Sdim
197218822Sdim  if (N_BADMAG (anexec))
198218822Sdim    {
199218822Sdim      bfd_set_error (bfd_error_wrong_format);
200218822Sdim      return 0;
201218822Sdim    }
202218822Sdim
203218822Sdim  bout_swap_exec_header_in (abfd, &exec_bytes, &anexec);
204218822Sdim  return aout_32_some_aout_object_p (abfd, &anexec, b_out_callback);
205218822Sdim}
206218822Sdim
207130561Sobrienstruct bout_data_struct
208130561Sobrien  {
209130561Sobrien    struct aoutdata a;
210130561Sobrien    struct internal_exec e;
211130561Sobrien  };
212130561Sobrien
213130561Sobrienstatic bfd_boolean
214218822Sdimb_out_mkobject (bfd *abfd)
215130561Sobrien{
216130561Sobrien  struct bout_data_struct *rawptr;
217130561Sobrien  bfd_size_type amt = sizeof (struct bout_data_struct);
218130561Sobrien
219218822Sdim  rawptr = bfd_zalloc (abfd, amt);
220130561Sobrien  if (rawptr == NULL)
221130561Sobrien    return FALSE;
222130561Sobrien
223130561Sobrien  abfd->tdata.bout_data = rawptr;
224130561Sobrien  exec_hdr (abfd) = &rawptr->e;
225130561Sobrien
226218822Sdim  obj_textsec (abfd) = NULL;
227218822Sdim  obj_datasec (abfd) = NULL;
228218822Sdim  obj_bsssec (abfd)  = NULL;
229130561Sobrien
230130561Sobrien  return TRUE;
231130561Sobrien}
232130561Sobrien
233130561Sobrienstatic int
234218822Sdimb_out_symbol_cmp (const void * a_ptr, const void * b_ptr)
235130561Sobrien{
236130561Sobrien  struct aout_symbol ** a = (struct aout_symbol **) a_ptr;
237130561Sobrien  struct aout_symbol ** b = (struct aout_symbol **) b_ptr;
238130561Sobrien  asection *sec;
239130561Sobrien  bfd_vma av, bv;
240130561Sobrien
241130561Sobrien  /* Primary key is address.  */
242130561Sobrien  sec = bfd_get_section (&(*a)->symbol);
243130561Sobrien  av = sec->output_section->vma + sec->output_offset + (*a)->symbol.value;
244130561Sobrien  sec = bfd_get_section (&(*b)->symbol);
245130561Sobrien  bv = sec->output_section->vma + sec->output_offset + (*b)->symbol.value;
246130561Sobrien
247130561Sobrien  if (av < bv)
248130561Sobrien    return -1;
249130561Sobrien  if (av > bv)
250130561Sobrien    return 1;
251130561Sobrien
252218822Sdim  /* Secondary key puts CALLNAME syms last and BALNAME syms first,
253218822Sdim     so that they have the best chance of being contiguous.  */
254130561Sobrien  if (IS_BALNAME ((*a)->other) || IS_CALLNAME ((*b)->other))
255130561Sobrien    return -1;
256130561Sobrien  if (IS_CALLNAME ((*a)->other) || IS_BALNAME ((*b)->other))
257130561Sobrien    return 1;
258130561Sobrien
259130561Sobrien  return 0;
260130561Sobrien}
261130561Sobrien
262130561Sobrienstatic bfd_boolean
263218822Sdimb_out_squirt_out_relocs (bfd *abfd, asection *section)
264130561Sobrien{
265218822Sdim  arelent **generic;
266218822Sdim  int r_extern = 0;
267218822Sdim  int r_idx;
268218822Sdim  int incode_mask;
269218822Sdim  int len_1;
270218822Sdim  unsigned int count = section->reloc_count;
271218822Sdim  struct relocation_info *native, *natptr;
272218822Sdim  bfd_size_type natsize;
273218822Sdim  int extern_mask, pcrel_mask, len_2, callj_mask;
274218822Sdim
275218822Sdim  if (count == 0)
276218822Sdim    return TRUE;
277218822Sdim
278218822Sdim  generic = section->orelocation;
279218822Sdim  natsize = (bfd_size_type) count * sizeof (struct relocation_info);
280218822Sdim  native = bfd_malloc (natsize);
281218822Sdim  if (!native && natsize != 0)
282218822Sdim    return FALSE;
283218822Sdim
284218822Sdim  if (bfd_header_big_endian (abfd))
285218822Sdim    {
286218822Sdim      /* Big-endian bit field allocation order.  */
287218822Sdim      pcrel_mask  = 0x80;
288218822Sdim      extern_mask = 0x10;
289218822Sdim      len_2       = 0x40;
290218822Sdim      len_1       = 0x20;
291218822Sdim      callj_mask  = 0x02;
292218822Sdim      incode_mask = 0x08;
293218822Sdim    }
294218822Sdim  else
295218822Sdim    {
296218822Sdim      /* Little-endian bit field allocation order.  */
297218822Sdim      pcrel_mask  = 0x01;
298218822Sdim      extern_mask = 0x08;
299218822Sdim      len_2       = 0x04;
300218822Sdim      len_1       = 0x02;
301218822Sdim      callj_mask  = 0x40;
302218822Sdim      incode_mask = 0x10;
303218822Sdim    }
304218822Sdim
305218822Sdim  for (natptr = native; count > 0; --count, ++natptr, ++generic)
306218822Sdim    {
307218822Sdim      arelent *g = *generic;
308218822Sdim      unsigned char *raw = (unsigned char *) natptr;
309218822Sdim      asymbol *sym = *(g->sym_ptr_ptr);
310218822Sdim      asection *output_section = sym->section->output_section;
311218822Sdim
312218822Sdim      H_PUT_32 (abfd, g->address, raw);
313218822Sdim      /* Find a type in the output format which matches the input howto -
314218822Sdim	 at the moment we assume input format == output format FIXME!!  */
315218822Sdim      r_idx = 0;
316218822Sdim      /* FIXME:  Need callj stuff here, and to check the howto entries to
317218822Sdim	 be sure they are real for this architecture.  */
318218822Sdim      if (g->howto== &howto_reloc_callj)
319218822Sdim	raw[7] = callj_mask + pcrel_mask + len_2;
320218822Sdim      else if (g->howto == &howto_reloc_pcrel24)
321218822Sdim	raw[7] = pcrel_mask + len_2;
322218822Sdim      else if (g->howto == &howto_reloc_pcrel13)
323218822Sdim	raw[7] = pcrel_mask + len_1;
324218822Sdim      else if (g->howto == &howto_reloc_abs32code)
325218822Sdim	raw[7] = len_2 + incode_mask;
326218822Sdim      else if (g->howto >= howto_align_table
327218822Sdim	       && g->howto <= (howto_align_table + ARRAY_SIZE (howto_align_table) - 1))
328218822Sdim	{
329218822Sdim	  /* symnum == -2; extern_mask not set, pcrel_mask set.  */
330218822Sdim	  r_idx = -2;
331218822Sdim	  r_extern = 0;
332218822Sdim	  raw[7] = (pcrel_mask
333218822Sdim		    | ((g->howto - howto_align_table) << 1));
334218822Sdim	}
335218822Sdim      else
336218822Sdim	raw[7] = len_2;
337218822Sdim
338218822Sdim      if (r_idx != 0)
339218822Sdim	/* Already mucked with r_extern, r_idx.  */;
340218822Sdim      else if (bfd_is_com_section (output_section)
341218822Sdim	       || bfd_is_abs_section (output_section)
342218822Sdim	       || bfd_is_und_section (output_section))
343218822Sdim	{
344218822Sdim	  if (bfd_abs_section_ptr->symbol == sym)
345218822Sdim	    {
346218822Sdim	      /* Whoops, looked like an abs symbol, but is really an offset
347218822Sdim		 from the abs section.  */
348218822Sdim	      r_idx = 0;
349218822Sdim	      r_extern = 0;
350218822Sdim	    }
351218822Sdim	  else
352218822Sdim	    {
353218822Sdim	      /* Fill in symbol.  */
354218822Sdim	      r_extern = 1;
355218822Sdim	      r_idx = (*g->sym_ptr_ptr)->udata.i;
356218822Sdim	    }
357218822Sdim	}
358218822Sdim      else
359218822Sdim	{
360218822Sdim	  /* Just an ordinary section.  */
361218822Sdim	  r_extern = 0;
362218822Sdim	  r_idx  = output_section->target_index;
363218822Sdim	}
364218822Sdim
365218822Sdim      if (bfd_header_big_endian (abfd))
366218822Sdim	{
367218822Sdim	  raw[4] = (unsigned char) (r_idx >> 16);
368218822Sdim	  raw[5] = (unsigned char) (r_idx >>  8);
369218822Sdim	  raw[6] = (unsigned char) (r_idx      );
370218822Sdim	}
371218822Sdim      else
372218822Sdim	{
373218822Sdim	  raw[6] = (unsigned char) (r_idx >> 16);
374218822Sdim	  raw[5] = (unsigned char) (r_idx>>   8);
375218822Sdim	  raw[4] = (unsigned char) (r_idx      );
376218822Sdim	}
377218822Sdim
378218822Sdim      if (r_extern)
379218822Sdim	raw[7] |= extern_mask;
380218822Sdim    }
381218822Sdim
382218822Sdim  if (bfd_bwrite ((void *) native, natsize, abfd) != natsize)
383218822Sdim    {
384218822Sdim      free (native);
385218822Sdim      return FALSE;
386218822Sdim    }
387218822Sdim
388218822Sdim  free (native);
389218822Sdim
390218822Sdim  return TRUE;
391218822Sdim}
392218822Sdim
393218822Sdimstatic bfd_boolean
394218822Sdimb_out_write_object_contents (bfd *abfd)
395218822Sdim{
396130561Sobrien  struct external_exec swapped_hdr;
397130561Sobrien  bfd_size_type amt;
398130561Sobrien
399130561Sobrien  if (! aout_32_make_sections (abfd))
400130561Sobrien    return FALSE;
401130561Sobrien
402130561Sobrien  exec_hdr (abfd)->a_info = BMAGIC;
403130561Sobrien
404218822Sdim  exec_hdr (abfd)->a_text = obj_textsec (abfd)->size;
405218822Sdim  exec_hdr (abfd)->a_data = obj_datasec (abfd)->size;
406218822Sdim  exec_hdr (abfd)->a_bss = obj_bsssec (abfd)->size;
407218822Sdim  exec_hdr (abfd)->a_syms = bfd_get_symcount (abfd) * 12;
408130561Sobrien  exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);
409218822Sdim  exec_hdr (abfd)->a_trsize = (obj_textsec (abfd)->reloc_count) * 8;
410218822Sdim  exec_hdr (abfd)->a_drsize = (obj_datasec (abfd)->reloc_count) * 8;
411130561Sobrien
412130561Sobrien  exec_hdr (abfd)->a_talign = obj_textsec (abfd)->alignment_power;
413130561Sobrien  exec_hdr (abfd)->a_dalign = obj_datasec (abfd)->alignment_power;
414130561Sobrien  exec_hdr (abfd)->a_balign = obj_bsssec (abfd)->alignment_power;
415130561Sobrien
416130561Sobrien  exec_hdr (abfd)->a_tload = obj_textsec (abfd)->vma;
417130561Sobrien  exec_hdr (abfd)->a_dload = obj_datasec (abfd)->vma;
418130561Sobrien
419130561Sobrien  bout_swap_exec_header_out (abfd, exec_hdr (abfd), &swapped_hdr);
420130561Sobrien
421130561Sobrien  amt = EXEC_BYTES_SIZE;
422130561Sobrien  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
423218822Sdim      || bfd_bwrite ((void *) &swapped_hdr, amt, abfd) != amt)
424130561Sobrien    return FALSE;
425130561Sobrien
426130561Sobrien  /* Now write out reloc info, followed by syms and strings */
427130561Sobrien  if (bfd_get_symcount (abfd) != 0)
428130561Sobrien    {
429130561Sobrien      /* Make sure {CALL,BAL}NAME symbols remain adjacent on output
430130561Sobrien	 by sorting.  This is complicated by the fact that stabs are
431130561Sobrien	 also ordered.  Solve this by shifting all stabs to the end
432130561Sobrien	 in order, then sorting the rest.  */
433130561Sobrien
434130561Sobrien      asymbol **outsyms, **p, **q;
435130561Sobrien
436130561Sobrien      outsyms = bfd_get_outsymbols (abfd);
437130561Sobrien      p = outsyms + bfd_get_symcount (abfd);
438130561Sobrien
439130561Sobrien      for (q = p--; p >= outsyms; p--)
440130561Sobrien	{
441130561Sobrien	  if ((*p)->flags & BSF_DEBUGGING)
442130561Sobrien	    {
443130561Sobrien	      asymbol *t = *--q;
444130561Sobrien	      *q = *p;
445130561Sobrien	      *p = t;
446130561Sobrien	    }
447130561Sobrien	}
448130561Sobrien
449130561Sobrien      if (q > outsyms)
450130561Sobrien	qsort (outsyms, (size_t) (q - outsyms), sizeof (asymbol*),
451130561Sobrien	       b_out_symbol_cmp);
452130561Sobrien
453130561Sobrien      /* Back to your regularly scheduled program.  */
454218822Sdim      if (bfd_seek (abfd, (file_ptr) (N_SYMOFF (*exec_hdr (abfd))), SEEK_SET)
455130561Sobrien	  != 0)
456130561Sobrien	return FALSE;
457130561Sobrien
458130561Sobrien      if (! aout_32_write_syms (abfd))
459130561Sobrien	return FALSE;
460130561Sobrien
461218822Sdim      if (bfd_seek (abfd, (file_ptr) (N_TROFF (*exec_hdr (abfd))), SEEK_SET)
462130561Sobrien	  != 0)
463130561Sobrien	return FALSE;
464130561Sobrien
465130561Sobrien      if (!b_out_squirt_out_relocs (abfd, obj_textsec (abfd)))
466130561Sobrien	return FALSE;
467218822Sdim      if (bfd_seek (abfd, (file_ptr) (N_DROFF (*exec_hdr (abfd))), SEEK_SET)
468130561Sobrien	  != 0)
469130561Sobrien	return FALSE;
470130561Sobrien
471130561Sobrien      if (!b_out_squirt_out_relocs (abfd, obj_datasec (abfd)))
472130561Sobrien	return FALSE;
473130561Sobrien    }
474130561Sobrien  return TRUE;
475130561Sobrien}
476130561Sobrien
477130561Sobrien/* Some reloc hackery.  */
478130561Sobrien
479130561Sobrien#define CALLS	  0x66003800	/* Template for 'calls' instruction	*/
480130561Sobrien#define BAL	  0x0b000000	/* Template for 'bal' instruction 	*/
481130561Sobrien#define BAL_MASK  0x00ffffff
482130561Sobrien#define BALX	  0x85f00000	/* Template for 'balx' instruction	*/
483130561Sobrien#define BALX_MASK 0x0007ffff
484130561Sobrien#define CALL      0x09000000
485130561Sobrien#define PCREL13_MASK 0x1fff
486130561Sobrien
487130561Sobrien#define output_addr(sec) ((sec)->output_offset+(sec)->output_section->vma)
488130561Sobrien
489218822Sdimstatic bfd_vma
490218822Sdimget_value (arelent *reloc,
491218822Sdim	   struct bfd_link_info *link_info,
492218822Sdim	   asection *input_section)
493218822Sdim{
494218822Sdim  bfd_vma value;
495218822Sdim  asymbol *symbol = *(reloc->sym_ptr_ptr);
496218822Sdim
497218822Sdim  /* A symbol holds a pointer to a section, and an offset from the
498218822Sdim     base of the section.  To relocate, we find where the section will
499218822Sdim     live in the output and add that in.  */
500218822Sdim  if (bfd_is_und_section (symbol->section))
501218822Sdim    {
502218822Sdim      struct bfd_link_hash_entry *h;
503218822Sdim
504218822Sdim      /* The symbol is undefined in this BFD.  Look it up in the
505218822Sdim	 global linker hash table.  FIXME: This should be changed when
506218822Sdim	 we convert b.out to use a specific final_link function and
507218822Sdim	 change the interface to bfd_relax_section to not require the
508218822Sdim	 generic symbols.  */
509218822Sdim      h = bfd_wrapped_link_hash_lookup (input_section->owner, link_info,
510218822Sdim					bfd_asymbol_name (symbol),
511218822Sdim					FALSE, FALSE, TRUE);
512218822Sdim      if (h != (struct bfd_link_hash_entry *) NULL
513218822Sdim	  && (h->type == bfd_link_hash_defined
514218822Sdim	      || h->type == bfd_link_hash_defweak))
515218822Sdim	value = h->u.def.value + output_addr (h->u.def.section);
516218822Sdim      else if (h != (struct bfd_link_hash_entry *) NULL
517218822Sdim	       && h->type == bfd_link_hash_common)
518218822Sdim	value = h->u.c.size;
519218822Sdim      else
520218822Sdim	{
521218822Sdim	  if (! ((*link_info->callbacks->undefined_symbol)
522218822Sdim		 (link_info, bfd_asymbol_name (symbol),
523218822Sdim		  input_section->owner, input_section, reloc->address,
524218822Sdim		  TRUE)))
525218822Sdim	    abort ();
526218822Sdim	  value = 0;
527218822Sdim	}
528218822Sdim    }
529218822Sdim  else
530218822Sdim    value = symbol->value + output_addr (symbol->section);
531218822Sdim
532218822Sdim  /* Add the value contained in the relocation.  */
533218822Sdim  value += reloc->addend;
534218822Sdim
535218822Sdim  return value;
536218822Sdim}
537218822Sdim
538130561Sobrien/* Magic to turn callx into calljx.  */
539130561Sobrien
540130561Sobrienstatic bfd_reloc_status_type
541218822Sdimcalljx_callback (bfd *abfd,
542218822Sdim		 struct bfd_link_info *link_info,
543218822Sdim		 arelent *reloc_entry,
544218822Sdim		 void * src,
545218822Sdim		 void * dst,
546218822Sdim		 asection *input_section)
547130561Sobrien{
548130561Sobrien  int word = bfd_get_32 (abfd, src);
549130561Sobrien  asymbol *symbol_in = *(reloc_entry->sym_ptr_ptr);
550130561Sobrien  aout_symbol_type *symbol = aout_symbol (symbol_in);
551130561Sobrien  bfd_vma value;
552130561Sobrien
553130561Sobrien  value = get_value (reloc_entry, link_info, input_section);
554130561Sobrien
555130561Sobrien  if (IS_CALLNAME (symbol->other))
556130561Sobrien    {
557130561Sobrien      aout_symbol_type *balsym = symbol+1;
558130561Sobrien      int inst = bfd_get_32 (abfd, (bfd_byte *) src-4);
559218822Sdim
560130561Sobrien      /* The next symbol should be an N_BALNAME.  */
561130561Sobrien      BFD_ASSERT (IS_BALNAME (balsym->other));
562130561Sobrien      inst &= BALX_MASK;
563130561Sobrien      inst |= BALX;
564130561Sobrien      bfd_put_32 (abfd, (bfd_vma) inst, (bfd_byte *) dst-4);
565130561Sobrien      symbol = balsym;
566130561Sobrien      value = (symbol->symbol.value
567130561Sobrien	       + output_addr (symbol->symbol.section));
568130561Sobrien    }
569130561Sobrien
570130561Sobrien  word += value + reloc_entry->addend;
571130561Sobrien
572130561Sobrien  bfd_put_32 (abfd, (bfd_vma) word, dst);
573130561Sobrien  return bfd_reloc_ok;
574130561Sobrien}
575130561Sobrien
576130561Sobrien/* Magic to turn call into callj.  */
577130561Sobrien
578130561Sobrienstatic bfd_reloc_status_type
579218822Sdimcallj_callback (bfd *abfd,
580218822Sdim		struct bfd_link_info *link_info,
581218822Sdim		arelent *reloc_entry,
582218822Sdim		void * data,
583218822Sdim		unsigned int srcidx,
584218822Sdim		unsigned int dstidx,
585218822Sdim		asection *input_section,
586218822Sdim		bfd_boolean shrinking)
587130561Sobrien{
588130561Sobrien  int word = bfd_get_32 (abfd, (bfd_byte *) data + srcidx);
589130561Sobrien  asymbol *symbol_in = *(reloc_entry->sym_ptr_ptr);
590130561Sobrien  aout_symbol_type *symbol = aout_symbol (symbol_in);
591130561Sobrien  bfd_vma value;
592130561Sobrien
593130561Sobrien  value = get_value (reloc_entry, link_info, input_section);
594130561Sobrien
595218822Sdim  if (IS_OTHER (symbol->other))
596218822Sdim    /* Call to a system procedure - replace code with system
597218822Sdim       procedure number.  */
598218822Sdim    word = CALLS | (symbol->other - 1);
599218822Sdim
600218822Sdim  else if (IS_CALLNAME (symbol->other))
601130561Sobrien    {
602130561Sobrien      aout_symbol_type *balsym = symbol+1;
603130561Sobrien
604130561Sobrien      /* The next symbol should be an N_BALNAME.  */
605218822Sdim      BFD_ASSERT (IS_BALNAME (balsym->other));
606130561Sobrien
607130561Sobrien      /* We are calling a leaf, so replace the call instruction with a
608130561Sobrien	 bal.  */
609130561Sobrien      word = BAL | ((word
610130561Sobrien		     + output_addr (balsym->symbol.section)
611130561Sobrien		     + balsym->symbol.value + reloc_entry->addend
612130561Sobrien		     - dstidx
613130561Sobrien		     - output_addr (input_section))
614130561Sobrien		    & BAL_MASK);
615130561Sobrien    }
616130561Sobrien  else if ((symbol->symbol.flags & BSF_SECTION_SYM) != 0)
617130561Sobrien    {
618130561Sobrien      /* A callj against a symbol in the same section is a fully
619130561Sobrien         resolved relative call.  We don't need to do anything here.
620130561Sobrien         If the symbol is not in the same section, I'm not sure what
621130561Sobrien         to do; fortunately, this case will probably never arise.  */
622130561Sobrien      BFD_ASSERT (! shrinking);
623130561Sobrien      BFD_ASSERT (symbol->symbol.section == input_section);
624130561Sobrien    }
625130561Sobrien  else
626218822Sdim    word = CALL | (((word & BAL_MASK)
627218822Sdim		    + value
628218822Sdim		    + reloc_entry->addend
629218822Sdim		    - (shrinking ? dstidx : 0)
630218822Sdim		    - output_addr (input_section))
631218822Sdim		   & BAL_MASK);
632218822Sdim
633130561Sobrien  bfd_put_32 (abfd, (bfd_vma) word, (bfd_byte *) data + dstidx);
634130561Sobrien  return bfd_reloc_ok;
635130561Sobrien}
636130561Sobrien
637130561Sobrienstatic reloc_howto_type *
638218822Sdimb_out_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
639218822Sdim			     bfd_reloc_code_real_type code)
640130561Sobrien{
641130561Sobrien  switch (code)
642130561Sobrien    {
643130561Sobrien    default:
644130561Sobrien      return 0;
645130561Sobrien    case BFD_RELOC_I960_CALLJ:
646130561Sobrien      return &howto_reloc_callj;
647130561Sobrien    case BFD_RELOC_32:
648130561Sobrien    case BFD_RELOC_CTOR:
649130561Sobrien      return &howto_reloc_abs32;
650130561Sobrien    case BFD_RELOC_24_PCREL:
651130561Sobrien      return &howto_reloc_pcrel24;
652130561Sobrien    }
653130561Sobrien}
654130561Sobrien
655218822Sdimstatic reloc_howto_type *
656218822Sdimb_out_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
657218822Sdim			     const char *r_name)
658218822Sdim{
659218822Sdim  if (strcasecmp (howto_reloc_callj.name, r_name) == 0)
660218822Sdim    return &howto_reloc_callj;
661218822Sdim  if (strcasecmp (howto_reloc_abs32.name, r_name) == 0)
662218822Sdim    return &howto_reloc_abs32;
663218822Sdim  if (strcasecmp (howto_reloc_pcrel24.name, r_name) == 0)
664218822Sdim    return &howto_reloc_pcrel24;
665218822Sdim
666218822Sdim  return NULL;
667218822Sdim}
668218822Sdim
669130561Sobrien/* Allocate enough room for all the reloc entries, plus pointers to them all.  */
670130561Sobrien
671130561Sobrienstatic bfd_boolean
672218822Sdimb_out_slurp_reloc_table (bfd *abfd, sec_ptr asect, asymbol **symbols)
673130561Sobrien{
674218822Sdim  struct relocation_info *rptr;
675130561Sobrien  unsigned int counter;
676130561Sobrien  arelent *cache_ptr;
677130561Sobrien  int extern_mask, pcrel_mask, callj_mask, length_shift;
678130561Sobrien  int incode_mask;
679130561Sobrien  int size_mask;
680130561Sobrien  bfd_vma prev_addr = 0;
681130561Sobrien  unsigned int count;
682130561Sobrien  bfd_size_type reloc_size, amt;
683130561Sobrien  struct relocation_info *relocs;
684130561Sobrien  arelent *reloc_cache;
685130561Sobrien
686130561Sobrien  if (asect->relocation)
687130561Sobrien    return TRUE;
688130561Sobrien
689130561Sobrien  if (!aout_32_slurp_symbol_table (abfd))
690130561Sobrien    return FALSE;
691130561Sobrien
692130561Sobrien  if (asect == obj_datasec (abfd))
693218822Sdim    reloc_size = exec_hdr (abfd)->a_drsize;
694218822Sdim  else if (asect == obj_textsec (abfd))
695218822Sdim    reloc_size = exec_hdr (abfd)->a_trsize;
696218822Sdim  else if (asect == obj_bsssec (abfd))
697218822Sdim    reloc_size = 0;
698218822Sdim  else
699130561Sobrien    {
700218822Sdim      bfd_set_error (bfd_error_invalid_operation);
701218822Sdim      return FALSE;
702130561Sobrien    }
703130561Sobrien
704130561Sobrien  if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
705130561Sobrien    return FALSE;
706130561Sobrien  count = reloc_size / sizeof (struct relocation_info);
707130561Sobrien
708218822Sdim  relocs = bfd_malloc (reloc_size);
709130561Sobrien  if (!relocs && reloc_size != 0)
710130561Sobrien    return FALSE;
711130561Sobrien
712130561Sobrien  amt = ((bfd_size_type) count + 1) * sizeof (arelent);
713218822Sdim  reloc_cache = bfd_malloc (amt);
714130561Sobrien  if (!reloc_cache)
715130561Sobrien    {
716130561Sobrien      if (relocs != NULL)
717130561Sobrien	free (relocs);
718130561Sobrien      return FALSE;
719130561Sobrien    }
720130561Sobrien
721218822Sdim  if (bfd_bread ((void *) relocs, reloc_size, abfd) != reloc_size)
722130561Sobrien    {
723130561Sobrien      free (reloc_cache);
724130561Sobrien      if (relocs != NULL)
725130561Sobrien	free (relocs);
726130561Sobrien      return FALSE;
727130561Sobrien    }
728130561Sobrien
729130561Sobrien  if (bfd_header_big_endian (abfd))
730130561Sobrien    {
731130561Sobrien      /* Big-endian bit field allocation order.  */
732130561Sobrien      pcrel_mask  = 0x80;
733130561Sobrien      extern_mask = 0x10;
734130561Sobrien      incode_mask = 0x08;
735130561Sobrien      callj_mask  = 0x02;
736130561Sobrien      size_mask =   0x20;
737130561Sobrien      length_shift = 5;
738130561Sobrien    }
739130561Sobrien  else
740130561Sobrien    {
741130561Sobrien      /* Little-endian bit field allocation order.  */
742130561Sobrien      pcrel_mask  = 0x01;
743130561Sobrien      extern_mask = 0x08;
744130561Sobrien      incode_mask = 0x10;
745130561Sobrien      callj_mask  = 0x40;
746130561Sobrien      size_mask   = 0x02;
747130561Sobrien      length_shift = 1;
748130561Sobrien    }
749130561Sobrien
750130561Sobrien  for (rptr = relocs, cache_ptr = reloc_cache, counter = 0;
751130561Sobrien       counter < count;
752130561Sobrien       counter++, rptr++, cache_ptr++)
753130561Sobrien  {
754130561Sobrien    unsigned char *raw = (unsigned char *)rptr;
755130561Sobrien    unsigned int symnum;
756130561Sobrien
757130561Sobrien    cache_ptr->address = H_GET_32 (abfd, raw + 0);
758130561Sobrien    cache_ptr->howto = 0;
759130561Sobrien
760130561Sobrien    if (bfd_header_big_endian (abfd))
761130561Sobrien      symnum = (raw[4] << 16) | (raw[5] << 8) | raw[6];
762130561Sobrien    else
763130561Sobrien      symnum = (raw[6] << 16) | (raw[5] << 8) | raw[4];
764130561Sobrien
765130561Sobrien    if (raw[7] & extern_mask)
766130561Sobrien      {
767130561Sobrien	/* If this is set then the r_index is an index into the symbol table;
768130561Sobrien	   if the bit is not set then r_index contains a section map.
769130561Sobrien	   We either fill in the sym entry with a pointer to the symbol,
770130561Sobrien	   or point to the correct section.  */
771130561Sobrien      cache_ptr->sym_ptr_ptr = symbols + symnum;
772130561Sobrien      cache_ptr->addend = 0;
773130561Sobrien      }
774130561Sobrien    else
775130561Sobrien      {
776130561Sobrien	/* In a.out symbols are relative to the beginning of the
777130561Sobrien	   file rather than sections ?
778130561Sobrien	   (look in translate_from_native_sym_flags)
779130561Sobrien	   The reloc entry addend has added to it the offset into the
780130561Sobrien	   file of the data, so subtract the base to make the reloc
781130561Sobrien	   section relative.  */
782130561Sobrien	int s;
783130561Sobrien
784130561Sobrien	/* Sign-extend symnum from 24 bits to whatever host uses.  */
785130561Sobrien	s = symnum;
786130561Sobrien	if (s & (1 << 23))
787130561Sobrien	  s |= (~0) << 24;
788130561Sobrien
789130561Sobrien	cache_ptr->sym_ptr_ptr = (asymbol **)NULL;
790130561Sobrien	switch (s)
791130561Sobrien	  {
792130561Sobrien	  case N_TEXT:
793130561Sobrien	  case N_TEXT | N_EXT:
794130561Sobrien	    cache_ptr->sym_ptr_ptr = obj_textsec (abfd)->symbol_ptr_ptr;
795130561Sobrien	    cache_ptr->addend = - obj_textsec (abfd)->vma;
796130561Sobrien	    break;
797130561Sobrien	  case N_DATA:
798130561Sobrien	  case N_DATA | N_EXT:
799130561Sobrien	    cache_ptr->sym_ptr_ptr = obj_datasec (abfd)->symbol_ptr_ptr;
800130561Sobrien	    cache_ptr->addend = - obj_datasec (abfd)->vma;
801130561Sobrien	    break;
802130561Sobrien	  case N_BSS:
803130561Sobrien	  case N_BSS | N_EXT:
804130561Sobrien	    cache_ptr->sym_ptr_ptr = obj_bsssec (abfd)->symbol_ptr_ptr;
805130561Sobrien	    cache_ptr->addend =  - obj_bsssec (abfd)->vma;
806130561Sobrien	    break;
807130561Sobrien	  case N_ABS:
808130561Sobrien	  case N_ABS | N_EXT:
809130561Sobrien	    cache_ptr->sym_ptr_ptr = obj_bsssec (abfd)->symbol_ptr_ptr;
810130561Sobrien	    cache_ptr->addend = 0;
811130561Sobrien	    break;
812130561Sobrien	  case -2: /* .align */
813130561Sobrien	    if (raw[7] & pcrel_mask)
814130561Sobrien	      {
815130561Sobrien		cache_ptr->howto = &howto_align_table[(raw[7] >> length_shift) & 3];
816130561Sobrien		cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
817130561Sobrien	      }
818130561Sobrien	    else
819130561Sobrien	      {
820130561Sobrien		/* .org? */
821130561Sobrien		abort ();
822130561Sobrien	      }
823130561Sobrien	    cache_ptr->addend = 0;
824130561Sobrien	    break;
825130561Sobrien	  default:
826218822Sdim	    BFD_ASSERT (FALSE);
827130561Sobrien	    break;
828130561Sobrien	  }
829130561Sobrien      }
830130561Sobrien
831130561Sobrien    /* The i960 only has a few relocation types:
832130561Sobrien       abs 32-bit and pcrel 24bit.   except for callj's!  */
833130561Sobrien    if (cache_ptr->howto != 0)
834130561Sobrien      ;
835130561Sobrien    else if (raw[7] & callj_mask)
836130561Sobrien      {
837130561Sobrien	cache_ptr->howto = &howto_reloc_callj;
838130561Sobrien      }
839130561Sobrien    else if ( raw[7] & pcrel_mask)
840130561Sobrien      {
841130561Sobrien	if (raw[7] & size_mask)
842130561Sobrien	  cache_ptr->howto = &howto_reloc_pcrel13;
843130561Sobrien	else
844130561Sobrien	  cache_ptr->howto = &howto_reloc_pcrel24;
845130561Sobrien      }
846130561Sobrien    else
847130561Sobrien      {
848130561Sobrien	if (raw[7] & incode_mask)
849130561Sobrien	  cache_ptr->howto = &howto_reloc_abs32code;
850130561Sobrien	else
851130561Sobrien	  cache_ptr->howto = &howto_reloc_abs32;
852130561Sobrien      }
853130561Sobrien
854130561Sobrien    if (cache_ptr->address < prev_addr)
855130561Sobrien      {
856130561Sobrien	/* Ouch! this reloc is out of order, insert into the right place.  */
857130561Sobrien	arelent tmp;
858130561Sobrien	arelent *cursor = cache_ptr-1;
859130561Sobrien	bfd_vma stop = cache_ptr->address;
860130561Sobrien
861130561Sobrien	tmp  = *cache_ptr;
862130561Sobrien	while (cursor->address > stop && cursor >= reloc_cache)
863130561Sobrien	  {
864130561Sobrien	    cursor[1] = cursor[0];
865130561Sobrien	    cursor--;
866130561Sobrien	  }
867130561Sobrien
868130561Sobrien	cursor[1] = tmp;
869130561Sobrien      }
870130561Sobrien    else
871218822Sdim      prev_addr = cache_ptr->address;
872130561Sobrien  }
873130561Sobrien
874130561Sobrien  if (relocs != NULL)
875130561Sobrien    free (relocs);
876130561Sobrien  asect->relocation = reloc_cache;
877130561Sobrien  asect->reloc_count = count;
878130561Sobrien
879130561Sobrien  return TRUE;
880130561Sobrien}
881130561Sobrien
882130561Sobrien/* This is stupid.  This function should be a boolean predicate.  */
883130561Sobrien
884130561Sobrienstatic long
885218822Sdimb_out_canonicalize_reloc (bfd *abfd,
886218822Sdim			  sec_ptr section,
887218822Sdim			  arelent **relptr,
888218822Sdim			  asymbol **symbols)
889130561Sobrien{
890130561Sobrien  arelent *tblptr;
891130561Sobrien  unsigned int count;
892130561Sobrien
893130561Sobrien  if ((section->flags & SEC_CONSTRUCTOR) != 0)
894130561Sobrien    {
895130561Sobrien      arelent_chain *chain = section->constructor_chain;
896130561Sobrien
897130561Sobrien      for (count = 0; count < section->reloc_count; count++)
898130561Sobrien	{
899130561Sobrien	  *relptr++ = &chain->relent;
900130561Sobrien	  chain = chain->next;
901130561Sobrien	}
902130561Sobrien    }
903130561Sobrien  else
904130561Sobrien    {
905130561Sobrien      if (section->relocation == NULL
906130561Sobrien	  && ! b_out_slurp_reloc_table (abfd, section, symbols))
907130561Sobrien	return -1;
908130561Sobrien
909130561Sobrien      tblptr = section->relocation;
910130561Sobrien      for (count = 0; count++ < section->reloc_count;)
911130561Sobrien	*relptr++ = tblptr++;
912130561Sobrien    }
913130561Sobrien
914130561Sobrien  *relptr = NULL;
915130561Sobrien
916130561Sobrien  return section->reloc_count;
917130561Sobrien}
918130561Sobrien
919130561Sobrienstatic long
920218822Sdimb_out_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
921130561Sobrien{
922130561Sobrien  if (bfd_get_format (abfd) != bfd_object)
923130561Sobrien    {
924130561Sobrien      bfd_set_error (bfd_error_invalid_operation);
925130561Sobrien      return -1;
926130561Sobrien    }
927130561Sobrien
928130561Sobrien  if (asect->flags & SEC_CONSTRUCTOR)
929130561Sobrien    return sizeof (arelent *) * (asect->reloc_count + 1);
930130561Sobrien
931130561Sobrien  if (asect == obj_datasec (abfd))
932130561Sobrien    return (sizeof (arelent *) *
933218822Sdim	    ((exec_hdr (abfd)->a_drsize / sizeof (struct relocation_info))
934218822Sdim	     + 1));
935130561Sobrien
936130561Sobrien  if (asect == obj_textsec (abfd))
937130561Sobrien    return (sizeof (arelent *) *
938218822Sdim	    ((exec_hdr (abfd)->a_trsize / sizeof (struct relocation_info))
939218822Sdim	     + 1));
940130561Sobrien
941130561Sobrien  if (asect == obj_bsssec (abfd))
942130561Sobrien    return 0;
943130561Sobrien
944130561Sobrien  bfd_set_error (bfd_error_invalid_operation);
945130561Sobrien  return -1;
946130561Sobrien}
947130561Sobrien
948130561Sobrien
949130561Sobrienstatic bfd_boolean
950218822Sdimb_out_set_section_contents (bfd *abfd,
951218822Sdim			    asection *section,
952218822Sdim			    const void * location,
953218822Sdim			    file_ptr offset,
954218822Sdim			    bfd_size_type count)
955130561Sobrien{
956130561Sobrien  if (! abfd->output_has_begun)
957130561Sobrien    {
958130561Sobrien      /* Set by bfd.c handler.  */
959130561Sobrien      if (! aout_32_make_sections (abfd))
960130561Sobrien	return FALSE;
961130561Sobrien
962218822Sdim      obj_textsec (abfd)->filepos = sizeof (struct external_exec);
963218822Sdim      obj_datasec (abfd)->filepos = obj_textsec (abfd)->filepos
964218822Sdim	+  obj_textsec (abfd)->size;
965130561Sobrien    }
966130561Sobrien
967130561Sobrien  /* Regardless, once we know what we're doing, we might as well get going.  */
968130561Sobrien  if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0)
969130561Sobrien    return FALSE;
970130561Sobrien
971130561Sobrien  if (count == 0)
972130561Sobrien    return TRUE;
973130561Sobrien
974218822Sdim  return bfd_bwrite ((void *) location, count, abfd) == count;
975130561Sobrien}
976130561Sobrien
977130561Sobrienstatic bfd_boolean
978218822Sdimb_out_set_arch_mach (bfd *abfd,
979218822Sdim		     enum bfd_architecture arch,
980218822Sdim		     unsigned long machine)
981130561Sobrien{
982218822Sdim  bfd_default_set_arch_mach (abfd, arch, machine);
983130561Sobrien
984130561Sobrien  if (arch == bfd_arch_unknown)	/* Unknown machine arch is OK.  */
985130561Sobrien    return TRUE;
986130561Sobrien
987130561Sobrien  if (arch == bfd_arch_i960)	/* i960 default is OK.  */
988130561Sobrien    switch (machine)
989130561Sobrien      {
990130561Sobrien      case bfd_mach_i960_core:
991130561Sobrien      case bfd_mach_i960_kb_sb:
992130561Sobrien      case bfd_mach_i960_mc:
993130561Sobrien      case bfd_mach_i960_xa:
994130561Sobrien      case bfd_mach_i960_ca:
995130561Sobrien      case bfd_mach_i960_ka_sa:
996130561Sobrien      case bfd_mach_i960_jx:
997130561Sobrien      case bfd_mach_i960_hx:
998130561Sobrien      case 0:
999130561Sobrien	return TRUE;
1000130561Sobrien      default:
1001130561Sobrien	return FALSE;
1002130561Sobrien      }
1003130561Sobrien
1004130561Sobrien  return FALSE;
1005130561Sobrien}
1006130561Sobrien
1007130561Sobrienstatic int
1008218822Sdimb_out_sizeof_headers (bfd *ignore_abfd ATTRIBUTE_UNUSED,
1009218822Sdim		      struct bfd_link_info *info ATTRIBUTE_UNUSED)
1010130561Sobrien{
1011218822Sdim  return sizeof (struct external_exec);
1012130561Sobrien}
1013130561Sobrien
1014130561Sobrienstatic void
1015218822Sdimperform_slip (bfd *abfd,
1016218822Sdim	      unsigned int slip,
1017218822Sdim	      asection *input_section,
1018218822Sdim	      bfd_vma value)
1019130561Sobrien{
1020130561Sobrien  asymbol **s;
1021130561Sobrien
1022130561Sobrien  s = _bfd_generic_link_get_symbols (abfd);
1023130561Sobrien  BFD_ASSERT (s != (asymbol **) NULL);
1024130561Sobrien
1025130561Sobrien  /* Find all symbols past this point, and make them know
1026130561Sobrien     what's happened.  */
1027130561Sobrien  while (*s)
1028130561Sobrien    {
1029130561Sobrien      asymbol *p = *s;
1030130561Sobrien
1031130561Sobrien      if (p->section == input_section)
1032130561Sobrien	{
1033130561Sobrien	  /* This was pointing into this section, so mangle it.  */
1034130561Sobrien	  if (p->value > value)
1035130561Sobrien	    {
1036130561Sobrien	      p->value -=slip;
1037130561Sobrien
1038130561Sobrien	      if (p->udata.p != NULL)
1039130561Sobrien		{
1040130561Sobrien		  struct generic_link_hash_entry *h;
1041130561Sobrien
1042130561Sobrien		  h = (struct generic_link_hash_entry *) p->udata.p;
1043130561Sobrien		  BFD_ASSERT (h->root.type == bfd_link_hash_defined);
1044130561Sobrien		  h->root.u.def.value -= slip;
1045130561Sobrien		  BFD_ASSERT (h->root.u.def.value == p->value);
1046130561Sobrien		}
1047130561Sobrien	    }
1048130561Sobrien	}
1049130561Sobrien      s++;
1050130561Sobrien    }
1051130561Sobrien}
1052130561Sobrien
1053130561Sobrien/* This routine works out if the thing we want to get to can be
1054130561Sobrien   reached with a 24bit offset instead of a 32 bit one.
1055130561Sobrien   If it can, then it changes the amode.  */
1056130561Sobrien
1057130561Sobrienstatic int
1058218822Sdimabs32code (bfd *abfd,
1059218822Sdim	   asection *input_section,
1060218822Sdim	   arelent *r,
1061218822Sdim	   unsigned int shrink,
1062218822Sdim	   struct bfd_link_info *link_info)
1063130561Sobrien{
1064130561Sobrien  bfd_vma value = get_value (r, link_info, input_section);
1065130561Sobrien  bfd_vma dot = output_addr (input_section) + r->address;
1066130561Sobrien  bfd_vma gap;
1067130561Sobrien
1068130561Sobrien  /* See if the address we're looking at within 2^23 bytes of where
1069130561Sobrien     we are, if so then we can use a small branch rather than the
1070130561Sobrien     jump we were going to.  */
1071130561Sobrien  gap = value - (dot - shrink);
1072130561Sobrien
1073130561Sobrien  if (-1 << 23 < (long)gap && (long)gap < 1 << 23)
1074130561Sobrien    {
1075130561Sobrien      /* Change the reloc type from 32bitcode possible 24, to 24bit
1076130561Sobrien	 possible 32.  */
1077130561Sobrien      r->howto = &howto_reloc_abs32codeshrunk;
1078130561Sobrien      /* The place to relc moves back by four bytes.  */
1079130561Sobrien      r->address -=4;
1080130561Sobrien
1081130561Sobrien      /* This will be four bytes smaller in the long run.  */
1082130561Sobrien      shrink += 4 ;
1083130561Sobrien      perform_slip (abfd, 4, input_section, r->address-shrink + 4);
1084130561Sobrien    }
1085130561Sobrien
1086130561Sobrien  return shrink;
1087130561Sobrien}
1088130561Sobrien
1089130561Sobrienstatic int
1090218822Sdimaligncode (bfd *abfd,
1091218822Sdim	   asection *input_section,
1092218822Sdim	   arelent *r,
1093218822Sdim	   unsigned int shrink)
1094130561Sobrien{
1095130561Sobrien  bfd_vma dot = output_addr (input_section) + r->address;
1096130561Sobrien  bfd_vma gap;
1097130561Sobrien  bfd_vma old_end;
1098130561Sobrien  bfd_vma new_end;
1099130561Sobrien  unsigned int shrink_delta;
1100130561Sobrien  int size = r->howto->size;
1101130561Sobrien
1102130561Sobrien  /* Reduce the size of the alignment so that it's still aligned but
1103130561Sobrien     smaller  - the current size is already the same size as or bigger
1104130561Sobrien     than the alignment required.  */
1105130561Sobrien
1106130561Sobrien  /* Calculate the first byte following the padding before we optimize.  */
1107130561Sobrien  old_end = ((dot + size ) & ~size) + size+1;
1108130561Sobrien  /* Work out where the new end will be - remember that we're smaller
1109130561Sobrien     than we used to be.  */
1110130561Sobrien  new_end = ((dot - shrink + size) & ~size);
1111130561Sobrien
1112130561Sobrien  /* This is the new end.  */
1113130561Sobrien  gap = old_end - ((dot + size) & ~size);
1114130561Sobrien
1115130561Sobrien  shrink_delta = (old_end - new_end) - shrink;
1116130561Sobrien
1117130561Sobrien  if (shrink_delta)
1118130561Sobrien    {
1119130561Sobrien      /* Change the reloc so that it knows how far to align to.  */
1120130561Sobrien      r->howto = howto_done_align_table + (r->howto - howto_align_table);
1121130561Sobrien
1122130561Sobrien      /* Encode the stuff into the addend - for future use we need to
1123130561Sobrien	 know how big the reloc used to be.  */
1124130561Sobrien      r->addend = old_end - dot + r->address;
1125130561Sobrien
1126130561Sobrien      /* This will be N bytes smaller in the long run, adjust all the symbols.  */
1127130561Sobrien      perform_slip (abfd, shrink_delta, input_section, r->address - shrink);
1128130561Sobrien      shrink += shrink_delta;
1129130561Sobrien    }
1130130561Sobrien
1131130561Sobrien  return shrink;
1132130561Sobrien}
1133130561Sobrien
1134130561Sobrienstatic bfd_boolean
1135218822Sdimb_out_bfd_relax_section (bfd *abfd,
1136218822Sdim			 asection *i,
1137218822Sdim			 struct bfd_link_info *link_info,
1138218822Sdim			 bfd_boolean *again)
1139130561Sobrien{
1140130561Sobrien  /* Get enough memory to hold the stuff.  */
1141130561Sobrien  bfd *input_bfd = i->owner;
1142130561Sobrien  asection *input_section = i;
1143130561Sobrien  unsigned int shrink = 0 ;
1144130561Sobrien  arelent **reloc_vector = NULL;
1145218822Sdim  long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
1146130561Sobrien
1147130561Sobrien  if (reloc_size < 0)
1148130561Sobrien    return FALSE;
1149130561Sobrien
1150130561Sobrien  /* We only run this relaxation once.  It might work to run it
1151130561Sobrien     multiple times, but it hasn't been tested.  */
1152130561Sobrien  *again = FALSE;
1153130561Sobrien
1154130561Sobrien  if (reloc_size)
1155130561Sobrien    {
1156130561Sobrien      long reloc_count;
1157130561Sobrien
1158218822Sdim      reloc_vector = bfd_malloc ((bfd_size_type) reloc_size);
1159130561Sobrien      if (reloc_vector == NULL && reloc_size != 0)
1160130561Sobrien	goto error_return;
1161130561Sobrien
1162130561Sobrien      /* Get the relocs and think about them.  */
1163130561Sobrien      reloc_count =
1164130561Sobrien	bfd_canonicalize_reloc (input_bfd, input_section, reloc_vector,
1165130561Sobrien				_bfd_generic_link_get_symbols (input_bfd));
1166130561Sobrien      if (reloc_count < 0)
1167130561Sobrien	goto error_return;
1168130561Sobrien      if (reloc_count > 0)
1169130561Sobrien	{
1170130561Sobrien	  arelent **parent;
1171130561Sobrien
1172130561Sobrien	  for (parent = reloc_vector; *parent; parent++)
1173130561Sobrien	    {
1174130561Sobrien	      arelent *r = *parent;
1175130561Sobrien
1176130561Sobrien	      switch (r->howto->type)
1177130561Sobrien		{
1178130561Sobrien		case ALIGNER:
1179130561Sobrien		  /* An alignment reloc.  */
1180130561Sobrien		  shrink = aligncode (abfd, input_section, r, shrink);
1181130561Sobrien		  break;
1182130561Sobrien		case ABS32CODE:
1183130561Sobrien		  /* A 32bit reloc in an addressing mode.  */
1184130561Sobrien		  shrink = abs32code (input_bfd, input_section, r, shrink,
1185130561Sobrien				      link_info);
1186130561Sobrien		  break;
1187130561Sobrien		case ABS32CODE_SHRUNK:
1188130561Sobrien		  shrink += 4;
1189130561Sobrien		  break;
1190130561Sobrien		}
1191130561Sobrien	    }
1192130561Sobrien	}
1193130561Sobrien    }
1194218822Sdim  input_section->size -= shrink;
1195130561Sobrien
1196130561Sobrien  if (reloc_vector != NULL)
1197130561Sobrien    free (reloc_vector);
1198130561Sobrien  return TRUE;
1199130561Sobrien error_return:
1200130561Sobrien  if (reloc_vector != NULL)
1201130561Sobrien    free (reloc_vector);
1202130561Sobrien  return FALSE;
1203130561Sobrien}
1204130561Sobrien
1205130561Sobrienstatic bfd_byte *
1206218822Sdimb_out_bfd_get_relocated_section_contents (bfd *output_bfd,
1207218822Sdim					  struct bfd_link_info *link_info,
1208218822Sdim					  struct bfd_link_order *link_order,
1209218822Sdim					  bfd_byte *data,
1210218822Sdim					  bfd_boolean relocatable,
1211218822Sdim					  asymbol **symbols)
1212130561Sobrien{
1213130561Sobrien  /* Get enough memory to hold the stuff.  */
1214130561Sobrien  bfd *input_bfd = link_order->u.indirect.section->owner;
1215130561Sobrien  asection *input_section = link_order->u.indirect.section;
1216218822Sdim  long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
1217130561Sobrien  arelent **reloc_vector = NULL;
1218130561Sobrien  long reloc_count;
1219130561Sobrien
1220130561Sobrien  if (reloc_size < 0)
1221130561Sobrien    goto error_return;
1222130561Sobrien
1223130561Sobrien  /* If producing relocatable output, don't bother to relax.  */
1224130561Sobrien  if (relocatable)
1225130561Sobrien    return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
1226130561Sobrien						       link_order,
1227130561Sobrien						       data, relocatable,
1228130561Sobrien						       symbols);
1229130561Sobrien
1230218822Sdim  reloc_vector = bfd_malloc ((bfd_size_type) reloc_size);
1231130561Sobrien  if (reloc_vector == NULL && reloc_size != 0)
1232130561Sobrien    goto error_return;
1233130561Sobrien
1234130561Sobrien  /* Read in the section.  */
1235130561Sobrien  BFD_ASSERT (bfd_get_section_contents (input_bfd,
1236130561Sobrien					input_section,
1237130561Sobrien					data,
1238130561Sobrien					(bfd_vma) 0,
1239218822Sdim					input_section->size));
1240130561Sobrien
1241130561Sobrien  reloc_count = bfd_canonicalize_reloc (input_bfd,
1242130561Sobrien					input_section,
1243130561Sobrien					reloc_vector,
1244130561Sobrien					symbols);
1245130561Sobrien  if (reloc_count < 0)
1246130561Sobrien    goto error_return;
1247130561Sobrien  if (reloc_count > 0)
1248130561Sobrien    {
1249130561Sobrien      arelent **parent = reloc_vector;
1250130561Sobrien      arelent *reloc ;
1251130561Sobrien      unsigned int dst_address = 0;
1252130561Sobrien      unsigned int src_address = 0;
1253130561Sobrien      unsigned int run;
1254130561Sobrien      unsigned int idx;
1255130561Sobrien
1256130561Sobrien      /* Find how long a run we can do.  */
1257130561Sobrien      while (dst_address < link_order->size)
1258130561Sobrien	{
1259130561Sobrien	  reloc = *parent;
1260130561Sobrien	  if (reloc)
1261130561Sobrien	    {
1262130561Sobrien	      /* Note that the relaxing didn't tie up the addresses in the
1263130561Sobrien		 relocation, so we use the original address to work out the
1264130561Sobrien		 run of non-relocated data.  */
1265130561Sobrien	      BFD_ASSERT (reloc->address >= src_address);
1266130561Sobrien	      run = reloc->address - src_address;
1267130561Sobrien	      parent++;
1268130561Sobrien	    }
1269130561Sobrien	  else
1270218822Sdim	    run = link_order->size - dst_address;
1271130561Sobrien
1272130561Sobrien	  /* Copy the bytes.  */
1273130561Sobrien	  for (idx = 0; idx < run; idx++)
1274130561Sobrien	    data[dst_address++] = data[src_address++];
1275130561Sobrien
1276130561Sobrien	  /* Now do the relocation.  */
1277130561Sobrien	  if (reloc)
1278130561Sobrien	    {
1279130561Sobrien	      switch (reloc->howto->type)
1280130561Sobrien		{
1281130561Sobrien		case ABS32CODE:
1282130561Sobrien		  calljx_callback (input_bfd, link_info, reloc,
1283130561Sobrien				   src_address + data, dst_address + data,
1284130561Sobrien				   input_section);
1285130561Sobrien		  src_address += 4;
1286130561Sobrien		  dst_address += 4;
1287130561Sobrien		  break;
1288130561Sobrien		case ABS32:
1289130561Sobrien		  bfd_put_32 (input_bfd,
1290130561Sobrien			      (bfd_get_32 (input_bfd, data + src_address)
1291130561Sobrien			       + get_value (reloc, link_info, input_section)),
1292130561Sobrien			      data + dst_address);
1293130561Sobrien		  src_address += 4;
1294130561Sobrien		  dst_address += 4;
1295130561Sobrien		  break;
1296130561Sobrien		case CALLJ:
1297130561Sobrien		  callj_callback (input_bfd, link_info, reloc, data,
1298130561Sobrien				  src_address, dst_address, input_section,
1299130561Sobrien				  FALSE);
1300130561Sobrien		  src_address += 4;
1301130561Sobrien		  dst_address += 4;
1302130561Sobrien		  break;
1303130561Sobrien		case ALIGNDONE:
1304130561Sobrien		  BFD_ASSERT (reloc->addend >= src_address);
1305130561Sobrien		  BFD_ASSERT ((bfd_vma) reloc->addend
1306218822Sdim			      <= input_section->size);
1307130561Sobrien		  src_address = reloc->addend;
1308130561Sobrien		  dst_address = ((dst_address + reloc->howto->size)
1309130561Sobrien				 & ~reloc->howto->size);
1310130561Sobrien		  break;
1311130561Sobrien		case ABS32CODE_SHRUNK:
1312130561Sobrien		  /* This used to be a callx, but we've found out that a
1313130561Sobrien		     callj will reach, so do the right thing.  */
1314130561Sobrien		  callj_callback (input_bfd, link_info, reloc, data,
1315130561Sobrien				  src_address + 4, dst_address, input_section,
1316130561Sobrien				  TRUE);
1317130561Sobrien		  dst_address += 4;
1318130561Sobrien		  src_address += 8;
1319130561Sobrien		  break;
1320130561Sobrien		case PCREL24:
1321130561Sobrien		  {
1322130561Sobrien		    long int word = bfd_get_32 (input_bfd,
1323130561Sobrien						data + src_address);
1324130561Sobrien		    bfd_vma value;
1325130561Sobrien
1326130561Sobrien		    value = get_value (reloc, link_info, input_section);
1327130561Sobrien		    word = ((word & ~BAL_MASK)
1328130561Sobrien			    | (((word & BAL_MASK)
1329130561Sobrien				+ value
1330130561Sobrien				- output_addr (input_section)
1331130561Sobrien				+ reloc->addend)
1332130561Sobrien			       & BAL_MASK));
1333130561Sobrien
1334130561Sobrien		    bfd_put_32 (input_bfd, (bfd_vma) word, data + dst_address);
1335130561Sobrien		    dst_address += 4;
1336130561Sobrien		    src_address += 4;
1337130561Sobrien
1338130561Sobrien		  }
1339130561Sobrien		  break;
1340130561Sobrien		case PCREL13:
1341130561Sobrien		  {
1342130561Sobrien		    long int word = bfd_get_32 (input_bfd,
1343130561Sobrien						data + src_address);
1344130561Sobrien		    bfd_vma value;
1345130561Sobrien
1346130561Sobrien		    value = get_value (reloc, link_info, input_section);
1347130561Sobrien		    word = ((word & ~PCREL13_MASK)
1348130561Sobrien			    | (((word & PCREL13_MASK)
1349130561Sobrien				+ value
1350130561Sobrien				+ reloc->addend
1351130561Sobrien				- output_addr (input_section))
1352130561Sobrien			       & PCREL13_MASK));
1353130561Sobrien
1354130561Sobrien		    bfd_put_32 (input_bfd, (bfd_vma) word, data + dst_address);
1355130561Sobrien		    dst_address += 4;
1356130561Sobrien		    src_address += 4;
1357130561Sobrien		  }
1358130561Sobrien		  break;
1359130561Sobrien
1360130561Sobrien		default:
1361130561Sobrien		  abort ();
1362130561Sobrien		}
1363130561Sobrien	    }
1364130561Sobrien	}
1365130561Sobrien    }
1366130561Sobrien  if (reloc_vector != NULL)
1367130561Sobrien    free (reloc_vector);
1368130561Sobrien  return data;
1369130561Sobrien error_return:
1370130561Sobrien  if (reloc_vector != NULL)
1371130561Sobrien    free (reloc_vector);
1372130561Sobrien  return NULL;
1373130561Sobrien}
1374130561Sobrien
1375130561Sobrien
1376130561Sobrien/* Build the transfer vectors for Big and Little-Endian B.OUT files.  */
1377130561Sobrien
1378218822Sdim#define aout_32_bfd_make_debug_symbol          _bfd_nosymbols_bfd_make_debug_symbol
1379218822Sdim#define aout_32_close_and_cleanup              aout_32_bfd_free_cached_info
1380218822Sdim#define b_out_bfd_link_hash_table_create       _bfd_generic_link_hash_table_create
1381218822Sdim#define b_out_bfd_link_hash_table_free         _bfd_generic_link_hash_table_free
1382218822Sdim#define b_out_bfd_link_add_symbols             _bfd_generic_link_add_symbols
1383218822Sdim#define b_out_bfd_link_just_syms               _bfd_generic_link_just_syms
1384218822Sdim#define b_out_bfd_final_link                   _bfd_generic_final_link
1385218822Sdim#define b_out_bfd_link_split_section           _bfd_generic_link_split_section
1386218822Sdim#define b_out_bfd_gc_sections                  bfd_generic_gc_sections
1387218822Sdim#define b_out_bfd_merge_sections               bfd_generic_merge_sections
1388218822Sdim#define b_out_bfd_is_group_section             bfd_generic_is_group_section
1389218822Sdim#define b_out_bfd_discard_group                bfd_generic_discard_group
1390218822Sdim#define b_out_section_already_linked           _bfd_generic_section_already_linked
1391218822Sdim#define aout_32_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
1392130561Sobrien
1393130561Sobrienextern const bfd_target b_out_vec_little_host;
1394130561Sobrien
1395130561Sobrienconst bfd_target b_out_vec_big_host =
1396130561Sobrien{
1397218822Sdim  "b.out.big",			/* Name.  */
1398130561Sobrien  bfd_target_aout_flavour,
1399218822Sdim  BFD_ENDIAN_LITTLE,		/* Data byte order.  */
1400218822Sdim  BFD_ENDIAN_BIG,		/* Header byte order.  */
1401218822Sdim  (HAS_RELOC | EXEC_P |		/* Object flags.  */
1402130561Sobrien   HAS_LINENO | HAS_DEBUG |
1403130561Sobrien   HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE ),
1404130561Sobrien  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
1405218822Sdim  '_',				/* Symbol leading char.  */
1406218822Sdim  ' ',				/* AR_pad_char.  */
1407218822Sdim  16,				/* AR_max_namelen.  */
1408130561Sobrien
1409130561Sobrien  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1410130561Sobrien     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1411218822Sdim     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data.  */
1412130561Sobrien  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1413130561Sobrien     bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1414218822Sdim     bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Headers.  */
1415218822Sdim {_bfd_dummy_target, b_out_object_p, /* bfd_check_format.  */
1416130561Sobrien   bfd_generic_archive_p, _bfd_dummy_target},
1417218822Sdim {bfd_false, b_out_mkobject,	/* bfd_set_format.  */
1418130561Sobrien   _bfd_generic_mkarchive, bfd_false},
1419218822Sdim {bfd_false, b_out_write_object_contents, /* bfd_write_contents.  */
1420130561Sobrien   _bfd_write_archive_contents, bfd_false},
1421130561Sobrien
1422130561Sobrien     BFD_JUMP_TABLE_GENERIC (aout_32),
1423130561Sobrien     BFD_JUMP_TABLE_COPY (_bfd_generic),
1424130561Sobrien     BFD_JUMP_TABLE_CORE (_bfd_nocore),
1425130561Sobrien     BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd),
1426130561Sobrien     BFD_JUMP_TABLE_SYMBOLS (aout_32),
1427130561Sobrien     BFD_JUMP_TABLE_RELOCS (b_out),
1428130561Sobrien     BFD_JUMP_TABLE_WRITE (b_out),
1429130561Sobrien     BFD_JUMP_TABLE_LINK (b_out),
1430130561Sobrien     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1431130561Sobrien
1432130561Sobrien  & b_out_vec_little_host,
1433130561Sobrien
1434218822Sdim  NULL
1435130561Sobrien};
1436130561Sobrien
1437130561Sobrienconst bfd_target b_out_vec_little_host =
1438130561Sobrien{
1439218822Sdim  "b.out.little",		/* Name.  */
1440130561Sobrien  bfd_target_aout_flavour,
1441218822Sdim  BFD_ENDIAN_LITTLE,		/* Data byte order.  */
1442218822Sdim  BFD_ENDIAN_LITTLE,		/* Header byte order.  */
1443218822Sdim  (HAS_RELOC | EXEC_P |		/* Object flags.  */
1444130561Sobrien   HAS_LINENO | HAS_DEBUG |
1445130561Sobrien   HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE ),
1446130561Sobrien  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
1447218822Sdim  '_',				/* Symbol leading char.  */
1448218822Sdim  ' ',				/* AR_pad_char.  */
1449218822Sdim  16,				/* AR_max_namelen.  */
1450130561Sobrien  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1451130561Sobrien    bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1452218822Sdim     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data.  */
1453130561Sobrien  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1454130561Sobrien     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1455218822Sdim     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Headers.  */
1456130561Sobrien
1457218822Sdim  {_bfd_dummy_target, b_out_object_p, /* bfd_check_format.  */
1458130561Sobrien     bfd_generic_archive_p, _bfd_dummy_target},
1459218822Sdim  {bfd_false, b_out_mkobject,	/* bfd_set_format.  */
1460130561Sobrien     _bfd_generic_mkarchive, bfd_false},
1461218822Sdim  {bfd_false, b_out_write_object_contents, /* bfd_write_contents.  */
1462130561Sobrien     _bfd_write_archive_contents, bfd_false},
1463130561Sobrien
1464130561Sobrien     BFD_JUMP_TABLE_GENERIC (aout_32),
1465130561Sobrien     BFD_JUMP_TABLE_COPY (_bfd_generic),
1466130561Sobrien     BFD_JUMP_TABLE_CORE (_bfd_nocore),
1467130561Sobrien     BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd),
1468130561Sobrien     BFD_JUMP_TABLE_SYMBOLS (aout_32),
1469130561Sobrien     BFD_JUMP_TABLE_RELOCS (b_out),
1470130561Sobrien     BFD_JUMP_TABLE_WRITE (b_out),
1471130561Sobrien     BFD_JUMP_TABLE_LINK (b_out),
1472130561Sobrien     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1473130561Sobrien
1474130561Sobrien  & b_out_vec_big_host,
1475130561Sobrien
1476218822Sdim  NULL
1477130561Sobrien};
1478