Author Topic: Calling nasm defined functions out of a c - program in shared libraries  (Read 26106 times)

Offline Zasti

  • Jr. Member
  • *
  • Posts: 16
Hello,

OS: openSUSE 11.4 32 Bit (x86)
nasm version: 2.09.10

I have a shared library project, which contains assembler code and C - code.
Out of the C-Code I want to call a function, that coded using nasm. The make
process of this shared library runs without any error message. So, when the
shared libary is loaded using the runtime linker, no error message is outputted
to the terminal. But when I call the asembler coded function, the error output
message indicates an segmentation fault. Testing the object code of the as-
sembler generated object file using objdump shows that the function, called by
the the c - program, is defined as an exported symbol, so there should be no prob-
lems when calling this function. I tried to output the address of the assembler defined
function to call by the c-program. The output was an address different from zero.
It seems, that this pointer points to an address that doesen't contain valid code.
Again, the runtime linker, which is used to link the shared libaries during startup didn't
output any error messages.

I followed the instruction of the nasm documetation strictly an there should be no problem
to call this assembler generated function.

What do I have to do to solve this problem ?

Thanks in advance !

Zasti

Offline Rob Neff

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 429
  • Country: us
Re: Calling nasm defined functions out of a c - program in shared libraries
« Reply #1 on: November 23, 2011, 01:18:58 PM »

The segfault may be due to your misunderstanding of the C calling convention or an invalid pointer to data.
Without seeing your code we can't help you.  Post the snippet of C code which shows the call parameters and the assembler source of the function being called.  That should be enough to get further help.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Calling nasm defined functions out of a c - program in shared libraries
« Reply #2 on: November 23, 2011, 03:29:09 PM »
Hi Zasti,

Is this the same (or similar) code that you posted the other day? You mentioned a command line to ld:

Code: [Select]
ld -shared  -o test.so cobject.o asmobject.so.

Doesn't your output file need to be named "libtest.so"? I hope you know how to create and "activate" a shared library, 'cause I'm real fuzzy on the details... As Rob says, we'll need to see the code - and I'll put in a request for full "make" details, as well...

I got as far as compiling your C code, and your asm code (with an attempt to access your structure added), and linked it to "libzasti.so". As I understand it, I have to copy that to one of the /lib directories in /etc/ld.so.conf, and run ldconfig before I can use it, right?

It wasn't clear to me how to test it. Your caller_function_c_code calls your asm function, but takes no parameters, and returns nothing. How are you testing this?

Looking forward to seeing more code. This is something I really should learn more about!

Best,
Frank


Offline Zasti

  • Jr. Member
  • *
  • Posts: 16
Re: Calling nasm defined functions out of a c - program in shared libraries
« Reply #3 on: November 23, 2011, 05:11:00 PM »
Hello Frank,

the project I'm talking about is an extension to the linphone code v3.4.2. This project is an assembly implementation of G722 audio decoding
using MMX to speed up the decoding process.

I have compiled the G722 codec without any problems using / configure / make / make install
That means, all .o files could be linked together and the result is an file named /usr/local/lib/mediastreamer/plugins/libmsg722.so.0.0.0 .


The procedure to include the assembler code is defined as follows:

Linux is running in an VMWare environment


#!/bin/bash

# copy the asm code to the working directory
cp /mnt/hgfs/LinuxShared/mmx.asm ./mmx.asm

# mmx.asm is the sourcefile including the assembler sourcecode

# call nasm
nasm -f elf ./mmx.asm -o ./mmx.o -l ./mmx.list

# there is no error output when assembling the code

# remove old version
rm -f /usr/src/packages/SOURCES/g722/src/mmx.o

# copy object code to g722/src directory
cp ./mmx.o /usr/src/packages/SOURCES/g722/src/mmx.o

# ./configure for g722 was already executed

# change to g722 directory
cd /usr/src/packages/SOURCES/g722/

make

make install

