GoLink Linker Manual
A "Go" development tool: http://www.GoDevTool.com
Version 0.26.10 by Jeremy Gordon -
Why a new linker?
GoLink's features in a nutshell
Using GoLink
Importing and Exporting functions and data
Legal stuff
Acknowledgements

Why a new linker?top

GoLink's features in a nutshelltop

Using GoLinktop

You can link a file very simply from an MS-DOS (command prompt) window for example:-
GoLink MyFile.obj
will create MyFile.exe.

Command files

In practice you will need to give GoLink a lot more information about input files and also using the command line switches. For convenience these can be in one or more command files named in the command line for example:-
GoLink @command.fil             ;example with one command file
GoLink @hello @goodbye.def      ;example with two command files
A command file must be a text only file containing one or more lines of instruction. It may be in ANSI, Unicode UTF-8BOM (Windows UTF-8) or Unicode UTF-16LE format. You can include comments in a command file because anything after a semi-colon on a line is ignored. You can therefore comment-out lines which temporarily you don't need. For example:-
MyProg.obj            ;link this file to make MyProg.exe
;/debug coff           ;use this line to add embedded debug information 
MyProg.res            ;use this file for resource input

Input files - object and res files

Since the main task of the linker is to link together object files, the main input files are files with the extension obj. Just list these in any order. A res file (containing resources) can also be specified as an input file.
Note that unless the /fo switch is used, the executable will take the name of the first named object or res file.
If the file is not in the current directory you must include its path.

Input files - dll/ocx/exe/drv files

Another type of input file is one containing exports, such as a DLL. Exports may be in DLL, OCX, DRV or other EXE files and you can provide the names of these in the command line or in a command file, or in your source code by using the directive #dynamiclinkfile if you are using GoAsm (see the GoAsm help file how to do this). Unlike other linkers there is no need to use LIB files. During the linking process GoLink looks at the list of files one by one for the required imports. When it has found all the required imports it will stop looking at the listed files. Because of this, GoLink will run more quickly if you list these files in order of popularity, by putting at the top of the list those which contains most of the required imports. Usually this order for the system DLLs is a good one:-
these contain most of the APIs you will be using:-
Kernel32.dll
User32.dll
Gdi32.dll
these are for the common controls and common dialog APIs:-
COMCTL32.dll
comdlg32.dll
you may also need to use these:-
OLEAUT32.dll
Hhctrl.ocx
winspool.drv
shell32.dll
There are of course several other system DLLs. You can find out which DLL holds the API you want to use by looking in the documentation for the API in the Windows Software Development Kit (SDK), available free from Microsoft see my web site for a link.

You can see how many imports from your program are coming from each DLL by using the /files switch in the command line or a command file.

32-bit and 64-bit input files

GoLink automatically senses whether it is being given 32-bit or 64-bit input files and produces a 32-bit or 64-bit executable accordingly. No command line switching is needed. Because you cannot mix 32-bit and 64-bit code, GoLink will show an error if you try to mix these input files.
Unless you have switched off command line reports using the /ni or /no switch GoLink will tell you in which format it has produced the executable.
Search order
You don't need to give a path for the dll/ocx/exe/drv file, because GoLink searches for the file using this search order:-
1. the directory from which GoLink was started
2. if different, the current directory
3. the windows system directory
4. the windows directory
5. directories listed in the PATH environment variable.
You will normally not need to use specific versions of these files, but if you do want to do this make sure you give the path to the specific file, or place the file in the directory from which GoLink was started.

You can see the path of the file used and also its creation date and time and its size by using the /files switch in the command line or a command file. Note that dates and times are adjusted to allow for the current daylight saving time setting on the computer running GoLink.

Screen output - controlling, limiting and redirecting

GoLink's default message output to the console is to give a copyright notice and report the output files. This is just a few lines, but if there are errors or if you use the /files switch or the /unused switch the output can be much larger.
You can control the message output by using various switches, eg. whether there is any output at all and what sort of output messages are given. You may need to do this if you use make files. See n switches for details.
If you run GoLink from an MS-DOS (command prompt) window, then you can use the /more switch. This will cause a screenful of messages to be shown at a time, and you will be prompted to press a key after each screenful. If you don't press a key (or give mouse input) there is a time-out of 60 seconds.
You can redirect the message output using the DOS redirection indicator:-
GoLink @command.fil > filename
The format of the file created by GoLink may differ. The rules are:- You should use the /more switch rather than using the DOS "more" filter.

