1/* BFD back-end for a.out files encapsulated with COFF headers.
2   Copyright 1990, 1991, 1994, 1995, 2000, 2001, 2002, 2003
3   Free Software Foundation, Inc.
4
5This file is part of BFD, the Binary File Descriptor library.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21/* THIS MODULE IS NOT FINISHED.  IT PROBABLY DOESN'T EVEN COMPILE.  */
22
23#if 0
24#define	TARGET_PAGE_SIZE	4096
25#define	SEGMENT_SIZE	TARGET_PAGE_SIZE
26#define TEXT_START_ADDR 0
27#endif
28
29#include "bfd.h"
30#include "sysdep.h"
31#include "libbfd.h"
32#include "aout/aout64.h"
33#include "aout/stab_gnu.h"
34#include "aout/ar.h"
35#include "libaout.h"           /* BFD a.out internal data structures */
36
37const bfd_target *encap_real_callback ();
38
39const bfd_target *
40encap_object_p (abfd)
41     bfd *abfd;
42{
43  unsigned char magicbuf[4]; /* Raw bytes of magic number from file */
44  unsigned long magic;		/* Swapped magic number */
45  short coff_magic;
46  struct external_exec exec_bytes;
47  struct internal_exec exec;
48  bfd_size_type amt = sizeof (magicbuf);
49
50  if (bfd_bread ((PTR) magicbuf, amt, abfd) != amt)
51    {
52      if (bfd_get_error () != bfd_error_system_call)
53	bfd_set_error (bfd_error_wrong_format);
54      return 0;
55    }
56
57  coff_magic = H_GET_16 (abfd, magicbuf);
58  if (coff_magic != COFF_MAGIC)
59    return 0;			/* Not an encap coff file */
60
61  magic = H_GET_32 (abfd, magicbuf);
62
63  if (N_BADMAG (*((struct internal_exec *) &magic)))
64    return 0;
65
66  if (bfd_seek (abfd, (file_ptr) sizeof (struct coffheader), SEEK_SET) != 0)
67    return 0;
68
69  amt = EXEC_BYTES_SIZE;
70  if (bfd_bread ((PTR) &exec_bytes, amt, abfd) != amt)
71    {
72      if (bfd_get_error () != bfd_error_system_call)
73	bfd_set_error (bfd_error_wrong_format);
74      return 0;
75    }
76  NAME(aout,swap_exec_header_in) (abfd, &exec_bytes, &exec);
77
78  return aout_32_some_aout_object_p (abfd, &exec, encap_realcallback);
79}
80
81/* Finish up the reading of an encapsulated-coff a.out file header.  */
82const bfd_target *
83encap_real_callback (abfd)
84     bfd *abfd;
85{
86  struct internal_exec *execp = exec_hdr (abfd);
87
88  MY(callback) (abfd, execp);
89
90  /* If we have a coff header, it can give us better values for
91     text_start and exec_data_start.  This is particularly useful
92     for remote debugging of embedded systems.  */
93  if (N_FLAGS(exec_aouthdr) & N_FLAGS_COFF_ENCAPSULATE)
94    {
95      struct coffheader ch;
96      int val;
97      val = lseek (execchan, -(sizeof (AOUTHDR) + sizeof (ch)), 1);
98      if (val == -1)
99	perror_with_name (filename);
100      val = myread (execchan, &ch, sizeof (ch));
101      if (val < 0)
102	perror_with_name (filename);
103      text_start = ch.text_start;
104      exec_data_start = ch.data_start;
105    }
106  else
107    {
108      text_start =
109	IS_OBJECT_FILE (exec_aouthdr) ? 0 : N_TXTADDR (exec_aouthdr);
110      exec_data_start = (IS_OBJECT_FILE (exec_aouthdr)
111			 ? exec_aouthdr.a_text
112			 : N_DATADDR (exec_aouthdr));
113    }
114
115  /* Determine the architecture and machine type of the object file.  */
116  bfd_default_set_arch_mach(abfd, bfd_arch_m68k, 0); /* FIXME */
117
118  return abfd->xvec;
119}
120
121/* Write an object file in Encapsulated COFF format.
122   Section contents have already been written.  We write the
123   file header, symbols, and relocation.  */
124
125bfd_boolean
126encap_write_object_contents (abfd)
127     bfd *abfd;
128{
129  bfd_size_type data_pad = 0;
130  struct external_exec exec_bytes;
131  struct internal_exec *execp = exec_hdr (abfd);
132
133  /* FIXME:  Fragments from the old GNU LD program for dealing with
134     encap coff.  */
135  struct coffheader coffheader;
136  int need_coff_header;
137
138  /* Determine whether to count the header as part of
139     the text size, and initialize the text size accordingly.
140     This depends on the kind of system and on the output format selected.  */
141
142  N_SET_MAGIC (outheader, magic);
143#ifdef INITIALIZE_HEADER
144  INITIALIZE_HEADER;
145#endif
146
147  text_size = sizeof (struct exec);
148#ifdef COFF_ENCAPSULATE
149  if (relocatable_output == 0 && file_table[0].just_syms_flag == 0)
150    {
151      need_coff_header = 1;
152      /* set this flag now, since it will change the values of N_TXTOFF, etc */
153      N_SET_FLAGS (outheader, aout_backend_info (abfd)->exec_hdr_flags);
154      text_size += sizeof (struct coffheader);
155    }
156#endif
157
158#ifdef COFF_ENCAPSULATE
159  if (need_coff_header)
160    {
161      /* We are encapsulating BSD format within COFF format.  */
162      struct coffscn *tp, *dp, *bp;
163
164      tp = &coffheader.scns[0];
165      dp = &coffheader.scns[1];
166      bp = &coffheader.scns[2];
167
168      strcpy (tp->s_name, ".text");
169      tp->s_paddr = text_start;
170      tp->s_vaddr = text_start;
171      tp->s_size = text_size;
172      tp->s_scnptr = sizeof (struct coffheader) + sizeof (struct exec);
173      tp->s_relptr = 0;
174      tp->s_lnnoptr = 0;
175      tp->s_nreloc = 0;
176      tp->s_nlnno = 0;
177      tp->s_flags = 0x20;
178      strcpy (dp->s_name, ".data");
179      dp->s_paddr = data_start;
180      dp->s_vaddr = data_start;
181      dp->s_size = data_size;
182      dp->s_scnptr = tp->s_scnptr + tp->s_size;
183      dp->s_relptr = 0;
184      dp->s_lnnoptr = 0;
185      dp->s_nreloc = 0;
186      dp->s_nlnno = 0;
187      dp->s_flags = 0x40;
188      strcpy (bp->s_name, ".bss");
189      bp->s_paddr = dp->s_vaddr + dp->s_size;
190      bp->s_vaddr = bp->s_paddr;
191      bp->s_size = bss_size;
192      bp->s_scnptr = 0;
193      bp->s_relptr = 0;
194      bp->s_lnnoptr = 0;
195      bp->s_nreloc = 0;
196      bp->s_nlnno = 0;
197      bp->s_flags = 0x80;
198
199      coffheader.f_magic = COFF_MAGIC;
200      coffheader.f_nscns = 3;
201      /* store an unlikely time so programs can
202       * tell that there is a bsd header
203       */
204      coffheader.f_timdat = 1;
205      coffheader.f_symptr = 0;
206      coffheader.f_nsyms = 0;
207      coffheader.f_opthdr = 28;
208      coffheader.f_flags = 0x103;
209      /* aouthdr */
210      coffheader.magic = ZMAGIC;
211      coffheader.vstamp = 0;
212      coffheader.tsize = tp->s_size;
213      coffheader.dsize = dp->s_size;
214      coffheader.bsize = bp->s_size;
215      coffheader.entry = outheader.a_entry;
216      coffheader.text_start = tp->s_vaddr;
217      coffheader.data_start = dp->s_vaddr;
218    }
219#endif
220
221#ifdef COFF_ENCAPSULATE
222  if (need_coff_header)
223    mywrite (&coffheader, sizeof coffheader, 1, outdesc);
224#endif
225
226#ifndef COFF_ENCAPSULATE
227  padfile (N_TXTOFF (outheader) - sizeof outheader, outdesc);
228#endif
229
230  text_size -= N_TXTOFF (outheader);
231  WRITE_HEADERS(abfd, execp);
232  return TRUE;
233}
234
235#define MY_write_object_content encap_write_object_contents
236#define MY_object_p encap_object_p
237#define MY_exec_hdr_flags N_FLAGS_COFF_ENCAPSULATE
238
239#include "aout-target.h"
240