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

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 #15 on: November 28, 2011, 07:20:48 PM »
Hi Zasti,

Well, I replaced allfilters.h with the version you sent me (thanks!). That clears up the problem of the undefined constants. I also created an empty(?) directory where linphone was complaining. Now my output looks like this:

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-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!
Terminating...

(two 't's in "Resetting", but I suspect that's "not your problem")

As you can see, I'm still not getting the output that purports to tell us the address of "decode_asm"... and still no segfault.

Quote
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
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.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Well, that's unexpected!

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

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

If you insist on doing it in decimal, the stack begins at 3221225472 and works down. Shared libraries should load at 1073741824 and up. Unless your shared libraries are going on the stack (highly improbable!), 3078322667 is not the address of decode_asm!

Quote
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 !

Not that strange, it indicates that you've clobbered the stack. C "shouldn't" do that to ya, but it's quite easy to do in asm. If the call to decode_asm returns, the problem is elsewhere.

There's something that happens in your output that's not happening in mine. Right after "a lot of output but not related to the problem". Appears that linphone thinks it's answering a call. If I could simulate that, I might see that output... and maybe a segfault. Any ideas?

Best,
Frank



Offline Zasti

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

>> Well, I replaced allfilters.h with the version you sent me (thanks!). That clears up the problem of the undefined constants. >> I also created an empty(?) directory where linphone was complaining. Now my output looks like this:

Yes, the terminal output looks good..

>> (two 't's in "Resetting", but I suspect that's "not your problem")

Sorry, that's really not my problem but I think, it will not affect the work of the assembler function too..

>> As you can see, I'm still not getting the output that purports to tell us the address of "decode_asm"... and still no segfault.

Look especially at my posting from November 28, 2011, at 08:55:13 am:

You won't get such an error message before calling the decode_asm assembler function. In my posting I told you how to call this function using the libmsg722_init(). That's what you should do to get this error message.

Again; a code example:

// 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);
}

That's enough to see the problem. You don't need to call a phone, that supports g722.

>> If you insist on doing it in decimal, the stack begins at 3221225472 and works down.

Sorry, I will use the hex notation the next time.

>> Shared libraries should load at 1073741824 and up. Unless your shared libraries are going on the stack (highly
>> improbable!), 3078322667 is not the address of decode_asm!

That means, if I follow your words, the address of the decode_asm function is invalid.
This should be true, because the call of the assembler defined function results in an segmentation fault.
But there is no error message that there is a problem to link the object files dynamically together.

I have to think about that problem tomorrow. We have it 10:44 pm and I'm very tired and I have to wake up at 5 o'clock in the morning. Sorry, I'll be back tomorrow.

Again: Thank you for your help !

It's very interesting to find that problem.

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 #17 on: November 28, 2011, 11:54:15 PM »
Okay, get some sleep - we're not going to solve this while overtired! In fact, sometimes I go to bed "stumped" and wake up knowing the answer. Amazing thing, the human mind!

I didn't get that you were telling me to move the call to decode_asm to a different place. I have done that, and thrown in a printf too, showing both "decode_asm" and "*decode_asm". As you say, they're both the same. This surprises me... but there's a lot about C I don't understand!

Quote
...
ortp-message-G.722 decoder registered

ortp-message-G.722 encoder registered

got here! addr=4002d9e0 *=4002d9e0
ortp-message-Plugin loaded (/usr/local/lib/mediastreamer/plugins/libmsg722.so.0.0.0)
ortp-message-ms_init() done
...

The address is about what I'd expect for a shared library, and no segfault either calling decode_asm or returning from the function. I didn't confirm that decode_asm actually returns zero, but... if it returns at all, that's what it'll return.

So what's different? I'm running a funky old 2.4 kernel (Slackware), on a funky old P4 with "only" a half a Gig of memory. As I understand it, you're running in a VM. Could that explain the difference? I dunno. "Works for me!" :)

We may need to look for some "high-powered" help with this.

Best,
Frank


Offline Zasti

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

I reduced the code of mmx.asm to the commands described later in this forum entry.

I think, I found one problem using the decode_asm function.

void libmsg722_init(void)
{
        char temp[200];
        int res = 0;
       
        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

        // This call functions correctly
        decode_asm(NULL, NULL, 0,0,0);
       
        // That is ok too
        ms_message("calling decode_asm %i\n", decode_asm(NULL, NULL, 0, 0, 0));

        // ************* And this produces a crash including a segmentation fault *********************
        res = decode_asm(NULL, NULL, 0, 0, 0);
   
        memset(temp, 0, 200);
   
        sprintf(temp, "result = %i\n", res);
   
        ms_message(temp);   
        // ******************************************************

        // ************* And this produces a crash including a segmentation fault too*********************
        switch(decode_asm(NULL, NULL, 0, 0, 0))
       {
          case 0:
          default:
                     // do something with the return code
                     break;
       }   

        // ******************************************************

}

The file mmx.asm contains nothing more than the following commands:

cpu 586                                                   
bits 32

;'''''''''''''''''''''''''''''''''''''''''''''''''
; exported entry point
;'''''''''''''''''''''''''''''''''''''''''''''''''
global decode_asm:function                            ; declare it as a function
 
section .data

section .bss

section .text

decode_asm:
                          ; setup the return value of the function
      mov eax, dword 0
      ret

That means, eax cannot be transfered to res without producing an segmentation fault.

It seems, that the data areas (int res) of the c-code cannot be accessed when returning from the assembler function.

My knowledge in assembly programming tells me, that the return value of a function should be initialized using register eax.

That's what I did in my code.

The operating system can't transfer the value provided by the eax register to the memory location,
where the value should be stored without producing an segmentation fault. That's a little bit strange.

By the way, the variable res is located inside the stack space, because it is an local variable of the c - program.
If I move that variable to a global space, the effect is the same.

It seems, that the memory spaces of the c - function is protected against accessing, that's why "segmentation fault".
That's something more than a little bit strange.

That's it for the first

Zasti
« Last Edit: November 29, 2011, 02:15:51 PM 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 #19 on: November 29, 2011, 07:12:40 PM »
That is strange indeed!

I first introduced "res" (local - on the stack) and printed it. Then introduced "temp" and sprinted to it, and did the ms_message. Still "works for me". I have not yet tried the switch.

There is something I just noticed, that I should have commented on earlier. Way back on Nov. 12, you posted some asm code that did a get_got_ebx. If we alter ebx in a function that returns to C, we need to restore its original value (push/pop). I don't think you're doing that currently, so I don't think it's an issue, but when/if we get past the current segfault and you return to similar code, you'll want to do that (also esi and edi need to be preserved, if we alter 'em).

