Add support for reading msdos MZ executables.
authorZebediah Figura <z.figura12@gmail.com>
Mon, 12 Feb 2018 13:12:45 +0000 (13:12 +0000)
committerNick Clifton <nickc@redhat.com>
Mon, 12 Feb 2018 13:15:56 +0000 (13:15 +0000)
See email thread starting here:  https://www.sourceware.org/ml/binutils/2018-01/msg00001.html

include * coff/msdos.h: New header.
* coff/pe.h: Move common defines to msdos.h.
* coff/powerpc.h: Likewise.

bfd * i386msdos.c (msdos_mkobject); New function.
(msdos_object_p): New function.
(i386_msdos_vec): Use msdos_object_p as the check_format
function.
* peicode.h: Rename external_PEI_DOS_hdr, DOSMAGIC, and
NT_SIGNATURE to external_DOS_hdr, IMAGE_DOS_SIGNATURE, and
IMAGE_NT_SIGNATURE.
* peXXigen.c: Likewise.
* coff-ia64.c: Likewise.

bfd/ChangeLog
bfd/coff-ia64.c
bfd/i386msdos.c
bfd/peXXigen.c
bfd/peicode.h
include/ChangeLog
include/coff/msdos.h [new file with mode: 0644]
include/coff/pe.h
include/coff/powerpc.h

index f1478064a4396e68f99bcfaa316acd2067c2cf17..960e48492c91107498e27c70454feef2141e23fe 100644 (file)
@@ -1,3 +1,15 @@
+2018-02-12  Zebediah Figura  <z.figura12@gmail.com>
+
+       * i386msdos.c (msdos_mkobject); New function.
+       (msdos_object_p): New function.
+       (i386_msdos_vec): Use msdos_object_p as the check_format
+       function.
+       * peicode.h: Rename external_PEI_DOS_hdr, DOSMAGIC, and
+       NT_SIGNATURE to external_DOS_hdr, IMAGE_DOS_SIGNATURE, and
+       IMAGE_NT_SIGNATURE.
+       * peXXigen.c: Likewise.
+       * coff-ia64.c: Likewise.
+
 2018-02-12  Nick Clifton  <nickc@redhat.com>
 
        * elf32-nds32.c (nds32_elf_relax_longjump3): Remove redundant