The command line switches you can use are as follows:-
/b = beep on error
/base xxxx = set image base (use hex) eg. /base 50000 sets the expected image base to 50000h.
This sets where, in virtual memory, you would like the executable to be loaded (the image base). If you do not set this value GoLink uses a default of 400000h for EXEs, 10000000h for DLLs and 10000h for drivers. You will not normally need to set this value when making an EXE because each loaded EXE has its own virtual memory. This means that at any one time a number of programs can be running, all with the same image base, and there will be no conflict between them. But if the EXE relies on DLLs the Windows loader will also load these DLLs into the virtual memory of the EXE. Inside the DLL, GoLink will have written certain addresses on the assumption that the DLL would be loaded at the expected base address. If the DLL cannot be loaded at that expected base address (because it is occupied by another DLL) the loader will have to load it at another address. If that happens, the loader will need to write over the addresses inserted by GoLink. These addresses which require changing are called base relocations. Clearly this process takes time during loading and you can help to speed up the loading process by specifying your own base address for your DLLs. This will ensure that the DLL will actually be loaded at the expected base address. I would suggest using the area 10000000h to 60000000h (the system itself tends to use the area outside these values). Ensure your value is rounded up to a 64K boundary. You can use GoBug (inspect/search promenade memory/promenade) to check where the operating system is loading your DLLs. It is interesting to note that the System DLLs themselves use this staggered base address system. Usually this is in the memory area of 80000000h and above.
GoLink inserts base relocation information in the executable only if you use the /base xxxx switch, or if you are making a DLL or a driver.
/console = make a console executable.
This sets a flag in the executable telling the Windows loader that the executable will not rely on the Windows GUI (Graphic User Interface). In practice this means that the executable will not be given a message queue and that it will not require memory to be set aside for creating windows and the resulting device contexts. On the other hand the executable will be automatically provided with a "console" by the loader, allowing input from and output to the various devices connected to the computer. Because of the lower overhead, console applications tend to load and exit more quickly than graphics applications.
/debug coff = add embedded coff debug information to the final executable.
GoLink's debug output is tailored to what is required by assembler programmers. Basically every symbol known to the linker is put in the debug information together with its value. This can then be used to bring the program to life under debug control, using GoBug or other debuggers which accept coff debug information.
/debug dbg = place coff debug information in a dbg file.
If this switch is used, GoLink places the coff debug information in a file in .dbg format in an "exe" or "dll" sub-folder depending on what type of executable is being made. The sub-folder is used to ensure that there is no mix-up between the main EXE and its DLLs. So for example MyProg.exe will have its debug information placed in exe\MyProg.dbg and MyProg.dll will have its debug information placed in dll\MyProg.dbg.
/dll = make a DLL.
GoLink makes a DLL if either this switch is used or if using the /fo switch you specify an output file with the extension DLL. If neither of these apply and you are not making a driver, GoLink makes an EXE.
GoLink inserts base relocation information in the executable only if you use the /base xxxx switch, if you are making a DLL or a driver.
/driver = make a driver.
GoLink makes a driver if either this switch is used or if using the /fo switch you specify an output file with the extension SYS. GoLink does not set the WDM flag, unless /wdm is specified. See also making a Windows Driver Model driver and specifying the uponly flag.
GoLink inserts base relocation information in drivers.
/e = empty output file allowed.
Using this switch you can make a "shell" PE file which will have all the necessary formal parts but no sections.
/entry xxxx = set program entry point to xxxx.
For example, /entry main will start the program at the code label "main:". If you do not specify the entry point with this switch GoLink assumes START will be used (in upper or lower case or a mixture). So if you want to use this default you should ensure that your code has the label "START:" at the correct place to start execution. Every EXE file needs an entry point, but in DLLs it is optional. GoLink warns you if it cannot find the entry point in your executable. For compatibility with Microsoft tools, GoLink also recognises the entry point specified at assemble time using END. This information is passed to the linker using the .drectve section.
/export xxxx = specify exported functions, data and ordinals.
See exporting procedures and data
/files = report in detail on files used and created
This option reports the full paths, file dates and times and sizes of the files used during the linker process and of the output files. There is other useful information such as the number of imports, exports and debug symbols. Note that all file times are adjusted to allow for the current daylight setting time of the computer running GoLink.
/fo = specify output path/file.
If the output file and path is not specified, GoLink assumes that the output file should be an EXE, and should have the same name and path as the first object or res file. You can use the /fo switch to change these defaults, for example /fo MyProg.exe or /fo MyProg.dll or /fo c:\exe\MyProg.exe.
/h or /? = show a screen displaying these various options only.
/mix = link input files and lib code made with a compiler which decorates symbols.
Part of the baggage of a "C" compiler, and of the MASM assembler, is the decoration of symbols in the object files which they produce. Examples are:-
_MessageBoxW@16 (indirect call to an API where there are four parameters)
__imp__GetKeyState@4 (direct call to an API where there is one parameter)
_MyDataLabel (simple decoration applied to a data label)
_MyCodeLabel (simple decoration applied to a code label)
_MyCodeLabel@4 (decoration applied to a code label declared as having one parameter) The idea behind the _Name@xx decoration is that it provides a check that the number of parameters declared for a function is the same between the various modules (object files). In practice however, the added complexity of the required source code (eg. in MASM the need for EXTRN, EXTERN or PROTO to define the type of symbol) is very much out of proportion to the benefits achieved.
Some compilers also use decoration to enhance error reporting, but this has another problem: there is no consistent format for this.
Because GoAsm does not decorate symbols (unless the GoAsm /ms switch is used), GoLink does not expect symbol decoration. This means that if you want to use GoLink to link files made with a third party compiler which decorates symbols you must specify the /mix switch. This will cause GoLink to strip out decoration when comparing symbol names.
If you use the /mix switch, you will be unable to use a single leading underscore intentionally to differentiate between symbols. For example GoLink will regard _DOG and DOG as the same name.
If the /mix switch is used, symbols of types IMAGE_SYM_CLASS_STATIC and IMAGE_SYM_CLASS_LABEL will be limited to the module (object file) in which they appear, as expected by third party compilers. Otherwise, if these types have the same name GoLink will complain about duplicate symbols.
The /mix switch may also resolve problems if you have merged in a GoAsm module static library code made with such third party tools. If such code calls or references other such merged code, it is possible that this will be done with decorated symbols. These would not be recognised by GoLink unless the /mix switch is used.
/more = show console screenful then wait for input
See screen output - controlling, limiting and redirecting.
/mslu = insert loader code for Microsoft Layer for Unicode.
This switch causes GoLink to add Microsoft Layer for Unicode ("mslu") loader code to the executable at link-time.
If you are making an EXE file this code executes automatically immediately after your application loads (the entry point of your EXE is changed to the beginning of the loader code).
If you are making a DLL GoLink adds the loader code as a function within the DLL called MSLU_LOADER which your EXE must call (only once) when convenient (certainly before using a function in the DLL which might need mslu). A convenient time in most cases will be to call MSLU_LOADER just after your EXE starts by using eg. CALL  MSLU_LOADER. If you have more than one Dll which contains mslu loader code you can call each specifically using the sytax CALL  DllName:MSLU_LOADER.
The way the loader code works is this. Upon loading your application the system loader will have written the addresses of all the imports (APIs and other external calls) to the image of your EXE or DLL in memory. These addresses are only known at load-time as the system and other DLLs are loaded in your application's address space. If your application is being run under Windows 95, 98 or ME the mslu loader code added by GoLink will overwrite the relevant addresses to point to unicows.dll, rather than to the system DLLs. Unicows.dll contains wrappers around the NT, 2000 and XP versions of those APIs which are not fully supported under Windows 95, 98 or ME. Using mslu means that you may write just one version of your application (using the unicode APIs) to run under all versions of Windows. Under Windows 95, 98 or ME all the necessary conversion code (usually translation of strings from Unicode to Ansi and vice versa) is carried out in unicows.dll. If your application is being run under Windows NT, 2000 or XP then no action is taken by the loader code and unicows.dll will not be loaded at all by your application. For more information about the mslu see my help file The Microsoft Layer for Unicode.
/msludll xxxx = mslu loader to use this name for unicows.dll.
This switch informs GoLink that you have changed the name of unicows.dll to the name specified. If this switch is used, GoLink does not look for unicows.dll at link-time but looks for the named file instead. Similarly at run-time the mslu loader will look for the named file instead. Also the mslu loader error messages will refer to the named file and not to unicows.dll (nor to the Microsoft download site).
/msluerr xxxx /msluerr filename = specify a text file holding the mslu error message or
/msluerr off = switch off the error action altogether
The Golink mslu loader code default action is to display an error message to the user and cause your application to exit if one of these events occurs:-
1. The unicows.dll is not found. It is looked for using the same search order as other DLLs.
2. Unicows.dll is found but is damaged.
3. An API which should be in unicows.dll is not there. The loader has a list of APIs found to be in unicows.dll at link-time and expects all of them to be in the unicows.dll found at run-time.
The error message is in a message box in a GUI application or written to the console in a console application.
The error message states that the application needs unicows.dll to run, that it should be placed in the same folder as the application, and that it is available from the supplier of the application or from microsoft via a link.
You may prefer to use your own message instead of this default and if so, you can specify it using this switch. The file should be an ordinary Ansi text file. For example, if you want to use error.txt, you would specify the switch /msluerr error.txt

You may wish to stop GoLink from giving the error message and ending the process on the happening of one of the above events. You can do this by specifying /msluerr off. If you use this switch, then your application will continue to run even if unicows.dll is not found or is found to be damaged or if expected APIs are missing. The mslu loader code indicates whether the unicows.dll load was successful. In your EXE this indication appears in the EAX register at the normal entry address for your program. In your DLLs EAX is set upon the return from the call to MSLU_LOADER. The values held in EAX are:-

EAX=0 load successful
EAX=1 unicows.dll not found
EAX=2 unicows.dll found but damaged
EAX=3 an API expected in unicows.dll not found
If you change the name of the unicows.dll file you can inform GoLink of this using the /msludll switch.
/ne
/ni
/nw
/no
= no error messages.
= no information messages.
= no warning messages.
= no output messages at all.
If you are using a makefile you may wish to suppress output messages and rely only on GoLink's exit code (error=1), or you may simply wish to reduce the output information.

In a batch file, you can use the error return with ERRORLEVEL, for example the following will pause if there is an error return:-

GoLink @command.fil
IF ERRORLEVEL 1 PAUSE
Error messages are those which will stop GoLink from making the executable and include:-
Insufficient memory; incorrect use of command line switches; unable to open or read a specified file; files in wrong format or corrupted; incorrect information given for output file; unable to make output file; specified entry point not found or not in a code section; duplicate Resource Type, nameID or Language found in res file; no defective or duplicate ordinal number if direct import/export by ordinal; symbols declared more than once; symbols not declared at all; exported symbols not found.
Information messages are copyright and output information.
Warning messages do not stop the executable being made. They include entry point not found and no exports in a DLL.
See also screen output - controlling, limiting and redirecting.
/stackinit xxxx = initial stack commitment on start-up and on new threads.
Here you can specify the size in bytes (using hex) of the amount of memory which the system should commit for the stack when the application starts or when making a new thread. If you do not use this switch a value of 10000h (64KB) is used by default. Regardless of the value specified using this switch the system always enlarges the amount of committed memory in the stack in 4K chunks as the application needs it.
This switch may be used if your application needs to create space for a large amount of local data. Without this switch an exception could occur if your local data is larger than 4K. The reason for this is that the system uses Structured Exception Handling to manage the enlargement of the stack as and when it is needed, and it does this by establishing guard pages just adjacent to and deeper into the area of stack already committed. If your application attempts to write or read from a place beyond these guard pages, a true exception will occur rather than a signal to the system to create more stack. In experiments the size of the guard pages seems to vary but it is unlikely that it could ever be below 4K which is the normal page size.
/stacksize xxxx = stack allocation size on start-up or on new threads.
Here you can specify the size in bytes (using hex) of the area of memory which the system should allocate for potential stack use, should the application require it. If you do not use this switch a value of 100000h (1MB) is used by default. At start-up the system merely allocates space in virtual memory and only a small amount is committed at first. The system commits the remainder automatically in 4K chunks if the application needs it.
The value given with this switch applies both to the main thread of the application and also any new threads it makes.
This switch may be used if your application might need more than 1MB of stack space. Specifying more than 1MB does not use memory unnecessarily since the memory is only committed if it is actually used. Normally 1MB is more than sufficient for the stack, but you would need this switch if you were keeping large amounts of local data on the stack in procedures which were highly recursive.
/unused = report on unused/unreferenced labels
this only works with GoAsm object files or "Go" compatible object files see technical note. If this switch is used, GoLink will report on those data and code labels which have not been referenced in any way. Such redundant data declarations or code are easily left in the source code by mistake during development of a program. Now you can discover these and weed them out.
/uponly = specify the uponly flag.
This sets the IMAGE_FILE_UP_SYSTEM_ONLY flag which indicates to Windows that the file (usually a driver) may only be used on single-processor machines.
/version xxxx = set image version to major minor value
This is a 32 bit hex value so /version 20001 sets major version value to 2 and minor version value to 1.
/wdm = make a Windows Driver Model driver.
GoLink makes a WDM driver if this switch is used. This is a driver which is designed for multiple Windows platforms. It is not necessary to specify the /driver flag as well. See also making a driver and specifying the uponly flag.

