Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Got "attempted to call an unknown symbol" for an hello world example #58

Open
dov opened this issue Dec 29, 2018 · 1 comment
Open

Got "attempted to call an unknown symbol" for an hello world example #58

dov opened this issue Dec 29, 2018 · 1 comment

Comments

@dov
Copy link

dov commented Dec 29, 2018

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!

@dov
Copy link
Author

dov commented Dec 29, 2018

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() .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant