2002-04-04 Daniel Jacobowitz <drow@mvista.com>
[external/binutils.git] / bfd / i386msdos.c
1 /* BFD back-end for MS-DOS executables.
2    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2001, 2002
3    Free Software Foundation, Inc.
4    Written by Bryan Ford of the University of Utah.
5
6    Contributed by the Center for Software Science at the
7    University of Utah (pa-gdb-bugs@cs.utah.edu).
8
9    This file is part of BFD, the Binary File Descriptor library.
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
24
25
26 #include "bfd.h"
27 #include "sysdep.h"
28 #include "libbfd.h"
29 #include "libaout.h"
30
31 #if 0
32 struct exe_header
33 {
34   unsigned short magic;
35   unsigned short bytes_in_last_page;
36   unsigned short npages;        /* number of 512-byte "pages" including this header */
37   unsigned short nrelocs;
38   unsigned short header_paras;  /* number of 16-byte paragraphs in header */
39   unsigned short reserved;
40   unsigned short load_switch;
41   unsigned short ss_ofs;
42   unsigned short sp;
43   unsigned short checksum;
44   unsigned short ip;
45   unsigned short cs_ofs;
46   unsigned short reloc_ofs;
47   unsigned short reserved2;
48   unsigned short something1;
49   unsigned short something2;
50   unsigned short something3;
51 };
52 #endif
53
54 #define EXE_MAGIC       0x5a4d
55 #define EXE_LOAD_HIGH   0x0000
56 #define EXE_LOAD_LOW    0xffff
57 #define EXE_PAGE_SIZE   512
58
59 static int     msdos_sizeof_headers PARAMS ((bfd *, boolean));
60 static boolean msdos_write_object_contents PARAMS ((bfd *));
61 static boolean msdos_set_section_contents PARAMS ((bfd *, sec_ptr, PTR, file_ptr, bfd_size_type));
62
63 static int
64 msdos_sizeof_headers (abfd, exec)
65      bfd *abfd ATTRIBUTE_UNUSED;
66      boolean exec ATTRIBUTE_UNUSED;
67 {
68   return 0;
69 }
70
71 static boolean
72 msdos_write_object_contents (abfd)
73      bfd *abfd;
74 {
75   static char hdr[EXE_PAGE_SIZE];
76   file_ptr outfile_size = sizeof(hdr);
77   bfd_vma high_vma = 0;
78   asection *sec;
79
80   /* Find the total size of the program on disk and in memory.  */
81   for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
82     {
83       if (bfd_get_section_size_before_reloc (sec) == 0)
84         continue;
85       if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)
86         {
87           bfd_vma sec_vma = bfd_get_section_vma (abfd, sec)
88                             + bfd_get_section_size_before_reloc (sec);
89           if (sec_vma > high_vma)
90             high_vma = sec_vma;
91         }
92       if (bfd_get_section_flags (abfd, sec) & SEC_LOAD)
93         {
94           file_ptr sec_end = sizeof(hdr)
95                              + bfd_get_section_vma (abfd, sec)
96                              + bfd_get_section_size_before_reloc (sec);
97           if (sec_end > outfile_size)
98             outfile_size = sec_end;
99         }
100     }
101
102   /* Make sure the program isn't too big.  */
103   if (high_vma > (bfd_vma)0xffff)
104     {
105       bfd_set_error(bfd_error_file_too_big);
106       return false;
107     }
108
109   /* Constants.  */
110   H_PUT_16 (abfd, EXE_MAGIC, &hdr[0]);
111   H_PUT_16 (abfd, EXE_PAGE_SIZE / 16, &hdr[8]);
112   H_PUT_16 (abfd, EXE_LOAD_LOW, &hdr[12]);
113   H_PUT_16 (abfd, 0x3e, &hdr[24]);
114   H_PUT_16 (abfd, 0x0001, &hdr[28]); /* XXX??? */
115   H_PUT_16 (abfd, 0x30fb, &hdr[30]); /* XXX??? */
116   H_PUT_16 (abfd, 0x726a, &hdr[32]); /* XXX??? */
117
118   /* Bytes in last page (0 = full page).  */
119   H_PUT_16 (abfd, outfile_size & (EXE_PAGE_SIZE - 1), &hdr[2]);
120
121   /* Number of pages.  */
122   H_PUT_16 (abfd, (outfile_size + EXE_PAGE_SIZE - 1) / EXE_PAGE_SIZE, &hdr[4]);
123
124   /* Set the initial stack pointer to the end of the bss.
125      The program's crt0 code must relocate it to a real stack.  */
126   H_PUT_16 (abfd, high_vma, &hdr[16]);
127
128   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
129       || bfd_bwrite (hdr, (bfd_size_type) sizeof(hdr), abfd) != sizeof(hdr))
130     return false;
131
132   return true;
133 }
134
135 static boolean
136 msdos_set_section_contents (abfd, section, location, offset, count)
137      bfd *abfd;
138      sec_ptr section;
139      PTR location;
140      file_ptr offset;
141      bfd_size_type count;
142 {
143
144   if (count == 0)
145     return true;
146
147   section->filepos = EXE_PAGE_SIZE + bfd_get_section_vma (abfd, section);
148
149   if (bfd_get_section_flags (abfd, section) & SEC_LOAD)
150     {
151       if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0
152           || bfd_bwrite (location, count, abfd) != count)
153         return false;
154     }
155
156   return true;
157 }
158
159
160
161 #define msdos_mkobject aout_32_mkobject
162 #define msdos_make_empty_symbol aout_32_make_empty_symbol
163 #define msdos_bfd_reloc_type_lookup aout_32_reloc_type_lookup
164
165 #define msdos_close_and_cleanup _bfd_generic_close_and_cleanup
166 #define msdos_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
167 #define msdos_new_section_hook _bfd_generic_new_section_hook
168 #define msdos_get_section_contents _bfd_generic_get_section_contents
169 #define msdos_get_section_contents_in_window \
170   _bfd_generic_get_section_contents_in_window
171 #define msdos_bfd_get_relocated_section_contents \
172   bfd_generic_get_relocated_section_contents
173 #define msdos_bfd_relax_section bfd_generic_relax_section
174 #define msdos_bfd_gc_sections bfd_generic_gc_sections
175 #define msdos_bfd_merge_sections bfd_generic_merge_sections
176 #define msdos_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
177 #define msdos_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
178 #define msdos_bfd_link_add_symbols _bfd_generic_link_add_symbols
179 #define msdos_bfd_final_link _bfd_generic_final_link
180 #define msdos_bfd_link_split_section _bfd_generic_link_split_section
181 #define msdos_set_arch_mach _bfd_generic_set_arch_mach
182
183 #define msdos_get_symtab_upper_bound _bfd_nosymbols_get_symtab_upper_bound
184 #define msdos_get_symtab _bfd_nosymbols_get_symtab
185 #define msdos_print_symbol _bfd_nosymbols_print_symbol
186 #define msdos_get_symbol_info _bfd_nosymbols_get_symbol_info
187 #define msdos_find_nearest_line _bfd_nosymbols_find_nearest_line
188 #define msdos_get_lineno _bfd_nosymbols_get_lineno
189 #define msdos_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name
190 #define msdos_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
191 #define msdos_read_minisymbols _bfd_nosymbols_read_minisymbols
192 #define msdos_minisymbol_to_symbol _bfd_nosymbols_minisymbol_to_symbol
193
194 #define msdos_canonicalize_reloc _bfd_norelocs_canonicalize_reloc
195 #define msdos_get_reloc_upper_bound _bfd_norelocs_get_reloc_upper_bound
196 #define msdos_32_bfd_link_split_section  _bfd_generic_link_split_section
197
198 const bfd_target i386msdos_vec =
199   {
200     "msdos",                    /* name */
201     bfd_target_msdos_flavour,
202     BFD_ENDIAN_LITTLE,          /* target byte order */
203     BFD_ENDIAN_LITTLE,          /* target headers byte order */
204     (EXEC_P),                   /* object flags */
205     (SEC_CODE | SEC_DATA | SEC_HAS_CONTENTS
206      | SEC_ALLOC | SEC_LOAD),   /* section flags */
207     0,                          /* leading underscore */
208     ' ',                                /* ar_pad_char */
209     16,                         /* ar_max_namelen */
210     bfd_getl64, bfd_getl_signed_64, bfd_putl64,
211     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
212     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
213     bfd_getl64, bfd_getl_signed_64, bfd_putl64,
214     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
215     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
216
217     {
218       _bfd_dummy_target,
219       _bfd_dummy_target,                /* bfd_check_format */
220       _bfd_dummy_target,
221       _bfd_dummy_target,
222     },
223     {
224       bfd_false,
225       msdos_mkobject,
226       _bfd_generic_mkarchive,
227       bfd_false,
228     },
229     {                           /* bfd_write_contents */
230       bfd_false,
231       msdos_write_object_contents,
232       _bfd_write_archive_contents,
233       bfd_false,
234     },
235
236     BFD_JUMP_TABLE_GENERIC (msdos),
237     BFD_JUMP_TABLE_COPY (_bfd_generic),
238     BFD_JUMP_TABLE_CORE (_bfd_nocore),
239     BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
240     BFD_JUMP_TABLE_SYMBOLS (msdos),
241     BFD_JUMP_TABLE_RELOCS (msdos),
242     BFD_JUMP_TABLE_WRITE (msdos),
243     BFD_JUMP_TABLE_LINK (msdos),
244     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
245
246     NULL,
247
248     (PTR) 0
249   };
250
251