Importing and exporting functions and datatop

Importing data

Data can only be imported indirectly. That is to say you can only import a pointer to data. However, using that pointer you can get the data itself.
For example, assuming DATA_VALUE is a data export in another program in GoAsm you get the pointer and the data as follows:-
MOV EBX,[DATA_VALUE]       ;get pointer to DATA_VALUE
MOV EAX,[EBX]              ;get the value
In the same way as for importing procedures from other programs at link-time you give GoLink the name of the executable containing the import.

Direct importing by ordinal

The usual method of importing a function in a DLL is effected by using CALL procedure, which will import the procedure by name. What happens here is that when the Windows loader starts the program it searches through the DLLs for the imports required by the program. This is done by comparing the names of the DLL exports against the names of the program's imports. To speed up this process with private DLLs sometimes exporting and importing by ordinal is used. Then the loader can find the correct import by using an index to a table within the DLL. Note that it is unwise to use this method for Windows system DLLs since the ordinal values of the exports are not guaranteed to be the same in all DLL versions.

Using GoLink and its companion program GoAsm, you can import by ordinal using this simple syntax in the assembler source script:-

CALL MyDll:6
This will call procedure number 6 in MyDll.dll. The way this works is that GoAsm simply passes the symbol "MyDll:6" to GoLink in the object file. GoLink knows this is an import by ordinal because of the presence of the colon. Note that the extension "dll" is assumed if no extension is given. Suppose you want a DLL to call a function in the main executable by ordinal, then you could use:-
CALL Main.exe:15
This calls the 15th function in Main.exe.
Calls to ordinals using the absolute form (using opcodes FF15) will result from using this syntax:-
CALL [Main.exe:15]
You should not include the path of the file in the call. GoLink will look for the file using the same search order as when looking for DLLs. If it is necessary to provide a path this should be provided in the command line or in a command file rather than incorporated in the call in the assembler script.
If you are not using GoAsm, you will still be able to use this method of importing by ordinal, provided your assembler will permit a symbol containing a colon (and a period if you need to add the extension).
Obviously in order to use this method of calling a function by ordinal you must ensure that the ordinal number of the function is fixed see exporting by ordinal.