Getting back to the present, I think your asm is fine. In the code you post above, you've got "cpu" and "586" on separate lines... well, I guess it depends on how I display it - now it looks fine. Wouldn't assemble that way anyway. I think your asm is fine.

Odd that you're showing the address of decode_asm as being on the stack, and I'm showing it as in the 0x40000000 block, where I'd expect a shared library to be located. I don't know why that is, but it might be a "clue"(?).

C will sometimes put things in read-only memory. For example, printf("hello world");, the "hello world" is in read-only ("const") memory. But "res" ought to be allright, either on the stack or "global" (I think).

In g722/src, after the build, I'm seeing libmsg722_la-msg722.o. I guess that's the output from msg722.c, right? I've looked at that with objdump -d - I'm a little disoriented, but it looks okay(?). Since it "works for me", I guess I wouldn't see anything anyway. I also see an .lo file. I don't know what that is, and objdump doesn't either, apparently. I'm just thinking that it might be helpful to compare objdump output(?).

I dunno, I'm just "thinking out loud". I really don't know where to go next with this...

Best,
Frank


Offline Zasti

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

Thank you for your message !

>> That is strange indeed!

That's it !

>> I first introduced "res" (local - on the stack) and printed it. Then introduced "temp" and sprinted to it, and did the
>> ms_message. Still "works for me". I have not yet tried the switch.

I tried the code, I have already posted; just like the following

; Assembler code

cpu 586                                                   
bits 32

;'''''''''''''''''''''''''''''''''''''''''''''''''
; exported entry point
;'''''''''''''''''''''''''''''''''''''''''''''''''
global decode_asm:function                            ; declare it as a function
 
