1 /* BFD back-end for MS-DOS executables. 2 Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 98, 1999 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 60 static int 61 msdos_sizeof_headers (abfd, exec) 62 bfd *abfd ATTRIBUTE_UNUSED; 63 boolean exec ATTRIBUTE_UNUSED; 64 { 65 return 0; 66 } 67 68 static boolean 69 msdos_write_object_contents (abfd) 70 bfd *abfd; 71 { 72 static char hdr[EXE_PAGE_SIZE]; 73 file_ptr outfile_size = sizeof(hdr); 74 bfd_vma high_vma = 0; 75 asection *sec; 76 77 /* Find the total size of the program on disk and in memory. */ 78 for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next) 79 { 80 if (bfd_get_section_size_before_reloc (sec) == 0) 81 continue; 82 if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC) 83 { 84 bfd_vma sec_vma = bfd_get_section_vma (abfd, sec) 85 + bfd_get_section_size_before_reloc (sec); 86 if (sec_vma > high_vma) 87 high_vma = sec_vma; 88 } 89 if (bfd_get_section_flags (abfd, sec) & SEC_LOAD) 90 { 91 file_ptr sec_end = sizeof(hdr) 92 + bfd_get_section_vma (abfd, sec) 93 + bfd_get_section_size_before_reloc (sec); 94 if (sec_end > outfile_size) 95 outfile_size = sec_end; 96 } 97 } 98 99 /* Make sure the program isn't too big. */ 100 if (high_vma > (bfd_vma)0xffff) 101 { 102 bfd_set_error(bfd_error_file_too_big); 103 return false; 104 } 105 106 /* constants */ 107 bfd_h_put_16(abfd, EXE_MAGIC, &hdr[0]); 108 bfd_h_put_16(abfd, EXE_PAGE_SIZE / 16, &hdr[8]); 109 bfd_h_put_16(abfd, EXE_LOAD_LOW, &hdr[12]); 110 bfd_h_put_16(abfd, 0x3e, &hdr[24]); 111 bfd_h_put_16(abfd, 0x0001, &hdr[28]); /* XXX??? */ 112 bfd_h_put_16(abfd, 0x30fb, &hdr[30]); /* XXX??? */ 113 bfd_h_put_16(abfd, 0x726a, &hdr[32]); /* XXX??? */ 114 115 /* bytes in last page (0 = full page) */ 116 bfd_h_put_16(abfd, outfile_size & (EXE_PAGE_SIZE - 1), &hdr[2]); 117 118 /* number of pages */ 119 bfd_h_put_16(abfd, (outfile_size + EXE_PAGE_SIZE - 1) / EXE_PAGE_SIZE, 120 &hdr[4]); 121 122 /* Set the initial stack pointer to the end of the bss. 123 The program's crt0 code must relocate it to a real stack. */ 124 bfd_h_put_16(abfd, high_vma, &hdr[16]); 125 126 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 127 || bfd_write (hdr, 1, sizeof(hdr), abfd) != sizeof(hdr)) 128 return false; 129 130 return true; 131 } 132 133 static boolean 134 msdos_set_section_contents (abfd, section, location, offset, count) 135 bfd *abfd; 136 sec_ptr section; 137 PTR location; 138 file_ptr offset; 139 bfd_size_type count; 140 { 141 142 if (count == 0) 143 return true; 144 145 section->filepos = EXE_PAGE_SIZE + bfd_get_section_vma (abfd, section); 146 147 if (bfd_get_section_flags (abfd, section) & SEC_LOAD) 148 { 149 if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0 150 || bfd_write (location, 1, count, abfd) != count) 151 return false; 152 } 153 154 return true; 155 } 156 157 158 159 #define msdos_mkobject aout_32_mkobject 160 #define msdos_make_empty_symbol aout_32_make_empty_symbol 161 #define msdos_bfd_reloc_type_lookup aout_32_reloc_type_lookup 162 163 #define msdos_close_and_cleanup _bfd_generic_close_and_cleanup 164 #define msdos_bfd_free_cached_info _bfd_generic_bfd_free_cached_info 165 #define msdos_new_section_hook _bfd_generic_new_section_hook 166 #define msdos_get_section_contents _bfd_generic_get_section_contents 167 #define msdos_get_section_contents_in_window \ 168 _bfd_generic_get_section_contents_in_window 169 #define msdos_bfd_get_relocated_section_contents \ 170 bfd_generic_get_relocated_section_contents 171 #define msdos_bfd_relax_section bfd_generic_relax_section 172 #define msdos_bfd_gc_sections bfd_generic_gc_sections 173 #define msdos_bfd_link_hash_table_create _bfd_generic_link_hash_table_create 174 #define msdos_bfd_link_add_symbols _bfd_generic_link_add_symbols 175 #define msdos_bfd_final_link _bfd_generic_final_link 176 #define msdos_bfd_link_split_section _bfd_generic_link_split_section 177 #define msdos_set_arch_mach _bfd_generic_set_arch_mach 178 179 #define msdos_get_symtab_upper_bound _bfd_nosymbols_get_symtab_upper_bound 180 #define msdos_get_symtab _bfd_nosymbols_get_symtab 181 #define msdos_print_symbol _bfd_nosymbols_print_symbol 182 #define msdos_get_symbol_info _bfd_nosymbols_get_symbol_info 183 #define msdos_find_nearest_line _bfd_nosymbols_find_nearest_line 184 #define msdos_get_lineno _bfd_nosymbols_get_lineno 185 #define msdos_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name 186 #define msdos_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol 187 #define msdos_read_minisymbols _bfd_nosymbols_read_minisymbols 188 #define msdos_minisymbol_to_symbol _bfd_nosymbols_minisymbol_to_symbol 189 190 #define msdos_canonicalize_reloc _bfd_norelocs_canonicalize_reloc 191 #define msdos_get_reloc_upper_bound _bfd_norelocs_get_reloc_upper_bound 192 #define msdos_32_bfd_link_split_section _bfd_generic_link_split_section 193 194 const bfd_target i386msdos_vec = 195 { 196 "msdos", /* name */ 197 bfd_target_msdos_flavour, 198 BFD_ENDIAN_LITTLE, /* target byte order */ 199 BFD_ENDIAN_LITTLE, /* target headers byte order */ 200 (EXEC_P), /* object flags */ 201 (SEC_CODE | SEC_DATA | SEC_HAS_CONTENTS 202 | SEC_ALLOC | SEC_LOAD), /* section flags */ 203 0, /* leading underscore */ 204 ' ', /* ar_pad_char */ 205 16, /* ar_max_namelen */ 206 bfd_getl64, bfd_getl_signed_64, bfd_putl64, 207 bfd_getl32, bfd_getl_signed_32, bfd_putl32, 208 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */ 209 bfd_getl64, bfd_getl_signed_64, bfd_putl64, 210 bfd_getl32, bfd_getl_signed_32, bfd_putl32, 211 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */ 212 213 { 214 _bfd_dummy_target, 215 _bfd_dummy_target, /* bfd_check_format */ 216 _bfd_dummy_target, 217 _bfd_dummy_target, 218 }, 219 { 220 bfd_false, 221 msdos_mkobject, 222 _bfd_generic_mkarchive, 223 bfd_false, 224 }, 225 { /* bfd_write_contents */ 226 bfd_false, 227 msdos_write_object_contents, 228 _bfd_write_archive_contents, 229 bfd_false, 230 }, 231 232 BFD_JUMP_TABLE_GENERIC (msdos), 233 BFD_JUMP_TABLE_COPY (_bfd_generic), 234 BFD_JUMP_TABLE_CORE (_bfd_nocore), 235 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), 236 BFD_JUMP_TABLE_SYMBOLS (msdos), 237 BFD_JUMP_TABLE_RELOCS (msdos), 238 BFD_JUMP_TABLE_WRITE (msdos), 239 BFD_JUMP_TABLE_LINK (msdos), 240 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 241 242 NULL, 243 244 (PTR) 0 245 }; 246 247 248