windows-nt/Source/XPSP1/NT/base/mvdm/wow16/kernel31/newexe.doc

392 lines
17 KiB
Plaintext
Raw Normal View History

2020-09-26 03:20:57 -05:00
New Executable Format
DOS 2.0 Windows will define a new executable format for .EXE files
that is a superset of the current DOS 2.0 .EXE format. The purpose
of this new format is to provide the additional information needed
to support the new dynamic linking and segmentation facilities provided
by DOS 2.0 Windows and DOS 4.0. In order for Windows and DOS 4.0
to recognize the new executable format, the existing .EXE format
will be used with a slight modification:
- 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 that identifies this as a new format .EXE file and
The word at offset 24h is the relative byte offset from the
beginning of the file to the beginning of the new format
executable header. The remainder of the old format header will
describe a small program that will either print an error message
or bring 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 DOS 2.0 Windows and DOS 4.0. Old .EXE
files will continue with the DOS 2.0 file format, as modified
by the DOS 4.0 group. In that format, the DOS 4.0 behavior bits
(2 bytes) are stored at offset 20h.
The format of the new .EXE file format looks like:
00h -------------------
| |
| Old EXE Header |
| |
-------------------
20h | DOS 4.0 bbits |
22h | unused bbits |
3eh | offset to new | ----
| EXE header | |
40h ------------------- |
| DOS 2.0 Stub | |
| Program & | |
| Reloc. Table | |
xxh ------------------- <---
| |
| New EXE Header |\
| | \
------------------- \
| | |
| Segment Table | |
| | |
------------------- |
| Resource | | DOS4 and Windows keep this
| Table | |-----------part as part of their
------------------- | MODULE table, currently
| 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 |
-------------------
20h - DW DOS 4.0 behavior bits
* 22h - 3ch - reserved for more behavior info
* 3eh - DW offset to new executable header
Program that DOS 2.0 header points to, that will either print out an
error message or load in a new-EXE loader.
xxh - Beginning of new executable header
DW signature word - can never be too careful
"N" is low order byte
"E" is high order byte
DB version# of LINK that produced this executable
DB revision# of LINK that produced this executable
DW Entry Table file offset relative to beginning of new EXE header
DW #bytes in Entry Table
DD CRC-32 of entire contents of file (with these words taken
as 00 during the calculation)
DW flag word
0000h = NOAUTODATA
0001h = SINGLEDATA (SOLO)
0002h = MULTIPLEDATA (INSTANCE)
0004h = runs in real mode
0008h = runs in protected mode (if 0Ch set, runs in either)
4000h = non-conforming program (a valid stack is not maintained)
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. If this flag
is set, the MULTIPLEDATA flag must be reset. The
SINGLEDATA flag may be set or reset.
DW segment# of automatic data segment (index into segment table)
set to zero if SINGLEDATA and MULTIPLEDATA flag bits are reset
DW initial size (bytes) of dynamic heap added to data segment
(0 if no local alloc)
DW initial size (bytes) of stack added to data segment
(0 if SS!=DS)
DD segment#:offset of CS:IP
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
DW #of entries in Segment Table
DW #of entries in Module Ref Table
DW #bytes in Non-Resident Name Table
DW Segment Table file offset relative to beginning of new EXE header
DW Resource Table file offset relative to beginning of new EXE header
DW Resident Name Table file offset relative to beginning of new EXE header
DW Module Ref Table file offset relative to beginning of new EXE header
DW Imported Names Table file offset relative to beginning of new EXE header
DD Non-Resident Name Table offset relative to beginning of file
* DW #moveable entry points
* DW alignment shift count for segment data. Value of zero means
* use the default value of 9 for 512 byte alignment.
* DB 12 DUP (?) - room for growth here
Segment Table
=============
"N" segment table entries:
The first entry in the segment table is segment number 1.
* DW logical sector offset to contents of the segment data
* relative to beginning of file (zero means no file data)
* The alignment field in the header determines the units
* of this offset.
DW length of segment in file (bytes) (zero means 64k bytes)
DW flag word
TYPE_MASK = 0007h ; segment type field
CODE = 0000h ; code segment type
DATA = 0001h ; data segment type
ITERATED = 0008h ; segment data is iterated
MOVABLE = 0010h ; segment is not fixed
PURE = 0020h ; segment can be shared
PRELOAD = 0040h ; segment is not demand loaded
ERONLY = 0080h ; execute only if code segment
; read only if data segment
RELOCINFO = 0100h ; set if segment has reloc records
DEBUGINFO = 0200h ; set if segment has debug info
SEGDPL = 0C00h ; reserved for 286 DPL bits
DISCARDABLE = F000h ; static discard priority level
DW minimum allocation size (bytes)
Total size of the segment (0 means 65536)
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 for runtime use
| |
| | "#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
| | MOVEABLE = 0010h ; resource is not fixed
| | PURE = 0020h ; resource can be shared
| | PRELOAD = 0040h ; 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
| | of the resource table
| | DD reserved for runtime use
\ \
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
Module Reference Table
======================
"N" entries of the form: (1-based)
DW offset within Imported Names Table to module name string
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 movabe or refer to the same fixed segment.
| =0 if no more bundles in Entry Table
|
| DB segment indicator for this bundle
| | 000 - Unused
| | 0FF - Movable segment, # is in entry
| | otherwise is segment # of fixed segment
| |
| | If fixed segment, entries are 3 bytes:
| | DB flags
| | 0000 0001 - set if entry is exported
| | 0000 0010 - 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.
| | nnnn n--- - # of parameter words
| | DW offset
| | Else movable segment, entries are 6 bytes:
| | DB flags
| | 0000 0001 - set if entry is exported
| | 0000 0010 - set if segment uses global (shared) data segment
| | nnnn n--- - # of parameter words
| | int 3Fh
| | DB segment#
\ \ DW offset
Resident or Non-resident Name Table Entry (3 + n bytes)
=========================================
The strings are CASE SENSITIVE and NOT NULL TERMINATED. If the
* .EXE was produced with the /IGNORECASE switch, then all strings
* will be UPPERCASE
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.
Imported Names Table Entry (1 + n bytes)
==========================
The strings are CASE SENSITIVE and NOT NULL TERMINATED. If the
* .EXE was produced with the /IGNORECASE switch, then all strings
* will be UPPERCASE
DB Length of name ; =0 if no more strings in Table
DB ASCII text of name
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 (32 bit address, 16 bit segment, 16 bit offset)
| NRSTYP = 07h ; source type mask
| NRSBYTE = 00h
| NRSSEG = 02h ; 16-bit segment
| NRSPTR = 03h ; 32-bit pointer
| NRSOFF = 05h ; 16-bit offset
| DB flags
| TARGET_MASK = 03h
| INTERNALREF = 00h
| IMPORTORDINAL = 01h
| IMPORTNAME = 02h
| ADDITIVE = 04h
| 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 0xFFFF terminated linked list within
| this segment of all references to the target.
| Target
| INTERNALREF
| DB segment# for fixed segment or FF if movable
| DB 0
| DW if moveable segment
* | ordinal# (index into entry table of this module)
| if fixed segment
| offset into segment if fixed
|
| 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
| applied by adding the fixup to the coprocessor instr.
| for 1-3, apply the first fixup at the offset, and
| the second fixup at the offset+1. for 4-6, just add
| the fixup at the offset.
|
| NOTE: the linker marks these relocations as NRSOFF, but
| they must be applied differently. in ldreloc.asm, we
| use a flag to discern this case.
|
\ DW 0
If DEBUGINFO
DW # of bytes of debug info
<debug info - not yet defined>
NOTE: this document does not totally agree with version 1.7, dated 5/05/87.