section .data

section .bss

section .text

decode_asm:

      ; setup the return value of the function
      mov eax, dword 0
      ret

// C - Code

void libmsg722_init(void)
{
        char temp[200];
        int res = 0;
       
        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

        // This call functions correctly
        decode_asm(NULL, NULL, 0,0,0);
       
        // That is ok too
        ms_message("calling decode_asm %i\n", decode_asm(NULL, NULL, 0, 0, 0));

        // ************* And this produces a crash including a segmentation fault *********************
        res = decode_asm(NULL, NULL, 0, 0, 0);
   
        memset(temp, 0, 200);
   
        sprintf(temp, "result = %i\n", res);
   
        ms_message(temp);   
        // ******************************************************

        // ************* And this produces a crash including a segmentation fault too*********************
        switch(decode_asm(NULL, NULL, 0, 0, 0))
       {
          case 0:
          default:
                     // do something with the return code
                     break;
       }   

        // ******************************************************

}

The problem is the same as I described in my last posting from November 28, 2011, 12:16:26 pm.

>> There is something I just noticed, that I should have commented on earlier. Way back on Nov. 12, you posted some asm
>> code that did a get_got_ebx. If we alter ebx in a function that returns to C, we need to restore its original value
>> (push/pop). I don't think you're doing that currently, so I don't think it's an issue, but when/if we get past the current
>> segfault and you return to similar code, you'll want to do that (also esi and edi need to be preserved, if we alter 'em).

That's a good advice and I have to test my code for that kind of problem. Thank you !
But the code I have posted to that forum (shown above) does not contain get_got_ebx
or something like that because I have no variables. Look at the code shown above to be
sure.

>> Getting back to the present, I think your asm is fine. In the code you post above, you've got "cpu" and "586" on separate
>> lines... well, I guess it depends on how I display it - now it looks fine. Wouldn't assemble that way anyway. I think your
>> asm is fine.

Hope so..

>> Odd that you're showing the address of decode_asm as being on the stack, and I'm showing it as in the 0x40000000
>> block, where I'd expect a shared library to be located. I don't know why that is, but it might be a "clue"(?).

You know, I'm running that code using VMWare workstation 7.x. Maybe, the address range could differ to that, what
it would be using the original Linux system !?

>> C will sometimes put things in read-only memory. For example, printf("hello world");, the "hello world" is in read-only
>> ("const") memory. But "res" ought to be allright, either on the stack or "global" (I think).

That is one of my real problems to get the right return value. That doesen't work correctly on my system.
If I have a variable to store the return value of decode_asm there, a segmentation fault follows instantly.
That's one of my problems. I don't know what is the reason that there is a different behavior on different
Linux systems. (Look at the problem to store the return value using a local variable !)

But it's like yesterday: We have 22:59 pm and I'm tired and I have to go to bed. Sorry for that behavior !
I'm just a human..

Again: Thank you for your help !

Zasti


Offline Zasti

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

I have one more question:

Which gcc version do you use when compiling the linphone source ?

Maybe this is the answer to the different behavior of our Linux systems...

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 #22 on: November 30, 2011, 01:25:03 AM »
gcc 4.2.1. That could indeed make a difference. I would have expected that C was pretty much a "solved problem", but different versions of gcc produce very different code. Also, different optimization levels produce very different code. I'm more inclined to blame VMWare for the "problem". These things have one thing in common: they're all supposed to "work". Somewhere along the line, this is apparently not true.

Do you know anybody in the "linphone community" who could test this code for us? Alternatively, are you in a position to install "real Linux" (any distro)? Or, if there's a newer version of VMWare, could you try that? I've been meaning to upgrade my system for quite some time - years - but it hasn't happened yet. Besides, upgrading to get a segfault on code that currently works seems counterproductive! :)

Sleep well. Pleasant dreams. Talk to you later.

Best,
Frank


Offline Zasti

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

Thank you for your comment and help !

My gcc Version is 4.5.1. There is a difference.

But there is another side of that problem:

The process of dynamic linking is executed by the glibc library.

My version of this library is 2.11.3-12.19.1.

Would you be so kind to tell me your installed glibc version, only for comparison.
I have to find the reason because the library works well on your system but on
my system it crashes. There must be a significant difference.

