loadlibrary
loadlibrary copied to clipboard
Got "attempted to call an unknown symbol" for an hello world example
In order to learn how to use the loadlbrary library with the goal of accessing a commercial win32 library from linux, I started off with a simple hello world example.
Here are my files:
- say-hello.h
#ifndef SAY_HELLO_H
#define SAY_HELLO_H
void say_hello();
#endif /* SAY-HELLO */
- say-hello.c
#include <stdio.h>
void say_hello()
{
printf("Say Hello!\n");
}
- hello-main.c - For testing the dll with wine
#include "say-hello.h"
int main(int argc, char*argv[])
{
say_hello();
}
- The build command of the dll:
i686-w64-mingw32-gcc -o hello-main.obj -c -O2 -mms-bitfields hello-main.c
i686-w64-mingw32-gcc -o say-hello.obj -c -fPIC -O2 -mms-bitfields say-hello.c
i686-w64-mingw32-gcc -o say-hello.dll -shared say-hello.obj
i686-w64-mingw32-gcc -o hello-main.exe hello-main.obj say-hello.dll
- Testing the dll works:
wine hello-main.exe
000b:fixme:winediag:start_process Wine Staging 4.0-rc2 is a testing version containing experimental patches.
000b:fixme:winediag:start_process Please mention your exact version when filing bug reports on winehq.org.
Say Hello!
Now I wanted to load this dll into load library and I started at mpclient.c sources and removed as much as I could and then tried to call my say_hello() function. This is what I got:
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include "winnt_types.h"
#include "pe_linker.h"
#include "ntoskernel.h"
int main(int argc, char **argv, char **envp)
{
PIMAGE_DOS_HEADER DosHeader;
PIMAGE_NT_HEADERS PeHeader;
struct pe_image image = {
.entry = NULL,
.name = "say-hello.dll",
};
// Load the mpengine module.
if (pe_load_library(image.name, &image.image, &image.size) == false) {
printf("You must add the dll and vdm files to the engine directory");
return 1;
}
// Handle relocations, imports, etc.
link_pe_images(&image, 1);
// Fetch the headers to get base offsets.
DosHeader = (PIMAGE_DOS_HEADER) image.image;
PeHeader = (PIMAGE_NT_HEADERS)(image.image + DosHeader->e_lfanew);
// Try calling into the library.
void (*SayHelloPtr)();
if (get_export("say_hello", &SayHelloPtr) != -1) {
(*SayHelloPtr)();
}
else
printf("Failed getting pointer to say_hello()!\n");
return 0;
}
It coompiles, the dll loads, the say_hello symbol is found, but it then crashes at (*SayHelloPtr)(). What did I miss?
Thanks!
After I wrote the above, I realized that perhaps the "attempt to call an unknown symbol" error is the call to printf(). I then added a new function to my dll:
int32_t add_hello(int32_t a, int32_t b);
and called it as follows:
// Try calling into the library.
int32_t (*AddHelloPtr)(int32_t a, int32_t b);
if (get_export("add_hello", &AddHelloPtr) != -1) {
int a=10,b=32;
printf("%d+%d=%d\n", a,b,AddHelloPtr(a,b));
}
else
printf("Failed getting pointer to say_hello()!\n");
and this worked!
But I still wonder how would I load the windows CRT library so that I can call printf (and other io functions)? Or is there a way to redirect the DLL printf() call to the gcc libc printf() .