.SYM Format

Microsoft introduced a new symbol format (.SYM) for their Symbolic Debug Utility. A .SYM file is basically the binary representation of a .MAP file generated by the 8086 Object Linker.

Basic Information
A .SYM file can be split into 3 sections, the header, the main body area (segments) and the version field.

The header contains information such as the file length, the segment with program entry point, the size of itself, the number of pre-segment 1 names, the address of the next segment and the module name.

The body contains the most important information - symbols and their addresses. The body consists of different segments, like the executable file and each segment can be broken into 3 pieces - segment header, symbols and something else that appears to be unused. The segment header contains information such as the address of the next segment, the number of symbols in the current segment, the length of this segment, the segment number and its name. The actual symbols comes after the segment header. Finally the segment ends with something unknown, presumably generated by MapSym based on the symbols.

The version field contains the MapSym version.

Different .SYM Versions
This document focuses on .SYM version 2.08 - 3.10 generated by MapSym 2.08 - 3.10. There are 2 main variations of the .SYM format used throughout the development of Windows 1.0 - the old format (2.08 - 3.00) and the new format (3.10). There is only one major difference between the 2 formats - the new format uses paragraphs instead of bytes, so everything must be padded to the nearest paragraph. By using paragraphs instead of bytes, in theory the new format can store 16 times more information than the old format.

.SYM to .MAP
It is possible to convert a .SYM file to a working .MAP that gives an identical .SYM file if converted again with MapSym. Since the process of .MAP to .SYM is not lossless, it is impossible to obtain the original .MAP file given a .SYM file. Segment class and program entry point information are discarded during the initial .MAP to .SYM conversion process thus they cannot be recovered by normal means. For Windows applications (not drivers or dynamic-link libraries), the entry point must be the address of the winstart function.

Documentation
Symbol format │ ├───Header │  ├───File header │  │       dword       symLength               Length of .SYM excluding itself (old format - in bytes, new format - in paragraphs) │  │       word        entrySeg                Segment with program entry point │  │       word        numInHeader             Number of names before the first segment (0000:xxxx) │  │       word        headSize                Size of header (header + segment zero) │  │       word        numSeg                  Number of segments (no segment zero) │  │       word        segOne                  Segment one address (old format - in bytes, new format - in paragraphs) │  │       byte        unknown │  │       byte        modNameLen              Module name length │  │       bytes       modName                 Module name │  │ │   ├───Segment zero (Imps and Abs) │  │       word        addr                    Address of function/variable in executable │  │       byte        nameLen                 Length of function/variable name │  │       bytes       name                    Function/variable name │  │                           --> Next function/variable │  │ │   └───Padding │          bytes       headerPad               Pad to nearest paragraph with zeros (no padding in old format) │ ├───Segments │  ├───Segment header │  │       word        nextSeg                 Next segment address in .SYM (old format - in bytes, new format - in paragraphs) │  │       word        numName                 Number of function/variable names │  │       word        segLen                  Length of segment in .SYM (old format - relative to beginning of file) │  │       word        segNum                  Segment number (origin) │  │       bytes       10 DUP(0)               10 bytes of empty space │  │       byte        0                       0 │  │       byte        0FFh                    255 │  │       byte        segNameLen              Length of segment name │  │       bytes       segName                 Segment name │  │ │   ├───Names │  │       word        addr                    Address of function/variable in executable │  │       byte        nameLen                 Length of function/variable name │  │       bytes       name                    Function/variable name │  │                           --> Next function/variable │  │ │   ├───Unknown │  │       word        unknown │  │                           --> Next function/variable │  │ │   └───Padding │          bytes       segPad                  Pad to nearest paragraph with zeros if not last segment (no padding in old format) │ └───Version └───MapSym version word       symVer                  Version of MapSym used to create the .SYM file