[2/2] For PE files, copy dos_message contents from source binary

Message ID 20191017192801.3oj477ouzvcn4j7z@foghorn.codeweavers.com
State New
Headers show
Series
  • [1/2] Fix size of dos_message type in internal_extra_pe_filehdr
Related show

Commit Message

Andrew Eikum Oct. 17, 2019, 7:28 p.m.
Wine uses a special message in this area to mark its own binaries.
strip(1) would discard the message from the original binary and replace
it with a hard-coded string. This would break Wine when its libraries
are built as PE files and installed with strip(1).

For example, see the special message in the original DLL from a Wine
build tree, starting at offset 0x40:

$ xxd ~/src/wine.win64/dlls/ieframe/ieframe.dll | head
00000000: 4d5a 9000 0300 0000 0400 0000 ffff 0000  MZ..............
00000010: b800 0000 0000 0000 4000 0000 0000 0000  ........@.......
00000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000030: 0000 0000 0000 0000 0000 0000 8000 0000  ................
00000040: 5769 6e65 2062 7569 6c74 696e 2044 4c4c  Wine builtin DLL
00000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000060: 7420 6265 2072 756e 2069 6e20 444f 5320  t be run in DOS
00000070: 6d6f 6465 2e0d 0d0a 2400 0000 0000 0000  mode....$.......
00000080: 5045 0000 6486 1200 58f1 9c5d 0030 3900  PE..d...X..].09.
00000090: 6817 0000 f000 2620 0b02 0220 0030 0300  h.....& ... .0..

And see how it is removed after stripping:

$ strip -o /tmp/ieframe.dll ~/src/wine.win64/dlls/ieframe/ieframe.dll
$ xxd /tmp/ieframe.dll | head
00000000: 4d5a 9000 0300 0000 0400 0000 ffff 0000  MZ..............
00000010: b800 0000 0000 0000 4000 0000 0000 0000  ........@.......
00000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000030: 0000 0000 0000 0000 0000 0000 8000 0000  ................
00000040: 0e1f ba0e 00b4 09cd 21b8 014c cd21 5468  ........!..L.!Th
00000050: 6973 2070 726f 6772 616d 2063 616e 6e6f  is program canno
00000060: 7420 6265 2072 756e 2069 6e20 444f 5320  t be run in DOS
00000070: 6d6f 6465 2e0d 0d0a 2400 0000 0000 0000  mode....$.......
00000080: 5045 0000 6486 0b00 0000 0000 0000 0000  PE..d...........
00000090: 0000 0000 f000 2e22 0b02 0220 0030 0300  ......."... .0..

This patch copies the message from the original binary into the new
binary.

Signed-off-by: Andrew Eikum <aeikum@codeweavers.com>

---
 bfd/libcoff-in.h |  1 +
 bfd/libcoff.h    |  1 +
 bfd/peXXigen.c   | 23 +++++------------------
 bfd/peicode.h    | 22 ++++++++++++++++++++++
 4 files changed, 29 insertions(+), 18 deletions(-)

-- 
2.23.0

Comments

Andrew Eikum Oct. 29, 2019, 1:05 p.m. | #1
Hey Nick,

Thanks for merging that patch. This is the other one in the series.
The first patch changed size of the dos_message field so it could be
used here in the memcpy()s.

Thanks,
Andrew

On Thu, Oct 17, 2019 at 02:28:02PM -0500, Andrew Eikum wrote:
> Wine uses a special message in this area to mark its own binaries.

> strip(1) would discard the message from the original binary and replace

> it with a hard-coded string. This would break Wine when its libraries

> are built as PE files and installed with strip(1).

> 

> For example, see the special message in the original DLL from a Wine

> build tree, starting at offset 0x40:

> 

> $ xxd ~/src/wine.win64/dlls/ieframe/ieframe.dll | head

> 00000000: 4d5a 9000 0300 0000 0400 0000 ffff 0000  MZ..............

> 00000010: b800 0000 0000 0000 4000 0000 0000 0000  ........@.......

> 00000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................

> 00000030: 0000 0000 0000 0000 0000 0000 8000 0000  ................

> 00000040: 5769 6e65 2062 7569 6c74 696e 2044 4c4c  Wine builtin DLL

> 00000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................

> 00000060: 7420 6265 2072 756e 2069 6e20 444f 5320  t be run in DOS

> 00000070: 6d6f 6465 2e0d 0d0a 2400 0000 0000 0000  mode....$.......

> 00000080: 5045 0000 6486 1200 58f1 9c5d 0030 3900  PE..d...X..].09.

> 00000090: 6817 0000 f000 2620 0b02 0220 0030 0300  h.....& ... .0..

