Andrew Kelley via llvm-dev
2017-Jun-04 19:33 UTC
[llvm-dev] trying to get a minimal windows program linked with lld
Here's some C code: extern void *GetStdHandle(unsigned int nStdHandle); extern void ExitProcess(unsigned int exit_code); extern char WriteFile(void *HANDLE, const void * lpBuffer, unsigned int nNumberOfBytesToWrite, unsigned int *lpNumberOfBytesWritten, void *lpOverlapped); static const char *message_ptr = "hello\n"; static const unsigned int message_len = 6; __attribute__((stdcall)) int _start(void) { void *hStdOut = GetStdHandle(-11); WriteFile(hStdOut, message_ptr, message_len, 0, 0); ExitProcess(0); } I use mingw-w64 like this: gcc -c test.c Create kernel32.def: EXPORTS ExitProcess GetStdHandle WriteFile Use dlltool to create kernel32.lib: dlltool -d kernel32.def -l kernel32.lib Then link with lld-link: lld-link -NOLOGO -SUBSYSTEM:console test.o kernel32.lib -OUT:test.exe -NODEFAULTLIB -ENTRY:_start This succeeds, but then I get a segfault when running test.exe. When I step through the code, what's happening is it's getting to 140005068: ff 25 ce cf ff ff jmpq *-0x3032(%rip) # 0x14000203c which is trying to jump into .idata section where presumably the stub for GetStdHandle lives. However after this jump, $rip ends up getting assigned a bogus address and then the segfault happens. Any ideas how to make these library calls hook up correctly? -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170604/9954c764/attachment.html>
Andrew Kelley via llvm-dev
2017-Jun-04 20:15 UTC
[llvm-dev] trying to get a minimal windows program linked with lld
Update: smeenai from #llvm has been helping me with this, and we narrowed it down to kernel32.lib being no good. kernel32.lib from the 14393 SDK worked fine. My goal is to not depend on .lib files from the SDK, so there's still a problem to solve here. On Sun, Jun 4, 2017 at 3:33 PM, Andrew Kelley <superjoe30 at gmail.com> wrote:> Here's some C code: > > extern void *GetStdHandle(unsigned int nStdHandle); > extern void ExitProcess(unsigned int exit_code); > extern char WriteFile(void *HANDLE, const void * lpBuffer, unsigned int > nNumberOfBytesToWrite, > unsigned int *lpNumberOfBytesWritten, void *lpOverlapped); > > static const char *message_ptr = "hello\n"; > static const unsigned int message_len = 6; > > __attribute__((stdcall)) int _start(void) { > void *hStdOut = GetStdHandle(-11); > WriteFile(hStdOut, message_ptr, message_len, 0, 0); > ExitProcess(0); > } > > > I use mingw-w64 like this: > > gcc -c test.c > > > Create kernel32.def: > > EXPORTS > ExitProcess > GetStdHandle > WriteFile > > > Use dlltool to create kernel32.lib: > > dlltool -d kernel32.def -l kernel32.lib > > > Then link with lld-link: > > lld-link -NOLOGO -SUBSYSTEM:console test.o kernel32.lib -OUT:test.exe > -NODEFAULTLIB -ENTRY:_start > > This succeeds, but then I get a segfault when running test.exe. When I > step through the code, what's happening is it's getting to > 140005068: ff 25 ce cf ff ff jmpq *-0x3032(%rip) # > 0x14000203c > which is trying to jump into .idata section where presumably the stub for > GetStdHandle lives. However after this jump, $rip ends up getting assigned > a bogus address and then the segfault happens. > > Any ideas how to make these library calls hook up correctly? >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170604/6b172d6b/attachment.html>
Shoaib Meenai via llvm-dev
2017-Jun-04 21:46 UTC
[llvm-dev] trying to get a minimal windows program linked with lld
+ruiu and compnerd, since there might be an lld issue here. A slightly simpler example. This is all x86_64; I haven't tried x86. % cat imp.c __declspec(dllimport) void ExitProcess(unsigned exitCode); int mainCRTStartup() { ExitProcess(0); } % cat kernel32.def LIBRARY kernel32 EXPORTS ExitProcess % dlltool –d kernel32.def –l kernel32.lib % cl /Zl /c imp.c % link /subsystem:console imp.obj kernel32.lib The above executable runs successfully, as does one compiled with ld: % ld --version GNU ld (GNU Binutils) 2.28 % ld imp.obj kernel32.lib If we compile with lld, however: % lld-link /subsystem:console /entry:mainCRTStartup imp.obj kernel32.lib The resulting executable segfaults, and it doesn't actually have any imports: % llvm-readobj -coff-imports imp.exe File: imp.exe Format: COFF-x86-64 Arch: x86_64 AddressSize: 64bit Given that both link.exe and MinGW-w64's ld are able to handle the import library correctly, I'm inclined to believe this is an issue with lld. I'm attaching the kernel32.lib output by dlltool for ease of investigation. From: llvm-dev <llvm-dev-bounces at lists.llvm.org> on behalf of Andrew Kelley via llvm-dev <llvm-dev at lists.llvm.org> Reply-To: Andrew Kelley <superjoe30 at gmail.com> Date: Sunday, June 4, 2017 at 1:15 PM To: LLVM Dev <llvm-dev at lists.llvm.org> Subject: Re: [llvm-dev] trying to get a minimal windows program linked with lld Update: smeenai from #llvm has been helping me with this, and we narrowed it down to kernel32.lib being no good. kernel32.lib from the 14393 SDK worked fine. My goal is to not depend on .lib files from the SDK, so there's still a problem to solve here. On Sun, Jun 4, 2017 at 3:33 PM, Andrew Kelley <superjoe30 at gmail.com> wrote: Here's some C code: extern void *GetStdHandle(unsigned int nStdHandle); extern void ExitProcess(unsigned int exit_code); extern char WriteFile(void *HANDLE, const void * lpBuffer, unsigned int nNumberOfBytesToWrite, unsigned int *lpNumberOfBytesWritten, void *lpOverlapped); static const char *message_ptr = "hello\n"; static const unsigned int message_len = 6; __attribute__((stdcall)) int _start(void) { void *hStdOut = GetStdHandle(-11); WriteFile(hStdOut, message_ptr, message_len, 0, 0); ExitProcess(0); } I use mingw-w64 like this: gcc -c test.c Create kernel32.def: EXPORTS ExitProcess GetStdHandle WriteFile Use dlltool to create kernel32.lib: dlltool -d kernel32.def -l kernel32.lib Then link with lld-link: lld-link -NOLOGO -SUBSYSTEM:console test.o kernel32.lib -OUT:test.exe -NODEFAULTLIB -ENTRY:_start This succeeds, but then I get a segfault when running test.exe. When I step through the code, what's happening is it's getting to 140005068: ff 25 ce cf ff ff jmpq *-0x3032(%rip) # 0x14000203c which is trying to jump into .idata section where presumably the stub for GetStdHandle lives. However after this jump, $rip ends up getting assigned a bogus address and then the segfault happens. Any ideas how to make these library calls hook up correctly?