Importing by specific DLL

Occasionally you may want to force the linker to use an import from a specific DLL. You might need to do this if two or more DLLs (given to the linker at link-time) offer functions with the same name.
You may also need to do this to override an API call when using the Microsoft Layer for Unicode using GoLink and the /mslu switch. This will add special loader code to your executable which will cause your application to call the relevant API in unicows.dll at run-time if running under Windows 95, 98 or ME. If you have written your own wrapper around a particular API you may need to stop this happening. You can therefore force GoLink to link to a particular DLL using the the syntax NameOfDll:NameOfAPI.

For example, if you do not want to call EnableWindow within unicows.dll under any circumstances, but always call EnableWindow within User32.dll you would use:-

User32:EnableWindow

Exporting procedures and datatop

You can make your procedures and your data available to other executables by exporting them. In Windows it is usual for DLLs to be used for exports, but sometimes a DLL will need to call a procedure or use data in an EXE file, and in that case the EXE file will also export. Exporting can be done either at link time (you tell GoLink which symbols to export), or using GoAsm, you can also do it at assemble time. GoAsm then tells GoLink the export information via the .drectve section in the object file. See the GoAsm help files as to how to declare exports at assemble time.
It is easy to declare exports at link time. You use the switch /export or /exports and follow this with one or more export names. Unless you use the \ continuation character you will need to use the switch again if you need to start on another line.
Example:-
/EXPORT LOAD_ELEMENT
/EXPORTS CALCULATE, ADJUST_DATA, DATA_VALUE
Here three functions are exported, and then a data pointer is exported. Only the symbol name is needed - there is no need to tell GoLink whether the symbol is in a code or data section.