> 

> And see how it is removed after stripping:

> 

> $ strip -o /tmp/ieframe.dll ~/src/wine.win64/dlls/ieframe/ieframe.dll

> $ xxd /tmp/ieframe.dll | head

> 00000000: 4d5a 9000 0300 0000 0400 0000 ffff 0000  MZ..............

> 00000010: b800 0000 0000 0000 4000 0000 0000 0000  ........@.......

> 00000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................

> 00000030: 0000 0000 0000 0000 0000 0000 8000 0000  ................

> 00000040: 0e1f ba0e 00b4 09cd 21b8 014c cd21 5468  ........!..L.!Th

> 00000050: 6973 2070 726f 6772 616d 2063 616e 6e6f  is program canno

> 00000060: 7420 6265 2072 756e 2069 6e20 444f 5320  t be run in DOS

> 00000070: 6d6f 6465 2e0d 0d0a 2400 0000 0000 0000  mode....$.......

> 00000080: 5045 0000 6486 0b00 0000 0000 0000 0000  PE..d...........

> 00000090: 0000 0000 f000 2e22 0b02 0220 0030 0300  ......."... .0..

> 

> This patch copies the message from the original binary into the new

> binary.

> 

> Signed-off-by: Andrew Eikum <aeikum@codeweavers.com>

> ---

>  bfd/libcoff-in.h |  1 +

>  bfd/libcoff.h    |  1 +

>  bfd/peXXigen.c   | 23 +++++------------------

>  bfd/peicode.h    | 22 ++++++++++++++++++++++

>  4 files changed, 29 insertions(+), 18 deletions(-)

> 

> diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h

> index 783d54a88a..5386236bc0 100644

> --- a/bfd/libcoff-in.h

> +++ b/bfd/libcoff-in.h

> @@ -128,6 +128,7 @@ typedef struct pe_tdata

>    int has_reloc_section;

>    int dont_strip_reloc;

>    bfd_boolean insert_timestamp;

> +  int dos_message[16];

>    bfd_boolean (*in_reloc_p) (bfd *, reloc_howto_type *);

>    flagword real_flags;

>  

> diff --git a/bfd/libcoff.h b/bfd/libcoff.h

> index f2613c2e77..cdd483535f 100644

> --- a/bfd/libcoff.h

> +++ b/bfd/libcoff.h

> @@ -132,6 +132,7 @@ typedef struct pe_tdata

>    int has_reloc_section;

>    int dont_strip_reloc;

>    bfd_boolean insert_timestamp;

> +  int dos_message[16];

>    bfd_boolean (*in_reloc_p) (bfd *, reloc_howto_type *);

>    flagword real_flags;

>  

> diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c

> index ab0da7f532..f6daf85859 100644

> --- a/bfd/peXXigen.c

> +++ b/bfd/peXXigen.c

> @@ -861,24 +861,9 @@ _bfd_XXi_only_swap_filehdr_out (bfd * abfd, void * in, void * out)

>  

>    filehdr_in->pe.e_lfanew = 0x80;

>  

> -  /* This next collection of data are mostly just characters.  It

> -     appears to be constant within the headers put on NT exes.  */

> -  filehdr_in->pe.dos_message[0]  = 0x0eba1f0e;

> -  filehdr_in->pe.dos_message[1]  = 0xcd09b400;

> -  filehdr_in->pe.dos_message[2]  = 0x4c01b821;

> -  filehdr_in->pe.dos_message[3]  = 0x685421cd;

> -  filehdr_in->pe.dos_message[4]  = 0x70207369;

> -  filehdr_in->pe.dos_message[5]  = 0x72676f72;

> -  filehdr_in->pe.dos_message[6]  = 0x63206d61;

> -  filehdr_in->pe.dos_message[7]  = 0x6f6e6e61;

> -  filehdr_in->pe.dos_message[8]  = 0x65622074;

> -  filehdr_in->pe.dos_message[9]  = 0x6e757220;

> -  filehdr_in->pe.dos_message[10] = 0x206e6920;

> -  filehdr_in->pe.dos_message[11] = 0x20534f44;

> -  filehdr_in->pe.dos_message[12] = 0x65646f6d;

> -  filehdr_in->pe.dos_message[13] = 0x0a0d0d2e;

> -  filehdr_in->pe.dos_message[14] = 0x24;

> -  filehdr_in->pe.dos_message[15] = 0x0;

> +  memcpy (filehdr_in->pe.dos_message, pe_data (abfd)->dos_message,

> +	  sizeof (filehdr_in->pe.dos_message));

> +

>    filehdr_in->pe.nt_signature = IMAGE_NT_SIGNATURE;

