News:

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

DLL exports without .DEF file

Started by jj2007, December 03, 2007, 04:58:11 PM

Previous topic - Next topic

jj2007

I am building a number of DLLs, and would like, out of laziness, to get rid of the .def file:

LIBRARY MyfavouriteDll
EXPORTS TextExp
EXPORTS FunStuff

Apparently, it is possible to do that by using this syntax:

TestExp proc EXPORT Arg1:DWORD, Arg2:DWORD, Arg3:WORD ; results in _TestEx@12
xor eax,eax ; whatever
add esp,12
ret
TestExp endp

The keyword EXPORT after proc tells the linker to export the name of the function.
LIBRARY is not needed, the linker uses the name of the source file, i.e. myfile.asm becomes myfile.dll, which is the desired behaviour.

So far, so fine. But now the problem: In the dll, the name of the exported function TestExp becomes

_TestExp@12

i.e. leading understroke, and @12 indicating the 4*3 bytes of arguments. This name "_TestExp@12" can safely be called using

invoke GetProcAddress, hDll, chr$("_TestExp@12")

That is certainly very informative, but it's ugly. I don't like leading understrokes, and will never understand why Microsoft indulges in using even two or three of them - to prevent ordinary people from understanding their code, probably.

I've checked the documentation and could not find anything explaining this particular behaviour. Can somebody solve the mystery, and point me to a better option? Please don't tell me to use a .def file, as I hate seeing my hard disk cluttered with little files here and there...

Thanxalot :bg

evlncrn8

think you need to put in the calling convention into it too... __stdcall if i remember right

Vortex

Hi jj2007,

Mainly, name mangling like _MessageBoxA@16 is a notation specific to the C++ language informing the linker about the version of the overloaded functions.

You can use Pelle's linker Polink to solve the problem :

\masm32\bin\polink /SUBSYSTEM:CONSOLE /DLL @Exports.txt ConsFuncs.obj

Exports.txt :

/EXPORT:locate /EXPORT:StdOut /EXPORT:ClearScreen /EXPORT:StrLen

Exports.txt is a response file declaring the exported functions.

[attachment deleted by admin]

Vortex

To simplify the task, I patched the object file to undecorate the symbols in the .ndrectve section. ( directive section )
Check the image PatchObjfile.png included in the attachment to see how the method is applied.

[attachment deleted by admin]

jj2007

#4
Hmmmm.... :dazzled:
Maybe I have not fully grasped the concept of "simplifying" - but thanks anyway for showing me the way, Vortex  :bg
So I could not resist the temptation to write a little wrapper. The attached archive has path names - extract to the root of your masm drive (mine is D: ) using folder names.
D:\masm32\VxDemo\ConsFuncs.asm is only slightly modified - look for RUN=demo
D:\masm32\Make_DLL.bat contains my settings - no need to change anything, it will work with other sources, too.
D:\masm32\MAKE_DLL.EXE is the wrapper; create a shortcut, move it to D:\masm32\VxDemo, and drag ConsFuncs.asm over the shortcut.
Strangely enough, ConsFuncs.dll seems to be shorter than in your example; I had to use the standard linker since polink complained about unresolved external symbols _stdout etc.
If the wrapper finds at the end of one of the xxx proc export lines a RUN=whateverfile.exe, the make_dll.bat will execute this file if assembling and linking was ok.

EDIT: Reading helps sometimes. I now realise that Vortex "calls" the DLL by linking it into the asm code, a technique that I have never used and will not be able to grasp at 3:00 in the morning. But I got a GetProcAddress example running - attached ConsFuncs_demo2.zip
What it essentially does is to parse any lines in the asm source containing the string "proc":
- extracts the name of the proc if the EXPORT keyword comes after "proc"
- checks the proc line for an UPPERCASE RUN=MyDemo.exe "with arguments"
- write the EXPORTS to a local TmpDllEx.def definition file, nicely formatted
- and runs the dll_temp.bat

I also changed the wrapper slightly; not it D:\masm32\Make_DLL.bat as a template, replaces the %1 etc args and writes it to disk as Dll_temp.bat, so that the user can see what exactly happens there.


[attachment deleted by admin]

zooba

In one of my projects I wanted to do exactly the same thing. I wrote a substitute PROLOGUE macro that echos the name of every procedure (except DLLMain) to stdout when you build it, wrapped up inside an IFDEF.


IFDEF NAMESOUT
    OPTION PROLOGUE:MyPro
   
    MyPro MACRO procname, flags, argbytes, localbytes, reglist, userparms:VARARG
        IFDIF <procname>,<DLLMain>
            ECHO procname
        ENDIF
        EXITM <1>
    ENDM
ENDIF