# add object code to the library
ld -shared -o /usr/local/lib/mediastreamer/plugins/libmsg722.so.0.0.0 ./mmx.o ./src/libmsg722_la-g722_decode.o ./src/libmsg722_la-g722_encode.o ./src/libmsg722_la-msg722.o

Thats all !

But I have to clear the possibility to share the asm code.
I'm not sure, if this is allowed to me.

I think, the creation process of the library is OK.

Offline Zasti

  • Jr. Member
  • *
  • Posts: 16
Re: Calling nasm defined functions out of a c - program in shared libraries
« Reply #4 on: November 24, 2011, 07:28:29 AM »
Hello,

I have tried to call the assembler function without any parameter,
the efect when calling the assembler function is still the same. So
it can't be a problem when accessing the parameter.
The assembler function will never be reached by  the c function call.
When I place an ret instruction after the functions name like this

; Start of sample code

cpu 586                                                   

bits 32

global testfunction:function

section .text

testfunction:

    ret

; End of sample code


there can't be an problem of stack handling or such things, but the
function will never be reached. The function call generates an error
message of segmentation fault. It's like I said yesterday:

The pointer to this assembler function contains invalid data from the
side of the c code. I coded an int 3 statement after the function entry
point, but the breakpoint will never be activated because the function
will never be executed.

Thanks in advance !

Zasti
« Last Edit: November 24, 2011, 07:31:49 AM by Zasti »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Calling nasm defined functions out of a c - program in shared libraries
« Reply #5 on: November 24, 2011, 12:13:39 PM »
I don't know what to tell ya, Zasti. When I get lost, my approach is usually to start with something much simpler, and work back up. To that end, here's "z1.asm":

Code: [Select]
global testfunction:function

section .text
testfunction:
    mov eax, 42
    ret

I assemble this with:

Code: [Select]
nasm -f elf z1.asm

and link it with:

Code: [Select]
ld -shared -o libz1.so z1.o

As root, I copy libz1.so to /lib, and do ldconfig.

Now we need a caller - z1caller.asm:

Code: [Select]
global _start
extern testfunction

section .text
_start:
    call testfunction
    mov ebx, eax
    mov eax, 1
    int 80h

I assemble this with:

Code: [Select]
nasm -f elf z1caller.asm

and link with:

Code: [Select]
ld -o z1caller z1caller.o -I/lib/ld-linux.so.2 -lz1

Running z1caller and doing "echo $?" yields 42, so it appears to be working so far.

I've downloaded the "linphone" code. I got 3.4.3 instead of 3.4.2, but I don't think it makes any difference - it's too complex for me, and I don't see where your proposed code fits into it. I guess what I really want is "G722" anyway(?).

Help me out, here. We have a rudimentary asm function in a shared library which appears to work. What's the next step? Try calling it from C?

From your description, it sounds more like a "C problem" than a "Nasm problem", but I could be wrong...

Best,
Frank


Offline Zasti

  • Jr. Member
  • *
  • Posts: 16
Re: Calling nasm defined functions out of a c - program in shared libraries
« Reply #6 on: November 24, 2011, 02:42:31 PM »
Hello Frank,

Thank you for your help.

The problem is not the code of the c-function, the problem is,
that the call of the assembler defined function does not call the desired function
instead the c-code calls an function, that is not the desired assembler function
and generates an segementation fault.

That is the problem.

Would you be so kind to send me your E-Mail address to to my E-Mail address described in my profile data.

Then I will send you the g722 c-project as an tar.gz file and the
startig point of the assembler code  as an file called mmx.asm.

Because you have already installed linphone (only the command line version -> using  ./configure --enable-gtk_ui=no --enable-video=no),
there should be no problem installing g722 code including the file mmx.asm including the file, which is used to assemble and link install the object files.

That would be very good.

Thanks in advance

Zasti

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Calling nasm defined functions out of a c - program in shared libraries
« Reply #7 on: November 24, 2011, 03:45:11 PM »
fbkotler at myfairpoint dot net