>  

>    H_PUT_16 (abfd, filehdr_in->f_magic, filehdr_out->f_magic);

> @@ -2979,6 +2964,8 @@ _bfd_XX_bfd_copy_private_bfd_data_common (bfd * ibfd, bfd * obfd)

>        && ! (pe_data (ibfd)->real_flags & IMAGE_FILE_RELOCS_STRIPPED))

>      pe_data (obfd)->dont_strip_reloc = 1;

>  

> +  memcpy (ope->dos_message, ipe->dos_message, sizeof (ope->dos_message));

> +

>    /* The file offsets contained in the debug directory need rewriting.  */

>    if (ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size != 0)

>      {

> diff --git a/bfd/peicode.h b/bfd/peicode.h

> index 1e2b104430..fed2b2d586 100644

> --- a/bfd/peicode.h

> +++ b/bfd/peicode.h

> @@ -271,6 +271,24 @@ pe_mkobject (bfd * abfd)

>    /* in_reloc_p is architecture dependent.  */

>    pe->in_reloc_p = in_reloc_p;

>  

> +  /* default dos message string */

> +  pe->dos_message[0]  = 0x0eba1f0e;

> +  pe->dos_message[1]  = 0xcd09b400;

> +  pe->dos_message[2]  = 0x4c01b821;

> +  pe->dos_message[3]  = 0x685421cd;

> +  pe->dos_message[4]  = 0x70207369;

> +  pe->dos_message[5]  = 0x72676f72;

> +  pe->dos_message[6]  = 0x63206d61;

> +  pe->dos_message[7]  = 0x6f6e6e61;

> +  pe->dos_message[8]  = 0x65622074;

> +  pe->dos_message[9]  = 0x6e757220;

> +  pe->dos_message[10] = 0x206e6920;

> +  pe->dos_message[11] = 0x20534f44;

> +  pe->dos_message[12] = 0x65646f6d;

> +  pe->dos_message[13] = 0x0a0d0d2e;

> +  pe->dos_message[14] = 0x24;

> +  pe->dos_message[15] = 0x0;

> +

>    memset (& pe->pe_opthdr, 0, sizeof pe->pe_opthdr);

>    return TRUE;

>  }

> @@ -325,6 +343,8 @@ pe_mkobject_hook (bfd * abfd,

>      coff_data (abfd) ->flags = 0;

>  #endif

>  

> +  memcpy (pe->dos_message, internal_f->pe.dos_message, sizeof (pe->dos_message));

> +

>    return (void *) pe;

>  }

>  

> @@ -1456,6 +1476,8 @@ pe_bfd_object_p (bfd * abfd)

>        return NULL;

>      }

>  

> +  memcpy (internal_f.pe.dos_message, dos_hdr.dos_message, sizeof (internal_f.pe.dos_message));

> +

>    /* Read the optional header, which has variable size.  */

>    opt_hdr_size = internal_f.f_opthdr;

>  

> -- 

> 2.23.0

>
Nick Clifton Oct. 29, 2019, 5:08 p.m. | #2
Hi Andrew,

> Thanks for merging that patch. This is the other one in the series.

> The first patch changed size of the dos_message field so it could be

> used here in the memcpy()s.

 
Approved and applied. :-)

Cheers
  Nick
Andrew Eikum Oct. 29, 2019, 5:31 p.m. | #3
On Tue, Oct 29, 2019 at 05:08:46PM +0000, Nick Clifton wrote:
> Hi Andrew,

> 

> > Thanks for merging that patch. This is the other one in the series.

> > The first patch changed size of the dos_message field so it could be

> > used here in the memcpy()s.

>  

> Approved and applied. :-)

> 


Thanks, Nick!  I'll go let the other Wine folks know.

Andrew

Patch

diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h
index 783d54a88a..5386236bc0 100644
--- a/bfd/libcoff-in.h
+++ b/bfd/libcoff-in.h
@@ -128,6 +128,7 @@  typedef struct pe_tdata
   int has_reloc_section;
   int dont_strip_reloc;
   bfd_boolean insert_timestamp;
+  int dos_message[16];
   bfd_boolean (*in_reloc_p) (bfd *, reloc_howto_type *);
   flagword real_flags;
 
diff --git a/bfd/libcoff.h b/bfd/libcoff.h
index f2613c2e77..cdd483535f 100644
--- a/bfd/libcoff.h
+++ b/bfd/libcoff.h
@@ -132,6 +132,7 @@  typedef struct pe_tdata
   int has_reloc_section;
   int dont_strip_reloc;
   bfd_boolean insert_timestamp;
