Search code examples
assemblygccnasmldkernel32

Link to kernel32.dll using ld.exe


I have assembled my assembly program using the following command:

nasm -f win64 -o test.obj test.asm

test.asm contains a few functions that call Win32 functions like GetStdHandle, HeapAlloc, etc

Normally, I would link one of my assembly projects like so:

ld -LC:/Windows/System32 -lkernel32 -e main -o test.exe test.obj

And it produces a test.exe file, as expected.

However, once I begin to use Win32 functions making use of the heap, like HeapAlloc, HeapFree, GetProcessHeap, I get the following error when linking:

C:\msys64\mingw64\bin\ld.exe: ertr000016.o:(.rdata+0x0): undefined reference to '_pei386_runtime_relocator'

I was then able to assume it has to do with MinGW's files being linked in. So I tried to compile it without them:

ld -nostdlib -nostartfiles -LC:/Windows/System32 -lkernel32 -e main -o test.exe test.obj

and get the following error:

C:\msys64\mingw64\bin\ld.exe: cannot find -lkernel32

So, my question is: how am I supposed to link to kernel32 using ld.exe (without including startfiles or stdlib), because no matter what I try I cannot get it to work.

Thank you for your help!

(I would like an answer that doesn't just tell me use GoLink, please, unless that is the only possible solution).


Solution

  • I've realized that the answer is in the comments now, but I'll post all the steps here just to be clear:

    1. Create a .def file for the DLL to be used. This can be done like this:
    LIBRARY [name of the dll]
    EXPORTS
        [required export #1]
        [required export #2]
        [etc.]
    
    1. Use dlltool.exe to create an archive library file for the .def file:
    dlltool -d "[path to the .def file]" -l "[path to output file C, defined below]"
    

    In this command, C is libXXX.a, with XXX changed out for a different name (preferably the name of the original dll without the extension).

    1. Instead of using ld.exe, use the linker built into gcc.exe. Also, change out the directory after -L for the directory containing the libXXX.a archive file(s) and change out the dll names that follow for the XXX that was replaced in libXXX.a. These steps, in the context of the original problem, would be:
    [Kernel32.def file]
    
    LIBRARY KERNEL32.DLL
    EXPORTS
        HeapAlloc
        HeapFree
        [...]
    
    dlltool -d "kernel32.def" -l "libkernel32.a"
    
    gcc -LC:/path/to/this/directory/ -lkernel32 -e main -o test.exe test.obj