LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-19-2020, 10:35 PM   #1
dogpatch
Member
 
Registered: Nov 2005
Location: Central America
Distribution: Mepis, Android
Posts: 413
Blog Entries: 4

Rep: Reputation: 181Reputation: 181
Question call c function from assembly in 64 bit mode


Am having a problem with static calls from assembly code to a C function. I suppose the problem is with the different calling conventions between 32 bit and 64 bit compilers. In my case, my home computer is a 32 bit Linux, where everything is working fine. The server where i compile the same program is 64 bit BSD. Am using gcc to compile both the C and assembly code, on both machines.

My principal code is a C program with a number of functions that may be called from a variety of points, sometimes recursively. It also calls a couple of assembly language routines contained in their own source code files, compiled and linked statically.

At a couple of points, i need to call one of the C functions from within the assembly code. Weirdly, the call works fine most of the time, say around 70 or 80 percent of the time, but sometimes fails at the call with a Seg violation or signal 10 (ten), which tech support says is a bus error. I cannot use gdb or other interactive debugging tools, just have to drop a value into a global variable which i can then look at after catching the signal.

The code is far too complex to show here. In simplified form, it goes something like this: The C code in my_program.c:
Code:
int c_function(int);

int main (int argc, char *argv[]) {
int var1 var2, ret_c, ret_a;
ret_c = c_function(var1);
.
.
ret_a = asm_func(var2);
.
.
}

int c_function(int my_var) {
do something here
}
The assembly module (asm_func.S):
Code:
.text
.globl asm_func
  .type    asm_func, @function
asm_func:
.
.
'prologue' and other assembly stuff
. 
.
pushq %rdi
movq a_var,%rdi
call c_function          /* SOMEtimes crashes right here */
popq %rdi
.
.
'epilogue' stuff
ret
The compile instructions in makefile:
Code:
asm_func.o : asm_func.S ;
    gcc -c -Wall asm_func.S -o asm_func.o

my_program : my_program.c asm_func.o ;
    gcc -s my_program.c asm_func.o -o my_program
I may try to write a simple routine (like the above) to try to make the problem occur in such a way as to give better details. Meanwhile, anybody that has experience in doing this sort of thing in 64 bit archtecture, i'd welcome a tip or two. Thanks

Last edited by dogpatch; 05-19-2020 at 10:37 PM.
 
Old 05-20-2020, 01:32 AM   #2
shruggy
Member
 
Registered: Mar 2020
Posts: 994

Rep: Reputation: Disabled
Quote:
Originally Posted by dogpatch View Post
Code:
int c_function(int);
Instead of relying on int that could have different size on different processor architectures, I'd use C99 explicit integer types intn_t here.
 
Old 05-20-2020, 04:46 AM   #3
dogpatch
Member
 
Registered: Nov 2005
Location: Central America
Distribution: Mepis, Android
Posts: 413

Original Poster
Blog Entries: 4

Rep: Reputation: 181Reputation: 181
Thanks, shruggy, but that isn't the problem. The sample code above is a very simplified picture of what my code is actually doing. In reality, i have a number of functions that accept different passed arguments or no arguments, and that produce different sized return values, or no return value. The common factor is that they crash at the call from assembly to a C function. They crash precisely at the call instruction, and intermittently, not all the time. I haven't yet figured out what is different about the failed calls.

Am beginning to suspect that this is a nasty random corruption of memory or of the stack pointer, or something like that, nothing to do with the call itself.

Have worked around the worst case for now, but will have to try at some point to make this happen with some simpler code.
 
Old 05-20-2020, 07:30 AM   #4
EdGr
Member
 
Registered: Dec 2010
Location: California, USA
Distribution: I run my own OS
Posts: 377

Rep: Reputation: 168Reputation: 168
You seem to be aware that the 32-bit and 64-bit x86 calling conventions are completely different.

You have to write completely different assembly code for 32-bits and 64-bits. That the 32-bit code works tells you nothing about the 64-bit code.

You should compile the C function into assembly to study it. Check that the parameters are being passed correctly and that the C function is not clobbering registers used by the caller. Make sure that the upper 32-bits are being preserved. It is easy to write %eax instead of %rax by mistake.

Assembly code should be avoided because there are so many pitfalls. If you must write assembly code, put it inline in a C function so that fewer things can go wrong.
Ed
 
Old 05-20-2020, 08:43 AM   #5
dogpatch
Member
 
Registered: Nov 2005
Location: Central America
Distribution: Mepis, Android
Posts: 413

Original Poster
Blog Entries: 4

Rep: Reputation: 181Reputation: 181
Yes, i am well aware of the difference in calling conventions. The 64-bit calling conventions are actually much simpler. Am also aware of the pitfalls of inter-language coding. But converting the assembly routine to C or in-line assembly is out of the question. Won't go into details right now.

Yes, I have compiled the C function into assembly, and have studied both how the function is coded, and how the function is called from other parts of the C program.

I should emphasize again that the code works in 64 bits as well as in 32 bits. At least, most of the time. Nothing appears to be clobbered at either end. The call instruction itself is where the fault is occuring. This could be because the stack register is somehow corrupted. Or, speaking of the stack, another thought has just occurred to me:

Do i vaguely remember reading somewhere that the stack pointer should be aligned to a 16-byte boundary for 64-bit calls? Can someone at LQ confirm or deny this? This would be something that the compiler would just do correctly as a matter of course within the C code before any call, or at least before an external call. It might also explain why my problem is intermittent, depending upon what the rsp value happens to be at the time the call instruction is executed. Would a poorly aligned stack pointer at a call instruction result in a seg fault or bus error?

At any rate, that may be what i look at next. But not right now. Have been up all night. Maybe i'll check back here again later, much later.
 
Old 05-20-2020, 09:24 AM   #6
EdGr
Member
 
Registered: Dec 2010
Location: California, USA
Distribution: I run my own OS
Posts: 377

Rep: Reputation: 168Reputation: 168
Yes, the stack pointer should be aligned to 16-bytes due to the XMM registers. On x86, misalignment generally results in lower performance. I would align the stack pointer to satisfy the ABI.

I presume that you have inherited a poorly-designed mess of C and assembly. I hope you are being paid well.

ETA: Double-check any use of 32-bit registers in 64-bit code. Writing to a 32-bit register zeros the upper 32 bits.
Ed

Last edited by EdGr; 05-20-2020 at 02:59 PM.
 
2 members found this post helpful.
Old 05-21-2020, 12:15 PM   #7
dogpatch
Member
 
Registered: Nov 2005
Location: Central America
Distribution: Mepis, Android
Posts: 413

Original Poster
Blog Entries: 4

Rep: Reputation: 181Reputation: 181
Aligning the stack pointer to a 16 byte boundary right before the call seems to have fixed the problem. Thanks, EdGr; have given you a reputation point.

(this code isn't really such a mess, but am still a 64-bit noobie, and didn't know about the stack alignment requirement)
 
  


Reply

Tags
'c', 64 bit, assembly, calling conventions


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
•Red Hat Enterprise Linux 5 (UL6+) (32-bit. 64 bit supported in 32-bit mode) download oylf1985 Linux - Newbie 13 04-08-2019 12:55 PM
[SOLVED] A problem. When using assembly language to call the C language function mirage1993 Programming 3 10-03-2014 08:15 AM
[SOLVED] Linux Assembly: write and receive assembly data errigour Programming 2 09-22-2012 09:54 AM
[SOLVED] Threaded function cannot call a function with extern "C" but nonthreaded function can morty346 Programming 16 01-12-2010 05:00 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 06:12 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration