1/* BFD back-end for os9000 i386 binaries.
2   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1998, 1999, 2001, 2002,
3   2004 Free Software Foundation, Inc.
4   Written by Cygnus Support.
5
6This file is part of BFD, the Binary File Descriptor library.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2 of the License, or
11(at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program; if not, write to the Free Software
20Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
22
23#include "bfd.h"
24#include "sysdep.h"
25#include "libbfd.h"
26#include "bfdlink.h"
27#include "libaout.h"		/* BFD a.out internal data structures */
28#include "os9k.h"
29
30static const bfd_target * os9k_callback
31  PARAMS ((bfd *));
32static const bfd_target * os9k_object_p
33  PARAMS ((bfd *));
34static int os9k_sizeof_headers
35  PARAMS ((bfd *, bfd_boolean));
36bfd_boolean os9k_swap_exec_header_in
37  PARAMS ((bfd *, mh_com *, struct internal_exec *));
38
39/* Swaps the information in an executable header taken from a raw byte
40   stream memory image, into the internal exec_header structure.  */
41bfd_boolean
42os9k_swap_exec_header_in (abfd, raw_bytes, execp)
43     bfd *abfd;
44     mh_com *raw_bytes;
45     struct internal_exec *execp;
46{
47  mh_com *bytes = (mh_com *) raw_bytes;
48  unsigned int dload, dmemsize, dmemstart;
49
50  /* Now fill in fields in the execp, from the bytes in the raw data.  */
51  execp->a_info = H_GET_16 (abfd, bytes->m_sync);
52  execp->a_syms = 0;
53  execp->a_entry = H_GET_32 (abfd, bytes->m_exec);
54  execp->a_talign = 2;
55  execp->a_dalign = 2;
56  execp->a_balign = 2;
57
58  dload = H_GET_32 (abfd, bytes->m_idata);
59  execp->a_data = dload + 8;
60
61  if (bfd_seek (abfd, (file_ptr) dload, SEEK_SET) != 0
62      || (bfd_bread (&dmemstart, (bfd_size_type) sizeof (dmemstart), abfd)
63	  != sizeof (dmemstart))
64      || (bfd_bread (&dmemsize, (bfd_size_type) sizeof (dmemsize), abfd)
65	  != sizeof (dmemsize)))
66    return FALSE;
67
68  execp->a_tload = 0;
69  execp->a_dload = H_GET_32 (abfd, (unsigned char *) &dmemstart);
70  execp->a_text = dload - execp->a_tload;
71  execp->a_data = H_GET_32 (abfd, (unsigned char *) &dmemsize);
72  execp->a_bss = H_GET_32 (abfd, bytes->m_data) - execp->a_data;
73
74  execp->a_trsize = 0;
75  execp->a_drsize = 0;
76
77  return TRUE;
78}
79
80#if 0
81/* Swaps the information in an internal exec header structure into the
82   supplied buffer ready for writing to disk.  */
83
84void os9k_swap_exec_header_out
85  PARAMS ((bfd *, struct internal_exec *, struct mh_com *));
86
87void
88os9k_swap_exec_header_out (abfd, execp, raw_bytes)
89     bfd *abfd;
90     struct internal_exec *execp;
91     mh_com *raw_bytes;
92{
93  mh_com *bytes = (mh_com *) raw_bytes;
94
95  /* Now fill in fields in the raw data, from the fields in the exec struct. */
96  H_PUT_32 (abfd, execp->a_info, bytes->e_info);
97  H_PUT_32 (abfd, execp->a_text, bytes->e_text);
98  H_PUT_32 (abfd, execp->a_data, bytes->e_data);
99  H_PUT_32 (abfd, execp->a_bss, bytes->e_bss);
100  H_PUT_32 (abfd, execp->a_syms, bytes->e_syms);
101  H_PUT_32 (abfd, execp->a_entry, bytes->e_entry);
102  H_PUT_32 (abfd, execp->a_trsize, bytes->e_trsize);
103  H_PUT_32 (abfd, execp->a_drsize, bytes->e_drsize);
104  H_PUT_32 (abfd, execp->a_tload, bytes->e_tload);
105  H_PUT_32 (abfd, execp->a_dload, bytes->e_dload);
106  bytes->e_talign[0] = execp->a_talign;
107  bytes->e_dalign[0] = execp->a_dalign;
108  bytes->e_balign[0] = execp->a_balign;
109  bytes->e_relaxable[0] = execp->a_relaxable;
110}
111
112#endif	/* 0 */
113
114static const bfd_target *
115os9k_object_p (abfd)
116     bfd *abfd;
117{
118  struct internal_exec anexec;
119  mh_com exec_bytes;
120
121  if (bfd_bread ((PTR) &exec_bytes, (bfd_size_type) MHCOM_BYTES_SIZE, abfd)
122      != MHCOM_BYTES_SIZE)
123    {
124      if (bfd_get_error () != bfd_error_system_call)
125	bfd_set_error (bfd_error_wrong_format);
126      return 0;
127    }
128
129  anexec.a_info = H_GET_16 (abfd, exec_bytes.m_sync);
130  if (N_BADMAG (anexec))
131    {
132      bfd_set_error (bfd_error_wrong_format);
133      return 0;
134    }
135
136  if (! os9k_swap_exec_header_in (abfd, &exec_bytes, &anexec))
137    {
138      if (bfd_get_error () != bfd_error_system_call)
139	bfd_set_error (bfd_error_wrong_format);
140      return NULL;
141    }
142  return aout_32_some_aout_object_p (abfd, &anexec, os9k_callback);
143}
144
145
146/* Finish up the opening of a b.out file for reading.  Fill in all the
147   fields that are not handled by common code.  */
148
149static const bfd_target *
150os9k_callback (abfd)
151     bfd *abfd;
152{
153  struct internal_exec *execp = exec_hdr (abfd);
154  unsigned long bss_start;
155
156  /* Architecture and machine type.  */
157  bfd_set_arch_mach (abfd, bfd_arch_i386, 0);
158
159  /* The positions of the string table and symbol table.  */
160  obj_str_filepos (abfd) = 0;
161  obj_sym_filepos (abfd) = 0;
162
163  /* The alignments of the sections.  */
164  obj_textsec (abfd)->alignment_power = execp->a_talign;
165  obj_datasec (abfd)->alignment_power = execp->a_dalign;
166  obj_bsssec (abfd)->alignment_power = execp->a_balign;
167
168  /* The starting addresses of the sections.  */
169  obj_textsec (abfd)->vma = execp->a_tload;
170  obj_datasec (abfd)->vma = execp->a_dload;
171
172  /* And reload the sizes, since the aout module zaps them.  */
173  obj_textsec (abfd)->size = execp->a_text;
174
175  bss_start = execp->a_dload + execp->a_data;	/* BSS = end of data section.  */
176  obj_bsssec (abfd)->vma = align_power (bss_start, execp->a_balign);
177
178  /* The file positions of the sections.  */
179  obj_textsec (abfd)->filepos = execp->a_entry;
180  obj_datasec (abfd)->filepos = execp->a_dload;
181
182  /* The file positions of the relocation info ***
183  obj_textsec (abfd)->rel_filepos = N_TROFF(*execp);
184  obj_datasec (abfd)->rel_filepos =  N_DROFF(*execp);  */
185
186  adata (abfd).page_size = 1;	/* Not applicable.  */
187  adata (abfd).segment_size = 1;/* Not applicable.  */
188  adata (abfd).exec_bytes_size = MHCOM_BYTES_SIZE;
189
190  return abfd->xvec;
191}
192
193#if 0
194struct bout_data_struct
195{
196  struct aoutdata a;
197  struct internal_exec e;
198};
199
200static bfd_boolean
201os9k_mkobject (abfd)
202     bfd *abfd;
203{
204  struct bout_data_struct *rawptr;
205  bfd_size_type amt = sizeof (struct bout_data_struct);
206
207  rawptr = (struct bout_data_struct *) bfd_zalloc (abfd, amt);
208  if (rawptr == NULL)
209    return FALSE;
210
211  abfd->tdata.bout_data = rawptr;
212  exec_hdr (abfd) = &rawptr->e;
213
214  obj_textsec (abfd) = (asection *) NULL;
215  obj_datasec (abfd) = (asection *) NULL;
216  obj_bsssec (abfd) = (asection *) NULL;
217
218  return TRUE;
219}
220
221static bfd_boolean
222os9k_write_object_contents (abfd)
223     bfd *abfd;
224{
225  struct external_exec swapped_hdr;
226
227  if (! aout_32_make_sections (abfd))
228    return FALSE;
229
230  exec_hdr (abfd)->a_info = BMAGIC;
231
232  exec_hdr (abfd)->a_text = obj_textsec (abfd)->size;
233  exec_hdr (abfd)->a_data = obj_datasec (abfd)->size;
234  exec_hdr (abfd)->a_bss = obj_bsssec (abfd)->size;
235  exec_hdr (abfd)->a_syms = bfd_get_symcount (abfd) * sizeof (struct nlist);
236  exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);
237  exec_hdr (abfd)->a_trsize = ((obj_textsec (abfd)->reloc_count) *
238			       sizeof (struct relocation_info));
239  exec_hdr (abfd)->a_drsize = ((obj_datasec (abfd)->reloc_count) *
240			       sizeof (struct relocation_info));
241
242  exec_hdr (abfd)->a_talign = obj_textsec (abfd)->alignment_power;
243  exec_hdr (abfd)->a_dalign = obj_datasec (abfd)->alignment_power;
244  exec_hdr (abfd)->a_balign = obj_bsssec (abfd)->alignment_power;
245
246  exec_hdr (abfd)->a_tload = obj_textsec (abfd)->vma;
247  exec_hdr (abfd)->a_dload = obj_datasec (abfd)->vma;
248
249  bout_swap_exec_header_out (abfd, exec_hdr (abfd), &swapped_hdr);
250
251  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
252      || bfd_bwrite ((PTR) & swapped_hdr, (bfd_size_type) EXEC_BYTES_SIZE,
253		    abfd) != EXEC_BYTES_SIZE)
254    return FALSE;
255
256  /* Now write out reloc info, followed by syms and strings.  */
257  if (bfd_get_symcount (abfd) != 0)
258    {
259      if (bfd_seek (abfd, (file_ptr) (N_SYMOFF (*exec_hdr (abfd))), SEEK_SET)
260	  != 0)
261	return FALSE;
262
263      if (!aout_32_write_syms (abfd))
264	return FALSE;
265
266      if (bfd_seek (abfd, (file_ptr) (N_TROFF (*exec_hdr (abfd))), SEEK_SET)
267	  != 0)
268	return FALSE;
269
270      if (!b_out_squirt_out_relocs (abfd, obj_textsec (abfd)))
271	return FALSE;
272      if (bfd_seek (abfd, (file_ptr) (N_DROFF (*exec_hdr (abfd))), SEEK_SET)
273	  != 0)
274	return FALSE;
275
276      if (!b_out_squirt_out_relocs (abfd, obj_datasec (abfd)))
277	return FALSE;
278    }
279  return TRUE;
280}
281
282static bfd_boolean
283os9k_set_section_contents (abfd, section, location, offset, count)
284     bfd *abfd;
285     sec_ptr section;
286     unsigned char *location;
287     file_ptr offset;
288     int count;
289{
290
291  if (! abfd->output_has_begun)
292    {				/* set by bfd.c handler */
293      if (! aout_32_make_sections (abfd))
294	return FALSE;
295
296      obj_textsec (abfd)->filepos = sizeof (struct internal_exec);
297      obj_datasec (abfd)->filepos = obj_textsec (abfd)->filepos
298	+ obj_textsec (abfd)->size;
299
300    }
301  /* Regardless, once we know what we're doing, we might as well get going.  */
302  if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0)
303    return FALSE;
304
305  if (count != 0)
306    return bfd_bwrite ((PTR) location, (bfd_size_type) count, abfd) == count;
307
308  return TRUE;
309}
310#endif	/* 0 */
311
312static int
313os9k_sizeof_headers (ignore_abfd, ignore)
314     bfd *ignore_abfd ATTRIBUTE_UNUSED;
315     bfd_boolean ignore ATTRIBUTE_UNUSED;
316{
317  return sizeof (struct internal_exec);
318}
319
320
321
322#define aout_32_close_and_cleanup aout_32_bfd_free_cached_info
323
324#define aout_32_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
325
326#define aout_32_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
327
328#define aout_32_get_section_contents_in_window \
329  _bfd_generic_get_section_contents_in_window
330
331#define os9k_bfd_get_relocated_section_contents \
332  bfd_generic_get_relocated_section_contents
333#define os9k_bfd_relax_section bfd_generic_relax_section
334#define os9k_bfd_gc_sections bfd_generic_gc_sections
335#define os9k_bfd_merge_sections bfd_generic_merge_sections
336#define os9k_bfd_is_group_section bfd_generic_is_group_section
337#define os9k_bfd_discard_group bfd_generic_discard_group
338#define os9k_section_already_linked \
339  _bfd_generic_section_already_linked
340#define os9k_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
341#define os9k_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
342#define os9k_bfd_link_add_symbols _bfd_generic_link_add_symbols
343#define os9k_bfd_link_just_syms _bfd_generic_link_just_syms
344#define os9k_bfd_final_link _bfd_generic_final_link
345#define os9k_bfd_link_split_section  _bfd_generic_link_split_section
346
347const bfd_target i386os9k_vec =
348  {
349    "i386os9k",			/* name */
350    bfd_target_os9k_flavour,
351    BFD_ENDIAN_LITTLE,		/* data byte order is little */
352    BFD_ENDIAN_LITTLE,		/* hdr byte order is little */
353    (HAS_RELOC | EXEC_P | WP_TEXT),	/* object flags */
354    (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD),	/* section flags */
355    0,				/* symbol leading char */
356    ' ',				/* ar_pad_char */
357    16,				/* ar_max_namelen */
358
359    bfd_getl64, bfd_getl_signed_64, bfd_putl64,
360    bfd_getl32, bfd_getl_signed_32, bfd_putl32,
361    bfd_getl16, bfd_getl_signed_16, bfd_putl16,	/* data */
362    bfd_getl64, bfd_getl_signed_64, bfd_putl64,
363    bfd_getl32, bfd_getl_signed_32, bfd_putl32,
364    bfd_getl16, bfd_getl_signed_16, bfd_putl16,	/* hdrs */
365    {_bfd_dummy_target, os9k_object_p,	/* bfd_check_format */
366     bfd_generic_archive_p, _bfd_dummy_target},
367    {bfd_false, bfd_false,	/* bfd_set_format */
368     _bfd_generic_mkarchive, bfd_false},
369    {bfd_false, bfd_false,	/* bfd_write_contents */
370     _bfd_write_archive_contents, bfd_false},
371
372    BFD_JUMP_TABLE_GENERIC (aout_32),
373    BFD_JUMP_TABLE_COPY (_bfd_generic),
374    BFD_JUMP_TABLE_CORE (_bfd_nocore),
375    BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd),
376    BFD_JUMP_TABLE_SYMBOLS (aout_32),
377    BFD_JUMP_TABLE_RELOCS (aout_32),
378    BFD_JUMP_TABLE_WRITE (aout_32),
379    BFD_JUMP_TABLE_LINK (os9k),
380    BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
381
382    NULL,
383
384    (PTR) 0,
385  };
386