add Linux support

This commit is contained in:
InoriRus
2022-10-03 15:33:23 +10:00
parent e427645422
commit 37b020e9ba
69 changed files with 2716 additions and 971 deletions
+37
View File
@@ -0,0 +1,37 @@
#!/bin/bash
PS3='Please enter your choice: '
options=("Debug" "Debug Final" "Release" "Release Final" "Exit")
select opt in "${options[@]}"
do
case $opt in
"Debug")
DirName=_DebugLinuxEclipseNinjaClang
Options="-DCMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES=FALSE -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -D CMAKE_BUILD_TYPE=Debug -D CMAKE_INSTALL_PREFIX=_bin ../../source"
;;
"Debug Final")
DirName=_DebugFinalLinuxEclipseNinjaClang
Options="-DCMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES=FALSE -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -D CMAKE_BUILD_TYPE=Debug -D KYTY_FINAL=1 -D CMAKE_INSTALL_PREFIX=_bin ../../source"
;;
"Release")
DirName=_ReleaseLinuxEclipseNinjaClang
Options="-DCMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES=FALSE -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=_bin ../../source"
;;
"Release Final")
DirName=_ReleaseFinalLinuxEclipseNinjaClang
Options="-DCMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES=FALSE -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -D CMAKE_BUILD_TYPE=Release -D KYTY_FINAL=1 -D CMAKE_INSTALL_PREFIX=_bin ../../source"
;;
esac
break
done
if [ -z "$DirName" ]; then
exit
fi
mkdir $DirName
cd $DirName
echo ninja >_build
echo ninja install/strip >>_build
chmod +x _build
cmake -G "Eclipse CDT4 - Ninja" $Options
+37
View File
@@ -0,0 +1,37 @@
#!/bin/bash
PS3='Please enter your choice: '
options=("Debug" "Debug Final" "Release" "Release Final" "Exit")
select opt in "${options[@]}"
do
case $opt in
"Debug")
DirName=_DebugLinuxMakeGcc
Options="-DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -D CMAKE_BUILD_TYPE=Debug -D CMAKE_INSTALL_PREFIX=_bin ../../source"
;;
"Debug Final")
DirName=_DebugFinalLinuxMakeGcc
Options="-DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -D CMAKE_BUILD_TYPE=Debug -D KYTY_FINAL=1 -D CMAKE_INSTALL_PREFIX=_bin ../../source"
;;
"Release")
DirName=_ReleaseLinuxMakeGcc
Options="-DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=_bin ../../source"
;;
"Release Final")
DirName=_ReleaseFinalLinuxMakeGcc
Options="-DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -D CMAKE_BUILD_TYPE=Release -D KYTY_FINAL=1 -D CMAKE_INSTALL_PREFIX=_bin ../../source"
;;
esac
break
done
if [ -z "$DirName" ]; then
exit
fi
mkdir $DirName
cd $DirName
echo make >_build
echo make install/strip >>_build
chmod +x _build
cmake -G "Unix Makefiles" $Options
+1 -1
View File
@@ -1,4 +1,4 @@
version: 0.2.1.build-{build} version: 0.2.2.build-{build}
image: Visual Studio 2019 image: Visual Studio 2019
environment: environment:
matrix: matrix:
+82 -30
View File
@@ -1,45 +1,97 @@
file(GLOB cpuinfo_src set(cpuinfo_src
src/init.c src/init.c
src/api.c src/api.c
src/cache.c src/cache.c
src/x86/init.c deps/clog/src/clog.c
src/x86/info.c
src/x86/vendor.c
src/x86/uarch.c
src/x86/name.c
src/x86/topology.c
src/x86/isa.c
src/x86/cache/init.c
src/x86/cache/descriptor.c
src/x86/cache/deterministic.c
src/x86/windows/init.c
deps/clog/src/clog.c
) )
if (MINGW) if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(i[3-6]86|AMD64|x86(_64)?)$")
if (CLANG) list(APPEND cpuinfo_src
set_source_files_properties(${cpuinfo_src} PROPERTIES COMPILE_FLAGS "-Wno-unused-variable -Wno-implicit-function-declaration") src/x86/init.c
src/x86/info.c
src/x86/vendor.c
src/x86/uarch.c
src/x86/name.c
src/x86/topology.c
src/x86/isa.c
src/x86/cache/init.c
src/x86/cache/descriptor.c
src/x86/cache/deterministic.c)
if(LINUX OR ANDROID)
list(APPEND cpuinfo_src src/x86/linux/init.c src/x86/linux/cpuinfo.c)
else() else()
set_source_files_properties(${cpuinfo_src} PROPERTIES COMPILE_FLAGS "-Wno-maybe-uninitialized -Wno-unused-variable -Wno-implicit-function-declaration -Wno-format -Wno-format-extra-args") list(APPEND cpuinfo_src src/x86/windows/init.c)
endif() endif()
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv[5-8].*|aarch64|arm64)$")
list(APPEND cpuinfo_src src/arm/uarch.c src/arm/cache.c)
if(LINUX OR ANDROID)
list(APPEND cpuinfo_src
src/arm/linux/init.c
src/arm/linux/cpuinfo.c
src/arm/linux/clusters.c
src/arm/linux/chipset.c
src/arm/linux/midr.c
src/arm/linux/hwcap.c)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^armv[5-8]")
list(APPEND cpuinfo_src src/arm/linux/aarch32-isa.c)
if(ANDROID AND ANDROID_ABI STREQUAL "armeabi")
set_source_files_properties(src/arm/linux/aarch32-isa.c PROPERTIES COMPILE_FLAGS -marm)
endif()
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64)$")
list(APPEND cpuinfo_src src/arm/linux/aarch64-isa.c)
endif()
endif()
if(ANDROID)
list(APPEND cpuinfo_src src/arm/android/properties.c)
endif()
endif() endif()
if (MSVC) if(LINUX OR ANDROID)
if (CLANG) list(APPEND cpuinfo_src
set_source_files_properties(${cpuinfo_src} PROPERTIES COMPILE_FLAGS "-Wno-unused-variable -Wno-deprecated-declarations -Wno-implicit-function-declaration") src/linux/smallfile.c
else() src/linux/multiline.c
set_source_files_properties(${cpuinfo_src} PROPERTIES COMPILE_FLAGS "") src/linux/cpulist.c
endif() src/linux/processors.c)
endif()
if (LINUX)
set_source_files_properties(${cpuinfo_src} PROPERTIES COMPILE_FLAGS "-D_GNU_SOURCE=1")
endif() endif()
include_directories(include src deps/clog/include) include_directories(include src deps/clog/include)
#add_library(cpuinfo STATIC ${cpuinfo_src}) add_library(cpuinfo STATIC ${cpuinfo_src})
add_library(cpuinfo_obj OBJECT ${cpuinfo_src})
add_library(cpuinfo STATIC $<TARGET_OBJECTS:cpuinfo_obj>) if (MINGW)
if (CLANG)
target_compile_options(cpuinfo PRIVATE -Wno-unused-variable -Wno-implicit-function-declaration)
else()
target_compile_options(cpuinfo PRIVATE -Wno-maybe-uninitialized -Wno-unused-variable -Wno-implicit-function-declaration -Wno-format -Wno-format-extra-args)
endif()
elseif (LINUX)
if (CLANG)
else()
target_compile_options(cpuinfo PRIVATE -Wno-unused-result)
endif()
elseif (MSVC)
if (CLANG)
target_compile_options(cpuinfo PRIVATE -Wno-unused-variable -Wno-deprecated-declarations -Wno-implicit-function-declaration)
else()
endif()
elseif(ANDROID)
target_compile_options(cpuinfo PRIVATE -Wno-implicit-function-declaration)
endif()
target_include_directories(cpuinfo PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") target_include_directories(cpuinfo PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_include_directories(cpuinfo_obj PRIVATE $<TARGET_PROPERTY:cpuinfo,INTERFACE_INCLUDE_DIRECTORIES>)
+8 -4
View File
@@ -1,5 +1,5 @@
file(GLOB easy_profiler_src file(GLOB easy_profiler_src
src/base_block_descriptor.cpp src/base_block_descriptor.cpp
src/block.cpp src/block.cpp
src/block_descriptor.cpp src/block_descriptor.cpp
src/easy_socket.cpp src/easy_socket.cpp
@@ -20,9 +20,13 @@ if (MINGW)
else() else()
set_source_files_properties(${easy_profiler_src} PROPERTIES COMPILE_FLAGS "-DWINVER=0x0601 -D_WIN32_WINNT=0x0601 -DBUILD_WITH_EASY_PROFILER -DEASY_PROFILER_STATIC -DEASY_DEFAULT_PORT=28077 -DEASY_PROFILER_VERSION_MAJOR=2 -DEASY_PROFILER_VERSION_MINOR=1 -DEASY_PROFILER_VERSION_PATCH=0 -DSTRSAFE_NO_DEPRECATE -Wno-reorder-ctor -Wno-reorder -Wno-unknown-pragmas -Wno-format -Wno-class-memaccess") set_source_files_properties(${easy_profiler_src} PROPERTIES COMPILE_FLAGS "-DWINVER=0x0601 -D_WIN32_WINNT=0x0601 -DBUILD_WITH_EASY_PROFILER -DEASY_PROFILER_STATIC -DEASY_DEFAULT_PORT=28077 -DEASY_PROFILER_VERSION_MAJOR=2 -DEASY_PROFILER_VERSION_MINOR=1 -DEASY_PROFILER_VERSION_PATCH=0 -DSTRSAFE_NO_DEPRECATE -Wno-reorder-ctor -Wno-reorder -Wno-unknown-pragmas -Wno-format -Wno-class-memaccess")
endif() endif()
endif() elseif (LINUX)
if (CLANG)
if (MSVC) set_source_files_properties(${easy_profiler_src} PROPERTIES COMPILE_FLAGS "-DBUILD_WITH_EASY_PROFILER -DEASY_PROFILER_STATIC -DEASY_DEFAULT_PORT=28077 -DEASY_PROFILER_VERSION_MAJOR=2 -DEASY_PROFILER_VERSION_MINOR=1 -DEASY_PROFILER_VERSION_PATCH=0 -DSTRSAFE_NO_DEPRECATE -Wno-unused-variable -Wno-writable-strings -Wno-braced-scalar-init -Wno-defaulted-function-deleted -Wno-unknown-pragmas -Wno-reorder-ctor")
else()
set_source_files_properties(${easy_profiler_src} PROPERTIES COMPILE_FLAGS "-DBUILD_WITH_EASY_PROFILER -DEASY_PROFILER_STATIC -DEASY_DEFAULT_PORT=28077 -DEASY_PROFILER_VERSION_MAJOR=2 -DEASY_PROFILER_VERSION_MINOR=1 -DEASY_PROFILER_VERSION_PATCH=0 -DSTRSAFE_NO_DEPRECATE -Wno-reorder-ctor -Wno-reorder -Wno-unknown-pragmas -Wno-format -Wno-class-memaccess")
endif()
elseif (MSVC)
if (CLANG) if (CLANG)
set_source_files_properties(${easy_profiler_src} PROPERTIES COMPILE_FLAGS "-DBUILD_WITH_EASY_PROFILER -DEASY_PROFILER_STATIC -DEASY_DEFAULT_PORT=28077 -DEASY_PROFILER_VERSION_MAJOR=2 -DEASY_PROFILER_VERSION_MINOR=1 -DEASY_PROFILER_VERSION_PATCH=0 -DSTRSAFE_NO_DEPRECATE -Wno-reorder-ctor -Wno-defaulted-function-deleted -Wno-braced-scalar-init -Wno-writable-strings -D_WINSOCK_DEPRECATED_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -Wno-format") set_source_files_properties(${easy_profiler_src} PROPERTIES COMPILE_FLAGS "-DBUILD_WITH_EASY_PROFILER -DEASY_PROFILER_STATIC -DEASY_DEFAULT_PORT=28077 -DEASY_PROFILER_VERSION_MAJOR=2 -DEASY_PROFILER_VERSION_MINOR=1 -DEASY_PROFILER_VERSION_PATCH=0 -DSTRSAFE_NO_DEPRECATE -Wno-reorder-ctor -Wno-defaulted-function-deleted -Wno-braced-scalar-init -Wno-writable-strings -D_WINSOCK_DEPRECATED_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -Wno-format")
else() else()
+12 -3
View File
@@ -5,13 +5,22 @@ set(SDL_TEST OFF CACHE BOOL "" FORCE)
add_subdirectory(sdl2 build_sdl2) add_subdirectory(sdl2 build_sdl2)
if (CLANG AND NOT ANDROID) if (CLANG AND NOT ANDROID)
target_compile_options(SDL2-static PRIVATE -Wno-pragma-pack -Wno-unused-command-line-argument -Wno-incompatible-function-pointer-types -Wno-unused-const-variable) target_compile_options(SDL2-static PRIVATE -Wno-pragma-pack -Wno-unused-command-line-argument -Wno-unused-function -Wno-incompatible-function-pointer-types -Wno-unused-but-set-variable -Wno-unused-const-variable)
endif() endif()
if (MSVC AND NOT CLANG) if (MSVC AND NOT CLANG)
target_compile_options(SDL2-static PRIVATE /wd4028) target_compile_options(SDL2-static PRIVATE /wd4028)
endif() endif()
if (ANDROID) if (ANDROID)
target_compile_options(SDL2-static PRIVATE -Wno-deprecated-declarations) target_compile_options(SDL2-static PRIVATE -Wno-deprecated-declarations)
endif()
if (LINUX)
if(CLANG)
target_compile_definitions(SDL2-static PRIVATE SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS)
target_compile_options(SDL2-static PRIVATE -Wno-unused-variable)
else()
target_compile_options(SDL2-static PRIVATE -Wno-unused-variable -Wno-unused-function)
endif()
endif() endif()
+1 -1
View File
@@ -3,7 +3,7 @@ file(GLOB sqlite_src
) )
if (MINGW) if (MINGW OR LINUX)
if (CLANG) if (CLANG)
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0.0) if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0.0)
set_source_files_properties(${sqlite_src} PROPERTIES COMPILE_FLAGS "-Wno-unused-but-set-variable -Wno-unused-function -Wno-unknown-pragmas -Wno-unused-variable -Wno-sometimes-uninitialized") set_source_files_properties(${sqlite_src} PROPERTIES COMPILE_FLAGS "-Wno-unused-but-set-variable -Wno-unused-function -Wno-unknown-pragmas -Wno-unused-variable -Wno-sometimes-uninitialized")
+11 -5
View File
@@ -10,6 +10,9 @@ elseif(MSVC AND CLANG)
else() else()
set_target_properties(vulkan-1 PROPERTIES IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/vulkan-1.lib") set_target_properties(vulkan-1 PROPERTIES IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/vulkan-1.lib")
endif() endif()
elseif(LINUX)
find_library(Vulkan_Lib vulkan)
set_target_properties(vulkan-1 PROPERTIES IMPORTED_LOCATION ${Vulkan_Lib})
endif() endif()
set(SPIRV_SOURCES set(SPIRV_SOURCES
@@ -335,12 +338,15 @@ set(SPIRV_TOOLS_OPT_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/source/opt/wrap_opkill.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/opt/wrap_opkill.cpp
) )
if (MSVC) if (LINUX)
set_source_files_properties(${SPIRV_SOURCES} PROPERTIES COMPILE_FLAGS "/Os -D_CRT_SECURE_NO_WARNINGS -DSPIRV_WINDOWS") set_source_files_properties(${SPIRV_SOURCES} PROPERTIES COMPILE_FLAGS "-Os -DSPIRV_LINUX")
set_source_files_properties(${SPIRV_TOOLS_OPT_SOURCES} PROPERTIES COMPILE_FLAGS "/Os -D_CRT_SECURE_NO_WARNINGS -DSPIRV_WINDOWS") set_source_files_properties(${SPIRV_TOOLS_OPT_SOURCES} PROPERTIES COMPILE_FLAGS "-Os -DSPIRV_LINUX")
elseif (MSVC)
set_source_files_properties(${SPIRV_SOURCES} PROPERTIES COMPILE_FLAGS "/Os -D_CRT_SECURE_NO_WARNINGS -DSPIRV_WINDOWS")
set_source_files_properties(${SPIRV_TOOLS_OPT_SOURCES} PROPERTIES COMPILE_FLAGS "/Os -D_CRT_SECURE_NO_WARNINGS -DSPIRV_WINDOWS")
else() else()
set_source_files_properties(${SPIRV_SOURCES} PROPERTIES COMPILE_FLAGS "-Os -DSPIRV_WINDOWS") set_source_files_properties(${SPIRV_SOURCES} PROPERTIES COMPILE_FLAGS "-Os -DSPIRV_WINDOWS")
set_source_files_properties(${SPIRV_TOOLS_OPT_SOURCES} PROPERTIES COMPILE_FLAGS "-Os -DSPIRV_WINDOWS") set_source_files_properties(${SPIRV_TOOLS_OPT_SOURCES} PROPERTIES COMPILE_FLAGS "-Os -DSPIRV_WINDOWS")
endif() endif()
+39 -25
View File
@@ -2,8 +2,12 @@ cmake_minimum_required(VERSION 3.12)
project(Kyty) project(Kyty)
if (NOT (WIN32 AND (MINGW OR MSVC))) if(CMAKE_SYSTEM_NAME MATCHES ".*Linux")
message(FATAL_ERROR "only mingw and msvc supported") set(LINUX TRUE)
endif()
if (NOT ((WIN32 AND (MINGW OR MSVC)) OR LINUX))
message(FATAL_ERROR "only mingw and msvc supported (or linux)")
endif() endif()
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
@@ -43,9 +47,22 @@ else()
set(KYTY_BUILD KYTY_BUILD_RELEASE) set(KYTY_BUILD KYTY_BUILD_RELEASE)
endif() endif()
set(KYTY_PLATFORM KYTY_PLATFORM_WINDOWS) if(LINUX)
set(KYTY_PLATFORM KYTY_PLATFORM_LINUX)
else()
set(KYTY_PLATFORM KYTY_PLATFORM_WINDOWS)
endif()
if(MINGW) if(LINUX)
if(CMAKE_CXX_COMPILER_ID MATCHES "(C|c?)lang")
set(CLANG 1)
set(KYTY_COMPILER CLANG)
set(KYTY_LINKER LLD)
else()
set(KYTY_COMPILER GCC)
set(KYTY_LINKER LD)
endif()
elseif(MINGW)
if(CMAKE_CXX_COMPILER_ID MATCHES "(C|c?)lang") if(CMAKE_CXX_COMPILER_ID MATCHES "(C|c?)lang")
set(CLANG 1) set(CLANG 1)
set(KYTY_COMPILER CLANG) set(KYTY_COMPILER CLANG)
@@ -78,11 +95,11 @@ if (CLANG AND (KYTY_LINKER STREQUAL LLD))
set(KYTY_LD_OPTIONS "-fuse-ld=lld") set(KYTY_LD_OPTIONS "-fuse-ld=lld")
endif() endif()
if (KYTY_LINKER STREQUAL LD) if (KYTY_LINKER STREQUAL LD AND NOT LINUX)
set(KYTY_LD_OPTIONS "-Wl,--image-base=0x100000000000") set(KYTY_LD_OPTIONS "-Wl,--image-base=0x100000000000")
endif() endif()
project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.2.1) project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.2.2)
include(src_script.cmake) include(src_script.cmake)
@@ -121,7 +138,7 @@ if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0.0)
core core
math_obj math_obj
scripts scripts
sys_obj sys
#launcher #launcher
unit_test unit_test
) )
@@ -130,7 +147,7 @@ if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0.0)
#core #core
#math_obj #math_obj
#scripts #scripts
#sys_obj #sys
launcher launcher
#unit_test #unit_test
) )
@@ -164,18 +181,20 @@ target_link_libraries(fc_script sys)
target_link_libraries(fc_script math) target_link_libraries(fc_script math)
target_link_libraries(fc_script scripts) target_link_libraries(fc_script scripts)
target_link_libraries(fc_script lua) target_link_libraries(fc_script lua)
if (MSVC OR MINGW)
target_link_libraries(fc_script opengl32) target_link_libraries(fc_script opengl32)
target_link_libraries(fc_script iphlpapi) target_link_libraries(fc_script iphlpapi)
target_link_libraries(fc_script SDL2-static)
target_link_libraries(fc_script setupapi) target_link_libraries(fc_script setupapi)
target_link_libraries(fc_script ws2_32)
target_link_libraries(fc_script psapi)
endif()
target_link_libraries(fc_script SDL2-static)
target_link_libraries(fc_script emulator) target_link_libraries(fc_script emulator)
target_link_libraries(fc_script rijndael) target_link_libraries(fc_script rijndael)
target_link_libraries(fc_script lzma) target_link_libraries(fc_script lzma)
target_link_libraries(fc_script sqlite) target_link_libraries(fc_script sqlite)
target_link_libraries(fc_script zstd) target_link_libraries(fc_script zstd)
target_link_libraries(fc_script easy_profiler) target_link_libraries(fc_script easy_profiler)
target_link_libraries(fc_script ws2_32)
target_link_libraries(fc_script psapi)
target_link_libraries(fc_script cpuinfo) target_link_libraries(fc_script cpuinfo)
if (CLANG AND NOT MSVC) if (CLANG AND NOT MSVC)
target_link_libraries(fc_script pthread) target_link_libraries(fc_script pthread)
@@ -186,21 +205,16 @@ endif()
set(KYTY_SCRIPT_BIN "../../__bin/fc_script") set(KYTY_SCRIPT_BIN "../../__bin/fc_script")
if(MSVC) if(LINUX)
set_target_properties(fc_script PROPERTIES LINK_FLAGS "${KYTY_LD_OPTIONS} -Wl,-Map=fc_script_${FYTY_COMPILER_ID}_${KYTY_LINKER_ID}_${KYTY_BITNESS}.map")
#add_custom_command(TARGET fc_script POST_BUILD COMMAND ${KYTY_SCRIPT_BIN} ${PROJECT_SOURCE_DIR}/map_to_csv.lua fc_script ${FYTY_COMPILER_ID} ${KYTY_BITNESS} ${KYTY_LINKER_ID})
elseif(MSVC)
set_target_properties(fc_script PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "$(SolutionDir)$(Configuration)/") set_target_properties(fc_script PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "$(SolutionDir)$(Configuration)/")
set_target_properties(fc_script set_target_properties(fc_script PROPERTIES LINK_FLAGS "/DYNAMICBASE:NO /MAP:fc_script_msvc_${KYTY_BITNESS}.map")
PROPERTIES add_custom_command(TARGET fc_script POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different fc_script_msvc_${KYTY_BITNESS}.map $<TARGET_FILE_DIR:fc_script>/fc_script_${KYTY_COMPILER_ID}_${KYTY_LINKER_ID}_${KYTY_BITNESS}.map)
LINK_FLAGS "/DYNAMICBASE:NO /MAP:fc_script_msvc_${KYTY_BITNESS}.map" add_custom_command(TARGET fc_script POST_BUILD COMMAND ${KYTY_SCRIPT_BIN} ${PROJECT_SOURCE_DIR}/map_to_csv.lua $<TARGET_FILE_DIR:fc_script>/fc_script ${KYTY_COMPILER_ID} ${KYTY_BITNESS} ${KYTY_LINKER_ID})
) add_custom_command(TARGET fc_script POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${PROJECT_SOURCE_DIR}/3rdparty/winpthread/bin/libwinpthread-1.dll" $<TARGET_FILE_DIR:fc_script>/libwinpthread-1.dll)
add_custom_command(TARGET fc_script POST_BUILD elseif(MINGW)
COMMAND ${CMAKE_COMMAND} -E copy_if_different fc_script_msvc_${KYTY_BITNESS}.map $<TARGET_FILE_DIR:fc_script>/fc_script_${KYTY_COMPILER_ID}_${KYTY_LINKER_ID}_${KYTY_BITNESS}.map)
add_custom_command(TARGET fc_script POST_BUILD
COMMAND ${KYTY_SCRIPT_BIN} ${PROJECT_SOURCE_DIR}/map_to_csv.lua $<TARGET_FILE_DIR:fc_script>/fc_script ${KYTY_COMPILER_ID} ${KYTY_BITNESS} ${KYTY_LINKER_ID})
add_custom_command(TARGET fc_script POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${PROJECT_SOURCE_DIR}/3rdparty/winpthread/bin/libwinpthread-1.dll" $<TARGET_FILE_DIR:fc_script>/libwinpthread-1.dll)
endif()
if(MINGW)
set_target_properties(fc_script PROPERTIES LINK_FLAGS "${KYTY_LD_OPTIONS} -Wl,-Map=fc_script_${KYTY_COMPILER_ID}_${KYTY_LINKER_ID}_${KYTY_BITNESS}.map") set_target_properties(fc_script PROPERTIES LINK_FLAGS "${KYTY_LD_OPTIONS} -Wl,-Map=fc_script_${KYTY_COMPILER_ID}_${KYTY_LINKER_ID}_${KYTY_BITNESS}.map")
add_custom_command(TARGET fc_script POST_BUILD COMMAND ${KYTY_SCRIPT_BIN} ${PROJECT_SOURCE_DIR}/map_to_csv.lua fc_script ${KYTY_COMPILER_ID} ${KYTY_BITNESS} ${KYTY_LINKER_ID}) add_custom_command(TARGET fc_script POST_BUILD COMMAND ${KYTY_SCRIPT_BIN} ${PROJECT_SOURCE_DIR}/map_to_csv.lua fc_script ${KYTY_COMPILER_ID} ${KYTY_BITNESS} ${KYTY_LINKER_ID})
endif() endif()
+3 -2
View File
@@ -3,8 +3,9 @@
#include "Kyty/Core/Common.h" #include "Kyty/Core/Common.h"
#if (KYTY_COMPILER == KYTY_COMPILER_CLANG || KYTY_COMPILER == KYTY_COMPILER_MINGW) && KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS && \ #if (KYTY_COMPILER == KYTY_COMPILER_CLANG || KYTY_COMPILER == KYTY_COMPILER_MINGW || KYTY_COMPILER == KYTY_COMPILER_GCC) && \
KYTY_BITNESS == 64 && KYTY_ENDIAN == KYTY_ENDIAN_LITTLE && KYTY_ABI == KYTY_ABI_X86_64 && KYTY_PROJECT == KYTY_PROJECT_EMULATOR (KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS || KYTY_PLATFORM == KYTY_PLATFORM_LINUX) && KYTY_BITNESS == 64 && \
KYTY_ENDIAN == KYTY_ENDIAN_LITTLE && KYTY_ABI == KYTY_ABI_X86_64 && KYTY_PROJECT == KYTY_PROJECT_EMULATOR
#define KYTY_EMU_ENABLED #define KYTY_EMU_ENABLED
#endif #endif
@@ -136,14 +136,14 @@ inline long double VaArg_long_double(VaList* l)
return VaArg_overflow_arg_area<long double, 16, 16>(l); return VaArg_overflow_arg_area<long double, 16, 16>(l);
} }
inline wint_t VaArg_wint_t(VaList* l) /*inline wint_t VaArg_wint_t(VaList* l)
{ {
if (l->gp_offset <= 40) if (l->gp_offset <= 40)
{ {
return VaArg_reg_save_area_gp<wint_t, 8>(l); return VaArg_reg_save_area_gp<wint_t, 8>(l);
} }
return VaArg_overflow_arg_area<wint_t, 1, 8>(l); return VaArg_overflow_arg_area<wint_t, 1, 8>(l);
} }*/
inline VaCharX16 VaArg_char_x16(VaList* l) inline VaCharX16 VaArg_char_x16(VaList* l)
{ {
@@ -12,6 +12,10 @@
#ifdef KYTY_EMU_ENABLED #ifdef KYTY_EMU_ENABLED
namespace Kyty::Core::VirtualMemory {
class ExceptionHandler;
} // namespace Kyty::Core::VirtualMemory
namespace Kyty::Loader { namespace Kyty::Loader {
class Elf64; class Elf64;
@@ -19,10 +23,6 @@ struct Elf64_Sym;
struct Elf64_Rela; struct Elf64_Rela;
class RuntimeLinker; class RuntimeLinker;
namespace VirtualMemory {
class ExceptionHandler;
} // namespace VirtualMemory
using module_func_t = int (*)(size_t args, const void* argp); using module_func_t = int (*)(size_t args, const void* argp);
struct ModuleId struct ModuleId
@@ -103,23 +103,23 @@ struct DynamicInfo
struct Program struct Program
{ {
int32_t unique_id = -1; int32_t unique_id = -1;
RuntimeLinker* rt = nullptr; RuntimeLinker* rt = nullptr;
String file_name; String file_name;
Elf64* elf = nullptr; Elf64* elf = nullptr;
VirtualMemory::ExceptionHandler* exception_handler = nullptr; Core::VirtualMemory::ExceptionHandler* exception_handler = nullptr;
DynamicInfo* dynamic_info = nullptr; DynamicInfo* dynamic_info = nullptr;
uint64_t base_vaddr = 0; uint64_t base_vaddr = 0;
uint64_t base_size = 0; uint64_t base_size = 0;
uint64_t base_size_aligned = 0; uint64_t base_size_aligned = 0;
SymbolDatabase* export_symbols = nullptr; SymbolDatabase* export_symbols = nullptr;
SymbolDatabase* import_symbols = nullptr; SymbolDatabase* import_symbols = nullptr;
ThreadLocalStorage tls; ThreadLocalStorage tls;
bool fail_if_global_not_resolved = true; bool fail_if_global_not_resolved = true;
bool dbg_print_reloc = false; bool dbg_print_reloc = false;
uint64_t proc_param_vaddr = 0; uint64_t proc_param_vaddr = 0;
uint64_t custom_call_plt_vaddr = 0; uint64_t custom_call_plt_vaddr = 0;
uint32_t custom_call_plt_num = 0; uint32_t custom_call_plt_num = 0;
}; };
class RuntimeLinker class RuntimeLinker
+5 -5
View File
@@ -3,6 +3,7 @@
#include "Kyty/Core/DbgAssert.h" #include "Kyty/Core/DbgAssert.h"
#include "Kyty/Core/File.h" #include "Kyty/Core/File.h"
#include "Kyty/Core/String.h" #include "Kyty/Core/String.h"
#include "Kyty/Core/VirtualMemory.h"
#include "Emulator/Config.h" #include "Emulator/Config.h"
#include "Emulator/Graphics/GraphicsRender.h" #include "Emulator/Graphics/GraphicsRender.h"
@@ -19,7 +20,6 @@
#include "Emulator/Kernel/Pthread.h" #include "Emulator/Kernel/Pthread.h"
#include "Emulator/Libs/Errno.h" #include "Emulator/Libs/Errno.h"
#include "Emulator/Libs/Libs.h" #include "Emulator/Libs/Libs.h"
#include "Emulator/Loader/VirtualMemory.h"
#include <algorithm> #include <algorithm>
#include <atomic> #include <atomic>
@@ -661,11 +661,11 @@ void* KYTY_SYSV_ABI GraphicsGetTheTessellationFactorRingBufferBaseAddress()
{ {
PRINT_NAME(); PRINT_NAME();
auto addr = Loader::VirtualMemory::AllocAligned(0, 0x20000, Loader::VirtualMemory::Mode::ReadWrite, 256); auto addr = Core::VirtualMemory::AllocAligned(0, 0x20000, Core::VirtualMemory::Mode::ReadWrite, 256);
Loader::VirtualMemory::Free(addr); Core::VirtualMemory::Free(addr);
bool again = Loader::VirtualMemory::AllocFixed(addr, 0x20000, Loader::VirtualMemory::Mode::ReadWrite); bool again = Core::VirtualMemory::AllocFixed(addr, 0x20000, Core::VirtualMemory::Mode::ReadWrite);
EXIT_NOT_IMPLEMENTED(!again); EXIT_NOT_IMPLEMENTED(!again);
Loader::VirtualMemory::Free(addr); Core::VirtualMemory::Free(addr);
printf("\t addr = %016" PRIx64 "\n", addr); printf("\t addr = %016" PRIx64 "\n", addr);
+2 -2
View File
@@ -7,7 +7,7 @@
#include "Emulator/Graphics/AsyncJob.h" #include "Emulator/Graphics/AsyncJob.h"
#include "Emulator/Profiler.h" #include "Emulator/Profiler.h"
#if KYTY_COMPILER != KYTY_COMPILER_CLANG #if KYTY_COMPILER != KYTY_COMPILER_CLANG && KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
#include <intrin.h> #include <intrin.h>
#endif #endif
@@ -20,7 +20,7 @@ namespace Kyty::Libs::Graphics {
static uint32_t IntLog2(uint32_t i) static uint32_t IntLog2(uint32_t i)
{ {
#if KYTY_COMPILER == KYTY_COMPILER_CLANG #if KYTY_COMPILER == KYTY_COMPILER_CLANG || KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS
return 31 - __builtin_clz(i | 1u); return 31 - __builtin_clz(i | 1u);
#else #else
unsigned long temp; unsigned long temp;
+3 -3
View File
@@ -8,6 +8,7 @@
#include "Kyty/Core/Threads.h" #include "Kyty/Core/Threads.h"
#include "Kyty/Core/Timer.h" #include "Kyty/Core/Timer.h"
#include "Kyty/Core/Vector.h" #include "Kyty/Core/Vector.h"
#include "Kyty/Core/VirtualMemory.h"
#include "Emulator/Config.h" #include "Emulator/Config.h"
#include "Emulator/Controller.h" #include "Emulator/Controller.h"
@@ -17,7 +18,6 @@
#include "Emulator/Graphics/Utils.h" #include "Emulator/Graphics/Utils.h"
#include "Emulator/Graphics/VideoOut.h" #include "Emulator/Graphics/VideoOut.h"
#include "Emulator/Loader/SystemContent.h" #include "Emulator/Loader/SystemContent.h"
#include "Emulator/Loader/VirtualMemory.h"
#include "Emulator/Profiler.h" #include "Emulator/Profiler.h"
#include "SDL.h" #include "SDL.h"
@@ -444,7 +444,7 @@ void game_event_keyboard(GameApi* game, const EventKeyboard* key)
(key->repeat ? "repeat" : ""), key->scan_code, key->key_code, key->mod); (key->repeat ? "repeat" : ""), key->scan_code, key->key_code, key->mod);
#endif #endif
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS #if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS || KYTY_PLATFORM == KYTY_PLATFORM_LINUX
if (key->down && key->key_code == SDLK_ESCAPE) if (key->down && key->key_code == SDLK_ESCAPE)
{ {
game->m_game_need_exit = true; game->m_game_need_exit = true;
@@ -2204,7 +2204,7 @@ static void VulkanCreate(WindowContext* ctx)
printf("Select device: %s\n", device_properties.deviceName); printf("Select device: %s\n", device_properties.deviceName);
memcpy(ctx->device_name, device_properties.deviceName, sizeof(ctx->device_name)); memcpy(ctx->device_name, device_properties.deviceName, sizeof(ctx->device_name));
memcpy(ctx->processor_name, Loader::GetSystemInfo().ProcessorName.C_Str(), sizeof(ctx->processor_name)); memcpy(ctx->processor_name, Core::GetSystemInfo().ProcessorName.C_Str(), sizeof(ctx->processor_name));
ctx->graphic_ctx.device = VulkanCreateDevice(ctx->graphic_ctx.physical_device, ctx->surface, &r, queues, device_extensions); ctx->graphic_ctx.device = VulkanCreateDevice(ctx->graphic_ctx.physical_device, ctx->surface, &r, queues, device_extensions);
if (ctx->graphic_ctx.device == nullptr) if (ctx->graphic_ctx.device == nullptr)
+2 -2
View File
@@ -5,13 +5,13 @@
#include "Kyty/Core/String.h" #include "Kyty/Core/String.h"
#include "Kyty/Core/Threads.h" #include "Kyty/Core/Threads.h"
#include "Kyty/Core/Vector.h" #include "Kyty/Core/Vector.h"
#include "Kyty/Core/VirtualMemory.h"
#include "Emulator/Graphics/GraphicsRun.h" #include "Emulator/Graphics/GraphicsRun.h"
#include "Emulator/Graphics/Objects/GpuMemory.h" #include "Emulator/Graphics/Objects/GpuMemory.h"
#include "Emulator/Graphics/Window.h" #include "Emulator/Graphics/Window.h"
#include "Emulator/Libs/Errno.h" #include "Emulator/Libs/Errno.h"
#include "Emulator/Libs/Libs.h" #include "Emulator/Libs/Libs.h"
#include "Emulator/Loader/VirtualMemory.h"
#include <algorithm> #include <algorithm>
@@ -19,7 +19,7 @@
namespace Kyty::Libs::LibKernel::Memory { namespace Kyty::Libs::LibKernel::Memory {
namespace VirtualMemory = Loader::VirtualMemory; namespace VirtualMemory = Core::VirtualMemory;
LIB_NAME("libkernel", "libkernel"); LIB_NAME("libkernel", "libkernel");
+12
View File
@@ -20,8 +20,16 @@
#ifdef KYTY_EMU_ENABLED #ifdef KYTY_EMU_ENABLED
#if KYTY_PLATFORM == KYTY_PLATFORM_LINUX
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#include <pthread.h> #include <pthread.h>
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
#include <pthread_time.h> #include <pthread_time.h>
#endif
namespace Kyty::Libs { namespace Kyty::Libs {
@@ -2701,4 +2709,8 @@ int KYTY_SYSV_ABI pthread_mutexattr_destroy(LibKernel::PthreadMutexattr* attr)
} // namespace Kyty::Libs } // namespace Kyty::Libs
#if KYTY_PLATFORM == KYTY_PLATFORM_LINUX
#pragma GCC diagnostic pop
#endif
#endif // KYTY_EMU_ENABLED #endif // KYTY_EMU_ENABLED
+3 -12
View File
@@ -6,6 +6,7 @@
#include "Kyty/Core/Subsystems.h" #include "Kyty/Core/Subsystems.h"
#include "Kyty/Core/Threads.h" #include "Kyty/Core/Threads.h"
#include "Kyty/Core/Vector.h" #include "Kyty/Core/Vector.h"
#include "Kyty/Core/VirtualMemory.h"
#include "Kyty/Scripts/Scripts.h" #include "Kyty/Scripts/Scripts.h"
#include "Kyty/UnitTest.h" #include "Kyty/UnitTest.h"
@@ -23,7 +24,6 @@
#include "Emulator/Loader/RuntimeLinker.h" #include "Emulator/Loader/RuntimeLinker.h"
#include "Emulator/Loader/SystemContent.h" #include "Emulator/Loader/SystemContent.h"
#include "Emulator/Loader/Timer.h" #include "Emulator/Loader/Timer.h"
#include "Emulator/Loader/VirtualMemory.h"
#include "Emulator/Network.h" #include "Emulator/Network.h"
#include "Emulator/Profiler.h" #include "Emulator/Profiler.h"
@@ -57,18 +57,9 @@ static void load_symbols_all(Loader::RuntimeLinker* rt)
static void print_system_info() static void print_system_info()
{ {
Loader::SystemInfo info = Loader::GetSystemInfo(); Core::SystemInfo info = Core::GetSystemInfo();
printf("PageSize = %" PRIu32 "\n", info.PageSize); printf("ProcessorName = %s\n", info.ProcessorName.C_Str());
printf("MinimumApplicationAddress = 0x%016" PRIx64 "\n", info.MinimumApplicationAddress);
printf("MaximumApplicationAddress = 0x%016" PRIx64 "\n", info.MaximumApplicationAddress);
printf("ActiveProcessorMask = 0x%08" PRIx32 "\n", info.ActiveProcessorMask);
printf("NumberOfProcessors = %" PRIu32 "\n", info.NumberOfProcessors);
printf("ProcessorArchitecture = %s\n", Core::EnumName(info.ProcessorArchitecture).C_Str());
printf("AllocationGranularity = %" PRIu32 "\n", info.AllocationGranularity);
printf("ProcessorLevel = %" PRIu16 "\n", info.ProcessorLevel);
printf("ProcessorRevision = 0x%04" PRIx16 "\n", info.ProcessorRevision);
printf("ProcessorName = %s\n", info.ProcessorName.C_Str());
} }
static void kyty_close() static void kyty_close()
+11 -7
View File
@@ -3,13 +3,13 @@
#include "Kyty/Core/String.h" #include "Kyty/Core/String.h"
#include "Kyty/Core/Threads.h" #include "Kyty/Core/Threads.h"
#include "Kyty/Core/Vector.h" #include "Kyty/Core/Vector.h"
#include "Kyty/Core/VirtualMemory.h"
#include "Kyty/Sys/SysDbg.h" #include "Kyty/Sys/SysDbg.h"
#include "Emulator/Common.h" #include "Emulator/Common.h"
#include "Emulator/Kernel/Memory.h" #include "Emulator/Kernel/Memory.h"
#include "Emulator/Libs/Libs.h" #include "Emulator/Libs/Libs.h"
#include "Emulator/Loader/SymbolDatabase.h" #include "Emulator/Loader/SymbolDatabase.h"
#include "Emulator/Loader/VirtualMemory.h"
#include <algorithm> #include <algorithm>
@@ -68,8 +68,8 @@ static void AllocShadow(uintptr_t min_addr, uintptr_t max_addr)
auto size = max_shadow - min_shadow + page_size; auto size = max_shadow - min_shadow + page_size;
printf("\t shadow = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(min_shadow)); printf("\t shadow = %016" PRIx64 "\n", static_cast<uint64_t>(min_shadow));
printf("\t size = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(size)); printf("\t size = %016" PRIx64 "\n", static_cast<uint64_t>(size));
for (uintptr_t page = min_shadow; page <= max_shadow; page += page_size) for (uintptr_t page = min_shadow; page <= max_shadow; page += page_size)
{ {
@@ -78,7 +78,7 @@ static void AllocShadow(uintptr_t min_addr, uintptr_t max_addr)
g_ctx->shadows[index].count++; g_ctx->shadows[index].count++;
} else } else
{ {
if (!Loader::VirtualMemory::AllocFixed(page, page_size, Loader::VirtualMemory::Mode::ReadWrite)) if (!Core::VirtualMemory::AllocFixed(page, page_size, Core::VirtualMemory::Mode::ReadWrite))
{ {
EXIT("can't allocate shadow memory\n"); EXIT("can't allocate shadow memory\n");
} }
@@ -104,8 +104,8 @@ static void FreeShadow(uintptr_t min_addr, uintptr_t max_addr)
auto size = max_shadow - min_shadow + page_size; auto size = max_shadow - min_shadow + page_size;
printf("\t shadow = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(min_shadow)); printf("\t shadow = %016" PRIx64 "\n", static_cast<uint64_t>(min_shadow));
printf("\t size = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(size)); printf("\t size = %016" PRIx64 "\n", static_cast<uint64_t>(size));
for (uintptr_t page = min_shadow; page <= max_shadow; page += page_size) for (uintptr_t page = min_shadow; page <= max_shadow; page += page_size)
{ {
@@ -115,7 +115,7 @@ static void FreeShadow(uintptr_t min_addr, uintptr_t max_addr)
if (g_ctx->shadows[index].count <= 0) if (g_ctx->shadows[index].count <= 0)
{ {
if (!Loader::VirtualMemory::Free(page)) if (!Core::VirtualMemory::Free(page))
{ {
EXIT("can't free shadow memory\n"); EXIT("can't free shadow memory\n");
} }
@@ -147,7 +147,11 @@ static void KYTY_SYSV_ABI asan_init()
sys_dbg_stack_info_t s {}; sys_dbg_stack_info_t s {};
sys_stack_usage(s); sys_stack_usage(s);
#if KYTY_PLATFORM == KYTY_PLATFORM_LINUX
AllocShadow(s.addr, reinterpret_cast<uintptr_t>(&s));
#else
AllocShadow(s.reserved_addr, reinterpret_cast<uintptr_t>(&s)); AllocShadow(s.reserved_addr, reinterpret_cast<uintptr_t>(&s));
#endif
LibKernel::Memory::RegisterCallbacks(KernelAlloc, KernelFree); LibKernel::Memory::RegisterCallbacks(KernelAlloc, KernelFree);
} }
+1 -1
View File
@@ -405,7 +405,7 @@ static size_t _etoa(out_fct_type out, Vector<char>* buffer, size_t idx, size_t m
int expval = static_cast<int>(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168); int expval = static_cast<int>(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168);
// now we want to compute 10^expval but we want to be sure it won't overflow // now we want to compute 10^expval but we want to be sure it won't overflow
// exp2 = static_cast<int>(expval * 3.321928094887362 + 0.5); // exp2 = static_cast<int>(expval * 3.321928094887362 + 0.5);
exp2 = lround(expval * 3.321928094887362); exp2 = static_cast<int>(lround(expval * 3.321928094887362));
const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453; const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453;
const double z2 = z * z; const double z2 = z * z;
conv.U = static_cast<uint64_t>(exp2 + 1023) << 52U; conv.U = static_cast<uint64_t>(exp2 + 1023) << 52U;
+39 -37
View File
@@ -7,6 +7,7 @@
#include "Kyty/Core/Singleton.h" #include "Kyty/Core/Singleton.h"
#include "Kyty/Core/String.h" #include "Kyty/Core/String.h"
#include "Kyty/Core/Threads.h" #include "Kyty/Core/Threads.h"
#include "Kyty/Core/VirtualMemory.h"
#include "Kyty/Sys/SysDbg.h" #include "Kyty/Sys/SysDbg.h"
#include "Emulator/Config.h" #include "Emulator/Config.h"
@@ -15,7 +16,6 @@
#include "Emulator/Loader/Elf.h" #include "Emulator/Loader/Elf.h"
#include "Emulator/Loader/Jit.h" #include "Emulator/Loader/Jit.h"
#include "Emulator/Loader/SymbolDatabase.h" #include "Emulator/Loader/SymbolDatabase.h"
#include "Emulator/Loader/VirtualMemory.h"
#include "Emulator/Profiler.h" #include "Emulator/Profiler.h"
#ifdef KYTY_EMU_ENABLED #ifdef KYTY_EMU_ENABLED
@@ -144,19 +144,19 @@ static void dbg_dump_rela(const String& folder, Elf64_Rela* records, uint64_t si
f.Close(); f.Close();
} }
static VirtualMemory::Mode get_mode(Elf64_Word flags) static Core::VirtualMemory::Mode get_mode(Elf64_Word flags)
{ {
switch (flags) switch (flags)
{ {
case PF_R: return VirtualMemory::Mode::Read; case PF_R: return Core::VirtualMemory::Mode::Read;
case PF_W: return VirtualMemory::Mode::Write; case PF_W: return Core::VirtualMemory::Mode::Write;
case PF_R | PF_W: return VirtualMemory::Mode::ReadWrite; case PF_R | PF_W: return Core::VirtualMemory::Mode::ReadWrite;
case PF_X: return VirtualMemory::Mode::Execute; case PF_X: return Core::VirtualMemory::Mode::Execute;
case PF_X | PF_R: return VirtualMemory::Mode::ExecuteRead; case PF_X | PF_R: return Core::VirtualMemory::Mode::ExecuteRead;
case PF_X | PF_W: return VirtualMemory::Mode::ExecuteWrite; case PF_X | PF_W: return Core::VirtualMemory::Mode::ExecuteWrite;
case PF_X | PF_W | PF_R: return VirtualMemory::Mode::ExecuteReadWrite; case PF_X | PF_W | PF_R: return Core::VirtualMemory::Mode::ExecuteReadWrite;
default: return VirtualMemory::Mode::NoAccess; default: return Core::VirtualMemory::Mode::NoAccess;
} }
} }
@@ -200,13 +200,13 @@ void KYTY_SYSV_ABI sys_stack_walk_x86(uint64_t rbp, void** stack, int* depth)
g_desired_base_addr - (SYSTEM_RESERVED + CODE_BASE_OFFSET)); g_desired_base_addr - (SYSTEM_RESERVED + CODE_BASE_OFFSET));
} }
static void kyty_exception_handler(const VirtualMemory::ExceptionHandler::ExceptionInfo* info) static void kyty_exception_handler(const Core::VirtualMemory::ExceptionHandler::ExceptionInfo* info)
{ {
printf("kyty_exception_handler: %016" PRIx64 "\n", info->exception_address); printf("kyty_exception_handler: %016" PRIx64 "\n", info->exception_address);
if (info->type == VirtualMemory::ExceptionHandler::ExceptionType::AccessViolation) if (info->type == Core::VirtualMemory::ExceptionHandler::ExceptionType::AccessViolation)
{ {
if (info->access_violation_type == VirtualMemory::ExceptionHandler::AccessViolationType::Write && if (info->access_violation_type == Core::VirtualMemory::ExceptionHandler::AccessViolationType::Write &&
Libs::Graphics::GpuMemoryCheckAccessViolation(info->access_violation_vaddr, sizeof(uint64_t))) Libs::Graphics::GpuMemoryCheckAccessViolation(info->access_violation_vaddr, sizeof(uint64_t)))
{ {
return; return;
@@ -428,7 +428,7 @@ static void relocate(uint32_t index, Elf64_Rela* r, Program* program, bool jmpre
if (ri.resolved) if (ri.resolved)
{ {
patched = VirtualMemory::PatchReplace(ri.vaddr, ri.value); patched = Core::VirtualMemory::PatchReplace(ri.vaddr, ri.value);
} else } else
{ {
uint64_t value = 0; uint64_t value = 0;
@@ -453,7 +453,7 @@ static void relocate(uint32_t index, Elf64_Rela* r, Program* program, bool jmpre
if (value != 0) if (value != 0)
{ {
patched = VirtualMemory::PatchReplace(ri.vaddr, value); patched = Core::VirtualMemory::PatchReplace(ri.vaddr, value);
} else } else
{ {
auto dbg_str = String::FromPrintf("[%016" PRIx64 "] <- %s%016" PRIx64 "%s, %s, %s, %s, %s", ri.vaddr, auto dbg_str = String::FromPrintf("[%016" PRIx64 "] <- %s%016" PRIx64 "%s, %s, %s, %s, %s", ri.vaddr,
@@ -788,6 +788,7 @@ void RuntimeLinker::Execute()
printf(FG_BRIGHT_YELLOW "--- Execute: " BOLD BG_BLUE "%s" BG_DEFAULT NO_BOLD DEFAULT "\n", "Main"); printf(FG_BRIGHT_YELLOW "--- Execute: " BOLD BG_BLUE "%s" BG_DEFAULT NO_BOLD DEFAULT "\n", "Main");
printf(FG_BRIGHT_YELLOW "---" DEFAULT "\n"); printf(FG_BRIGHT_YELLOW "---" DEFAULT "\n");
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
// Reserve some stack. There may be jumps over guard page. To prevent segfault we need to expand committed area. // Reserve some stack. There may be jumps over guard page. To prevent segfault we need to expand committed area.
size_t expanded_size = 0; size_t expanded_size = 0;
@@ -800,6 +801,7 @@ void RuntimeLinker::Execute()
*reinterpret_cast<uint32_t*>(s.guard_addr) = 0; *reinterpret_cast<uint32_t*>(s.guard_addr) = 0;
expanded_size += s.guard_size; expanded_size += s.guard_size;
} }
#endif
if (auto entry = GetEntry(); entry != 0) if (auto entry = GetEntry(); entry != 0)
{ {
@@ -1135,11 +1137,11 @@ void RuntimeLinker::LoadProgramToMemory(Program* program)
program->base_size = calc_base_size(ehdr, phdr); program->base_size = calc_base_size(ehdr, phdr);
program->base_size_aligned = (program->base_size & ~(static_cast<uint64_t>(0x1000) - 1)) + 0x1000; program->base_size_aligned = (program->base_size & ~(static_cast<uint64_t>(0x1000) - 1)) + 0x1000;
uint64_t exception_handler_size = VirtualMemory::ExceptionHandler::GetSize(); uint64_t exception_handler_size = Core::VirtualMemory::ExceptionHandler::GetSize();
uint64_t tls_handler_size = is_shared ? 0 : Jit::SafeCall::GetSize(); uint64_t tls_handler_size = is_shared ? 0 : Jit::SafeCall::GetSize();
uint64_t alloc_size = program->base_size_aligned + exception_handler_size + tls_handler_size; uint64_t alloc_size = program->base_size_aligned + exception_handler_size + tls_handler_size;
program->base_vaddr = VirtualMemory::Alloc(g_desired_base_addr, alloc_size, VirtualMemory::Mode::ExecuteReadWrite); program->base_vaddr = Core::VirtualMemory::Alloc(g_desired_base_addr, alloc_size, Core::VirtualMemory::Mode::ExecuteReadWrite);
if (!is_shared) if (!is_shared)
{ {
@@ -1160,7 +1162,7 @@ void RuntimeLinker::LoadProgramToMemory(Program* program)
printf("tls_handler_size = 0x%016" PRIx64 "\n", tls_handler_size); printf("tls_handler_size = 0x%016" PRIx64 "\n", tls_handler_size);
} }
program->exception_handler = new VirtualMemory::ExceptionHandler; program->exception_handler = new Core::VirtualMemory::ExceptionHandler;
if (is_shared) if (is_shared)
{ {
@@ -1175,7 +1177,7 @@ void RuntimeLinker::LoadProgramToMemory(Program* program)
// if (Libs::Graphics::GpuMemoryWatcherEnabled()) // if (Libs::Graphics::GpuMemoryWatcherEnabled())
{ {
VirtualMemory::ExceptionHandler::InstallVectored(kyty_exception_handler); Core::VirtualMemory::ExceptionHandler::InstallVectored(kyty_exception_handler);
} }
} }
@@ -1197,20 +1199,20 @@ void RuntimeLinker::LoadProgramToMemory(Program* program)
program->elf->LoadSegment(segment_addr, phdr[i].p_offset, segment_file_size); program->elf->LoadSegment(segment_addr, phdr[i].p_offset, segment_file_size);
bool skip_protect = (phdr[i].p_type == PT_LOAD && is_next_gen && mode == VirtualMemory::Mode::NoAccess); bool skip_protect = (phdr[i].p_type == PT_LOAD && is_next_gen && mode == Core::VirtualMemory::Mode::NoAccess);
if (VirtualMemory::IsExecute(mode)) if (Core::VirtualMemory::IsExecute(mode))
{ {
PatchProgram(program, segment_addr, segment_memory_size); PatchProgram(program, segment_addr, segment_memory_size);
} }
if (!skip_protect) if (!skip_protect)
{ {
VirtualMemory::Protect(segment_addr, segment_memory_size, mode); Core::VirtualMemory::Protect(segment_addr, segment_memory_size, mode);
if (VirtualMemory::IsExecute(mode)) if (Core::VirtualMemory::IsExecute(mode))
{ {
VirtualMemory::FlushInstructionCache(segment_addr, segment_memory_size); Core::VirtualMemory::FlushInstructionCache(segment_addr, segment_memory_size);
} }
} }
} }
@@ -1247,12 +1249,12 @@ void RuntimeLinker::DeleteProgram(Program* p)
{ {
if (p->base_vaddr != 0 || p->base_size != 0) if (p->base_vaddr != 0 || p->base_size != 0)
{ {
VirtualMemory::Free(p->base_vaddr); Core::VirtualMemory::Free(p->base_vaddr);
} }
if (p->custom_call_plt_vaddr != 0 || p->custom_call_plt_num != 0) if (p->custom_call_plt_vaddr != 0 || p->custom_call_plt_num != 0)
{ {
VirtualMemory::Free(p->custom_call_plt_vaddr); Core::VirtualMemory::Free(p->custom_call_plt_vaddr);
} }
delete p->elf; delete p->elf;
@@ -1380,17 +1382,17 @@ static void InstallRelocateHandler(Program* program)
uint64_t pltgot_size = static_cast<uint64_t>(3) * 8; uint64_t pltgot_size = static_cast<uint64_t>(3) * 8;
void** pltgot = reinterpret_cast<void**>(pltgot_vaddr); void** pltgot = reinterpret_cast<void**>(pltgot_vaddr);
VirtualMemory::Mode old_mode {}; Core::VirtualMemory::Mode old_mode {};
VirtualMemory::Protect(pltgot_vaddr, pltgot_size, VirtualMemory::Mode::Write, &old_mode); Core::VirtualMemory::Protect(pltgot_vaddr, pltgot_size, Core::VirtualMemory::Mode::Write, &old_mode);
pltgot[1] = program; pltgot[1] = program;
pltgot[2] = reinterpret_cast<void*>(RelocateHandler); pltgot[2] = reinterpret_cast<void*>(RelocateHandler);
VirtualMemory::Protect(pltgot_vaddr, pltgot_size, old_mode); Core::VirtualMemory::Protect(pltgot_vaddr, pltgot_size, old_mode);
if (VirtualMemory::IsExecute(old_mode)) if (Core::VirtualMemory::IsExecute(old_mode))
{ {
VirtualMemory::FlushInstructionCache(pltgot_vaddr, pltgot_size); Core::VirtualMemory::FlushInstructionCache(pltgot_vaddr, pltgot_size);
} }
// TODO(): check if this table already generated by compiler (sometimes it is missing) // TODO(): check if this table already generated by compiler (sometimes it is missing)
@@ -1398,12 +1400,12 @@ static void InstallRelocateHandler(Program* program)
{ {
program->custom_call_plt_num = program->dynamic_info->jmprela_table_size / sizeof(Elf64_Rela); program->custom_call_plt_num = program->dynamic_info->jmprela_table_size / sizeof(Elf64_Rela);
auto size = Jit::CallPlt::GetSize(program->custom_call_plt_num); auto size = Jit::CallPlt::GetSize(program->custom_call_plt_num);
program->custom_call_plt_vaddr = VirtualMemory::Alloc(SYSTEM_RESERVED, size, VirtualMemory::Mode::Write); program->custom_call_plt_vaddr = Core::VirtualMemory::Alloc(SYSTEM_RESERVED, size, Core::VirtualMemory::Mode::Write);
EXIT_NOT_IMPLEMENTED(program->custom_call_plt_vaddr == 0); EXIT_NOT_IMPLEMENTED(program->custom_call_plt_vaddr == 0);
auto* code = new (reinterpret_cast<void*>(program->custom_call_plt_vaddr)) Jit::CallPlt(program->custom_call_plt_num); auto* code = new (reinterpret_cast<void*>(program->custom_call_plt_vaddr)) Jit::CallPlt(program->custom_call_plt_num);
code->SetPltGot(pltgot_vaddr); code->SetPltGot(pltgot_vaddr);
VirtualMemory::Protect(program->custom_call_plt_vaddr, size, VirtualMemory::Mode::Execute); Core::VirtualMemory::Protect(program->custom_call_plt_vaddr, size, Core::VirtualMemory::Mode::Execute);
VirtualMemory::FlushInstructionCache(program->custom_call_plt_vaddr, size); Core::VirtualMemory::FlushInstructionCache(program->custom_call_plt_vaddr, size);
} }
} }
@@ -1415,7 +1417,7 @@ void RuntimeLinker::Relocate(Program* program)
if (g_invalid_memory == 0) if (g_invalid_memory == 0)
{ {
g_invalid_memory = VirtualMemory::Alloc(INVALID_MEMORY, 4096, VirtualMemory::Mode::NoAccess); g_invalid_memory = Core::VirtualMemory::Alloc(INVALID_MEMORY, 4096, Core::VirtualMemory::Mode::NoAccess);
EXIT_NOT_IMPLEMENTED(g_invalid_memory == 0); EXIT_NOT_IMPLEMENTED(g_invalid_memory == 0);
} }
@@ -1570,8 +1572,8 @@ void RuntimeLinker::SetupTlsHandler(Program* program)
code->SetRegSaveArea(g_tls_reg_save_area); code->SetRegSaveArea(g_tls_reg_save_area);
code->SetLockVar(&g_tls_spinlock); code->SetLockVar(&g_tls_spinlock);
VirtualMemory::Protect(program->tls.handler_vaddr, Jit::SafeCall::GetSize(), VirtualMemory::Mode::Execute); Core::VirtualMemory::Protect(program->tls.handler_vaddr, Jit::SafeCall::GetSize(), Core::VirtualMemory::Mode::Execute);
VirtualMemory::FlushInstructionCache(program->tls.handler_vaddr, Jit::SafeCall::GetSize()); Core::VirtualMemory::FlushInstructionCache(program->tls.handler_vaddr, Jit::SafeCall::GetSize());
} }
void RuntimeLinker::DeleteTlss(int thread_id) void RuntimeLinker::DeleteTlss(int thread_id)
@@ -1,497 +0,0 @@
#include "Emulator/Loader/VirtualMemory.h"
#include "Kyty/Core/DbgAssert.h"
#include "Emulator/Common.h"
#include "Emulator/Loader/Jit.h"
#include "Emulator/Profiler.h"
#include "cpuinfo.h"
//#include <atomic>
//#include <new>
// NOLINTNEXTLINE
//#define NTDDI_VERSION 0x0A000005
#include <windows.h> // IWYU pragma: keep
// IWYU pragma: no_include <minwindef.h>
// IWYU pragma: no_include <sysinfoapi.h>
// IWYU pragma: no_include <memoryapi.h>
// IWYU pragma: no_include <errhandlingapi.h>
// IWYU pragma: no_include <processthreadsapi.h>
// IWYU pragma: no_include <basetsd.h>
// IWYU pragma: no_include <excpt.h>
// IWYU pragma: no_include <wtypes.h>
// IWYU pragma: no_include <minwinbase.h>
// IWYU pragma: no_include <apisetcconv.h>
// IWYU pragma: no_include <winbase.h>
// IWYU pragma: no_include <winerror.h>
//#include <memoryapi.h>
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Loader {
SystemInfo GetSystemInfo()
{
SystemInfo ret {};
SYSTEM_INFO system_info;
GetSystemInfo(&system_info);
switch (system_info.wProcessorArchitecture)
{
case PROCESSOR_ARCHITECTURE_AMD64: ret.ProcessorArchitecture = ProcessorArchitecture::Amd64; break;
case PROCESSOR_ARCHITECTURE_UNKNOWN:
default: ret.ProcessorArchitecture = ProcessorArchitecture::Unknown;
}
ret.PageSize = system_info.dwPageSize;
ret.MinimumApplicationAddress = reinterpret_cast<uintptr_t>(system_info.lpMinimumApplicationAddress);
ret.MaximumApplicationAddress = reinterpret_cast<uintptr_t>(system_info.lpMaximumApplicationAddress);
ret.ActiveProcessorMask = system_info.dwActiveProcessorMask;
ret.NumberOfProcessors = system_info.dwNumberOfProcessors;
ret.ProcessorLevel = system_info.wProcessorLevel;
ret.ProcessorRevision = system_info.wProcessorRevision;
const auto* p = cpuinfo_get_package(0);
EXIT_IF(p == nullptr);
ret.ProcessorName = String::FromUtf8(p->name);
return ret;
}
namespace VirtualMemory {
class ExceptionHandlerPrivate
{
public:
#pragma pack(1)
struct UnwindInfo
{
uint8_t Version : 3;
uint8_t Flags : 5;
uint8_t SizeOfProlog;
uint8_t CountOfCodes;
uint8_t FrameRegister : 4;
uint8_t FrameOffset : 4;
ULONG ExceptionHandler;
ExceptionHandlerPrivate* ExceptionData;
};
struct HandlerInfo
{
Jit::JmpRax code;
RUNTIME_FUNCTION function_table = {};
UnwindInfo unwind_info = {};
};
#pragma pack()
static EXCEPTION_DISPOSITION Handler(PEXCEPTION_RECORD exception_record, ULONG64 /*EstablisherFrame*/, PCONTEXT /*ContextRecord*/,
PDISPATCHER_CONTEXT dispatcher_context)
{
ExceptionHandler::ExceptionInfo info {};
info.exception_address = reinterpret_cast<uint64_t>(exception_record->ExceptionAddress);
if (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
{
info.type = ExceptionHandler::ExceptionType::AccessViolation;
switch (exception_record->ExceptionInformation[0])
{
case 0: info.access_violation_type = ExceptionHandler::AccessViolationType::Read; break;
case 1: info.access_violation_type = ExceptionHandler::AccessViolationType::Write; break;
case 8: info.access_violation_type = ExceptionHandler::AccessViolationType::Execute; break;
default: info.access_violation_type = ExceptionHandler::AccessViolationType::Unknown; break;
}
info.access_violation_vaddr = exception_record->ExceptionInformation[1];
}
info.rbp = dispatcher_context->ContextRecord->Rbp;
info.exception_win_code = exception_record->ExceptionCode;
auto* p = *static_cast<ExceptionHandlerPrivate**>(dispatcher_context->HandlerData);
p->func(&info);
return ExceptionContinueExecution;
}
void InitHandler()
{
auto* h = new (reinterpret_cast<void*>(handler_addr)) HandlerInfo;
auto* code = &h->code;
auto* unwind_info = &h->unwind_info;
function_table = &h->function_table;
function_table->BeginAddress = 0;
function_table->EndAddress = image_size;
function_table->UnwindData = reinterpret_cast<uintptr_t>(unwind_info) - base_address;
unwind_info->Version = 1;
unwind_info->Flags = UNW_FLAG_EHANDLER;
unwind_info->SizeOfProlog = 0;
unwind_info->CountOfCodes = 0;
unwind_info->FrameRegister = 0;
unwind_info->FrameOffset = 0;
unwind_info->ExceptionHandler = reinterpret_cast<uintptr_t>(code) - base_address;
unwind_info->ExceptionData = this;
code->SetFunc(Handler);
FlushInstructionCache(reinterpret_cast<uint64_t>(code), sizeof(h->code));
}
uint64_t base_address = 0;
uint64_t handler_addr = 0;
uint64_t image_size = 0;
PRUNTIME_FUNCTION function_table = nullptr;
ExceptionHandler::handler_func_t func = nullptr;
static ExceptionHandler::handler_func_t g_vec_func;
};
ExceptionHandler::handler_func_t ExceptionHandlerPrivate::g_vec_func = nullptr;
ExceptionHandler::ExceptionHandler(): m_p(new ExceptionHandlerPrivate) {}
ExceptionHandler::~ExceptionHandler()
{
Uninstall();
delete m_p;
}
uint64_t ExceptionHandler::GetSize()
{
return (sizeof(ExceptionHandlerPrivate::HandlerInfo) & ~(static_cast<uint64_t>(0x1000) - 1)) + 0x1000;
}
bool ExceptionHandler::Install(uint64_t base_address, uint64_t handler_addr, uint64_t image_size, handler_func_t func)
{
if (m_p->function_table == nullptr)
{
m_p->base_address = base_address;
m_p->handler_addr = handler_addr;
m_p->image_size = image_size;
m_p->func = func;
m_p->InitHandler();
if (RtlAddFunctionTable(m_p->function_table, 1, base_address) == FALSE)
{
printf("RtlAddFunctionTable() failed: 0x%08" PRIx32 "\n", static_cast<uint32_t>(GetLastError()));
return false;
}
return true;
}
return false;
}
static LONG WINAPI ExceptionFilter(PEXCEPTION_POINTERS exception)
{
PEXCEPTION_RECORD exception_record = exception->ExceptionRecord;
ExceptionHandler::ExceptionInfo info {};
info.exception_address = reinterpret_cast<uint64_t>(exception_record->ExceptionAddress);
// printf("exception_record->ExceptionCode = %u\n", static_cast<uint32_t>(exception_record->ExceptionCode));
if (exception_record->ExceptionCode == DBG_PRINTEXCEPTION_C || exception_record->ExceptionCode == DBG_PRINTEXCEPTION_WIDE_C)
{
return EXCEPTION_CONTINUE_EXECUTION;
}
if (exception_record->ExceptionCode == 0x406D1388)
{
// Set a thread name
return EXCEPTION_CONTINUE_EXECUTION;
}
if (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
{
info.type = ExceptionHandler::ExceptionType::AccessViolation;
switch (exception_record->ExceptionInformation[0])
{
case 0: info.access_violation_type = ExceptionHandler::AccessViolationType::Read; break;
case 1: info.access_violation_type = ExceptionHandler::AccessViolationType::Write; break;
case 8: info.access_violation_type = ExceptionHandler::AccessViolationType::Execute; break;
default: info.access_violation_type = ExceptionHandler::AccessViolationType::Unknown; break;
}
info.access_violation_vaddr = exception_record->ExceptionInformation[1];
}
info.rbp = exception->ContextRecord->Rbp;
info.exception_win_code = exception_record->ExceptionCode;
ExceptionHandlerPrivate::g_vec_func(&info);
return EXCEPTION_CONTINUE_EXECUTION;
}
bool ExceptionHandler::InstallVectored(handler_func_t func)
{
if (ExceptionHandlerPrivate::g_vec_func == nullptr)
{
ExceptionHandlerPrivate::g_vec_func = func;
if (AddVectoredExceptionHandler(1, ExceptionFilter) == nullptr)
{
printf("AddVectoredExceptionHandler() failed\n");
return false;
}
return true;
}
return false;
}
bool ExceptionHandler::Uninstall()
{
if (m_p->function_table != nullptr)
{
if (RtlDeleteFunctionTable(m_p->function_table) == FALSE)
{
printf("RtlDeleteFunctionTable() failed: 0x%08" PRIx32 "\n", static_cast<uint32_t>(GetLastError()));
return false;
}
m_p->function_table = nullptr;
return true;
}
return false;
}
static DWORD get_protection_flag(VirtualMemory::Mode mode)
{
DWORD protect = PAGE_NOACCESS;
switch (mode)
{
case VirtualMemory::Mode::Read: protect = PAGE_READONLY; break;
case VirtualMemory::Mode::Write:
case VirtualMemory::Mode::ReadWrite: protect = PAGE_READWRITE; break;
case VirtualMemory::Mode::Execute: protect = PAGE_EXECUTE; break;
case VirtualMemory::Mode::ExecuteRead: protect = PAGE_EXECUTE_READ; break;
case VirtualMemory::Mode::ExecuteWrite:
case VirtualMemory::Mode::ExecuteReadWrite: protect = PAGE_EXECUTE_READWRITE; break;
case VirtualMemory::Mode::NoAccess:
default: protect = PAGE_NOACCESS; break;
}
return protect;
}
static VirtualMemory::Mode get_protection_flag(DWORD mode)
{
switch (mode)
{
case PAGE_NOACCESS: return VirtualMemory::Mode::NoAccess;
case PAGE_READONLY: return VirtualMemory::Mode::Read;
case PAGE_READWRITE: return VirtualMemory::Mode::ReadWrite;
case PAGE_EXECUTE: return VirtualMemory::Mode::Execute;
case PAGE_EXECUTE_READ: return VirtualMemory::Mode::ExecuteRead;
case PAGE_EXECUTE_READWRITE: return VirtualMemory::Mode::ExecuteReadWrite;
default: return VirtualMemory::Mode::NoAccess;
}
}
void Init()
{
cpuinfo_initialize();
}
uint64_t Alloc(uint64_t address, uint64_t size, Mode mode)
{
auto ptr = (address == 0 ? AllocAligned(address, size, mode, 1)
: reinterpret_cast<uintptr_t>(VirtualAlloc(reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size,
static_cast<DWORD>(MEM_COMMIT) | static_cast<DWORD>(MEM_RESERVE),
get_protection_flag(mode))));
if (ptr == 0)
{
auto err = static_cast<uint32_t>(GetLastError());
if (err != ERROR_INVALID_ADDRESS)
{
printf("VirtualAlloc() failed: 0x%08" PRIx32 "\n", err);
} else
{
return AllocAligned(address, size, mode, 1);
}
}
return ptr;
}
using VirtualAlloc2_func_t = /*WINBASEAPI*/ PVOID WINAPI (*)(HANDLE, PVOID, SIZE_T, ULONG, ULONG, MEM_EXTENDED_PARAMETER*, ULONG);
static VirtualAlloc2_func_t ResolveVirtualAlloc2()
{
HMODULE h = GetModuleHandle("KernelBase");
if (h != nullptr)
{
return reinterpret_cast<VirtualAlloc2_func_t>(GetProcAddress(h, "VirtualAlloc2"));
}
return nullptr;
}
uint64_t AllocAligned(uint64_t address, uint64_t size, Mode mode, uint64_t alignment)
{
if (alignment == 0)
{
printf("VirtualAlloc2 failed: 0x%08" PRIx32 "\n", static_cast<uint32_t>(GetLastError()));
return 0;
}
static constexpr uint64_t SYSTEM_MANAGED_MIN = 0x0000040000u;
static constexpr uint64_t SYSTEM_MANAGED_MAX = 0x07FFFFBFFFu;
static constexpr uint64_t USER_MIN = 0x1000000000u;
static constexpr uint64_t USER_MAX = 0xFBFFFFFFFFu;
MEM_ADDRESS_REQUIREMENTS req {};
MEM_EXTENDED_PARAMETER param {};
req.LowestStartingAddress = (address == 0 ? reinterpret_cast<PVOID>(SYSTEM_MANAGED_MIN) : reinterpret_cast<PVOID>(address));
req.HighestEndingAddress = (address == 0 ? reinterpret_cast<PVOID>(SYSTEM_MANAGED_MAX) : reinterpret_cast<PVOID>(USER_MAX));
req.Alignment = alignment;
param.Type = MemExtendedParameterAddressRequirements;
param.Pointer = &req;
MEM_ADDRESS_REQUIREMENTS req2 {};
MEM_EXTENDED_PARAMETER param2 {};
req2.LowestStartingAddress = (address == 0 ? reinterpret_cast<PVOID>(USER_MIN) : reinterpret_cast<PVOID>(address));
req2.HighestEndingAddress = reinterpret_cast<PVOID>(USER_MAX);
req2.Alignment = alignment;
param2.Type = MemExtendedParameterAddressRequirements;
param2.Pointer = &req2;
static auto virtual_alloc2 = ResolveVirtualAlloc2();
EXIT_NOT_IMPLEMENTED(virtual_alloc2 == nullptr);
auto ptr = reinterpret_cast<uintptr_t>(virtual_alloc2(GetCurrentProcess(), nullptr, size,
static_cast<DWORD>(MEM_COMMIT) | static_cast<DWORD>(MEM_RESERVE),
get_protection_flag(mode), &param, 1));
if (ptr == 0)
{
ptr = reinterpret_cast<uintptr_t>(virtual_alloc2(GetCurrentProcess(), nullptr, size,
static_cast<DWORD>(MEM_COMMIT) | static_cast<DWORD>(MEM_RESERVE),
get_protection_flag(mode), &param2, 1));
}
if (ptr == 0)
{
auto err = static_cast<uint32_t>(GetLastError());
if (err != ERROR_INVALID_PARAMETER)
{
printf("VirtualAlloc2(alignment = 0x%016" PRIx64 ") failed: 0x%08" PRIx32 "\n", alignment, err);
} else
{
return AllocAligned(address, size, mode, alignment << 1u);
}
}
return ptr;
}
bool AllocFixed(uint64_t address, uint64_t size, Mode mode)
{
auto ptr = reinterpret_cast<uintptr_t>(VirtualAlloc(reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size,
static_cast<DWORD>(MEM_COMMIT) | static_cast<DWORD>(MEM_RESERVE),
get_protection_flag(mode)));
if (ptr == 0)
{
auto err = static_cast<uint32_t>(GetLastError());
printf("VirtualAlloc() failed: 0x%08" PRIx32 "\n", err);
return false;
}
if (ptr != address)
{
printf("VirtualAlloc() failed: wrong address\n");
VirtualFree(reinterpret_cast<LPVOID>(ptr), 0, MEM_RELEASE);
return false;
}
return true;
}
bool Free(uint64_t address)
{
if (VirtualFree(reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), 0, MEM_RELEASE) == 0)
{
printf("VirtualFree() failed: 0x%08" PRIx32 "\n", static_cast<uint32_t>(GetLastError()));
return false;
}
return true;
}
bool Protect(uint64_t address, uint64_t size, Mode mode, Mode* old_mode)
{
KYTY_PROFILER_FUNCTION();
DWORD old_protect = 0;
if (VirtualProtect(reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size, get_protection_flag(mode), &old_protect) == 0)
{
printf("VirtualProtect() failed: 0x%08" PRIx32 "\n", static_cast<uint32_t>(GetLastError()));
return false;
}
if (old_mode != nullptr)
{
*old_mode = get_protection_flag(old_protect);
}
return true;
}
bool FlushInstructionCache(uint64_t address, uint64_t size)
{
if (::FlushInstructionCache(GetCurrentProcess(), reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size) == 0)
{
printf("FlushInstructionCache() failed: 0x%08" PRIx32 "\n", static_cast<uint32_t>(GetLastError()));
return false;
}
return true;
}
bool PatchReplace(uint64_t vaddr, uint64_t value)
{
KYTY_PROFILER_FUNCTION();
VirtualMemory::Mode old_mode {};
VirtualMemory::Protect(vaddr, 8, VirtualMemory::Mode::ReadWrite, &old_mode);
auto* ptr = reinterpret_cast<uint64_t*>(vaddr);
bool ret = (*ptr != value);
*ptr = value;
VirtualMemory::Protect(vaddr, 8, old_mode);
if (VirtualMemory::IsExecute(old_mode))
{
VirtualMemory::FlushInstructionCache(vaddr, 8);
}
return ret;
}
} // namespace VirtualMemory
} // namespace Kyty::Loader
#endif // KYTY_EMU_ENABLED
+1 -5
View File
@@ -29,11 +29,7 @@ bool dbg_is_debugger_present();
} // namespace Kyty::Core } // namespace Kyty::Core
//#if KYTY_COMPILER == KYTY_COMPILER_MINGW #if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS || KYTY_PLATFORM == KYTY_PLATFORM_LINUX
//#pragma GCC diagnostic ignored "-Warray-bounds"
//#endif
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
#define ASSERT_HALT() \ #define ASSERT_HALT() \
(Kyty::Core::dbg_is_debugger_present() ? (::fflush(nullptr), *(reinterpret_cast<volatile int*>(1)) = 0) \ (Kyty::Core::dbg_is_debugger_present() ? (::fflush(nullptr), *(reinterpret_cast<volatile int*>(1)) = 0) \
: (Kyty::Core::dbg_exit(321), 1)) : (Kyty::Core::dbg_exit(321), 1))
+1 -1
View File
@@ -93,7 +93,7 @@ public:
virtual ~CondVar(); virtual ~CondVar();
void Wait(Mutex* mutex); void Wait(Mutex* mutex);
void WaitFor(Mutex* mutex, uint32_t micros); bool WaitFor(Mutex* mutex, uint32_t micros);
void Signal(); void Signal();
void SignalAll(); void SignalAll();
@@ -1,33 +1,14 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_LOADER_VIRTUALMEMORY_H_ #ifndef INCLUDE_KYTY_CORE_VIRTUALMEMORY_H_
#define EMULATOR_INCLUDE_EMULATOR_LOADER_VIRTUALMEMORY_H_ #define INCLUDE_KYTY_CORE_VIRTUALMEMORY_H_
#include "Kyty/Core/Common.h" #include "Kyty/Core/Common.h"
#include "Kyty/Core/String.h" #include "Kyty/Core/String.h"
#include "Emulator/Common.h" namespace Kyty::Core {
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Loader {
enum class ProcessorArchitecture
{
Unknown,
Amd64, // x64 (AMD or Intel)
};
struct SystemInfo struct SystemInfo
{ {
uint32_t PageSize; String ProcessorName;
uint64_t MinimumApplicationAddress;
uint64_t MaximumApplicationAddress;
uint32_t ActiveProcessorMask;
uint32_t NumberOfProcessors;
ProcessorArchitecture ProcessorArchitecture;
uint32_t AllocationGranularity;
uint16_t ProcessorLevel;
uint16_t ProcessorRevision;
String ProcessorName;
}; };
SystemInfo GetSystemInfo(); SystemInfo GetSystemInfo();
@@ -110,8 +91,6 @@ bool PatchReplace(uint64_t vaddr, uint64_t value);
} // namespace VirtualMemory } // namespace VirtualMemory
} // namespace Kyty::Loader } // namespace Kyty::Core
#endif // KYTY_EMU_ENABLED #endif /* INCLUDE_KYTY_CORE_VIRTUALMEMORY_H_ */
#endif /* EMULATOR_INCLUDE_EMULATOR_LOADER_VIRTUALMEMORY_H_ */
@@ -9,6 +9,7 @@
namespace Kyty { namespace Kyty {
// NOLINTNEXTLINE(readability-identifier-naming)
struct sys_dbg_stack_info_t struct sys_dbg_stack_info_t
{ {
uintptr_t code_addr; uintptr_t code_addr;
@@ -8,25 +8,28 @@
#else #else
#include "Kyty/Core/String.h" #include "Kyty/Core/String.h"
#include "Kyty/Sys/SysLinuxTimer.h" #include "Kyty/Sys/Linux/SysLinuxTimer.h"
namespace Kyty { namespace Kyty {
// NOLINTNEXTLINE(readability-identifier-naming)
enum sys_file_type_t enum sys_file_type_t
{ {
SYS_FILE_ERROR, SYS_FILE_ERROR, // NOLINT(readability-identifier-naming)
SYS_FILE_MEMORY_STAT, SYS_FILE_MEMORY_STAT, // NOLINT(readability-identifier-naming)
SYS_FILE_FILE, SYS_FILE_FILE, // NOLINT(readability-identifier-naming)
SYS_FILE_MEMORY_DYN SYS_FILE_MEMORY_DYN // NOLINT(readability-identifier-naming)
}; };
// NOLINTNEXTLINE(readability-identifier-naming)
enum sys_file_cache_type_t enum sys_file_cache_type_t
{ {
SYS_FILE_CACHE_AUTO = 0, SYS_FILE_CACHE_AUTO = 0, // NOLINT(readability-identifier-naming)
SYS_FILE_CACHE_RANDOM_ACCESS = 1, SYS_FILE_CACHE_RANDOM_ACCESS = 1, // NOLINT(readability-identifier-naming)
SYS_FILE_CACHE_SEQUENTIAL_SCAN = 2 SYS_FILE_CACHE_SEQUENTIAL_SCAN = 2 // NOLINT(readability-identifier-naming)
}; };
// NOLINTNEXTLINE(readability-identifier-naming)
struct sys_file_mem_buf_t struct sys_file_mem_buf_t
{ {
uint8_t* base; uint8_t* base;
@@ -34,6 +37,7 @@ struct sys_file_mem_buf_t
uint32_t size; uint32_t size;
}; };
// NOLINTNEXTLINE(readability-identifier-naming)
struct sys_file_t struct sys_file_t
{ {
sys_file_type_t type; sys_file_type_t type;
@@ -44,6 +48,7 @@ struct sys_file_t
}; };
}; };
// NOLINTNEXTLINE(readability-identifier-naming)
struct sys_file_find_t struct sys_file_find_t
{ {
String path_with_name; String path_with_name;
@@ -52,14 +57,15 @@ struct sys_file_find_t
uint64_t size; uint64_t size;
}; };
// NOLINTNEXTLINE(readability-identifier-naming)
struct sys_dir_entry_t struct sys_dir_entry_t
{ {
String name; String name;
bool is_file; bool is_file;
}; };
void sys_file_read(void* data, uint32_t size, sys_file_t& f, uint32_t* bytes_read = 0); void sys_file_read(void* data, uint32_t size, sys_file_t& f, uint32_t* bytes_read = nullptr);
void sys_file_write(const void* data, uint32_t size, sys_file_t& f, uint32_t* bytes_written = 0); void sys_file_write(const void* data, uint32_t size, sys_file_t& f, uint32_t* bytes_written = nullptr);
void sys_file_read_r(void* data, uint32_t size, sys_file_t& f); void sys_file_read_r(void* data, uint32_t size, sys_file_t& f);
void sys_file_write_r(const void* data, uint32_t size, sys_file_t& f); void sys_file_write_r(const void* data, uint32_t size, sys_file_t& f);
sys_file_t* sys_file_create(const String& file_name); sys_file_t* sys_file_create(const String& file_name);
@@ -0,0 +1,104 @@
#ifndef SYS_LINUX_INCLUDE_KYTY_SYSHEAP_H_
#define SYS_LINUX_INCLUDE_KYTY_SYSHEAP_H_
// IWYU pragma: private
#if KYTY_PLATFORM != KYTY_PLATFORM_LINUX
//#error "KYTY_PLATFORM != KYTY_PLATFORM_LINUX"
#else
#include "Kyty/Sys/Linux/SysLinuxSync.h"
namespace Kyty {
using sys_heap_id_t = SysCS*;
inline sys_heap_id_t sys_heap_create()
{
return nullptr;
}
inline sys_heap_id_t sys_heap_deafult()
{
return nullptr;
}
inline void* sys_heap_alloc(sys_heap_id_t /*heap_id*/, size_t size)
{
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc,hicpp-no-malloc)
void* m = malloc(size);
EXIT_IF(m == nullptr);
return m;
}
inline void* sys_heap_realloc(sys_heap_id_t /*heap_id*/, void* p, size_t size)
{
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc,hicpp-no-malloc)
void* m = p != nullptr ? realloc(p, size) : malloc(size);
if (m == nullptr)
{
EXIT_IF(m == nullptr);
}
return m;
}
inline void sys_heap_free(sys_heap_id_t /*heap_id*/, void* p)
{
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc,hicpp-no-malloc)
free(p);
}
inline sys_heap_id_t sys_heap_create_s()
{
auto* cs = new SysCS;
cs->Init();
return cs;
}
inline void* sys_heap_alloc_s(sys_heap_id_t heap_id, size_t size)
{
heap_id->Enter();
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc,hicpp-no-malloc)
void* m = malloc(size);
heap_id->Leave();
EXIT_IF(m == nullptr);
return m;
}
inline void* sys_heap_realloc_s(sys_heap_id_t heap_id, void* p, size_t size)
{
heap_id->Enter();
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc,hicpp-no-malloc)
void* m = p != nullptr ? realloc(p, size) : malloc(size);
heap_id->Leave();
EXIT_IF(m == nullptr);
return m;
}
inline void sys_heap_free_s(sys_heap_id_t heap_id, void* p)
{
heap_id->Enter();
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc,hicpp-no-malloc)
free(p);
heap_id->Leave();
}
} // namespace Kyty
#endif
#endif /* SYS_LINUX_INCLUDE_KYTY_SYSHEAP_H_ */
@@ -8,22 +8,22 @@
#else #else
//#include <stdio.h> //#include <stdio.h>
#include <cstdarg>
namespace Kyty { namespace Kyty {
inline uint32_t sys_vscprintf(const char* format, va_list argptr) inline uint32_t sys_vscprintf(const char* format, va_list argptr)
{ {
int len;
va_list argcopy; va_list argcopy;
va_copy(argcopy, argptr); va_copy(argcopy, argptr);
len = vsnprintf(0, 0, format, argcopy); int len = vsnprintf(nullptr, 0, format, argcopy);
va_end(argcopy); va_end(argcopy);
return len < 0 ? 0 : len; return len < 0 ? 0 : len;
} }
inline uint32_t sys_vsnprintf(char* Dest, size_t Count, const char* Format, va_list Args) inline uint32_t sys_vsnprintf(char* dest, size_t count, const char* format, va_list args)
{ {
int len = vsnprintf(Dest, Count + 1, Format, Args); int len = vsnprintf(dest, count + 1, format, args);
return len < 0 ? 0 : len; return len < 0 ? 0 : len;
} }
@@ -21,12 +21,12 @@ inline double sys_strtod(const char* nptr, char** endptr)
inline int32_t sys_strtoi32(const char* nptr, char** endptr, int base) inline int32_t sys_strtoi32(const char* nptr, char** endptr, int base)
{ {
long r = strtol(nptr, endptr, base); int64_t r = strtol(nptr, endptr, base);
if (r >= static_cast<long>(INT32_MAX)) if (r >= static_cast<int64_t>(INT32_MAX))
{ {
return INT32_MAX; return INT32_MAX;
} }
if (r <= static_cast<long>(INT32_MIN)) if (r <= static_cast<int64_t>(INT32_MIN))
{ {
return INT32_MIN; return INT32_MIN;
} }
@@ -15,64 +15,66 @@ namespace Kyty {
class SysCS class SysCS
{ {
public: public:
SysCS() { check_ptr = 0; } SysCS() = default;
void Init() void Init()
{ {
EXIT_IF(check_ptr != 0); EXIT_IF(m_check_ptr != nullptr);
check_ptr = this; m_check_ptr = this;
pthread_mutexattr_t attr; pthread_mutexattr_t attr {};
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
pthread_mutex_init(&m, &attr); pthread_mutex_init(&m_mutex, &attr);
pthread_mutexattr_destroy(&attr); pthread_mutexattr_destroy(&attr);
} }
void Delete() void Delete()
{ {
EXIT_IF(check_ptr != this); EXIT_IF(m_check_ptr != this);
check_ptr = 0; m_check_ptr = nullptr;
pthread_mutex_destroy(&m); pthread_mutex_destroy(&m_mutex);
} }
~SysCS() { EXIT_IF(check_ptr != 0); } ~SysCS() { EXIT_IF(m_check_ptr != nullptr); }
void Enter() void Enter()
{ {
EXIT_IF(check_ptr != this); EXIT_IF(m_check_ptr != this);
pthread_mutex_lock(&m); pthread_mutex_lock(&m_mutex);
} }
bool TryEnter() bool TryEnter()
{ {
EXIT_IF(check_ptr != this); EXIT_IF(m_check_ptr != this);
return pthread_mutex_trylock(&m) == 0; return pthread_mutex_trylock(&m_mutex) == 0;
} }
void Leave() void Leave()
{ {
EXIT_IF(check_ptr != this); EXIT_IF(m_check_ptr != this);
pthread_mutex_unlock(&m); pthread_mutex_unlock(&m_mutex);
} }
KYTY_CLASS_NO_COPY(SysCS); KYTY_CLASS_NO_COPY(SysCS);
private: private:
SysCS* check_ptr; SysCS* m_check_ptr = nullptr;
pthread_mutex_t m; pthread_mutex_t m_mutex {};
}; };
inline void sys_sleep(uint32_t ms) inline void sys_sleep(uint32_t ms)
{ {
struct timespec ts; struct timespec ts
{
};
ts.tv_sec = ms / 1000; ts.tv_sec = ms / 1000;
ts.tv_nsec = (ms % 1000) * 1000000; ts.tv_nsec = static_cast<int64_t>(ms % 1000) * 1000000;
nanosleep(&ts, 0); nanosleep(&ts, nullptr);
} }
} // namespace Kyty } // namespace Kyty
@@ -31,9 +31,11 @@ struct SysFileTimeStruct
inline void sys_file_to_system_time_utc(const SysFileTimeStruct& f, SysTimeStruct& t) inline void sys_file_to_system_time_utc(const SysFileTimeStruct& f, SysTimeStruct& t)
{ {
struct tm i; struct tm i
{
};
if (f.is_invalid || !gmtime_r(&f.time, &i)) if (f.is_invalid || gmtime_r(&f.time, &i) == nullptr)
{ {
t.is_invalid = true; t.is_invalid = true;
return; return;
@@ -51,7 +53,7 @@ inline void sys_file_to_system_time_utc(const SysFileTimeStruct& f, SysTimeStruc
inline void sys_time_t_to_system(time_t t, SysTimeStruct& s) inline void sys_time_t_to_system(time_t t, SysTimeStruct& s)
{ {
SysFileTimeStruct ft; SysFileTimeStruct ft {};
ft.time = t; ft.time = t;
ft.is_invalid = false; ft.is_invalid = false;
sys_file_to_system_time_utc(ft, s); sys_file_to_system_time_utc(ft, s);
@@ -66,7 +68,9 @@ inline time_t sys_timegm(struct tm* tm)
inline void sys_system_to_file_time_utc(const SysTimeStruct& f, SysFileTimeStruct& t) inline void sys_system_to_file_time_utc(const SysTimeStruct& f, SysFileTimeStruct& t)
{ {
struct tm i; struct tm i
{
};
i.tm_year = f.Year - 1900; i.tm_year = f.Year - 1900;
i.tm_mon = f.Month - 1; i.tm_mon = f.Month - 1;
@@ -75,22 +79,18 @@ inline void sys_system_to_file_time_utc(const SysTimeStruct& f, SysFileTimeStruc
i.tm_min = f.Minute; i.tm_min = f.Minute;
i.tm_sec = f.Second; i.tm_sec = f.Second;
if (f.is_invalid || (t.time = sys_timegm(&i)) == (time_t)-1) t.is_invalid = (f.is_invalid || (t.time = sys_timegm(&i)) == static_cast<time_t>(-1));
{
t.is_invalid = true;
} else
{
t.is_invalid = false;
}
} }
// Retrieves the current local date and time // Retrieves the current local date and time
inline void sys_get_system_time(SysTimeStruct& t) inline void sys_get_system_time(SysTimeStruct& t)
{ {
time_t st; time_t st {};
struct tm i; struct tm i
{
};
if (time(&st) == (time_t)-1 || !localtime_r(&st, &i)) if (time(&st) == static_cast<time_t>(-1) || localtime_r(&st, &i) == nullptr)
{ {
t.is_invalid = true; t.is_invalid = true;
return; return;
@@ -109,10 +109,12 @@ inline void sys_get_system_time(SysTimeStruct& t)
// Retrieves the current system date and time in Coordinated Universal Time (UTC). // Retrieves the current system date and time in Coordinated Universal Time (UTC).
inline void sys_get_system_time_utc(SysTimeStruct& t) inline void sys_get_system_time_utc(SysTimeStruct& t)
{ {
time_t st; time_t st {};
struct tm i; struct tm i
{
};
if (time(&st) == (time_t)-1 || !gmtime_r(&st, &i)) if (time(&st) == static_cast<time_t>(-1) || gmtime_r(&st, &i) == nullptr)
{ {
t.is_invalid = true; t.is_invalid = true;
return; return;
@@ -135,7 +137,9 @@ inline void sys_query_performance_frequency(uint64_t* freq)
inline void sys_query_performance_counter(uint64_t* counter) inline void sys_query_performance_counter(uint64_t* counter)
{ {
struct timespec now; struct timespec now
{
};
clock_gettime(CLOCK_MONOTONIC, &now); clock_gettime(CLOCK_MONOTONIC, &now);
*counter = now.tv_sec * 1000000000LL + now.tv_nsec; *counter = now.tv_sec * 1000000000LL + now.tv_nsec;
} }
@@ -0,0 +1,30 @@
#ifndef INCLUDE_KYTY_SYS_LINUX_SYSLINUXVIRTUAL_H_
#define INCLUDE_KYTY_SYS_LINUX_SYSLINUXVIRTUAL_H_
#if KYTY_PLATFORM != KYTY_PLATFORM_LINUX
//#error "KYTY_PLATFORM != KYTY_PLATFORM_LINUX"
#else
#include "Kyty/Core/Common.h"
#include "Kyty/Core/String.h"
#include "Kyty/Core/VirtualMemory.h"
namespace Kyty::Core {
void sys_get_system_info(SystemInfo* info);
void sys_virtual_init();
uint64_t sys_virtual_alloc(uint64_t address, uint64_t size, VirtualMemory::Mode mode);
uint64_t sys_virtual_alloc_aligned(uint64_t address, uint64_t size, VirtualMemory::Mode mode, uint64_t alignment);
bool sys_virtual_alloc_fixed(uint64_t address, uint64_t size, VirtualMemory::Mode mode);
bool sys_virtual_free(uint64_t address);
bool sys_virtual_protect(uint64_t address, uint64_t size, VirtualMemory::Mode mode, VirtualMemory::Mode* old_mode = nullptr);
bool sys_virtual_flush_instruction_cache(uint64_t address, uint64_t size);
bool sys_virtual_patch_replace(uint64_t vaddr, uint64_t value);
} // namespace Kyty::Core
#endif
#endif /* INCLUDE_KYTY_SYS_LINUX_SYSLINUXVIRTUAL_H_ */
+2 -3
View File
@@ -2,8 +2,7 @@
#define INCLUDE_KYTY_SYS_SYSDBG_H_ #define INCLUDE_KYTY_SYS_SYSDBG_H_
#include "Kyty/Core/Common.h" #include "Kyty/Core/Common.h"
#include "Kyty/Sys/Linux/SysLinuxDbg.h" // IWYU pragma: export
#include "Kyty/Sys/SysLinuxDbg.h" // IWYU pragma: export #include "Kyty/Sys/Windows/SysWindowsDbg.h" // IWYU pragma: export
#include "Kyty/Sys/SysWindowsDbg.h" // IWYU pragma: export
#endif /* INCLUDE_KYTY_SYS_SYSDBG_H_ */ #endif /* INCLUDE_KYTY_SYS_SYSDBG_H_ */
+2 -3
View File
@@ -2,8 +2,7 @@
#define INCLUDE_KYTY_SYS_SYSFILEIO_H_ #define INCLUDE_KYTY_SYS_SYSFILEIO_H_
#include "Kyty/Core/Common.h" #include "Kyty/Core/Common.h"
#include "Kyty/Sys/Linux/SysLinuxFileIO.h" // IWYU pragma: export
#include "Kyty/Sys/SysLinuxFileIO.h" // IWYU pragma: export #include "Kyty/Sys/Windows/SysWindowsFileIO.h" // IWYU pragma: export
#include "Kyty/Sys/SysWindowsFileIO.h" // IWYU pragma: export
#endif /* INCLUDE_KYTY_SYS_SYSFILEIO_H_ */ #endif /* INCLUDE_KYTY_SYS_SYSFILEIO_H_ */
+2 -3
View File
@@ -2,8 +2,7 @@
#define INCLUDE_KYTY_SYS_SYSHEAP_H_ #define INCLUDE_KYTY_SYS_SYSHEAP_H_
#include "Kyty/Core/Common.h" #include "Kyty/Core/Common.h"
#include "Kyty/Sys/Linux/SysLinuxHeap.h" // IWYU pragma: export
#include "Kyty/Sys/SysLinuxHeap.h" // IWYU pragma: export #include "Kyty/Sys/Windows/SysWindowsHeap.h" // IWYU pragma: export
#include "Kyty/Sys/SysWindowsHeap.h" // IWYU pragma: export
#endif /* INCLUDE_KYTY_SYS_SYSHEAP_H_ */ #endif /* INCLUDE_KYTY_SYS_SYSHEAP_H_ */
-98
View File
@@ -1,98 +0,0 @@
#ifndef SYS_LINUX_INCLUDE_KYTY_SYSHEAP_H_
#define SYS_LINUX_INCLUDE_KYTY_SYSHEAP_H_
// IWYU pragma: private
#if KYTY_PLATFORM != KYTY_PLATFORM_LINUX
//#error "KYTY_PLATFORM != KYTY_PLATFORM_LINUX"
#else
#include "Kyty/Sys/SysLinuxSync.h"
namespace Kyty {
typedef SysCS* sys_heap_id_t;
inline sys_heap_id_t sys_heap_create()
{
return 0;
}
inline sys_heap_id_t sys_heap_deafult()
{
return 0;
}
inline void* sys_heap_alloc(sys_heap_id_t heap_id, size_t size)
{
void* m = malloc(size);
EXIT_IF(m == 0);
return m;
}
inline void* sys_heap_realloc(sys_heap_id_t heap_id, void* p, size_t size)
{
void* m = p ? realloc(p, size) : malloc(size);
if (m == 0)
{
EXIT_IF(m == 0);
}
return m;
}
inline void sys_heap_free(sys_heap_id_t heap_id, void* p)
{
free(p);
}
inline sys_heap_id_t sys_heap_create_s()
{
SysCS* cs = new SysCS;
cs->Init();
return cs;
}
inline void* sys_heap_alloc_s(sys_heap_id_t heap_id, size_t size)
{
heap_id->Enter();
void* m = malloc(size);
heap_id->Leave();
EXIT_IF(m == 0);
return m;
}
inline void* sys_heap_realloc_s(sys_heap_id_t heap_id, void* p, size_t size)
{
heap_id->Enter();
void* m = p ? realloc(p, size) : malloc(size);
heap_id->Leave();
EXIT_IF(m == 0);
return m;
}
inline void sys_heap_free_s(sys_heap_id_t heap_id, void* p)
{
heap_id->Enter();
free(p);
heap_id->Leave();
}
} // namespace Kyty
#endif
#endif /* SYS_LINUX_INCLUDE_KYTY_SYSHEAP_H_ */
+2 -3
View File
@@ -2,8 +2,7 @@
#define INCLUDE_KYTY_SYS_SYSSTDIO_H_ #define INCLUDE_KYTY_SYS_SYSSTDIO_H_
#include "Kyty/Core/Common.h" #include "Kyty/Core/Common.h"
#include "Kyty/Sys/Linux/SysLinuxStdio.h" // IWYU pragma: export
#include "Kyty/Sys/SysLinuxStdio.h" // IWYU pragma: export #include "Kyty/Sys/Windows/SysWindowsStdio.h" // IWYU pragma: export
#include "Kyty/Sys/SysWindowsStdio.h" // IWYU pragma: export
#endif /* INCLUDE_KYTY_SYS_SYSSTDIO_H_ */ #endif /* INCLUDE_KYTY_SYS_SYSSTDIO_H_ */
+2 -3
View File
@@ -2,8 +2,7 @@
#define INCLUDE_KYTY_SYS_SYSSTDLIB_H_ #define INCLUDE_KYTY_SYS_SYSSTDLIB_H_
#include "Kyty/Core/Common.h" #include "Kyty/Core/Common.h"
#include "Kyty/Sys/Linux/SysLinuxStdlib.h" // IWYU pragma: export
#include "Kyty/Sys/SysLinuxStdlib.h" // IWYU pragma: export #include "Kyty/Sys/Windows/SysWindowsStdlib.h" // IWYU pragma: export
#include "Kyty/Sys/SysWindowsStdlib.h" // IWYU pragma: export
#endif /* INCLUDE_KYTY_SYS_SYSSTDLIB_H_ */ #endif /* INCLUDE_KYTY_SYS_SYSSTDLIB_H_ */
+2 -3
View File
@@ -2,8 +2,7 @@
#define INCLUDE_KYTY_SYS_SYSSYNC_H_ #define INCLUDE_KYTY_SYS_SYSSYNC_H_
#include "Kyty/Core/Common.h" #include "Kyty/Core/Common.h"
#include "Kyty/Sys/Linux/SysLinuxSync.h" // IWYU pragma: export
#include "Kyty/Sys/SysLinuxSync.h" // IWYU pragma: export #include "Kyty/Sys/Windows/SysWindowsSync.h" // IWYU pragma: export
#include "Kyty/Sys/SysWindowsSync.h" // IWYU pragma: export
#endif /* INCLUDE_KYTY_SYS_SYSSYNC_H_ */ #endif /* INCLUDE_KYTY_SYS_SYSSYNC_H_ */
+2 -3
View File
@@ -2,8 +2,7 @@
#define INCLUDE_KYTY_SYS_SYSTIMER_H_ #define INCLUDE_KYTY_SYS_SYSTIMER_H_
#include "Kyty/Core/Common.h" #include "Kyty/Core/Common.h"
#include "Kyty/Sys/Linux/SysLinuxTimer.h" // IWYU pragma: export
#include "Kyty/Sys/SysLinuxTimer.h" // IWYU pragma: export #include "Kyty/Sys/Windows/SysWindowsTimer.h" // IWYU pragma: export
#include "Kyty/Sys/SysWindowsTimer.h" // IWYU pragma: export
#endif /* INCLUDE_KYTY_SYS_SYSTIMER_H_ */ #endif /* INCLUDE_KYTY_SYS_SYSTIMER_H_ */
+8
View File
@@ -0,0 +1,8 @@
#ifndef INCLUDE_KYTY_SYS_SYSVIRTUAL_H_
#define INCLUDE_KYTY_SYS_SYSVIRTUAL_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Sys/Linux/SysLinuxVirtual.h" // IWYU pragma: export
#include "Kyty/Sys/Windows/SysWindowsVirtual.h" // IWYU pragma: export
#endif /* INCLUDE_KYTY_SYS_SYSVIRTUAL_H_ */
@@ -0,0 +1,30 @@
#ifndef INCLUDE_KYTY_SYS_WINDOWS_SYSWINDOWSVIRTUAL_H_
#define INCLUDE_KYTY_SYS_WINDOWS_SYSWINDOWSVIRTUAL_H_
#if KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS
//#error "KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS"
#else
#include "Kyty/Core/Common.h"
#include "Kyty/Core/String.h"
#include "Kyty/Core/VirtualMemory.h"
namespace Kyty::Core {
void sys_get_system_info(SystemInfo* info);
void sys_virtual_init();
uint64_t sys_virtual_alloc(uint64_t address, uint64_t size, VirtualMemory::Mode mode);
uint64_t sys_virtual_alloc_aligned(uint64_t address, uint64_t size, VirtualMemory::Mode mode, uint64_t alignment);
bool sys_virtual_alloc_fixed(uint64_t address, uint64_t size, VirtualMemory::Mode mode);
bool sys_virtual_free(uint64_t address);
bool sys_virtual_protect(uint64_t address, uint64_t size, VirtualMemory::Mode mode, VirtualMemory::Mode* old_mode = nullptr);
bool sys_virtual_flush_instruction_cache(uint64_t address, uint64_t size);
bool sys_virtual_patch_replace(uint64_t vaddr, uint64_t value);
} // namespace Kyty::Core
#endif
#endif /* INCLUDE_KYTY_SYS_WINDOWS_SYSWINDOWSVIRTUAL_H_ */
+22 -13
View File
@@ -28,8 +28,10 @@ add_executable(launcher WIN32
target_link_libraries(launcher Qt5::Widgets) target_link_libraries(launcher Qt5::Widgets)
if(MSVC OR MINGW)
target_link_libraries(launcher psapi) target_link_libraries(launcher psapi)
target_link_libraries(launcher setupapi) target_link_libraries(launcher setupapi)
endif()
if (CLANG AND NOT MSVC) if (CLANG AND NOT MSVC)
target_link_libraries(launcher pthread) target_link_libraries(launcher pthread)
endif() endif()
@@ -45,9 +47,11 @@ endif()
add_dependencies(launcher KytyGitVersion) add_dependencies(launcher KytyGitVersion)
find_program(QT_WINDEPLOYQT NAMES windeployqt PATHS "${Qt5_DIR}/../../../bin") if(NOT LINUX)
if(NOT QT_WINDEPLOYQT) find_program(QT_WINDEPLOYQT NAMES windeployqt PATHS "${Qt5_DIR}/../../../bin")
message(FATAL_ERROR "Could not find windeployqt") if(NOT QT_WINDEPLOYQT)
message(FATAL_ERROR "Could not find windeployqt")
endif()
endif() endif()
set(launcher_name "launcher") set(launcher_name "launcher")
@@ -56,17 +60,19 @@ set_target_properties(launcher PROPERTIES OUTPUT_NAME ${launcher_name})
install(TARGETS launcher DESTINATION .) install(TARGETS launcher DESTINATION .)
install(CODE " if(NOT LINUX)
execute_process( install(CODE "
COMMAND ${QT_WINDEPLOYQT} \"\${CMAKE_INSTALL_PREFIX}/${launcher_name}.exe\" execute_process(
COMMAND ${QT_WINDEPLOYQT} \"\${CMAKE_INSTALL_PREFIX}/${launcher_name}.exe\"
--no-svg --no-svg
--no-angle --no-angle
--no-opengl --no-opengl
--no-opengl-sw --no-opengl-sw
--no-system-d3d-compiler --no-system-d3d-compiler
--no-translations --no-translations
) )
") ")
endif()
qt5_create_translation(QM_FILES ${launcher_src} ${launcher_forms} ${launcher_ts} OPTIONS -I ${CMAKE_SOURCE_DIR}/launcher/include) qt5_create_translation(QM_FILES ${launcher_src} ${launcher_forms} ${launcher_ts} OPTIONS -I ${CMAKE_SOURCE_DIR}/launcher/include)
@@ -79,10 +85,13 @@ get_property(inc_headers TARGET launcher PROPERTY INCLUDE_DIRECTORIES)
list(APPEND inc_headers list(APPEND inc_headers
${CMAKE_SOURCE_DIR}/launcher ${CMAKE_SOURCE_DIR}/launcher
${CMAKE_BINARY_DIR}/launcher/launcher_autogen/include ${CMAKE_BINARY_DIR}/launcher/launcher_autogen/include
${Qt5_DIR}/../../../include ${Qt5Widgets_INCLUDE_DIRS}
${Qt5_DIR}/../../../include/QtWidgets ${Qt5Core_INCLUDE_DIRS}
${Qt5_DIR}/../../../include/QtCore ${Qt5Gui_INCLUDE_DIRS}
${Qt5_DIR}/../../../include/QtGui #${Qt5_DIR}/../../../include
#${Qt5_DIR}/../../../include/QtWidgets
#${Qt5_DIR}/../../../include/QtCore
#${Qt5_DIR}/../../../include/QtGui
) )
include_what_you_use_with_mappings(launcher "${inc_headers}" "${iwyu_maps}") include_what_you_use_with_mappings(launcher "${inc_headers}" "${iwyu_maps}")
+1 -1
View File
@@ -30,7 +30,7 @@ public:
explicit MainDialog(QWidget* parent = nullptr); explicit MainDialog(QWidget* parent = nullptr);
~MainDialog() override = default; ~MainDialog() override = default;
void RunInterpreter(QProcess* process, Kyty::Configuration* info, bool con_emu); void RunInterpreter(QProcess* process, Kyty::Configuration* info, [[maybe_unused]] bool con_emu);
static void WriteSettings(QSettings* s); static void WriteSettings(QSettings* s);
static void ReadSettings(QSettings* s); static void ReadSettings(QSettings* s);
@@ -64,7 +64,11 @@ void ConfigurationListWidget::WriteSettings()
s = new QSettings(CONF_FILE_NAME, QSettings::IniFormat); s = new QSettings(CONF_FILE_NAME, QSettings::IniFormat);
} else } else
{ {
#ifdef __linux__
s = new QSettings(QSettings::IniFormat, QSettings::UserScope, CONF_ORG_NAME, CONF_APP_NAME);
#else
s = new QSettings(QSettings::IniFormat, QSettings::SystemScope, CONF_ORG_NAME, CONF_APP_NAME); s = new QSettings(QSettings::IniFormat, QSettings::SystemScope, CONF_ORG_NAME, CONF_APP_NAME);
#endif
} }
if (s != nullptr) if (s != nullptr)
@@ -95,7 +99,11 @@ void ConfigurationListWidget::ReadSettings()
s = new QSettings(CONF_FILE_NAME, QSettings::IniFormat); s = new QSettings(CONF_FILE_NAME, QSettings::IniFormat);
} else } else
{ {
#ifdef __linux__
s = new QSettings(QSettings::IniFormat, QSettings::UserScope, CONF_ORG_NAME, CONF_APP_NAME);
#else
s = new QSettings(QSettings::IniFormat, QSettings::SystemScope, CONF_ORG_NAME, CONF_APP_NAME); s = new QSettings(QSettings::IniFormat, QSettings::SystemScope, CONF_ORG_NAME, CONF_APP_NAME);
#endif
} }
if (s != nullptr) if (s != nullptr)
+88 -18
View File
@@ -27,7 +27,9 @@
#include "ui_main_dialog.h" #include "ui_main_dialog.h"
#ifndef __linux__
#include <windows.h> // IWYU pragma: keep #include <windows.h> // IWYU pragma: keep
#endif
// IWYU pragma: no_include <minwindef.h> // IWYU pragma: no_include <minwindef.h>
// IWYU pragma: no_include <processthreadsapi.h> // IWYU pragma: no_include <processthreadsapi.h>
@@ -35,24 +37,39 @@
class QWidget; class QWidget;
constexpr char SCRIPT_EXE[] = "fc_script.exe"; #ifdef __linux__
constexpr char CMD_EXE[] = "cmd.exe"; constexpr char SCRIPT_EXE[] = "fc_script";
constexpr char CONEMU_EXE[] = "C:/Program Files/ConEmu/ConEmu64.exe"; #else
constexpr char SCRIPT_EXE[] = "fc_script.exe";
#endif
#ifndef __linux__
constexpr char CMD_EXE[] = "cmd.exe";
constexpr char CONEMU_EXE[] = "C:/Program Files/ConEmu/ConEmu64.exe";
#else
constexpr char GNOME[] = "gnome-terminal";
constexpr char XTERM[] = "xterm";
constexpr char KYTY_BASH_FILE[] = "kyty_run.sh";
#endif
constexpr char KYTY_MOUNT[] = "kyty_mount"; constexpr char KYTY_MOUNT[] = "kyty_mount";
constexpr char KYTY_EXECUTE[] = "kyty_execute"; constexpr char KYTY_EXECUTE[] = "kyty_execute";
constexpr char KYTY_LOAD_ELF[] = "kyty_load_elf"; constexpr char KYTY_LOAD_ELF[] = "kyty_load_elf";
// constexpr char KYTY_LOAD_SYMBOLS[] = "kyty_load_symbols"; // constexpr char KYTY_LOAD_SYMBOLS[] = "kyty_load_symbols";
constexpr char KYTY_LOAD_SYMBOLS_ALL[] = "kyty_load_symbols_all"; constexpr char KYTY_LOAD_SYMBOLS_ALL[] = "kyty_load_symbols_all";
constexpr char KYTY_LOAD_PARAM_SFO[] = "kyty_load_param_sfo"; constexpr char KYTY_LOAD_PARAM_SFO[] = "kyty_load_param_sfo";
constexpr char KYTY_INIT[] = "kyty_init"; constexpr char KYTY_INIT[] = "kyty_init";
constexpr char KYTY_LUA_FILE[] = "kyty_run.lua"; constexpr char KYTY_LUA_FILE[] = "kyty_run.lua";
constexpr DWORD CMD_X_CHARS = 175; #ifndef __linux__
constexpr DWORD CMD_Y_CHARS = 1000; constexpr DWORD CMD_X_CHARS = 175;
constexpr char SETTINGS_MAIN_DIALOG[] = "MainDialog"; constexpr DWORD CMD_Y_CHARS = 1000;
constexpr char SETTINGS_MAIN_LAST_GEOMETRY[] = "geometry"; #endif
constexpr char SETTINGS_MAIN_DIALOG[] = "MainDialog";
constexpr char SETTINGS_MAIN_LAST_GEOMETRY[] = "geometry";
class DetachableProcess: public QProcess class DetachableProcess: public QProcess
{ {
Q_OBJECT;
public: public:
explicit DetachableProcess(QObject* parent = nullptr): QProcess(parent) {} explicit DetachableProcess(QObject* parent = nullptr): QProcess(parent) {}
void Detach() void Detach()
@@ -87,10 +104,12 @@ public:
private: private:
static QByteArray g_last_geometry; static QByteArray g_last_geometry;
Ui::MainDialog* m_ui = {nullptr}; Ui::MainDialog* m_ui = {nullptr};
MainDialog* m_main_dialog = nullptr; MainDialog* m_main_dialog = nullptr;
QString m_interpreter; QString m_interpreter;
DetachableProcess m_process;
/*DetachableProcess*/ QProcess m_process;
ConfigurationItem* m_running_item = nullptr; ConfigurationItem* m_running_item = nullptr;
}; };
@@ -135,7 +154,7 @@ void MainDialogPrivate::Setup(MainDialog* main_dialog)
Update(); Update();
}); });
connect(main_dialog, &MainDialog::Quit, [=]() { m_process.Detach(); }); // connect(main_dialog, &MainDialog::Quit, [=]() { m_process.Detach(); });
m_ui->label_settings_file->setText(tr("Settings file: ") + m_ui->widget->GetSettingsFile()); m_ui->label_settings_file->setText(tr("Settings file: ") + m_ui->widget->GetSettingsFile());
@@ -196,14 +215,23 @@ void MainDialogPrivate::FindInterpreter()
return; return;
} }
#ifndef __linux__
QFile console(CONEMU_EXE); QFile console(CONEMU_EXE);
bool con_emu = console.exists(); bool con_emu = console.exists();
#else
bool con_emu = true;
#endif
m_ui->radioButton_Cmd->setEnabled(true); m_ui->radioButton_Cmd->setEnabled(true);
m_ui->radioButton_Cmd->setChecked(true); m_ui->radioButton_Cmd->setChecked(true);
m_ui->radioButton_ConEmu->setEnabled(con_emu); m_ui->radioButton_ConEmu->setEnabled(con_emu);
m_ui->radioButton_ConEmu->setChecked(false); m_ui->radioButton_ConEmu->setChecked(false);
#ifdef __linux__
m_ui->radioButton_Cmd->setText(QCoreApplication::translate("MainDialog", "gnome-terminal", nullptr));
m_ui->radioButton_ConEmu->setText(QCoreApplication::translate("MainDialog", "xterm", nullptr));
#endif
Update(); Update();
} }
@@ -265,7 +293,28 @@ static bool CreateLuaScript(Kyty::Configuration* info, const QString& file_name)
return false; return false;
} }
void MainDialog::RunInterpreter(QProcess* process, Kyty::Configuration* info, bool con_emu) #ifdef __linux__
static bool CreateBashScript(const QString& interpreter, const QString& lua_file_name, const QString& file_name)
{
QFile file(file_name);
if (file.open(QIODevice::WriteOnly | QIODevice::Text))
{
QTextStream s(&file);
s << "#!/bin/bash\n";
s << interpreter << " " << lua_file_name << "\n";
s << "echo Press any key...\n";
s << "read -n1\n";
file.close();
return file.setPermissions(file.permissions() | QFile::ExeUser | QFile::ExeOwner | QFile::ExeGroup);
}
return false;
}
#endif
void MainDialog::RunInterpreter(QProcess* process, Kyty::Configuration* info, [[maybe_unused]] bool con_emu)
{ {
const auto& interpreter = m_p->GetInterpreter(); const auto& interpreter = m_p->GetInterpreter();
@@ -273,7 +322,6 @@ void MainDialog::RunInterpreter(QProcess* process, Kyty::Configuration* info, bo
auto dir = f.absoluteDir(); auto dir = f.absoluteDir();
auto lua_file_name = dir.filePath(KYTY_LUA_FILE); auto lua_file_name = dir.filePath(KYTY_LUA_FILE);
if (!CreateLuaScript(info, lua_file_name)) if (!CreateLuaScript(info, lua_file_name))
{ {
QMessageBox::critical(this, tr("Error"), tr("Can't create file:\n") + lua_file_name); QMessageBox::critical(this, tr("Error"), tr("Can't create file:\n") + lua_file_name);
@@ -281,6 +329,25 @@ void MainDialog::RunInterpreter(QProcess* process, Kyty::Configuration* info, bo
return; return;
} }
#ifdef __linux__
auto bash_file_name = dir.filePath(KYTY_BASH_FILE);
if (!CreateBashScript(interpreter, lua_file_name, bash_file_name))
{
QMessageBox::critical(this, tr("Error"), tr("Can't create file:\n") + bash_file_name);
QApplication::quit();
return;
}
if (con_emu)
{
process->setProgram(XTERM);
process->setArguments({"-e", "bash", "-c", bash_file_name});
} else
{
process->setProgram(GNOME);
process->setArguments({"--", "bash", "-c", bash_file_name});
}
#else
if (con_emu) if (con_emu)
{ {
process->setProgram(CONEMU_EXE); process->setProgram(CONEMU_EXE);
@@ -290,7 +357,9 @@ void MainDialog::RunInterpreter(QProcess* process, Kyty::Configuration* info, bo
process->setProgram(CMD_EXE); process->setProgram(CMD_EXE);
process->setArguments({"/K", interpreter, lua_file_name}); process->setArguments({"/K", interpreter, lua_file_name});
} }
#endif
process->setWorkingDirectory(dir.path()); process->setWorkingDirectory(dir.path());
#ifndef __linux__
process->setCreateProcessArgumentsModifier( process->setCreateProcessArgumentsModifier(
[](QProcess::CreateProcessArguments* args) [](QProcess::CreateProcessArguments* args)
{ {
@@ -303,6 +372,7 @@ void MainDialog::RunInterpreter(QProcess* process, Kyty::Configuration* info, bo
// args->startupInfo->dwFillAttribute = // args->startupInfo->dwFillAttribute =
// static_cast<DWORD>(BACKGROUND_BLUE) | static_cast<DWORD>(FOREGROUND_RED) | static_cast<DWORD>(FOREGROUND_INTENSITY); // static_cast<DWORD>(BACKGROUND_BLUE) | static_cast<DWORD>(FOREGROUND_RED) | static_cast<DWORD>(FOREGROUND_INTENSITY);
}); });
#endif
process->start(); process->start();
process->waitForFinished(100); process->waitForFinished(100);
} }
+27 -15
View File
@@ -258,42 +258,42 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/ConfigurationListWidget.cpp" line="128"/> <location filename="../src/ConfigurationListWidget.cpp" line="136"/>
<source>New configuration</source> <source>New configuration</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/ConfigurationListWidget.cpp" line="142"/> <location filename="../src/ConfigurationListWidget.cpp" line="150"/>
<source>Edit configuration</source> <source>Edit configuration</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/ConfigurationListWidget.cpp" line="153"/> <location filename="../src/ConfigurationListWidget.cpp" line="161"/>
<source>Delete configuration</source> <source>Delete configuration</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/ConfigurationListWidget.cpp" line="153"/> <location filename="../src/ConfigurationListWidget.cpp" line="161"/>
<source>Do you want to delete configuration?</source> <source>Do you want to delete configuration?</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/ConfigurationListWidget.cpp" line="189"/> <location filename="../src/ConfigurationListWidget.cpp" line="197"/>
<source>Run</source> <source>Run</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/ConfigurationListWidget.cpp" line="191"/> <location filename="../src/ConfigurationListWidget.cpp" line="199"/>
<source>New...</source> <source>New...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/ConfigurationListWidget.cpp" line="192"/> <location filename="../src/ConfigurationListWidget.cpp" line="200"/>
<source>Edit...</source> <source>Edit...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/ConfigurationListWidget.cpp" line="193"/> <location filename="../src/ConfigurationListWidget.cpp" line="201"/>
<source>Delete</source> <source>Delete</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@@ -328,12 +328,24 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/MainDialog.cpp" line="279"/> <location filename="../src/MainDialog.cpp" line="231"/>
<source>gnome-terminal</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/MainDialog.cpp" line="232"/>
<source>xterm</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/MainDialog.cpp" line="327"/>
<location filename="../src/MainDialog.cpp" line="336"/>
<source>Error</source> <source>Error</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/MainDialog.cpp" line="279"/> <location filename="../src/MainDialog.cpp" line="327"/>
<location filename="../src/MainDialog.cpp" line="336"/>
<source>Can&apos;t create file: <source>Can&apos;t create file:
</source> </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@@ -342,27 +354,27 @@
<context> <context>
<name>MainDialogPrivate</name> <name>MainDialogPrivate</name>
<message> <message>
<location filename="../src/MainDialog.cpp" line="140"/> <location filename="../src/MainDialog.cpp" line="159"/>
<source>Settings file: </source> <source>Settings file: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/MainDialog.cpp" line="166"/> <location filename="../src/MainDialog.cpp" line="185"/>
<source>Emulator: </source> <source>Emulator: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/MainDialog.cpp" line="178"/> <location filename="../src/MainDialog.cpp" line="197"/>
<source>Version: </source> <source>Version: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/MainDialog.cpp" line="194"/> <location filename="../src/MainDialog.cpp" line="213"/>
<source>Error</source> <source>Error</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/MainDialog.cpp" line="194"/> <location filename="../src/MainDialog.cpp" line="213"/>
<source>Can&apos;t find emulator</source> <source>Can&apos;t find emulator</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
+2 -1
View File
@@ -16,6 +16,7 @@
#include "Kyty/Core/SimpleArray.h" // IWYU pragma: associated #include "Kyty/Core/SimpleArray.h" // IWYU pragma: associated
#include "Kyty/Core/Singleton.h" // IWYU pragma: associated #include "Kyty/Core/Singleton.h" // IWYU pragma: associated
#include "Kyty/Core/Vector.h" // IWYU pragma: associated #include "Kyty/Core/Vector.h" // IWYU pragma: associated
#include "Kyty/Core/VirtualMemory.h"
namespace Kyty::Core { namespace Kyty::Core {
@@ -25,8 +26,8 @@ KYTY_SUBSYSTEM_INIT(Core)
core_file_init(); core_file_init();
core_debug_init(parent->GetArgv()[0]); core_debug_init(parent->GetArgv()[0]);
Language::Init(); Language::Init();
Database::Init(); Database::Init();
VirtualMemory::Init();
} }
KYTY_SUBSYSTEM_UNEXPECTED_SHUTDOWN(Core) {} KYTY_SUBSYSTEM_UNEXPECTED_SHUTDOWN(Core) {}
+31 -1
View File
@@ -19,6 +19,36 @@ constexpr int PRINT_STACK_FROM = 4;
constexpr int PRINT_STACK_FROM = 2; constexpr int PRINT_STACK_FROM = 2;
#endif #endif
#if KYTY_PLATFORM == KYTY_PLATFORM_LINUX
int IsDebuggerPresent()
{
bool dbg = false;
FILE* f = fopen("/proc/self/status", "r");
if (f != nullptr)
{
char str[1024];
while (feof(f) == 0)
{
str[1023] = '\0';
int pid = 0;
[[maybe_unused]] auto* result = fgets(str, 1023, f);
if (sscanf(str, "TracerPid: %d", &pid) == 1) // NOLINT
{
dbg = (pid != 0);
break;
}
}
[[maybe_unused]] auto result = fclose(f);
}
return (dbg ? 1 : 0);
}
#endif
void dbg_print_stack() void dbg_print_stack()
{ {
DebugStack s; DebugStack s;
@@ -80,7 +110,7 @@ void dbg_exit(int status)
bool dbg_is_debugger_present() bool dbg_is_debugger_present()
{ {
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS #if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS || KYTY_PLATFORM == KYTY_PLATFORM_LINUX
return !(IsDebuggerPresent() == 0); return !(IsDebuggerPresent() == 0);
#endif #endif
return false; return false;
+4
View File
@@ -210,7 +210,11 @@ void* mem_alloc(size_t size)
{ {
if (size == 0) if (size == 0)
{ {
#if KYTY_PLATFORM == KYTY_PLATFORM_LINUX
size = 1;
#else
EXIT("size == 0\n"); EXIT("size == 0\n");
#endif
} }
if ((g_mem_max_size != 0u) && size > g_mem_max_size) if ((g_mem_max_size != 0u) && size > g_mem_max_size)
+1
View File
@@ -9,6 +9,7 @@
// IWYU pragma: no_include "SDL_error.h" // IWYU pragma: no_include "SDL_error.h"
// IWYU pragma: no_include "SDL_platform.h" // IWYU pragma: no_include "SDL_platform.h"
// IWYU pragma: no_include "SDL_stdinc.h" // IWYU pragma: no_include "SDL_stdinc.h"
// IWYU pragma: no_include "begin_code.h"
#include "SDL.h" #include "SDL.h"
+136 -19
View File
@@ -8,20 +8,39 @@
#include "Kyty/Core/Vector.h" #include "Kyty/Core/Vector.h"
#include <atomic> #include <atomic>
#include <chrono> #include <chrono> // IWYU pragma: keep
#include <condition_variable> // IWYU pragma: keep #include <condition_variable> // IWYU pragma: keep
#include <mutex> #include <mutex>
#include <sstream>
#include <string>
#include <thread>
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS && KYTY_COMPILER == KYTY_COMPILER_CLANG #if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS && KYTY_COMPILER == KYTY_COMPILER_CLANG
#define KYTY_WIN_CS #define KYTY_WIN_CS
#endif #endif
#if KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS && KYTY_PLATFORM != KYTY_PLATFORM_LINUX
#define KYTY_SDL_THREADS
#define KYTY_SDL_CS
#endif
//#define KYTY_DEBUG_LOCKS //#define KYTY_DEBUG_LOCKS
//#define KYTY_DEBUG_LOCKS_TIMED //#define KYTY_DEBUG_LOCKS_TIMED
#ifdef KYTY_SDL_THREADS
#include "SDL_thread.h"
#include "SDL_timer.h"
#else
#include <sstream>
#include <string>
#include <thread>
#endif
#ifdef KYTY_SDL_CS
#include "SDL_mutex.h"
#endif
#if defined(KYTY_WIN_CS) && defined(KYTY_SDL_CS)
#error "defined(KYTY_WIN_CS) && defined(KYTY_SDL_CS)"
#endif
#if !(defined(KYTY_DEBUG_LOCKS) || defined(KYTY_DEBUG_LOCKS_TIMED)) && defined(KYTY_WIN_CS) #if !(defined(KYTY_DEBUG_LOCKS) || defined(KYTY_DEBUG_LOCKS_TIMED)) && defined(KYTY_WIN_CS)
#include <windows.h> // IWYU pragma: keep #include <windows.h> // IWYU pragma: keep
// IWYU pragma: no_include <winbase.h> // IWYU pragma: no_include <winbase.h>
@@ -30,6 +49,10 @@ constexpr DWORD KYTY_CS_SPIN_COUNT = 4000;
// IWYU pragma: no_include <minwindef.h> // IWYU pragma: no_include <minwindef.h>
// IWYU pragma: no_include <synchapi.h> // IWYU pragma: no_include <synchapi.h>
// IWYU pragma: no_include <minwinbase.h> // IWYU pragma: no_include <minwinbase.h>
// IWYU pragma: no_include <__mutex_base>
// IWYU pragma: no_include <__threading_support>
// IWYU pragma: no_include <errhandlingapi.h>
// IWYU pragma: no_include <winerror.h>
using InitializeConditionVariable_func_t = /*WINBASEAPI*/ VOID WINAPI (*)(PCONDITION_VARIABLE); using InitializeConditionVariable_func_t = /*WINBASEAPI*/ VOID WINAPI (*)(PCONDITION_VARIABLE);
using WakeConditionVariable_func_t = /*WINBASEAPI*/ VOID WINAPI (*)(PCONDITION_VARIABLE); using WakeConditionVariable_func_t = /*WINBASEAPI*/ VOID WINAPI (*)(PCONDITION_VARIABLE);
@@ -38,7 +61,7 @@ using SleepConditionVariableCS_func_t = /*WINBASEAPI*/ BOOL WINAPI (*)(PCO
static InitializeConditionVariable_func_t ResolveInitializeConditionVariable() static InitializeConditionVariable_func_t ResolveInitializeConditionVariable()
{ {
if (HMODULE h = GetModuleHandle("KernelBase"); h != nullptr) if (HMODULE h = GetModuleHandle("KernelBase"); h != nullptr) // @suppress("Invalid arguments")
{ {
return reinterpret_cast<InitializeConditionVariable_func_t>(GetProcAddress(h, "InitializeConditionVariable")); return reinterpret_cast<InitializeConditionVariable_func_t>(GetProcAddress(h, "InitializeConditionVariable"));
} }
@@ -46,7 +69,7 @@ static InitializeConditionVariable_func_t ResolveInitializeConditionVariable()
} }
static WakeConditionVariable_func_t ResolveWakeConditionVariable() static WakeConditionVariable_func_t ResolveWakeConditionVariable()
{ {
if (HMODULE h = GetModuleHandle("KernelBase"); h != nullptr) if (HMODULE h = GetModuleHandle("KernelBase"); h != nullptr) // @suppress("Invalid arguments")
{ {
return reinterpret_cast<WakeConditionVariable_func_t>(GetProcAddress(h, "WakeConditionVariable")); return reinterpret_cast<WakeConditionVariable_func_t>(GetProcAddress(h, "WakeConditionVariable"));
} }
@@ -54,7 +77,7 @@ static WakeConditionVariable_func_t ResolveWakeConditionVariable()
} }
static WakeAllConditionVariable_func_t ResolveWakeAllConditionVariable() static WakeAllConditionVariable_func_t ResolveWakeAllConditionVariable()
{ {
if (HMODULE h = GetModuleHandle("KernelBase"); h != nullptr) if (HMODULE h = GetModuleHandle("KernelBase"); h != nullptr) // @suppress("Invalid arguments")
{ {
return reinterpret_cast<WakeAllConditionVariable_func_t>(GetProcAddress(h, "WakeAllConditionVariable")); return reinterpret_cast<WakeAllConditionVariable_func_t>(GetProcAddress(h, "WakeAllConditionVariable"));
} }
@@ -62,7 +85,7 @@ static WakeAllConditionVariable_func_t ResolveWakeAllConditionVariable()
} }
static SleepConditionVariableCS_func_t ResolveSleepConditionVariableCS() static SleepConditionVariableCS_func_t ResolveSleepConditionVariableCS()
{ {
if (HMODULE h = GetModuleHandle("KernelBase"); h != nullptr) if (HMODULE h = GetModuleHandle("KernelBase"); h != nullptr) // @suppress("Invalid arguments")
{ {
return reinterpret_cast<SleepConditionVariableCS_func_t>(GetProcAddress(h, "SleepConditionVariableCS")); return reinterpret_cast<SleepConditionVariableCS_func_t>(GetProcAddress(h, "SleepConditionVariableCS"));
} }
@@ -73,7 +96,11 @@ static SleepConditionVariableCS_func_t ResolveSleepConditionVariableCS()
namespace Kyty::Core { namespace Kyty::Core {
#ifdef KYTY_SDL_THREADS
using thread_id_t = uint64_t;
#else
using thread_id_t = std::thread::id; using thread_id_t = std::thread::id;
#endif
#if defined(KYTY_DEBUG_LOCKS) || defined(KYTY_DEBUG_LOCKS_TIMED) #if defined(KYTY_DEBUG_LOCKS) || defined(KYTY_DEBUG_LOCKS_TIMED)
constexpr auto DBG_TRY_SECONDS = std::chrono::seconds(15); constexpr auto DBG_TRY_SECONDS = std::chrono::seconds(15);
@@ -94,7 +121,15 @@ struct MutexPrivate
DeleteCriticalSection(&m_cs); DeleteCriticalSection(&m_cs);
} }
KYTY_CLASS_NO_COPY(MutexPrivate); KYTY_CLASS_NO_COPY(MutexPrivate);
CRITICAL_SECTION m_cs {}; CRITICAL_SECTION m_cs {};
#elif defined(KYTY_SDL_CS)
MutexPrivate(): sdl(SDL_CreateMutex()) {}
~MutexPrivate()
{
SDL_DestroyMutex(sdl);
}
KYTY_CLASS_NO_COPY(MutexPrivate);
SDL_mutex* sdl;
#else #else
std::recursive_mutex m_mutex; std::recursive_mutex m_mutex;
#endif #endif
@@ -113,6 +148,14 @@ struct CondVarPrivate
~CondVarPrivate() = default; ~CondVarPrivate() = default;
KYTY_CLASS_NO_COPY(CondVarPrivate); KYTY_CLASS_NO_COPY(CondVarPrivate);
CONDITION_VARIABLE m_cv {}; CONDITION_VARIABLE m_cv {};
#elif !(defined(KYTY_DEBUG_LOCKS) || defined(KYTY_DEBUG_LOCKS_TIMED)) && defined(KYTY_SDL_CS)
CondVarPrivate(): sdl(SDL_CreateCond()) {}
~CondVarPrivate()
{
SDL_DestroyCond(sdl);
}
KYTY_CLASS_NO_COPY(CondVarPrivate);
SDL_cond* sdl;
#else #else
std::condition_variable_any m_cv; std::condition_variable_any m_cv;
#endif #endif
@@ -173,7 +216,17 @@ static std::atomic<WaitForGraph*> g_wait_for_graph = nullptr;
struct ThreadPrivate struct ThreadPrivate
{ {
ThreadPrivate(thread_func_t f, void* a): func(f), arg(a), m_thread(&Run, this) {} ThreadPrivate(thread_func_t f, void* a)
: func(f), arg(a),
#ifdef KYTY_SDL_THREADS
sdl(SDL_CreateThread(SdlThreadRun, "sdl_thread", this))
{
}
#else
m_thread(&Run, this)
{
}
#endif
static void Run(ThreadPrivate* t) static void Run(ThreadPrivate* t)
{ {
@@ -191,13 +244,23 @@ struct ThreadPrivate
} }
} }
static int SdlThreadRun(void* data)
{
Run(static_cast<ThreadPrivate*>(data));
return 0;
}
thread_func_t func; thread_func_t func;
void* arg; void* arg;
std::atomic_bool finished = false; std::atomic_bool finished = false;
std::atomic_bool auto_delete = false; std::atomic_bool auto_delete = false;
std::atomic_bool started = false; std::atomic_bool started = false;
int unique_id = 0; int unique_id = 0;
std::thread m_thread; #ifdef KYTY_SDL_THREADS
SDL_Thread* sdl;
#else
std::thread m_thread;
#endif
}; };
static thread_id_t g_main_thread; static thread_id_t g_main_thread;
@@ -206,7 +269,11 @@ static std::atomic<int> g_thread_counter = 0;
KYTY_SUBSYSTEM_INIT(Threads) KYTY_SUBSYSTEM_INIT(Threads)
{ {
g_main_thread = std::this_thread::get_id(); #ifdef KYTY_SDL_THREADS
g_main_thread = SDL_ThreadID();
#else
g_main_thread = std::this_thread::get_id();
#endif
g_main_thread_int = Thread::GetThreadIdUnique(); g_main_thread_int = Thread::GetThreadIdUnique();
g_wait_for_graph = new WaitForGraph; g_wait_for_graph = new WaitForGraph;
} }
@@ -468,7 +535,13 @@ void Thread::Join()
{ {
EXIT_IF(m_thread->finished || m_thread->auto_delete); EXIT_IF(m_thread->finished || m_thread->auto_delete);
#ifdef KYTY_SDL_THREADS
int status = -1;
SDL_WaitThread(m_thread->sdl, &status);
EXIT_IF(status != 0);
#else
m_thread->m_thread.join(); m_thread->m_thread.join();
#endif
m_thread->finished = true; m_thread->finished = true;
} }
@@ -478,34 +551,58 @@ void Thread::Detach()
EXIT_IF(m_thread->finished || m_thread->auto_delete); EXIT_IF(m_thread->finished || m_thread->auto_delete);
m_thread->auto_delete = true; m_thread->auto_delete = true;
#ifdef KYTY_SDL_THREADS
SDL_DetachThread(m_thread->sdl);
#else
m_thread->m_thread.detach(); m_thread->m_thread.detach();
#endif
} }
void Thread::Sleep(uint32_t millis) void Thread::Sleep(uint32_t millis)
{ {
#ifdef KYTY_SDL_THREADS
SDL_Delay(millis);
#else
std::this_thread::sleep_for(std::chrono::milliseconds(millis)); std::this_thread::sleep_for(std::chrono::milliseconds(millis));
#endif
} }
void Thread::SleepMicro(uint32_t micros) void Thread::SleepMicro(uint32_t micros)
{ {
#ifdef KYTY_SDL_THREADS
SDL_Delay(micros < 1000 && micros != 0 ? 1 : micros / 1000);
#else
std::this_thread::sleep_for(std::chrono::microseconds(micros)); std::this_thread::sleep_for(std::chrono::microseconds(micros));
#endif
} }
void Thread::SleepNano(uint64_t nanos) void Thread::SleepNano(uint64_t nanos)
{ {
#ifdef KYTY_SDL_THREADS
SDL_Delay(nanos < 1000000 && nanos != 0 ? 1 : nanos / 1000000);
#else
std::this_thread::sleep_for(std::chrono::nanoseconds(nanos)); std::this_thread::sleep_for(std::chrono::nanoseconds(nanos));
#endif
} }
bool Thread::IsMainThread() bool Thread::IsMainThread()
{ {
#ifdef KYTY_SDL_THREADS
return g_main_thread == static_cast<thread_id_t>(SDL_ThreadID());
#else
return g_main_thread == std::this_thread::get_id(); return g_main_thread == std::this_thread::get_id();
#endif
} }
String Thread::GetId() const String Thread::GetId() const
{ {
#ifdef KYTY_SDL_THREADS
return String::FromPrintf("%" PRIu64, static_cast<uint64_t>(SDL_GetThreadID(m_thread->sdl)));
#else
std::stringstream ss; std::stringstream ss;
ss << m_thread->m_thread.get_id(); ss << m_thread->m_thread.get_id();
return String::FromUtf8(ss.str().c_str()); return String::FromUtf8(ss.str().c_str());
#endif
} }
int Thread::GetUniqueId() const int Thread::GetUniqueId() const
@@ -515,9 +612,13 @@ int Thread::GetUniqueId() const
String Thread::GetThreadId() String Thread::GetThreadId()
{ {
#ifdef KYTY_SDL_THREADS
return String::FromPrintf("%" PRIu64, static_cast<uint64_t>(SDL_ThreadID()));
#else
std::stringstream ss; std::stringstream ss;
ss << std::this_thread::get_id(); ss << std::this_thread::get_id();
return String::FromUtf8(ss.str().c_str()); return String::FromUtf8(ss.str().c_str());
#endif
} }
Mutex::Mutex(): m_mutex(new MutexPrivate) {} Mutex::Mutex(): m_mutex(new MutexPrivate) {}
@@ -560,7 +661,7 @@ void Mutex::Lock()
} }
#else #else
#ifdef KYTY_DEBUG_LOCKS_TIMED #ifdef KYTY_DEBUG_LOCKS_TIMED
bool locked = false; bool locked = false;
do do
{ {
locked = m_mutex->m_mutex.try_lock_for(DBG_TRY_SECONDS); locked = m_mutex->m_mutex.try_lock_for(DBG_TRY_SECONDS);
@@ -573,6 +674,8 @@ void Mutex::Lock()
#else #else
#ifdef KYTY_WIN_CS #ifdef KYTY_WIN_CS
EnterCriticalSection(&m_mutex->m_cs); EnterCriticalSection(&m_mutex->m_cs);
#elif defined(KYTY_SDL_CS)
SDL_LockMutex(m_mutex->sdl);
#else #else
m_mutex->m_mutex.lock(); m_mutex->m_mutex.lock();
#endif #endif
@@ -591,6 +694,8 @@ void Mutex::Unlock()
#else #else
#if !defined(KYTY_DEBUG_LOCKS_TIMED) && defined(KYTY_WIN_CS) #if !defined(KYTY_DEBUG_LOCKS_TIMED) && defined(KYTY_WIN_CS)
LeaveCriticalSection(&m_mutex->m_cs); LeaveCriticalSection(&m_mutex->m_cs);
#elif !defined(KYTY_DEBUG_LOCKS_TIMED) && defined(KYTY_SDL_CS)
SDL_UnlockMutex(m_mutex->sdl);
#else #else
m_mutex->m_mutex.unlock(); m_mutex->m_mutex.unlock();
#endif #endif
@@ -612,6 +717,8 @@ bool Mutex::TryLock()
#else #else
#if !defined(KYTY_DEBUG_LOCKS_TIMED) && defined(KYTY_WIN_CS) #if !defined(KYTY_DEBUG_LOCKS_TIMED) && defined(KYTY_WIN_CS)
return (TryEnterCriticalSection(&m_mutex->m_cs) != 0); return (TryEnterCriticalSection(&m_mutex->m_cs) != 0);
#elif !defined(KYTY_DEBUG_LOCKS_TIMED) && defined(KYTY_SDL_CS)
return (SDL_TryLockMutex(m_mutex->sdl) == 0);
#else #else
return m_mutex->m_mutex.try_lock(); return m_mutex->m_mutex.try_lock();
#endif #endif
@@ -630,7 +737,7 @@ void CondVar::Wait(Mutex* mutex)
#if defined(KYTY_DEBUG_LOCKS) || defined(KYTY_DEBUG_LOCKS_TIMED) #if defined(KYTY_DEBUG_LOCKS) || defined(KYTY_DEBUG_LOCKS_TIMED)
std::unique_lock<std::recursive_timed_mutex> cpp_lock(mutex->m_mutex->m_mutex, std::adopt_lock_t()); std::unique_lock<std::recursive_timed_mutex> cpp_lock(mutex->m_mutex->m_mutex, std::adopt_lock_t());
#else #else
#ifdef KYTY_WIN_CS #if defined(KYTY_WIN_CS) || defined(KYTY_SDL_CS)
#else #else
std::unique_lock<std::recursive_mutex> cpp_lock(mutex->m_mutex->m_mutex, std::adopt_lock_t()); std::unique_lock<std::recursive_mutex> cpp_lock(mutex->m_mutex->m_mutex, std::adopt_lock_t());
#endif #endif
@@ -652,22 +759,25 @@ void CondVar::Wait(Mutex* mutex)
static auto func = ResolveSleepConditionVariableCS(); static auto func = ResolveSleepConditionVariableCS();
EXIT_NOT_IMPLEMENTED(func == nullptr); EXIT_NOT_IMPLEMENTED(func == nullptr);
func(&m_cond_var->m_cv, &mutex->m_mutex->m_cs, INFINITE); func(&m_cond_var->m_cv, &mutex->m_mutex->m_cs, INFINITE);
#elif !defined(KYTY_DEBUG_LOCKS_TIMED) && defined(KYTY_SDL_CS)
SDL_CondWait(m_cond_var->sdl, mutex->m_mutex->sdl);
#else #else
m_cond_var->m_cv.wait(cpp_lock); m_cond_var->m_cv.wait(cpp_lock);
#endif #endif
#endif #endif
#if !(defined(KYTY_DEBUG_LOCKS) || defined(KYTY_DEBUG_LOCKS_TIMED)) && defined(KYTY_WIN_CS) #if !(defined(KYTY_DEBUG_LOCKS) || defined(KYTY_DEBUG_LOCKS_TIMED)) && (defined(KYTY_WIN_CS) || defined(KYTY_SDL_CS))
#else #else
cpp_lock.release(); cpp_lock.release();
#endif #endif
} }
void CondVar::WaitFor(Mutex* mutex, uint32_t micros) bool CondVar::WaitFor(Mutex* mutex, uint32_t micros)
{ {
bool ok = false;
#if defined(KYTY_DEBUG_LOCKS) || defined(KYTY_DEBUG_LOCKS_TIMED) #if defined(KYTY_DEBUG_LOCKS) || defined(KYTY_DEBUG_LOCKS_TIMED)
std::unique_lock<std::recursive_timed_mutex> cpp_lock(mutex->m_mutex->m_mutex, std::adopt_lock_t()); std::unique_lock<std::recursive_timed_mutex> cpp_lock(mutex->m_mutex->m_mutex, std::adopt_lock_t());
#else #else
#ifdef KYTY_WIN_CS #if defined(KYTY_WIN_CS) || defined(KYTY_SDL_CS)
#else #else
std::unique_lock<std::recursive_mutex> cpp_lock(mutex->m_mutex->m_mutex, std::adopt_lock_t()); std::unique_lock<std::recursive_mutex> cpp_lock(mutex->m_mutex->m_mutex, std::adopt_lock_t());
#endif #endif
@@ -675,11 +785,14 @@ void CondVar::WaitFor(Mutex* mutex, uint32_t micros)
#if !(defined(KYTY_DEBUG_LOCKS) || defined(KYTY_DEBUG_LOCKS_TIMED)) && defined(KYTY_WIN_CS) #if !(defined(KYTY_DEBUG_LOCKS) || defined(KYTY_DEBUG_LOCKS_TIMED)) && defined(KYTY_WIN_CS)
static auto func = ResolveSleepConditionVariableCS(); static auto func = ResolveSleepConditionVariableCS();
EXIT_NOT_IMPLEMENTED(func == nullptr); EXIT_NOT_IMPLEMENTED(func == nullptr);
func(&m_cond_var->m_cv, &mutex->m_mutex->m_cs, (micros < 1000 ? 1 : micros / 1000)); ok = !(func(&m_cond_var->m_cv, &mutex->m_mutex->m_cs, (micros < 1000 ? 1 : micros / 1000)) == 0 && GetLastError() == ERROR_TIMEOUT);
#elif !(defined(KYTY_DEBUG_LOCKS) || defined(KYTY_DEBUG_LOCKS_TIMED)) && defined(KYTY_SDL_CS)
ok = !(SDL_CondWaitTimeout(m_cond_var->sdl, mutex->m_mutex->sdl, (micros < 1000 ? 1 : micros / 1000)) == SDL_MUTEX_TIMEDOUT);
#else #else
m_cond_var->m_cv.wait_for(cpp_lock, std::chrono::microseconds(micros)); ok = (m_cond_var->m_cv.wait_for(cpp_lock, std::chrono::microseconds(micros)) == std::cv_status::no_timeout);
cpp_lock.release(); cpp_lock.release();
#endif #endif
return ok;
} }
void CondVar::Signal() void CondVar::Signal()
@@ -688,6 +801,8 @@ void CondVar::Signal()
static auto func = ResolveWakeConditionVariable(); static auto func = ResolveWakeConditionVariable();
EXIT_NOT_IMPLEMENTED(func == nullptr); EXIT_NOT_IMPLEMENTED(func == nullptr);
func(&m_cond_var->m_cv); func(&m_cond_var->m_cv);
#elif !(defined(KYTY_DEBUG_LOCKS) || defined(KYTY_DEBUG_LOCKS_TIMED)) && defined(KYTY_SDL_CS)
SDL_CondSignal(m_cond_var->sdl);
#else #else
m_cond_var->m_cv.notify_one(); m_cond_var->m_cv.notify_one();
#endif #endif
@@ -699,6 +814,8 @@ void CondVar::SignalAll()
static auto func = ResolveWakeAllConditionVariable(); static auto func = ResolveWakeAllConditionVariable();
EXIT_NOT_IMPLEMENTED(func == nullptr); EXIT_NOT_IMPLEMENTED(func == nullptr);
func(&m_cond_var->m_cv); func(&m_cond_var->m_cv);
#elif !(defined(KYTY_DEBUG_LOCKS) || defined(KYTY_DEBUG_LOCKS_TIMED)) && defined(KYTY_SDL_CS)
SDL_CondBroadcast(m_cond_var->sdl);
#else #else
m_cond_var->m_cv.notify_all(); m_cond_var->m_cv.notify_all();
#endif #endif
+324
View File
@@ -0,0 +1,324 @@
#include "Kyty/Core/VirtualMemory.h"
#include "Kyty/Sys/SysVirtual.h"
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
#define KYTY_HAS_EXCEPTIONS
#endif
#ifdef KYTY_HAS_EXCEPTIONS
#include <windows.h> // IWYU pragma: keep
#endif
// IWYU pragma: no_include <basetsd.h>
// IWYU pragma: no_include <errhandlingapi.h>
// IWYU pragma: no_include <excpt.h>
// IWYU pragma: no_include <minwinbase.h>
// IWYU pragma: no_include <minwindef.h>
// IWYU pragma: no_include <wtypes.h>
namespace Kyty::Core {
SystemInfo GetSystemInfo()
{
SystemInfo ret {};
sys_get_system_info(&ret);
return ret;
}
namespace VirtualMemory {
#ifdef KYTY_HAS_EXCEPTIONS
struct JmpRax
{
template <class Handler>
void SetFunc(Handler func)
{
*reinterpret_cast<Handler*>(&code[2]) = func;
}
// mov rax, 0x1122334455667788
// jmp rax
uint8_t code[16] = {0x48, 0xB8, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0xFF, 0xE0};
};
class ExceptionHandlerPrivate
{
public:
#pragma pack(1)
struct UnwindInfo
{
uint8_t Version : 3;
uint8_t Flags : 5;
uint8_t SizeOfProlog;
uint8_t CountOfCodes;
uint8_t FrameRegister : 4;
uint8_t FrameOffset : 4;
ULONG ExceptionHandler;
ExceptionHandlerPrivate* ExceptionData;
};
struct HandlerInfo
{
JmpRax code;
RUNTIME_FUNCTION function_table = {};
UnwindInfo unwind_info = {};
};
#pragma pack()
static EXCEPTION_DISPOSITION Handler(PEXCEPTION_RECORD exception_record, ULONG64 /*EstablisherFrame*/, PCONTEXT /*ContextRecord*/,
PDISPATCHER_CONTEXT dispatcher_context)
{
ExceptionHandler::ExceptionInfo info {};
info.exception_address = reinterpret_cast<uint64_t>(exception_record->ExceptionAddress);
if (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
{
info.type = ExceptionHandler::ExceptionType::AccessViolation;
switch (exception_record->ExceptionInformation[0])
{
case 0: info.access_violation_type = ExceptionHandler::AccessViolationType::Read; break;
case 1: info.access_violation_type = ExceptionHandler::AccessViolationType::Write; break;
case 8: info.access_violation_type = ExceptionHandler::AccessViolationType::Execute; break;
default: info.access_violation_type = ExceptionHandler::AccessViolationType::Unknown; break;
}
info.access_violation_vaddr = exception_record->ExceptionInformation[1];
}
info.rbp = dispatcher_context->ContextRecord->Rbp;
info.exception_win_code = exception_record->ExceptionCode;
auto* p = *static_cast<ExceptionHandlerPrivate**>(dispatcher_context->HandlerData);
p->func(&info);
return ExceptionContinueExecution;
}
void InitHandler()
{
auto* h = new (reinterpret_cast<void*>(handler_addr)) HandlerInfo;
auto* code = &h->code;
auto* unwind_info = &h->unwind_info;
function_table = &h->function_table;
function_table->BeginAddress = 0;
function_table->EndAddress = image_size;
function_table->UnwindData = reinterpret_cast<uintptr_t>(unwind_info) - base_address;
unwind_info->Version = 1;
unwind_info->Flags = UNW_FLAG_EHANDLER;
unwind_info->SizeOfProlog = 0;
unwind_info->CountOfCodes = 0;
unwind_info->FrameRegister = 0;
unwind_info->FrameOffset = 0;
unwind_info->ExceptionHandler = reinterpret_cast<uintptr_t>(code) - base_address;
unwind_info->ExceptionData = this;
code->SetFunc(Handler);
FlushInstructionCache(reinterpret_cast<uint64_t>(code), sizeof(h->code));
}
uint64_t base_address = 0;
uint64_t handler_addr = 0;
uint64_t image_size = 0;
PRUNTIME_FUNCTION function_table = nullptr;
ExceptionHandler::handler_func_t func = nullptr;
static ExceptionHandler::handler_func_t g_vec_func;
};
ExceptionHandler::handler_func_t ExceptionHandlerPrivate::g_vec_func = nullptr;
#else
class ExceptionHandlerPrivate
{
};
#endif
ExceptionHandler::ExceptionHandler(): m_p(new ExceptionHandlerPrivate) {}
ExceptionHandler::~ExceptionHandler()
{
#ifdef KYTY_HAS_EXCEPTIONS
Uninstall();
#endif
delete m_p;
}
uint64_t ExceptionHandler::GetSize()
{
#ifdef KYTY_HAS_EXCEPTIONS
return (sizeof(ExceptionHandlerPrivate::HandlerInfo) & ~(static_cast<uint64_t>(0x1000) - 1)) + 0x1000;
#else
return 0x1000;
#endif
}
// NOLINTNEXTLINE(readability-convert-member-functions-to-static, misc-unused-parameters)
bool ExceptionHandler::Install(uint64_t base_address, uint64_t handler_addr, uint64_t image_size, handler_func_t func)
{
#ifdef KYTY_HAS_EXCEPTIONS
if (m_p->function_table == nullptr)
{
m_p->base_address = base_address;
m_p->handler_addr = handler_addr;
m_p->image_size = image_size;
m_p->func = func;
m_p->InitHandler();
if (RtlAddFunctionTable(m_p->function_table, 1, base_address) == FALSE)
{
printf("RtlAddFunctionTable() failed: 0x%08" PRIx32 "\n", static_cast<uint32_t>(GetLastError()));
return false;
}
return true;
}
return false;
#else
return true;
#endif
}
#ifdef KYTY_HAS_EXCEPTIONS
static LONG WINAPI ExceptionFilter(PEXCEPTION_POINTERS exception)
{
PEXCEPTION_RECORD exception_record = exception->ExceptionRecord;
ExceptionHandler::ExceptionInfo info {};
info.exception_address = reinterpret_cast<uint64_t>(exception_record->ExceptionAddress);
// printf("exception_record->ExceptionCode = %u\n", static_cast<uint32_t>(exception_record->ExceptionCode));
if (exception_record->ExceptionCode == DBG_PRINTEXCEPTION_C || exception_record->ExceptionCode == DBG_PRINTEXCEPTION_WIDE_C)
{
return EXCEPTION_CONTINUE_EXECUTION;
}
if (exception_record->ExceptionCode == 0x406D1388)
{
// Set a thread name
return EXCEPTION_CONTINUE_EXECUTION;
}
if (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
{
info.type = ExceptionHandler::ExceptionType::AccessViolation;
switch (exception_record->ExceptionInformation[0])
{
case 0: info.access_violation_type = ExceptionHandler::AccessViolationType::Read; break;
case 1: info.access_violation_type = ExceptionHandler::AccessViolationType::Write; break;
case 8: info.access_violation_type = ExceptionHandler::AccessViolationType::Execute; break;
default: info.access_violation_type = ExceptionHandler::AccessViolationType::Unknown; break;
}
info.access_violation_vaddr = exception_record->ExceptionInformation[1];
}
info.rbp = exception->ContextRecord->Rbp;
info.exception_win_code = exception_record->ExceptionCode;
ExceptionHandlerPrivate::g_vec_func(&info);
return EXCEPTION_CONTINUE_EXECUTION;
}
#endif
// NOLINTNEXTLINE(readability-convert-member-functions-to-static, misc-unused-parameters)
bool ExceptionHandler::InstallVectored(handler_func_t func)
{
#ifdef KYTY_HAS_EXCEPTIONS
if (ExceptionHandlerPrivate::g_vec_func == nullptr)
{
ExceptionHandlerPrivate::g_vec_func = func;
if (AddVectoredExceptionHandler(1, ExceptionFilter) == nullptr)
{
printf("AddVectoredExceptionHandler() failed\n");
return false;
}
return true;
}
return false;
#else
return true;
#endif
}
// NOLINTNEXTLINE(readability-convert-member-functions-to-static, misc-unused-parameters)
bool ExceptionHandler::Uninstall()
{
#ifdef KYTY_HAS_EXCEPTIONS
if (m_p->function_table != nullptr)
{
if (RtlDeleteFunctionTable(m_p->function_table) == FALSE)
{
printf("RtlDeleteFunctionTable() failed: 0x%08" PRIx32 "\n", static_cast<uint32_t>(GetLastError()));
return false;
}
m_p->function_table = nullptr;
return true;
}
return false;
#else
return true;
#endif
}
void Init()
{
sys_virtual_init();
}
uint64_t Alloc(uint64_t address, uint64_t size, Mode mode)
{
return sys_virtual_alloc(address, size, mode);
}
uint64_t AllocAligned(uint64_t address, uint64_t size, Mode mode, uint64_t alignment)
{
return sys_virtual_alloc_aligned(address, size, mode, alignment);
}
bool AllocFixed(uint64_t address, uint64_t size, Mode mode)
{
return sys_virtual_alloc_fixed(address, size, mode);
}
bool Free(uint64_t address)
{
return sys_virtual_free(address);
}
bool Protect(uint64_t address, uint64_t size, Mode mode, Mode* old_mode)
{
return sys_virtual_protect(address, size, mode, old_mode);
}
bool FlushInstructionCache(uint64_t address, uint64_t size)
{
return sys_virtual_flush_instruction_cache(address, size);
}
bool PatchReplace(uint64_t vaddr, uint64_t value)
{
return sys_virtual_patch_replace(vaddr, value);
}
} // namespace VirtualMemory
} // namespace Kyty::Core
+10 -7
View File
@@ -2,22 +2,25 @@ file(GLOB sys_src
"src/*.cpp" "src/*.cpp"
) )
add_library(sys_obj OBJECT ${sys_src}) add_library(sys STATIC ${sys_src})
add_library(sys STATIC $<TARGET_OBJECTS:sys_obj>)
target_link_libraries(sys core) target_link_libraries(sys core cpuinfo)
get_property(inc_headers TARGET sys PROPERTY INCLUDE_DIRECTORIES) get_property(inc_headers TARGET sys PROPERTY INCLUDE_DIRECTORIES)
target_include_directories(sys_obj PRIVATE ${inc_headers})
list(APPEND check_headers list(APPEND check_headers
${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include
) )
clang_tidy_check(sys_obj "" "${check_headers}" "${inc_headers}") list(APPEND inc_headers
${CMAKE_SOURCE_DIR}/3rdparty/sdl2/sdl2/include
${CMAKE_SOURCE_DIR}/3rdparty/cpuinfo/include
)
include_what_you_use(sys_obj "${inc_headers}") clang_tidy_check(sys "" "${check_headers}" "${inc_headers}")
#clang_tidy_fix(sys_obj "{Checks: '-*,cppcoreguidelines-init-variables'}" "${check_headers}" "${inc_headers}")
include_what_you_use(sys "${inc_headers}")
+145
View File
@@ -4,4 +4,149 @@
//#error "KYTY_PLATFORM != KYTY_PLATFORM_LINUX" //#error "KYTY_PLATFORM != KYTY_PLATFORM_LINUX"
#else #else
#include "Kyty/Sys/SysDbg.h"
#include <cstdlib>
#include <cstring>
#include <sys/param.h>
#include <sys/types.h>
#include <unistd.h>
namespace Kyty {
static thread_local sys_dbg_stack_info_t g_stack = {0};
void sys_stack_walk(void** /*stack*/, int* depth)
{
*depth = 0;
}
void sys_stack_usage_print(sys_dbg_stack_info_t& stack)
{
printf("stack: (0x%" PRIx64 ", %" PRIu64 ")\n", static_cast<uint64_t>(stack.commited_addr), static_cast<uint64_t>(stack.commited_size));
printf("code: (0x%" PRIx64 ", %" PRIu64 ")\n", static_cast<uint64_t>(stack.code_addr), static_cast<uint64_t>(stack.code_size));
}
void sys_stack_usage(sys_dbg_stack_info_t& s)
{
pid_t pid = getpid();
// printf("pid = %"I64"d\n", (int64_t)pid);
[[maybe_unused]] int result = 0;
char str[1024];
char str2[1024];
result = sprintf(str, "/proc/%d/exe", static_cast<int>(pid));
ssize_t buff_len = 0;
if ((buff_len = readlink(str, str2, 1023)) == -1)
{
return;
}
str2[buff_len] = '\0';
const char* name = basename(str2);
result = sprintf(str, "/proc/%d/maps", static_cast<int>(pid));
memset(&s, 0, sizeof(sys_dbg_stack_info_t));
FILE* f = fopen(str, "r");
if (f == nullptr)
{
return;
}
// printf("&str = %"I64"x\n", (uint64_t)&str);
uint64_t addr = 0;
uint64_t endaddr = 0;
[[maybe_unused]] uint64_t size = 0;
uint64_t offset = 0;
uint64_t inode = 0;
char permissions[8] = {};
char device[8] = {};
char filename[MAXPATHLEN] = {};
auto check_addr = reinterpret_cast<uintptr_t>(&f);
while (true)
{
if (feof(f) != 0)
{
break;
}
if (fgets(str, sizeof(str), f) == nullptr)
{
break;
}
filename[0] = 0;
permissions[0] = 0;
addr = 0;
size = 0;
// printf("%s", str);
// NOLINTNEXTLINE(cert-err34-c)
result = sscanf(str, "%" SCNx64 "-%" SCNx64 " %s %" SCNx64 " %s %" SCNx64 " %s", &addr, &endaddr, permissions, &offset, device,
&inode, filename);
size = endaddr - addr;
bool read = (strchr(permissions, 'r') != nullptr);
bool write = (strchr(permissions, 'w') != nullptr);
bool exec = (strchr(permissions, 'x') != nullptr);
// printf("%016"I64"x, %"I64"d, %s, %d, %d\n", addr, size, filename, read, write);
if (read && write && !exec && strncmp(filename, "[stack", 6) == 0)
{
// printf("stack: %016"I64"x, %"I64"d\n", addr, size);
if (check_addr >= addr && check_addr < addr + size)
{
s.addr = addr;
s.total_size = size;
s.commited_addr = addr;
s.commited_size = size;
if (s.code_addr != 0)
{
break;
}
}
}
if (read && !write && exec && strstr(filename, name) != nullptr)
{
s.code_addr = addr;
s.code_size = size;
if (s.addr != 0)
{
break;
}
}
}
result = fclose(f);
}
void sys_get_code_info(uintptr_t* addr, size_t* size)
{
if (g_stack.code_size == 0)
{
sys_stack_usage(g_stack);
}
*addr = g_stack.code_addr;
*size = g_stack.code_size;
}
void sys_set_exception_filter(exception_filter_func_t /*func*/) {}
} // namespace Kyty
#endif #endif
+665
View File
@@ -4,4 +4,669 @@
//#error "KYTY_PLATFORM != KYTY_PLATFORM_LINUX" //#error "KYTY_PLATFORM != KYTY_PLATFORM_LINUX"
#else #else
#include "Kyty/Core/DbgAssert.h"
#include "Kyty/Core/MemoryAlloc.h"
#include "Kyty/Core/String.h"
#include "Kyty/Sys/SysFileIO.h"
#include "Kyty/Sys/SysTimer.h"
#include "SDL_system.h"
#include <cerrno>
#include <sys/stat.h>
#include <unistd.h>
#include <utime.h>
namespace Kyty {
template <typename T>
class Vector;
static String* g_internal_files_dir = nullptr;
static String get_internal_name(const String& name)
{
return name.StartsWith(U"/") ? name : *g_internal_files_dir + U"/" + name;
}
bool sys_file_io_init()
{
g_internal_files_dir = new String();
*g_internal_files_dir = U".";
return !g_internal_files_dir->IsEmpty();
}
void sys_file_read(void* data, uint32_t size, sys_file_t& f, uint32_t* bytes_read)
{
if (f.type == SYS_FILE_FILE)
{
size_t w = fread(data, 1, size, f.f);
if (bytes_read != nullptr)
{
*bytes_read = w;
}
} else if (f.type == SYS_FILE_MEMORY_STAT)
{
uint32_t s = size;
if (f.buf->size != 0)
{
uint32_t l = f.buf->size - (f.buf->ptr - f.buf->base);
if (s > l)
{
s = l;
}
}
memcpy(data, f.buf->ptr, s);
f.buf->ptr += s;
if (bytes_read != nullptr)
{
*bytes_read = s;
}
} else if (f.type == SYS_FILE_MEMORY_DYN)
{
uint32_t s = size;
if (f.buf->size != 0)
{
uint32_t l = f.buf->size - (f.buf->ptr - f.buf->base);
if (s > l)
{
s = l;
}
} else
{
s = 0;
}
memcpy(data, f.buf->ptr, s);
f.buf->ptr += s;
if (bytes_read != nullptr)
{
*bytes_read = s;
}
}
}
void sys_file_write(const void* data, uint32_t size, sys_file_t& f, uint32_t* bytes_written)
{
if (f.type == SYS_FILE_FILE)
{
size_t w = fwrite(data, 1, size, f.f);
if (bytes_written != nullptr)
{
*bytes_written = w;
}
} else if (f.type == SYS_FILE_MEMORY_STAT)
{
uint32_t s = size;
if (f.buf->size != 0)
{
uint32_t l = f.buf->size - (f.buf->ptr - f.buf->base);
if (s > l)
{
s = l;
}
}
memcpy(f.buf->ptr, data, s);
f.buf->ptr += s;
if (bytes_written != nullptr)
{
*bytes_written = s;
}
} else if (f.type == SYS_FILE_MEMORY_DYN)
{
uint32_t pos = f.buf->ptr - f.buf->base;
if (f.buf->size < pos + size)
{
f.buf->base = static_cast<uint8_t*>(Core::mem_realloc(f.buf->base, pos + size));
f.buf->ptr = f.buf->base + pos;
f.buf->size = pos + size;
}
memcpy(f.buf->ptr, data, size);
f.buf->ptr += size;
if (bytes_written != nullptr)
{
*bytes_written = size;
}
}
}
void sys_file_read_r(void* data, uint32_t size, sys_file_t& f)
{
// DWORD w;
// ReadFile(f, data, size, &w, 0);
sys_file_read(data, size, f);
for (uint32_t i = 0; i < size / 2; i++)
{
char t = (static_cast<char*>(data))[i];
(static_cast<char*>(data))[i] = (static_cast<char*>(data))[size - i - 1];
(static_cast<char*>(data))[size - i - 1] = t;
}
}
void sys_file_write_r(const void* data, uint32_t size, sys_file_t& f)
{
char* data_r = new char[size];
for (uint32_t i = 0; i < size; i++)
{
data_r[i] = (static_cast<const char*>(data))[size - i - 1];
}
sys_file_write(data_r, size, f);
delete[] data_r;
}
void sys_file_write(uint32_t n, sys_file_t& f)
{
sys_file_write(&n, 4, f);
}
void sys_file_write_r(uint32_t n, sys_file_t& f)
{
sys_file_write_r(&n, 4, f);
}
sys_file_t* sys_file_create(const String& file_name)
{
auto* ret = new sys_file_t;
String real_name = get_internal_name(file_name);
ret->f = fopen(real_name.utf8_str().GetData(), "w+");
if (ret->f == nullptr)
{
printf("can't create file: %s\n", real_name.utf8_str().GetData());
}
ret->type = SYS_FILE_FILE;
return ret;
}
sys_file_t* sys_file_open_r(const String& file_name, sys_file_cache_type_t /*cache_type*/)
{
auto* ret = new sys_file_t;
ret->type = SYS_FILE_FILE;
String internal_name = get_internal_name(file_name);
;
FILE* f = fopen(internal_name.utf8_str().GetData(), "r");
if (f == nullptr)
{
ret->type = SYS_FILE_ERROR;
}
ret->f = f;
return ret;
}
sys_file_t* sys_file_open(uint8_t* buf, uint32_t buf_size)
{
auto* ret = new sys_file_t;
ret->type = SYS_FILE_MEMORY_STAT;
ret->buf = new sys_file_mem_buf_t;
ret->buf->base = buf;
ret->buf->ptr = buf;
ret->buf->size = buf_size;
return ret;
}
sys_file_t* sys_file_create()
{
auto* ret = new sys_file_t;
ret->type = SYS_FILE_MEMORY_DYN;
ret->buf = new sys_file_mem_buf_t;
ret->buf->base = nullptr;
ret->buf->ptr = nullptr;
ret->buf->size = 0;
return ret;
}
sys_file_t* sys_file_open_w(const String& file_name, sys_file_cache_type_t /*cache_type*/)
{
auto* ret = new sys_file_t;
String real_name = get_internal_name(file_name);
;
FILE* f = fopen(real_name.utf8_str().GetData(), "r+");
if (f == nullptr)
{
ret->type = SYS_FILE_ERROR;
} else
{
ret->type = SYS_FILE_FILE;
}
ret->f = f;
return ret;
}
sys_file_t* sys_file_open_rw(const String& file_name, sys_file_cache_type_t /*cache_type*/)
{
auto* ret = new sys_file_t;
String real_name = get_internal_name(file_name);
FILE* f = fopen(real_name.utf8_str().GetData(), "r+");
if (f == nullptr)
{
ret->type = SYS_FILE_ERROR;
} else
{
ret->type = SYS_FILE_FILE;
}
ret->f = f;
return ret;
}
void sys_file_close(sys_file_t* f)
{
[[maybe_unused]] int result = 0;
if (f->type == SYS_FILE_FILE && f->f != nullptr)
{
result = fclose(f->f);
} else if (f->type == SYS_FILE_MEMORY_STAT)
{
delete f->buf;
} else if (f->type == SYS_FILE_MEMORY_DYN)
{
Core::mem_free(f->buf->base);
delete f->buf;
}
// f.type = SYS_FILE_ERROR;
delete f;
}
uint64_t sys_file_size(sys_file_t& f)
{
[[maybe_unused]] int result = 0;
if (f.type == SYS_FILE_FILE)
{
uint32_t pos = ftell(f.f);
result = fseek(f.f, 0, SEEK_END);
uint32_t size = ftell(f.f);
result = fseek(f.f, pos, SEEK_SET);
return size;
}
if (f.type == SYS_FILE_MEMORY_STAT || f.type == SYS_FILE_MEMORY_DYN)
{
return f.buf->size;
}
return 0;
}
uint64_t sys_file_size(const String& file_name)
{
sys_file_t* f = sys_file_open_r(file_name);
uint64_t size = sys_file_size(*f);
sys_file_close(f);
return size;
}
bool sys_file_truncate(sys_file_t& /*f*/, uint64_t /*size*/)
{
return false;
}
bool sys_file_seek(sys_file_t& f, uint64_t offset)
{
bool ok = true;
if (f.type == SYS_FILE_FILE)
{
ok = (fseek(f.f, static_cast<int64_t>(offset), SEEK_SET) == 0);
// LARGE_INTEGER s;
// s.QuadPart = offset;
// SetFilePointerEx(f.handle, s, 0, FILE_BEGIN);
// printf("seek: %u\n", offset);
} else if (f.type == SYS_FILE_MEMORY_STAT || f.type == SYS_FILE_MEMORY_DYN)
{
f.buf->ptr = f.buf->base + offset;
}
return ok;
}
uint64_t sys_file_tell(sys_file_t& f)
{
if (f.type == SYS_FILE_FILE)
{
return ftell(f.f);
}
if (f.type == SYS_FILE_MEMORY_STAT || f.type == SYS_FILE_MEMORY_DYN)
{
return f.buf->ptr - f.buf->base;
}
return 0;
}
bool sys_file_is_error(sys_file_t& f)
{
return f.type == SYS_FILE_ERROR || (f.type == SYS_FILE_FILE && f.f == nullptr);
}
bool sys_file_is_directory_existing(const String& path)
{
String real_name = get_internal_name(path);
struct stat s
{
};
if (0 != stat(real_name.utf8_str().GetData(), &s))
{
return false;
}
return S_ISDIR(s.st_mode); // NOLINT
}
bool sys_file_is_file_existing(const String& name)
{
String real_name = get_internal_name(name);
struct stat s
{
};
if (0 != stat(real_name.utf8_str().GetData(), &s))
{
return false;
}
return !S_ISDIR(s.st_mode); // NOLINT
}
bool sys_file_create_directory(const String& path)
{
String real_name = get_internal_name(path);
mode_t m = S_IRWXU | S_IRWXG | S_IRWXO; // NOLINT
String::Utf8 u = real_name.utf8_str();
int r = mkdir(u.GetDataConst(), m);
if (r != 0)
{
int e = errno;
if (e == EEXIST)
{
printf("mkdir(%s, %" PRIx32 ") failed: The named file exists\n", real_name.C_Str(), static_cast<uint32_t>(m));
} else
{
printf("mkdir(%s, %" PRIx32 ") failed: %d\n", real_name.C_Str(), static_cast<uint32_t>(m), e);
return false;
}
}
return true;
}
bool sys_file_delete_directory(const String& path)
{
String real_name = get_internal_name(path);
return 0 == remove(real_name.utf8_str().GetData());
}
bool sys_file_delete_file(const String& name)
{
String real_name = get_internal_name(name);
return 0 == unlink(real_name.utf8_str().GetData());
}
bool sys_file_flush(sys_file_t& f)
{
if (f.type == SYS_FILE_FILE && f.f != nullptr)
{
return (fflush(f.f) == 0);
}
return false;
}
SysFileTimeStruct sys_file_get_last_access_time_utc(const String& name)
{
SysFileTimeStruct r {};
String real_name = get_internal_name(name);
struct stat s
{
};
if (0 != stat(real_name.utf8_str().GetData(), &s))
{
r.is_invalid = true;
} else
{
r.is_invalid = false;
r.time = s.st_atime;
}
return r;
}
SysFileTimeStruct sys_file_get_last_write_time_utc(const String& name)
{
SysFileTimeStruct r {};
String real_name = get_internal_name(name);
struct stat s
{
};
if (0 != stat(real_name.utf8_str().GetData(), &s))
{
r.is_invalid = true;
} else
{
r.is_invalid = false;
r.time = s.st_mtime;
}
return r;
}
void sys_file_get_last_access_and_write_time_utc(const String& name, SysFileTimeStruct& a, SysFileTimeStruct& w)
{
String real_name = get_internal_name(name);
struct stat s
{
};
if (0 != stat(real_name.utf8_str().GetData(), &s))
{
a.is_invalid = true;
w.is_invalid = true;
} else
{
a.is_invalid = false;
w.is_invalid = false;
a.time = s.st_atime;
w.time = s.st_mtime;
}
}
void sys_file_get_last_access_and_write_time_utc(sys_file_t& /*f*/, SysFileTimeStruct& /*a*/, SysFileTimeStruct& /*w*/)
{
EXIT("not implemented\n");
}
bool sys_file_set_last_access_time_utc(const String& name, SysFileTimeStruct& access)
{
if (access.is_invalid)
{
return false;
}
String real_name = get_internal_name(name);
struct stat s
{
};
String::Utf8 n = real_name.utf8_str();
if (0 != stat(n.GetData(), &s))
{
return false;
}
utimbuf times {};
times.actime = access.time;
times.modtime = s.st_mtime;
return !(0 != utime(n.GetData(), &times));
// if (0 != stat(n.GetData(), &s))
// {
// return false;
// }
//
// times.actime += times.actime - s.st_atime;
// times.modtime += times.modtime - s.st_mtime;
//
// if (0 != utime(n.GetData(), &times))
// {
// return false;
// }
}
bool sys_file_set_last_write_time_utc(const String& name, SysFileTimeStruct& write)
{
if (write.is_invalid)
{
return false;
}
String real_name = get_internal_name(name);
struct stat s
{
};
String::Utf8 n = real_name.utf8_str();
if (0 != stat(n.GetData(), &s))
{
return false;
}
utimbuf times {};
times.actime = s.st_atime;
times.modtime = write.time;
return !(0 != utime(n.GetData(), &times));
// if (0 != stat(n.GetData(), &s))
// {
// return false;
// }
//
// times.actime += times.actime - s.st_atime;
// times.modtime += times.modtime - s.st_mtime;
//
// if (0 != utime(n.GetData(), &times))
// {
// return false;
// }
}
bool sys_file_set_last_access_and_write_time_utc(const String& name, SysFileTimeStruct& access, SysFileTimeStruct& write)
{
if (access.is_invalid || write.is_invalid)
{
return false;
}
String real_name = get_internal_name(name);
struct stat s
{
};
String::Utf8 n = real_name.utf8_str();
if (0 != stat(n.GetData(), &s))
{
return false;
}
utimbuf times {};
times.actime = access.time;
times.modtime = write.time;
return !(0 != utime(n.GetData(), &times));
// if (0 != stat(n.GetData(), &s))
// {
// return false;
// }
//
// times.actime += times.actime - s.st_atime;
// times.modtime += times.modtime - s.st_mtime;
//
// if (0 != utime(n.GetData(), &times))
// {
// return false;
// }
}
void sys_file_find_files(const String& /*path*/, Vector<sys_file_find_t>& /*out*/)
{
EXIT("not implemented\n");
}
void sys_file_get_dents(const String& /*path*/, Kyty::Vector<sys_dir_entry_t>& /*out*/)
{
EXIT("not implemented\n");
}
bool sys_file_copy_file(const String& /*src*/, const String& /*dst*/)
{
EXIT("not implemented\n");
return false;
}
bool sys_file_move_file(const String& /*src*/, const String& /*dst*/)
{
EXIT("not implemented\n");
return false;
}
void sys_file_remove_readonly(const String& /*name*/)
{
EXIT("not implemented\n");
}
} // namespace Kyty
#endif #endif
+373
View File
@@ -0,0 +1,373 @@
#include "Kyty/Core/Common.h"
#if KYTY_PLATFORM != KYTY_PLATFORM_LINUX
//#error "KYTY_PLATFORM != KYTY_PLATFORM_LINUX"
#else
#include "Kyty/Core/DbgAssert.h"
#include "Kyty/Core/String.h"
#include "Kyty/Core/VirtualMemory.h"
#include "Kyty/Sys/SysVirtual.h"
#include "cpuinfo.h"
#include <cerrno>
#include <map>
#include <pthread.h>
#include <sys/mman.h>
// IWYU pragma: no_include <asm/mman-common.h>
// IWYU pragma: no_include <asm/mman.h>
// IWYU pragma: no_include <bits/pthread_types.h>
// IWYU pragma: no_include <linux/mman.h>
#if defined(MAP_FIXED_NOREPLACE) && KYTY_PLATFORM == KYTY_PLATFORM_LINUX
#define KYTY_FIXED_NOREPLACE
#endif
namespace Kyty::Core {
static pthread_mutex_t g_virtual_mutex {};
static std::map<uintptr_t, size_t>* g_allocs = nullptr;
static std::map<uintptr_t, int>* g_protects = nullptr;
void sys_get_system_info(SystemInfo* info)
{
EXIT_IF(info == nullptr);
const auto* p = cpuinfo_get_package(0);
EXIT_IF(p == nullptr);
info->ProcessorName = String::FromUtf8(p->name);
}
void sys_virtual_init()
{
pthread_mutexattr_t attr {};
pthread_mutexattr_init(&attr);
#if KYTY_PLATFORM == KYTY_PLATFORM_LINUX
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_FAST_NP);
#else
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
#endif
pthread_mutex_init(&g_virtual_mutex, &attr);
pthread_mutexattr_destroy(&attr);
g_allocs = new std::map<uintptr_t, size_t>;
g_protects = new std::map<uintptr_t, int>;
cpuinfo_initialize();
}
static int get_protection_flag(VirtualMemory::Mode mode)
{
int protect = PROT_NONE;
switch (mode)
{
case VirtualMemory::Mode::Read: protect = PROT_READ; break;
case VirtualMemory::Mode::Write:
case VirtualMemory::Mode::ReadWrite: protect = PROT_READ | PROT_WRITE; break; // NOLINT
case VirtualMemory::Mode::Execute: protect = PROT_EXEC; break;
case VirtualMemory::Mode::ExecuteRead: protect = PROT_EXEC | PROT_READ; break; // NOLINT
case VirtualMemory::Mode::ExecuteWrite:
case VirtualMemory::Mode::ExecuteReadWrite: protect = PROT_EXEC | PROT_WRITE | PROT_READ; break; // NOLINT
case VirtualMemory::Mode::NoAccess:
default: protect = PROT_NONE; break;
}
return protect;
}
static VirtualMemory::Mode get_protection_flag(int mode)
{
switch (mode)
{
case PROT_NONE: return VirtualMemory::Mode::NoAccess;
case PROT_READ: return VirtualMemory::Mode::Read;
case PROT_WRITE: return VirtualMemory::Mode::Write;
case PROT_READ | PROT_WRITE: return VirtualMemory::Mode::ReadWrite; // NOLINT
case PROT_EXEC: return VirtualMemory::Mode::Execute;
case PROT_EXEC | PROT_WRITE: return VirtualMemory::Mode::ExecuteWrite; // NOLINT
case PROT_EXEC | PROT_READ: return VirtualMemory::Mode::ExecuteRead; // NOLINT
case PROT_EXEC | PROT_WRITE | PROT_READ: return VirtualMemory::Mode::ExecuteReadWrite; // NOLINT
default: return VirtualMemory::Mode::NoAccess;
}
}
uint64_t sys_virtual_alloc(uint64_t address, uint64_t size, VirtualMemory::Mode mode)
{
EXIT_IF(g_allocs == nullptr);
auto addr = static_cast<uintptr_t>(address);
int protect = get_protection_flag(mode);
void* ptr = mmap(reinterpret_cast<void*>(addr), size, protect, MAP_PRIVATE | MAP_ANON, -1, 0); // NOLINT
auto ret_addr = reinterpret_cast<uintptr_t>(ptr);
if (ptr != MAP_FAILED)
{
pthread_mutex_lock(&g_virtual_mutex);
(*g_allocs)[ret_addr] = size;
uintptr_t page_start = ret_addr >> 12u;
uintptr_t page_end = (ret_addr + size - 1) >> 12u;
for (uintptr_t page = page_start; page <= page_end; page++)
{
(*g_protects)[page] = protect;
}
pthread_mutex_unlock(&g_virtual_mutex);
}
return ret_addr;
}
static uintptr_t align_up(uintptr_t addr, uint64_t alignment)
{
return (addr + alignment - 1) & ~(alignment - 1);
}
uint64_t sys_virtual_alloc_aligned(uint64_t address, uint64_t size, VirtualMemory::Mode mode, uint64_t alignment)
{
if (alignment == 0)
{
return 0;
}
EXIT_IF(g_allocs == nullptr);
auto addr = static_cast<uintptr_t>(address);
int protect = get_protection_flag(mode);
void* ptr = mmap(reinterpret_cast<void*>(addr), size, protect, MAP_PRIVATE | MAP_ANON, -1, 0); // NOLINT
auto ret_addr = reinterpret_cast<uintptr_t>(ptr);
if (ptr != MAP_FAILED && ((ret_addr & (alignment - 1)) != 0))
{
munmap(ptr, size);
ptr = mmap(reinterpret_cast<void*>(addr), size + alignment, protect, MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, -1, 0); // NOLINT
ret_addr = reinterpret_cast<uintptr_t>(ptr);
if (ptr != MAP_FAILED)
{
munmap(ptr, size + alignment);
auto aligned_addr = align_up(ret_addr, alignment);
#ifdef KYTY_FIXED_NOREPLACE
// NOLINTNEXTLINE
ptr = mmap(reinterpret_cast<void*>(aligned_addr), size, protect, MAP_FIXED_NOREPLACE | MAP_PRIVATE | MAP_ANON, -1, 0);
#else
// NOLINTNEXTLINE
ptr = mmap(reinterpret_cast<void*>(aligned_addr), size, protect, MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
#endif
ret_addr = reinterpret_cast<uintptr_t>(ptr);
if (ptr == MAP_FAILED)
{
[[maybe_unused]] int err = errno;
// printf("mmap failed: %d\n", err);
}
if (ptr != MAP_FAILED && ((ret_addr & (alignment - 1)) != 0))
{
munmap(ptr, size);
ret_addr = 0;
ptr = MAP_FAILED;
}
}
}
if (ptr == MAP_FAILED)
{
return sys_virtual_alloc_aligned(address, size, mode, alignment << 1u);
}
pthread_mutex_lock(&g_virtual_mutex);
(*g_allocs)[ret_addr] = size;
uintptr_t page_start = ret_addr >> 12u;
uintptr_t page_end = (ret_addr + size - 1) >> 12u;
for (uintptr_t page = page_start; page <= page_end; page++)
{
(*g_protects)[page] = protect;
}
pthread_mutex_unlock(&g_virtual_mutex);
return ret_addr;
}
[[maybe_unused]] static bool is_mmaped(void* ptr, size_t length)
{
FILE* file = fopen("/proc/self/maps", "r");
char line[1024];
bool ret = false;
auto addr = reinterpret_cast<uintptr_t>(ptr);
[[maybe_unused]] int result = 0;
while (feof(file) == 0)
{
if (fgets(line, 1024, file) == nullptr)
{
break;
}
uint64_t start = 0;
uint64_t end = 0;
// NOLINTNEXTLINE(cert-err34-c)
if (sscanf(line, "%" SCNx64 "-%" SCNx64, &start, &end) != 2)
{
continue;
}
if (addr >= start && addr + length <= end)
{
ret = true;
break;
}
}
result = fclose(file);
return ret;
}
bool sys_virtual_alloc_fixed(uint64_t address, uint64_t size, VirtualMemory::Mode mode)
{
EXIT_IF(g_allocs == nullptr);
auto addr = static_cast<uintptr_t>(address);
int protect = get_protection_flag(mode);
#ifdef KYTY_FIXED_NOREPLACE
// NOLINTNEXTLINE
void* ptr = mmap(reinterpret_cast<void*>(addr), size, protect, MAP_FIXED_NOREPLACE | MAP_PRIVATE | MAP_ANON, -1, 0);
#else
// NOLINTNEXTLINE
void* ptr = (is_mmaped(reinterpret_cast<void*>(addr), size)
? MAP_FAILED
: mmap(reinterpret_cast<void*>(addr), size, protect, MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0));
#endif
auto ret_addr = reinterpret_cast<uintptr_t>(ptr);
if (ptr != MAP_FAILED && ret_addr != addr)
{
munmap(ptr, size);
ret_addr = 0;
ptr = MAP_FAILED;
}
if (ptr != MAP_FAILED)
{
pthread_mutex_lock(&g_virtual_mutex);
(*g_allocs)[ret_addr] = size;
uintptr_t page_start = ret_addr >> 12u;
uintptr_t page_end = (ret_addr + size - 1) >> 12u;
for (uintptr_t page = page_start; page <= page_end; page++)
{
(*g_protects)[page] = protect;
}
pthread_mutex_unlock(&g_virtual_mutex);
return true;
}
return false;
}
bool sys_virtual_free(uint64_t address)
{
EXIT_IF(g_allocs == nullptr);
size_t size = 0;
auto addr = static_cast<uintptr_t>(address & ~static_cast<uint64_t>(0xfffu));
pthread_mutex_lock(&g_virtual_mutex);
if (auto s = g_allocs->find(addr); s != g_allocs->end())
{
size = s->second;
g_allocs->erase(s);
}
pthread_mutex_unlock(&g_virtual_mutex);
if (size == 0)
{
return false;
}
if (munmap(reinterpret_cast<void*>(addr), size) == 0)
{
uintptr_t page_start = addr >> 12u;
uintptr_t page_end = (addr + size - 1) >> 12u;
pthread_mutex_lock(&g_virtual_mutex);
for (uintptr_t page = page_start; page <= page_end; page++)
{
if (auto s = g_protects->find(page); s != g_protects->end())
{
g_protects->erase(s);
}
}
pthread_mutex_unlock(&g_virtual_mutex);
return true;
}
return false;
}
bool sys_virtual_protect(uint64_t address, uint64_t size, VirtualMemory::Mode mode, VirtualMemory::Mode* old_mode)
{
auto addr = static_cast<uintptr_t>(address);
pthread_mutex_lock(&g_virtual_mutex);
if (old_mode != nullptr)
{
if (auto s = g_protects->find(addr >> 12u); s != g_protects->end())
{
*old_mode = get_protection_flag(s->second);
} else
{
*old_mode = VirtualMemory::Mode::NoAccess;
}
}
pthread_mutex_unlock(&g_virtual_mutex);
uintptr_t page_start = addr >> 12u;
uintptr_t page_end = (addr + size - 1) >> 12u;
if (mprotect(reinterpret_cast<void*>(page_start << 12u), (page_end - page_start + 1) << 12u, get_protection_flag(mode)) == 0)
{
pthread_mutex_lock(&g_virtual_mutex);
for (uintptr_t page = page_start; page <= page_end; page++)
{
(*g_protects)[page] = get_protection_flag(mode);
}
pthread_mutex_unlock(&g_virtual_mutex);
return true;
}
return false;
}
bool sys_virtual_flush_instruction_cache(uint64_t /*address*/, uint64_t /*size*/)
{
return true;
}
bool sys_virtual_patch_replace(uint64_t vaddr, uint64_t value)
{
VirtualMemory::Mode old_mode {};
sys_virtual_protect(vaddr, 8, VirtualMemory::Mode::ReadWrite, &old_mode);
auto* ptr = reinterpret_cast<uint64_t*>(vaddr);
bool ret = (*ptr != value);
*ptr = value;
sys_virtual_protect(vaddr, 8, old_mode);
if (VirtualMemory::IsExecute(old_mode))
{
sys_virtual_flush_instruction_cache(vaddr, 8);
}
return ret;
}
} // namespace Kyty::Core
#endif
+4 -3
View File
@@ -1,8 +1,6 @@
#include "Kyty/Sys/SysWindowsDbg.h" #include "Kyty/Sys/Windows/SysWindowsDbg.h"
#include "Kyty/Core/Common.h" #include "Kyty/Core/Common.h"
#include "Kyty/Core/DbgAssert.h"
#include "Kyty/Sys/SysDbg.h"
// IWYU pragma: no_include <basetsd.h> // IWYU pragma: no_include <basetsd.h>
// IWYU pragma: no_include <memoryapi.h> // IWYU pragma: no_include <memoryapi.h>
@@ -16,6 +14,9 @@
//#error "KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS" //#error "KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS"
#else #else
#include "Kyty/Core/DbgAssert.h"
#include "Kyty/Sys/SysDbg.h"
#include <windows.h> // IWYU pragma: keep #include <windows.h> // IWYU pragma: keep
#if KYTY_COMPILER == KYTY_COMPILER_MSVC #if KYTY_COMPILER == KYTY_COMPILER_MSVC
#include <intrin.h> #include <intrin.h>
+1 -1
View File
@@ -1,4 +1,4 @@
#include "Kyty/Sys/SysWindowsFileIO.h" #include "Kyty/Sys/Windows/SysWindowsFileIO.h"
#include "Kyty/Core/Common.h" #include "Kyty/Core/Common.h"
+259
View File
@@ -0,0 +1,259 @@
#include "Kyty/Core/Common.h"
#if KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS
//#error "KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS"
#else
#include "Kyty/Core/DbgAssert.h"
#include "Kyty/Core/String.h"
#include "Kyty/Core/VirtualMemory.h"
#include "Kyty/Sys/SysVirtual.h"
#include "cpuinfo.h"
#include <windows.h> // IWYU pragma: keep
// IWYU pragma: no_include <basetsd.h>
// IWYU pragma: no_include <errhandlingapi.h>
// IWYU pragma: no_include <memoryapi.h>
// IWYU pragma: no_include <minwindef.h>
// IWYU pragma: no_include <processthreadsapi.h>
// IWYU pragma: no_include <winbase.h>
// IWYU pragma: no_include <winerror.h>
// IWYU pragma: no_include <wtypes.h>
namespace Kyty::Core {
void sys_get_system_info(SystemInfo* info)
{
EXIT_IF(info == nullptr);
const auto* p = cpuinfo_get_package(0);
EXIT_IF(p == nullptr);
info->ProcessorName = String::FromUtf8(p->name);
}
static DWORD get_protection_flag(VirtualMemory::Mode mode)
{
DWORD protect = PAGE_NOACCESS;
switch (mode)
{
case VirtualMemory::Mode::Read: protect = PAGE_READONLY; break;
case VirtualMemory::Mode::Write:
case VirtualMemory::Mode::ReadWrite: protect = PAGE_READWRITE; break;
case VirtualMemory::Mode::Execute: protect = PAGE_EXECUTE; break;
case VirtualMemory::Mode::ExecuteRead: protect = PAGE_EXECUTE_READ; break;
case VirtualMemory::Mode::ExecuteWrite:
case VirtualMemory::Mode::ExecuteReadWrite: protect = PAGE_EXECUTE_READWRITE; break;
case VirtualMemory::Mode::NoAccess:
default: protect = PAGE_NOACCESS; break;
}
return protect;
}
static VirtualMemory::Mode get_protection_flag(DWORD mode)
{
switch (mode)
{
case PAGE_NOACCESS: return VirtualMemory::Mode::NoAccess;
case PAGE_READONLY: return VirtualMemory::Mode::Read;
case PAGE_READWRITE: return VirtualMemory::Mode::ReadWrite;
case PAGE_EXECUTE: return VirtualMemory::Mode::Execute;
case PAGE_EXECUTE_READ: return VirtualMemory::Mode::ExecuteRead;
case PAGE_EXECUTE_READWRITE: return VirtualMemory::Mode::ExecuteReadWrite;
default: return VirtualMemory::Mode::NoAccess;
}
}
void sys_virtual_init()
{
cpuinfo_initialize();
}
uint64_t sys_virtual_alloc(uint64_t address, uint64_t size, VirtualMemory::Mode mode)
{
auto ptr = (address == 0 ? sys_virtual_alloc_aligned(address, size, mode, 1)
: reinterpret_cast<uintptr_t>(VirtualAlloc(reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size,
static_cast<DWORD>(MEM_COMMIT) | static_cast<DWORD>(MEM_RESERVE),
get_protection_flag(mode))));
if (ptr == 0)
{
auto err = static_cast<uint32_t>(GetLastError());
if (err != ERROR_INVALID_ADDRESS)
{
printf("VirtualAlloc() failed: 0x%08" PRIx32 "\n", err);
} else
{
return sys_virtual_alloc_aligned(address, size, mode, 1);
}
}
return ptr;
}
using VirtualAlloc2_func_t = /*WINBASEAPI*/ PVOID WINAPI (*)(HANDLE, PVOID, SIZE_T, ULONG, ULONG, MEM_EXTENDED_PARAMETER*, ULONG);
static VirtualAlloc2_func_t ResolveVirtualAlloc2()
{
HMODULE h = GetModuleHandle("KernelBase"); // @suppress("Invalid arguments")
if (h != nullptr)
{
return reinterpret_cast<VirtualAlloc2_func_t>(GetProcAddress(h, "VirtualAlloc2"));
}
return nullptr;
}
static uint64_t align_up(uint64_t addr, uint64_t alignment)
{
return (addr + alignment - 1) & ~(alignment - 1);
}
uint64_t sys_virtual_alloc_aligned(uint64_t address, uint64_t size, VirtualMemory::Mode mode, uint64_t alignment)
{
if (alignment == 0)
{
printf("VirtualAlloc2 failed: 0x%08" PRIx32 "\n", static_cast<uint32_t>(GetLastError()));
return 0;
}
static constexpr uint64_t SYSTEM_MANAGED_MIN = 0x0000040000u;
static constexpr uint64_t SYSTEM_MANAGED_MAX = 0x07FFFFBFFFu;
static constexpr uint64_t USER_MIN = 0x1000000000u;
static constexpr uint64_t USER_MAX = 0xFBFFFFFFFFu;
MEM_ADDRESS_REQUIREMENTS req {};
MEM_EXTENDED_PARAMETER param {};
req.LowestStartingAddress =
(address == 0 ? reinterpret_cast<PVOID>(SYSTEM_MANAGED_MIN) : reinterpret_cast<PVOID>(align_up(address, alignment)));
req.HighestEndingAddress = (address == 0 ? reinterpret_cast<PVOID>(SYSTEM_MANAGED_MAX) : reinterpret_cast<PVOID>(USER_MAX));
req.Alignment = alignment;
param.Type = MemExtendedParameterAddressRequirements;
param.Pointer = &req;
MEM_ADDRESS_REQUIREMENTS req2 {};
MEM_EXTENDED_PARAMETER param2 {};
req2.LowestStartingAddress = (address == 0 ? reinterpret_cast<PVOID>(USER_MIN) : reinterpret_cast<PVOID>(align_up(address, alignment)));
req2.HighestEndingAddress = reinterpret_cast<PVOID>(USER_MAX);
req2.Alignment = alignment;
param2.Type = MemExtendedParameterAddressRequirements;
param2.Pointer = &req2;
static auto virtual_alloc2 = ResolveVirtualAlloc2();
EXIT_NOT_IMPLEMENTED(virtual_alloc2 == nullptr);
auto ptr = reinterpret_cast<uintptr_t>(virtual_alloc2(GetCurrentProcess(), nullptr, size,
static_cast<DWORD>(MEM_COMMIT) | static_cast<DWORD>(MEM_RESERVE),
get_protection_flag(mode), &param, 1));
if (ptr == 0)
{
ptr = reinterpret_cast<uintptr_t>(virtual_alloc2(GetCurrentProcess(), nullptr, size,
static_cast<DWORD>(MEM_COMMIT) | static_cast<DWORD>(MEM_RESERVE),
get_protection_flag(mode), &param2, 1));
}
if (ptr == 0)
{
auto err = static_cast<uint32_t>(GetLastError());
if (err != ERROR_INVALID_PARAMETER)
{
printf("VirtualAlloc2(alignment = 0x%016" PRIx64 ") failed: 0x%08" PRIx32 "\n", alignment, err);
} else
{
return sys_virtual_alloc_aligned(address, size, mode, alignment << 1u);
}
}
return ptr;
}
bool sys_virtual_alloc_fixed(uint64_t address, uint64_t size, VirtualMemory::Mode mode)
{
auto ptr = reinterpret_cast<uintptr_t>(VirtualAlloc(reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size,
static_cast<DWORD>(MEM_COMMIT) | static_cast<DWORD>(MEM_RESERVE),
get_protection_flag(mode)));
if (ptr == 0)
{
auto err = static_cast<uint32_t>(GetLastError());
printf("VirtualAlloc() failed: 0x%08" PRIx32 "\n", err);
return false;
}
if (ptr != address)
{
printf("VirtualAlloc() failed: wrong address\n");
VirtualFree(reinterpret_cast<LPVOID>(ptr), 0, MEM_RELEASE);
return false;
}
return true;
}
bool sys_virtual_free(uint64_t address)
{
if (VirtualFree(reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), 0, MEM_RELEASE) == 0)
{
printf("VirtualFree() failed: 0x%08" PRIx32 "\n", static_cast<uint32_t>(GetLastError()));
return false;
}
return true;
}
bool sys_virtual_protect(uint64_t address, uint64_t size, VirtualMemory::Mode mode, VirtualMemory::Mode* old_mode)
{
DWORD old_protect = 0;
if (VirtualProtect(reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size, get_protection_flag(mode), &old_protect) == 0)
{
printf("VirtualProtect() failed: 0x%08" PRIx32 "\n", static_cast<uint32_t>(GetLastError()));
return false;
}
if (old_mode != nullptr)
{
*old_mode = get_protection_flag(old_protect);
}
return true;
}
bool sys_virtual_flush_instruction_cache(uint64_t address, uint64_t size)
{
if (::FlushInstructionCache(GetCurrentProcess(), reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size) == 0)
{
printf("FlushInstructionCache() failed: 0x%08" PRIx32 "\n", static_cast<uint32_t>(GetLastError()));
return false;
}
return true;
}
bool sys_virtual_patch_replace(uint64_t vaddr, uint64_t value)
{
VirtualMemory::Mode old_mode {};
sys_virtual_protect(vaddr, 8, VirtualMemory::Mode::ReadWrite, &old_mode);
auto* ptr = reinterpret_cast<uint64_t*>(vaddr);
bool ret = (*ptr != value);
*ptr = value;
sys_virtual_protect(vaddr, 8, old_mode);
if (VirtualMemory::IsExecute(old_mode))
{
sys_virtual_flush_instruction_cache(vaddr, 8);
}
return ret;
}
} // namespace Kyty::Core
#endif
+21 -25
View File
@@ -19,7 +19,7 @@ function(add_generator_macros t m v)
endfunction() endfunction()
function(include_what_you_use target dirs) function(include_what_you_use target dirs)
if (CLANG AND ("${target}" IN_LIST KYTY_IWYU)) if (NOT LINUX AND CLANG AND ("${target}" IN_LIST KYTY_IWYU))
find_program (CLANG_IWYU_EXE NAMES "include-what-you-use") find_program (CLANG_IWYU_EXE NAMES "include-what-you-use")
if (CLANG_IWYU_EXE) if (CLANG_IWYU_EXE)
set_target_properties(${target} PROPERTIES CXX_INCLUDE_WHAT_YOU_USE "${CLANG_IWYU_EXE};-Xiwyu;--cxx17ns;-Qunused-arguments;-Werror") set_target_properties(${target} PROPERTIES CXX_INCLUDE_WHAT_YOU_USE "${CLANG_IWYU_EXE};-Xiwyu;--cxx17ns;-Qunused-arguments;-Werror")
@@ -28,7 +28,7 @@ function(include_what_you_use target dirs)
endfunction() endfunction()
function(include_what_you_use_with_mappings target dirs mappings) function(include_what_you_use_with_mappings target dirs mappings)
if (CLANG AND ("${target}" IN_LIST KYTY_IWYU)) if (NOT LINUX AND CLANG AND ("${target}" IN_LIST KYTY_IWYU))
find_program (CLANG_IWYU_EXE NAMES "include-what-you-use") find_program (CLANG_IWYU_EXE NAMES "include-what-you-use")
if (CLANG_IWYU_EXE) if (CLANG_IWYU_EXE)
foreach(map ${mappings}) foreach(map ${mappings})
@@ -83,12 +83,8 @@ macro(config_compiler_and_linker)
set(KYTY_WARNINGS_ARE_ERRORS ON) set(KYTY_WARNINGS_ARE_ERRORS ON)
set(KYTY_C_FLAGS "")
set(KYTY_CPP_FLAGS "") set(KYTY_CPP_FLAGS "")
set(KYTY_CPP_FLAGS_RELEASE "")
set(KYTY_CPP_FLAGS_DEBUG "")
set(KYTY_EXE_LINKER_FLAGS "")
set(KYTY_EXE_LINKER_FLAGS_RELEASE "")
set(KYTY_EXE_LINKER_FLAGS_DEBUG "")
SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "") SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "")
@@ -112,41 +108,41 @@ if(MSVC)
set(KYTY_CPP_FLAGS "${KYTY_CPP_FLAGS} /Zc:__cplusplus /utf-8 /Oy- /wd4244 /wd4305 /wd4800 /wd4345") set(KYTY_CPP_FLAGS "${KYTY_CPP_FLAGS} /Zc:__cplusplus /utf-8 /Oy- /wd4244 /wd4305 /wd4800 /wd4345")
endif() endif()
set(KYTY_EXE_LINKER_FLAGS_RELEASE "/OPT:NOREF") add_link_options("$<$<CONFIG:RELEASE>:/OPT:NOREF>")
if(KYTY_WARNINGS_ARE_ERRORS) if(KYTY_WARNINGS_ARE_ERRORS)
set(KYTY_CPP_FLAGS "${KYTY_CPP_FLAGS} /WX") #set(KYTY_CPP_FLAGS "${KYTY_CPP_FLAGS} /WX")
add_compile_options(/WX)
endif() endif()
endif()
if(MINGW) set(KYTY_C_FLAGS "${KYTY_CPP_FLAGS}")
elseif(MINGW OR LINUX)
if (CLANG) if (CLANG)
set(KYTY_CPP_FLAGS "${KYTY_CPP_FLAGS} -fno-rtti -fno-exceptions -fcolor-diagnostics -finput-charset=UTF-8 -fexec-charset=UTF-8 -g -static -fno-strict-aliasing -fno-omit-frame-pointer -Wall -fmessage-length=0") set(KYTY_CPP_FLAGS "${KYTY_CPP_FLAGS} -fno-rtti -fno-exceptions -fcolor-diagnostics -finput-charset=UTF-8 -fexec-charset=UTF-8 -g -fno-strict-aliasing -fno-omit-frame-pointer -Wall -fmessage-length=0")
if (MINGW)
set(KYTY_CPP_FLAGS "${KYTY_CPP_FLAGS} -static")
endif()
else() else()
set(KYTY_CPP_FLAGS "${KYTY_CPP_FLAGS} -fno-exceptions -fdiagnostics-color=always -finput-charset=UTF-8 -fexec-charset=UTF-8 -static-libgcc -static-libstdc++ -g -fno-strict-aliasing -fno-omit-frame-pointer -Wall -fmessage-length=0") set(KYTY_CPP_FLAGS "${KYTY_CPP_FLAGS} -fno-exceptions -fdiagnostics-color=always -finput-charset=UTF-8 -fexec-charset=UTF-8 -static-libgcc -static-libstdc++ -g -fno-strict-aliasing -fno-omit-frame-pointer -Wall -Wno-unused-value -fmessage-length=0")
endif() endif()
set(KYTY_CPP_FLAGS_DEBUG "${KYTY_CPP_FLAGS_DEBUG} -O0")
if(KYTY_WARNINGS_ARE_ERRORS) if(KYTY_WARNINGS_ARE_ERRORS)
set(KYTY_CPP_FLAGS "${KYTY_CPP_FLAGS} -Werror") #set(KYTY_CPP_FLAGS "${KYTY_CPP_FLAGS} -Werror")
add_compile_options(-Werror)
endif() endif()
set(KYTY_EXE_LINKER_FLAGS "${KYTY_EXE_LINKER_FLAGS} -g") add_link_options("-g")
unset(CMAKE_CXX_STANDARD_LIBRARIES CACHE) unset(CMAKE_CXX_STANDARD_LIBRARIES CACHE)
unset(CMAKE_C_STANDARD_LIBRARIES CACHE) unset(CMAKE_C_STANDARD_LIBRARIES CACHE)
set(KYTY_C_FLAGS "${KYTY_CPP_FLAGS}")
endif() endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${KYTY_CPP_FLAGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${KYTY_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KYTY_CPP_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KYTY_CPP_FLAGS}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${KYTY_CPP_FLAGS_RELEASE}")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${KYTY_CPP_FLAGS_RELEASE}")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${KYTY_CPP_FLAGS_DEBUG}")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${KYTY_CPP_FLAGS_DEBUG}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${KYTY_EXE_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${KYTY_EXE_LINKER_FLAGS_RELEASE}")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${KYTY_EXE_LINKER_FLAGS_DEBUG}")
endmacro() endmacro()