+  int dos_message[16];
   bfd_boolean (*in_reloc_p) (bfd *, reloc_howto_type *);
   flagword real_flags;
 
diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index ab0da7f532..f6daf85859 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -861,24 +861,9 @@  _bfd_XXi_only_swap_filehdr_out (bfd * abfd, void * in, void * out)
 
   filehdr_in->pe.e_lfanew = 0x80;
 
-  /* This next collection of data are mostly just characters.  It
-     appears to be constant within the headers put on NT exes.  */
-  filehdr_in->pe.dos_message[0]  = 0x0eba1f0e;
-  filehdr_in->pe.dos_message[1]  = 0xcd09b400;
-  filehdr_in->pe.dos_message[2]  = 0x4c01b821;
-  filehdr_in->pe.dos_message[3]  = 0x685421cd;
-  filehdr_in->pe.dos_message[4]  = 0x70207369;
-  filehdr_in->pe.dos_message[5]  = 0x72676f72;
-  filehdr_in->pe.dos_message[6]  = 0x63206d61;
-  filehdr_in->pe.dos_message[7]  = 0x6f6e6e61;
-  filehdr_in->pe.dos_message[8]  = 0x65622074;
-  filehdr_in->pe.dos_message[9]  = 0x6e757220;
-  filehdr_in->pe.dos_message[10] = 0x206e6920;
-  filehdr_in->pe.dos_message[11] = 0x20534f44;
-  filehdr_in->pe.dos_message[12] = 0x65646f6d;
-  filehdr_in->pe.dos_message[13] = 0x0a0d0d2e;
-  filehdr_in->pe.dos_message[14] = 0x24;
-  filehdr_in->pe.dos_message[15] = 0x0;
+  memcpy (filehdr_in->pe.dos_message, pe_data (abfd)->dos_message,
+	  sizeof (filehdr_in->pe.dos_message));
+
   filehdr_in->pe.nt_signature = IMAGE_NT_SIGNATURE;
 
   H_PUT_16 (abfd, filehdr_in->f_magic, filehdr_out->f_magic);
@@ -2979,6 +2964,8 @@  _bfd_XX_bfd_copy_private_bfd_data_common (bfd * ibfd, bfd * obfd)
       && ! (pe_data (ibfd)->real_flags & IMAGE_FILE_RELOCS_STRIPPED))
     pe_data (obfd)->dont_strip_reloc = 1;
 
+  memcpy (ope->dos_message, ipe->dos_message, sizeof (ope->dos_message));
+
   /* The file offsets contained in the debug directory need rewriting.  */
   if (ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size != 0)
     {
diff --git a/bfd/peicode.h b/bfd/peicode.h
index 1e2b104430..fed2b2d586 100644
--- a/bfd/peicode.h
+++ b/bfd/peicode.h
@@ -271,6 +271,24 @@  pe_mkobject (bfd * abfd)
   /* in_reloc_p is architecture dependent.  */
   pe->in_reloc_p = in_reloc_p;
 
+  /* default dos message string */
+  pe->dos_message[0]  = 0x0eba1f0e;
+  pe->dos_message[1]  = 0xcd09b400;
+  pe->dos_message[2]  = 0x4c01b821;
+  pe->dos_message[3]  = 0x685421cd;
+  pe->dos_message[4]  = 0x70207369;
+  pe->dos_message[5]  = 0x72676f72;
+  pe->dos_message[6]  = 0x63206d61;
+  pe->dos_message[7]  = 0x6f6e6e61;
+  pe->dos_message[8]  = 0x65622074;
+  pe->dos_message[9]  = 0x6e757220;
+  pe->dos_message[10] = 0x206e6920;
+  pe->dos_message[11] = 0x20534f44;
+  pe->dos_message[12] = 0x65646f6d;
+  pe->dos_message[13] = 0x0a0d0d2e;
+  pe->dos_message[14] = 0x24;
+  pe->dos_message[15] = 0x0;
+
   memset (& pe->pe_opthdr, 0, sizeof pe->pe_opthdr);
   return TRUE;
 }
@@ -325,6 +343,8 @@  pe_mkobject_hook (bfd * abfd,
     coff_data (abfd) ->flags = 0;
 #endif
 
+  memcpy (pe->dos_message, internal_f->pe.dos_message, sizeof (pe->dos_message));
+
   return (void *) pe;
 }
 
@@ -1456,6 +1476,8 @@  pe_bfd_object_p (bfd * abfd)
       return NULL;
     }
 
+  memcpy (internal_f.pe.dos_message, dos_hdr.dos_message, sizeof (internal_f.pe.dos_message));
+
   /* Read the optional header, which has variable size.  */
   opt_hdr_size = internal_f.f_opthdr;