I have a simple main prog and Im trying to build and link to a dynamic library
using the Gnu Assembler. However, it's not working. Below is what im getting.
$ make
ld -shared libsimple.o -o libsimple.so
ld -L . -e_start -o simple simple.o -lsimple kernel32
ld: cannot find -lsimple
make: *** [simple] Error 1
I am using cygwin under windows XP but I dont think this is the issue as I
can make the main prog without error if im not linking to the library.
Can someone help me with this ?
I'm just trying to get a simple main prog call a function that does nothing but
'ret' inside a DLL/so.
Whilst im on windows I have kept the names as they would appear under
linux. I hope this doesnt confuse the issue.
I'm also calling the source that makes the simple.so/dll 'libsimple'.
My source is below.
Rgs, James.
Makefile
SRC = simple.s libsimple.s
OBJ = simple.o libsimple.o
BIN = simple libsimple
LIBS = simple kernel32
all: $(OBJ) $(BIN)
clean:
rm -f $(OBJ)
rm -f $(BIN)
rm -f *.so
.s.o:
as -g -o $@ $<
simple: simple.o libsimple
ld -L . -e_start -o simple simple.o -l$(LIBS)
libsimple: libsimple.o
ld -shared libsimple.o -o libsimple.so
simple.s
.intel_syntax noprefix
.arch pentium
.global _start
.data
.extern _ExitProcess@4
.extern _myfunc
.text
.align 8
_start:
xor eax, eax
call _myfunc
pushd 0
call _ExitProcess@4
libsimple.s
.intel_syntax noprefix
.arch pentium
.data
.text
myfunc:
xor eax, eax
ret
james,
At the minimum a DLL must have an entry point which is in the form or a LibMain or DllMain. It assumes 3 x 4 bytes are passed on the stack, it must return NON zero in EAX to start and it must balance the stack for the 12 bytes. This should be the first proc in the code.
To build it specifically as a DLL, you must use a linker that does this as it is not performed by the assembler. If you are using LD.EXE you will have to have a wade through the command line options and there are a lot of them. LD --help
LD apparently has a chicken/egg problem in creating a DLL. Using the information here:
http://programming.ccp14.ac.uk/cygnus-gnu-win32/misc/gnu-win32/dll-hints.txt
I was finally able to create the app and the DLL without the tools returning an error, and once I changed _myfunc to return non-zero, the app ran without apparent error (even though balancing the stack did not occur to me).
Apparantly attachments are not working yet.
test.asm
.intel_syntax noprefix
.arch pentium
.global _start
.extern _ExitProcess@4
.extern _myfunc
.data
.text
.align 8
_start:
xor eax, eax
call _myfunc
pushd 0
call _ExitProcess@4
testdll.asm
.intel_syntax noprefix
.arch pentium
.global _myfunc
.data
.text
_myfunc:
;xor eax, eax
mov eax, 1
ret
testdll.dll.def
LIBRARY testdll.dll
EXPORTS
myfunc
makeit.bat
as -o testdll.o testdll.asm
pause
ld --dll -e _myfunc -o jnk --base-file testdll.base testdll.o
pause
dlltool --dllname testdll.dll --base-file testdll.base --def testdll.dll.def --output-lib testdll.dll.a --output-exp testdll.exp
pause
ld --dll -e _myfunc -o testdll.dll testdll.o testdll.exp testdll.base
pause
as -o test.o test.asm
pause
ld -e _start -subsystem console -L C:\masm32\lib -o test.exe test.o testdll.dll.a --library=kernel32
pause
Thanks Hutch and Michael,
I can't believe I forgot LibMain.
I was so busy yesterday with painting a house and moving that I really didnt concentrate.
I'll apply the items here and let you know how I go.
It's 8am and we have a house inspection soon so I have to try this in between cleaning
and moving.
Michael I have tried the process you have outlined and it works without error.
However, when debugging (with DDD) I get a segmentation fault :(
Im also thinking that you had to change myfunc to return non-zero because
as Hutch suggests there needs to be a DllMain and you set the entry point for the
Dll to be _myfunc.
I'll make these changes and see how I go.
Thanks again.
Rgs, James.
Hutch - Balance the stack ?
Quote
At the minimum a DLL must have an entry point which is in the form or a LibMain or DllMain. It assumes 3 x 4 bytes are passed on the stack, it must return NON zero in EAX to start and it must balance the stack for the 12 bytes. This should be the first proc in the code.
Is this what you mean ?
_DllMain:
mov eax, 1
add esp, 12
ret
James,
Must be the first code in the app.
LibMain:
mov eax, 1
ret 12
All of the rest of your code here.
Hutch - You so totally rock !!
That fixed my code right up.
This is what I have now for GAS and it builds a simple file and loads a DLL and calls a function in it.
The function doesnt do much because I just want it to be called and return.
The environment I am using is cygwin under windows XP.
This allows me to use the Gnu Toolchain (Gnu Assembler, ld, objdump, ddd, etc)
and to have my code compile under both windows and linux (it will very soon at least).
Makefile
OBJS = libsimple.o
all: libsimple simple
clean:
rm -f $(OBJS) *.dll *.base *.exp *.temp *.a *.lib *.def
.s.o:
as -g -o $@ $<
libsimple: $(OBJS)
ld --dll -e _DllMain -o $@.temp --base-file $@.base $(OBJS)
ar rc $@.a $(OBJS)
@echo LIBRARY $@ > $@.def
@echo EXPORTS >> $@.def
nm $@.a | grep [TC] | sed '/ _/s// /' | awk '{print $$3;}' >> $@.def
dlltool --dllname $@.dll -b $@.base --def $@.def -l $@.lib -e $@.exp
ld --dll -e _DllMain -o $@.dll $(OBJS) $@.exp
simple: simple.o
ld -e _start -subsystem console -o $@.exe $@.o libsimple.lib --library kernel32
This Makefile creates simple.exe and libsimple.lib and libsimple.dll
It also makes the .DEF file automatically.
libsimple.s
.intel_syntax noprefix
.arch pentium
.global _DllMain
.global _myfunc
.data
.text
_DllMain:
mov eax, 1
ret 12
_myfunc:
xor eax, eax
ret
This is the DLL code which doesnt do much other than export _myfunc which
as you can see, does nothing but return.
simple.s
.intel_syntax noprefix
.arch pentium
.global _start
.data
.extern _ExitProcess@4
.extern _myfunc
.text
.align 8
_start:
xor eax, eax
call _myfunc
pushd 0
call _ExitProcess@4
This is the simple.exe source and it just calls myfunc and thats it.
In linux source files for assembler have a '.s' extension.
My next task will be to make this work under Linux as well as Windows
from the one piece of source. So watch out for some 'ifeq' stuff in
the Makefile
Im currently using 'ddd' to debug the code. THis is a GUI front end to gdb that works
under X-windows. So the same toolchain is being used on both platforms.
All comments welcomed.
Special thanks to Hutch and MichaelW !!!
Rgs, James.
Here is a small example coded with MinGW. It displays a message box on the screen.
testdll.asm :
.intel_syntax noprefix
.global _DllMain
.global _MsgBox
.data
.extern _MessageBoxA@16
caption:
.asciz "Hello!"
.text
_DllMain:
mov eax,1
ret 12
_MsgBox:
push ebp
mov ebp,esp
pushd 0
push OFFSET caption
push DWORD PTR [ebp+8]
pushd 0
call _MessageBoxA@16
leave
ret 4
demo.asm :
.intel_syntax noprefix
.global _start
.data
.extern _ExitProcess@4
.extern _MsgBox
msg:
.asciz "It's a GAS dll"
.text
_start:
push OFFSET msg
call _MsgBox
pushd 0
call _ExitProcess@4
The switch -s is used to strip the symbols to reduce the size of the DLL and EXE
Build.bat :
@echo Build DLL
\mingw\bin\as -o testdll.o testdll.asm
\mingw\bin\ld --dll -L C:\masm32\lib -e _DllMain -o jnk --base-file testdll.base testdll.o --library=user32 -s
\mingw\bin\dlltool --dllname testdll.dll --base-file testdll.base --def testdll.dll.def --output-lib testdll.dll.a --output-exp testdll.exp
\mingw\bin\ld --dll -L C:\masm32\lib -e _DllMain -o testdll.dll testdll.o testdll.exp --base-file testdll.base --library=user32 -s
@echo Build EXE
\mingw\bin\as -o demo.o demo.asm
\mingw\bin\ld -e _start -subsystem windows -L C:\masm32\lib -o demo.exe demo.o testdll.dll.a --library=kernel32 -s
[attachment deleted by admin]
This time, I used Polink to link the object files making the building process more easy :
@echo Build DLL
\mingw\bin\as -o testdll.o testdll.asm
\pellesc\bin\polink /SUBSYSTEM:WINDOWS /DLL /DEF:testdll.dll.def /ENTRY:DllMain testdll.o \pellesc\lib\win\user32.lib
@echo Build EXE
\mingw\bin\as -o demo.o demo.asm
\pellesc\bin\polink /SUBSYSTEM:WINDOWS /ENTRY:start demo.o testdll.lib \pellesc\lib\win\kernel32.lib
test.dll.def modified like the following :
LIBRARY testdll
EXPORTS
_MsgBox
[attachment deleted by admin]
Vortex,
Thanks for your example.
Do you recommend using the -s and does it work if you have -g (debug) set?
Rgs, James.
I never tried the -g debug switch so I cannot tell anything about the effects of -s combined with -g
In my modest opinion, I recommend using the -s switch reducing the size of the final EXE \ DLL
Vortex, Thanks.
The -g switch will generate debug info, so it wont be hard for me to test this
in combination with -s.
My problems seem to have been solved here and in this thread:
http://www.masm32.com/board/index.php?topic=4913.0
Building decorated import library with ld.exe :
\mingw\bin\dlltool -d test.def -l testdll.a
test.def :
LIBRARY testdll.dll
EXPORTS
MsgBox@4=MsgBox
[attachment deleted by admin]