Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 17 Jan 2022 22:31:09 +0000
From:      Damian's Proton Mail <damian@dmcyk.xyz>
To:        Konstantin Belousov <kostikbel@gmail.com>
Cc:        "freebsd-hackers@freebsd.org" <freebsd-hackers@freebsd.org>
Subject:   Re: amd64 syscall ABI (vs. Darwin)
Message-ID:  <94B30813-0034-4F90-9AAC-113402A1A3E8@dmcyk.xyz>
In-Reply-To: <YeVxXdPlmYdwV5PI@kib.kiev.ua>
References:  <Gp_BfNXrv9qjA5V5DpeI-lfdH6EmwKDuqkMLI7DHkses-P6-bT7Ga9p_nURlQC2D4fYuWyf6pFC7s8FPUjWV5Ut7j7uL8iiqx9hv8oePlHs=@dmcyk.xyz> <YeVxXdPlmYdwV5PI@kib.kiev.ua>

next in thread | previous in thread | raw e-mail | index | archive | help

> On 17 Jan 2022, at 14:38, Konstantin Belousov <kostikbel@gmail.com> wrote=
:
>
> On Mon, Jan 17, 2022 at 12:41:59PM +0000, Damian Malarczyk wrote:
>> Hello,
>>
>> I'm hacking on a toy project to run Darwin (MachO) binaries on FreeBSD.
>> Currently I'm at a stage of syscalls support, and I've noticed a differe=
nce in the amd64 ABI that I didn't expect.
>>
>> FreeBSD is changing values of some registers that aren't used as the sys=
call output. e.g., r8-r11 are changed, while r12-r15 don't seem to be affec=
ted.
>> That's not the case on Darwin, from what I've seen onlyrax, rdx used as =
syscall results are changed.
>> It looks like FreeBSD's syscalls calling convention is more like standar=
d function calling, and r8-r11 should be always caller saved.
> It is not 'more like'. FreeBSD follows C ABI for amd64 for syscall
> registers handling. An additional twist is that the registers which are
> declared as calleee-clobered are zeroed to avoid kernel data leakage to
> userspace.
Oh I see, this explains it then.

>>
>> At a first glance Darwin approach seems more optimal, as less registers =
get clobbered. Is there any specific reason why this isn't also the case on=
 FreeBSD?
>> I'm also wondering where exactly the register values are changed. When I=
 look at thetrapframe contents in the sv_set_syscall_retvalsystem vector ca=
llback the r8 register value is same as on the input, so it must be changed=
 somewhere later. Does anyone know where exactly this happens?
>
> Look at the sys/amd64/amd64/exceptions.S.  The fast_syscall entry point
> is where we receive control after the syscall instruction.
A lot of new things in there for me, but the flow is clear. I was able to f=
ind corresponding logic in XNU=E2=80=99s sources too. Earlier I said:

> At a first glance Darwin approach seems more optimal
But it=E2=80=99s instead the opposite/no difference at all, as in Darwin, t=
hey explicitly restore/set all registers, including callee saved r12-r15.

Explicitly preserving registers would prevent kernel data leakage too. Doin=
g so in FreeBSD would also be an ABI compatible change I think, since users=
 shouldn=E2=80=99t rely on values in those registers.
I=E2=80=99m curious if you see any obvious pros/cons with either approach, =
or is it just a more arbitrary implementation choice?

Not that I=E2=80=99d propose changing the ABI though, I also want my toy pr=
oject to work as a plug-in kernel module.
I guess the only other option to emulate Darwin's behaviour would be to int=
ercept syscalls in userspace somehow first and manually preserve the regist=
er values?






Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?94B30813-0034-4F90-9AAC-113402A1A3E8>