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
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
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
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
Can you try the current binutils? I can try to take a look if it still fails.
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
Created attachment 1672 [details] testcase-src from description, for the record, so that I can remove it from where was hosted.
Created attachment 1673 [details] testcase-full from description, for the record, so that I can remove it from where was hosted.
Created attachment 1674 [details] patch from additional comment #2
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
I got it. You can remove it now.
(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>
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
(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.