I may not be able to do anything with this - I'm running some pretty obsolete software. I have not "installed" the linphone code, only downloaded it and looked at it (and it's "over my head"!). Still, being able to look at mmx.asm and the code that calls it might(!) give me ideas for something I can test to help you track down the problem...

Best,
Frank


Offline Zasti

  • Jr. Member
  • *
  • Posts: 16
Re: Calling nasm defined functions out of a c - program in shared libraries
« Reply #8 on: November 25, 2011, 01:03:27 PM »
Hello Frank,

I have sent you an email containing the g722 project.

I tried to use ldconfig to update the cache file but the problem is still the same.

Thanks a lot

Zasti

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Calling nasm defined functions out of a c - program in shared libraries
« Reply #9 on: November 26, 2011, 10:35:58 AM »
Well... after installing intltool, gettext, osip2, speex (maybe more), I got stuck on ffmpeg, so I can't build linphone. I don't think I'm going to be able to help you with this. The only thing I can suggest is to look through the pantload of text produced by "ldconfig -v", and make sure your intended library (libmsg722.so.0.0.0) is on the list. I have no explanation for the lack of error messages. Sorry.

Best,
Frank


Offline Zasti

  • Jr. Member
  • *
  • Posts: 16
Re: Calling nasm defined functions out of a c - program in shared libraries
« Reply #10 on: November 26, 2011, 07:35:54 PM »
Hello  Frank,

>> Well... after installing intltool, gettext, osip2, speex (maybe more), I got stuck on ffmpeg,

No problem,

look at my posting from November 24, 2011, 02:42:31 pm

To create linphone from the source level you have to use the following commandline arguments:

./configure --enable-gtk_ui=no --enable-video=no

After that, you don't need to install ffmpeg. There is absolutely no problem.

>> so I can't build linphone. I don't think I'm going to be able to help you with this. The only thing I can suggest is to look
>> through the pantload of text produced by "ldconfig -v", and make sure your intended library (libmsg722.so.0.0.0) is on the >> list.

That's what I already did...

libmsg722.so.0.0.0 is a part of the list. This library could be loaded without any problems. I've sent you a logfile when starting linphone. You can see, that the library could be loaded and initialized without any error messages. You can see, that the address of the assembler function is a valid address. The only problem is, that the call of the assembler function results in a
segmentation fault. This behavior is independent from arguments (given by the c-function) on the stack or the complete code of the assembler function.

>> I have no explanation for the lack of error messages. Sorry.

And I have no explanation for the lack of error messages too. :'(

That's the way it is..

All the best for you

Zasti

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Calling nasm defined functions out of a c - program in shared libraries
« Reply #11 on: November 26, 2011, 09:21:27 PM »
Ah! "--enable...=no". You did tell me that. Sorry, I got disoriened. Okay, that gets "linphone" installed. Then, installing "pkg-config" gets me by "./configure" in g722. But "make" fails like so:

Quote
msg722.c:148: error: 'MS_G722_ENC_ID' undeclared here (not in a function)
msg722.c:469: error: 'MS_G722_DEC_ID' undeclared here (not in a function)
msg722.c:511:2: warning: no newline at end of file
make[2]: *** [libmsg722_la-msg722.lo] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2

If you can hold my hand and walk me past that, maybe I can test this. Whew! Probably just confirm your segfault, without any idea how to fix it., but... Having come this far, I'd really like to help you with this, but I'm afraid it's going to be beyond me.

Best,
Frank


Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Calling nasm defined functions out of a c - program in shared libraries
« Reply #12 on: November 28, 2011, 03:58:49 AM »
Well... I arbitrarily #defined both of those as 1. That got everything(?) built(?) and installed(?) - the ".o" files aren't under "packages" on my machine, so I had to change the ld command from what "do" says, but I think I got it right... but my output differs from yours...

