Adding BLDLEVEL information to executables

Written by Roman Stangl, Prokushev

What is BLDLEVEL
The BLDLEVEL (Build Level) is a signature that OS/2 modules (*.EXE and *.DLL files) contain, which allows one to easily identify the version and/or build date of that modules. OS/2 ships with a command line utility named BLDLEVEL which allows you to display such signatures. For example, the output when invoking the command BLDLEVEL \os2krnl against the kernel of a OS/2 Warp 4 installation [C:\]BLDLEVEL \os2krnl Signature:  @#IBM:9.23#@  IBM OS/2 Kernel Vendor:     IBM Revision:   9.23 Description: IBM OS/2 Kernel Figure 1.a

The following REXX batch job, showing how you can add a Build Level to your own products, was taken from my Program Commander/2 (PC/2) program, which is available from my homepage and it's Freeware!

Format of the BLDLEVEL string (Type I)
The version information displayed by bldlevel.exe is actually just the description string from the .DEF file of the module. In order to work, the string must have the following format: @#:#@ where  is up to two digits major version number, a dot and exactly 3 digits minor version. If the minor version is stated with less than 3 digits, the result is not as expected.

Simple example (in DEF file syntax): DESCRIPTION '@#Mimikri Software:1.110#@Yeah - Yet Another Editor' yields the following result: Build Level Display Facility Version 6.12.675 Sep 25 2001 (C) Copyright IBM Corporation 1993-2001 Signature:      @#Mimikri Software:1.110#@Yeah - Yet Another Editor Vendor:         Mimikri Software Revision:       1.110 File Version:   1.110 Description:    Yeah - Yet Another Editor The difference between "Revision" and "File Version" is beyond my knowledge...

Format of BLDLEVEL string (Type II)
MPTN and TCP/IP services of OS/2 use extended build level information. In most cases such information is not stored as description, but as asciiz constant string in code. This is why standard OS/2 bldlevel tool does not work for such files. Syntax is following: @#:#@##built  -- on ; 0.1@@[:[:...] where: Example: Description '@#osFree:9.23#@##build 5 Oct 2003 15:00:00 -- on RACERPC; 0.1@@Command line tools:Control utility for ANSI'
 *  is date and time of build
 *  is machine on which build compiled
 *  is closer desctiption of software pack

Format of BLDLEVEL string (Type III)
Another most known, and most complex, type of build level information is following: @#<Vendor>:<Revision>#@##1## DD.MM.YY hh:mm:ss <BuildHost>:<ASDFeatureID>:<LanguageCode>:<CountryCode>:<Build>:<Unknown>: <FixPackVer>@@<Description> where:
 * DD.MM.YY is the build date in day/month/year, preceded by 1 space
 * hh:mm:ss is the build time in hour/minute/second, preceded by 1 space
 * <BuildHost> is machine on which build compiled, preceded by 8 spaces
 * <ASDFeatureID> is identifier of ASD feature
 * <LanguageCode> is code of language of component
 * <CountryCode> is country code of component
 * <Build> is build number
 * <Unknown> is not known information (must be empty)
 * <FixPackVer> is FixPack version (if distributed as part of).
 * Note:If you leave build date and/or build time empty you still have to provide the same amount of spaces to replace build date/build time.

Example: Description '@#osFree:9.23#@1##RACERPC:0:866:7:436::WRR8706@@Control utility for ANSI' Nowadays many projects use this BLDLEVEL format string.

Changes to a header file
In order to support the inclusion of the Build Level into your products, just add the following macros to any header file, as for example shown bellow for my PC/2 program. Just replace the macro's value with the data you want to be included into the signature. /* PC/2 BLDLEVEL information (in C source modules added via macro   concatenation) for BuildLevel.cmd to generate BLDLEVEL information */ Figure 2.1.a
 * 1) define BLDLEVEL_VENDOR        "(C) Roman Stangl (rstangl@vnet.ibm.com)"
 * 2) define BLDLEVEL_VERSION       "V1.99r (05,1997)"
 * 3) define BLDLEVEL_INFO          "PC/2 - Program Commander/2"

When running the command BLDLEVEL executable</tt> where executable is any DLL or EXE of my PC/2 product, output similar to previous output will be displayed. Signature:  @#(C) Roman Stangl (rstangl@vnet.ibm.com):V1.99r (05,1997) (PC2.exe )#@PC/2 - Program Commander/2 Vendor:     (C) Roman Stangl (rstangl@vnet.ibm.com) Revision:   V1.99r (05,1997) (PC2.exe) Description: PC/2 - Program Commander/2 Figure 2.1.b - NOTE: the first line should be unbroken

The executable BuildLevel.cmd
Listing shows the REXX batch job BuildLevel.cmd which will modify your module definition files to add the Build Level signature created from the name of the module and the data read from the macros in the header file.

Either save this document as ASCII text, or get BuildLevel.cmd from PC/2 via my homepage.

The batch file is sufficiently commented, so it shouldn't be that difficult to see what it does.

Changes in the Makefile
Figure 2.3.a shows how to add a step while linking an executable to include Build Level information into that executable. For DLLs the step is completely equivalent, add the same parameters are passed to BuildLevel.cmd, that is the module definition file and the header file containing the macros. The differences between an EXE and DLL are inside the module definition file, not the step to add Build Level signatures. BLDLEVEL = BuildLevel PC2.exe: $(ALL_OBJ) $(SRC)\PC2.def $(SRC)\PC2.l $(SRC)\PC2.res $(BLDLEVEL) $(SRC)\PC2.def $(SRC)\PC2.h    $(LINK) @Source\PC2.l     rc $(SRC)\PC2.res PC2.exe Figure 2.3.a

When running BuildLevel.cmd against a module definition file, the Description statement will be modified according to the information in the header file. Additionally, the module type will be added (module definition files for executables must only contain a NAME statement, whereas for dynamic link libraries only a LIBRARY statement may be included, however the correct one must be present). Figure 2.3.b shows what a module definition file looks like after BuildLevel.cmd has been invoked against it, only the Description statement should have been touched, containing the signature in a form readable by the BLDLEVEL utility. NAME       PC2     WINDOWAPI NEWFILES Description '$@#(C) Roman Stangl (rstangl@vnet.ibm.com):V1.99r (05,1997) (PC2.exe)#@PC/2 - Program Commander/2' DATA       MULTIPLE STACKSIZE  96000 HEAPSIZE   128000 PROTMODE Figure 2.3.b - NOTE: the fourth line should be unbroken

Known limitations
As the BLDLEVEL utility does not scan the complete file when looking for a signature but just near at the end of the file, it is possible that it doesn't find a signature even if you have added one for sure. The reason most likely is that you have created modules that contain debug information. As the debug information (at least partly) seems to be added to the module after the signature, the signature is too far away from the end of the file for BLDLEVEL to find it. Once you create modules without debugging information, BLDLEVEL should be able to find the signature again.

Credits
From the DDK (Device Driver Kit) I found out that the BLDLEVEL signature can be added via the module definition files (*.DEF files), developing the REXX batch job was no problem afterwards.