Skip to content

Commit

Permalink
Added suport for Riscv64 architecture
Browse files Browse the repository at this point in the history
  • Loading branch information
Poopi authored and mkozlowski committed Feb 17, 2024
1 parent 0f06cce commit f02aa88
Show file tree
Hide file tree
Showing 10 changed files with 454 additions and 1 deletion.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ ifndef ARCH
ARCH = arm
else ifeq ($(findstring aarch64, $(GCC_TARGET)), aarch64)
ARCH = arm64
else ifeq ($(findstring riscv64, $(GCC_TARGET)), riscv64)
ARCH = riscv64
else
$(error unable to detect arch: $(GCC_TARGET))
endif
Expand All @@ -94,6 +96,8 @@ else ifeq ($(ARCH), arm)
PCFLAGS += -marm
else ifeq ($(ARCH), arm64)
# do nothing
else ifeq ($(ARCH), riscv64)
# do nothing
else
$(error unsupported arch: $(ARCH))
endif
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ make COMPRESS_LZ4=1 CHECKSUM_MD5=1 ENCRYPT=1
```

##### cross compilation
Currently, supported architectures are x86_64, arm and arm64. You can cross compile memcr by providing `CROSS_COMPILE` prefix. i.e.:
Currently, supported architectures are x86_64, arm, arm64 and riscv64. You can cross compile memcr by providing `CROSS_COMPILE` prefix. i.e.:
```
make CROSS_COMPILE=arm-linux-gnueabihf-
make CROSS_COMPILE=aarch64-linux-gnu-
Expand Down
2 changes: 2 additions & 0 deletions arch/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "arm/cpu.h"
#elif defined(__aarch64__)
#include "arm64/cpu.h"
#elif defined(__riscv_xlen)
#include "riscv64/cpu.h"
#else
#error unsupported arch
#endif
Expand Down
70 changes: 70 additions & 0 deletions arch/riscv64/cpu.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright (C) 2023 Mariusz Kozłowski
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, version 2
* of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/

#include <stdio.h>
#include <linux/ptrace.h>
#include <sys/user.h>
#include <assert.h>

#include "../cpu.h"

void set_cpu_regs(struct registers *regs, unsigned long *pc, unsigned long arg0, unsigned long arg1)
{
regs->pc = (unsigned long)pc; /* point to the injected blob */
regs->s6 = arg0; /* s6 used as arg0 to blob */
regs->s7 = arg1; /* s7 used as arg1 to blob */
}

void *get_cpu_regs_sp(struct registers *regs)
{
return (void *)regs->sp;
}

void *get_cpu_regs_pc(struct registers *regs)
{
return (void *)regs->pc;
}

unsigned long get_cpu_syscall_ret(struct registers *regs)
{
return regs->a0;
}

#if 0
unsigned long get_cpu_syscall_arg0(struct registers *regs)
{
return regs->x10;
}
#endif

void print_cpu_regs(struct registers *regs)
{
int idx;
const char *rg_names[] = {
"pc", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
"s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
"a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7",
"s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"
};

for (idx = 0; idx < sizeof(*regs)/sizeof(regs->pc); idx++) {
fprintf(stdout, "regs[%s]\t %0*lx\n", rg_names[idx], 2 * (int)sizeof(unsigned long), ((unsigned long *)regs)[idx]);
}
}

static_assert(sizeof(struct registers) == sizeof(struct user_regs_struct), "struct registers size mismatch");
52 changes: 52 additions & 0 deletions arch/riscv64/cpu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2023 Mariusz Kozłowski
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, version 2
* of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/

