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).
I've realized that the answer is in the comments now, but I'll post all the steps here just to be clear:
.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.]
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).
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
... -LC:/Windows/System32 -lkernel32...
This is definitely wrong: -lkernel32
will not search for a DLL file named kernel32.dll
, but for a library file named libkernel32.a
.
... and libkernel32.a
is surely not located in C:/Windows/System32
.
How I would go about using
dlltool.exe
to generate my ownlibkernel32.a
?
For 64-bit Windows this is easier than for 32-bit Windows (because in 32-bit Windows the fuctions are named differently in the DLL and in the object files).
First, you create a definition file ( .def
) that looks like this:
LIBRARY KERNEL32.DLL
EXPORTS
HeapAlloc
HeapFree
GetProcessHeap
CreateFileA
ReadFile
There is a 3rd party tool that can read a .dll
file and generate a .def
file containing all functions of the DLL; however, you can do this manually and only add the functions that you need.
Then run the following command line:
dlltool -d kernel32.def -l libkernel32.a
Unfortunately, I cannot tell you if this solves your problem with _pei386_runtime_relocator
.
EDIT
undefined reference to 'SetFilePointer'
SetFilePointer
is also a function defined in kernel32.dll
. Did you add SetFilePointer
to the .def
file?
LIBRARY KERNEL32.DLL
EXPORTS
HeapAlloc
HeapFree
GetProcessHeap
CreateFileA
ReadFile
SetFilePointer <-- HERE?
I am linking with the following command:
There may be a second problem:
Some versions of gcc
require the command line arguments in a certain order. Maybe this is true for ld
, too.
Try to move the -L
and -l
argument to the end of the line:
ld ... -o test.exe test.o -L... -lkernel32
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.