Bug 3732 - strip breaks mixed msvc++ (with manifest) and gcc (with debug) generated pei-i386
Summary: strip breaks mixed msvc++ (with manifest) and gcc (with debug) generated pei-...
Status: RESOLVED INVALID
Alias: None
Product: binutils
Classification: Unclassified
Component: binutils (show other bugs)
Version: unspecified
: P2 minor
Target Milestone: ---
Assignee: unassigned
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-12-15 17:27 UTC by Ramiro Polla
Modified: 2007-04-12 00:42 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
testcase-src from description, for the record, so that I can remove it from where was hosted. (1.04 KB, application/x-gzip)
2007-04-11 02:01 UTC, Ramiro Polla
Details
testcase-full from description, for the record, so that I can remove it from where was hosted. (197.59 KB, application/x-gzip)
2007-04-11 02:01 UTC, Ramiro Polla
Details
patch from additional comment #2 (346 bytes, patch)
2007-04-11 02:02 UTC, Ramiro Polla
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Ramiro Polla 2006-12-15 17:27:49 UTC
Hello,

I posted this bug as an e-mail to the list. Here it is a bug report.

Here's the scenario:
- A static library is built with MinGW gcc.exe *with* debug information.
- A C file which uses that static library is compiled with MSVC++'s cl.exe.
- Everything is linked using Microsoft's link.exe *with* manifest information.
(I don't know what that is, but MSVC++ does it by default now).
- The resulting executable runs fine.
- That executable is stripped using strip.exe.
- The resulting executable does not run anymore.

The system:
- gcc 3.4.6 built for MinGW. No other gccs tested.
- Microsoft Visual C++ 2005 Express Edition (the free one).
- binutils 2.17.50 and CVS.

It only happens if gcc.exe was run with debug (-g), and link.exe was run with
manifest files.

The testcase can be found at:
http://arrozcru.no-ip.org/testcase-src.tar.gz <- contains only the files to
reproduce the problem
http://arrozcru.no-ip.org/testcase-full.tar.gz <- also contains the files generated

It must be run from MSys with MSVC++'s bin folder in its PATH.
The problematic file is "gmsmain.exe".

-- more info from after the testcase was created --

Running all executables with wine, I get this error from "gmsmain.exe":
err:module:map_image Section .rsrc too large (11000+1000/10000)
err:module:map_image Section .rsrc too large (11000+1000/10000)
wine: could not load L"Z:\\export\\ramiro\\testcase\\gmsmain.exe": Bad EXE
format for

If I "strip -R .rsrc gmsmain.exe", it runs again.

Ramiro Polla
Comment 1 angustia@arrozcru.no-ip.org 2006-12-19 17:10:35 UTC
Subject:  New: strip breaks mixed msvc++ (with manifest)
 and gcc (with debug) generated pei-i386

After running the file with wine, I came closer to the problem. 
Specifically reading around 
http://source.winehq.org/source/dlls/ntdll/virtual.c#L1068

gmmain.exe (the original file with msvc++ manifest and gcc debug) had 
these sections:

Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         000083b4  00401000  00401000  00001000  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .rdata        00001d0e  0040a000  0040a000  0000a000  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .data         00001000  0040c000  0040c000  0000c000  2**4
                  CONTENTS, ALLOC, LOAD, DATA
  3 .stab         00000324  0040f000  0040f000  0000d000  2**2
                  CONTENTS, ALLOC, LOAD, DATA, DEBUGGING
  4 .stabstr      00000787  00410000  00410000  0000e000  2**0
                  CONTENTS, ALLOC, LOAD, DATA, DEBUGGING
  5 .rsrc         000001f8  00411000  00411000  0000f000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA

Strip removed .stab and .stabstr. That way, .rsrc was moved down the 
file. But the VirtualAddress value from .rsrc's IMAGE_SECTION_HEADER was 
not updated, and that lead to the error. PointerToRawData was, though.

I looked for other programs to strip pei-i386 executables. I came 
accross PE Explorer, in which I can remove some sections and re-save the 
file. Whenever I remove a section, it asks me "Number of sections has 
been changed. Update NumberOfSections and recalculate SizeOfImage?".

It seems to me that the sections headers need to and can safely be 
updated. I don't know if it's possible to come accross a file in which 
the VirtualAddress value can't be changed. I really don't know much 
about executable file formats.

Anyways, after I remove .stab and .stabstr with PE Explorer, and run 
binutils' strip on the output file (which I named gmmain2.exe), it works 
alright, and the size is exactly the same as if I had run strip on the 
original file, with debug information. Here is their objdump -h.

gmmain2.exe:     file format pei-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         000083b4  00401000  00401000  00000400  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .rdata        00001d0e  0040a000  0040a000  00008800  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .data         00001000  0040c000  0040c000  0000a600  2**4
                  CONTENTS, ALLOC, LOAD, DATA
  3 .rsrc         000001f8  0040f000  0040f000  0000b600  2**2
                  CONTENTS, ALLOC, LOAD, DATA

gmsmain.exe:     file format pei-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         000083b4  00401000  00401000  00000400  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .rdata        00001d0e  0040a000  0040a000  00008800  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .data         00001000  0040c000  0040c000  0000a600  2**4
                  CONTENTS, ALLOC, LOAD, DATA
  3 .rsrc         000001f8  00411000  00411000  0000b600  2**2
                  CONTENTS, ALLOC, LOAD, DATA

You can find both files here (gmsmain.exe is the same as in the other 
tarball. gmmain2.exe is the working file).
http://arrozcru.no-ip.org/stripped_files.tar.gz

Ramiro Polla
Comment 2 angustia@arrozcru.no-ip.org 2006-12-21 04:22:31 UTC
Subject:  strip breaks mixed msvc++ (with manifest) and
 gcc (with debug) generated pei-i386

The following hack re-calculates VirtualAddress for every section (based 
on previous section) except first one (which is just copied).
http://arrozcru.no-ip.org/strip_hack.patch

I couldn't find a better place to put it (I tried 
coff_compute_section_file_positions, but 
pe_data(abfd)->pe_opthdr.SectionAlignment isn't valid there yet).

Now the VirtualAddress fields are consistent with what PE Explorer 
generates. One new problem is that it seems the resources will also have 
to be regenerated (PE Explorer does this) to reflect the change of 
VirtualAddress. I'll start looking into this now.

Ramiro Polla
Comment 3 angustia@arrozcru.no-ip.org 2006-12-22 16:23:24 UTC
Subject:  strip breaks mixed msvc++ (with manifest) and
 gcc (with debug) generated pei-i386

Ok, this is way beyond my capabilities (and free time). So, I'll stop 
here, and hope someone with enough knowledge will pick up this 
information and finish =)