index 56100dd4c76fe4abb0d8bbdab5aad9d351fd03c8..270c959dff384bc3ad4d8fcc465f80b914a0618f 100644 (file)
@@ -72,7 +72,7 @@ ia64coff_object_p (bfd *abfd)
 {
 #ifdef COFF_IMAGE_WITH_PE
   {
-    struct external_PEI_DOS_hdr dos_hdr;
+    struct external_DOS_hdr dos_hdr;
     struct external_PEI_IMAGE_hdr image_hdr;
     file_ptr offset;
 
@@ -87,7 +87,7 @@ ia64coff_object_p (bfd *abfd)
 
     /* There are really two magic numbers involved; the magic number
        that says this is a NT executable (PEI) and the magic number
-       that determines the architecture.  The former is DOSMAGIC,
+       that determines the architecture.  The former is IMAGE_DOS_SIGNATURE,
        stored in the e_magic field.  The latter is stored in the
        f_magic field.  If the NT magic number isn't valid, the
        architecture magic number could be mimicked by some other
@@ -95,7 +95,7 @@ ia64coff_object_p (bfd *abfd)
        this routine can only be called correctly for a PEI file, check
        the e_magic number here, and, if it doesn't match, clobber the
        f_magic number so that we don't get a false match.  */
-    if (H_GET_16 (abfd, dos_hdr.e_magic) != DOSMAGIC)
+    if (H_GET_16 (abfd, dos_hdr.e_magic) != IMAGE_DOS_SIGNATURE)
       {
        bfd_set_error (bfd_error_wrong_format);
        return NULL;
index c15707c38d315db1eedb9a1117f4f2fa5d21981d..5437b162fae24368d7b23f6571f8c9ae258c50c2 100644 (file)
 #include "bfd.h"
 #include "libbfd.h"
 #include "libaout.h"
+#include "coff/msdos.h"
 
-#define EXE_MAGIC      0x5a4d
 #define EXE_LOAD_HIGH  0x0000
 #define EXE_LOAD_LOW   0xffff
 #define EXE_PAGE_SIZE  512
 
+static bfd_boolean
+msdos_mkobject (bfd *abfd)
+{
+  bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_i386_i8086);
+
+  return aout_32_mkobject (abfd);
+}
+
+static const bfd_target *
+msdos_object_p (bfd *abfd)
+{
+  struct external_DOS_hdr hdr;
+  bfd_byte buffer[2];
+  asection *section;
+  unsigned int size;
+
+  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
+      || bfd_bread (&hdr, (bfd_size_type) sizeof (hdr), abfd) < DOS_HDR_SIZE)
+    {
+      if (bfd_get_error () != bfd_error_system_call)
+       bfd_set_error (bfd_error_wrong_format);
+      return NULL;
+    }
+
+  if (H_GET_16 (abfd, hdr.e_magic) != IMAGE_DOS_SIGNATURE)
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return NULL;
+    }
+
+  /* Check that this isn't actually a PE, NE, or LE file. If it is, the
+     e_lfanew field will be valid and point to a header beginning with one of
+     the relevant signatures.  If not, e_lfanew might point to anything, so
+     don't bail if we can't read there.  */
+  if (H_GET_16 (abfd, hdr.e_cparhdr) < 4
+      || bfd_seek (abfd, (file_ptr) H_GET_32 (abfd, hdr.e_lfanew), SEEK_SET) != 0
+      || bfd_bread (buffer, (bfd_size_type) 2, abfd) != 2)
+    {
+      if (bfd_get_error () == bfd_error_system_call)
+       return NULL;
+    }
+  else
+    {
+      if (H_GET_16 (abfd, buffer) == IMAGE_NT_SIGNATURE
+         || H_GET_16 (abfd, buffer) == IMAGE_OS2_SIGNATURE
+         || H_GET_16 (abfd, buffer) == IMAGE_OS2_SIGNATURE_LE
+         || H_GET_16 (abfd, buffer) == IMAGE_OS2_SIGNATURE_LX)
+       {
+         bfd_set_error (bfd_error_wrong_format);
+         return NULL;
+       }
+    }
+
+  if (!msdos_mkobject (abfd))
+    return NULL;
+
+  abfd->flags = EXEC_P;
+  abfd->start_address = H_GET_16 (abfd, hdr.e_ip);
+
+  section = bfd_make_section (abfd, ".text");
+  if (section == NULL)
+    return NULL;
+
+  section->flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS);
+  section->filepos = H_GET_16 (abfd, hdr.e_cparhdr) * 16;
+  size = (H_GET_16 (abfd, hdr.e_cp) - 1) * EXE_PAGE_SIZE - section->filepos;
+  size += H_GET_16 (abfd, hdr.e_cblp);
+
+  /* Check that the size is valid.  */
+  if (bfd_seek (abfd, (file_ptr) (section->filepos + size), SEEK_SET) != 0)
+    {
+      if (bfd_get_error () != bfd_error_system_call)
+       bfd_set_error (bfd_error_wrong_format);
+      return NULL;
+    }
+
+  bfd_set_section_size (abfd, section, size);
+  section->alignment_power = 4;
+
+  return abfd->xvec;
+}
+
 static int
 msdos_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
                      struct bfd_link_info *info ATTRIBUTE_UNUSED)
@@ -77,7 +159,7 @@ msdos_write_object_contents (bfd *abfd)
     }
 
   /* Constants.  */
-  H_PUT_16 (abfd, EXE_MAGIC, &hdr[0]);
+  H_PUT_16 (abfd, IMAGE_DOS_SIGNATURE, &hdr[0]);
   H_PUT_16 (abfd, EXE_PAGE_SIZE / 16, &hdr[8]);
   H_PUT_16 (abfd, EXE_LOAD_LOW, &hdr[12]);
   H_PUT_16 (abfd, 0x3e, &hdr[24]);
@@ -127,7 +209,6 @@ msdos_set_section_contents (bfd *abfd,
 
 
 
-#define msdos_mkobject aout_32_mkobject
 #define msdos_make_empty_symbol aout_32_make_empty_symbol
 #define msdos_bfd_reloc_type_lookup aout_32_reloc_type_lookup
 #define msdos_bfd_reloc_name_lookup aout_32_reloc_name_lookup
@@ -203,7 +284,7 @@ const bfd_target i386_msdos_vec =
 
     {
       _bfd_dummy_target,
-      _bfd_dummy_target,               /* bfd_check_format */
+      msdos_object_p,          /* bfd_check_format */
       _bfd_dummy_target,
       _bfd_dummy_target,
     },
index 679dabf4cf023d47b662c49ee424fb4cb704495e..6caca1729b8e80fc6e341e551e7a381af56befc4 100644 (file)
@@ -828,7 +828,7 @@ _bfd_XXi_only_swap_filehdr_out (bfd * abfd, void * in, void * out)
   if (pe_data (abfd)->dll)
     filehdr_in->f_flags |= F_DLL;
 
-  filehdr_in->pe.e_magic    = DOSMAGIC;
+  filehdr_in->pe.e_magic    = IMAGE_DOS_SIGNATURE;
   filehdr_in->pe.e_cblp     = 0x90;
   filehdr_in->pe.e_cp       = 0x3;
   filehdr_in->pe.e_crlc     = 0x0;
@@ -872,7 +872,7 @@ _bfd_XXi_only_swap_filehdr_out (bfd * abfd, void * in, void * out)
   filehdr_in->pe.dos_message[13] = 0x0a0d0d2e;
   filehdr_in->pe.dos_message[14] = 0x24;
   filehdr_in->pe.dos_message[15] = 0x0;
-  filehdr_in->pe.nt_signature = NT_SIGNATURE;
+  filehdr_in->pe.nt_signature = IMAGE_NT_SIGNATURE;
 
   H_PUT_16 (abfd, filehdr_in->f_magic, filehdr_out->f_magic);
   H_PUT_16 (abfd, filehdr_in->f_nscns, filehdr_out->f_nscns);
index 94dd861a91e85c295891d3d6ca9b3ff1f011df01..30dc08b45eae80d2c84244d13a5b1c361f460b7d 100644 (file)
@@ -1386,7 +1386,7 @@ static const bfd_target *
 pe_bfd_object_p (bfd * abfd)
 {
   bfd_byte buffer[6];
-  struct external_PEI_DOS_hdr dos_hdr;
+  struct external_DOS_hdr dos_hdr;
   struct external_PEI_IMAGE_hdr image_hdr;
   struct internal_filehdr internal_f;
   struct internal_aouthdr internal_a;
@@ -1420,7 +1420,7 @@ pe_bfd_object_p (bfd * abfd)
 
   /* There are really two magic numbers involved; the magic number
      that says this is a NT executable (PEI) and the magic number that
-     determines the architecture.  The former is DOSMAGIC, stored in
+     determines the architecture.  The former is IMAGE_DOS_SIGNATURE, stored in
      the e_magic field.  The latter is stored in the f_magic field.
      If the NT magic number isn't valid, the architecture magic number
      could be mimicked by some other field (specifically, the number
@@ -1428,7 +1428,7 @@ pe_bfd_object_p (bfd * abfd)
      correctly for a PEI file, check the e_magic number here, and, if
      it doesn't match, clobber the f_magic number so that we don't get
      a false match.  */
-  if (H_GET_16 (abfd, dos_hdr.e_magic) != DOSMAGIC)
+  if (H_GET_16 (abfd, dos_hdr.e_magic) != IMAGE_DOS_SIGNATURE)
     {
       bfd_set_error (bfd_error_wrong_format);
       return NULL;
index ea7476c2f3b1e3f63826b1aa623d59f901ec7061..2563ab58397bc6e35a7fef2b4830b320125a8015 100644 (file)
@@ -1,3 +1,9 @@
+2018-02-12  Zebediah Figura  <z.figura12@gmail.com>
+
+       * coff/msdos.h: New header.
+       * coff/pe.h: Move common defines to msdos.h.
+       * coff/powerpc.h: Likewise.
+
 2018-01-13  Nick Clifton  <nickc@redhat.com>
 
        2.30 branch created.
diff --git a/include/coff/msdos.h b/include/coff/msdos.h
new file mode 100644 (file)
index 0000000..cebd957
--- /dev/null
@@ -0,0 +1,57 @@
+/* msdos.h  -  MS-DOS and derived executable header information
+
+   Copyright (C) 1999-2018 Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+#ifndef _MSDOS_H
+#define _MSDOS_H
+
+#define IMAGE_DOS_SIGNATURE    0x5a4d          /* MZ */
+#define IMAGE_OS2_SIGNATURE    0x454e          /* NE */
+#define IMAGE_OS2_SIGNATURE_LE 0x454c          /* LE */
+#define IMAGE_OS2_SIGNATURE_LX 0x584c          /* LX */
+#define IMAGE_NT_SIGNATURE     0x00004550      /* PE\0\0 */
+
+struct external_DOS_hdr
+{
+  /* DOS header fields - always at offset zero in the EXE file.  */
+  char e_magic[2];             /* Magic number.  */
+  char e_cblp[2];              /* Bytes on last page of file.  */
+  char e_cp[2];                        /* Pages in file.  */
+  char e_crlc[2];              /* Relocations.  */
+  char e_cparhdr[2];           /* Size of header in paragraphs.  */
+  char e_minalloc[2];          /* Minimum extra paragraphs needed.  */
+  char e_maxalloc[2];          /* Maximum extra paragraphs needed.  */
+  char e_ss[2];                        /* Initial (relative) SS value.  */
+  char e_sp[2];                        /* Initial SP value.  */
+  char e_csum[2];              /* Checksum.  */
+  char e_ip[2];                        /* Initial IP value.  */
+  char e_cs[2];                        /* Initial (relative) CS value.  */
+  char e_lfarlc[2];            /* File address of relocation table.  */
+  char e_ovno[2];              /* Overlay number.  */
+  char e_res[4][2];            /* Reserved words, all 0x0.  */
+  char e_oemid[2];             /* OEM identifier.  */
+  char e_oeminfo[2];           /* OEM information.  */
+  char e_res2[10][2];          /* Reserved words, all 0x0.  */
+  char e_lfanew[4];            /* File address of new exe header, usually 0x80.  */
+  char dos_message[16][4];     /* Other stuff, always follow DOS header.  */
+};
+
+/* The actual DOS header only includes up to the e_ovno field.  */
+#define DOS_HDR_SIZE           (offsetof (struct external_DOS_hdr, e_res))
+
+#endif /* _MSDOS_H */
index f9035bf8a351de3d803926273f8f332367f5e519..56cc4e20c2c4461cd0216896e54f53f42be97381 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef _PE_H
 #define _PE_H
 
+#include "msdos.h"
+
 /* NT specific file attributes.  */
 #define IMAGE_FILE_RELOCS_STRIPPED           0x0001
 #define IMAGE_FILE_EXECUTABLE_IMAGE          0x0002
 #define IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER     13
 #define IMAGE_SUBSYSTEM_XBOX                   14
 
-/* Magic values that are true for all dos/nt implementations.  */
-#define DOSMAGIC       0x5a4d
-#define NT_SIGNATURE   0x00004550
-
 /* NT allows long filenames, we want to accommodate this.
    This may break some of the bfd functions.  */
 #undef  FILNMLEN
 #define FILNMLEN       18      /* # characters in a file name.  */
 
-struct external_PEI_DOS_hdr
-{
-  /* DOS header fields - always at offset zero in the EXE file.  */
-  char e_magic[2];             /* Magic number, 0x5a4d.  */
-  char e_cblp[2];              /* Bytes on last page of file, 0x90.  */
-  char e_cp[2];                        /* Pages in file, 0x3.  */
-  char e_crlc[2];              /* Relocations, 0x0.  */
-  char e_cparhdr[2];           /* Size of header in paragraphs, 0x4.  */
-  char e_minalloc[2];          /* Minimum extra paragraphs needed, 0x0.  */
-  char e_maxalloc[2];          /* Maximum extra paragraphs needed, 0xFFFF.  */
-  char e_ss[2];                        /* Initial (relative) SS value, 0x0.  */
-  char e_sp[2];                        /* Initial SP value, 0xb8.  */
-  char e_csum[2];              /* Checksum, 0x0.  */
-  char e_ip[2];                        /* Initial IP value, 0x0.  */
-  char e_cs[2];                        /* Initial (relative) CS value, 0x0.  */
-  char e_lfarlc[2];            /* File address of relocation table, 0x40.  */
-  char e_ovno[2];              /* Overlay number, 0x0.  */
-  char e_res[4][2];            /* Reserved words, all 0x0.  */
-  char e_oemid[2];             /* OEM identifier (for e_oeminfo), 0x0.  */
-  char e_oeminfo[2];           /* OEM information; e_oemid specific, 0x0.  */
-  char e_res2[10][2];          /* Reserved words, all 0x0.  */
-  char e_lfanew[4];            /* File address of new exe header, usually 0x80.  */
-  char dos_message[16][4];     /* Other stuff, always follow DOS header.  */
-};
-
 struct external_PEI_IMAGE_hdr
 {
   char nt_signature[4];                /* Required NT signature, 0x4550.  */
index 37fef428ba9295750d192ddbbf7b33c0589396a0..a5e56fb1e70edc46ad5aa741b68a0a2e0b026b7b 100644 (file)
@@ -37,8 +37,6 @@
 
 /* extra NT defines */
 #define PPCMAGIC       0760         /* peeked on aa PowerPC Windows NT box */
-#define DOSMAGIC       0x5a4d       /* from arm.h, i386.h */
-#define NT_SIGNATURE   0x00004550   /* from arm.h, i386.h */
 
 /* from winnt.h */
 #define IMAGE_NT_OPTIONAL_HDR_MAGIC        0x10b