Exporting by ordinal

Normally exports are conducted by name. What happens here is that when the Windows loader starts the program it searches through the DLLs for the imports required by the program. This is done by comparing the names of the DLL exports against the names of the program's imports. To speed up this process with private DLLs sometimes exporting and importing by ordinal is used. Then the loader can find the correct import by using an index to a table within the DLL. Note that it is unwise to use this method for Windows system DLLs since the ordinal values of the exports are not guaranteed to be the same in all DLL versions.

In order to use this method clearly it is imperative that the exporting program specifies an ordinal value for a particular export and the linker must not change this.

This can be done very easily, for example:-

/EXPORTS CALCULATE:2, DATA_VALUE:6
Here GoLink is instructed to use the ordinals 2 and 6 for the exports.

Exporting by ordinal without a name

Exporting by ordinal does not stop the name of the export appearing in the final executable. This is because it is the importing program which decides whether to import by ordinal or by name. All the exporting program can do is to fix the ordinal value. However sometimes a programmer might like to ensure no name for the export appears in the final executable. You sometimes see such "no name" exports in system DLLs for example, probably in order to hide the job carried out by particular functions. In order to do this add the word NONAME to the end of the export for example:-
/EXPORTS CALCULATE:2:NONAME, DATA_VALUE:6:NONAME
Here the value of the code label CALCULATE will be exported as ordinal number 2, but the name of the export will not appear in the final executable. This means that if another program tried to call the CALCULATE function it would fail. The function can only be called by ordinal. This works for data as well, as in this example.

Using Unicode for imported and exported labels

GoLink is aware that it might receive Unicode labels in the object files, and it expects them to be in UTF-8 format. When making the executable and making debug symbol information GoLink retains this format. This means you can import and export functions and data using Unicode (you can use non-Roman characters in your symbols if you wish). Note that named resource IDs and named resources are treated differently. They are always in UTF-16 format as required by the PE format specifications.

Legal stufftop

Copyright

GoLink is copyright © Jeremy Gordon 2002/9 [MrDuck Software] - all rights reserved.

Licence and distribution

You may use GoLink free for any purpose. You may redistribute GoLink freely (but not for payment nor for use with a program or any material for which the user is asked to pay). You are not entitled to hide or deny my copyright.

Disclaimer

The author has made every effort to ensure that the output of GoLink is accurate, but you do use it entirely at your own risk. The author does not accept any liability for it failing to work properly or giving the wrong output nor for any errors in this manual.

Acknowledgementstop

My grateful thanks to Wayne J Radburn, of Gatineau, Québec, and to Anthony Williams, of Brixham, Devon England, author of ALINK. And thanks for your ideas, support and bug reports Leland M. George of West Virginia, Daniel Fazekas of Budapest, Brian Becker and members of the GoAsm Assembler and Tools forum.