GaloisInc / macaw

Open source binary analysis tools.
BSD 3-Clause "New" or "Revised" License
203 stars 20 forks source link

`macaw-ppc-symbolic`: Allow simulating syscalls #387

Closed RyanGlScott closed 2 months ago

RyanGlScott commented 3 months ago

Currently, macaw-symbolic's lookupSyscallHandle memory model operation is wired up to support x86-64 and AArch32, but not PowerPC. We should add support for PowerPC, following the blueprint laid out in https://github.com/GaloisInc/macaw/pull/246.

Note that PPC32 and PPC64 have ever-so-slightly different calling conventions for syscalls, as seen in man 2 syscall:

       Arch/ABI      arg1  arg2  arg3  arg4  arg5  arg6  arg7  Notes
       ──────────────────────────────────────────────────────────────
       powerpc       r3    r4    r5    r6    r7    r8    r9
       powerpc64     r3    r4    r5    r6    r7    r8    -
       Arch/ABI    Instruction           System  Ret  Ret  Error    Notes
                                         call #  val  val2
       ───────────────────────────────────────────────────────────────────
       powerpc     sc                    r0      r3   -    r0       1
       powerpc64   sc                    r0      r3   -    cr0.SO   1

       Notes:

       [1] On  a few architectures, a register is used as a boolean (0 indicating no error,
           and -1 indicating an error) to signal that the system call failed.   The  actual
           error  value is still contained in the return register.  On sparc, the carry bit
           (csr) in the processor status register (psr) is used instead of a full register.
           On powerpc64, the summary overflow bit (SO) in field 0 of the condition register
           (cr0) is used.

Still, these differences are minor enough that we may be able to simply put all of the PowerPC-related syscall information into a single PPCSyscall constructor in PPCPrimFn and do slightly different things with this information depending on whether a PowerPC binary uses 32 bits or 64 bits.

sauclovian-g commented 3 months ago

FWIW, the carry flag is traditional and what's used on almost all older architectures. (Also, when the failure goes in a full register it's not necessarily -1, just nonzero. On mips you'll usually get 1.)

not immediately relevant of course