diff --git a/examples/jit/Makefile b/examples/jit/Makefile new file mode 100644 index 0000000..b030e4c --- /dev/null +++ b/examples/jit/Makefile @@ -0,0 +1,41 @@ +LIBPS4 := $(PS4SDK)/libPS4 + +TEXT := 0x926200000 +DATA := 0x926300000 + +CC := gcc +AS := gcc +OBJCOPY := objcopy +ODIR := build +SDIR := source +IDIRS := -I$(LIBPS4)/include -I. -Iinclude +LDIRS := -L$(LIBPS4) -L. -Llib +CFLAGS := $(IDIRS) -O2 -std=c11 -fno-builtin -nostartfiles -nostdlib -Wall -masm=intel -march=btver2 -mtune=btver2 -m64 -mabi=sysv -mcmodel=large -DTEXT_ADDRESS=$(TEXT) -DDATA_ADDRESS=$(DATA) +SFLAGS := -nostartfiles -nostdlib -march=btver2 -mtune=btver2 +LFLAGS := $(LDIRS) -Xlinker -T $(LIBPS4)/linker.x -Wl,--build-id=none -Ttext=$(TEXT) -Tdata=$(DATA) +CFILES := $(wildcard $(SDIR)/*.c) +SFILES := $(wildcard $(SDIR)/*.s) +OBJS := $(patsubst $(SDIR)/%.c, $(ODIR)/%.o, $(CFILES)) $(patsubst $(SDIR)/%.s, $(ODIR)/%.o, $(SFILES)) + +LIBS := -lPS4 + +TARGET = $(shell basename $(CURDIR)).bin + +$(TARGET): $(ODIR) $(OBJS) + $(CC) $(LIBPS4)/crt0.s $(ODIR)/*.o -o temp.t $(CFLAGS) $(LFLAGS) $(LIBS) + $(OBJCOPY) -O binary temp.t $(TARGET) + rm -f temp.t + +$(ODIR)/%.o: $(SDIR)/%.c + $(CC) -c -o $@ $< $(CFLAGS) + +$(ODIR)/%.o: $(SDIR)/%.s + $(AS) -c -o $@ $< $(SFLAGS) + +$(ODIR): + @mkdir $@ + +.PHONY: clean + +clean: + rm -f $(TARGET) $(ODIR)/*.o diff --git a/examples/jit/source/main.c b/examples/jit/source/main.c new file mode 100644 index 0000000..e56f5b9 --- /dev/null +++ b/examples/jit/source/main.c @@ -0,0 +1,57 @@ +#include "ps4.h" + +int sock; + +#define printf(format, ...)\ + do {\ + char buffer[512];\ + int size = sprintf(buffer, format, ##__VA_ARGS__);\ + sceNetSend(sock, buffer, size, 0);\ + } while(0) + +int _main(void) { + initKernel(); + + initLibc(); + initNetwork(); + initJIT(); + + + struct sockaddr_in server; + + server.sin_len = sizeof(server); + server.sin_family = AF_INET; + server.sin_addr.s_addr = IP(192, 168, 0, 4); + server.sin_port = sceNetHtons(9023); + memset(server.sin_zero, 0, sizeof(server.sin_zero)); + + sock = sceNetSocket("debug", AF_INET, SOCK_STREAM, 0); + sceNetConnect(sock, (struct sockaddr *)&server, sizeof(server)); + + + void *executableAddress = NULL; + void *writableAddress = NULL; + void *dataAddress = NULL; + + allocateJIT(PAGE_SIZE, &executableAddress, &writableAddress); + dataAddress = malloc(PAGE_SIZE); + + printf("Executable address: %p\n", executableAddress); + printf("Writable address: %p\n", writableAddress); + printf("Data address: %p\n", dataAddress); + + sceNetSocketClose(sock); + + + // writableAddress and executableAddress are 2 different virtual mappings, with different protections, but which point to the same physical memory + + + //unsigned char ret[] = { 0xc3 }; + unsigned char loop[] = { 0xeb, 0xfe }; + memcpy(writableAddress, loop, sizeof(loop)); + + ((void (*)())executableAddress)(); + + + return 0; +} diff --git a/libPS4/include/jit.h b/libPS4/include/jit.h new file mode 100644 index 0000000..a94d781 --- /dev/null +++ b/libPS4/include/jit.h @@ -0,0 +1,9 @@ +#pragma once + +extern int (*sceKernelJitCreateSharedMemory)(int flags, size_t size, int protection, int *destinationHandle); +extern int (*sceKernelJitCreateAliasOfSharedMemory)(int handle, int protection, int *destinationHandle); +extern int (*sceKernelJitMapSharedMemory)(int handle, int protection, void **destination); + +void initJIT(void); + +void allocateJIT(size_t size, void **executableAddress, void **writableAddress); diff --git a/libPS4/include/ps4.h b/libPS4/include/ps4.h index c00e665..72ff4a0 100644 --- a/libPS4/include/ps4.h +++ b/libPS4/include/ps4.h @@ -19,3 +19,4 @@ #include "camera.h" #include "pad.h" #include "graphics.h" +#include "jit.h" diff --git a/libPS4/source/jit.c b/libPS4/source/jit.c new file mode 100644 index 0000000..f94c130 --- /dev/null +++ b/libPS4/source/jit.c @@ -0,0 +1,31 @@ +#include "kernel.h" +#include "module.h" +#include "memory.h" + +#include "jit.h" + +int (*sceKernelJitCreateSharedMemory)(int flags, size_t size, int protection, int *destinationHandle); +int (*sceKernelJitCreateAliasOfSharedMemory)(int handle, int protection, int *destinationHandle); +int (*sceKernelJitMapSharedMemory)(int handle, int protection, void **destination); + +void initJIT(void) { + int libkernel; + loadModule("libkernel.sprx", &libkernel); + + RESOLVE(libkernel, sceKernelJitCreateSharedMemory); + RESOLVE(libkernel, sceKernelJitCreateAliasOfSharedMemory); + RESOLVE(libkernel, sceKernelJitMapSharedMemory); +} + +void allocateJIT(size_t size, void **executableAddress, void **writableAddress) { + int executableHandle; + int writableHandle; + + sceKernelJitCreateSharedMemory(0, size, PROT_CPU_READ | PROT_CPU_WRITE | PROT_CPU_EXEC, &executableHandle); + sceKernelJitCreateAliasOfSharedMemory(executableHandle, PROT_CPU_READ | PROT_CPU_WRITE, &writableHandle); + + *executableAddress = mmap(NULL, size, PROT_CPU_READ | PROT_CPU_EXEC, MAP_SHARED, executableHandle, 0); + + //sceKernelJitMapSharedMemory(writableHandle, PROT_CPU_READ | PROT_CPU_WRITE, writableAddress); + *writableAddress = mmap(NULL, size, PROT_CPU_READ | PROT_CPU_WRITE, MAP_PRIVATE | MAP_TYPE, writableHandle, 0); +}