News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Linking C With ASM

Started by Ehtyar, October 19, 2006, 11:06:16 PM

Previous topic - Next topic

Ehtyar

Hi all.
I recently came across an excellent piece of code here that allows you to load a dll from resources, and uses custom functions to emulate LoadLibrary, GetProcAddress, and FreeLibrary using a memory pointer instead of a zero-terminated string. Unfortunately, as many of us are probably aware, a lot of good code is in C :(
I spent the majority of yesterday afternoon attempting to link the object file i compiled in MinGW with the object file from MASM using mslink, polink and the linker that comes with MinGW. Unfortunately, Polink took issue with my declaration of STDCALL functions in the C object file, and the MinGW linker took issue with the MASM object file's lib inclusions. I came closest to accomplishing the link using mslink, but it seems that in order for MinGW to compile on multiple platforms, it injects custom startup code from one of it's librarys into the object file. The library file from MinGW which exports the custom functions is not compatible with mslink.
My question is whether or not anyone can give me any ideas on how best to link the c object file to the MASM one using a free C compiler and a linker of some kind. The ONLY problem i'm having is this injected code from MinGW, so if anyone has a solution to that problem, it would aos be greatly appreciated.

Thanks, Ehtyar.

P.S. Please forgive any mistakes, was in kind of a hurry :(

hutch--

The object module compatibility is the main factor, if the mingw object format does not work with MASM's COFF format, perhaps you could use the source in a Microsoft C compiler building COFF output and that will link fine. As usual you will have to write a MASM prototype for the C module making sure you get the calling convention correct but it should be simple enough to do.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Ehtyar

I have completed he prototypes, only needed three functions, but it's the compiler i wonder about. Do you have any suggestions on which microsoft compiler? I *CAN* use visual studio if i have absolutely no other choice, but any other solution would be greatly appreciated.
I did check the file created by masm and by MinGW, and the first few bytes were a match, and i noticed a similar structure when looking at a hex dump....so i just assumed they were both coff. My bad i guess.

Thanks, Ehtyar

Vortex

Ehtyar,

Have a look at this thread :

Loading and running EXEs and DLLs from memory

http://www.masm32.com/board/index.php?topic=3150.0

Ehtyar

My god microsoft sure know how to turn compiling an object file into a fiasco..i know why i use MinGW. Anyway, thank you for that link Vortex, i'm rather annoyed with myself for not having found that link earlier. I will give it a go and report back, maybe with a demo of what i'm making ;)

Vortex

Ehtyar,

Please feel free to post here all your questions regarding linking C with asm. Paul and me , we created a set of examples of mixed C & asm, have a look at the GeneSys project. Would you like that I send here a new example of C&asm?

Ehtyar

Well i'll try to cut a long story short.
I tried your library Vortex, but couldnt get it to not crash when i tried to load the dll from a pointer returned by LockResource. So, i had a look at GeneSys like you suggested, and noticed you had used PellesC, so i gave it a shot myself.
It compiled the MemoryModule code perfectly (i had to substitute stricmp with lstrcmpi, but what ya gonna do). I have compiled it into a static library, and included it in my test project. Unfortunately, despite almost 4 hours now of working on it, i cannot get it to not-crash when loading the dll.
In the attachment, i have included the library (MemoryModule.lib) with its PellesC project files (in MemoryModule dir), an asm test project (the one that isnt working) (MemoryModuleTest.asm), and a C test (MemoryModule\MemoryModuleTest.c) that does exactly the same thing as the asm version, but it works. If anyone can provide any insight into this problem, i'd be very appreciative.

Thanks, Ehtyar.

P.S. Thanks for the help so far guys, think i'd have lost my mind by now otherwise :U

[attachment deleted by admin]

Vortex

Quotebut couldnt get it to not crash when i tried to load the dll from a pointer returned by LockResource.

Ehtyar,

My library doesn't accept normal resources, it cannot handle them:

http://www.masm32.com/board/index.php?topic=3150.msg24252#msg24252

The solution is to use binary resource template for dialog boxes etc. To embed a DLL in your executable, you need to convert it to an object file with Hutch's file data assembler fda.exe My example project explains how to do this. Back home, I will check your attachment.


Ehtyar

Oh i'm sorry Vortex, i thought it meant you couldnt load resources from the loaded DLL. Right now though, i really want to know why the c version isnt working, so i;m looking foreward to your feedback, but ill try using your method again the right way in the meantime :)

Ehtyar

It seems PellesC is missing a protoype for the return value used for the MemoryGetProcAddress function: FARPROC (line 40 in MemoryModule.h). I searched a little for it, but i am in a rush to get to work, but if anyone has any quick solutions, i'd appreciate it :)

Thanks, Ehtyar.

Ehtyar

OK, apparently this is not the case either. If i typedef FARPROC above the prototypes, i get a redinfintion error..So that leaves me officially without any more ideas...
Any help would be really appreciated guys.

Thanks, Ehtyar.

drizz

Hello Ehtyar,

I'm sorry i didnt have time sooner to reply, i'd save you some time....

basically everything is fine but your asm code.

When statically linkiing C library you MUST NOT override its startup code
by placing entrypoint directly (label "code:" in your case, "END code")
you MUST write either "main proc c argc,argv"  procedure  for console
or "WinMain proc stdcall hInst,hInstPrev,szCmdLine,iCmdShow" for GUI.

from your MemoryModuleTest.zip file, replace MemoryModuleTest.asm
with my modifications:
.386
.MODEL FLAT,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
includelib MemoryModule.lib
include \masm32\macros\macros.asm
MemoryFreeLibrary PROTO :DWORD
MemoryGetProcAddress PROTO :DWORD, :DWORD
MemoryLoadLibrary PROTO :DWORD
.data?
hInstance dd ?
.code
WinMain proc stdcall hInst,hInstPrev,szCmdLine,iCmdShow
local hLib
push hInst
pop hInstance
invoke FindResource, NULL, 1000, chr$("RT_RCDATA", 0)
cmp eax, 0
je damn
invoke LoadResource, NULL, eax
cmp eax, 0
je damn
invoke LockResource, eax
cmp eax, 0
je damn
push eax
invoke MemoryLoadLibrary, eax
mov hLib,eax
cmp eax, 0
je damn
invoke MemoryGetProcAddress, eax, chr$("TestPublic", 0)
cmp eax, 0
jz damn
call eax
invoke MemoryFreeLibrary, hLib
jmp get_out
damn:
invoke MessageBox, NULL, chr$("damn", 0), NULL, MB_OK
get_out:
ret
WinMain endp

END
The truth cannot be learned ... it can only be recognized.

Ehtyar

#12
Thank you for the help drizz, and it probably works perfectly, if not for this s**t.
crt.lib(_setenvp.obj) : error LNK2001: unresolved external symbol __imp__GetEnvironmentStrings@0
To explain this line, crt.lib is the PellesC static lib for linking to the crt. It is placed inside the working dir for the test app so that mslink can find it when MemoryModule.lib wants it. Basically, this is the error i get when i try to assemble your code drizz. It never popped up earlier, but what i really can't understand is how that is the only api it is missing when the test app is linked to kernel32 anyway.....
Please someone tell me this is not normal, because i'm really starting to build up a major aversion to hlls at the moment....

Once again, any help is much appreciated, Ehtyar.

[edit]
Playing with the settings in PellesC, and adding a pragma or two has taken me to now having _WinMainCRTStartup unresolved...guess that's not much of an advancement.
[/edit]

drizz

i dont know what  is wrong, it compiles perfectly here...

Microsoft (R) Windows (R) Resource Compiler Version 5.2.3668.0
Copyright (C) Microsoft Corporation.  All rights reserved.
Microsoft (R) Macro Assembler Version 6.15.8803
Copyright (C) Microsoft Corp 1981-2000.  All rights reserved.
Microsoft (R) Incremental Linker Version 7.10.3077
Copyright (C) Microsoft Corporation.  All rights reserved.


DLL_PROCESS_ATTACH
Called exported function TestPublic.
DLL_PROCESS_DETACH


i dont use MASM32 includes... i've looked at them and i see that GetEnvironmentStrings is defined as
GetEnvironmentStrings equ <GetEnvironmentStringsA>

but kernel32 exports 3 functions:
GetEnvironmentStrings
GetEnvironmentStringsA
GetEnvironmentStringsW

so i assume that that is the cause of error

try this:
comment this line in your kernel32.inc
;GetEnvironmentStrings equ <GetEnvironmentStringsA>
and write this:
GetEnvironmentStrings PROTO


hope that does it...
The truth cannot be learned ... it can only be recognized.

Ehtyar

You won't believe this. All i had to do was specify WinMain as the entry point...and lookie lookie, i get 3 pretty little messageboxes saying "DLL_PROCESS_ATTACH", "Called exported function TestPublic." and "DLL_PROCESS_DETACH". I'm going to leave my comments at that, in case my language gets too colorful, lol, having spent 3 days working on something that took about 10 characters of typing to fix.

Thank you very much for your help gentlemen, i will post my working copy in probably about an hour or so, after i've cleaned up this mess i've made here, and incorporate this code into my existing project.

Thanks again guys, Ehtyar.