Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added suport for Riscv64 architecture #84

Merged
merged 1 commit into from
Feb 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading