When I attach to a process using PTRACE_ATTACH, how do I know whether the tracee is currently in a syscall or not?
When you attach to a process using PTRACE_ATTACH, the tracee is sent a STOP signal.
The STOP signal can take effect while executing userspace code, when entering a syscall, while blocking in a "slow" syscall in kernel, and when returning to userspace from a syscall.
By examining the instruction pointer, and the instructions around the instruction pointer, you can usually determine whether the process was executing userspace code, but that's about it.
However, because the stop point is essentially random, you can wait for the process to stop, then single-step each of its threads using PTRACE_SINGLESTEP, until the instruction pointer changes. Then you know the thread is executing userspace code.
Alternatively, if the singlestep causes the thread to block for a long time, it means the thread is executing a slow system call that is blocking.
Put differently, if I restart the tracee using PTRACE_SYSCALL, how do I know whether the next syscall-stop is a syscall-enter-stop or a syscall-exit-stop?
You don't, unless you know the state where the tracee stopped. As I noted above, you can do that by single-stepping the code, until the instruction pointer changes.