I was looking at the assembly output of 'objdump -S' and noticed something strange. This was on cygwin/x86_64 v. 3.1.5 with gcc 9.3.0 on Windows 10.
Here is the assembly output of a particular function (the function is not useful and is merely illustrative of the problem):
u_int64_t returnit(u_int64_t x) {
1004010b9: 55 push rbp
1004010ba: 48 89 e5 mov rbp,rsp
1004010bd: 48 83 ec 10 sub rsp,0x10
1004010c1: 48 89 4d 10 mov QWORD PTR [rbp+0x10],rcx
u_int64_t a = 1;
1004010c5: 48 c7 45 f8 01 00 00 mov QWORD PTR [rbp-0x8],0x1
1004010cc: 00
return a + x;
1004010cd: 48 8b 55 f8 mov rdx,QWORD PTR [rbp-0x8]
1004010d1: 48 8b 45 10 mov rax,QWORD PTR [rbp+0x10]
1004010d5: 48 01 d0 add rax,rdx
}
1004010d8: 48 83 c4 10 add rsp,0x10
1004010dc: 5d pop rbp
1004010dd: c3 ret
Almost everything looks normal: set up the stack frame, with extra space for the local variable, and copy the passed argument ("x", in register rcx) to a position on the stack.
Here's the part that seems odd:
mov QWORD PTR [rbp+0x10],rcx
It's copying the contents of rcx OUTSIDE the current stack frame. Local variable(s) are stored in the current stack frame, as they should be.
I tried this on an older installation of cygwin (32-bit, v. 2.9.0 with gcc 6.4.0) and it behaved the same way.
I also tried this on other platforms - an older ubuntu linux liveboot with kernel 4.4.0 and gcc 5.3.1, and a FreeBSD 12.1 box with clang 8.0.1, both 64-bit - and they do what one would expect, copying the value of the argument passed in a register inside the local stack frame. For example, here's the relevant line on FreeBSD (it uses rdi instead of rcx):
2012e8: 89 7d fc mov DWORD PTR [rbp-0x4],edi
Is there some particular reason it's done this way on cygwin?