The MASM Forum Archive 2004 to 2012

General Forums => The Workshop => Topic started by: James Ladd on May 26, 2006, 08:34:37 AM

Title: GAS and DLL's please help ...
Post by: James Ladd on May 26, 2006, 08:34:37 AM
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

Title: Re: GAS and DLL's please help ...
Post by: hutch-- on May 26, 2006, 09:13:27 AM
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
Title: Re: GAS and DLL's please help ...
Post by: MichaelW on May 26, 2006, 11:38:16 AM
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

Title: Re: GAS and DLL's please help ...
Post by: James Ladd on May 26, 2006, 10:10:19 PM
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.
Title: Re: GAS and DLL's please help ...
Post by: James Ladd on May 27, 2006, 10:46:01 PM
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

Title: Re: GAS and DLL's please help ...
Post by: hutch-- on May 27, 2006, 11:34:46 PM
James,

Must be the first code in the app.

LibMain:
mov eax, 1
ret 12

All of the rest of your code here.
Title: Re: GAS and DLL's please help ...
Post by: James Ladd on May 28, 2006, 12:34:30 AM
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.
Title: Re: GAS and DLL's please help ...
Post by: Vortex on May 28, 2006, 09:11:44 AM
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]
Title: Re: GAS and DLL's please help ...
Post by: Vortex on May 28, 2006, 06:11:31 PM
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]
Title: Re: GAS and DLL's please help ...
Post by: James Ladd on May 28, 2006, 08:45:10 PM
Vortex,

Thanks for your example.
Do you recommend using the -s and does it work if you have -g (debug) set?

Rgs, James.
Title: Re: GAS and DLL's please help ...
Post by: Vortex on May 29, 2006, 09:54:09 AM
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
Title: Re: GAS and DLL's please help ...
Post by: James Ladd on May 30, 2006, 02:09:06 AM
Vortex, Thanks.
The -g switch will generate debug info, so it wont be hard for me to test this
in combination with -s.
Title: Re: GAS and DLL's please help ...
Post by: James Ladd on June 08, 2006, 01:49:58 AM
My problems seem to have been solved here and in this thread:
http://www.masm32.com/board/index.php?topic=4913.0
Title: Re: GAS and DLL's please help ...
Post by: Vortex on June 08, 2006, 06:37:15 PM
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]