Skip to content

OpenBSD amd64 segfault #624

@namtsui

Description

@namtsui

I am trying to write an OpenBSD port for libretro-flycast. Currently, it segfaults while trying to load Phantasy Star Online.

platform: amd64 x64
retroarch version: 1.7.6, available in OpenBSD packages (I also tested 1.7.8 to the same result)
libretro-flycast version: a4b5ca1

build logs: https://gist.github.com/namtsui/18871b05c33cfd7bd21702b93f1ffa5e

I printed out allocated pages per your suggestion here: #451 (comment)

I was able to confirm that this .cdi loads on Slackware Linux retroarch 1.7.7 with reicast (dc_boot.bin and dc_flash.bin) so the .cdi is not the problem. The game exhibits the same behavior, with and without the bioses, and they should no longer be necessary thanks to your HLE bios.

Any hints would be appreciated. core/libretro/common.cpp looks especially complex. There, I redefined the MCTX macro, as suggested in RPCS3/rpcs3@1a13d3a

sigaction(2):

On OpenBSD, ucontext_t is an alias for the sigcontext structure defined in <signal.h>. The contents of this structure are machine-dependent.

/sys/arch/amd64/include/signal.h:

struct sigcontext {
	/* plain match trapframe */
	long	sc_rdi;
	long	sc_rsi;
	long	sc_rdx;
	long	sc_rcx;
	long	sc_r8;
	long	sc_r9;
	long	sc_r10;
	long	sc_r11;
	long	sc_r12;
	long	sc_r13;
	long	sc_r14;
	long	sc_r15;
	long	sc_rbp;
	long	sc_rbx;
	long	sc_rax;
	long	sc_gs;
	long	sc_fs;
	long	sc_es;
	long	sc_ds;
	long	sc_trapno;
	long	sc_err;
	long	sc_rip;
	long	sc_cs;
	long	sc_rflags;
	long	sc_rsp;
	long	sc_ss;

	struct fxsave64 *sc_fpstate;
	int	__sc_unused;
	int	sc_mask;
	long	sc_cookie;
};

output from attempting to load the game:

[reicast]: Got size: 640 x 480.
Creating dir: /home/namtsui/games/data/roms/retroarch_system/dc/data
Linux paging: 00001000 00001000 00000FFF
MAP 00800000 w/ 25165824
MAP 20000000 w/ 25165824
MAP 04000000 w/ 16777216
MAP 06000000 w/ 16777216
MAP 0C000000 w/ 0
A8
vmem reserve: base: 0x2fec7800000, aram: 0x2fee7800000, vram: 0x2fecb800000, ram: 0x2fed3800000
Resetting mem
DCFlashChip::Validate resetting FLASH_PT_FACTORY
DCFlashChip::Validate resetting FLASH_PT_USER
DCFlashChip::Validate resetting FLASH_PT_GAME
DCFlashChip::Validate resetting FLASH_PT_UNKNOWN
Sh4 Reset
recSh4 Init
@@	ngen_ResetBlocks()
Freeing fpcb
gdrom: Opened image "/home/namtsui/games/data/roms/dreamcast/pso/IVES_PSOV1_US.cdi"
Initializing VMU data...
Initializing VMU data...
Initializing VMU data...
Initializing VMU data...
Sh4 Reset
context_reset.
Allocated 1 PAGES [00000000]
SIGSEGV @ 0x2febcb384b6 ... 0x2febcb81000 -> was not in vram (dyna code 0)
DEBUGBREAK!
SIGSEGV @ 0x2febdb9ffe3 ... 0x2febdb9ffe3 -> was not in vram (dyna code 0)
DEBUGBREAK!

output from gdb:

Starting program: /usr/local/bin/retroarch 
[New thread 466703]
[New thread 203482]
[New thread 442281]
[New thread 189917]

Thread 1 received signal SIGSEGV, Segmentation fault.
0x000004000a6f6daa in bm_GetCode (addr=2684354560)
    at core/hw/sh4/dyna/blockmanager.cpp:47
47	core/hw/sh4/dyna/blockmanager.cpp: No such file or directory.
#0  0x000004000a6f6daa in bm_GetCode (addr=2684354560)
    at core/hw/sh4/dyna/blockmanager.cpp:47
#1  0x00000400096a158f in ngen_mainloop (
    v_cntx=0x400096a158f <ngen_mainloop(void*)+79>)
    at core/rec-x64/rec_x64.cpp:72
#2  0x0000000000000000 in ?? ()
Continuing.