Apparently, besides recalculating the VirtualAddress for every section 
(like I did in that hacked patch), PE Explorer browses through the 
Resources and fixes the OffsetToDirectory and OffsetToData informations. 
It also seems to pack the resources eliminating unused data.

Good luck, devs...
Ramiro Polla
Comment 4 H.J. Lu 2007-04-06 15:32:13 UTC
Can you try the current binutils? I can try to take a look if it still fails.
Comment 5 H.J. Lu 2007-04-06 17:15:19 UTC
Please provide a testcase with one executable, working.exe and show me
how strip will generate a bad nonworking.exe with

# strip working.exe -o nonworking.exe
Comment 6 Ramiro Polla 2007-04-11 02:01:19 UTC
Created attachment 1672 [details]
testcase-src from description, for the record, so that I can remove it from where was hosted.
Comment 7 Ramiro Polla 2007-04-11 02:01:55 UTC
Created attachment 1673 [details]
testcase-full from description, for the record, so that I can remove it from where was hosted.
Comment 8 Ramiro Polla 2007-04-11 02:02:33 UTC
Created attachment 1674 [details]
patch from additional comment #2
Comment 9 Ramiro Polla 2007-04-11 02:41:55 UTC
Hello,

If you take gmmain.exe from testcase-full.tar.gz and strip it with:
strip-CVS gmmain.exe -o gmsmain.exe

you'll still get the error while trying to run the executable on Windows.
Wine, for some reason, seems to run the executable stripped with CVS correctly,
and it did not before. So, there was some improvement =)

Thanks for looking into this.

Ramiro Polla
Comment 10 H.J. Lu 2007-04-11 04:24:24 UTC
I got it. You can remove it now.
Comment 11 H.J. Lu 2007-04-11 04:48:58 UTC
(In reply to comment #9)
> Hello,
> 
> If you take gmmain.exe from testcase-full.tar.gz and strip it with:
> strip-CVS gmmain.exe -o gmsmain.exe
> 

I can't run gmmain.exe even without strip:

T:\home\hjl\bugs\binutils\pe-2\testcase>.\gmmain.exe
The system cannot execute the specified program.

T:\home\hjl\bugs\binutils\pe-2\testcase>
Comment 12 Ramiro Polla 2007-04-12 00:58:59 UTC
Hello,

That's odd. gmmain.exe runs fine on Windows XP SP2, but not on Windows XP
Professional.
It's either a bug on the Microsoft linker, or on Windows XP Professional. Most
likely on Windows, since SP2 runs it fine.

Anyways, the bug in binutils is still valid. Could you look for a machine with
Windows XP SP2 to test?

Ramiro Polla
Comment 13 H.J. Lu 2007-04-12 01:42:08 UTC
(In reply to comment #12)
> Hello,
> 
> That's odd. gmmain.exe runs fine on Windows XP SP2, but not on Windows XP
> Professional.
> It's either a bug on the Microsoft linker, or on Windows XP Professional. Most
> likely on Windows, since SP2 runs it fine.
> 
> Anyways, the bug in binutils is still valid. Could you look for a machine with
> Windows XP SP2 to test?
>

I only have Win/Pro. If it won't run on Win/Pro, I consider this executable
is bad. When you feed a bad input to strip, you won't get a good output. I
am closing this bug. You can reopen it when you find a testcase for Win/Pro.