Wlink-ing for fun & … profit?

well rounding out the experiment is of course the hidden OS/2 2ine. And how does it respond to the various linkers?

Operating System/2 LX (Linear Executable) Linker
Version 2.00.000 Mar 20 1992
Copyright (C) IBM Corporation 1988-1991.
Copyright (C) Microsoft Corp. 1988-1991.
All rights reserved.

If you remember this is from the Limited Edition or Citrix Multiuser 2.0 version:

$ ./lx_loader /mnt/c/msos2/test/mt.exe
mmap((nil), 8192, RW-, ANON|PRIVATE|FIXED, -1, 0) failed (1): Operation not permitted
$

What about the OS/2 2.0 GA linker?

[<ohestwo>-C:\TEMP]\os2\link386 mt.obj

Operating System/2 Linear Executable Linker
Version 2.01.005 Mar 16 1993
Copyright (C) IBM Corporation 1988-1993.
Copyright (C) Microsoft Corp. 1988-1993.
 All rights reserved.

Run File [mt.exe]:
List File [nul.map]:
Libraries [.lib]:
Definitions File [nul.def]:
LINK386 :  warning L4071: application type not specified; assuming WINDOWCOMPAT

[<ohestwo>-C:\TEMP]mt
hi

[<ohestwo>-C:\TEMP]

and on 2ine?

$ ./lx_loader /mnt/c/msos2/test/mt.exe
not an OS/2 module
$

Well this all sucks. But how about a 3rd party linker? Watcom?!

C:\msos2\test>cl386 /c mt.c
Microsoft (R) Microsoft 386 C Compiler. Version 1.00.075
Copyright (c) Microsoft Corp 1984-1989. All rights reserved.

mt.c

C:\msos2\test>wlink d all SYS os2v2 op m op maxe=25 op q op symf @mt.lnk

C:\msos2\test>dir mt.exe
 Volume in drive C has no label.
 Volume Serial Number is 3C41-1D63

 Directory of C:\msos2\test

13/05/2021  01:48 am             5,160 mt.exe
               1 File(s)          5,160 bytes
               0 Dir(s)  646,855,708,672 bytes free

C:\msos2\test>

and on 2ine?

$ ./lx_loader /mnt/c/msos2/test/mt.exe
hi
$

Wow! How about OS/2 2.00 GA?

Sadly a no go.

Obviously this needs more testing on later versions of OS/2. I tried wlink from Watcom C/C++ 10.0 and it won’t run. Once more again the devil is in the linker, and just as last time, it turns out that the ‘portable’ tools are 16bit!

$ ./lx_dump /mnt/c/msos2/bin/orig/CL386.EXE
/mnt/c/msos2/bin/orig/CL386.EXE
NE (16-bit) executable.
Linker version: 5
Linker revision: 2
Entry table offset: 117
Entry table size: 2
CRC32: 0x30E8EA59
Module flags: MULTIPLEDATA
Application type: WINPMCOMPAT

I meant to post earlier but if you want to follow along, project dump is msos2-wlink.7z.