Thread 1 received signal SIGSEGV, Segmentation fault.
0x00000400096ad4b6 in Xbyak::CodeArray::db (this=0x3ff4cb1c520, code=131)
    at ./core/deps/xbyak/xbyak.h:891
891	./core/deps/xbyak/xbyak.h: No such file or directory.
#0  0x00000400096ad4b6 in Xbyak::CodeArray::db (this=0x3ff4cb1c520, code=131)
    at ./core/deps/xbyak/xbyak.h:891
#1  0x00000400096ace92 in Xbyak::CodeGenerator::opModM (this=0x3ff4cb1c520, 
    addr=..., reg=..., code0=130, code1=256, code2=256, immSize=1)
    at ./core/deps/xbyak/xbyak.h:1607
#2  0x00000400096e350b in Xbyak::CodeGenerator::opR_ModM (this=0x3ff4cb1c520, 
    op=..., bit=0, ext=5, code0=130, code1=256, code2=256, disableRex=false, 
    immSize=1) at ./core/deps/xbyak/xbyak.h:1739
#3  0x00000400096e32dd in Xbyak::CodeGenerator::opRM_I (this=0x3ff4cb1c520, 
    op=..., imm=1, code=40, ext=5) at ./core/deps/xbyak/xbyak.h:1793
#4  0x00000400096c5bbd in Xbyak::CodeGenerator::sub (this=0x3ff4cb1c520, 
    op=..., imm=1) at ./core/deps/xbyak/xbyak_mnemonic.h:745
#5  0x00000400096a2f08 in BlockCompilerx64::compile (this=0x3ff4cb1c520, 
    block=0x3ffc4124c00, force_checks=false, reset=false, staging=false, 
    optimise=true) at core/rec-x64/rec_x64.cpp:203
#6  0x00000400096a195e in ngen_Compile_x64 (block=0x3ffc4124c00, 
    force_checks=false, reset=false, staging=false, optimise=true)
    at core/rec-x64/rec_x64.cpp:1222
#7  0x00000400096f4b0d in rdv_CompilePC () at core/hw/sh4/dyna/driver.cpp:229
#8  0x00000400096f4c6e in rdv_FailedToFindBlock (pc=2684354560)
    at core/hw/sh4/dyna/driver.cpp:248
#9  0x00000400096a1516 in ngen_FailedToFindBlock_internal ()
    at core/rec-x64/rec_x64.cpp:36
#10 0x00000400096a1591 in ngen_mainloop (
    v_cntx=0x400096a1591 <ngen_mainloop(void*)+81>)
    at core/rec-x64/rec_x64.cpp:72
#11 0x0000000000000000 in ?? ()
Continuing.

Thread 1 received signal SIGILL, Illegal instruction.
os_DebugBreak () at core/libretro/libretro.cpp:2921
2921	core/libretro/libretro.cpp: No such file or directory.
#0  os_DebugBreak () at core/libretro/libretro.cpp:2921
#1  0x000004000a71a379 in signal_handler (sn=11, si=0x7f7ffffe7660, 
    segfault_ctx=0x7f7ffffe7570) at core/libretro/common.cpp:406
#2  0x000003ff0b366005 in ?? ()
#3  0x0000000000000000 in ?? ()
Continuing.

Thread 5 received signal SIGINT, Interrupt.
[Switching to thread 189917]
futex () at -:3
3	-: No such file or directory.

diffs / changes I made for the port:

$OpenBSD$

Index: Makefile
--- Makefile.orig
+++ Makefile
@@ -14,13 +14,13 @@ HAVE_GL3      := 0
 FORCE_GLES    := 0
 STATIC_LINKING:= 0
 HAVE_TEXUPSCALE := 1
-HAVE_OPENMP   := 1
+HAVE_OPENMP   := 0
 HAVE_CHD      := 1
-HAVE_CLANG    := 0
+HAVE_CLANG    := 1
 HAVE_CDROM    := 0
+DEBUG := 1
 THREADED_RENDERING_DEFAULT := 0
 
-
 TARGET_NAME   := flycast
 
 ifeq ($(HAVE_CLANG),1)
@@ -36,12 +36,12 @@ CC_AS    ?= ${CC_PREFIX}as
 
 MFLAGS   := 
 ASFLAGS  := 
-LDFLAGS  :=
+LDFLAGS  := -L/usr/lib -L/usr/local/lib -L/usr/X11R6/lib
 LDFLAGS_END :=
 INCFLAGS :=
 LIBS     :=