Quote
ortp-message-oRTP-0.16.5 initialized.
ortp-message-Registering all filters...
ortp-message-Registering all soundcard handlers
ortp-message-Card 'ALSA: default device' added
ortp-message-Card 'ALSA: SiS SI7012' added
ortp-message-Card 'OSS: /dev/dsp' added
ortp-message-Card 'OSS: /dev/dsp0' added
ortp-message-Card 'OSS: /dev/dsp1' added
ortp-message-Card 'OSS: /dev/dsp2' added
ortp-message-Card 'OSS: /dev/dsp3' added
ortp-message-Loading plugins
ortp-message-Loading plugin /usr/local/lib/mediastreamer/plugins/libmsg722.so.0.0.0...
ortp-message-G.722 decoder registered

ortp-message-G.722 encoder registered

ortp-message-Plugin loaded (/usr/local/lib/mediastreamer/plugins/libmsg722.so.0.0.0)
ortp-message-ms_init() done
ortp-message-Cannot open directory /usr/local/lib/liblinphone/plugins: No such file or directory
ortp-message-linphone_core_set_playback_gain_db(): no active call.
ortp-message-getaddrinfo returned the following addresses:
ortp-message-0.0.0.0 port 5060
ortp-message-eXosip: Reseting timer to 10s before waking up!
Ready
Warning: video is disabled in linphonec, use -V or -C or -D to enable.
linphonec> ortp-message-New local ip address is 192.168.1.44
ortp-message-Network state is now [UP]
ortp-message-getaddrinfo returned the following addresses:
ortp-message-0.0.0.0 port 5060
ortp-message-eXosip: Reseting timer to 10s before waking up!
ortp-message-keep alive: 0
ortp-message-eXosip: Reseting timer to 10s before waking up!
Terminating...

I should have converted that number in your output that you sent me to hex before! 0xb77d5976 is (I think) a stack address - probably where the real address is stored. How do we get C to do "[]"? Oh yeah, '*', I think. Where you do:

Code: [Select]
// Here follows the output of the address of the decode function
// The value is different to 0
  sprintf(st,"=> id = %u dist = %u adr1 = %u\n", count, dist, (unsigned int) decode_asm);


Try:
Code: [Select]
// Here follows the output of the address of the decode function
// The value is different to 0
  sprintf(st,"=> id = %u dist = %u adr1 = %x\n", count, dist, (unsigned int) *decode_asm);

I haven't tried this, since I don't seem to be getting any output from that file. I would expect 0x40000000+ for a shared library address. Do I have to "get a call" or "make a call" to trigger this, or have I done something wrong? Is that "cannot open directory" my problem?

Anyway... try that '*' and see if you still get a non-zero address...

Best,
Frank


Offline Zasti

  • Jr. Member
  • *
  • Posts: 16
Re: Calling nasm defined functions out of a c - program in shared libraries
« Reply #13 on: November 28, 2011, 08:55:13 AM »
Hello Frank,

For the first:

Again: Thank you for your help !

For the second:

You can see, that the output contains absolutely no error message !

except "Cannot open directory /usr/local/lib/liblinphone/plugins: No such file or directory"

I will comment this problem a little bit later in this forum entry.

For the third:

>> sprintf(st,"=> id = %u dist = %u adr1 = %x\n", count, dist, (unsigned int) *decode_asm);

I think, definitely that is the wrong way !

In the c - programming language a address of a function is defined using the functions name;
that means: (unsigned int) decode_asm
not (unsigned int) *decode_asm.

In your code you would get the first 32 bit value of the code, the function pointer points to.

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Add: I tried all the versions auf calling but the value of the pointer is the same
It doesen't matter if using *decode_asm or decode_asm.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Again:  I think, definitely that is the wrong way !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

For the fourth:

>> I would expect 0x40000000+ for a shared library address.

In my environment the pointer has a value of about 3078322667.

For the fifth:

>> Do I have to "get a call" or "make a call" to trigger this, or have I done something wrong?

