First of all, thanks for your time investment into reading this garble of mine.
I took the time to consider the right section for this topic, this may or may not be the right place. I also took the time to search instead of taking time to sleep and what is dawning on me is - there are some major misconceptions regarding this matter in my head. I'm not a newbie at MASM, been at it for years now, but I can be a full fledged idiot at times.
Anyway, like the topic title says, I'm trying to use a library written in c (it's the opensource cyassl project) compiled with VC++ 6.0 in my MASM32 project. Basically, this proggie of mine would like to connect via sockets wrapped in ssl to gmail pop3 servers and establish communication.
So, I took the .c and .h files from the cyassl package and placed them into a newly created VC++ 6.0 (library) project. Went into project properties and changed the calling convention to stdcall, the same what is used in my MASM project. The library compiles with no problems. I got the cyassl.lib file and placed it into my MASM project, referenced it with the includelib directive.
This bit of code prototypes the functions I need from the library
SSLv3_client_method PROTO
SSL_CTX_new PROTO method:DWORD
SSL_new PROTO ctx:DWORD
SSL_set_fd PROTO ssl:DWORD,sock:DWORD
SSL_connect PROTO ssl:DWORD
SSL_get_cipher PROTO ssl:DWORD
SSL_write PROTO ssl:DWORD,pReq:DWORD,sizeReq:DWORD
SSL_read PROTO ssl:DWORD,pBuf:DWORD,sizeBuf:DWORD
SSL_shutdown PROTO ssl:DWORD
SSL_free PROTO ssl:DWORD
SSL_CTX_free PROTO ctx:DWORD
SSL_load_error_strings PROTO
SSL_library_init PROTO
Once I build my MASM project I get these (I guess you can guess what follows :bg)
test.obj : error LNK2001: unresolved external symbol _SSLv3_client_method@0
test.obj : error LNK2001: unresolved external symbol _SSL_CTX_new@4
test.obj : error LNK2001: unresolved external symbol _SSL_new@4
test.obj : error LNK2001: unresolved external symbol _SSL_set_fd@8
test.obj : error LNK2001: unresolved external symbol _SSL_connect@4
test.obj : error LNK2001: unresolved external symbol _SSL_write@12
test.obj : error LNK2001: unresolved external symbol _SSL_read@12
test.obj : error LNK2001: unresolved external symbol _SSL_shutdown@4
test.obj : error LNK2001: unresolved external symbol _SSL_free@4
test.obj : error LNK2001: unresolved external symbol _SSL_CTX_free@4
test.obj : error LNK2001: unresolved external symbol _SSL_load_error_strings@0
test.obj : error LNK2001: unresolved external symbol _SSL_library_init@0
Lets take a moment to discuss the SSLv3_client_method function in a bit more detail. This is how the function is defined
CYASSL_METHOD* CyaSSLv3_client_method(void)
{
CYASSL_METHOD* method =
(CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0,
DYNAMIC_TYPE_METHOD);
CYASSL_ENTER("SSLv3_client_method");
if (method)
InitSSL_Method(method, MakeSSLv3());
return method;
}
I tried adding __stdcall in front of the function name and also the extern prefix (not sure if you would even need something like that in a library) but that doesn't change anything. That function is also referenced in the header file
CYASSL_API CYASSL_METHOD *CyaSSLv3_client_method(void);
tried doing the same as above and yet again the library compiles nicely but there is no change as far as MASM build goes.
The only moves in some other direction I managed to make were these:-
1) Change the proto to
SSLv3_client_method PROTO C
then the error thrown while building in MASM is
test.obj : error LNK2001: unresolved external symbol _SSLv3_client_method
2) When compiling the project as C code in VC++ 2008 Express by using __stdcall I managed only to get about 5 times larger library file (?) with the same source code, but nothing besides that changed, the build errors are exactly the same.
Note: as far as I can understand, for c++ code, if you want to keep the function names non mangled you're supposed to add extern "C" prefix to function definitions. But, as this is c code what would be the point of compiling it as c++?
If you wish to inspect any source files, just speak up. I don't think any of my assembly is really relevant here as it compiles nicely.
Again, thanks for your time.
Here is a very simple example calling a C object file from Masm:
.686
.model flat, stdcall
asmprint proto
.code
start:
mov eax, 12345
call asmprint
ret
end start
#include <stdio.h>
void __stdcall asmprint();
void __stdcall asmprint(){
unsigned int veax;
__asm mov veax, eax
printf("The number is %u - cute, isn't it?", veax);
}
Commandline for the C program:
"%ProgramFiles%\Microsoft Visual Studio 9.0\VC\bin\cl.exe" /nologo /Os /c /Zl /Fa /Fp TestAsmC.c
The linker commandline is
/merge:.text=.data \masm32\lib\msvcrt.lib TestAsmC.obj tmp_file.obj
Count the number of understrokes ... :thumbu
Thanks for your reply.
Maybe I missed something, but is there anything I wrote which leads to the assumption that I'm not aware there are two (2) underscores prior to the stdcall? Because it isn't so.
What does the /Os switch do? My cl.exe version does not support that option.
Also, since I'm trying to build a library, am I supposed to use lib.exe instead of link.exe?
My "count the underscores" was half joking. I have never understood why C is so fuzzy with underscores and the like...
In any case: my two snippets work fine together. Are you able to build them?
Link.exe can be used to build a library.
C:\Program Files\Microsoft Visual Studio 10.0\VC\bin>cl /?
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
/Os favor code space
I find it that they just keep adding more underscores to replace the old stuff.
I'm encountering more (of the same, I assume) damned problems. This is what I did.
CYASSL_API CYASSL_METHOD *CyaSSLv3_client_method(void);
CYASSL_METHOD* CyaSSLv3_client_method(void)
{
CYASSL_METHOD* method =
(CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0,
DYNAMIC_TYPE_METHOD);
CYASSL_ENTER("SSLv3_client_method");
if (method)
InitSSL_Method(method, MakeSSLv3());
return method;
}
changed a bit to
CYASSL_METHOD* __stdcall CyaSSLv3_client_method(void);
CYASSL_METHOD* __stdcall CyaSSLv3_client_method(void)
{
CYASSL_METHOD* method =
(CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0,
DYNAMIC_TYPE_METHOD);
CYASSL_ENTER("SSLv3_client_method");
if (method)
InitSSL_Method(method, MakeSSLv3());
return method;
}
CYASSL_API defines the scope of the function, depending on the build type. I think it's safe to just have it replace with what is needed here.
CYASSL_METHOD is the structure name, obviously.
Modified only one function, just to see if I can get it working. That /Os switch is definitively not present, there doesn't seem to be anything like that, either. Anyway, I used this shell script to compile 33 .c files
@echo off
del *.obj
del dir.lst
del cyassl.lib
for %%a in ("*.c") do cl /nologo /c /Zl /Fa /Fp %%a
dir *.obj /b>dir.lst
lib /verbose /subsystem:windows /out:cyassl.lib @dir.lst
the /Os being omitted. I added both paths to the path variable.
It builds the cyassl.lib library out of 33 .obj files, but still I get the same error in MASM.
Could the problem arise from the fact I'm invoking an SSLv3_client_method which is being defined as CyaSSLv3_client_method in the .h file? Apparently, if I invoke CyaSSLv3_client_method instead, I get a
LINK : fatal error LNK1104: cannot open file "uuid.lib"
So it is true, you cannot see past the choices you don't understand.
Yet another edit:
I tried compiling your example with this shell script
@echo off
del *.obj
del code.exe
cl /nologo /c /Zl /Fa /Fp code.c
ml /c /coff /Cp asm.asm
link /subsystem:windows /merge:.text=.data E:\masm32\lib\msvcrt.lib code.obj asm.obj
pause
No go, the app does not start. I'll start my VM XP and try to debug it. The program seems to be working normally, but it doesn't output anything.
Edit 67:
I modified your .c code above a bit, to reflect this
#include <windows.h>
#include <winuser.h>
void __stdcall asmprint();
void __stdcall asmprint(){
MessageBeep(-1);
}
and the compile script accordingly
@echo off
del *.obj
del code.exe
cl /nologo /c /Zl /Fa /Fp code.c
ml /c /coff /Cp asm.asm
link /subsystem:windows /merge:.text=.data E:\masm32\lib\user32.lib code.obj asm.obj
pause
This works normally, the app beeps and exits.
More "development". This also works
.686
.model flat, stdcall
asmprint proto c
.code
start:
mov eax, 12345
call asmprint
ret
end start
Note the proto c definition.
#include <windows.h>
#include <winuser.h>
void asmprint();
void asmprint(){
MessageBeep(-1);
}
No more __stdcall. Now onto the build scripts.
@echo off
cl /nologo /c /Zl /Fa /Fp code.c
ml /c /coff /Cp asm.asm
link /subsystem:windows E:\masm32\lib\user32.lib code.obj asm.obj
pause
"Exe version".
@echo off
cl /nologo /c /Zl /Fa /Fp code.c
lib /verbose /subsystem:windows /out:beep.lib code.obj
ml /c /coff /Cp asm.asm
link /subsystem:windows E:\masm32\lib\user32.lib beep.lib asm.obj
pause
"Lib version". From all of this I gather the blasted cyassl.lib only needs to be built and then finally use the proto c declarations to have the functions properly linked in MASM. But that still isn't happening, I must have done some extremely stupid error somewhere.
two things, look up your compiler notation for its correct form of EXTERN C and make sure the prototyping matches in terms of calling convention (STDCALL or C). From memory you must use the EXERN C notation to avoid C++ name mangling as this will prevent successful cross module calling between MASM and CL.
I don't think that's an issue as this is c code. If you put extern "c" you get a "string" error. I'm compiling this as c code, extern "c" is a c++ thing. Lost good 4-5 hours today while figuring that point out. Also, another fun fact, the VC IDE will compile source files depending on the file extension, disregarding the setting in the project properties. That one killed off a nice part of my sanity allotment for today.
Additionally, both of the above beep.lib examples work as intended, so I have to assume the "proto c" & "void function()" and "proto" & "void __stdcall function()" pairs work as intended in my environment.
Yet another (this time not a repeatable one) problem has surfaced. If I use any of the beep.lib libraries from above in my MASM project, the program refuses to build, it throws me a
LINK : fatal error LNK1104: cannot open file "uuid.lib"
I said OK, I must be losing my mind but OK, I'll just open up another RadASM project, an empty one and try to use this small lib there. Again, the same LNK1104 error. I close RadASM IDE, start it again and suddenly the damned beep.lib allows the project to build, as long as you pair the proto / function declaration in c properly. Probably there was something borked up in the IDE regarding the include libraries and whatnot.
Still no luck on the cyassl.lib front, though. I even tried redefining return function types, the library compiles nicely but the build in MASM still has unresolved external symbols. I know what can probably be done about this, just compile a cyassl.dll and then create a library to go with it, it will work nicely (probably), but that doesn't explain what's going on. After all this pain it would be nice to get a solution.
One more (last probably) update:
I redid the entire cyassl project, used the Pelles package to compile and build; set the __stdcall calling convention in project properties and checked the "Undecorate exported __stdcall functions" option. Still nothing :/
that can probably be done, but not easily by someone new to assembly language
you would have to look at each module and deal with minor issues regarding stack frames, parms, etc
You misunderstood me. I'm not in any way new to assembly and when I say "redid" I mean "taken the source files from the cyassl package, created a new project in Pelles, changed the directory structure and handled some minor issues so that the library compiles normally". It was never my intention to recode the entire library in asm.
Anyway, the damned thing compiles now. What I thought may be the culprit, in fact was; sort of. Since this library is intended to supplement/surpass the OpenSSL library, it just redefines some of their own functions using OpenSSL function names. Example:
#define SSLv3_server_method CyaSSLv3_server_method
For some reason, Pelles IDE/compiler ignore these (there is no conditional defines around those defines, mind you) so I just used the original function names, prefixed with "Cya".
CyaSSLv3_client_method PROTO
CyaSSL_CTX_new PROTO method:DWORD
CyaSSL_new PROTO ctx:DWORD
CyaSSL_set_fd PROTO ssl:DWORD,sock:DWORD
CyaSSL_connect PROTO ssl:DWORD
CyaSSL_get_cipher PROTO ssl:DWORD
CyaSSL_write PROTO ssl:DWORD,pReq:DWORD,sizeReq:DWORD
CyaSSL_read PROTO ssl:DWORD,pBuf:DWORD,sizeBuf:DWORD
CyaSSL_shutdown PROTO ssl:DWORD
CyaSSL_free PROTO ssl:DWORD
CyaSSL_CTX_free PROTO ctx:DWORD
CyaSSL_load_error_strings PROTO
CyaSSL_library_init PROTO
SetErrorString PROTO :DWORD,:DWORD
I also had to add msvcrt.lib, but there are still some external functions the linker doesn't recognize.
cyassl.lib(internal.obj) : error LNK2001: unresolved external symbol ___ftoll
cyassl.lib(dh.obj) : error LNK2001: unresolved external symbol ___ftoll
cyassl.lib(dh.obj) : error LNK2001: unresolved external symbol ___log
cyassl.lib(integer.obj) : error LNK2001: unresolved external symbol ___chkstk
cyassl.lib(integer.obj) : error LNK2001: unresolved external symbol ___llmul
The __ftoll function I can't find anywhere on the web.
The __log is far too general name.
The __chkstk is declared in psxrtl.inc and the corresponding lib, but the inclusion of that library in my MASM project does not solve the problem.
The __llmul function I haven't found neither in the include files.
These functions aren't mentioned in the cyassl source files, neither.
Any light you may shed on these new issues would be greatly appreciated, even more so since it seems I'm rather close to compiling this blasted library.
maybe these are part of the c-compiler initialization routines
with some luck, someone in here may be able to help
i think this is down Clive's ally :P
Quote from: mkey on January 05, 2012, 06:45:16 PM
The __ftoll function I can't find anywhere on the web.
Try tcclib, example at http://pastebin.com/rTiv6CYQ
Well, get that good man over here asap :D
Btw, I used dumpbin on the compiled library, /symbols switch.
009 00000000 UNDEF notype External | ___log
014 00000000 UNDEF notype External | ___ftoll
00B 00000000 UNDEF notype External | ___chkstk
00D 00000000 UNDEF notype External | ___llmul
Not sure what I hoped to find in there, but there it is nevertheless. The /disasm switch fails with a "LINK : warning LNK4195: unable to load MSDIS109.DLL" error even though the dll is present in the bin folder.
EDIT:
jj2007, there is no library in MASM that corresponds to that name. I'll look into creating one.
Maybe I wasn't clear on that point, but the errors above I get when building the MASM project, not while building the library.
EDIT2:
While doing some text searches (lol noobish but effective) I found a few libs that seem to be using/defining __ftoll function, namely
crt.lib
crtmt.lib
pocrt.lib
glaux.lib
I shall dig more.
QuoteLNK4195: unable to load MSDIS109.DLL" error even though the dll is present in the bin folder.
the DLL may have to exist in the path environment variable, as well as in the same folder as LINK
Quote from: mkey on January 05, 2012, 07:05:26 PM
jj2007, there is no library in MASM that corresponds to that name. I'll look into creating one.
Maybe I wasn't clear on that point, but the errors above I get when building the MASM project, not while building the library.
It is the linker complaining, not the assembler. But I see you found the right approach: Binary search on all files in the C folders ;-)
Quote
While doing some text searches (lol noobish but effective) I found a few libs that seem to be using/defining __ftoll function, namely
crt.lib
crtmt.lib
pocrt.lib
glaux.lib
I shall dig more.
dedndave, it is, the MASM32\bin folder, which is on the path :/
Anyway, don't allow me to derail the topic at this point, we cornered this mofo.
jj2007, I know that the assembler is fine with my code, it doesn't check functions in libs :P
Anyway x2, interesting development. In the Pelles bin folder there is this certain pocrt.dll library, dumpbinned it and this is what I got
Dump of file pocrt.dll
File Type: DLL
Section contains the following exports for pocrt.dll
0 characteristics
4DA9C944 time date stamp Sat Apr 16 18:52:20 2011
0.00 version
1 ordinal base
874 number of functions
874 number of names
ordinal hint RVA name
...
4 3 00031A20 ___ftoll
...
17 10 00031EF0 ___llmul
...
66 41 0001CFE0 __log
...
Summary
3000 .data
9000 .rdata
2000 .reloc
1000 .rsrc
3A000 .text
1000 .tls
So, Pelles uses some functions of their own and causes pain to people like me. Only chkstk is missing.
EDIT:
Added
includelib "C:\Program Files (x86)\PellesC\Lib\pocrt.lib"
and the damned think linked lol Let's now see if the library even fits my needs :D If things check out OK, I'll summarize the results and attach a working example in this thread.
Note 1: my exe gained 130kb, now it's a fat bastard.
Note 2: does this mean now I have to distribute pocrt.dll with my app? Sure as hell it does :D
But, you specify only the folder in the path variable, no? And all the mentioned files reside in MASM32\bin dir.
Another option is to include the missing functions in the assembler code via ExternDef and see if they get called, and if yes, if you can simulate them.
This?
includelib "C:\Program Files (x86)\PellesC\Lib\pocrt.lib"
EXTERNDEF __log:far
EXTERNDEF __ftoll:far
EXTERNDEF __chkstk:far
EXTERNDEF __llmul:far
When you say "simulate" do you mean "debug/disassemble the blasted dll and rip the opcodes"? Because that doesn't sound very nice :P
no need to specify a type with EXTERNDEF, as they may be dwords, bytes, or code, or who knows what
they are likely NEAR code
EXTERNDEF __log
EXTERNDEF __ftoll
EXTERNDEF __chkstk
EXTERNDEF __llmul
Well, if I don't specify the type I get this
error A2008: syntax error : in directive
If I use only externdef directive, without the aforementioned lib, the program doesn't build. If I do specify the lib, then externdef directive is not even needed, the program builds nicely. If I'm supposed to write those functions on my own and have them included in my source, it's no problem to do that. But it's very odd to me the compiler would make the library dependent on one of its own dll files. Here I'm talking about the Pelleas compiler and the cyassl.lib I was building.
And still I don't get where is the __chkstk function? It's not in the pocrt.dll but pocrt.lib does define it. I checked my program imports but there is no mention of that function.
EDIT:
Dear lord, it's getting late and I should just stop. I just went through project properties in the Pelles IDE, switching things on and off, trying to trigger something. And it did trigger something, instead of the pocrt.lib and mscrvt.lib now the library asks for crt.lib (or crmt.lib if the library was compiled as multithreaded) when linking in MASM and there is no more dependency for pocrt.dll :/
Even after returning all the project properties at default values, the library compiles and links in ASM properly :D Now I'm trying to break it again lol maybe Pelles can do something with this info.
Quote from: mkey on January 05, 2012, 08:48:38 PM
When you say "simulate" do you mean "debug/disassemble the blasted dll and rip the opcodes"? Because that doesn't sound very nice :P
I agree, copying would not be nice. What I mean is
- insert a
chkstk proc in your assembler code
- put a MsgBox there
- see if it ever gets called (most probably not)
- if no, just leave a stub there
- if yes, check if you can get the same functionality from elsewhere, e.g. a CRT function. Write a wrapper, in other words.
One option is obviously to roll your own chkstk.
Anyway, congrats that you got it working :U
Hi mkey,
Here is how to obtain _chkstk :
First, be sure that you have the following static library : \PellesC\Lib\crt.lib
Now, you need to extract all the member modules from this library :
\PellesC\Bin\polib.exe /explode crt.lib
I have the latest Pelles C development suit and the command above produced 984 MS COFF object modules. One of them is _chkstk.obj
You can link statically this object file with your main project modules. Analyzing this object file :
objconv.exe -fmasm _chkstk.obj _chkstk.asm
The output is :
; Disassembly of file: _chkstk.obj
; Fri Jan 06 20:32:31 2012
; Mode: 32 bits
; Syntax: MASM/ML
; Instruction set: 80386
.386
.model flat
public ___chkstk
_text SEGMENT PARA PUBLIC 'CODE' ; section number 1
___chkstk PROC NEAR
push ecx ; 0000 _ 51
cmp eax, 4096 ; 0001 _ 3D, 00001000
lea ecx, [esp+8H] ; 0006 _ 8D. 4C 24, 08
jc ?_002 ; 000A _ 72, 14
?_001: sub ecx, 4096 ; 000C _ 81. E9, 00001000
sub eax, 4096 ; 0012 _ 2D, 00001000
test dword ptr [ecx], eax ; 0017 _ 85. 01
cmp eax, 4096 ; 0019 _ 3D, 00001000
jnc ?_001 ; 001E _ 73, EC
?_002: sub ecx, eax ; 0020 _ 29. C1
mov eax, esp ; 0022 _ 89. E0
test dword ptr [ecx], eax ; 0024 _ 85. 01
mov esp, ecx ; 0026 _ 89. CC
mov ecx, dword ptr [eax] ; 0028 _ 8B. 08
mov eax, dword ptr [eax+4H] ; 002A _ 8B. 40, 04
push eax ; 002D _ 50
ret ; 002E _ C3
___chkstk ENDP
nop ; 002F _ 90
_text ENDS
END
As you can see, this function does not have any dependency.
You can get objconv from :
http://www.agner.org/optimize/#objconv
Thanks for details, but as you may see there was something off with that build as it linked to Pelles system dlls.
I ran into even more problems with the static library, internal functions failed at odd stages so finally I decided to count my losses and go with a dynamic library. Size is a bit larger now, but it took like half an hour to set up. I'll post here some results of my work, the dll, lib, inc file and a small pop3 mail client which uses ssl (more or less) successfully. That library works nicely, the only problem I had was with certificates as I can't validate any servers I'm connecting to. Still working on that one.
OK, finally got this example ready.
Note that this is very basic stuff, uses blocking sockets and CyaSSL dll to connect to POP3 server over SSL, checks the number of new messages and displays the latest message as raw text. Very, very basic.
- the CyaSSL dll has been compiled from latest CyaSSL package with multithreading off, logging on (uncomment in source to turn logging on) and only client support by means of VC++ 6.0
- the prepared inc file contains only some of the exported functions, the ones I actually used. Consult the CyaSSL source and documentation for more
- certificate checking is off by default, only gmail CA file has been included and it should be working normally. If you want more CA files, add them in cert folder and include in source, check the comments. I haven't mastered the skill to find proper CA files, yet. They can be exported from the browser, but which ones exactly is unclear to me at this point in time
- since this program does not support anything but plain text passwords, it does not work with Hotmail. It does work normally with Gmail, haven't tried any of the other mail services
- the source comes as is, no guarantees, you're free to do with it whatever you like
I'm always open for any questions and suggestions.
Some keywords:
SSL CyaSSL MASM ASM ASSEMBLY LIBRARY