[PATCH v2 resend] [BFD] Add support for reading msdos (MZ) executables.

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH v2 resend] [BFD] Add support for reading msdos (MZ) executables.

Zebediah Figura
Allows them to be read with objdump. I ran `make test` and found no
regressions.

        include/
        * msdos.h: New header.
        * coff/pe.h: Move common defines to msdos.h.
        * coff/powerpc.h: Likewise.
        bfd/
        * i386msdos.c: Add msdos_object_p().
        * 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.

Signed-off-by: Zebediah Figura <[hidden email]>
---
Resent now that my copright assignment should hopefully be taken care of.

 bfd/coff-ia64.c        |  6 ++--
 bfd/i386msdos.c        | 89 +++++++++++++++++++++++++++++++++++++++++++++++---
 bfd/peXXigen.c         |  4 +--
 bfd/peicode.h          |  6 ++--
 include/coff/pe.h      | 31 ++----------------
 include/coff/powerpc.h |  2 --
 include/msdos.h        | 57 ++++++++++++++++++++++++++++++++
 7 files changed, 152 insertions(+), 43 deletions(-)
 create mode 100644 include/msdos.h

diff --git a/bfd/coff-ia64.c b/bfd/coff-ia64.c
index 56100dd..270c959 100644
--- a/bfd/coff-ia64.c
+++ b/bfd/coff-ia64.c
@@ -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;
diff --git a/bfd/i386msdos.c b/bfd/i386msdos.c
index c15707c..7541a6f 100644
--- a/bfd/i386msdos.c
+++ b/bfd/i386msdos.c
@@ -27,12 +27,94 @@
 #include "bfd.h"
 #include "libbfd.h"
 #include "libaout.h"
+#include "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,
     },
diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index 679dabf..6caca17 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -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);
diff --git a/bfd/peicode.h b/bfd/peicode.h
index 94dd861..30dc08b 100644
--- a/bfd/peicode.h
+++ b/bfd/peicode.h
@@ -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;
diff --git a/include/coff/pe.h b/include/coff/pe.h
index f9035bf..56cc4e2 100644
--- a/include/coff/pe.h
+++ b/include/coff/pe.h
@@ -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
@@ -168,40 +170,11 @@
 #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.  */
diff --git a/include/coff/powerpc.h b/include/coff/powerpc.h
index 37fef42..a5e56fb 100644
--- a/include/coff/powerpc.h
+++ b/include/coff/powerpc.h
@@ -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
diff --git a/include/msdos.h b/include/msdos.h
new file mode 100644
index 0000000..df2be0a
--- /dev/null
+++ b/include/msdos.h
@@ -0,0 +1,57 @@
+/* msdos.h  -  MS-DOS and derived executable header information
+
+   Copyright (C) 1999-2017 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 */
--
2.7.4

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v2 resend] [BFD] Add support for reading msdos (MZ) executables.

Nick Clifton
Gu Zebediah,

> include/
> * msdos.h: New header.
> * coff/pe.h: Move common defines to msdos.h.
> * coff/powerpc.h: Likewise.
> bfd/
> * i386msdos.c: Add msdos_object_p().
> * 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.

Approved and applied.  I made one small change, moving the msdos.h header
into the include/coff directory.

> Resent now that my copright assignment should hopefully be taken care of.

It has.  Thank you for persisting with this.

Cheers
  Nick