The other side of that problem is that there was a major change in glibc when
changing from kernel 2.4 to kernel 2.6. My current version of the kernel is 2.6.37.6-0.9.
That should be the current version, that is available.

I think, that there is a problem when linking the object files of libmsg722*.o  and mmx.o
together. There is always a problem when I try to call the assembler coded functions.
I think, there must be a problem. Another problem is, that there are no error outputs
while the dynamic linking is in progress.

I have to find a solution for that problem.

Zasti



Offline Zasti

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

I could determine the problem that it is not possible to call decode_asm without getting a segfault.

You have to add the -fpic option to the options of ld when linking mmx.o and the other files to the resulting library.

This option MUST also be defined when using the option -shared.

Now it is possible to call this function and to get the return value without getting a segfault.

The problem to store the return value is also cleared using this option.

I think, it would be a good idea to update the nasm documentation related to this fact.

But I don't want to be happy, I think, there are of course other link problems.

Zasti
« Last Edit: November 30, 2011, 03:02:52 PM by Zasti »

Offline Zasti

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

I have an additional question:

When do I have to define the option  > wrt ..plt <

I want to call the function sprintf defined inside the c-standard library.

When I want to call this function; do I have to append  wrt ..plt to the of the call command ?

When I want to call a function inside the library libmsg722.so.0.0.0; do I have to append  wrt ..plt to the of the call command ?

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 #26 on: December 01, 2011, 04:50:21 AM »
Hi Zasti,

Glad you solved it! "-fpic", huh? Seems that "-shared" would always imply PIC, no? Well, ld is what it is - this isn't the first time Nasm got blamed for an ld bug. Can't really call it a "bug", I guess, more like a "new requirement".

Ordinarily, I'd argue that it isn't the place of the Nasm manual to document ld's switches, but since we mention "-shared" maybe we ought to mention "-fpic". It would be nice to know which versions of ld require both...

My ld version is 2.18. It doesn't seem to require "-fpic" but doesn't complain if I use it. I'd look up versions of those other things, but it doesn't matter - antique!

Out of curiousity, what address do you get for decode_asm when you use the "-fpic" switch?

I don't know when you'd need to use "wrt ..plt". From the friendly manual, I get that you would need to use it if you were calling printf (etc.) from a shared library function. I'm not sure about calling one shared library function from another. Try it, and see what happens...

I'm looking forward to talking to you again!

Best,
Frank


Offline Zasti_2

  • New Member
  • Posts: 1
Re: Calling nasm defined functions out of a c - program in shared libraries
« Reply #27 on: December 01, 2011, 05:22:12 PM »
Hello Frank,

I had to create a new account on your website because I have left the firm yesterday,
where I created an account, so I was formerly known as Zasti. Because of this fact I'm
not longer involved to create the shared library for g722.

>> Glad you solved it! "-fpic", huh? Seems that "-shared" would always imply PIC, no? Well, ld is what it is - this isn't the first >> time Nasm got blamed for an ld bug.

I never wanted to blame nasm, that's really not want I want to do.
I had to use google for lds options and I found on one website that I have to pass these two options.
There are so many google search results for ld options, that it took a long time to find the answer.
Most of the pages do not offer this behavior of command line options.
But now it is cleared.

>> "new requirement"

That's it.

>> Ordinarily, I'd argue that it isn't the place of the Nasm manual to document ld's switches,
>> but since we mention "-shared" maybe we ought to mention "-fpic".
 
That's what I said.
Maybe this is useful for other nasm users.

>> Out of curiousity, what address do you get for decode_asm when you use the "-fpic" switch?

Because I'm not longer involved in creating the shared library for g722, I can't answer your question. Sorry.

Again: Thank you for your help.

Zasti_2 (formerly known as Zasti)
 
« Last Edit: December 01, 2011, 07:59:38 PM by Zasti_2 »

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 #28 on: December 01, 2011, 05:51:31 PM »
Hi Zasti_2,

Too bad you "left the firm" just when you "learned the trick". I hope it was voluntary! (times are tough all over!)

Perhaps you'll have other questions, so perhaps we'll "see you around". Keep well.

Best,
Frank