Intended use
------------


Link COFF object files together to form a PE/COFF image file. Possibly replace the MS linker along the way.


Requirements
------------

A working .NET environment. On Windows, the .NET framework 2 is needed. On *nix, Mono should work
(but has not been tested yet).


Usage
-----

Linker <files> <options>

Specify each object file on the command line. If you have lots of files, you can use a response file.
Put the path of each file on a separate line in a text file, and specify this file to the linker. For
example, if you have loader1.obj and loader2.obj, write the names of these files in a new file, and
specify @list_of_object_files.txt to the linker instead of having to type the name of each object file.

Linking archives (.a files) (libraries on Windows, .lib files) are not supported yet.
Generating DLL files is not tested yet.

You can specify as many object files as you want, unused ones will be removed anyway. The linker is
fairly good at removing unneeded object files and sections from the resulting image. However it is
far from perfect yet - when linking in C code, all the .debug sections will be included in the image
(if your compiler generates any - the Microsoft C compiler does). Also on x64, the pdata and xdata
sections may not be ordered correctly.

When mixing assembly and C/C++ code, the linker will attempt to demangle (undecorate) C/C++ symbol names
if a name cant be matched to any symbols. Currently MS Visual C++, stdcall and fastcall name mangling
is supported, however MSVC name mangling is not complete (templates, operators and string constants
are not supported. I doubt you want to use C++ classes in your bootloader though.)

Accepted input formats
----------------------

For the time being, COFF only. Additional input formats can be added, as the linker can be extended.
Libraries are not yet supported.

Possible output formats
-----------------------

Windows Portable Executable (PE) files, and raw output (just the image without any headers). Additional
output formats can be added, as the linker can be extended.
  

Options
-------

  -base=N         Specify the base address of the image (optional). If not specified, the linker
                  uses the default 0x00400000 value. Take the size of the PE header into account
                  as well. For example, if you want the code to start at the 64K mark (0x10000),
                  and have only code sections in the object files, specify 64K-512 (0x0FE00) to
                  the linker. The PE header usually fits in 512 bytes, if you have more than two or
                  three sections however, it may grow to 1024 bytes. Check the map file or image
                  file to verify that the base address of the code is what you wanted. The base
                  address plus the RVA of the first section should sum up to the intended base address.
                  The value N can be written as a decimal number or as a C-style hexadecimal number.

  -align=N        Specify section alignment. It defaults to 4096, the size of a page. You can specify
                  any power of two from 512 to probably 64K. The file alignment is currently fixed
                  to 512 bytes. If you are using the linker to generate a bootloader, and have
                  multiple sections in your output, use the value of the file alignment (512) unless
                  you want to deal with paging.
                  The value N can be written as a decimal number or as a C-style hexadecimal number.

  -out=file       Specify the output file. If not specified, the linker will check the input files
                  and output an error message.

  -map=file       Specify the linker map file (optional). The map file contains information about the
                  layout of the sections and public symbols.

  -machine        Select target machine (optional). This affects only the value written into the PE
                  file header. Specify in conjunction with -ignoremachine if the object files have
                  different target machines, and you want the linker to generate the image. Otherwise,
                  if all the object files have the same target machine, this option can be omitted.

  -ignoremachine  Ignore conflicting target machines in the object files. Without this option, the
                  linker will probably not allow to mix 32- and 64-bit code.

  -entry          Specify the name of the entry point (for example "-entry=MyKernelEntryPoint").
                  If not specified, the default entry point ("_NtProcessStartup") is used. Use
                  the -noentry option to ignore the entry point.
  -export         Specify additional public symbol that you want to include in the image. Contrary to
                  its name, it does not (yet) generate a PE Export Data Directory. (If you dont know
                  what that means, dont worry about it).

                  If a public symbol specified with -entry or -export does not exist, the linker will
                  emit a warning and ignore the offending symbol. Thus, it is possible to generate an
                  empty PE image (if the linker finds none of the symbols specified). Check the output
                  messages or the map file to verify that all the specified symbols are linked in.

  -noentry        Tells the linker that the image does not have an entry point, and the default entry
                  point ("_NtProcessStartup") should not be used either.

  -debug          Output more debug information. Allowed values are "relocs", "symbols", "layout",
                  "demangle", "all". Works only on debug builds anyway.

  -dll            Tells the linker to generate a dynamic link library instead of an executable file.
                  This has no effect on the generated image, apart from setting a flag in the PE header.

  -listformats    Lists the accepted output formats. These can be used inconjunction with the -format
                  option to specify an output format.

  -format         Specifies the output format to use (optional). Defaults to "pe", which represents
                  the Windows PE format.

  -plugin         Specifies that a plugin should be loaded, that provides additional input or output
                  format implementations.


