Calling convention and ecall

656 views
Skip to first unread message

b little

unread,
Jul 15, 2018, 9:05:11 AM7/15/18
to RISC-V ISA Dev
Hi

I'm doing some binary rewriting, and I'm wondering if the calling convention for procedure call applies to ecall (system call).

I don't think the calling convention applies.

From the objdump of of a statically linked executive, I notice that the a2-a7 are used directly without being loaded from the stack.

So it seems that the caller save registers are not saved during ecall.

Does that mean that calling convention does not apply to ecall ?

Thank you

Jim Wilson

unread,
Jul 15, 2018, 11:22:11 AM7/15/18
to b little, RISC-V ISA Dev
On Sun, Jul 15, 2018 at 6:05 AM, b little <ror...@gmail.com> wrote:
> I'm doing some binary rewriting, and I'm wondering if the calling convention
> for procedure call applies to ecall (system call).

System call ABIs may be OS dependent. You didn't mention the OS.

For Linux, we can have up to 6 system call arguments which get passed
in a0 to a5, with the system call number passed in a7. Posix system
calls tend to have simple arguments, pointers and integers, so it is
just one argument per register with no complex cases to worry about.

The newlib/libgloss support uses the same scheme, with the extra
complication that for rv32e support we put the system call number in
t0 because a7 doesn't exist.

> So it seems that the caller save registers are not saved during ecall.

Again, this may be OS dependent. For linux, you call a GNU libc
function, which then makes the ecall, so caller saved registers would
be saved before the glibc function call if necessary.

Jim

b little

unread,
Jul 15, 2018, 11:38:50 AM7/15/18
to RISC-V ISA Dev, ror...@gmail.com

Thank you.

I'm writing the rewriter on fedora. (https://fedoraproject.org/wiki/Architectures/RISC-V)
I'm examining the ecall convention by disassembling a statically linked "hello world" program.

I'm trying to rewrite the ecall with a jump instruction to run some other subroutine and then return back.
I need a register to store the address of the ecall so that the subroutine could jump back to the position of the old ecall.
Hence I need a register that can be overwritten, so I thought I could write to register a2-a6, since if they are caller saved registers then they will be deprecated after the ecall.

But this doesn't seem to be the case from the disassembling of the binary.

I'll keep looking into that.


在 2018年7月15日星期日 UTC+1下午4:22:11,Jim Wilson写道:

Jim Wilson

unread,
Jul 15, 2018, 1:03:57 PM7/15/18
to b little, RISC-V ISA Dev
On Sun, Jul 15, 2018 at 8:38 AM, b little <ror...@gmail.com> wrote:
> I'm trying to rewrite the ecall with a jump instruction to run some other
> subroutine and then return back.
> I need a register to store the address of the ecall so that the subroutine
> could jump back to the position of the old ecall.
> Hence I need a register that can be overwritten, so I thought I could write
> to register a2-a6, since if they are caller saved registers then they will
> be deprecated after the ecall.

An ecall is not the same as a function call in this respect. All
registers must be saved and restored by the OS, so there are no free
caller-saved registers at this point. The only register modified by a
syscall is a0, because this is where the syscall return value is
stored. But since this is also an argument passing register, you
can't put anything in a0 before the syscall.

Depending on register allocation, there might be an available register
at this point, but you would have to disassemble the function code and
track register lifetimes to determine if there is a free register,
which might be more work than you want to do, and there is no
guarantee that there will be a free register to find.

You can perhaps allocate some stack space, store a register on the
stack, use it for the jump address, and then reload the register value
and deallocate the temp stack space when done.

Jim
Reply all
Reply to author
Forward
0 new messages