]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/i386msdos.c
Automatic date update in version.in
[thirdparty/binutils-gdb.git] / bfd / i386msdos.c
CommitLineData
252b5132 1/* BFD back-end for MS-DOS executables.
fd67aa11 2 Copyright (C) 1990-2024 Free Software Foundation, Inc.
252b5132
RH
3 Written by Bryan Ford of the University of Utah.
4
5 Contributed by the Center for Software Science at the
6 University of Utah (pa-gdb-bugs@cs.utah.edu).
7
8 This file is part of BFD, the Binary File Descriptor library.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
cd123cb7 12 the Free Software Foundation; either version 3 of the License, or
252b5132
RH
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
cd123cb7
NC
22 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
23 MA 02110-1301, USA. */
252b5132
RH
24
25
252b5132 26#include "sysdep.h"
3db64b00 27#include "bfd.h"
252b5132
RH
28#include "libbfd.h"
29#include "libaout.h"
830db048 30#include "coff/msdos.h"
252b5132 31
252b5132
RH
32#define EXE_LOAD_HIGH 0x0000
33#define EXE_LOAD_LOW 0xffff
34#define EXE_PAGE_SIZE 512
35
0a1b45a2 36static bool
830db048
ZF
37msdos_mkobject (bfd *abfd)
38{
39 bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_i386_i8086);
40
41 return aout_32_mkobject (abfd);
42}
43
cb001c0d 44static bfd_cleanup
830db048
ZF
45msdos_object_p (bfd *abfd)
46{
47 struct external_DOS_hdr hdr;
48 bfd_byte buffer[2];
49 asection *section;
5e737279 50 bfd_size_type size;
830db048 51
226f9f4f
AM
52 if (bfd_seek (abfd, 0, SEEK_SET) != 0
53 || (size = bfd_read (&hdr, sizeof (hdr), abfd)) + 1 < DOS_HDR_SIZE + 1)
830db048
ZF
54 {
55 if (bfd_get_error () != bfd_error_system_call)
56 bfd_set_error (bfd_error_wrong_format);
57 return NULL;
58 }
59
60 if (H_GET_16 (abfd, hdr.e_magic) != IMAGE_DOS_SIGNATURE)
61 {
62 bfd_set_error (bfd_error_wrong_format);
63 return NULL;
64 }
65
66 /* Check that this isn't actually a PE, NE, or LE file. If it is, the
67 e_lfanew field will be valid and point to a header beginning with one of
68 the relevant signatures. If not, e_lfanew might point to anything, so
69 don't bail if we can't read there. */
5e737279
AM
70 if (size < offsetof (struct external_DOS_hdr, e_lfanew) + 4
71 || H_GET_16 (abfd, hdr.e_cparhdr) < 4)
72 ;
73 else if (bfd_seek (abfd, H_GET_32 (abfd, hdr.e_lfanew), SEEK_SET) != 0
226f9f4f 74 || bfd_read (buffer, 2, abfd) != 2)
830db048
ZF
75 {
76 if (bfd_get_error () == bfd_error_system_call)
77 return NULL;
78 }
79 else
80 {
81 if (H_GET_16 (abfd, buffer) == IMAGE_NT_SIGNATURE
82 || H_GET_16 (abfd, buffer) == IMAGE_OS2_SIGNATURE
83 || H_GET_16 (abfd, buffer) == IMAGE_OS2_SIGNATURE_LE
84 || H_GET_16 (abfd, buffer) == IMAGE_OS2_SIGNATURE_LX)
85 {
86 bfd_set_error (bfd_error_wrong_format);
87 return NULL;
88 }
89 }
90
91 if (!msdos_mkobject (abfd))
92 return NULL;
93
94 abfd->flags = EXEC_P;
95 abfd->start_address = H_GET_16 (abfd, hdr.e_ip);
96
97 section = bfd_make_section (abfd, ".text");
98 if (section == NULL)
99 return NULL;
100
101 section->flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS);
102 section->filepos = H_GET_16 (abfd, hdr.e_cparhdr) * 16;
103 size = (H_GET_16 (abfd, hdr.e_cp) - 1) * EXE_PAGE_SIZE - section->filepos;
104 size += H_GET_16 (abfd, hdr.e_cblp);
105
106 /* Check that the size is valid. */
5e737279 107 if (bfd_seek (abfd, section->filepos + size, SEEK_SET) != 0)
830db048
ZF
108 {
109 if (bfd_get_error () != bfd_error_system_call)
110 bfd_set_error (bfd_error_wrong_format);
111 return NULL;
112 }
113
fd361982 114 bfd_set_section_size (section, size);
830db048
ZF
115 section->alignment_power = 4;
116
cb001c0d 117 return _bfd_no_cleanup;
830db048
ZF
118}
119
252b5132 120static int
a6b96beb
AM
121msdos_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
122 struct bfd_link_info *info ATTRIBUTE_UNUSED)
252b5132
RH
123{
124 return 0;
125}
126
0a1b45a2 127static bool
a6b96beb 128msdos_write_object_contents (bfd *abfd)
252b5132
RH
129{
130 static char hdr[EXE_PAGE_SIZE];
131 file_ptr outfile_size = sizeof(hdr);
132 bfd_vma high_vma = 0;
133 asection *sec;
134
135 /* Find the total size of the program on disk and in memory. */
136 for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
137 {
eea6121a 138 if (sec->size == 0)
07d6d2b8 139 continue;
fd361982 140 if (bfd_section_flags (sec) & SEC_ALLOC)
07d6d2b8 141 {
fd361982 142 bfd_vma sec_vma = bfd_section_vma (sec) + sec->size;
252b5132
RH
143 if (sec_vma > high_vma)
144 high_vma = sec_vma;
145 }
fd361982 146 if (bfd_section_flags (sec) & SEC_LOAD)
07d6d2b8 147 {
911d08a7 148 file_ptr sec_end = (sizeof (hdr)
fd361982 149 + bfd_section_vma (sec)
eea6121a 150 + sec->size);
252b5132
RH
151 if (sec_end > outfile_size)
152 outfile_size = sec_end;
153 }
154 }
155
156 /* Make sure the program isn't too big. */
157 if (high_vma > (bfd_vma)0xffff)
158 {
159 bfd_set_error(bfd_error_file_too_big);
0a1b45a2 160 return false;
252b5132
RH
161 }
162
e4b17274 163 /* Constants. */
830db048 164 H_PUT_16 (abfd, IMAGE_DOS_SIGNATURE, &hdr[0]);
dc810e39
AM
165 H_PUT_16 (abfd, EXE_PAGE_SIZE / 16, &hdr[8]);
166 H_PUT_16 (abfd, EXE_LOAD_LOW, &hdr[12]);
167 H_PUT_16 (abfd, 0x3e, &hdr[24]);
168 H_PUT_16 (abfd, 0x0001, &hdr[28]); /* XXX??? */
169 H_PUT_16 (abfd, 0x30fb, &hdr[30]); /* XXX??? */
170 H_PUT_16 (abfd, 0x726a, &hdr[32]); /* XXX??? */
252b5132 171
e4b17274 172 /* Bytes in last page (0 = full page). */
dc810e39 173 H_PUT_16 (abfd, outfile_size & (EXE_PAGE_SIZE - 1), &hdr[2]);
252b5132 174
e4b17274 175 /* Number of pages. */
dc810e39 176 H_PUT_16 (abfd, (outfile_size + EXE_PAGE_SIZE - 1) / EXE_PAGE_SIZE, &hdr[4]);
252b5132
RH
177
178 /* Set the initial stack pointer to the end of the bss.
179 The program's crt0 code must relocate it to a real stack. */
dc810e39 180 H_PUT_16 (abfd, high_vma, &hdr[16]);
252b5132 181
226f9f4f
AM
182 if (bfd_seek (abfd, 0, SEEK_SET) != 0
183 || bfd_write (hdr, sizeof (hdr), abfd) != sizeof (hdr))
0a1b45a2 184 return false;
252b5132 185
0a1b45a2 186 return true;
252b5132
RH
187}
188
0a1b45a2 189static bool
a6b96beb
AM
190msdos_set_section_contents (bfd *abfd,
191 sec_ptr section,
192 const void *location,
193 file_ptr offset,
194 bfd_size_type count)
252b5132
RH
195{
196
197 if (count == 0)
0a1b45a2 198 return true;
252b5132 199
fd361982 200 section->filepos = EXE_PAGE_SIZE + bfd_section_vma (section);
252b5132 201
fd361982 202 if (bfd_section_flags (section) & SEC_LOAD)
252b5132 203 {
dc810e39 204 if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0
226f9f4f 205 || bfd_write (location, count, abfd) != count)
0a1b45a2 206 return false;
252b5132
RH
207 }
208
0a1b45a2 209 return true;
252b5132
RH
210}
211
212
213
252b5132
RH
214#define msdos_make_empty_symbol aout_32_make_empty_symbol
215#define msdos_bfd_reloc_type_lookup aout_32_reloc_type_lookup
157090f7 216#define msdos_bfd_reloc_name_lookup aout_32_reloc_name_lookup
252b5132
RH
217
218#define msdos_close_and_cleanup _bfd_generic_close_and_cleanup
219#define msdos_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
220#define msdos_new_section_hook _bfd_generic_new_section_hook
221#define msdos_get_section_contents _bfd_generic_get_section_contents
252b5132
RH
222#define msdos_bfd_get_relocated_section_contents \
223 bfd_generic_get_relocated_section_contents
224#define msdos_bfd_relax_section bfd_generic_relax_section
225#define msdos_bfd_gc_sections bfd_generic_gc_sections
ae17ab41 226#define msdos_bfd_lookup_section_flags bfd_generic_lookup_section_flags
8550eb6e 227#define msdos_bfd_merge_sections bfd_generic_merge_sections
72adc230 228#define msdos_bfd_is_group_section bfd_generic_is_group_section
cb7f4b29 229#define msdos_bfd_group_name bfd_generic_group_name
e61463e1 230#define msdos_bfd_discard_group bfd_generic_discard_group
082b7297
L
231#define msdos_section_already_linked \
232 _bfd_generic_section_already_linked
3023e3f6 233#define msdos_bfd_define_common_symbol bfd_generic_define_common_symbol
34a87bb0 234#define msdos_bfd_link_hide_symbol _bfd_generic_link_hide_symbol
7dba9362 235#define msdos_bfd_define_start_stop bfd_generic_define_start_stop
252b5132
RH
236#define msdos_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
237#define msdos_bfd_link_add_symbols _bfd_generic_link_add_symbols
2d653fc7 238#define msdos_bfd_link_just_syms _bfd_generic_link_just_syms
1338dd10
PB
239#define msdos_bfd_copy_link_hash_symbol_type \
240 _bfd_generic_copy_link_hash_symbol_type
252b5132
RH
241#define msdos_bfd_final_link _bfd_generic_final_link
242#define msdos_bfd_link_split_section _bfd_generic_link_split_section
243#define msdos_set_arch_mach _bfd_generic_set_arch_mach
4f3b23b3 244#define msdos_bfd_link_check_relocs _bfd_generic_link_check_relocs
252b5132
RH
245
246#define msdos_get_symtab_upper_bound _bfd_nosymbols_get_symtab_upper_bound
6cee3f79 247#define msdos_canonicalize_symtab _bfd_nosymbols_canonicalize_symtab
252b5132
RH
248#define msdos_print_symbol _bfd_nosymbols_print_symbol
249#define msdos_get_symbol_info _bfd_nosymbols_get_symbol_info
60bb06bc
L
250#define msdos_get_symbol_version_string \
251 _bfd_nosymbols_get_symbol_version_string
252b5132 252#define msdos_find_nearest_line _bfd_nosymbols_find_nearest_line
6e7a29c7 253#define msdos_find_nearest_line_with_alt _bfd_nosymbols_find_nearest_line_with_alt
9c461f7d 254#define msdos_find_line _bfd_nosymbols_find_line
4ab527b0 255#define msdos_find_inliner_info _bfd_nosymbols_find_inliner_info
252b5132 256#define msdos_get_lineno _bfd_nosymbols_get_lineno
d00dd7dc 257#define msdos_bfd_is_target_special_symbol _bfd_bool_bfd_asymbol_false
252b5132
RH
258#define msdos_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name
259#define msdos_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
260#define msdos_read_minisymbols _bfd_nosymbols_read_minisymbols
261#define msdos_minisymbol_to_symbol _bfd_nosymbols_minisymbol_to_symbol
262
263#define msdos_canonicalize_reloc _bfd_norelocs_canonicalize_reloc
23186865 264#define msdos_set_reloc _bfd_norelocs_set_reloc
252b5132
RH
265#define msdos_get_reloc_upper_bound _bfd_norelocs_get_reloc_upper_bound
266#define msdos_32_bfd_link_split_section _bfd_generic_link_split_section
267
6d00b590 268const bfd_target i386_msdos_vec =
252b5132 269 {
e4b17274
NC
270 "msdos", /* name */
271 bfd_target_msdos_flavour,
272 BFD_ENDIAN_LITTLE, /* target byte order */
273 BFD_ENDIAN_LITTLE, /* target headers byte order */
274 (EXEC_P), /* object flags */
275 (SEC_CODE | SEC_DATA | SEC_HAS_CONTENTS
276 | SEC_ALLOC | SEC_LOAD), /* section flags */
277 0, /* leading underscore */
278 ' ', /* ar_pad_char */
279 16, /* ar_max_namelen */
0aabe54e 280 0, /* match priority. */
d1bcae83 281 TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */
e4b17274
NC
282 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
283 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
284 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
285 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
286 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
287 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
288
289 {
290 _bfd_dummy_target,
830db048 291 msdos_object_p, /* bfd_check_format */
e4b17274
NC
292 _bfd_dummy_target,
293 _bfd_dummy_target,
294 },
295 {
d00dd7dc 296 _bfd_bool_bfd_false_error,
e4b17274
NC
297 msdos_mkobject,
298 _bfd_generic_mkarchive,
d00dd7dc 299 _bfd_bool_bfd_false_error,
e4b17274
NC
300 },
301 { /* bfd_write_contents */
d00dd7dc 302 _bfd_bool_bfd_false_error,
e4b17274
NC
303 msdos_write_object_contents,
304 _bfd_write_archive_contents,
d00dd7dc 305 _bfd_bool_bfd_false_error,
e4b17274
NC
306 },
307
308 BFD_JUMP_TABLE_GENERIC (msdos),
309 BFD_JUMP_TABLE_COPY (_bfd_generic),
310 BFD_JUMP_TABLE_CORE (_bfd_nocore),
311 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
312 BFD_JUMP_TABLE_SYMBOLS (msdos),
313 BFD_JUMP_TABLE_RELOCS (msdos),
314 BFD_JUMP_TABLE_WRITE (msdos),
315 BFD_JUMP_TABLE_LINK (msdos),
316 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
317
318 NULL,
dc810e39 319
2c3fc389 320 NULL
e4b17274 321 };
252b5132
RH
322
323