Article View: comp.os.os2.programmer
Article #282Re: .EXE format documentation.
From: David Charlap
Date: Thu, 06 Aug 1992 20:38
Date: Thu, 06 Aug 1992 20:38
428 lines
18468 bytes
18468 bytes
In article <1992Aug06.145422.24447@proto.com> joe@proto.com (Joe Huffman) writes:
>
>Does anyone know where I can get some documentation on the .EXE format
>used for OS/2 executables? It would be ideal if someone could just
>email an on-line document for me.
Following is a document I've run across explaining the New Exe format
(Segmented executables) that DOS 4.0+, OS/2, and Windows apps use. I
also have a file called newexe.h, but this header is labeled
"Copyright 1984-1987 Microsoft", so I don't dare distribute it.
Microsoft Segmented Executable Format
-------------------------------------
5/05/87
This document defines the Segmented Executable format, which is a
superset of the MS-DOS 2.x and 3.x .EXE format (hereafter called DOS
3.x). The purpose of the segmented-executable format is to provide
the information needed to support the dynamic linking and segmentation
capabilities provided by OS/2, MS-DOS 4.0, and MS Windows. Also,
information needed for protected mode is provided.
The DOS 3.x .EXE format has been extended as follows:
- The word at offset 18h in the existing .EXE file contains the
relative byte offset to the relocation table. If this offset
is 40h, then the double word at offset 3Ch is assumed to be
the relative byte offset from the beginning of the file to the
beginning of the new format executable header. A new format
.EXE file is identified if the new executable header contains
a valid signature. If the signature is not valid the file is
assumed to be an old format .EXE file. The remainder of the
old format header will describe a DOS 3.x program, the stub. The
stub may be any valid program but will typically be a program
which displays an error message, emulates the new-format program,
or brings in a loader that can handle the job.
See the picture below for the actual file layout.
- This format will only be used for .EXE files that use the new
memory model supported by OS/2, MS-DOS 4.0 and MS Windows.
Old .EXE files will continue with the DOS 3.x file format.
Note
====
Throughout this specification, all unused fields and flag bits are
reserved for future use and are expected to contain 0.
The new .EXE file has the following format:
00h -------------------
| |
| Old EXE Header |
| |
20h -------------------
| reserved |
-------------------
| |
3Ch | offset to new | ---+
| EXE header | |
40h ------------------- |
| DOS 3.x Stub | |
| Program & | |
| Reloc. Table | |
------------------- |
| | |
xxh ------------------- <---
| |
| New EXE Header |
| |
-------------------
| |
| Segment Table |
| |
-------------------
| Resource |
| Table |
-------------------
| Resident |
| Name |
| Table |
-------------------
| Module Ref |
| Table |
-------------------
| Imported |
| Names |
| Table |
-------------------
| Entry |
| Table |
-------------------
| Non-Resident |
| Name |
| Table |
-------------------
| Seg #1 Data |
| Seg #1 Info |
-------------------
.
.
.
-------------------
| Seg #n Data |
| Seg #n Info |
-------------------
| Debug |
| Information |
-------------------
New Executable Header
=====================
00h DW signature word
"N" is low order byte
"E" is high order byte
02h DB version#
03h DB revision#
04h DW Entry Table file offset relative to beginning of new
EXE header
06h DW #bytes in Entry Table
08h DD 32-bit checksum of entire contents of file
(with these words taken as 00 during the calculation)
0Ch DW flag word
0000h = NOAUTODATA
0001h = Shared automatic data segment (SINGLEDATA)
0002h = Instance automatic data segment (MULTIPLEDATA)
0004h = Per-process library initialization (INITINSTANCE)
0008h = Runs in protected mode only (PROTMODE)
0008h = runs in protected mode only
0010h = 8086 instructions present
0020h = 286 instructions present
0080h = floating point instructions present
2000h = errors detected at link time
8000h = Library module (SS:SP info is invalid, CS:IP
points to initialization procedure that is
called with AX = the module handle. The
procedure must execute a far return to the
caller, with AX != 0 to indicate success and
AX = 0 to indicate failure to initialize. DS =
the library's data segment if the SINGLEDATA
flag is set and the caller's DS otherwise.)
A program can only contain dynamic links to
executables that have this flag set.
0Eh DW segment# of automatic data segment (index into segment
table)
set to zero if SINGLEDATA and MULTIPLEDATA flag bits are
reset
10h DW initial size of dynamic heap added to data segment in
bytes (0 if no local alloc)
12h DW initial size of stack added to data segment in bytes
(0 if SS!=DS)
14h DD segment#:offset of CS:IP
18h DD segment#:offset of SS:SP
Segment# is an index into the module's segment table.
The first entry in the segment table is segment number 1.
If SS = automatic data segment and SP = 0,
the stack pointer is set to the top of the automatic
data segment just below the additional heap area.
+-------------------------+
| additional dynamic heap |
+-------------------------+ <- SP
| additional stack |
+-------------------------+
| loaded data segment |
+-------------------------+ <- DS, SS
1Ch DW #of entries in Segment Table
1Eh DW #of entries in Module Ref Table
20h DW #bytes in Non-Resident Name Table
22h DW Segment Table file offset relative to beginning of new EXE
header
24h DW Resource Table file offset relative to beginning of new
EXE header
26h DW Resident Name Table file offset relative to beginning of
new EXE header
28h DW Module Ref Table file offset relative to beginning of new
EXE header
2Ah DW Imported Names Table file offset relative to beginning of
new EXE header
2Ch DD Non-Resident Name Table offset relative to beginning of
file
30h DW #of movable entries in Entry Table
32h DW logical sector alignment shift count, log(base 2) of
segment sector size (default 9)
34h DW #of resource entries
36h -
3Eh DW reserved, currently 0's
Segment Table
=============
"N" segment table entries:
The first entry in the segment table is segment number 1.
DW n-byte logical sector offset to contents of the segment
data relative to beginning of file (zero means no file
data)
DW length of segment in file, in bytes (zero means 64K)
DW flag word
0007h = TYPE_MASK ; segment type field
0000h = CODE ; code segment type
0001h = DATA ; data segment type
0008h = ITERATED ; segment data is iterated
0010h = MOVABLE ; segment is movable (OS/2 ignores)
0020h = SHARED ; segment can be shared
0040h = PRELOAD ; segment is preloaded
0080h = ERONLY ; execute only if code segment
; read only if data segment
0100h = RELOCINFO ; set if segment has reloc records
0200h = CONFORM ; segment is conforming
0C00h = SEGDPL ; I/O privilege level
1000h = DISCARD ; discardable segment (OS/2
; ignores)
4000h = HUGE ; huge segment: length of segment
; and minimum allocation sizes are
; in units of segment sector size
DW minimum allocation size in bytes
Total size of the segment 0 means 64K
Resource Table
==============
DW alignment shift count for resource data
"N" iterations of record:
| DW type ID - integer type if high order bit is set (8000h)
| otherwise offset to type string, relative to
| beginning of the resource table
| = 0 marks end of resource records
|
| DW #resources for this type
| DD Reserved
| |
| | "#resources" copies of Resource Entry (8 bytes)
| |
| | DW file offset to contents of the resource data relative
| | to beginning of file. Offset is in terms of alignment
| | units specified at beginning of resource table.
| | DW length of resource in file (bytes)
| | DW flag word
| | 0010h = MOVEABLE ; resource is not fixed
| | 0020h = PURE ; resource can be shared
| | 0040h = PRELOAD ; resource is not demand loaded
| | DW resource ID - integer type if high order bit is set
| | (8000h) otherwise offset to resource string, relative
| | to beginning
| | DD Reserved
\ \ of the resource table
Resource type and name strings stored at end of resource table
Note that these strings are NOT null terminated
DB length of type or name ; = 0 if end of resource
; table
DB ASCII text of type or name ; Case sensitive
Resident or Non-resident Name Table Entry (3 + n bytes)
=========================================
The strings are CASE SENSITIVE and NOT NULL TERMINATED
DB Length of string ; =0 if no more strings in table
DB ASCII text of string
DW ordinal# (index into entry table)
First string in resident name table is the module name.
First string in non-resident name table is the module description.
Module Reference Table
======================
"N" entries of the form: (1-based)
DW offset within Imported Names Table to module name string
Imported Names Table (1 + n bytes)
====================
The strings are CASE SENSITIVE and NOT NULL TERMINATED
DB 0 ; to ensure non-zero first entry
; offset
"N" entries of the form:
DB Length of name
DB ASCII text of name
Entry Table (1 based)
===========
"N" bundles of entry definitions. The ordinal value of an entry
| point is its ordinal within the entry table, counting the
| first entry as ordinal #1. The loader must scan over the
| bundles until it finds the bundle containing the entry point;
| the loader can then multiply by entry size to index the
| proper entry.
|
| The linker forms bundles in the densest manner it can, given
| the restriction that it cannot reorder entry points to improve
| bundling because other EXE files may refer to entry points
| within this one by their ordinal in this table.
|
| DB #entries in this bundle. All records in one bundle are
| either movable or refer to the same fixed segment.
| Equal to 0 if no more bundles in Entry Table.
|
| DB segment indicator for this bundle
| | 00h - Unused, bundle not present, next bundle count
| | follows
| | FFh - Movable segment, # is in entry
| | otherwise is segment # of fixed segment
| |
| | If fixed segment, entries are 3 bytes:
| | DB flags
| | 01h = set if entry is exported
| | 02h = set if entry uses global (shared) data
| | segment
| | "mov ax,#ds-value" must be the 1st
| | instruction in the prolog of this
| | entry. This flag may only be set
| | for SINGLEDATA library modules.
| | F8h = # of parameter words
| | DW offset
| | Else movable segment, entries are 6 bytes:
| | DB flags
| | 01h = set if entry is exported
| | 02h = set if entry uses global (shared) data
| | segment
| | F8h = # of parameter words
| | int 3Fh
| | DB segment#
\ \ DW offset
Per segment data:
================
If ITERATED
DW #iterations
DW #bytes of data
DB data bytes
else
DB data bytes
If RELOCINFO
DW #relocation items
|
| Relocation Item: (8 bytes)
|
| DB source type
| 0Fh = SOURCE_MASK
| 00h = LOBYTE
| 02h = SEGMENT
| 03h = FAR_ADDR (32-bit pointer)
| 05h = OFFSET (16-bit offset)
|
| DB flags
| 03h = TARGET_MASK
| 00h = INTERNALREF
| 01h = IMPORTORDINAL
| 02h = IMPORTNAME
| 03h = OSFIXUP
| 04h = ADDITIVE
|
| DW offset within this segment of source chain
| If ADDITIVE flag set, then add target value to source
| contents, instead of replacing source and following the
| chain.
| The source chain is a FFFFh terminated linked list within
| this segment of all references to the target.
|
| Target
| INTERNALREF
| DB segment# for fixed segment or FFh if movable
| DB 0
| DW offset into segment if fixed
| index into Entry Table iff movable
|
| IMPORTNAME
| DW index into module ref table
| DW offset within Imported Names Table to proc. name
| string
|
| IMPORTORDINAL
| DW index into module ref table
| DW procedure ordinal#
|
| OSFIXUP
| DW Operating system fixup type
| Floating-point fixups
| 0001h = FIARQQ, FJARQQ
| 0002h = FISRQQ, FJSRQQ
| 0003h = FICRQQ, FJCRQQ
| 0004h = FIERQQ
| 0005h = FIDRQQ
| 0006h = FIWRQQ
\ DW 0
Debug Information
=================
Any debug information will be at the end of the executable.
No information about it will appear in the header, so executable
files may be longer than the file length indicated in the
header.
--
|) David Charlap "I don't even represent myself
/|_ dic5340@hertz.njit.edu sometimes so NJIT is right out!.
((|,)
~|~ Hi! I am a .signature virus, copy me into your .signature file.
Technical Details
Message-ID:
<1992Aug6.203836.27777@njitgw.njit.edu>Path:
arc1-ca.pugleaf.net!sparky!uunet!stanford.edu!rutgers!njitgw.njit.edu!hertz.njit.edu!dic5340References:
<1992Aug06.145422.24447@proto.com>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!sparky!uunet!stanford.edu!rutgers!njitgw.njit.edu!hertz.njit.edu!dic5340 From: dic5340@hertz.njit.edu (David Charlap) Newsgroups: comp.os.os2.programmer Subject: Re: .EXE format documentation. Keywords: .EXE format Message-ID: <1992Aug6.203836.27777@njitgw.njit.edu> Date: 6 Aug 92 20:38:36 GMT References: <1992Aug06.145422.24447@proto.com> Sender: news@njit.edu Distribution: comp Organization: New Jersey Institute of Technology, Newark, N.J. Lines: 428 Nntp-Posting-Host: hertz.njit.edu