struct registers {
unsigned long pc;
unsigned long ra;
unsigned long sp;
unsigned long gp;
unsigned long tp;
unsigned long t0;
unsigned long t1;
unsigned long t2;
unsigned long s0;
unsigned long s1;
unsigned long a0;
unsigned long a1;
unsigned long a2;
unsigned long a3;
unsigned long a4;
unsigned long a5;
unsigned long a6;
unsigned long a7;
unsigned long s2;
unsigned long s3;
unsigned long s4;
unsigned long s5;
unsigned long s6;
unsigned long s7;
unsigned long s8;
unsigned long s9;
unsigned long s10;
unsigned long s11;
unsigned long t3;
unsigned long t4;
unsigned long t5;
unsigned long t6;
};
119 changes: 119 additions & 0 deletions arch/riscv64/enter.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* Copyright (C) 2023 Mariusz Kozłowski
* Copyright (C) 2024 Wojciech Łazarski
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, version 2
* of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/

#include <signal.h>
#include <sys/mman.h>
#include <linux/sched.h>

#include <string.h>


static void __attribute__((used)) container(void)
{
/*
* Upon completion, each blob triggers debug trap to pass the
* control back to the main program.
*/

/* rt_sigprocmask(), expects pointer to area for masks in a6 */

asm volatile(
".global sigprocmask_blob \n"
".align 3 \n"
"sigprocmask_blob: \n"
"li a7, 135 \n" /* __NR_rt_sigprocmask */
"li a0, %0 \n" /* @how */
"mv a1, s6 \n" /* @nset */
"mv a2, s6 \n" /* @oset */
"li a3, 8 \n" /* @sigsetsize */
"ecall \n"
"ebreak \n" /* SIGTRAP */
".global sigprocmask_blob_size \n"
".align 3 \n"
"sigprocmask_blob_size: \n"
".int sigprocmask_blob_size - sigprocmask_blob \n"
:: "i" (SIG_SETMASK)
);

/* mmaps anon area for parasite_blob */
asm volatile(
".global mmap_blob \n"
".align 3 \n"
"mmap_blob: \n"
"li a7, 222 \n" /* __NR_mmap2 */
"li a0, 0 \n" /* @addr */
"mv a1, s6 \n" /* @len */
"li a2, %0 \n" /* @prot */
"li a3, %1 \n" /* @flags */
"li a4, -1 \n" /* @fd */
"li a5, 0 \n" /* @off */
"ecall \n"
"ebreak \n" /* SIGTRAP */
".global mmap_blob_size \n"

".align 3 \n"
"mmap_blob_size: \n"
".int mmap_blob_size - mmap_blob \n"
:: "i" (PROT_EXEC | PROT_READ | PROT_WRITE),
"i" (MAP_ANONYMOUS | MAP_PRIVATE)
);

/* clones parasite, expects parasite address in a6 */
asm volatile(
".global clone_blob \n"
".align 3 \n"
"clone_blob: \n"
"li a7, 220 \n" /* __NR_clone */
"ld a0, CLONE_FLAGS \n" /* @flags */
"li a1, 0 \n" /* @newsp */
"li a2, 0 \n" /* @parent_tid */
"li a3, 0 \n" /* @child_tid */
"ecall \n"
"li a1, 0 \n"
"beq a0, a1, .child \n"
"ebreak \n" /* SIGTRAP */
".child: \n"
"jr s6 \n" /* br parasite */
"CLONE_FLAGS: \n"
".quad (%0 & 0xffffffff) \n" /* zero high .word */
".global clone_blob_size \n"
"clone_blob_size: \n"

".align 3 \n"
".int clone_blob_size - clone_blob \n"
:: "i" (CLONE_FILES | CLONE_FS | CLONE_IO | CLONE_SIGHAND | CLONE_SYSVSEM | CLONE_THREAD | CLONE_VM)
);

/* munmap anon area for parasite_blob, expects addr in a6 and len in a7 */
asm volatile(
".global munmap_blob \n"
".align 3 \n"
"munmap_blob: \n"
"li a7, 215 \n" /* __NR_munmap */
"mv a0, s6 \n" /* @addr */
"mv a1, s7 \n" /* @len */
"ecall \n"
"ebreak \n" /* SIGTRAP */
".global munmap_blob_size \n"

".align 3 \n"
"munmap_blob_size: \n"
".int munmap_blob_size - munmap_blob \n"
);
}
Loading

0 comments on commit f02aa88

Please sign in to comment.