Reputation: 157
I want to know how the arguments are passed when we call a libc function in C on amd64.
For example, if I call sqrt(double)
, is the argument passed by the stack or by a register?
Upvotes: 2
Views: 877
Reputation: 16133
I've recently created a tool to visualize stack frames of functions, registers usage, memory layout of structured types and other ABI information. You can look at the result for libssh library function ssh_channel_read_timeout on x86_64 here.
Upvotes: 3
Reputation: 16133
Lets write a sample usecase (test.c):
#include <math.h>
int main()
{
double val = sqrt(foo(8));
return 0;
}
double foo(double val)
{
val+=1;
return val;
}
Compile it:
gcc test.c -lm
And then check imported symbols:
readelf -Wa a.out |grep sqrt
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND sqrt@GLIBC_2.2.5 (3)
63: 0000000000000000 0 FUNC GLOBAL DEFAULT UND sqrt@@GLIBC_2.2.5
Disassemble the object:
objdump -d a.out
0000000000400582 <main>:
400582: 55 push %rbp
400583: 48 89 e5 mov %rsp,%rbp
400586: 48 83 ec 10 sub $0x10,%rsp
40058a: f2 0f 10 05 26 01 00 movsd 0x126(%rip),%xmm0
400591: 00
400592: e8 bd ff ff ff callq 400554 <foo>
400597: 66 0f 28 c8 movapd %xmm0,%xmm1
40059b: f2 0f 51 c1 sqrtsd %xmm1,%xmm0
40059f: 66 0f 2e c0 ucomisd %xmm0,%xmm0
4005a3: 7a 06 jp 4005ab <main+0x29>
4005a5: 66 0f 2e c0 ucomisd %xmm0,%xmm0
4005a9: 74 09 je 4005b4 <main+0x32>
4005ab: 66 0f 28 c1 movapd %xmm1,%xmm0
4005af: e8 ac fe ff ff callq 400460 <sqrt@plt>
4005b4: f2 0f 11 45 f8 movsd %xmm0,-0x8(%rbp)
4005b9: b8 00 00 00 00 mov $0x0,%eax
4005be: c9 leaveq
4005bf: c3 retq
So you can see that the argument for sqrt is passed by the %xmm0 register.
Upvotes: 1