Subject: RE: Bad EXE format (error 193)
From: "Dave Korn" <[email-masked]>
To: <[email-masked]>
Cc: "'Lynn Winebarger'" <[email-masked]>
Date: Sat, 6 Oct 2007 00:06:27 +0100
List-Id: <cygwin.cygwin.com>

On 05 October 2007 03:28, Lynn Winebarger wrote:

[  Cc'ing the mailing list back in. ]

> On 10/4/07, Lynn Winebarger <> wrote:
>> On 10/4/07, Dave Korn <> wrote:
>>>  Yes, why not; feel free to send them both to me, off list.  Can't promise
>>> I'll spot anything, but I'll take a look.  (My first WAG would be that the
>>> sassy assembler does something different from other w32 assemblers and
>>> that's where the trouble is coming from).
>> 
>>    Many thanks, Dave, I will send them tonight.
>> 
> And they are attached.
> 
> Thanks!
> Lynn

  Well, this was a weird one.  I think the underlying problem must be a bug in
larceny's final link stage during the build.  First, this command made your
binary executable for me:

    objcopy -R .comment larceny.bin larceny2.exe

  To work this out, I looked at the headers to the binary you sent, using both
GNU (objdump -x) and MS (dumpbin /all).  Here's the output from editbin;
objdump shows all the same information in a slightly different form.

Microsoft (R) COFF/PE Dumper Version 8.00.50727.42
Copyright (C) Microsoft Corporation.  All rights reserved.

Dump of file larceny.bin

PE signature found

File Type: EXECUTABLE IMAGE

FILE HEADER VALUES
             14C machine (x86)
               8 number of sections
        47059D7D time date stamp Fri Oct 05 03:12:13 2007
           2E000 file pointer to symbol table
             6EA number of symbols
              E0 size of optional header
             107 characteristics
                   Relocations stripped
                   Executable
                   Line numbers stripped
                   32 bit word machine

OPTIONAL HEADER VALUES
             10B magic # (PE32)
            2.56 linker version
           23200 size of code
            9800 size of initialized data
            3000 size of uninitialized data
            1000 entry point (00401000)
            1000 base of code
           25000 base of data
          400000 image base (00400000 to 00435FFF)
            1000 section alignment
             200 file alignment
            4.00 operating system version
            1.00 image version
            4.00 subsystem version
               0 Win32 version
           36000 size of image
             2B8 size of headers
           44EB4 checksum
               3 subsystem (Windows CUI)
               0 DLL characteristics
          200000 size of stack reserve
            1000 size of stack commit
          100000 size of heap reserve
            1000 size of heap commit
               0 loader flags
              10 number of directories
               0 [       0] RVA [size] of Export Directory
           32000 [     860] RVA [size] of Import Directory
               0 [       0] RVA [size] of Resource Directory
               0 [       0] RVA [size] of Exception Directory
               0 [       0] RVA [size] of Certificates Directory
               0 [       0] RVA [size] of Base Relocation Directory
               0 [       0] RVA [size] of Debug Directory
               0 [       0] RVA [size] of Architecture Directory
               0 [       0] RVA [size] of Global Pointer Directory
               0 [       0] RVA [size] of Thread Storage Directory
               0 [       0] RVA [size] of Load Configuration Directory
               0 [       0] RVA [size] of Bound Import Directory
               0 [       0] RVA [size] of Import Address Table Directory
               0 [       0] RVA [size] of Delay Import Directory
               0 [       0] RVA [size] of COM Descriptor Directory
               0 [       0] RVA [size] of Reserved Directory

  Looking at the headers, and comparing them to the output from a 'hello
world' C executable, one thing stood out:

             2B8 size of headers

  That's been 400 in every other program I've looked at.  It also meant
something to me, because I had tried experimentally attempting to relink the
larceny binary with the MS linker (link) just in case it could smooth out
something that was malformed, and it had mentioned 2B8 in the error message:

C:\>link larceny.bin /OUT:lar2.exe
Microsoft (R) Incremental Linker Version 8.00.50727.42
Copyright (C) Microsoft Corporation.  All rights reserved.

larceny.bin : fatal error LNK1107: invalid or corrupt file: cannot read at
0x2B8

C:\> 

  So, what's at offset 0x2B8 in the larceny binary?  It turns out to be:

SECTION HEADER #1
.comment name
      1F virtual size
FFC00000 virtual address (100000000 to 10000001E)
     208 size of raw data
     2B8 file pointer to raw data (000002B8 to 000004BF)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
       0 flags

RAW DATA #1
  100000000: 00 54 68 65 20 4E 65 74 77 69 64 65 20 41 73 73 .The Netwide Ass
  100000010: 65 6D 62 6C 65 72 20 30 2E 39 38 2E 33 39 00    embler 0.98.39.

... some kind of comment/id section left behind by nasm.  Ok, fair enough, but
why would that make the file invalid?  Well, look at the section table - this
dump's from objdump:

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .comment      0000001f  00000000  00000000  000002b8  2**2
                  CONTENTS, READONLY
  1 .text         000230c0  00401000  00401000  00000600  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .data         000047d0  00425000  00425000  00023800  2**4
                  CONTENTS, ALLOC, LOAD, DATA
  3 .rdata        00004470  0042a000  0042a000  00028000  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .bss          00002e30  0042f000  0042f000  00000000  2**4
                  ALLOC
  5 .idata        00000860  00432000  00432000  0002c600  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  6 .stab         00000d08  00433000  00433000  0002d000  2**2
                  CONTENTS, READONLY, DEBUGGING, EXCLUDE
  7 .stabstr      0000001b  00434000  00434000  0002de00  2**0
                  CONTENTS, READONLY, DEBUGGING, EXCLUDE

  You immediately see that it's the only section at an address that doesn't
end in zeros.  That made me think there might be some kind of problem with the
alignment, and then I looked at the header again and saw:

             200 file alignment

  So, the file is regarded as malformed by the loader because it contains a
section that isn't correctly aligned to the file alignment.  I don't know how
it got that way, but it's clearly inconsistent.  It might be that the section
was supposed to have EXCLUDE or some other flag that would have made the
loader not care, I don't know, but since it's just a comment section,
discarding it with objdump -R does the job nicely.

    cheers,
      DaveK
-- 
Can't think of a witty .sigline today....

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/