5 thoughts on “Wlink-ing for fun & … profit?

  1. I downloaded and built 2ine, and tested the various EXEs I linked with the various linker versions under the various OS/2 builds.

    I had no problems running the EXE generated by link386 2.01.005 from OS/2 2.0 FixPak 2, so I don’t know why you did. The error you got, though — “not an OS/2 module” — is what 2ine shows if you try to run an LE binary (or any other format it wouldn’t understand). Are you 100% positive you didn’t accidentally try to run the EXE you linked with 6.123?

    All of the other LX binaries from all of the other OS/2 versions also ran fine for me under 2ine, *except* for the one from Citrix / 6.177. It bombs out with the same mmap error yours did.

    If I use lx_dump to get details about each executable and then compare them, the only difference I see between the Citrix-generated one and the others is this (one generated by 2.0 GA is -, and one generated by Citrix is +):

    @@ -44,7 +44,7 @@
    Object table (2 entries):
    Object #1:
    Virtual size: 4106
    -Relocation base address: 0x10000
    +Relocation base address: 0x0
    Object flags: READ EXEC BIG
    Page table index: 1
    Number of page table entries: 2
    @@ -516,7 +516,7 @@

    Object #2:
    Virtual size: 8944
    -Relocation base address: 0x20000
    +Relocation base address: 0x10000
    Object flags: READ WRITE BIG
    Page table index: 3
    Number of page table entries: 1

    So reloc base address of the executable object code is 0 on the Citrix one.

    I did find these notes within the 2ine CMake file:

    # Note that this project doesn’t work on Mac OS X because I can’t mmap()
    # address 0x10000, which is the usual base address for OS/2 binaries.
    # It appears the address is already accessible when main() begins, but no
    # objects seem to be loaded there. I don’t know what it is…maybe some
    # thing allocated by the C runtime at startup? Have to solve that somehow or
    # give up on Mac support.

    So 0x10000 is the “usual” base address; hmm. I wonder if 2ine is making some assumptions that don’t always hold true.

    Now, it’s possible that this is a bug in Citrix’s linker, but the resulting binary runs fine on genuine OS/2 for me. It’s just 2ine that can’t handle it. So OS/2 seems capable of fixing that entry point up. Even more interesting is that the linker from 6.167 (October 1991 pre-release, first with LX and WPS, preceding 2.0 LA / 6.177 by 3 months) used base offset 0x10000 too, just like all the other linkers.

    So either it changed from 64k to 0 between 6.167 and 6.177, and then *back* to 64k after 6.177, *or* maybe for some reason Citrix specifically wanted their linker to behave differently in this regard. Probably worth installing genuine OS/2 2.0 LA instead of Citrix and seeing if its link386 behaves the same way! (I’m going to guess not, because Citrix linker is dated March 1992, which is even later than the linker that shipped with 2.0 GA. So Citrix 2.0 runs an older kernel than OS/2 2.0 GA, but not everything in Citrix 2.0 was taken from the older OS/2 2.0 LA.)

    It might also be interesting to look at any 32-bit executables that shipped with Citrix.

  2. yeah it gets a bit confusing.. hence the ‘wasteland’ more so of my attempt to find and categorize tools


    c050fa0c465988f34093e58713d0c2d4 Citrix_Multiuser_2\LINK386.EXE
    22/03/1992 01:34 pm 144,113 LINK386.EXE
    b67808642825b657494d0298376e7408 MSOS2.20\OLD-LINK\LINK386.EXE
    08/05/2021 09:58 am 123,008 LINK386.EXE
    2e3275c0079f8c86152743cfaee75685 MSOS2.20\SDK20\TOOLKT20\OS2BIN\LINK386.EXE
    30/05/1990 11:32 am 133,102 LINK386.EXE
    b67808642825b657494d0298376e7408 nt35-bh\LINK386.EXE
    02/03/1994 04:37 pm 123,008 LINK386.EXE
    be0188e56b0e243c7d6ca158558dd157 os2_2.00_v123\LINK386.EXE
    28/11/1990 09:23 pm 138,829 LINK386.EXE
    bd266c8b27e8cfe0e2b0d4956bc939cb OS2_DDK_1.2\LINK386.EXE
    21/02/1994 12:19 pm 151,395 LINK386.EXE
    3c7f7227c47e185c60a4df34a6b2213d OS2_DDK_2.0\LINK386.EXE
    10/04/1995 07:43 pm 154,052 LINK386.EXE
    b67808642825b657494d0298376e7408 Windows3.1DDK\link386.exe
    04/01/1992 02:52 pm 123,008 link386.exe

    I’m still looking for stuff, but it’s by no mean an exhaustive collection of linkers.

  3. Probably you could add the linker from EMX to that list. I not sure that will work but probably worth trying.

    • it does it’s own magic, but yeah there is the old binutils based one. I managed to get it running under 32bit Linux. I need to finish porting the a.out to OMF converter, so then GCC can use WLINK. I’m like half way there before trying to test, but it’s been interesting to go through all the LINK386 variations and see what works with what.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.