0

When inspecting the registers of a Swift iOS function, I did not understand why I could not create a simple mapping of certain arm64 registers to x86/64 registers. I was always looking upon entry to a function.

I tried the following mapping but that did not work.

enter image description here

ANSWERED by @JasonMolenda below.

lldb had convenience $arg variable for this very purpose.

(lldb) reg read $arg5
x4 = 0x0000000000000020

(lldb) po $arg3
1

(lldb) p/x $arg3
(unsigned long) $4 = 0x0000000000000001

Now you don't need to remember the x86/64 to arm64 mappings :o)

rustyMagnet
  • 3,479
  • 1
  • 31
  • 41

1 Answers1

2

If you're just looking at the calling conventions and registers on entry / exit of a function (not in the middle), then yes, those are right for the x86-64 System V calling convention.

See What are the calling conventions for UNIX & Linux system calls on i386 and x86-64 for a summary of the function-calling convention (and see https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI for the full details of the ABI, including how small vs. large structs, and FP values, are passed / returned by value.)

According to https://en.wikipedia.org/wiki/Calling_convention#ARM_(A64), AArch64's standard calling convention passes args in x0..x7, and also returns in x0. (It's not clear from that super-brief summary how large an arg can be returned in registers, whether 16-byte struct could be returned in x1:x0.)


But inside a function, it's totally up to the compiler, and it isn't even trying for similar code-gen.

You're compiling separate binaries for separate architectures. When compiling for x86-64, the compiler probably isn't even trying to make asm that looks anything like AArch64, just to apply the "as-if" rule and make asm that implements the function as efficiently as possible for x86-64.

Different tuning heuristics will lead to different inlining and other code-gen decisions.

AArch64 has more architectural registers than x86-64. Obviously there couldn't be a 1:1 mapping even if you were using an x86-64 compiler that tried to make x86-64 asm that looked like the AArch64 asm for the same function.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 3
    Yeah, the darwin arm64 calling convention is close enough to AAPCS64 for this, that you can refer to that doc. lldb provides convenience variables `$arg1`, `$arg2` etc for targets that pass arguments in registers. These aren't defined on 32-bit i386, for instance, where arguments are passed on the stack. There isn't a convenience alias for the return value register. Peter's answer is a good one that when functions don't have external linkage, a compiler may use an alternate ABI. But I'd start by assuming the standard calling convention is used; if that falls over, look closely at the asm. – Jason Molenda Aug 02 '18 at 21:06
  • Thanks @JasonMolenda. Do you want to change your comment to the answer? That was the answer I was looking for; (lldb) reg read $arg4. These are excellent convenience variables and work whether you are on the simulator or an arm device. – rustyMagnet Aug 06 '18 at 15:35