I then built using a batch file specific to that project, but the relevant part is here (gle is the project name, and I'm using a response file because I was building with a version that didn't support wildcards on the command line, version 7? I can't remember now):


dir /b *.asm > gle.rsp
\masm32\bin\ml /c /coff /nologo /DNAMESOUT @gle.rsp > functions.list

echo LIBRARY gle > gle.def
echo EXPORTS    >> gle.def
sort < functions.list | find /V " Assembling:" >> gle.def
del functions.list


After this you'll need to build a second time without the /DNAMESOUT setting and then link with the .def file generated.

It's a bit of work to set up, but makes things reasonably simple once you're going.

Cheers,

Zooba :U

donkey

I don't know, it seems to me there is more work to not having a DEF file than the other way around, laziness only pays off if there is less work. The laziest way to do it is to use RadASM, right click the procedure name in the code properties window and select "Add Export" ;)

Another easy way for GoAsm users is like this...

EXPORT MyProc FRAME lParam
    xor eax,eax
    ret
ENDF


GoAsm does not require a DEF file or any special setup, though I generally use a DEF file anyway to make my DLLs more easily translated to MASM.

Donkey
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Mark Jones

Sorry for going a little off-topic but I'm liking GoAsm more and more. Donkey's libraries has made it even more useable (thanks!), however I miss the conditionals of MASM (and tried to make a GoAsm SWITCH/CASE macro to failure) but am thinking GoAsm might still be the best alternative assembler out there. I just love being able to do:


    invoke MessageBox,0,<'Hello World!',13,10,'This is a "nice" feature!',0>,"MessageBox",MB_OK
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

Vortex

QuoteI now realise that Vortex "calls" the DLL by linking it into the asm code, a technique that I have never used and will not be able to grasp at 3:00 in the morning.

jj2007,

Believe, you are using the technique everyday :
This one,
includelib  \masm32\lib\kernel32.lib
and this one :
includelib  ConsFuncs.lib
have no any difference in techical terms. This method is called Load-Time Dynamic Linking.
Calling functions with LoadLibrary refers to the Run-Time Dynamic Linking method.

jj2007

#9
Quote from: donkey on December 04, 2007, 09:46:14 AM
I don't know, it seems to me there is more work to not having a DEF file than the other way around, laziness only pays off if there is less work
I am fighting hard to get the laziest version ever. See attachment - now for DLLs, console and Windows apps.

EDIT: Just discovered an odd behaviour: I always thought batch files worked synchronously, i.e. prog2 waits until prog1 has finished the job. This seems not to be the case: To make this work, insert a PAUSE in StartMe.bat between the two calls to MAKE_ASM.EXE - otherwise A simple dll.asm will assemble to an exe, and the second proggie fails with an error message. Don't ask me why...
In both A simple dll.asm and Demo with GetProcAddress.asm, there is a section in the format

; OPT_RES rsrc.obj ; use if needed
; OPT_SUSY CONSOLE ; Subsystem; default is WINDOWS, use CONSOLE if needed
; OPT_CLEANLST 1 ;lst file is not needed, right?

Make_asm.exe checks for the OPT_ and decides to write an environment variable of the form

set oRes=rsrc.obj
set oSusy=CONSOLE
set oCleanlst=1

to the temporary batch file Dll_temp.bat, which is based on the freely configurable \masm32\Make_asm.txt
So you can define all necessary options directly in the source file. Furthermore, Make_asm.exe checks for <name> proc EXPORT and writes these names to TmpDllEx.def - hence no definition file needed. The system is pretty flexible, and fast, too. Main advantage is that all options can be defined directly in the ASM source, and the batch file behaviour can be tailored to the source.


[attachment deleted by admin]

zooba

Looks quite similar to my own build tool. :bg

It doesn't actually do exports automatically, but the source is included (you'll need ASM Runtime to build it) and it should be easy (relatively) to add it in. I was just reading the source, which I haven't look at in over a year, and it still makes sense, so it must be pretty clear  :toothy

</shameless self promotion>

Cheers,

Zooba :U

jj2007


jj2007

#12
I was restlessly working on my little tool, and decided to make it even more flexible and easy yo use.
With the new version, you can build a dll, GUI or console app directly from the asm source, without definition files, and without a specific makefile. See yourself...
Note this took longer than expected because of the extremely crappy behaviour and documentation of Windows batch files, namely the START, CALL and CMD functions. More in the README.TXT file.
EDIT: Corrected a harmless little bug - please take the second zip.

[attachment deleted by admin]

jj2007

Quote from: zooba on December 04, 2007, 05:46:54 AM
In one of my projects I wanted to do exactly the same thing.
...

dir /b *.asm > gle.rsp
\masm32\bin\ml /c /coff /nologo /DNAMESOUT @gle.rsp > functions.list

echo LIBRARY gle > gle.def
echo EXPORTS    >> gle.def
sort < functions.list | find /V " Assembling:" >> gle.def
del functions.list

Hmmm... I tried this one, but 1. MASM chokes on filenames with spaces, and 2. even without spaces, I get an empty list back using the batch below:

dir /b A_S*.asm > A_simple_dll.rsp
\masm32\bin\ml /c /coff /nologo /DNAMESOUT @A_simple_dll.rsp > functions.list

echo LIBRARY A_simple_dll > A_simple_dll.def
echo EXPORTS    >> A_simple_dll.def
sort < functions.list | find /V " Assembling:" >> A_simple_dll.def
rem del functions.list
pause

functions.list contains a single line:  Assembling: A_simple_dll.asm, same for A_simple_dll.rsp
A_simple_dll.asm has marked the exports like this:

ClearScreen PROC EXPORT    ; from masm32.lib

In the meantime, AsmBuild has learnt to automatically recognise dll, console and win apps, to include resource files, and to tolerate long path and file names with spaces. I tested it on many of the \Masm32\examples, and it works as it should, i.e. opening the *.asm with \Masm32\asmbuild\ASMBUILD.EXE builds the exe or dll without an extra build.bat or *.def file etc.

[attachment deleted by admin]

zooba

jj2007,

Did you include the alternate prologue macro? It needs both of them to work.


IFDEF NAMESOUT
    OPTION PROLOGUE:MyPro
   
    MyPro MACRO procname, flags, argbytes, localbytes, reglist, userparms:VARARG
        IFDIF <procname>,<DLLMain>
            ECHO procname
        ENDIF
        EXITM <1>
    ENDM
ENDIF


Of course, building it into the build system is much cleaner :bg

Cheers,

Zooba :U