In the real world you should do a call to a phone that can handle the G722 mode.

But you don't have to call such an device because you can use the init function
to call decode_asm. You can use a 0 (for pointer arguments NULL) value for all
of the parameters of the function. That is no problem because the function does
absolutely nothing except initializing the return value (0x00000000) in eax.

This init function is declared in msg722.c and the output is shown on the terminal.

********************** code for libmsg722_init **********************
void libmsg722_init(void)
{
        /* no longer required due to official Linphone integration

        payload_type_set_user_data(&payload_type_g722,(void*)9);
        rtp_profile_set_payload(&av_profile, 9, &payload_type_g722);
        ms_message("payload type g722 assigned\n");
        */
       
        ms_filter_register(&ms_g722_dec_desc);
        ms_message("G.722 decoder registered\n");            // first output

        ms_filter_register(&ms_g722_enc_desc);
        ms_message("G.722 encoder registered\n");            // second output
       


        // ****************** my note **************************************
        Here is the right place to call decode_asm because the called function simply does nothing
        except setting up the return value in eax to 0.
 
        The runtime linker has already done its work at the current time.
        So, the function call to decode_asm should be possible without any problems.
        // ***************************************************************

}
**********************************************************

These to messages are outputted by this function:

ortp-message-Loading plugin /usr/local/lib/mediastreamer/plugins/libmsg722.so.0.0.0...
ortp-message-G.722 decoder registered

ortp-message-G.722 encoder registered

ortp-message-Plugin loaded (/usr/local/lib/mediastreamer/plugins/libmsg722.so.0.0.0)
ortp-message-ms_init() done


>> Is that "cannot open directory" my problem?

That is not the problem because the g722 library could be
initialized properly. That means, the runtime linker has done its work properly.
The brown coloured output shows, that the library libmsg722.so.0.0.0 can be
called without any problems. Because you don't call anyone, that is no problem.
The only problem is, that the call of decode_asm results in an segmentation fault.

So, you can call the assembler function after registering encoder
and decoder part of the library.

You can use the purple coloured part of the init function to place a call to decode_asm.

****************************************************************

>> msg722.c:148: error: 'MS_G722_ENC_ID' undeclared here (not in a function)
>> msg722.c:469: error: 'MS_G722_DEC_ID' undeclared here (not in a function)
>> msg722.c:511:2: warning: no newline at end of file
>> make[2]: *** [libmsg722_la-msg722.lo] Error 1
>> make[1]: *** [all-recursive] Error 1
>> make: *** [all] Error 2

I will send you an email that contains all the values needed by linphonec. You have installed the downloaded version
and these values are not defined in this version.

Today I will try to check the address-offsets of the mmx.o file using objdump to find out, if there is something wrong.
If I have a news regarding this problem, I will create a new entry in this forum to let you know about that.

Thank you for your help !

Zasti


« Last Edit: November 28, 2011, 03:54:13 PM by Zasti »

Offline Zasti

  • Jr. Member
  • *
  • Posts: 16
Re: Calling nasm defined functions out of a c - program in shared libraries
« Reply #14 on: November 28, 2011, 02:07:49 PM »
Hello Frank,

I found a special behaviour when returning from the function void libmsg722_init() to call decode_asm.

// example

void libmsg722_init(void)
{       
        ms_filter_register(&ms_g722_dec_desc);
        ms_message("G.722 decoder registered\n");            // first output

        ms_filter_register(&ms_g722_enc_desc);
        ms_message("G.722 encoder registered\n");            // second output

        // I placed the call on this position.       
        decode_asm(NULL, NULL, 0,0,0);

}

For better understanding:

The function decode_asm will only initialize eax using 0 and then
it will return to the caller instantly. No other code will be executed !


Now I found, that the function decode_asm when calling it inside libmsg722_init();
returns to the caller, but libmsg722_init will trigger an segmentation fault when
leaving the function libmsg722_init. A strange behaviour !

Zasti