link.exe cheatsheet

TOOLS

Let's say you have a COFF or a PE object lying around, which you would like to make into a proper executable on Windows. Perhaps you are a compiler developer, or maybe you are just a masochist. Whatever the reason, link.exe is an archaic and strange tool, and your knowledge of ld will not be much help. Hence this cheatsheet!

This cheatsheet is meant to be a quick reference for some common usecases I've encountered. For a more detailed guide of the various options, see the Microsoft docs page on Linker options and MSVC Linker reference for everything else.

Prerequisites

link.exe can be obtained with Visual Studio Installer, for instance by installing Desktop development with C++. In order to actually use the tool, it needs to be in your PATH. This can be done by either locating and adding the binaries manually at a path like

C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.33.31629\bin\Hostx64\x64
C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.33.31629\bin\Hostx86\x86

Alternatively, vcvars{32,64}.bat will do this automatically. It lives somewhere around

C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build
vcvars in Powershell

Since this is a batch file, it must be run in a batch terminal (aka cmd). If you want to use it in Powershell, then you can open it as a subprocess from within a cmd where vcvars has been executed:

C:\tmp>vcvars64
**********************************************************************
** Visual Studio 2022 Developer Command Prompt v17.3.6
** Copyright (c) 2022 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'

C:\tmp>powershell
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

PS> link /help
Microsoft (R) Incremental Linker Version 14.33.31630.0
Copyright (C) Microsoft Corporation.  All rights reserved.

   For help on Linker, type `link /link' or `link'
   For help on Library Manager, type `link /lib' or `lib'
   For help on Dumper, type `link /dump' or `dumpbin'
   For help on Editor, type `link /edit' or `editbin'
   For help on CvtCIL, type `link /cvtcil'
   For help on PushThunkObj Generator, type `link /pushthunkobj'

If the linker is in your path, then link /help should be a valid command.

C:\tmp>link /help
Microsoft (R) Incremental Linker Version 14.33.31630.0
Copyright (C) Microsoft Corporation.  All rights reserved.

   For help on Linker, type `link /link' or `link'
   For help on Library Manager, type `link /lib' or `lib'
   For help on Dumper, type `link /dump' or `dumpbin'
   For help on Editor, type `link /edit' or `editbin'
   For help on CvtCIL, type `link /cvtcil'
   For help on PushThunkObj Generator, type `link /pushthunkobj'

Finally, note that most things in the linker (with the exception of symbols and such) are case insensitive. So you can type in your lowercase UNIX-y chic despite the help pages screaming options and commands at you.

Dumping

Although you can use a tool like objdump to inspect the files you generate, link.exe does actually come with a built-in object dumping tool, cleverly called /dump.

General syntax:

link /dump [options] [files]
Option Description
/disasm Disassemble the object
/headers Show header information from the object
/relocations Display any relocations in the object
/symbols Show symbols defined within the object

Linking

Linking works more or less as expected. Note that since Windows syscalls are deliberately unstable, you typically end up needing to link against certain libraries to do things like open files or exit a process. For ExitProcess we can see on its Microsoft docs page that it lives in Kernel32.lib and Kernel32.dll. To link with it statically, you'd typically include it with your object files:

link /entry:_WinMain my_exec.lib Kernel32.lib /out:my_exec.exe

General syntax:

link [options] [files]
Option Description
/dll Produce a DLL
/entry:symbol Set the entry point to be symbol
/machine:arch Specify target architecture
/out:filename Produce the linked executable in filename
/subsystem:sys Select the subsystem to link for1