-CFLAGS   := 
-CXXFLAGS :=
+CFLAGS   := -I/usr/include -I/usr/local/include -I/usr/X11R6/include
+CXXFLAGS := -I/usr/include -I/usr/local/include -I/usr/X11R6/include
 
 GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)"
 ifneq ($(GIT_VERSION)," unknown")
@@ -70,6 +70,7 @@ ifeq ($(platform),)
 	ifeq ($(UNAME),)
 		platform = win
 	else ifneq ($(findstring MINGW,$(UNAME)),)
+		ST_CPU = $(HOST_CPU_X64)
 		platform = win
 	else ifneq ($(findstring Darwin,$(UNAME)),)
 		platform = osx
@@ -119,11 +120,8 @@ ifneq (,$(findstring unix,$(platform)))
 	EXT    ?= so
 	TARGET := $(TARGET_NAME)_libretro.$(EXT)
 	SHARED += -shared -Wl,--version-script=link.T
-	LDFLAGS +=  -Wl,--no-undefined
 	ifneq (,$(findstring Haiku,$(shell uname -s)))
 		LIBS += -lroot -lnetwork
-	else
-		LIBS += -lrt
 	endif
 
 	ifneq ($(HAVE_GL2), 1)
@@ -135,7 +133,7 @@ ifneq (,$(findstring unix,$(platform)))
 	HAVE_CDROM = 1
 	fpic = -fPIC
 
-	ifeq ($(WITH_DYNAREC), $(filter $(WITH_DYNAREC), x86_64 x64))
+	ifeq ($(WITH_DYNAREC), $(filter $(WITH_DYNAREC), x86_64 x64 amd64))
 		CFLAGS += -DTARGET_LINUX_x64 -D TARGET_NO_AREC
 		SINGLE_PREC_FLAGS=1
 		CXXFLAGS += -fexceptions
@@ -771,7 +769,7 @@ ifeq ($(ARM_FLOAT_ABI_HARD),1)
 	CFLAGS += -DARM_HARDFP
 endif
 
-ifeq ($(WITH_DYNAREC), $(filter $(WITH_DYNAREC), x86_64 x64))
+ifeq ($(WITH_DYNAREC), $(filter $(WITH_DYNAREC), x86_64 x64 amd64))
 	HOST_CPU_FLAGS = -DHOST_CPU=$(HOST_CPU_X64)
 	HAVE_LTCG = 0
 endif

$OpenBSD$

Index: Makefile.common
--- Makefile.common.orig
+++ Makefile.common
@@ -251,7 +251,7 @@ endif
 
 # Recompiler (x64)
 
-ifneq ($(filter $(WITH_DYNAREC), x86_64 x64),)
+ifneq ($(filter $(WITH_DYNAREC), x86_64 x64 amd64),)
 DYNAREC_USED = 1
 SOURCES_CXX += $(CORE_DIR)/core/rec-x64/rec_x64.cpp 
 # Recompiler (x86 32bit)

$OpenBSD$

Index: core/hw/mem/_vmem.cpp
--- core/hw/mem/_vmem.cpp.orig
+++ core/hw/mem/_vmem.cpp
@@ -680,7 +680,7 @@ bool BM_LockedWrite(u8* address)
 
 	if (addr<sizeof(p_sh4rcb->fpcb))
 	{
-		//printf("Allocated %d PAGES [%08X]\n",++pagecnt,addr);
+		printf("Allocated %d PAGES [%08X]\n",++pagecnt,addr);
 
 #ifdef _WIN32
       verify(VirtualAlloc(address,PAGE_SIZE,MEM_COMMIT,PAGE_READWRITE));

$OpenBSD$

error: use of undeclared identifier 'SOL_TCP'

Index: core/hw/modem/picoppp.cpp
--- core/hw/modem/picoppp.cpp.orig
+++ core/hw/modem/picoppp.cpp
@@ -172,7 +172,7 @@ void set_tcp_nodelay(sock_t fd)
 #if defined(_WIN32)
    struct protoent *tcp_proto = getprotobyname("TCP");
    setsockopt(fd, tcp_proto->p_proto, TCP_NODELAY, (const char *)&optval, optlen);
-#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__)
+#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__)
    setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&optval, optlen);
 #else
    struct protoent *tcp_proto = getprotobyname("TCP");

$OpenBSD$