Example
-------

This is the command line I build my bootloader with:
> Linker @stage1.txt -out=stage1 -map=stage1.map -base=0x1FE00 -machine=x86 -align=512 -ignoremachine -entry=EntryNormal
Linker v1.0.0.563
.\Ldr16Init.obj: warning LNK4302: Relocation for other than target machine x86 found (type X86Dir16), image may not run correctly.



How do I get my bootloader out of the PE file?
----------------------------------------------

Use the "-format=raw" option, this outputs raw binary files. Alternatively you can use the PE output
format, and use your program of choice that can copy a region from inside file A to file B.


Why yet another linker?
-----------------------

As far as I know, there are no linkers that allow you to freely mix 16-bit, 32-bit and 64-bit code
in COFF object file format. Both the ld linker and Microsoft's link choke on 16-bit relocations, and
neither can mix x86 and x64 object files as well.

If you use Windows to develop your OS, and you use the MS toolchain, you are probably screwed.

I have tried various workarounds to this issue, but the easiest way was to write a custom linker.
There are adventages to this approach as well:
 - support for ld linker scripts (not yet, but planned) (MS linker does not support this at all)
 - other object file and image formats (for example, ELF) can be added easily
 - allow arbitrary base address for image
 - mix assembly and C/C++ code, and let the linker worry about those pesky C++ names.

This version (1.0.0.563) supports COFF object files as input, and PE/COFF and raw image output only.
It is experimental, may contain bugs. If you find bugs, please report it back to me via the osdev
forum (PM to ru2aqare).


Why not use <insert your favorite assembler here>, why need linking?
--------------------------------------------------------------------

The project which eventually started the development of the linker is fairly complex. It will
eventually be a bootloader, with support for PE and ELF images, chainloading from GRUB or the NT
bootsector, chainloading to NTLDR, providing v86 services to a higher layer (even in x64 mode).
Some of these are working reliably, others are have not yet been implemented.

The result is that I have lots of source files, some are in assembly, a large portion is written
in C however. Writing everything in one single assembly file is simply not a feasible option.

I have tried:
 - nasm, but it did not support x64 code generation.
 - fasm, but it had issues emitting 16-bit relocations to COFF files
 - masm, but it had issues with 16-bit code


Why is the linker in IL, why not C/C++/asm/...
----------------------------------------------

The big advantage of managed environments (.NET framework or Java) is that RAD - Rapid Application
Development - is possible. I simply did not have the time to write the complete linker in C. Not
that I wanted to.

Also you can decompile the linker and see how it works internally. A big binary executable written
in C may do anything to your system however.


Why not Java, .NET sucks!
-------------------------

MS VisualStudio 2oo8 is much more comfortable (at least for debugging it is) than NetBeans or
Eclipse. I use run-to-cursor, single-step and step-over all the time for debugging - I like to
see the execution flow of the code, and watch the variables as they are modified. Doing this in
Java has always been a pain in the *** for me (this does not imply that Java sucks, only that
VS2oo8 is a more comfortable environment).
Also the [DebuggerStepThrough] feature of VS2oo8 is a huge bonus - no need to remember which
functions have been debugged already, I can single-step all the way and the debugger will not
step into code that is working correctly.