Index: core/hw/sh4/dyna/driver.cpp
--- core/hw/sh4/dyna/driver.cpp.orig
+++ core/hw/sh4/dyna/driver.cpp
@@ -4,7 +4,7 @@
 #include <windows.h>
 #else
 #include <unistd.h>
-#if defined(__linux__) || defined(__MACH__)
+#if defined(__linux__) || defined(__MACH__) || defined(__OpenBSD__)
 #include <sys/mman.h>
 #endif
 #endif
@@ -34,7 +34,7 @@ u8 SH4_TCB[CODE_SIZE+4096]
 #if defined(_WIN32) || FEAT_SHREC != DYNAREC_JIT
 	;
 #elif defined(__linux__) || defined(__HAIKU__) || \
-      defined(__FreeBSD__) || defined(__DragonFly__)
+      defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
 	__attribute__((section(".text")));
 #elif defined(__MACH__)
 	__attribute__((section("__TEXT,.text")));

$OpenBSD$

sources:
https://svnweb.freebsd.org/ports/head/games/libretro-cores/files/patch-reicast-emulator_core_libretro_common.cpp?revision=434412&view=markup&pathrev=460154
OpenBSD does not have mcontext_t https://github.com/RPCS3/rpcs3/commit/1a13d3ae4e28fc46baef52086c64189f84cf2b9f

Index: core/libretro/common.cpp
--- core/libretro/common.cpp.orig
+++ core/libretro/common.cpp
@@ -10,11 +10,17 @@
 #if !defined(TARGET_NO_EXCEPTIONS)
 #ifndef _WIN32
 #ifndef __HAIKU__
+#ifndef __OpenBSD__
 #include <ucontext.h>
 #endif
 #endif
 #endif
+#endif
 
+#ifdef __OpenBSD__
+#include <signal.h>
+#endif
+
 #if defined(_ANDROID)
 #include <asm/sigcontext.h>
 #endif
@@ -248,7 +254,7 @@ struct rei_host_context_t
 };
 
 
-#define MCTX(p) (((ucontext_t *)(segfault_ctx))->uc_mcontext p)
+#define MCTX(p) (((ucontext_t *)(segfault_ctx)) p)
 
 template <typename Ta, typename Tb>
 static void bicopy(Ta& rei, Tb& seg, bool to_segfault)
@@ -263,7 +269,7 @@ static void context_segfault(rei_host_context_t* reict
 {
 #if !defined(TARGET_NO_EXCEPTIONS)
 #if HOST_CPU == CPU_ARM
-#ifdef __linux__
+#if defined(__linux__)) || defined(__OpenBSD__)
    bicopy(reictx->pc, MCTX(.arm_pc), to_segfault);
    u32* r =(u32*) &MCTX(.arm_r0);
 
@@ -292,6 +298,8 @@ static void context_segfault(rei_host_context_t* reict
 #elif HOST_CPU == CPU_X64
 #ifdef __linux__
    bicopy(reictx->pc, MCTX(.gregs[REG_RIP]), to_segfault);
+#elif defined(__OpenBSD__)
+   bicopy(reictx->pc, MCTX(->sc_rip), to_segfault);
 #elif defined(__MACH__)
    bicopy(reictx->pc, MCTX(->__ss.__rip), to_segfault);
 #endif
@@ -342,7 +350,7 @@ static void sigill_handler(int sn, siginfo_t * si, voi
 #endif
 
 #if defined(__MACH__) || defined(__linux__) || defined(__HAIKU__) || \
-   defined(__FreeBSD__) || defined(__DragonFly__)
+   defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
 //#define LOG_SIGHANDLER
 
 static void signal_handler(int sn, siginfo_t * si, void *segfault_ctx)
@@ -693,7 +701,7 @@ void common_libretro_setup(void)
    ReserveBottomMemory();
 #endif
 
-#if defined(__MACH__) || defined(__linux__)
+#if defined(__MACH__) || defined(__linux__) || defined(__OpenBSD__)
    enable_runfast();
 #endif
 #ifdef _WIN32
@@ -707,7 +715,7 @@ void common_libretro_setup(void)
    signal(SIGINT, exit);
 #endif
 
-#if defined(__MACH__) || defined(__linux__)
+#if defined(__MACH__) || defined(__linux__) || defined(__OpenBSD__)
    printf("Linux paging: %08X %08X %08X\n",sysconf(_SC_PAGESIZE),PAGE_SIZE,SH4_PAGE_MASK);
    verify(SH4_PAGE_MASK==(sysconf(_SC_PAGESIZE)-1));
 #endif

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions