Compare commits

..
129 Commits
Author SHA1 Message Date
ptitSeb e6e9fae178 Bumped to v0.1.6 2021-11-19 22:21:29 +01:00
ptitSeb 7042a1ae30 Try to use Github Actions 2021-11-19 21:52:10 +01:00
ptitSeb 7d277cc1ec Updated CHANGELOG 2021-11-19 21:43:49 +01:00
ptitSeb 1ac0465a03 Small change on unload of box64 2021-11-19 21:43:32 +01:00
ptitSeb 3533db97ff [DYNAREC] Reduce performance impact of StrongMem, and added old Strongmem method as BOX64_DYNAREC_STRONGMEM=2 2021-11-19 11:22:59 +01:00
ptitSeb 7888cae6c7 Merge pull request #166 from eerykitty/main
Minor changes to allow box64 to build and run on 64-bit PowerPC.
2021-11-19 07:48:02 +01:00
Joseph Allen b021beba6a Minor changes to allow box64 to build and run on ppc64le. 2021-11-18 17:48:52 -06:00
ptitSeb 684d67d12e Added wrapped __isoc99_scanf function (for #164) 2021-11-18 14:25:53 +01:00
ptitSeb 8d7683b851 Changed elfloader a bit to merge elf memory block if close enough (help load program on loongarch architecture) 2021-11-18 14:23:37 +01:00
ptitSeb e7290d78d5 [DYNAREC] Improved JIT handling, and added a HotPage detection to temporarily disable Dynarec when write occurs on the same page of some Dynablocks (help speedup some C#/Unity3D programs) 2021-11-18 14:21:16 +01:00
ptitSeb 4f0e98ade5 [DYNAREC] Added an option to simulate Strong Memory Model, and auto activate it when libmonobdgcw-2.0.so is detected (should help #110 and #158 at least) 2021-11-18 14:18:00 +01:00
ptitSeb 39dbfd9fd8 [DYNAREC] Removed special case for RimWorldLinux and generalized it for all program loading libmonodbwgc-2.0.so 2021-11-18 13:50:10 +01:00
ptitSeb 2d18558dc5 [TRACE] Fixed trace on function from a dlopen library not triggering preperly 2021-11-17 19:41:00 +01:00
ptitSeb 5fb9397521 [DYNAREC] Fixed a small issue with Segfault in Fillblock detection 2021-11-15 17:45:31 +01:00
ptitSeb f85e24dff8 [DYNAREC] Added some DMB to try help multi-tasked+JIT program (may help #110) 2021-11-14 21:43:02 +01:00
ptitSeb 2ea272fcd6 [DYNAREC] Added DMB emitter 2021-11-14 20:57:51 +01:00
ptitSeb d3e85b439b Added wrapped libxslt (from box86) (should help #161) 2021-11-14 15:19:25 +01:00
ptitSeb ea837908b6 Added wrapped libldap_r and liblber (helps wine) 2021-11-14 15:15:47 +01:00
ptitSeb a1573835dd Change ResolvePath behaviour in sync with box86 2021-11-14 10:44:55 +01:00
ptitSeb 34355d6b0c Added some data symbol to wrapped libxml2 (for #161 but it would probably be better to wrap libxslt directly) 2021-11-12 19:20:08 +01:00
ptitSeb 9557e4711f Added a few xcb symbols (for #161) 2021-11-12 12:19:50 +01:00
ptitSeb 6a1b9e050a [DYNAREC] Changed Dynarec a bit to try stabilise program using many threads and a JIT (help RimWorld Linux, but not enough to be 100% stable) 2021-11-11 20:47:10 +01:00
ptitSeb 6675b43dd0 [DYNAREC] Pass0 now alocate memory and do more stuff from pass1 2021-11-11 12:37:32 +01:00
ptitSeb 79d7e9f8eb Mark memprot as volatile to try help stability in heavily multithread programs 2021-11-11 12:37:01 +01:00
ptitSeb f5c9439f91 Improved CMPSS/CMPSD opcodes, improved test17 ([DYNAREC] too, and improved MINSS/MAXSS/MINSD/MAXSD too) 2021-11-07 15:06:55 +01:00
ptitSeb f73e4193f0 Chnaged memory protection tracking to reduce usage of lock, especially for [DYNAREC] reduced mutrex and chances of deadlock (help RimWorld) 2021-11-05 21:17:14 +01:00
ptitSeb 841003bc47 Added 1 wrapped function to freetype (for SOR4) 2021-11-02 22:21:36 +01:00
ptitSeb 27cf5c81b2 Better wrapping for libz inflate 2021-11-02 22:08:43 +01:00
ptitSeb 323783bf49 [DYNAREC] Fixed right shift emmiter with const = 1 (help wine 6.17, and probably many other stuffs) 2021-11-01 13:20:32 +01:00
ptitSeb fbd9604dc1 Added handling of ARCH_GET_FS to arch_prctl 2021-11-01 13:19:44 +01:00
ptitSeb 5494d417c0 [DEBUG] Don't overwrite trace if %pid is used 2021-11-01 11:28:17 +01:00
ptitSeb 472037cba2 [ARM64] Check if Atomics are supported (not used yet) 2021-11-01 11:27:36 +01:00
ptitSeb 1b19d8b909 Added Phytium paragraph to COMPILE.md 2021-10-30 12:12:13 +02:00
ptitSeb c2909c32ab Updated the CHANGELOG 2021-10-27 19:42:19 +02:00
ptitSeb a7c0c01bf4 [DYNAREC] Cancel a dynablock if a segfault occurs while building it 2021-10-27 19:42:01 +02:00
ptitSeb d80226ec61 Added signalfd wrapped function to libc 2021-10-26 20:10:29 +02:00
ptitSeb da81ba5be8 Fixed some program (like the one made in rust) that was getting the command line properly 2021-10-26 19:03:03 +02:00
ptitSeb f81874277c Added reboot wrapped function to libc 2021-10-26 18:30:38 +02:00
ptitSeb d93b97ee92 Added a bunch of aio_ and mq_ wrapped function to librt 2021-10-26 17:45:24 +02:00
ptitSeb 4812d20da5 Added mogery to major code contributor in chinese Readme too 2021-10-25 09:34:47 +02:00
ptitSeb 734e7cd47c Added @mogery to major code contributor 2021-10-25 09:34:12 +02:00
ptitSeb d052b35c40 Detect steamwebhelper and don't load it for now (until it's actually fixed) 2021-10-24 19:07:55 +02:00
ptitSeb 2bd3a3ccfa Optimized (and small fixes) to custom allocator ([DYNAREC] Speedup long launch time) 2021-10-24 19:06:23 +02:00
ptitSeb 1886c454ca Added 67 0F 67/7F ocpodes ([DYNAREC] too) (for The Last Federation) 2021-10-24 18:12:37 +02:00
ptitSeb 91ee1afe24 Added wrapped libncursesw.so.6 (for #148) 2021-10-23 19:02:49 +02:00
ptitSeb d867f578df Fixed SDL_Log wrapped function 2021-10-23 15:50:41 +02:00
ptitSeb b48ba048ed Added FcConfigAppFontAddDir wrapped function (for #150) 2021-10-22 20:54:37 +02:00
ptitSeb 35a21d8932 Merge pull request #147 from bbbruni/main
Add a debug mode compilation with disabled compiler optimizations
2021-10-21 22:14:19 +02:00
bbbruni 81ec174e2a Added PKGBUILD-x86_64-DEBUG 2021-10-21 22:47:08 +03:00
bbbruni 400ea800d9 Added PKGBUILD-tegra-DEBUG 2021-10-21 22:45:44 +03:00
bbbruni 0e1215268a Added PKGBUILD-rpi4-DEBUG 2021-10-21 22:44:24 +03:00
bbbruni a72d257443 Added PKGBUILD-rk3399-DEBUG 2021-10-21 22:42:28 +03:00
bbbruni 6a99a4b359 Changed DCMAKE_BUILD_TYPE to Debug 2021-10-21 22:40:57 +03:00
bbbruni b6764d1d6f Add debug version of PKGBUILD-arm64 2021-10-21 22:37:11 +03:00
bbbruni d5e105ce62 Disable compiler optimizations in debug mode 2021-10-21 22:31:50 +03:00
ptitSeb 45ee1e3c3c Added a new wrapped function to libc (for #143) 2021-10-21 19:31:33 +02:00
ptitSeb b1d0dde0b4 Proper fix for link issue on glibc 2.34+ (for #120) 2021-10-20 22:54:42 +02:00
ptitSeb cb06d28383 Added explicit link with libc (might help with #120) 2021-10-20 10:40:29 +02:00
ptitSeb 36bfcd21d4 Merge pull request #135 from mogery/getattr-align-wrap
Add alignment wrapper to pthread_getattr_np.
2021-10-18 10:12:48 +02:00
ptitSeb faa48276e5 Merge pull request #137 from Heasterian/patch-2
Fixing typo
2021-10-18 07:43:21 +02:00
ptitSeb 8e5d32430a Fixed build 2021-10-17 23:06:01 +02:00
Heasterian ac2d5b17dd Fixing typo 2021-10-17 23:59:46 +03:00
ptitSeb 0e2c63d9fb Merge pull request #136 from Heasterian/patch-1
Add Snapdragon 845 compilation
2021-10-17 22:21:33 +02:00
Heasterian 71b446774c Update COMPILE.md
Changes about compilation on Snapdragon 845 devices
2021-10-17 22:34:47 +03:00
Heasterian dac71e9f7b Update CMakeLists.txt
Adding configuration for Snapdragon 845 devices.
2021-10-17 22:31:45 +03:00
Gergő Móricz e1a2230e9c Add alignment wrapper to pthread_getattr_np.
This fixes stack corruption when using pthread_getattr_np on
hirsute (Ubuntu 21.04) and libc >=2.33

This should also fix #130.
2021-10-17 21:19:52 +02:00
ptitSeb 82bd4431e6 [TRAVIS] Try to use Graviton2 for Arm64 2021-10-14 08:58:27 +02:00
ptitSeb 7262288502 Merge pull request #132 from mogery/memory-map-fix
Map bricks below first 2GB of address space
2021-10-13 22:42:20 +02:00
mogery bcb0bdea77 Declare my_mmap and my_munmap to avoid warning
This adds a declaration of my_mmap and my_munmap to
src/tools/bridge.c in order to avoid a
-Wimplicit-function-declaration warning when compiling.

This should probably be moved to a header file in the
future.
2021-10-13 15:09:48 +02:00
mogery 4ca58d1f99 Fix incorrect brick cleanup
FreeBridge used free to clean up the pointer allocated by
my_mmap, which is incorrect and lead to a crash upon code
that exited gracefully.

The free was replaced with my_munmap.
2021-10-12 20:05:22 +02:00
mogery 0c27b82ff3 Map bricks below first 2GB of address space
This fixes an issue with mono where JIT compiled code would
near-call wrapped libraries, but fail because the difference
between PC and the call address did not fit into an imm32.

This was fixed by replacing posix_memalign with my_mmap and
providing the MAP_32BIT flag.

Fixes #131
2021-10-12 19:47:31 +02:00
ptitSeb 289deb3655 [DYNAREC] Added F2 0F E6 opcode 2021-10-05 23:07:32 +02:00
ptitSeb 8d69c17839 [DYNAREC] Added 67 89/C1/F7 opcodes 2021-10-05 23:06:58 +02:00
ptitSeb 348cb57240 Small fix for elfloader 2021-10-05 00:23:42 +02:00
ptitSeb 46f71f3947 Added some more crypto and ssl wrapped functions (bedrock server starts now) 2021-10-04 08:25:29 +02:00
ptitSeb 0ba4b04078 Added empty wrapped libnsl.so.1 2021-10-04 08:25:29 +02:00
ptitSeb 5a5f572162 Added Phytium profile 2021-10-02 09:46:33 +02:00
ptitSeb fb5bc122cc Added mallinfo wrapped function (for #121) 2021-09-29 08:10:06 +02:00
ptitSeb 4c328d0fca Fix g_source_new wrapped function and friends (helps Zoom) 2021-09-28 19:55:26 +02:00
ptitSeb dbce2758b2 Merge pull request #119 from Linux-Adaptation-Integrated-Toolkit/main
additional info for compilation document
2021-09-27 17:21:48 +02:00
zhaozhen 837f7edd55 additional info for compilation document 2021-09-27 22:21:49 +08:00
ptitSeb f054fb3a5f Merge pull request #118 from Jai-JAP/patch-1
Fix small typo in README.md
2021-09-26 19:12:26 +02:00
Jai A P 96831b144c Update README.md 2021-09-26 22:29:37 +05:30
ptitSeb d75116dab7 Merge pull request #117 from Linux-Adaptation-Integrated-Toolkit/main
add loongarch cmake fix and chinese document
2021-09-26 16:58:14 +02:00
zhaozhen 8da46ee305 add loongarch cmake fix and chinese document 2021-09-26 22:48:28 +08:00
ptitSeb 4cac721e74 Yeah, that too should help fix build for the untested loogarch64 support 2021-09-26 13:07:07 +02:00
ptitSeb 3fda41cbf6 Still more build fix for the untested loogarch64 support 2021-09-26 13:01:08 +02:00
ptitSeb 053d5e9b8d One more build fix for the untested loogarch64 support 2021-09-26 12:50:20 +02:00
ptitSeb 40cb14bf31 And yet another build fixe for the untested loogarch64 support 2021-09-26 12:35:45 +02:00
ptitSeb 27d18e4169 Another build fixe for the untested loogarch64 support 2021-09-26 12:24:47 +02:00
ptitSeb 5403002a36 Some build fixes for the untested loogarch64 support 2021-09-26 12:15:40 +02:00
ptitSeb 22f1a6c5ca CMake have an option for loongarch64 now 2021-09-26 12:09:16 +02:00
ptitSeb 783e9a4b74 More untested support for loongarch64 va_list 2021-09-26 12:06:01 +02:00
ptitSeb 202a067a61 Added some untested support for loongarch64 va_list 2021-09-26 11:46:04 +02:00
ptitSeb f2d1a8bc70 [DYNAREC] Somme fix for 66 83 opcodes 2021-09-26 11:29:45 +02:00
ptitSeb b6bc7922b3 Fixed some elf loading issues (like Torchlight2) 2021-09-23 19:54:52 +02:00
ptitSeb 7e4af27ba7 More work on gtk and nss3+friends 2021-09-21 20:50:52 +02:00
ptitSeb 06bbf93bf8 More work on gtk wrapping 2021-09-20 21:51:15 +02:00
ptitSeb e08bdd644b Added minimum wrapped libsecret-1 2021-09-19 21:29:06 +02:00
ptitSeb 1c5ddfafcd And 2 more wrapped gtk functions 2021-09-19 19:36:54 +02:00
ptitSeb 0f4db4c230 More gtk wrapped functions 2021-09-19 19:00:42 +02:00
ptitSeb 960ce86289 Fixed some nasty copypasta on EmuCall 2021-09-19 19:00:19 +02:00
ptitSeb b2bd3103d8 Fixed va_list conversion for aarch64 2021-09-19 18:59:34 +02:00
ptitSeb 745fd1b702 A bit more log on Interpretor mode 2021-09-19 18:59:01 +02:00
ptitSeb 6df1b65249 Added 1 more gtk function 2021-09-19 16:29:10 +02:00
ptitSeb 510f8d45e8 Added wrapped g_signal_connect_object 2021-09-19 16:24:43 +02:00
ptitSeb c5d328a5da Fixed a bug with some TLS relocation when symbol is in another elf (helps c++ softs, probably other too) 2021-09-19 16:06:24 +02:00
ptitSeb 1430c811cd Added 1 wrapped function to xcbxfixes (for #28) 2021-09-19 13:33:19 +02:00
ptitSeb ec2eadd893 More work on GTK wrapping. Still not ok, but better 2021-09-19 12:36:01 +02:00
ptitSeb 56c272c17a Added some more wrapped functions to xcb, gio2 and gobject2 (for #46) 2021-09-19 09:38:46 +02:00
ptitSeb 6f92db542b Updated wrapped libnns3, libnssutil3 and libsmime3 with more wrapped functions (from box86) 2021-09-18 21:46:00 +02:00
ptitSeb 8531750631 Added wrapped libsndfile (dwarf fortress have sound now, and seems completly playable) 2021-09-18 21:15:35 +02:00
ptitSeb 9414ece323 Added wrapped gtk2 (enough to launch Dwarf Fortress and some simple gtk2 samples) 2021-09-18 21:01:13 +02:00
ptitSeb c64cb5b92b Added 66 0F 38 39/3C opcodes ([DYNAREC] too) (for #81) 2021-09-18 08:49:55 +02:00
ptitSeb 2b1e12dafd Fixed 66 0F 3A 22 opcode for REX.W ([DYNAREC] too) (should help #81) 2021-09-16 20:54:40 +02:00
ptitSeb b4ca2be9e0 Added some libcrypto wrapped functions (for #99) 2021-09-14 21:30:41 +02:00
ptitSeb 203de52d71 Added syscall 120 (for #99) 2021-09-14 21:27:21 +02:00
ptitSeb c48333db44 Added syscall 118 (for #99) 2021-09-13 19:53:44 +02:00
ptitSeb e3552befe9 Try to use mmap first when loading elf file into memory 2021-09-12 18:37:03 +02:00
ptitSeb 6141421f92 [DYNAREC] some fixes to alternate handling and vsyscall support 2021-09-12 13:59:10 +02:00
ptitSeb 911ecc4489 Added minimal wrapped libnsp4, libnss3, libnssutil3 and linsmime3 2021-09-08 20:55:05 +02:00
ptitSeb 63ab450d87 Added 66 0F 7C ocpode (for #111) 2021-09-08 20:54:19 +02:00
ptitSeb bcc29168cd [TRAVIS] Refined the script a little bit 2021-09-08 20:53:50 +02:00
ptitSeb 4a9b0128d7 [TRAVIS] Move travis integration 2021-09-05 13:57:51 +02:00
ptitSeb 6cc56ac5f7 [TRAVIS] Specified focal as distrib to use 2021-09-05 13:42:36 +02:00
ptitSeb f53c967e18 [TRAVIS] Added python3 to travis script 2021-09-05 13:38:13 +02:00
ptitSeb b309933571 [TRAVIS] Small change 2021-09-05 13:29:17 +02:00
ptitSeb c7e8044f92 [TRAVIS] Try some travis build 2021-09-05 13:19:28 +02:00
ptitSeb 29720048e2 Started a new dev. cycle 2021-09-05 13:08:37 +02:00
227 changed files with 27837 additions and 940 deletions

No files matched your search

+83
View File
@@ -0,0 +1,83 @@
### Auto build Box64 and release its binary with Github Action
name: Build and Release Box64
on:
workflow_dispatch:
release:
push:
paths:
- "**/*.c"
- "**/*.h"
- "**/*.S"
- "**/*.py"
- "CMakeList.txt"
- "**/*.yml"
pull_request:
types: [assigned, opened, synchronize, reopened]
paths:
- "**/*.c"
- "**/*.h"
- "**/*.S"
- "**/*.py"
- "CMakeList.txt"
- "**/*.yml"
jobs:
build:
strategy:
fail-fast: false
matrix:
platform: [X64, OTHER_ARM, RPI4ARM64, RK3326, RK3399, RK3288, TEGRAX1, PHYTIUM, SD845]
type: [Release, Trace]
runs-on: ubuntu-latest
steps:
- name: "Checkout Box64 Repository"
uses: actions/checkout@v2
- name: "Environment preparation"
run: |
sudo apt-get update
if [[ ${{ matrix.platform }} != 'X64' && ${{ matrix.platform }} != 'OTHER_ARM' ]]; then
echo "BOX64_PLATFORM_MARCRO=-D${{ matrix.platform }}=1" >> $GITHUB_ENV
echo "BOX64_COMPILER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
sudo apt-get -y install git gcc-aarch64-linux-gnu cmake make python3
else
if [[ ${{ matrix.platform }} == 'X64' ]]; then
echo "BOX64_PLATFORM_MARCRO=-DLD80BITS=1 -DNOALIGN=1" >> $GITHUB_ENV
echo "BOX64_COMPILER=gcc" >> $GITHUB_ENV
sudo apt-get -y install git cmake make python3
ls /bin/*gcc*
else
echo BOX64_PLATFORM_MARCRO="-DARM_DYNAREC=ON" >> $GITHUB_ENV
echo "BOX64_COMPILER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
sudo apt-get -y install git gcc-aarch64-linux-gnu cmake make python3
fi
fi
if [[ ${{ matrix.type }} == 'Release' ]]; then
echo BOX64_BUILD_TYPE=Release >> $GITHUB_ENV
echo BOX64_HAVE_TRACE=0 >> $GITHUB_ENV
else
echo BOX64_BUILD_TYPE=RelWithDebInfo >> $GITHUB_ENV
echo BOX64_HAVE_TRACE=1 >> $GITHUB_ENV
fi
- name: "Display Build info"
run: |
echo "CMake Platform Macro: ${{ env.BOX64_PLATFORM_MARCRO }}"
echo "CMake C Compiler: ${{ env.BOX64_COMPILER }}"
echo "Build type: ${{ env.BOX64_BUILD_TYPE }}"
echo "Trace Enabled: ${{ env.BOX64_HAVE_TRACE }}"
- name: "Build Box64"
run: |
mkdir build
cd build
cmake .. -DCMAKE_C_COMPILER=${{ env.BOX64_COMPILER }} ${{ env.BOX64_PLATFORM_MARCRO }} -DCMAKE_BUILD_TYPE=${{ env.BOX64_BUILD_TYPE }} -DHAVE_TRACE=${{ env.BOX64_HAVE_TRACE }} -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON
make -j$(nproc) VERBOSE=1
- name: "Upload Artifact"
uses: actions/upload-artifact@v2
with:
name: box86-${{ matrix.platform }}-${{ matrix.type }}
path: build/box64
Executable
+24
View File
@@ -0,0 +1,24 @@
language: c
arch:
- amd64
- arm64-graviton2
os: linux
dist: focal
compiler:
- gcc
addons:
apt:
packages:
- python3
#Build steps
before_script:
- mkdir build
- cd build
- if [ "$TRAVIS_CPU_ARCH" = "arm64" ]; then cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo ; else cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo ; fi
script:
- make
- ctest --output-on-failure
+51 -2
View File
@@ -2,15 +2,26 @@ cmake_minimum_required(VERSION 3.4)
cmake_policy(SET CMP0065 NEW)
SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
option(RPI4ARM64 "Set to ON if targeting an RaspberryPI4 device with multiarch arm64 and armhf" ${RPI4ARM64})
option(RK3326 "Set to ON if targeting an Rockchip RK3326 based device" ${RK3326})
option(RK3399 "Set to ON if targeting an Rockchip RK3399 based device" ${RK3399})
option(TEGRAX1 "Set to ON if targeting an Tegra X1 based device" ${TEGRAX1})
option(PHYTIUM "Set to ON if targeting an Phytium (D2000 or FT2000/4) based device" ${PHYTIUM})
option(SD845 "Set to ON if targeting a Snapragon 845 based device" ${SD845})
option(LARCH64 "Set to ON if targeting an Loongarch64 based device" ${LARCH64})
option(USE_CCACHE "Set to ON to use ccache if present in the system" ${USE_CCACHE})
option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box64" OFF)
option(NOGIT "Set to ON if not building from a git clone repo (like when building from a zip download from github)" ${NOGIT})
if(RK3399 OR RPI4ARM64 OR RK3326 OR TEGRAX1)
if(LARCH64)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC OFF CACHE BOOL "")
endif()
if(RK3399 OR RPI4ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC ON CACHE BOOL "")
@@ -63,6 +74,18 @@ elseif(TEGRAX1)
add_definitions(-DTEGRAX1)
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a57+crypto)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a57+crypto")
elseif(PHYTIUM)
add_definitions(-DPHYSIUM)
add_definitions(-pipe -march=armv8.1-a+crc+simd+crypto)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.1-a+crc+simd+crypto+aes")
elseif(SD845)
add_definitions(-DSD845)
add_definitions(-pipe -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55")
elseif(LARCH64)
add_definitions(-DLARCH64)
add_definitions(-pipe -march=loongarch64)
set(CMAKE_ASM_FLAGS "-pipe -march=loongarch64")
elseif(ARM_DYNAREC)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto")
endif()
@@ -180,6 +203,7 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/tools/bridge.c"
"${BOX64_ROOT}/src/tools/callback.c"
"${BOX64_ROOT}/src/tools/my_cpuid.c"
"${BOX64_ROOT}/src/tools/gtkclass.c"
"${BOX64_ROOT}/src/tools/pathcoll.c"
"${BOX64_ROOT}/src/tools/fileutils.c"
"${BOX64_ROOT}/src/tools/wine_tools.c"
@@ -198,13 +222,23 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedcrypto.c"
"${BOX64_ROOT}/src/wrapped/wrappedcurl.c"
"${BOX64_ROOT}/src/wrapped/wrappeddbus.c"
"${BOX64_ROOT}/src/wrapped/wrappeddbusglib1.c"
"${BOX64_ROOT}/src/wrapped/wrappedexpat.c"
"${BOX64_ROOT}/src/wrapped/wrappedflac.c"
"${BOX64_ROOT}/src/wrapped/wrappedfontconfig.c"
"${BOX64_ROOT}/src/wrapped/wrappedfreetype.c"
"${BOX64_ROOT}/src/wrapped/wrappedgconf2.c"
"${BOX64_ROOT}/src/wrapped/wrappedgdkpixbuf2.c"
"${BOX64_ROOT}/src/wrapped/wrappedgdkx112.c"
"${BOX64_ROOT}/src/wrapped/wrappedgio2.c"
"${BOX64_ROOT}/src/wrapped/wrappedglib2.c"
"${BOX64_ROOT}/src/wrapped/wrappedgmodule2.c"
"${BOX64_ROOT}/src/wrapped/wrappedgnutls.c"
"${BOX64_ROOT}/src/wrapped/wrappedgobject2.c"
"${BOX64_ROOT}/src/wrapped/wrappedgssapi.c"
"${BOX64_ROOT}/src/wrapped/wrappedgssapikrb5.c"
"${BOX64_ROOT}/src/wrapped/wrappedgthread2.c"
"${BOX64_ROOT}/src/wrapped/wrappedgtkx112.c"
"${BOX64_ROOT}/src/wrapped/wrappedkrb5.c"
"${BOX64_ROOT}/src/wrapped/wrappedldlinux.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibasound.c"
@@ -222,6 +256,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibncurses.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibncurses6.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibncursesw.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibncursesw6.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibogg.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibpanel.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibpcre.c"
@@ -229,6 +264,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibresolv.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibrt.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibsm.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibsndfile.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibssl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibtinfo.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibtinfo6.c"
@@ -265,10 +301,16 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibz.c"
"${BOX64_ROOT}/src/wrapped/wrappedlzma.c"
"${BOX64_ROOT}/src/wrapped/wrappedmpg123.c"
"${BOX64_ROOT}/src/wrapped/wrappednsl.c"
"${BOX64_ROOT}/src/wrapped/wrappednspr4.c"
"${BOX64_ROOT}/src/wrapped/wrappednss3.c"
"${BOX64_ROOT}/src/wrapped/wrappednssutil3.c"
"${BOX64_ROOT}/src/wrapped/wrappedopenal.c"
"${BOX64_ROOT}/src/wrapped/wrappedpango.c"
"${BOX64_ROOT}/src/wrapped/wrappedpangocairo.c"
"${BOX64_ROOT}/src/wrapped/wrappedpangoft2.c"
"${BOX64_ROOT}/src/wrapped/wrappedplc4.c"
"${BOX64_ROOT}/src/wrapped/wrappedplds4.c"
"${BOX64_ROOT}/src/wrapped/wrappedpng16.c"
"${BOX64_ROOT}/src/wrapped/wrappedpulse.c"
"${BOX64_ROOT}/src/wrapped/wrappedpulsesimple.c"
@@ -278,13 +320,17 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedsdl1net.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl1sound.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl1ttf.c"
"${BOX64_ROOT}/src/wrapped/wrappedsecret1.c"
"${BOX64_ROOT}/src/wrapped/wrappedsmpeg.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl2.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl2image.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl2mixer.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl2net.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl2ttf.c"
"${BOX64_ROOT}/src/wrapped/wrappedselinux.c"
"${BOX64_ROOT}/src/wrapped/wrappedsmime3.c"
"${BOX64_ROOT}/src/wrapped/wrappedsmpeg2.c"
"${BOX64_ROOT}/src/wrapped/wrappedssl3.c"
"${BOX64_ROOT}/src/wrapped/wrappedtcmallocminimal.c"
"${BOX64_ROOT}/src/wrapped/wrappedudev0.c"
"${BOX64_ROOT}/src/wrapped/wrappedudev1.c"
@@ -294,6 +340,9 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedxkbcommon.c"
"${BOX64_ROOT}/src/wrapped/wrappedxkbcommonx11.c"
"${BOX64_ROOT}/src/wrapped/wrappedxml2.c"
"${BOX64_ROOT}/src/wrapped/wrappedxslt.c"
"${BOX64_ROOT}/src/wrapped/wrappedldapr.c"
"${BOX64_ROOT}/src/wrapped/wrappedlber.c"
)
#set(WRAPPEDS_HEAD "${BOX64_ROOT}/src/wrapped/wrappedd3dadapter9_gen.h")
@@ -415,7 +464,7 @@ add_executable(${BOX64} ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX64_ROOT}/src/git_head
set_target_properties(${BOX64} PROPERTIES ENABLE_EXPORTS ON)
add_dependencies(${BOX64} WRAPPERS)
#add_dependencies(${BOX64} PRINTER)
target_link_libraries(${BOX64} m dl rt pthread)
target_link_libraries(${BOX64} c m dl rt pthread)
if(ARM_DYNAREC)
target_link_libraries(${BOX64} dynarec)
endif()
+32 -1
View File
@@ -1,5 +1,36 @@
Current Version
v0.1.6
======
* Introduce "HotPage", to temporarily disable Dynarec on a page were writing is also occuring (can help speed up C# code)
* Some work on Dynarec to limit the number of mutex use, and also allow smaller block to be built (for JIT'd programs)
* Introduce BOX64_DYNAREC_STRONGMEM for the (Arm) dynarec to emulate StrngMemory Model (needed by some games, like RimWorld)
* More functions wrapped
* Improve speed of the custom allocator used by dynarec and Hash (speedup loading)
* Added a workaround for streamwebhelper to not load it
* More opcodes added
* More wrapped libraries, including gtk2
* Added a fix for linking box64 on system using glibc 2.34+
* Some residual fixes on thread attribute handling
* Better handling of app that want 32bits jumps, like unity3d/mono (thanks mogery)
* More ARM hardware option in CMake (Phytium, NX...)
* Added loongarch64 support (interpretor only)
* Some fixes to elfloader
* Added a mecanism to cancel a Dynarec block construction if it triggers a segfault (instead of a crash)
v0.1.4
======
* Reworked README a bit
* Added some more wrapped libs
* Added some SSE4x opcodes
* Preliminary support for VSyscall (still missing VDSO)
* Added support for AES-NI cpu extension, also in Dynarec (and using ARM extension if present)
* Added some syscall
* Added some more wrapped functions
* Improvment to the handling of longjmp inside signal handlers
* Improved wrapper helpers (from rajdakin)
* Some fixes to opcodes (especially C2 flags for some x87 opcodes)
* Handling of some specific opcode as privileged instruction (instead of NOP)
* Fixed ELF signature detection
* Some fixes to a few env. var. handling
v0.1.2
======
+49
View File
@@ -47,6 +47,55 @@ If it's the first install, you also need:
sudo systemctl restart systemd-binfmt
```
#### for Snapdragon 845
Using a 64bits OS:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DSD845=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
```
----
#### for Phytium
Using a 64bits OS:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DPHYTIUM=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
```
#### for LoongArch
Using a 64bits OS:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DLARCH64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
```
#### for Other ARM64 Linux platforms
`mkdir build; cd build; cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j$(nproc)`
+6 -2
View File
@@ -4,6 +4,9 @@
Linux Userspace x86_64 Emulator with a twist
----
![box64 build status](https://app.travis-ci.com/ptitSeb/box64.svg?branch=main)
[中文](README_CN.md)
Box64 lets you run x86_64 Linux programs (such as games) on non-x86_64 Linux systems, like ARM (host system needs to be 64bit little-endian).
@@ -75,7 +78,7 @@ GTK libraries are not wrapped yet on box64 (contrary to box86). Many games use g
Notes about Steam
----
Not that Steam is an hybrid 32buts / 64bits. You NEED box86 to run steam, as the client app is a 32bits binaries. It also use a 64bits local server binaries, but like most stuff using libsef/chromium. it's not working correctly on box64 for now.
Not that Steam is an hybrid 32bits / 64bits. You NEED box86 to run steam, as the client app is a 32bits binaries. It also use a 64bits local server binaries, but like most stuff using libcef/chromium. it's not working correctly on box64 for now.
So: no Steam for now on box64.
----
@@ -100,8 +103,9 @@ Final word
I want to thank everyone who has contributed to box64 developpement.
There are many ways to contribute: code contribution, financial, hardware and advertisement!
So, in no particular order, I want to thank:
* For their major code contribution: rajdakin
* For their major code contribution: rajdakin, mogery
* For their major financial contribution: FlyingFathead, stormchaser3000
* For hardware contribution and LoongArch migration: [xiaoji](https://www.linuxgame.cn/), Deepin Beijing Develop Team
* For their hardware contribution: [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/)
* For their continous advertisement of box64 project: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS](https://twisteros.com/) team, [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
+119
View File
@@ -0,0 +1,119 @@
# box64
![Official logo](img/Box64Logo.png "Official Logo")
Linux上用户空间的x86_64应用模拟器
----
![box64 build status](https://app.travis-ci.com/ptitSeb/box64.svg?branch=main)
[English](README.md)
在ARM或其他非X86_64架构的Linux操作系统上,使用Box64可以运行x86_64 Linux程序(例如游戏),请注意,主机系统需要**64位小端**。
您可以在Youtube的[MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)、[Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)或[The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA)频道找到更多Box64视频。
Box64使用了一些“系统”库的原生版本,例如libc、libm、SDL和OpenGL,所以它很容易与大多数应用程序集成和使用,并且在很多情况下性能会出奇的高。点击[此处](https://box86.org/index.php/2021/06/game-performances/)查看示例的基准测试分析。
Box64为ARM64平台集成了DynaRec(动态重编译器),比仅使用解释器提升5到10倍性能。关于Dynarec如何工作的更多信息,可以在[这里](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/)找到。
注:DynaRec需要针对不同平台编写一部分汇编代码,目前仅支持ARM64。
一些x64内部操作码使用“Realmode X86 Emulator Library”的部分内容,请参阅[x64primop.c](../src/emu/x64primop.c)了解版权详情
<img src="img/Box64Icon.png" width="96" height="96">
Logo和图标由grayduck制作,感谢!
----
使用方法
----
若干环境变量可以设置Box64的行为。
点击[这里](USAGE.md)了解所有的环境变量和它们的作用。
请注意:Box64的Dynarec提供了一种机制来处理JIT代码,包含内存保护和段错误信号处理程序。简单地说,如果您想用GDB来调试一个使用JIT代码的运行程序(比如mono/Unity3D),您仍然会触发很多“正常”的段错误。建议在GDB中使用类似于`handle SIGSEGV nostop`的东西,不要在每个段错误时都停止,如果您想捕获段错误,可以在`signals.c`中的`my_memprotectionhandler`中放置一个断点。
----
编译/安装
----
> 编译说明可以在[这里](COMPILE.md)查看。
----
版本历史
----
版本日志在[这里](CHANGELOG.md)。
----
32位平台的注意事项
----
Box64的工作原理是直接将函数调用从x86_64转换到主机系统,主机系统(Box64运行的系统)需要有64位的库。Box64并不包括任何64位<->32位的转换。
所以请理解,Box64只能运行64位的Linux二进制文件。对于32位的二进制文件,需要Box86(在64位的操作系统上需要所有的multiarch库或一些proot技巧)。
请注意,许多(基于mojo的)安装程序,即使存在x86_64版本,但在检测到架构为ARM64时会退回到"x86",这时会尝试使用(如果有)box86进行安装。这时你可以使用一个假的"uname",当它的参数为"-m"时返回"x86_64"。
----
关于Unity游戏模拟的注意事项
----
当前Unity游戏模拟是一件碰运气的事情。Unity使用Mono(它的信号表示,并不总能100%成功模拟)。
您还应该注意,一些Unity3D游戏需要OpenGL 3+,目前在ARM SBC(单板计算机)上提供OpenGL 3+是很棘手的。
所以,并不是所有的Unity游戏都能工作,而且可能需要很高的OpenGL配置,但现在很多游戏都能工作。
提示:如果游戏开始后在显示任何东西之前退出,在Pi4上使用`MESA_GL_VERSION_OVERRIDE=3.2`,在Panfrost上使用`PAN_MESA_DEBUG=gl3`来使用更高的配置文件。
----
关于GTK程序的注意事项
----
GTK库尚未封装在Box64内(与Box86相反)。许多游戏(包括设置)都使用gtk,例如Unity游戏的屏幕选择对话框。有些Unity游戏可以在没有该对话框的情况下运行(使用默认设置),还有一些不能。您需要将一套gtk x86_64库放在游戏目录(或其他一些Box64识别的目录)中以获得gtk支持。Box64有计划封装GTK原生库。
----
关于Steam的注意事项
----
Steam并不是32位/64位混合的,而是32位的,因此您需要Box86才能运行Steam。Steam也使用64位的本地服务器程序,但像大多数使用libcef/chromium的程序一样,在box64上暂时无法正常工作。
所以:目前在box64上无法运行Steam。
----
关于Wine的注意事项
----
box64支持64位Wine,但请注意,64位的Wine还包含32位的组件,以便能够运行32位的Windws程序。32位程序需要Box86,没有它就不能运行。在Box64和Box86共存的系统上,设置64位Wine可以同时运行32位和64位windows程序(只需分别使用 `wine` 和 `wine64`)。
----
关于Vulkan注意事项
----
Box64尚未封装原生Vulkan库,有计划这么做,但目前,vulkan程序不能在box64上运行。
----
结语
----
我要感谢所有为 box64 开发做出贡献的人。
贡献方式有很多种:代码贡献、财务帮助、捐赠捐赠和广告合作!
以下感谢不分先后:
* 代码贡献:rajdakin, mogery
* 财务帮助:FlyingFathead, stormchaser3000
* 硬件捐赠:[Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/)
* 硬件捐赠和LoongArch迁移:[xiaoji](https://www.linuxgame.cn)
* 为本项目持续的宣传:salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS](https://twisteros.com/) team, [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
我还要感谢很多人,即使他们只参与了一次本项目。
(如果你的项目中使用了Box64,请不要忘记提及!)
+11
View File
@@ -115,6 +115,17 @@ Enables/Disables trace for generated code.
Forbid dynablock creation in the interval specified (helpfull for debugging behaviour difference between Dynarec and Interpretor)
* 0xXXXXXXXX-0xYYYYYYYY : define the interval where dynablock cannot start (inclusive-exclusive)
#### BOX64_DYNAREC_BIGBLOCK
Enables/Disables Box64's Dynarec building BigBlock.
* 0 : Don't try to build block as big as possible (can help program using lots of thread and a JIT, like C#/Unity) (Default when libmonobdwgc-2.0.so is loaded)
* 1 : Build Dynarec block as big as possible (Default.)
#### BOX64_DYNAREC_STRONGMEM
Enable/Disable simulation of Strong Memory model
* 0 : Don't try anything special (Default.)
* 1 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
* 2 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model
#### BOX64_LIBGL
* libXXXX set the name for libGL (defaults to libGL.so.1).
* /PATH/TO/libGLXXX : Sets the name and path for libGL
+44
View File
@@ -0,0 +1,44 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-arm64-git
pkgver=1116.9243ea4
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box64"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-arm64-git}-git" "${pkgname%-arm64-git}")
conflicts=("${pkgname%-git}" "${pkgname%-arm64-git}-git" "${pkgname%-arm64-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-arm64-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-arm64-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=Debug
fi
}
build() {
cd "$srcdir/${pkgname%-arm64-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-arm64-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
}
+44
View File
@@ -0,0 +1,44 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-rk3399-git
pkgver=1116.9243ea4
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box64"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-rk3399-git}-git" "${pkgname%-rk3399-git}")
conflicts=("${pkgname%-git}" "${pkgname%-rk3399-git}-git" "${pkgname%-rk3399-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-rk3399-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-rk3399-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=Debug
fi
}
build() {
cd "$srcdir/${pkgname%-rk3399-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-rk3399-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
}
+44
View File
@@ -0,0 +1,44 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-rpi-git
pkgver=1116.9243ea4
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box64"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%-rpi-git}")
conflicts=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%-rpi-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-rpi-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-rpi-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=Debug
fi
}
build() {
cd "$srcdir/${pkgname%-rpi-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-rpi-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
}
+44
View File
@@ -0,0 +1,44 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-tegra-git
pkgver=1116.9243ea4
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box64"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-tegra-git}-git" "${pkgname%-tegra-git}")
conflicts=("${pkgname%-git}" "${pkgname%-tegra-git}-git" "${pkgname%-tegra-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-tegra-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-tegra-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DTEGRAX1=1 -DCMAKE_BUILD_TYPE=Debug
fi
}
build() {
cd "$srcdir/${pkgname%-tegra-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-tegra-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
}
+43
View File
@@ -0,0 +1,43 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-x64-git
pkgver=1116.9243ea4
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box64"
license=('MIT')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-x64-git}-git" "${pkgname%-x64-git}")
conflicts=("${pkgname%-git}" "${pkgname%-x64-git}-git" "${pkgname%-x64-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-x64-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-x64-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=Debug
fi
}
build() {
cd "$srcdir/${pkgname%-x64-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-x64-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
}
+10 -10
View File
@@ -169,9 +169,9 @@ box64context_t *NewBox64Context(int argc)
context->vsyscalls[1] = AddVSyscall(context->system, 201);
context->vsyscalls[2] = AddVSyscall(context->system, 309);
// create the alternate to map at address
addAlternate((void*)context->vsyscalls[0], (void*)0xffffffffff600000);
addAlternate((void*)context->vsyscalls[1], (void*)0xffffffffff600400);
addAlternate((void*)context->vsyscalls[2], (void*)0xffffffffff600800);
addAlternate((void*)0xffffffffff600000, (void*)context->vsyscalls[0]);
addAlternate((void*)0xffffffffff600400, (void*)context->vsyscalls[1]);
addAlternate((void*)0xffffffffff600800, (void*)context->vsyscalls[2]);
// get handle to box64 itself
context->box64lib = dlopen(NULL, RTLD_NOW|RTLD_GLOBAL);
context->dlprivate = NewDLPrivate();
@@ -270,6 +270,13 @@ void FreeBox64Context(box64context_t** context)
if(ctx->tlsdata)
free(ctx->tlsdata);
free_neededlib(&ctx->neededlibs);
if(ctx->emu_sig)
FreeX64Emu(&ctx->emu_sig);
finiAllHelpers(ctx);
pthread_mutex_destroy(&ctx->mutex_once);
pthread_mutex_destroy(&ctx->mutex_once2);
pthread_mutex_destroy(&ctx->mutex_trace);
@@ -282,13 +289,6 @@ void FreeBox64Context(box64context_t** context)
pthread_mutex_destroy(&ctx->mutex_thread);
pthread_mutex_destroy(&ctx->mutex_bridge);
free_neededlib(&ctx->neededlibs);
if(ctx->emu_sig)
FreeX64Emu(&ctx->emu_sig);
finiAllHelpers(ctx);
free(ctx);
}
+1 -1
View File
@@ -3,6 +3,6 @@
#define BOX64_MAJOR 0
#define BOX64_MINOR 1
#define BOX64_REVISION 4
#define BOX64_REVISION 6
#endif //__BOX64_VERSION_H_
+309 -250
View File
@@ -31,21 +31,21 @@
// init inside dynablocks.c
KHASH_MAP_INIT_INT64(dynablocks, dynablock_t*)
static dynablocklist_t*** dynmap123[1<<DYNAMAP_SHIFT]; // 64bits.. in 4x16bits array
static pthread_mutex_t mutex_mmap;
static mmaplist_t *mmaplist;
static size_t mmapsize;
static mmaplist_t *mmaplist = NULL;
static size_t mmapsize = 0;
static size_t mmapcap = 0;
static kh_dynablocks_t *dblist_oversized; // store the list of oversized dynablocks (normal sized are inside mmaplist)
static uintptr_t*** box64_jmptbl3[1<<JMPTABL_SHIFT];
static uintptr_t** box64_jmptbldefault2[1<<JMPTABL_SHIFT];
static uintptr_t* box64_jmptbldefault1[1<<JMPTABL_SHIFT];
static uintptr_t box64_jmptbldefault0[1<<JMPTABL_SHIFT];
#endif
#define MEMPROT_SHIFT 12
#define MEMPROT_SHIFT2 (32-MEMPROT_SHIFT)
#define MEMPROT_SIZE (1<<(32-MEMPROT_SHIFT))
static pthread_mutex_t mutex_prot;
KHASH_MAP_INIT_INT(memprot, uint8_t*)
static kh_memprot_t *memprot;
#define MEMPROT_SHIFT 12
#define MEMPROT_SHIFT2 (16+12)
#define MEMPROT_SIZE (1<<16)
static uint8_t *volatile memprot[1<<20]; // x86_64 mem is 48bits, page is 12bits, so memory is tracked as [20][16][page protection]
static uint8_t memprot_default[MEMPROT_SIZE];
static int inited = 0;
typedef struct blocklist_s {
@@ -62,8 +62,8 @@ static blocklist_t* p_blocks = NULL; // actual blocks for custom mallo
typedef union mark_s {
struct {
unsigned int fill:1;
unsigned int size:31;
unsigned int fill:1;
};
uint32_t x32;
} mark_t;
@@ -72,86 +72,123 @@ typedef struct blockmark_s {
mark_t next;
} blockmark_t;
#define NEXT_BLOCK(b) (blockmark_t*)((uintptr_t)(b) + (b)->next.size + sizeof(blockmark_t))
#define PREV_BLOCK(b) (blockmark_t*)(((uintptr_t)(b) - (b)->prev.size) - sizeof(blockmark_t))
#define LAST_BLOCK(b, s) (blockmark_t*)(((uintptr_t)(b)+(s))-sizeof(blockmark_t))
static void printBlock(blockmark_t* b, void* start)
{
printf_log(LOG_INFO, "========== Block is:\n");
do {
printf_log(LOG_INFO, "%c%p, fill=%d, size=0x%x (prev=%d/0x%x)\n", b==start?'*':' ', b, b->next.fill, b->next.size, b->prev.fill, b->prev.size);
b = NEXT_BLOCK(b);
} while(b->next.x32);
printf_log(LOG_INFO, "===================\n");
}
// get first subblock free in block. Return NULL if no block, else first subblock free (mark included), filling size
static void* getFirstBlock(void* block, size_t maxsize, size_t* size)
static void* getFirstBlock(void* block, size_t maxsize, size_t* size, void* start)
{
// get start of block
blockmark_t *m = (blockmark_t*)block;
blockmark_t *m = (blockmark_t*)((start)?start:block);
while(m->next.x32) { // while there is a subblock
if(!m->next.fill && m->next.size>=maxsize+sizeof(blockmark_t)) {
*size = m->next.size-sizeof(blockmark_t);
if(!m->next.fill && m->next.size>=maxsize) {
*size = m->next.size;
return m;
}
m = (blockmark_t*)((uintptr_t)m + m->next.size);
m = NEXT_BLOCK(m);
}
return NULL;
}
static size_t getMaxFreeBlock(void* block, size_t block_size)
static size_t getMaxFreeBlock(void* block, size_t block_size, void* start)
{
// get start of block
blockmark_t *m = (blockmark_t*)((uintptr_t)block+block_size-sizeof(blockmark_t)); // start with the end
int maxsize = 0;
while(m->prev.x32) { // while there is a subblock
if(!m->prev.fill && m->prev.size>maxsize) {
maxsize = m->prev.size;
if((uintptr_t)block+maxsize>(uintptr_t)m)
return (maxsize>=sizeof(blockmark_t))?(maxsize-sizeof(blockmark_t)):0; // no block large enough left...
if(start) {
blockmark_t *m = (blockmark_t*)start;
int maxsize = 0;
while(m->next.x32) { // while there is a subblock
if(!m->next.fill && m->next.size>maxsize) {
maxsize = m->next.size;
}
m = NEXT_BLOCK(m);
}
m = (blockmark_t*)((uintptr_t)m - m->prev.size);
return (maxsize>=sizeof(blockmark_t))?maxsize:0;
} else {
blockmark_t *m = LAST_BLOCK(block, block_size); // start with the end
int maxsize = 0;
while(m->prev.x32) { // while there is a subblock
if(!m->prev.fill && m->prev.size>maxsize) {
maxsize = m->prev.size;
if((uintptr_t)block+maxsize>(uintptr_t)m)
return (maxsize>=sizeof(blockmark_t))?maxsize:0; // no block large enough left...
}
m = PREV_BLOCK(m);
}
return (maxsize>=sizeof(blockmark_t))?maxsize:0;
}
return (maxsize>=sizeof(blockmark_t))?(maxsize-sizeof(blockmark_t)):0;
}
static void* allocBlock(void* block, void *sub, size_t size)
static void* allocBlock(void* block, void *sub, size_t size, void** pstart)
{
(void)block;
blockmark_t *s = (blockmark_t*)sub;
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
blockmark_t *n = NEXT_BLOCK(s);
s->next.fill = 1;
s->next.size = size+sizeof(blockmark_t);
blockmark_t *m = (blockmark_t*)((uintptr_t)s + s->next.size); // this is new n
// check if a new mark is worth it
if(s->next.size>size+2*sizeof(blockmark_t))
s->next.size = size;
blockmark_t *m = NEXT_BLOCK(s); // this is new n
m->prev.fill = 1;
m->prev.size = s->next.size;
if(n!=m) {
// new mark
m->prev.fill = 1;
m->prev.size = s->next.size;
m->next.fill = 0;
m->next.size = (uintptr_t)n - (uintptr_t)m;
m->next.size = ((uintptr_t)n - (uintptr_t)m) - sizeof(blockmark_t);
n->prev.fill = 0;
n->prev.size = m->next.size;
}
if(pstart && sub==*pstart) {
// get the next free block
m = (blockmark_t*)*pstart;
while(m->next.fill)
m = NEXT_BLOCK(m);
*pstart = (void*)m;
}
return (void*)((uintptr_t)sub + sizeof(blockmark_t));
}
static void freeBlock(void *block, void* sub)
static size_t freeBlock(void *block, void* sub, void** pstart)
{
blockmark_t *m = (blockmark_t*)block;
blockmark_t *s = (blockmark_t*)sub;
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
blockmark_t *n = NEXT_BLOCK(s);
if(block!=sub)
m = (blockmark_t*)((uintptr_t)s - s->prev.size);
m = PREV_BLOCK(s);
s->next.fill = 0;
n->prev.fill = 0;
// check if merge with previous
if (s->prev.x32 && !s->prev.fill) {
// remove s...
m->next.size += s->next.size;
m->next.size += s->next.size + sizeof(blockmark_t);
n->prev.size = m->next.size;
s = m;
}
// check if merge with next
if(n->next.x32 && !n->next.fill) {
blockmark_t *n2 = (blockmark_t*)((uintptr_t)n + n->next.size);
blockmark_t *n2 = NEXT_BLOCK(n);
//remove n
s->next.size += n->next.size;
s->next.size += n->next.size + sizeof(blockmark_t);
n2->prev.size = s->next.size;
}
if(pstart && (uintptr_t)*pstart>(uintptr_t)sub) {
*pstart = (void*)s;
}
// return free size at current block (might be bigger)
return s->next.size;
}
// return 1 if block has been expanded to new size, 0 if not
static int expandBlock(void* block, void* sub, size_t newsize)
@@ -160,15 +197,21 @@ static int expandBlock(void* block, void* sub, size_t newsize)
newsize = (newsize+3)&~3;
blockmark_t *s = (blockmark_t*)sub;
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
blockmark_t *n = NEXT_BLOCK(s);
if(s->next.size>=newsize)
// big enough, no shrinking...
return 1;
if(s->next.fill)
return 0; // next block is filled
// unsigned bitfield of this length gets "promoted" to *signed* int...
if((size_t)(s->next.size + n->next.size) < newsize)
if((size_t)(s->next.size + n->next.size + sizeof(blockmark_t)) < newsize)
return 0; // free space too short
// ok, doing the alloc!
s->next.size = newsize+sizeof(blockmark_t);
blockmark_t *m = (blockmark_t*)((uintptr_t)s + s->next.size); // this is new n
if((s->next.size+n->next.size+sizeof(blockmark_t))-newsize<2*sizeof(blockmark_t))
s->next.size += n->next.size+sizeof(blockmark_t);
else
s->next.size = newsize+sizeof(blockmark_t);
blockmark_t *m = NEXT_BLOCK(s); // this is new n
m->prev.fill = 1;
m->prev.size = s->next.size;
if(n!=m) {
@@ -197,11 +240,11 @@ void* customMalloc(size_t size)
for(int i=0; i<n_blocks; ++i) {
if(p_blocks[i].maxfree>=size) {
size_t rsize = 0;
sub = getFirstBlock(p_blocks[i].block, size, &rsize);
sub = getFirstBlock(p_blocks[i].block, size, &rsize, NULL);
if(sub) {
void* ret = allocBlock(p_blocks[i].block, sub, size);
void* ret = allocBlock(p_blocks[i].block, sub, size, NULL);
if(rsize==p_blocks[i].maxfree)
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size);
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL);
pthread_mutex_unlock(&mutex_blocks);
return ret;
}
@@ -225,14 +268,14 @@ void* customMalloc(size_t size)
blockmark_t* m = (blockmark_t*)p;
m->prev.x32 = 0;
m->next.fill = 0;
m->next.size = allocsize-sizeof(blockmark_t);
m = (blockmark_t*)(p+allocsize-sizeof(blockmark_t));
m->next.x32 = 0;
m->prev.fill = 0;
m->prev.size = allocsize-sizeof(blockmark_t);
m->next.size = allocsize-2*sizeof(blockmark_t);
blockmark_t* n = NEXT_BLOCK(m);
n->next.x32 = 0;
n->prev.fill = 0;
n->prev.size = m->next.size;
// alloc 1st block
void* ret = allocBlock(p_blocks[i].block, p, size);
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size);
void* ret = allocBlock(p_blocks[i].block, p, size, NULL);
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL);
pthread_mutex_unlock(&mutex_blocks);
return ret;
}
@@ -254,7 +297,7 @@ void* customRealloc(void* p, size_t size)
&& (addr<((uintptr_t)p_blocks[i].block+p_blocks[i].size))) {
void* sub = (void*)(addr-sizeof(blockmark_t));
if(expandBlock(p_blocks[i].block, sub, size)) {
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size);
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL);
pthread_mutex_unlock(&mutex_blocks);
return p;
}
@@ -280,8 +323,8 @@ void customFree(void* p)
if ((addr>(uintptr_t)p_blocks[i].block)
&& (addr<((uintptr_t)p_blocks[i].block+p_blocks[i].size))) {
void* sub = (void*)(addr-sizeof(blockmark_t));
freeBlock(p_blocks[i].block, sub);
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size);
size_t newfree = freeBlock(p_blocks[i].block, sub, NULL);
if(p_blocks[i].maxfree < newfree) p_blocks[i].maxfree = newfree;
pthread_mutex_unlock(&mutex_blocks);
return;
}
@@ -298,6 +341,8 @@ typedef struct mmaplist_s {
size_t size;
kh_dynablocks_t* dblist;
uint8_t* helper;
void* first; // first free block, to speed up things
int locked; // don't try to add stuff on locked block
} mmaplist_t;
uintptr_t FindFreeDynarecMap(dynablock_t* db, size_t size)
@@ -305,13 +350,15 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, size_t size)
// look for free space
void* sub = NULL;
for(size_t i=0; i<mmapsize; ++i) {
if(mmaplist[i].maxfree>=size) {
if(mmaplist[i].maxfree>=size+sizeof(blockmark_t) && !mmaplist[i].locked) {
mmaplist[i].locked = 1;
size_t rsize = 0;
sub = getFirstBlock(mmaplist[i].block, size, &rsize);
sub = getFirstBlock(mmaplist[i].block, size, &rsize, mmaplist[i].first);
if(sub) {
uintptr_t ret = (uintptr_t)allocBlock(mmaplist[i].block, sub, size);
if(rsize==mmaplist[i].maxfree)
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size);
uintptr_t ret = (uintptr_t)allocBlock(mmaplist[i].block, sub, size, &mmaplist[i].first);
if(rsize==mmaplist[i].maxfree) {
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size, mmaplist[i].first);
}
kh_dynablocks_t *blocks = mmaplist[i].dblist;
if(!blocks) {
blocks = mmaplist[i].dblist = kh_init(dynablocks);
@@ -321,9 +368,17 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, size_t size)
int r;
k = kh_put(dynablocks, blocks, (uintptr_t)ret, &r);
kh_value(blocks, k) = db;
for(size_t j=0; j<size; ++j)
mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+j] = (j<256)?j:255;
int size255=(size<256)?size:255;
for(size_t j=0; j<size255; ++j)
mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+j] = j;
if(size!=size255)
memset(&mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+256], -1, size-255);
mmaplist[i].locked = 0;
return ret;
} else {
printf_log(LOG_INFO, "BOX64: Warning, sub not found, corrupted mmaplist[%zu] info?\n", i);
if(box64_log >= LOG_DEBUG)
printBlock(mmaplist[i].block, mmaplist[i].first);
}
}
}
@@ -333,8 +388,11 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, size_t size)
uintptr_t AddNewDynarecMap(dynablock_t* db, size_t size)
{
size_t i = mmapsize++;
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%zu\n", mmapsize);
mmaplist = (mmaplist_t*)realloc(mmaplist, mmapsize*sizeof(mmaplist_t));
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%zu/%zu\n", mmapsize, mmapcap);
if(mmapsize>mmapcap) {
mmapcap += 32;
mmaplist = (mmaplist_t*)realloc(mmaplist, mmapcap*sizeof(mmaplist_t));
}
#ifndef USE_MMAP
void *p = NULL;
if(posix_memalign(&p, box64_pagesize, MMAPSIZE)) {
@@ -353,21 +411,23 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, size_t size)
#endif
setProtection((uintptr_t)p, MMAPSIZE, PROT_READ | PROT_WRITE | PROT_EXEC);
mmaplist[i].locked = 1;
mmaplist[i].block = p;
mmaplist[i].size = MMAPSIZE;
mmaplist[i].helper = (uint8_t*)calloc(1, MMAPSIZE);
mmaplist[i].first = p;
// setup marks
blockmark_t* m = (blockmark_t*)p;
m->prev.x32 = 0;
m->next.fill = 0;
m->next.size = MMAPSIZE-sizeof(blockmark_t);
m = (blockmark_t*)(p+MMAPSIZE-sizeof(blockmark_t));
m->next.x32 = 0;
m->prev.fill = 0;
m->prev.size = MMAPSIZE-sizeof(blockmark_t);
m->next.size = MMAPSIZE-2*sizeof(blockmark_t);
blockmark_t* n = NEXT_BLOCK(m);
n->next.x32 = 0;
n->prev.fill = 0;
n->prev.size = m->next.size;
// alloc 1st block
uintptr_t sub = (uintptr_t)allocBlock(mmaplist[i].block, p, size);
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size);
uintptr_t sub = (uintptr_t)allocBlock(mmaplist[i].block, p, size, &mmaplist[i].first);
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size, mmaplist[i].first);
kh_dynablocks_t *blocks = mmaplist[i].dblist = kh_init(dynablocks);
kh_resize(dynablocks, blocks, 64);
khint_t k;
@@ -376,6 +436,7 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, size_t size)
kh_value(blocks, k) = db;
for(size_t j=0; j<size; ++j)
mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block + j] = (j<256)?j:255;
mmaplist[i].locked = 0;
return sub;
}
@@ -388,15 +449,18 @@ void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t size)
if ((addr>(uintptr_t)mmaplist[i].block)
&& (addr<((uintptr_t)mmaplist[i].block+mmaplist[i].size))) {
void* sub = (void*)(addr-sizeof(blockmark_t));
freeBlock(mmaplist[i].block, sub);
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size);
size_t newfree = freeBlock(mmaplist[i].block, sub, &mmaplist[i].first);
if(mmaplist[i].maxfree < newfree) mmaplist[i].maxfree = newfree;
kh_dynablocks_t *blocks = mmaplist[i].dblist;
if(blocks) {
khint_t k = kh_get(dynablocks, blocks, (uintptr_t)sub);
if(k!=kh_end(blocks))
kh_del(dynablocks, blocks, k);
for(size_t j=0; j<size; ++j)
mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block+j] = 0;
memset(&mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block], 0, size);
}
if(mmaplist[i].locked) {
printf_log(LOG_INFO, "BOX64: Warning, Free a chunk in a locked mmaplist[%zu]\n", i);
++mmaplist[i].locked;
}
return;
}
@@ -432,11 +496,9 @@ uintptr_t AllocDynarecMap(dynablock_t* db, size_t size)
if(!size)
return 0;
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
pthread_mutex_lock(&mutex_mmap);
#ifndef USE_MMAP
void *p = NULL;
if(posix_memalign(&p, box64_pagesize, size)) {
pthread_mutex_unlock(&mutex_mmap);
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", size);
return 0;
}
@@ -444,7 +506,6 @@ uintptr_t AllocDynarecMap(dynablock_t* db, size_t size)
#else
void* p = mmap(NULL, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
if(p==(void*)-1) {
pthread_mutex_unlock(&mutex_mmap);
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", size);
return 0;
}
@@ -459,18 +520,14 @@ uintptr_t AllocDynarecMap(dynablock_t* db, size_t size)
int ret;
k = kh_put(dynablocks, blocks, (uintptr_t)p, &ret);
kh_value(blocks, k) = db;
pthread_mutex_unlock(&mutex_mmap);
return (uintptr_t)p;
}
pthread_mutex_lock(&mutex_mmap);
uintptr_t ret = FindFreeDynarecMap(db, size);
if(!ret)
ret = AddNewDynarecMap(db, size);
pthread_mutex_unlock(&mutex_mmap);
return ret;
}
@@ -479,7 +536,6 @@ void FreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t size)
if(!addr || !size)
return;
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
pthread_mutex_lock(&mutex_mmap);
#ifndef USE_MMAP
free((void*)addr);
#else
@@ -491,12 +547,9 @@ void FreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t size)
if(k!=kh_end(blocks))
kh_del(dynablocks, blocks, k);
}
pthread_mutex_unlock(&mutex_mmap);
return;
}
pthread_mutex_lock(&mutex_mmap);
ActuallyFreeDynarecMap(db, addr, size);
pthread_mutex_unlock(&mutex_mmap);
}
dynablocklist_t* getDB(uintptr_t idx)
@@ -695,44 +748,35 @@ uintptr_t getJumpTableAddress64(uintptr_t addr)
}
// Remove the Write flag from an adress range, so DB can be executed safely
void protectDBnolock(uintptr_t addr, uintptr_t size)
void protectDB(uintptr_t addr, uintptr_t size)
{
dynarec_log(LOG_DEBUG, "protectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
if(end>=(1LL<<(20+16)))
end = (1LL<<(20+16))-1;
if(end<idx) // memory addresses higher than 48bits are not tracked
return;
pthread_mutex_lock(&mutex_prot);
int ret;
for (uintptr_t i=idx; i<=end; ++i) {
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
khint_t k = kh_put(memprot, memprot, key, &ret);
if(ret) {
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
kh_value(memprot, k) = m;
for (uintptr_t i=(idx>>16); i<=(end>>16); ++i)
if(memprot[i]==memprot_default) {
uint8_t* newblock = calloc(1<<16, sizeof(uint8_t));
/*if (arm64_lock_storeifref(&memprot[i], newblock, memprot_default) != newblock) {
free(newblock);
}*/
memprot[i] = newblock;
}
const uintptr_t ii = i&(MEMPROT_SIZE-1);
uint8_t prot = kh_value(memprot, k)[ii];
if(!(prot&PROT_DYNAREC)) {
if(!prot)
prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute
kh_value(memprot, k)[ii] = prot|PROT_DYNAREC;
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~(PROT_WRITE|PROT_CUSTOM));
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t prot = memprot[i>>16][i&0xffff];
if(!prot)
prot = PROT_READ | PROT_WRITE | PROT_EXEC; // comes from malloc & co, so should not be able to execute
if((prot&PROT_WRITE)) {
prot&=~PROT_WRITE;
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot);
memprot[i>>16][i&0xffff] = prot|PROT_DYNAREC; // need to use atomic exchange?
}
}
}
void protectDB(uintptr_t addr, size_t size)
{
pthread_mutex_lock(&mutex_prot);
protectDBnolock(addr, size);
pthread_mutex_unlock(&mutex_prot);
}
void lockDB()
{
pthread_mutex_lock(&mutex_prot);
}
void unlockDB()
{
pthread_mutex_unlock(&mutex_prot);
}
@@ -742,90 +786,109 @@ void unprotectDB(uintptr_t addr, size_t size)
{
dynarec_log(LOG_DEBUG, "unprotectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
int ret;
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
if(end>=(1LL<<(20+16)))
end = (1LL<<(20+16))-1;
if(end<idx) // memory addresses higher than 48bits are not tracked
return;
pthread_mutex_lock(&mutex_prot);
for (uintptr_t i=idx; i<=end; ++i) {
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
khint_t k = kh_put(memprot, memprot, key, &ret);
if(ret) {
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
kh_value(memprot, k) = m;
for (uintptr_t i=(idx>>16); i<=(end>>16); ++i)
if(memprot[i]==memprot_default) {
uint8_t* newblock = calloc(1<<16, sizeof(uint8_t));
/*if (arm64_lock_storeifref(&memprot[i], newblock, memprot_default) != newblock) {
free(newblock);
}*/
memprot[i] = newblock;
}
const uintptr_t ii = i&(MEMPROT_SIZE-1);
uint8_t prot = kh_value(memprot, k)[ii];
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t prot = memprot[i>>16][i&0xffff];
if(prot&PROT_DYNAREC) {
kh_value(memprot, k)[ii] = prot&~PROT_DYNAREC;
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_CUSTOM);
prot&=~PROT_DYNAREC;
prot|=PROT_WRITE;
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot);
memprot[i>>16][i&0xffff] = prot; // need to use atomic exchange?
}
}
pthread_mutex_unlock(&mutex_prot);
}
int isprotectedDB(uintptr_t addr, size_t size)
{
dynarec_log(LOG_DEBUG, "isprotectedDB %p -> %p => ", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
if(end>=(1LL<<(20+16)))
end = (1LL<<(20+16))-1LL;
if(end<idx) { // memory addresses higher than 48bits are not tracked
dynarec_log(LOG_DEBUG, "00\n");
return 0;
}
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t prot = memprot[i>>16][i&0xffff];
if((prot&PROT_WRITE)) {
dynarec_log(LOG_DEBUG, "0\n");
return 0;
}
}
dynarec_log(LOG_DEBUG, "1\n");
return 1;
}
#endif
void updateProtection(uintptr_t addr, size_t size, uint32_t prot)
{
dynarec_log(LOG_DEBUG, "updateProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
int ret;
uintptr_t last = idx<<MEMPROT_SHIFT;
uint8_t oldprot = 0xff;
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
if(end>=(1LL<<(20+16)))
end = (1LL<<(20+16))-1;
if(end<idx) // memory addresses higher than 48bits are not tracked
return;
pthread_mutex_lock(&mutex_prot);
for (uintptr_t i=idx; i<=end; ++i) {
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
khint_t k = kh_put(memprot, memprot, key, &ret);
if(ret) {
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
kh_value(memprot, k) = m;
}
const uintptr_t start = i&(MEMPROT_SIZE-1);
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
uint8_t* block = kh_value(memprot, k);
for(uintptr_t ii = start; ii<=finish; ++ii) {
uint32_t dyn = block[ii]&PROT_DYNAREC;
if(dyn && (prot&PROT_WRITE)) { // need to remove the write protection from this block
if(oldprot!=prot) {
if(oldprot!=0xff)
mprotect((void*)last, (i<<MEMPROT_SHIFT)-last, oldprot&~PROT_CUSTOM); // need to optimize
last = i<<MEMPROT_SHIFT;
oldprot = prot;
}
} else if(prot!=0xff) {
mprotect((void*)last, (i<<MEMPROT_SHIFT)-last, oldprot&~PROT_CUSTOM); // need to optimize
last = i << MEMPROT_SHIFT;
oldprot = 0xff;
for (uintptr_t i=(idx>>16); i<=(end>>16); ++i)
if(memprot[i]==memprot_default) {
uint8_t* newblock = calloc(1<<16, sizeof(uint8_t));
#if 0 //def ARM64 //disabled for now, not usefull with the mutex
if (arm64_lock_storeifref(&memprot[i], newblock, memprot_default) != newblock) {
free(newblock);
}
block[ii] = prot|dyn|PROT_ALLOC;
#else
memprot[i] = newblock;
#endif
}
i+=finish-start; // +1 from the "for" loop
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t dyn=(memprot[i>>16][i&0xffff]&PROT_DYNAREC);
if(dyn && (prot&PROT_WRITE)) // need to remove the write protection from this block
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
memprot[i>>16][i&0xffff] = prot|dyn;
}
if(oldprot!=0xff)
mprotect((void*)last, (end<<MEMPROT_SHIFT)-last, oldprot&~PROT_CUSTOM); // need to optimize
pthread_mutex_unlock(&mutex_prot);
}
void setProtection(uintptr_t addr, size_t size, uint32_t prot)
{
dynarec_log(LOG_DEBUG, "setProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
int ret;
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
if(end>=(1LL<<(20+16)))
end = (1LL<<(20+16))-1;
if(end<idx) // memory addresses higher than 48bits are not tracked
return;
pthread_mutex_lock(&mutex_prot);
for (uintptr_t i=idx; i<=end; ++i) {
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
khint_t k = kh_put(memprot, memprot, key, &ret);
if(ret) {
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
kh_value(memprot, k) = m;
for (uintptr_t i=(idx>>16); i<=(end>>16); ++i)
if(memprot[i]==memprot_default) {
uint8_t* newblock = calloc(MEMPROT_SIZE, sizeof(uint8_t));
#if 0 //def ARM64 //disabled for now, not usefull with the mutex
if (arm64_lock_storeifref(&memprot[i], newblock, memprot_default) != newblock) {
free(newblock);
}
#else
memprot[i] = newblock;
#endif
}
const uintptr_t start = i&(MEMPROT_SIZE-1);
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
memset(kh_value(memprot, k)+start, prot|PROT_ALLOC, finish-start+1);
i+=finish-start; // +1 from the "for" loop
}
for (uintptr_t i=idx; i<=end; ++i)
memprot[i>>16][i&0xffff] = prot;
pthread_mutex_unlock(&mutex_prot);
}
@@ -834,18 +897,26 @@ void allocProtection(uintptr_t addr, size_t size, uint32_t prot)
dynarec_log(LOG_DEBUG, "allocProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
int ret;
if(end>=(1LL<<(20+16)))
end = (1LL<<(20+16))-1;
if(end<idx) // memory addresses higher than 48bits are not tracked
return;
pthread_mutex_lock(&mutex_prot);
for (uintptr_t i=idx; i<=end; ++i) {
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
khint_t k = kh_put(memprot, memprot, key, &ret);
if(ret) {
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
kh_value(memprot, k) = m;
for (uintptr_t i=(idx>>16); i<=(end>>16); ++i)
if(memprot[i]==memprot_default) {
uint8_t* newblock = calloc(1<<16, sizeof(uint8_t));
#if 0 //def ARM64 //disabled for now, not usefull with the mutex
if (arm64_lock_storeifref(&memprot[i], newblock, memprot_default) != newblock) {
free(newblock);
}
#else
memprot[i] = newblock;
#endif
}
for (uintptr_t i=idx; i<=end; ++i) {
const uintptr_t start = i&(MEMPROT_SIZE-1);
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
uint8_t* block = kh_value(memprot, k);
uint8_t* block = memprot[i>>16];
for(uintptr_t ii = start; ii<=finish; ++ii) {
if(!block[ii])
block[ii] = prot;
@@ -868,7 +939,7 @@ void loadProtectionFromMap()
uintptr_t s, e;
if(sscanf(buf, "%lx-%lx %c%c%c", &s, &e, &r, &w, &x)==5) {
int prot = ((r=='r')?PROT_READ:0)|((w=='w')?PROT_WRITE:0)|((x=='x')?PROT_EXEC:0);
allocProtection(s, e-s, prot);
allocProtection(s, e-s, prot|PROT_ALLOC);
}
}
fclose(f);
@@ -876,8 +947,9 @@ void loadProtectionFromMap()
static int blockempty(uint8_t* mem)
{
for (int i=0; i<(MEMPROT_SIZE); ++i)
if(mem[i])
uint32_t *p4 = (uint32_t*)mem;
for (int i=0; i<(MEMPROT_SIZE)/4; ++i, ++p4)
if(*p4)
return 0;
return 1;
}
@@ -887,19 +959,35 @@ void freeProtection(uintptr_t addr, size_t size)
dynarec_log(LOG_DEBUG, "freeProtection %p:%p\n", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
if(end>=(1LL<<(20+16)))
end = (1LL<<(20+16))-1;
if(end<idx) // memory addresses higher than 48bits are not tracked
return;
pthread_mutex_lock(&mutex_prot);
for (uintptr_t i=idx; i<=end; ++i) {
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
khint_t k = kh_get(memprot, memprot, key);
if(k!=kh_end(memprot)) {
const uint32_t key = (i>>16);
if(memprot[key]!=memprot_default) {
const uintptr_t start = i&(MEMPROT_SIZE-1);
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
uint8_t *block = kh_value(memprot, k);
uint8_t *block = memprot[key];
memset(block+start, 0, finish-start+1);
if(blockempty(block)) {
free(block);
kh_del(memprot, memprot, k);
#if 0 //def ARM64 //disabled for now, not usefull with the mutex
if (blockempty(block)) {
block = (void*)arm64_lock_xchg(&memprot[key], (uintptr_t)memprot_default);
if(!blockempty(block)) {
block = (void*)arm64_lock_xchg(&memprot[key], (uintptr_t)block);
for (int i = 0; i < 0x10000; ++i) {
memprot[key][i] |= block[i];
}
}
if (block != memprot_default) free(block);
}
#else
if(blockempty(block)) {
memprot[key] = memprot_default;
free(block);
}
#endif
i+=finish-start; // +1 from the "for" loop
}
}
@@ -908,65 +996,52 @@ void freeProtection(uintptr_t addr, size_t size)
uint32_t getProtection(uintptr_t addr)
{
const uint32_t key = (addr>>32)&0xffffffff;
pthread_mutex_lock(&mutex_prot);
khint_t k = kh_get(memprot, memprot, key);
if(k==kh_end(memprot)) {
pthread_mutex_unlock(&mutex_prot);
if(addr>=(1LL<<48))
return 0;
}
const uintptr_t idx = ((addr&0xffffffff)>>MEMPROT_SHIFT);
uint32_t ret = kh_val(memprot, k)[idx];
pthread_mutex_unlock(&mutex_prot);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
uint32_t ret = memprot[idx>>16][idx&0xffff];
return ret;
}
#define LOWEST (void*)0x20000
int availableBlock(uint8_t* p, size_t n)
{
for (size_t i=0; i<n; ++i, ++p)
if(*p)
return 0;
return 1;
}
static uintptr_t nextFree(uintptr_t addr)
{
if(addr>=(1LL<<48))
return 0;
do {
const uint32_t key = (addr>>32)&0xffffffff;
khint_t k = kh_get(memprot, memprot, key);
if(k==kh_end(memprot)) {
uintptr_t idx = (addr>>MEMPROT_SHIFT);
if(memprot[idx>>16]==memprot_default) {
return addr;
}
uint8_t *block = kh_value(memprot, k);
for (uintptr_t i=(addr&0xffffffffLL)>>MEMPROT_SHIFT; i<MEMPROT_SIZE; ++i)
if(!block[i]) {
return (addr&~0xffffffffLL)+(i<<MEMPROT_SHIFT);
for (uintptr_t i=(idx&0xffff); i<MEMPROT_SIZE; ++i)
if(!memprot[idx>>16][i]) {
return ((idx>>16)<<(16+12))+(i<<MEMPROT_SHIFT);
}
addr += 0x100000000LL;
addr &= ~0xffffffffLL;
addr += (1LL<<(16+12));
addr &= ~((1LL<<(16+12)-1LL));
} while(1);
}
static uintptr_t maxFree(uintptr_t addr, uintptr_t sz)
{
if(addr>=(1LL<<48))
return 0;
uintptr_t mfree = 0;
do {
const uint32_t key = (addr>>32)&0xffffffff;
khint_t k = kh_get(memprot, memprot, key);
if(k==kh_end(memprot)) {
mfree+=0x100000000LL;
uintptr_t idx = (addr>>MEMPROT_SHIFT);
if(memprot[idx>>16]==memprot_default) {
mfree+=(1LL<<(16+12));
if(mfree>sz) {
return addr;
}
} else {
uint8_t *block = kh_value(memprot, k);
for (uintptr_t i=(addr&0xffffffffLL)>>MEMPROT_SHIFT; i<MEMPROT_SIZE; ++i)
if(!block[i]) {
mfree+=1<<MEMPROT_SHIFT;
for (uintptr_t i=(idx&0xffffLL); i<MEMPROT_SIZE; ++i)
if(!memprot[idx>>16][i]) {
mfree+=(1<<MEMPROT_SHIFT);
} else
return mfree;
}
addr += 0x100000000LL;
addr &= ~0xffffffffLL;
addr += (1LL<<(12+16));
addr &= ~((1LL<<(12+16))-1LL);
} while(1);
}
void* find32bitBlock(size_t size)
@@ -977,12 +1052,10 @@ void* find47bitBlock(size_t size)
{
// slow iterative search... Would need something better one day
uintptr_t addr = 0x100000000LL;
pthread_mutex_lock(&mutex_prot);
do {
addr = nextFree(addr);
uintptr_t sz = maxFree(addr, size);
if(sz>=size) {
pthread_mutex_unlock(&mutex_prot);
return (void*)addr;
}
addr += sz;
@@ -993,12 +1066,10 @@ void* find47bitBlock(size_t size)
addr = nextFree(addr);
uintptr_t sz = maxFree(addr, size);
if(sz>=size) {
pthread_mutex_unlock(&mutex_prot);
return (void*)addr;
}
addr += sz;
} while(addr<0x100000000LL);
pthread_mutex_unlock(&mutex_prot);
printf_log(LOG_NONE, "Warning: cannot find a 0x%zx block in 47bits address space\n", size);
return NULL;
}
@@ -1006,17 +1077,14 @@ void* find47bitBlockNearHint(void* hint, size_t size)
{
// slow iterative search... Would need something better one day
uintptr_t addr = (uintptr_t)hint;
pthread_mutex_lock(&mutex_prot);
do {
addr = nextFree(addr);
uintptr_t sz = maxFree(addr, size);
if(sz>=size) {
pthread_mutex_unlock(&mutex_prot);
return (void*)addr;
}
addr += sz;
} while(addr<0x800000000000LL);
pthread_mutex_unlock(&mutex_prot);
printf_log(LOG_NONE, "Warning: cannot find a 0x%zx block in 32bits address space\n", size);
return NULL;
}
@@ -1024,17 +1092,14 @@ void* findBlockNearHint(void* hint, size_t size)
{
// slow iterative search... Would need something better one day
uintptr_t addr = (uintptr_t)hint;
pthread_mutex_lock(&mutex_prot);
do {
addr = nextFree(addr);
uintptr_t sz = maxFree(addr, size);
if(sz>=size) {
pthread_mutex_unlock(&mutex_prot);
return (void*)addr;
}
addr += sz;
} while(addr<0x100000000LL);
pthread_mutex_unlock(&mutex_prot);
printf_log(LOG_NONE, "Warning: cannot find a 0x%zx block in 32bits address space\n", size);
return NULL;
}
@@ -1051,9 +1116,6 @@ int unlockCustommemMutex()
}
GO(mutex_blocks, 0)
GO(mutex_prot, 1)
#ifdef DYNAREC
GO(mutex_mmap, 2)
#endif
#undef GO
return ret;
}
@@ -1066,9 +1128,6 @@ void relockCustommemMutex(int locks)
GO(mutex_blocks, 0)
GO(mutex_prot, 1)
#ifdef DYNAREC
GO(mutex_mmap, 2)
#endif
#undef GO
}
@@ -1079,9 +1138,6 @@ static void init_mutexes(void)
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&mutex_blocks, &attr);
pthread_mutex_init(&mutex_prot, &attr);
#ifdef DYNAREC
pthread_mutex_init(&mutex_mmap, &attr);
#endif
pthread_mutexattr_destroy(&attr);
}
@@ -1098,7 +1154,9 @@ void init_custommem_helper(box64context_t* ctx)
if(inited) // already initialized
return;
inited = 1;
memprot = kh_init(memprot);
memset(memprot_default, 0, sizeof(memprot_default));
for(int i=0; i<(1<<20); ++i)
memprot[i] = memprot_default;
init_mutexes();
#ifdef DYNAREC
#ifdef ARM64
@@ -1146,6 +1204,7 @@ void fini_custommem_helper(box64context_t *ctx)
dblist_oversized = NULL;
}
mmapsize = 0;
mmapcap = 0;
dynarec_log(LOG_DEBUG, "Free dynamic Dynarecblocks\n");
for (uintptr_t idx3=0; idx3<=0xffff; ++idx3)
if(dynmap123[idx3]) {
@@ -1160,7 +1219,6 @@ void fini_custommem_helper(box64context_t *ctx)
}
free(mmaplist);
pthread_mutex_destroy(&mutex_mmap);
for (int i3=0; i3<(1<<DYNAMAP_SHIFT); ++i3)
if(box64_jmptbl3[i3]!=box64_jmptbldefault2) {
for (int i2=0; i2<(1<<DYNAMAP_SHIFT); ++i2)
@@ -1176,10 +1234,11 @@ void fini_custommem_helper(box64context_t *ctx)
}
#endif
uint8_t* m;
kh_foreach_value(memprot, m,
free(m);
);
kh_destroy(memprot, memprot);
for(int i=0; i<(1<<20); ++i) {
m = memprot[i];
if(m!=memprot_default)
free(m);
}
for(int i=0; i<n_blocks; ++i)
#ifdef USE_MMAP
+3
View File
@@ -351,6 +351,9 @@
#define PST_L1_STREAM_U12(Rn, imm12) EMIT(PRFM_imm(((imm12)>>3)&0xfff, Rn, 0b01001))
// Data Memory Barrier
#define DMB_gen(CRm) (0b1101010100<<22 | 0b011<<16 | 0b0011<<12 | (CRm)<<8 | 1<<7 | 0b01<<5 | 0b11111)
#define DMB_ISH() EMIT(DMB_gen(0b1011))
// BR and Branches
#define BR_gen(Z, op, A, M, Rn, Rm) (0b1101011<<25 | (Z)<<24 | (op)<<21 | 0b11111<<16 | (A)<<11 | (M)<<10 | (Rn)<<5 | (Rm))
+22 -3
View File
@@ -21,6 +21,7 @@
arm64_lock_read_b:
dmb ish
// address is x0, return is x0
ldaxrb w0, [x0]
ret
@@ -29,9 +30,11 @@ arm64_lock_write_b:
// address is x0, value is x1, return is x0
mov x2, x0
stlxrb w0, w1, [x2]
dmb ish
ret
arm64_lock_read_h:
dmb ish
// address is x0, return is x0
ldaxrh w0, [x0]
ret
@@ -40,9 +43,11 @@ arm64_lock_write_h:
// address is x0, value is x1, return is x0
mov x2, x0
stlxrh w0, w1, [x2]
dmb ish
ret
arm64_lock_read_d:
dmb ish
// address is x0, return is x0
ldaxr w0, [x0]
ret
@@ -51,9 +56,11 @@ arm64_lock_write_d:
// address is x0, value is w1, return is x0
mov x2, x0
stlxr w0, w1, [x2]
dmb ish
ret
arm64_lock_read_dd:
dmb ish
// address is x0, return is x0
ldaxr x0, [x0]
ret
@@ -62,9 +69,11 @@ arm64_lock_write_dd:
// address is x0, value is x1, return is x0
mov x2, x0
stlxr w0, x1, [x2]
dmb ish
ret
arm64_lock_read_dq:
dmb ish
// address is r2, return is r0, r1
ldaxp x4, x3, [x2]
str x4, [x0]
@@ -76,37 +85,47 @@ arm64_lock_write_dq:
// r0 needs to be aligned
stlxp w3, x0, x1, [x2]
mov w0, w3
dmb ish
ret
arm64_lock_xchg:
dmb ish
arm64_lock_xchg_0:
// address is x0, value is x1, return old value in x0
ldaxr x2, [x0]
stlxr w3, x1, [x0]
cbnz w3, arm64_lock_xchg
cbnz w3, arm64_lock_xchg_0
dmb ish
mov x0, x2
ret
arm64_lock_storeifnull:
dmb ish
arm64_lock_storeifnull_0:
// address is x0, value is x1, x1 store to x0 only if [x0] is 0. return new [x0] value (so x1 or old value)
ldaxr x2, [x0]
cbnz x2, arm64_lock_storeifnull_exit
mov x2, x1
stlxr w3, x2, [x0]
cbnz w3, arm64_lock_storeifnull
cbnz w3, arm64_lock_storeifnull_0
arm64_lock_storeifnull_exit:
dmb ish
mov x0, x2
ret
arm64_lock_storeifref:
dmb ish
arm64_lock_storeifref_0:
// address is x0, value is x1, x1 store to x0 only if [x0] is x3. return new [x0] value (so x1 or old value)
ldaxr x3, [x0]
cmp x2, x3
bne arm64_lock_storeifref_exit
stlxr w4, x1, [x0]
cbnz w4, arm64_lock_storeifref
cbnz w4, arm64_lock_storeifref_0
mov x0, x1
ret
arm64_lock_storeifref_exit:
dmb ish
mov x0, x3
ret
+3 -2
View File
@@ -18,9 +18,10 @@ arm64_next:
stp x12, x13, [sp, (8 * 4)]
stp x14, x15, [sp, (8 * 6)]
stp x16, x17, [sp, (8 * 8)]
str x18, [sp, (8 * 10)]
stp x18, x27, [sp, (8 * 10)] // also save x27(rip) to allow change in LinkNext
mov x2, lr // "from" is in lr, so put in x2
add x3, sp, 8*11 // x3 is address to change rip
// call the function
bl LinkNext
// preserve return value
@@ -31,7 +32,7 @@ arm64_next:
ldp x12, x13, [sp, (8 * 4)]
ldp x14, x15, [sp, (8 * 6)]
ldp x16, x17, [sp, (8 * 8)]
ldr x18, [sp, (8 * 10)]
ldp x18, x27, [sp, (8 * 10)]
add sp, sp, (8 * 12)
// return offset is jump address
br x3
+169 -58
View File
@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <setjmp.h>
#include "debug.h"
#include "box64context.h"
@@ -47,6 +48,8 @@ dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct)
dynablocklist_t* ret = (dynablocklist_t*)calloc(1, sizeof(dynablocklist_t));
ret->text = text;
ret->textsz = textsz;
ret->minstart = text;
ret->maxend = text+textsz-1;
if(direct && textsz) {
ret->direct = (dynablock_t**)calloc(textsz, sizeof(dynablock_t*));
if(!ret->direct) {printf_log(LOG_NONE, "Warning, fail to create direct block for dynablock @%p\n", (void*)text);}
@@ -55,12 +58,14 @@ dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct)
return ret;
}
void FreeDynablock(dynablock_t* db)
void FreeDynablock(dynablock_t* db, int need_lock)
{
if(db) {
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x64=%p:%p parent=%p, father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size, db->parent, db->father, db->sons_size, db->gone);
if(db->gone)
return; // already in the process of deletion!
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x64=%p:%p parent=%p, father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size-1, db->parent, db->father, db->sons_size, db->gone);
if(need_lock)
pthread_mutex_lock(&my_context->mutex_dyndump);
db->done = 0;
db->gone = 1;
// remove from direct if there
@@ -76,16 +81,18 @@ void FreeDynablock(dynablock_t* db)
// remove and free the sons
for (int i=0; i<db->sons_size; ++i) {
dynablock_t *son = (dynablock_t*)arm64_lock_xchg(&db->sons[i], 0);
FreeDynablock(son);
FreeDynablock(son, 0);
}
// only the father free the DynarecMap
if(!db->father) {
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->block, db->size);
FreeDynarecMap(db, (uintptr_t)db->block, db->size);
free(db->sons);
free(db->instsize);
}
free(db->sons);
free(db->instsize);
free(db);
if(need_lock)
pthread_mutex_unlock(&my_context->mutex_dyndump);
}
}
@@ -99,7 +106,7 @@ void FreeDynablockList(dynablocklist_t** dynablocks)
if((*dynablocks)->direct) {
for (int i=0; i<(*dynablocks)->textsz; ++i) {
if((*dynablocks)->direct[i] && !(*dynablocks)->direct[i]->father)
FreeDynablock((*dynablocks)->direct[i]);
FreeDynablock((*dynablocks)->direct[i], 1);
}
free((*dynablocks)->direct);
}
@@ -116,7 +123,8 @@ void MarkDynablock(dynablock_t* db)
db = db->father; // mark only father
if(db->need_test)
return; // already done
db->need_test = 1; // test only blocks that can be marked (and so deleted)
dynarec_log(LOG_DEBUG, "MarkDynablock %p with %d son(s) %p-%p\n", db, db->sons_size, db->x64_addr, db->x64_addr+db->x64_size-1);
db->need_test = 1;
setJumpTableDefault64(db->x64_addr);
for(int i=0; i<db->sons_size; ++i)
setJumpTableDefault64(db->sons[i]->x64_addr);
@@ -145,24 +153,19 @@ int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2, uintp
void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
{
// Mark will try to find *any* blocks that intersect the range to mark
if(!dynablocks)
return;
if(!dynablocks->direct)
return;
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz -1;
uintptr_t start = addr;
uintptr_t end = addr+size-1;
if(start<startdb)
start = startdb;
if(end>enddb)
end = enddb;
uintptr_t sizedb = dynablocks->textsz;
dynablock_t *db;
if(end>startdb && start<enddb)
for(uintptr_t i = start; i<end; ++i)
if((db=dynablocks->direct[i-startdb]))
if(IntervalIntersects((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr+db->x64_size-1, addr, addr+size+1))
MarkDynablock(db);
dynarec_log(LOG_DEBUG, "MarkDirectDynablock %p-%p .. startdb=%p, sizedb=%p\n", (void*)addr, (void*)addr+size-1, (void*)startdb, (void*)sizedb);
for(uintptr_t i = 0; i<sizedb; ++i)
if((db=dynablocks->direct[i]))
if(IntervalIntersects((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr+db->x64_size-1, addr, addr+size+1))
MarkDynablock(db);
}
int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
@@ -198,7 +201,7 @@ int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t si
}
// purge the list
kh_foreach_value(blocks, db,
FreeDynablock(db);
FreeDynablock(db, 1);
);
kh_destroy(dynablocks, blocks);
// check emptyness
@@ -213,13 +216,14 @@ void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t s
{
if(!dynablocks)
return;
dynarec_log(LOG_DEBUG, "MarkRangeDynablock %p-%p\n", (void*)addr, (void*)addr+size-1);
if(dynablocks->direct) {
uintptr_t new_addr = addr - dynablocks->maxsz;
uintptr_t new_size = size + dynablocks->maxsz;
MarkDirectDynablock(dynablocks, new_addr, new_size);
uintptr_t new_addr = dynablocks->minstart;
uintptr_t new_size = dynablocks->maxend - new_addr + 1;
MarkDirectDynablock(dynablocks, addr, size);
// the blocks check before
for(unsigned idx=(new_addr)>>DYNAMAP_SHIFT; idx<(addr>>DYNAMAP_SHIFT); ++idx)
MarkDirectDynablock(getDB(idx), new_addr, new_size);
MarkDirectDynablock(getDB(idx), addr, size);
}
}
@@ -267,6 +271,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
if (!*created)
return block;
pthread_mutex_lock(&my_context->mutex_dyndump);
if(!dynablocks->direct) {
dynablock_t** p = (dynablock_t**)calloc(dynablocks->textsz, sizeof(dynablock_t*));
if(arm64_lock_storeifnull(&dynablocks->direct, p)!=p)
@@ -281,20 +286,30 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
dynablock_t* tmp = (dynablock_t*)arm64_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], block);
if(tmp != block) {
// a block appeard!
pthread_mutex_unlock(&my_context->mutex_dyndump);
free(block);
*created = 0;
return tmp;
}
*created = 1;
pthread_mutex_lock(&my_context->mutex_dyndump);
return block;
}
//TODO: move this to dynrec_arm.c and track allocated structure to avoid memory leak
static __thread struct __jmp_buf_tag dynarec_jmpbuf;
void cancelFillBlock()
{
longjmp(&dynarec_jmpbuf, 1);
}
/*
return NULL if block is not found / cannot be created.
Don't create if create==0
*/
static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current)
static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current, int need_lock)
{
// try the quickest way first: get parent of current and check if ok!
dynablocklist_t *dynablocks = NULL;
@@ -323,15 +338,19 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
if(!created)
return block; // existing block...
#if 0
if(box64_dynarec_dump)
pthread_mutex_lock(&my_context->mutex_dyndump);
#endif
// fill the block
block->x64_addr = (void*)addr;
pthread_mutex_lock(&my_context->mutex_dyndump);
if(need_lock)
pthread_mutex_lock(&my_context->mutex_dyndump);
if(sigsetjmp(&dynarec_jmpbuf, 1)) {
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr);
if(need_lock)
pthread_mutex_unlock(&my_context->mutex_dyndump);
return NULL;
}
void* ret = FillBlock64(block, filladdr);
pthread_mutex_unlock(&my_context->mutex_dyndump);
if(need_lock)
pthread_mutex_unlock(&my_context->mutex_dyndump);
if(!ret) {
dynarec_log(LOG_DEBUG, "Fillblock of block %p for %p returned an error\n", block, (void*)addr);
void* old = (void*)arm64_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], 0, block);
@@ -342,24 +361,20 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
free(block);
block = NULL;
}
#if 0
if(box64_dynarec_dump)
pthread_mutex_unlock(&my_context->mutex_dyndump);
#endif
// check size
if(block && block->x64_size) {
if(dynablocks->minstart>addr)
dynablocks->minstart = addr;
int blocksz = block->x64_size;
if(dynablocks->maxsz<blocksz) {
dynablocks->maxsz = blocksz;
for(unsigned idx=(addr>>DYNAMAP_SHIFT)+1; idx<=((addr+blocksz)>>DYNAMAP_SHIFT); ++idx) {
if(dynablocks->maxend<addr+blocksz) {
dynablocks->maxend = addr+blocksz;
for(unsigned idx=(addr>>DYNAMAP_SHIFT)+1; idx<=((addr+blocksz-1)>>DYNAMAP_SHIFT); ++idx) {
dynablocklist_t* dblist;
if((dblist = getDB(idx)))
if(dblist->maxsz<blocksz)
dblist->maxsz = blocksz;
if(dblist->minstart>addr)
dblist->minstart = addr;
}
}
lockDB();
protectDBnolock((uintptr_t)block->x64_addr, block->x64_size);
// fill-in jumptable
addJumpTableIfDefault64(block->x64_addr, block->block);
for(int i=0; i<block->sons_size; ++i) {
@@ -367,39 +382,133 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
block->sons[i]->done = 1;
}
block->done = 1;
unlockDB();
}
dynarec_log(LOG_DEBUG, " --- DynaRec Block %s @%p:%p (%p, 0x%x bytes, with %d son(s))\n", created?"created":"recycled", (void*)addr, (void*)(addr+((block)?block->x64_size:0)), (block)?block->block:0, (block)?block->size:0, (block)?block->sons_size:0);
dynarec_log(LOG_DEBUG, "%04d| --- DynaRec Block %s @%p:%p (%p, 0x%x bytes, with %d son(s))\n", GetTID(), created?"created":"recycled", (void*)addr, (void*)(addr+((block)?block->x64_size:1)-1), (block)?block->block:0, (block)?block->size:0, (block)?block->sons_size:0);
return block;
}
#define MAX_HOTPAGE 64
#define HOTPAGE_STEP 64
static int volatile hotpage_count[MAX_HOTPAGE] = {0};
static uintptr_t volatile hotpage[MAX_HOTPAGE] = {0};
static uintptr_t volatile hotpage_size[MAX_HOTPAGE] = {0};
static volatile int hotpages = 0;
int IsInHotPage(uintptr_t addr) {
if(!hotpages)
return 0;
for(int i=0; i<MAX_HOTPAGE; ++i) {
if((hotpage_count[i]>0) && (addr>=hotpage[i]) && (addr<hotpage[i]+0x1000*(hotpage_size[i]+1))) {
--hotpage_count[i];
if(!hotpage_count[i]) {
--hotpages;
hotpage_size[i] = 0;
dynarec_log(LOG_DEBUG, "End of Hotpage %p\n", (void*)hotpage[i]);
}
return 1;
}
}
return 0;
}
int AreaInHotPage(uintptr_t start, uintptr_t end) {
if(!hotpages)
return 0;
for(int i=0; i<MAX_HOTPAGE; ++i) {
if(hotpage_count[i]>0)
if(IntervalIntersects(start, end, hotpage[i], hotpage[i]+0x1000*(hotpage_size[i]+1)-1)) {
--hotpage_count[i];
if(!hotpage_count[i]) {
--hotpages;
hotpage_size[i] = 0;
dynarec_log(LOG_DEBUG, "End of Hotpage %p\n", (void*)hotpage[i]);
}
return 1;
}
}
return 0;
}
void AddHotPage(uintptr_t addr) {
addr&=~0xfff;
// look for same address
for(int i=0; i<MAX_HOTPAGE; ++i) {
if(addr>=hotpage[i] && addr<hotpage[i]+0x1000*(hotpage_size[i]+1)) {
if(!hotpage_count[i])
++hotpages;
hotpage_count[i] = HOTPAGE_STEP;
return;
}
if(addr==hotpage[i]+0x1000*(hotpage_size[i]+1)) {
++hotpage_size[i];
hotpage_count[i] = HOTPAGE_STEP;
return;
}
if(addr+0x1000==hotpage[i]) {
++hotpage_size[i];
hotpage[i] = addr;
hotpage_count[i] = HOTPAGE_STEP;
return;
}
}
// look for empty spot / minium
int mincnt = hotpage_count[0];
int minidx = 0;
for(int i=1; i<MAX_HOTPAGE; ++i)
if(hotpage_count[i]<mincnt) {
mincnt = hotpage_count[i];
minidx = i;
}
if(hotpage_count[minidx]) {
dynarec_log(LOG_NONE, "Warning, not enough Hotpage, replacing %p(%p/%d) with %p\n", (void*)hotpage[minidx], (void*)(0x1000*(hotpage_size[minidx]+1)), hotpage_count[minidx], (void*)addr);
hotpage_size[minidx] = 0;
} else
++hotpages;
hotpage[minidx] = addr;
hotpage_count[minidx] = HOTPAGE_STEP;
}
dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, dynablock_t** current)
{
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current);
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current, 1);
if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) {
if(pthread_mutex_trylock(&my_context->mutex_dyndump)) {
dynarec_log(LOG_DEBUG, "mutex_dyndump not available when trying to validate block %p from %p:%p (hash:%X) with %d son(s) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, db->hash, db->sons_size, (void*)addr);
return NULL;
}
dynablock_t *father = db->father?db->father:db;
if(AreaInHotPage((uintptr_t)father->x64_addr, (uintptr_t)father->x64_addr + father->x64_size - 1)) {
dynarec_log(LOG_DEBUG, "Not running block %p from %p:%p with %d son(s) for %p because it's in a hotpage\n", father, father->x64_addr, father->x64_addr+father->x64_size-1, father->sons_size, (void*)addr);
pthread_mutex_unlock(&my_context->mutex_dyndump);
return NULL;
}
uint32_t hash = X31_hash_code(father->x64_addr, father->x64_size);
if(hash!=father->hash) {
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size, hash, father->hash, father->sons_size, (void*)addr);
father->done = 0; // invalidating the block
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size-1, hash, father->hash, father->sons_size, (void*)addr);
// no more current if it gets invalidated too
if(*current && father->x64_addr>=(*current)->x64_addr && (father->x64_addr+father->x64_size)<(*current)->x64_addr)
if(*current && IntervalIntersects(
(uintptr_t)father->x64_addr,
(uintptr_t)father->x64_addr+father->x64_size-1,
(uintptr_t)(*current)->x64_addr,
(uintptr_t)(*current)->x64_addr+(*current)->x64_size-1))
*current = NULL;
// Free father, it's now invalid!
FreeDynablock(father);
FreeDynablock(father, 0);
// start again... (will create a new block)
db = internalDBGetBlock(emu, addr, addr, create, *current);
db = internalDBGetBlock(emu, addr, addr, create, *current, 0);
} else {
father->need_test = 0;
lockDB();
protectDBnolock((uintptr_t)father->x64_addr, father->x64_size);
dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size-1, father->hash, father->sons_size, (void*)addr);
protectDB((uintptr_t)father->x64_addr, father->x64_size);
// fill back jumptable
addJumpTableIfDefault64(father->x64_addr, father->block);
for(int i=0; i<father->sons_size; ++i)
addJumpTableIfDefault64(father->sons[i]->x64_addr, father->sons[i]->block);
unlockDB();
}
pthread_mutex_unlock(&my_context->mutex_dyndump);
}
return db;
}
@@ -408,26 +517,28 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr)
{
dynarec_log(LOG_DEBUG, "Creating AlternateBlock at %p for %p\n", (void*)addr, (void*)filladdr);
int create = 1;
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 1);
if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) {
if(pthread_mutex_trylock(&my_context->mutex_dyndump))
return NULL;
dynablock_t *father = db->father?db->father:db;
uint32_t hash = X31_hash_code(father->x64_addr, father->x64_size);
if(hash!=father->hash) {
father->done = 0; // invalidating the block
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size, hash, father->hash, father->sons_size, (void*)addr);
// Free father, it's now invalid!
FreeDynablock(father);
FreeDynablock(father, 0);
// start again... (will create a new block)
db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 0);
} else {
father->need_test = 0;
lockDB();
protectDBnolock((uintptr_t)father->x64_addr, father->x64_size);
protectDB((uintptr_t)father->x64_addr, father->x64_size);
// fill back jumptable
addJumpTableIfDefault64(father->x64_addr, father->block);
for(int i=0; i<father->sons_size; ++i)
addJumpTableIfDefault64(father->sons[i]->x64_addr, father->sons[i]->block);
unlockDB();
}
pthread_mutex_unlock(&my_context->mutex_dyndump);
}
return db;
}
+2 -1
View File
@@ -29,7 +29,8 @@ typedef struct dynablock_s {
typedef struct dynablocklist_s {
uintptr_t text;
int textsz;
int maxsz; // maxblock size (for this block or previous block)
uintptr_t maxend; // max address end for anyblock on this blocklist
uintptr_t minstart; // min start address for block overlapping this blocklist
dynablock_t** direct; // direct mapping (waste of space, so the array is created at first write)
} dynablocklist_t;
+28 -11
View File
@@ -19,6 +19,7 @@
#ifdef DYNAREC
#include "dynablock.h"
#include "dynablock_private.h"
#include "bridge.h"
#endif
#ifdef DYNAREC
@@ -32,7 +33,7 @@ void arm64_epilog_fast() EXPORTDYN;
#ifdef DYNAREC
uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr);
void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2)
void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
{
#ifdef HAVE_TRACE
if(!addr) {
@@ -45,10 +46,22 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2)
dynablock_t* block = DBGetBlock(emu, addr, 1, &current);
if(!block) {
// no block, let link table as is...
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
printf_log(LOG_NONE, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL);
//tableupdate(arm64_epilog, addr, table);
return arm64_epilog;
if(hasAlternate((void*)addr)) {
printf_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr);
addr = (uintptr_t)getAlternate((void*)addr); // set new address
R_RIP = addr; // but also new RIP!
*x3 = addr; // and the RIP in x27 register
printf_log(LOG_INFO, " -> %p\n", (void*)addr);
block = DBGetBlock(emu, addr, 1, &current);
}
if(!block) {
#ifdef HAVE_TRACE
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL);
#endif
//tableupdate(arm64_epilog, addr, table);
return arm64_epilog;
}
}
if(!block->done) {
// not finished yet... leave linker
@@ -101,16 +114,17 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
PushExit(emu);
R_RIP = addr;
emu->df = d_none;
dynablock_t* block = NULL;
dynablock_t* current = NULL;
dynablock_t* block = DBGetBlock(emu, R_RIP, 1, &current);
current = block;
while(!emu->quit) {
block = DBGetBlock(emu, R_RIP, 1, &current);
current = block;
if(!block || !block->block || !block->done) {
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
dynarec_log(LOG_DEBUG, "%04d|Calling Interpretor @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
Run(emu, 1);
block = DBGetBlock(emu, R_RIP, 1, &current);
current = block;
} else {
dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x64 instructions (father=%p) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize ,block->father, emu);
CHECK_FLAGS(emu);
@@ -118,6 +132,7 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
#ifdef ARM64
arm64_prolog(emu, block->block);
#endif
block = NULL;
}
if(emu->fork) {
int forktype = emu->fork;
@@ -181,22 +196,24 @@ int DynaRun(x64emu_t* emu)
return Run(emu, 0);
#ifdef DYNAREC
else {
dynablock_t* block = NULL;
dynablock_t* current = NULL;
dynablock_t* block = DBGetBlock(emu, R_RIP, 1, &current);;
current = block;
while(!emu->quit) {
block = DBGetBlock(emu, R_RIP, 1, &current);
current = block;
if(!block || !block->block || !block->done) {
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
dynarec_log(LOG_DEBUG, "%04d|Running Interpretor @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
Run(emu, 1);
block = DBGetBlock(emu, R_RIP, 1, &current);
current = block;
} else {
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x64 insts (father=%p) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize, block->father, emu);
// block is here, let's run it!
#ifdef ARM64
arm64_prolog(emu, block->block);
#endif
block = NULL;
}
if(emu->fork) {
int forktype = emu->fork;
+66 -20
View File
@@ -58,13 +58,15 @@ void printf_x64_instruction(zydis_dec_t* dec, instruction_x64_t* inst, const cha
}
void add_next(dynarec_arm_t *dyn, uintptr_t addr) {
if(!box64_dynarec_bigblock)
return;
for(int i=0; i<dyn->next_sz; ++i)
if(dyn->next[i]==addr)
return;
if(dyn->next_sz == dyn->next_cap) {
dyn->next_cap += 16;
dyn->next = (uintptr_t*)realloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
}
for(int i=0; i<dyn->next_sz; ++i)
if(dyn->next[i]==addr)
return;
dyn->next[dyn->next_sz++] = addr;
}
uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr) {
@@ -333,28 +335,64 @@ uintptr_t arm_pass1(dynarec_arm_t* dyn, uintptr_t addr);
uintptr_t arm_pass2(dynarec_arm_t* dyn, uintptr_t addr);
uintptr_t arm_pass3(dynarec_arm_t* dyn, uintptr_t addr);
__thread void* current_helper = NULL;
void CancelBlock64()
{
dynarec_arm_t* helper = (dynarec_arm_t*)current_helper;
current_helper = NULL;
if(!helper)
return;
free(helper->next);
free(helper->insts);
free(helper->table64);
free(helper->sons_x64);
free(helper->sons_arm);
if(helper->dynablock && helper->dynablock->block)
FreeDynarecMap(helper->dynablock, (uintptr_t)helper->dynablock->block, helper->dynablock->size);
}
void* FillBlock64(dynablock_t* block, uintptr_t addr) {
if(IsInHotPage(addr)) {
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock on hotpage for %p\n", (void*)addr);
return NULL;
}
if(addr>=box64_nodynarec_start && addr<box64_nodynarec_end) {
block->done = 1;
return (void*)block;
}
// protect the 1st page
protectDB(addr, 1);
// init the helper
dynarec_arm_t helper = {0};
current_helper = &helper;
helper.dynablock = block;
helper.start = addr;
uintptr_t start = addr;
helper.cap = 64; // needs epilog handling
helper.insts = (instruction_arm64_t*)calloc(helper.cap, sizeof(instruction_arm64_t));
// pass 0, addresses, x86 jump addresses, overall size of the block
uintptr_t end = arm_pass0(&helper, addr);
// no need for next anymore
free(helper.next);
helper.next_sz = helper.next_cap = 0;
helper.next = NULL;
// basic checks
if(!helper.size) {
dynarec_log(LOG_DEBUG, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
block->done = 1;
dynarec_log(LOG_INFO, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
CancelBlock64();
return (void*)block;
}
helper.cap = helper.size+3; // needs epilog handling
helper.insts = (instruction_arm64_t*)calloc(helper.cap, sizeof(instruction_arm64_t));
// already protect the block and compute hash signature
protectDB(addr, end-addr); //end is 1byte after actual end
if(!isprotectedDB(addr, 1)) {
dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr);
CancelBlock64();
return NULL;
}
// protect the block of it goes over the 1st page
if((addr&~0xfff)!=(end&~0xfff)) // need to protect some other pages too
protectDB(addr, end-addr); //end is 1byte after actual end
// compute hash signature
uint32_t hash = X31_hash_code((void*)addr, end-addr);
// pass 1, addresses, x64 jump addresses, flags
arm_pass1(&helper, addr);
// calculate barriers
for(int i=0; i<helper.size; ++i)
if(helper.insts[i].x64.jmp) {
@@ -373,6 +411,8 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
helper.insts[i].x64.jmp_insts = k;
}
}
// pass 1, flags
arm_pass1(&helper, addr);
for(int i=0; i<helper.size; ++i)
if(helper.insts[i].x64.set_flags && !helper.insts[i].x64.need_flags) {
helper.insts[i].x64.need_flags = needed_flags(&helper, i+1, helper.insts[i].x64.set_flags, 0);
@@ -386,10 +426,8 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
size_t sz = helper.arm_size + helper.table64size*sizeof(uint64_t);
void* p = (void*)AllocDynarecMap(block, sz);
if(p==NULL) {
dynarec_log(LOG_DEBUG, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
free(helper.insts);
free(helper.next);
free(helper.table64);
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
CancelBlock64();
return NULL;
}
helper.block = p;
@@ -443,8 +481,9 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
}
// ok, free the helper now
free(helper.insts);
free(helper.next);
helper.insts = NULL;
free(helper.table64);
helper.table64 = NULL;
block->size = sz;
block->isize = helper.size;
block->block = p;
@@ -453,13 +492,17 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
block->x64_size = end-start;
block->hash = X31_hash_code(block->x64_addr, block->x64_size);
// Check if something changed, to abbort if it as
if(block->hash != hash) {
if((block->hash != hash)) {
dynarec_log(LOG_INFO, "Warning, a block changed while beeing processed hash(%p:%ld)=%x/%x\n", block->x64_addr, block->x64_size, block->hash, hash);
free(helper.sons_x64);
free(helper.sons_arm);
FreeDynarecMap(block, (uintptr_t)p, sz);
CancelBlock64();
return NULL;
} // fill sons if any
if(!isprotectedDB(addr, end-addr)) {
dynarec_log(LOG_INFO, "Warning, block unprotected while beeing processed %p:%ld, cancelling\n", block->x64_addr, block->x64_size);
CancelBlock64();
return NULL;
//protectDB(addr, end-addr);
}
dynablock_t** sons = NULL;
int sons_size = 0;
if(helper.sons_size) {
@@ -488,7 +531,10 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
free(sons);
}
free(helper.sons_x64);
helper.sons_x64 = NULL;
free(helper.sons_arm);
helper.sons_arm = NULL;
current_helper = NULL;
//block->done = 1;
return (void*)block;
}
+44 -44
View File
@@ -639,17 +639,15 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
BARRIER(2); \
JUMP(addr+i8);\
GETFLAGS; \
if(dyn->insts) { \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
Bcond(NO, i32); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
Bcond(YES, i32); \
} \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
Bcond(NO, i32); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
Bcond(YES, i32); \
}
GOCOND(0x70, "J", "ib");
@@ -846,6 +844,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
BFIx(gb1, x1, gb2*8, 8);
BFIx(eb1, x4, eb2*8, 8);
} else {
DMB_ISH();
GETGB(x4);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
MARKLOCK;
@@ -854,6 +853,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
// do the swap 14 -> strb(ed), 1 -> gd
STLXRB(x3, x4, ed);
CBNZx_MARKLOCK(x3);
DMB_ISH();
BFIx(gb1, x1, gb2*8, 8);
}
break;
@@ -869,6 +869,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
GETGD;
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
DMB_ISH();
TSTx_mask(ed, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
MARKLOCK;
@@ -880,6 +881,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
LDRxw_U12(x1, ed, 0);
STRxw_U12(gd, ed, 0);
MARK2;
DMB_ISH();
MOVxw_REG(gd, x1);
}
break;
@@ -953,6 +955,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = wback;
}
} else {
if(box64_dynarec_strongmem &&
(dyn->insts[ninst].x64.barrier || !ninst || box64_dynarec_strongmem>1 || (ninst && dyn->insts[ninst-1].x64.barrier))) {
DMB_ISH();
}
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, 0, 0);
LDRB_U12(x4, wback, fixedaddress);
ed = x4;
@@ -963,9 +969,13 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("MOV Gd, Ed");
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
if(MODREG) {
MOVxw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
} else { // mem <= reg
} else {
if(box64_dynarec_strongmem &&
(dyn->insts[ninst].x64.barrier || !ninst || box64_dynarec_strongmem>1 || (ninst && dyn->insts[ninst-1].x64.barrier))) {
DMB_ISH();
}
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
LDRxw_U12(gd, ed, fixedaddress);
}
@@ -1970,17 +1980,15 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
#define GO(Z) \
BARRIER(2); \
JUMP(addr+i8); \
if(dyn->insts) { \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
if(Z) {CBNZx(xRCX, i32);} else {CBZx(xRCX, i32);}; \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
if(Z) {CBZx(xRCX, i32);} else {CBNZx(xRCX, i32);}; \
} \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
if(Z) {CBNZx(xRCX, i32);} else {CBZx(xRCX, i32);}; \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
if(Z) {CBZx(xRCX, i32);} else {CBNZx(xRCX, i32);}; \
}
case 0xE0:
INST_NAME("LOOPNZ");
@@ -2019,12 +2027,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
printf_log(LOG_INFO, "Warning, CALL to 0x0 at %p (%p)\n", (void*)addr, (void*)(addr-1));
#endif
}
#if STEP == 0
if(isNativeCall(dyn, addr+i32, NULL, NULL))
tmp = 3;
else
tmp = 0;
#elif STEP < 2
#if STEP < 2
if(isNativeCall(dyn, addr+i32, &dyn->insts[ninst].natcall, &dyn->insts[ninst].retn))
tmp = dyn->insts[ninst].pass2choice = 3;
else
@@ -2042,7 +2045,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall-1)), dyn->insts[ninst].retn);
// calling a native function
sse_purge07cache(dyn, ninst, x3);
if(box64_log<2 && dyn->insts && (tmp=isSimpleWrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2)))) {
if(box64_log<2 && dyn->insts[ninst].natcall && (tmp=isSimpleWrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2)))) {
//GETIP(ip+3+8+8); // read the 0xCC
call_n(dyn, ninst, *(void**)(dyn->insts[ninst].natcall+2+8), tmp);
POP1(xRIP); // pop the return address
@@ -2104,18 +2107,16 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
i32 = F8S;
}
JUMP(addr+i32);
if(dyn->insts) {
PASS2IF(dyn->insts[ninst].x64.jmp_insts==-1, 1) {
// out of the block
jump_to_next(dyn, addr+i32, 0, ninst);
PASS2IF(dyn->insts[ninst].x64.jmp_insts==-1, 1) {
// out of the block
jump_to_next(dyn, addr+i32, 0, ninst);
} else {
// inside the block
tmp = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size);
if(tmp==4) {
NOP;
} else {
// inside the block
tmp = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size);
if(tmp==4) {
NOP;
} else {
B(tmp);
}
B(tmp);
}
}
*need_epilog = 0;
@@ -2384,8 +2385,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 2: // CALL Ed
INST_NAME("CALL Ed");
PASS2IF(dyn->insts &&
((ninst && dyn->insts[ninst-1].x64.set_flags)
PASS2IF(((ninst && dyn->insts[ninst-1].x64.set_flags)
|| ((ninst>1) && dyn->insts[ninst-2].x64.set_flags)), 1)
{
READFLAGS(X_PEND); // that's suspicious
+10 -12
View File
@@ -992,18 +992,16 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
BARRIER(2); \
JUMP(addr+i32_);\
GETFLAGS; \
if(dyn->insts) { \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
Bcond(NO, i32); \
jump_to_next(dyn, addr+i32_, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
Bcond(YES, i32); \
} \
}
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
Bcond(NO, i32); \
jump_to_next(dyn, addr+i32_, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
Bcond(YES, i32); \
} \
GOCOND(0x80, "J", "Id");
#undef GO
+1 -2
View File
@@ -801,8 +801,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 2: // CALL Ed
INST_NAME("CALL Ed");
PASS2IF(dyn->insts &&
((ninst && dyn->insts[ninst-1].x64.set_flags)
PASS2IF(((ninst && dyn->insts[ninst-1].x64.set_flags)
|| ((ninst>1) && dyn->insts[ninst-2].x64.set_flags)), 1)
{
READFLAGS(X_PEND); // that's suspicious
+10 -10
View File
@@ -172,9 +172,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("SBB AX, Iw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
i16 = F16;
i16 = F16S;
UXTHw(x1, xRAX);
MOV32w(x2, i16);
MOVZw(x2, i16);
emit_sbb16(dyn, ninst, x1, x2, x3, x4);
BFIx(xRAX, x1, 0, 16);
break;
@@ -341,7 +341,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
MOVZw(x5, i16);
emit_add16(dyn, ninst, ed, x5, x2, x4);
EWBACK;
break;
@@ -350,7 +350,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
MOVZw(x5, i16);
emit_or16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
@@ -360,7 +360,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
MOVZw(x5, i16);
emit_adc16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
@@ -370,7 +370,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
MOVZw(x5, i16);
emit_sbb16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
@@ -379,7 +379,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
MOVZw(x5, i16);
emit_and16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
@@ -388,7 +388,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
MOVZw(x5, i16);
emit_sub16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
@@ -397,7 +397,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
MOVZw(x5, i16);
emit_xor16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
@@ -407,7 +407,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
if(i16) {
MOV32w(x2, i16);
MOVZw(x2, i16);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);
} else
emit_cmp16_0(dyn, ninst, x1, x3, x4);
+21 -1
View File
@@ -381,6 +381,22 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
SXTL_32(q0, q1); // 32bits->64bits
break;
case 0x39:
INST_NAME("PMINSD Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0);
GETGX(q0);
SMINQ_32(q0, q0, q1);
break;
case 0x3D:
INST_NAME("PMINSD Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0);
GETGX(q0);
SMAXQ_32(q0, q0, q1);
break;
case 0xDB:
INST_NAME("AESIMC Gx, Ex"); // AES-NI
nextop = F8;
@@ -532,7 +548,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(q0);
GETED(1);
u8 = F8;
VMOVQSfrom(q0, (u8&3), ed);
if(rex.w) {
VMOVQDfrom(q0, (u8&1), ed);
} else {
VMOVQSfrom(q0, (u8&3), ed);
}
break;
default:
+275 -14
View File
@@ -26,21 +26,29 @@
gd = ((nextop&0x38)>>3)+(rex.r<<3); \
a = sse_get_reg(dyn, ninst, x1, gd)
#define GETGM(a) \
gd = ((nextop&0x38)>>3); \
a = mmx_get_reg(dyn, ninst, x1, gd)
#define GETGm gd = ((nextop&0x38)>>3)
uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed;
uint8_t gd, ed, wback, wb;
int64_t fixedaddress;
int8_t i8;
uint8_t u8;
int32_t i32;
int64_t j64;
int v0, s0;
int64_t j64, i64;
int v0, v1, s0;
MAYUSE(i32);
MAYUSE(j64);
MAYUSE(v0);
MAYUSE(v1);
MAYUSE(s0);
// REX prefix before the 67 are ignored
@@ -83,11 +91,51 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0x6F:
INST_NAME("MOVQ Gm, Em");
nextop = F8;
GETGm;
if(MODREG) {
v1 = mmx_get_reg(dyn, ninst, x1, nextop&7); // no rex.b on MMX
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
VMOVeD(v0, 0, v1, 0);
} else {
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
VLDR64_U12(v0, ed, fixedaddress);
}
break;
case 0x7F:
INST_NAME("MOVQ Em, Gm");
nextop = F8;
GETGM(v0);
if(MODREG) {
v1 = mmx_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOV(v1, v0);
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
VSTR64_U12(v0, ed, fixedaddress);
}
break;
default:
DEFAULT;
}
break;
case 0x89:
INST_NAME("MOV Ed, Gd");
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), gd);
} else { // mem <= reg
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
STRxw_U12(gd, ed, fixedaddress);
}
break;
case 0x8D:
INST_NAME("LEA Gd, Ed");
nextop=F8;
@@ -103,20 +151,91 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0xC1:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ed, Ib");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
GETED32(1);
u8 = (F8)&(rex.w?0x3f:0x1f);
emit_rol32c(dyn, ninst, rex, ed, u8, x3, x4);
if(u8) { WBACK; }
break;
case 1:
INST_NAME("ROR Ed, Ib");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
GETED32(1);
u8 = (F8)&(rex.w?0x3f:0x1f);
emit_ror32c(dyn, ninst, rex, ed, u8, x3, x4);
if(u8) { WBACK; }
break;
case 2:
INST_NAME("RCL Ed, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
GETED32W(x4, x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(rex.w?((void*)rcl64):((void*)rcl32), ed, x4);
WBACK;
break;
case 3:
INST_NAME("RCR Ed, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
GETED32W(x4, x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(rex.w?((void*)rcr64):((void*)rcr32), ed, x4);
WBACK;
break;
case 4:
case 6:
INST_NAME("SHL Ed, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETED32(1);
u8 = (F8)&(rex.w?0x3f:0x1f);
emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4);
WBACK;
break;
case 5:
INST_NAME("SHR Ed, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETED32(1);
u8 = (F8)&(rex.w?0x3f:0x1f);
emit_shr32c(dyn, ninst, rex, ed, u8, x3, x4);
if(u8) {
WBACK;
}
break;
case 7:
INST_NAME("SAR Ed, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETED32(1);
u8 = (F8)&(rex.w?0x3f:0x1f);
emit_sar32c(dyn, ninst, rex, ed, u8, x3, x4);
if(u8) {
WBACK;
}
break;
}
break;
#define GO(NO, YES) \
BARRIER(2); \
JUMP(addr+i8);\
if(dyn->insts) { \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
Bcond(NO, i32); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
Bcond(YES, i32); \
} \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
Bcond(NO, i32); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
Bcond(YES, i32); \
}
case 0xE0:
INST_NAME("LOOPNZ (32bits)");
@@ -160,6 +279,148 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xE8:
return dynarec64_00(dyn, addr-1, ip, ninst, rex, rep, ok, need_epilog); // addr-1, to "put back" opcode)
case 0xF7:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
case 1:
INST_NAME("TEST Ed, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED32H(x1, 4);
i64 = F32S;
MOV64xw(x2, i64);
emit_test32(dyn, ninst, rex, ed, x2, x3, x4);
break;
case 2:
INST_NAME("NOT Ed");
GETED32(4);
MVNxw_REG(ed, ed);
WBACK;
break;
case 3:
INST_NAME("NEG Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED32(0);
emit_neg32(dyn, ninst, rex, ed, x3, x4);
WBACK;
break;
case 4:
INST_NAME("MUL EAX, Ed");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_DF(x2, rex.w?d_mul64:d_mul32);
GETED32(0);
if(rex.w) {
if(ed==xRDX) gd=x3; else gd=xRDX;
UMULH(gd, xRAX, ed);
MULx(xRAX, xRAX, ed);
if(gd!=xRDX) {MOVx_REG(xRDX, gd);}
} else {
UMULL(xRDX, xRAX, ed); //64 <- 32x32
MOVw_REG(xRAX, xRDX);
LSRx(xRDX, xRDX, 32);
}
UFLAG_RES(xRAX);
UFLAG_OP1(xRDX);
break;
case 5:
INST_NAME("IMUL EAX, Ed");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_DF(x2, rex.w?d_imul64:d_imul32);
GETED32(0);
if(rex.w) {
if(ed==xRDX) gd=x3; else gd=xRDX;
SMULH(gd, xRAX, ed);
MULx(xRAX, xRAX, ed);
if(gd!=xRDX) {MOVx_REG(xRDX, gd);}
} else {
SMULL(xRDX, xRAX, ed); //64 <- 32x32
MOVw_REG(xRAX, xRDX);
LSRx(xRDX, xRDX, 32);
}
UFLAG_RES(xRAX);
UFLAG_OP1(xRDX);
break;
case 6:
INST_NAME("DIV Ed");
SETFLAGS(X_ALL, SF_SET);
if(!rex.w) {
SET_DFNONE(x2);
GETED32(0);
MOVw_REG(x3, xRAX);
ORRx_REG_LSL(x3, x3, xRDX, 32);
if(MODREG) {
MOVw_REG(x4, ed);
ed = x4;
}
UDIVx(x2, x3, ed);
MSUBx(x4, x2, ed, xRAX);
MOVw_REG(xRAX, x2);
MOVw_REG(xRDX, x4);
} else {
if(ninst && dyn->insts
&& dyn->insts[ninst-1].x64.addr
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x31
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0xD2) {
SET_DFNONE(x2);
GETED32(0);
UDIVx(x2, xRAX, ed);
MSUBx(xRDX, x2, ed, xRAX);
MOVx_REG(xRAX, x2);
} else {
GETED32H(x1, 0); // get edd changed addr, so cannot be called 2 times for same op...
CBZxw_MARK(xRDX);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(div64, -1);
B_NEXT_nocond;
MARK;
UDIVx(x2, xRAX, ed);
MSUBx(xRDX, x2, ed, xRAX);
MOVx_REG(xRAX, x2);
SET_DFNONE(x2);
}
}
break;
case 7:
INST_NAME("IDIV Ed");
SETFLAGS(X_ALL, SF_SET);
if(!rex.w) {
SET_DFNONE(x2)
GETSED32w(0);
MOVw_REG(x3, xRAX);
ORRx_REG_LSL(x3, x3, xRDX, 32);
SDIVx(x2, x3, wb);
MSUBx(x4, x2, wb, x3);
MOVw_REG(xRAX, x2);
MOVw_REG(xRDX, x4);
} else {
if(ninst && dyn->insts
&& dyn->insts[ninst-1].x64.addr
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x48
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0x99) {
SET_DFNONE(x2)
GETED32(0);
SDIVx(x2, xRAX, ed);
MSUBx(xRDX, x2, ed, xRAX);
MOVx_REG(xRAX, x2);
} else {
GETED32H(x1, 0); // get edd changed addr, so cannot be called 2 times for same op...
CBZxw_MARK(xRDX);
MVNx_REG(x2, xRDX);
CBZxw_MARK(x2);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL((void*)idiv64, -1);
B_NEXT_nocond;
MARK;
SDIVx(x2, xRAX, ed);
MSUBx(xRDX, x2, ed, xRAX);
MOVx_REG(xRAX, x2);
SET_DFNONE(x2)
}
}
break;
}
break;
default:
DEFAULT;
}
+3 -3
View File
@@ -209,7 +209,7 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
if(c>1) {
LSRxw(s3, s1, c-1);
}
BFIw(xFlags, s3, 0, 1);
BFIw(xFlags, (c>1)?s3:s1, 0, 1);
}
LSRxw(s1, s1, c);
IFX(X_PEND) {
@@ -257,7 +257,7 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
if(c>1) {
ASRxw(s3, s1, c-1);
}
BFIw(xFlags, s3, 0, 1);
BFIw(xFlags, (c>1)?s3:s1, 0, 1);
}
ASRxw(s1, s1, c);
IFX(X_PEND) {
@@ -366,7 +366,7 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int3
if(c>1) {
LSRxw(s3, s1, c-1);
}
BFIw(xFlags, s3, 0, 1);
BFIw(xFlags, (c>1)?s3:s1, 0, 1);
}
LSRxw(s3, s1, c);
ORRxw_REG_LSL(s1, s3, s2, (rex.w?64:32)-c);
+26
View File
@@ -56,6 +56,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("LOCK ADD Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
DMB_ISH();
GETGB(x2);
if((nextop&0xC0)==0xC0) {
if(rex.rex) {
@@ -77,12 +78,14 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
STLXRB(x4, x1, wback);
CBNZx_MARKLOCK(x4);
}
DMB_ISH();
break;
case 0x01:
INST_NAME("LOCK ADD Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
if((nextop&0xC0)==0xC0) {
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_add32(dyn, ninst, rex, ed, gd, x3, x4);
@@ -94,6 +97,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
DMB_ISH();
break;
case 0x09:
@@ -101,6 +105,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_or32(dyn, ninst, rex, ed, gd, x3, x4);
@@ -112,6 +117,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
DMB_ISH();
break;
case 0x0F:
@@ -123,6 +129,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
@@ -163,6 +170,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UFLAG_IF {emit_cmp32(dyn, ninst, rex, xRAX, x1, x3, x4, x5);}
MOVxw_REG(xRAX, x1); // upper par of RAX will be erase on 32bits, no mater what
}
DMB_ISH();
break;
case 0xC1:
@@ -170,6 +178,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
MOVxw_REG(x1, ed);
@@ -201,6 +210,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
MOVxw_REG(gd, x1);
}
DMB_ISH();
break;
case 0xC7:
@@ -208,6 +218,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ZF, SF_SUBSET);
nextop = F8;
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, rex, 0, 0);
DMB_ISH();
MARKLOCK;
LDAXPxw(x2, x3, wback);
CMPSxw_REG(xRAX, x2);
@@ -223,6 +234,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVxw_REG(xRDX, x3);
MOV32w(x1, 0);
MARK3;
DMB_ISH();
BFIw(xFlags, x1, F_ZF, 1);
break;
@@ -236,6 +248,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_sub32(dyn, ninst, rex, ed, gd, x3, x4);
@@ -247,6 +260,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
DMB_ISH();
break;
case 0x66:
@@ -255,6 +269,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x81:
case 0x83:
nextop = F8;
DMB_ISH();
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {
@@ -448,6 +463,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
}
DMB_ISH();
break;
default:
DEFAULT;
@@ -456,6 +472,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x80:
nextop = F8;
DMB_ISH();
switch((nextop>>3)&7) {
case 0: //ADD
INST_NAME("ADD Eb, Ib");
@@ -614,10 +631,12 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
default:
DEFAULT;
}
DMB_ISH();
break;
case 0x81:
case 0x83:
nextop = F8;
DMB_ISH();
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {
@@ -794,6 +813,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
}
DMB_ISH();
break;
case 0x87:
@@ -807,6 +827,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVxw_REG(ed, x1);
} else {
GETGD;
DMB_ISH();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
TSTx_mask(ed, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
@@ -819,6 +840,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
LDRxw_U12(x1, ed, 0);
STRxw_U12(gd, ed, 0);
MARK2;
DMB_ISH();
MOVxw_REG(gd, x1);
}
break;
@@ -830,6 +852,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0: // INC Ed
INST_NAME("LOCK INC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
DMB_ISH();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_inc32(dyn, ninst, rex, ed, x3, x4);
@@ -852,10 +875,12 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
CBNZw_MARK(x3);
STRxw_U12(x1, wback, 0);
}
DMB_ISH();
break;
case 1: //DEC Ed
INST_NAME("LOCK DEC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
DMB_ISH();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_dec32(dyn, ninst, rex, ed, x3, x4);
@@ -878,6 +903,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
CBNZw_MARK(x3);
STRxw_U12(x1, wback, 0);
}
DMB_ISH();
break;
default:
DEFAULT;
+31 -11
View File
@@ -49,7 +49,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
uint8_t gd, ed;
uint8_t wback;
uint8_t u8;
uint64_t u64;
uint64_t u64, j64;
int v0, v1;
int q0;
int d0, d1;
@@ -214,9 +214,15 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(v1, 0);
// MINSD: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
#if 0
d0 = fpu_get_scratch(dyn);
FMINNMD(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
VMOVeD(v0, 0, d0, 0); // to not erase uper part
#else
FCMPD(v0, v1);
B_NEXT(cLS); //Less than or equal
VMOVeD(v0, 0, v1, 0); // to not erase uper part
#endif
break;
case 0x5E:
INST_NAME("DIVSD Gx, Ex");
@@ -234,9 +240,15 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(v1, 0);
// MAXSD: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
#if 0
d0 = fpu_get_scratch(dyn);
FMAXNMD(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
VMOVeD(v0, 0, d0, 0); // to not erase uper part
#else
FCMPD(v0, v1);
B_NEXT(cGE); //Greater than or equal
VMOVeD(v0, 0, v1, 0); // to not erase uper part
#endif
break;
case 0x70:
@@ -282,19 +294,15 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(v0);
GETEX(v1, 1);
u8 = F8;
if((u8&7)==6){
FCMPD(v1, v0);
} else {
FCMPD(v0, v1);
}
FCMPD(v0, v1);
switch(u8&7) {
case 0: CSETMx(x2, cEQ); CSELx(x2, xZR, x2, cVS); break; // Equal
case 1: CSETMx(x2, cMI); CSELx(x2, xZR, x2, cVS); break; // Less than
case 2: CSETMx(x2, cLE); CSELx(x2, xZR, x2, cVS); break; // Less or equal
case 0: CSETMx(x2, cEQ); break; // Equal
case 1: CSETMx(x2, cCC); break; // Less than
case 2: CSETMx(x2, cLS); break; // Less or equal
case 3: CSETMx(x2, cVS); break; // NaN
case 4: CSETMx(x2, cNE); break; // Not Equal
case 4: CSETMx(x2, cNE); break; // Not Equal or unordered
case 5: CSETMx(x2, cCS); break; // Greater or equal or unordered
case 6: CSETMx(x2, cLT); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
case 6: CSETMx(x2, cHI); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
case 7: CSETMx(x2, cVC); break; // not NaN
}
VMOVQDfrom(v0, 0, x2);
@@ -313,6 +321,18 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VFMLAQS(v0, v1, q0);
break;
case 0xE6:
INST_NAME("CVTPD2DQ Gx, Ex");
nextop = F8;
GETEX(v1, 0);
GETGX_empty(v0);
u8 = sse_setround(dyn, ninst, x1, x2, x3);
FRINTXD(v0, v1);
x87_restoreround(dyn, ninst, u8);
VFCVTNSQD(v0, v0); // convert double -> int64
SQXTN_32(v0, v0); // convert int64 -> int32 with saturation in lower part, RaZ high part
break;
case 0xF0:
INST_NAME("LDDQU Gx,Ex");
nextop = F8;
+18 -10
View File
@@ -259,9 +259,15 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(v0);
GETEX(v1, 0);
// MINSS: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
#if 0
d0 = fpu_get_scratch(dyn);
FMINNMS(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
VMOVeS(v0, 0, d0, 0); // to not erase uper part
#else
FCMPS(v0, v1);
B_NEXT(cLS); //Less than or equal
VMOVeS(v0, 0, v1, 0); // to not erase uper part
#endif
break;
case 0x5E:
INST_NAME("DIVSS Gx, Ex");
@@ -278,9 +284,15 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(v0);
GETEX(v1, 0);
// MAXSS: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
#if 0
d0 = fpu_get_scratch(dyn);
FMAXNMS(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
VMOVeS(v0, 0, d0, 0); // to not erase uper part
#else
FCMPS(v0, v1);
B_NEXT(cGE); //Greater than or equal
VMOVeS(v0, 0, v1, 0); // to not erase uper part
#endif
break;
case 0x6F:
@@ -384,19 +396,15 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(v0);
GETEX(v1, 1);
u8 = F8;
if((u8&7)==6){
FCMPS(v1, v0);
} else {
FCMPS(v0, v1);
}
FCMPS(v0, v1);
switch(u8&7) {
case 0: CSETMw(x2, cEQ); CSELw(x2, xZR, x2, cVS); break; // Equal
case 1: CSETMw(x2, cMI); CSELw(x2, xZR, x2, cVS); break; // Less than
case 2: CSETMw(x2, cLE); CSELw(x2, xZR, x2, cVS); break; // Less or equal
case 0: CSETMw(x2, cEQ); break; // Equal
case 1: CSETMw(x2, cCC); break; // Less than
case 2: CSETMw(x2, cLS); break; // Less or equal
case 3: CSETMw(x2, cVS); break; // NaN
case 4: CSETMw(x2, cNE); break; // Not Equal
case 4: CSETMw(x2, cNE); break; // Not Equal or unordered
case 5: CSETMw(x2, cCS); break; // Greater or equal or unordered
case 6: CSETMw(x2, cLT); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
case 6: CSETMw(x2, cHI); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
case 7: CSETMw(x2, cVC); break; // not NaN
}
VMOVQSfrom(v0, 0, x2);
+2 -1
View File
@@ -26,6 +26,7 @@
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "custommem.h"
#include "bridge.h"
void arm_fstp(x64emu_t* emu, void* p)
{
@@ -448,7 +449,7 @@ int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int
return 0;
if(PK(0)==0xff && PK(1)==0x25) { // "absolute" jump, maybe the GOT (well, RIP relative in fact)
uintptr_t a1 = addr + 6 + (PK32(2)); // need to add a check to see if the address is from the GOT !
addr = *(uintptr_t*)a1;
addr = (uintptr_t)getAlternate(*(void**)a1);
}
if(!addr || !getProtection(addr))
return 0;
+59 -24
View File
@@ -69,6 +69,24 @@
LDRSW_U12(x1, wback, fixedaddress); \
wb = ed = x1; \
}
#define GETED32(D) if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
addr = geted32(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
LDRxw_U12(x1, wback, fixedaddress); \
ed = x1; \
}
#define GETSED32w(D) if((nextop&0xC0)==0xC0) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
SXTWx(x1, ed); \
wb = x1; \
wback = 0; \
} else { \
addr = geted32(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, D); \
LDRSW_U12(x1, wback, fixedaddress); \
wb = ed = x1; \
}
//GETEDH can use hint for ed, and r1 or r2 for wback (depending on hint). wback is 0 if ed is xEAX..xEDI
#define GETEDH(hint, D) if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
@@ -78,8 +96,16 @@
LDRxw_U12(hint, wback, fixedaddress); \
ed = hint; \
}
#define GETED32H(hint, D) if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
addr = geted32(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
LDRxw_U12(hint, wback, fixedaddress); \
ed = hint; \
}
//GETEDW can use hint for wback and ret for ed. wback is 0 if ed is xEAX..xEDI
#define GETEDW(hint, ret, D) if(MODREG) { \
#define GETEDW(hint, ret, D) if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
MOVxw_REG(ret, ed); \
wback = 0; \
@@ -88,6 +114,15 @@
ed = ret; \
LDRxw_U12(ed, wback, fixedaddress); \
}
#define GETED32W(hint, ret, D) if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
MOVxw_REG(ret, ed); \
wback = 0; \
} else { \
addr = geted32(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
ed = ret; \
LDRxw_U12(ed, wback, fixedaddress); \
}
// Write back ed in wback (if wback not 0)
#define WBACK if(wback) {STRxw_U12(ed, wback, fixedaddress);}
// Write back ed in wback (if wback not 0)
@@ -277,18 +312,18 @@
// R0 will not be pushed/popd if ret is -2. Flags are not save/restored
#define CALL_S(F, ret) call_c(dyn, ninst, F, x7, ret, 0, 0)
#define MARK if(dyn->insts) {dyn->insts[ninst].mark = dyn->arm_size;}
#define GETMARK ((dyn->insts)?dyn->insts[ninst].mark:(dyn->arm_size+4))
#define MARK2 if(dyn->insts) {dyn->insts[ninst].mark2 = dyn->arm_size;}
#define GETMARK2 ((dyn->insts)?dyn->insts[ninst].mark2:(dyn->arm_size+4))
#define MARK3 if(dyn->insts) {dyn->insts[ninst].mark3 = dyn->arm_size;}
#define GETMARK3 ((dyn->insts)?dyn->insts[ninst].mark3:(dyn->arm_size+4))
#define MARKF if(dyn->insts) {dyn->insts[ninst].markf = dyn->arm_size;}
#define GETMARKF ((dyn->insts)?dyn->insts[ninst].markf:(dyn->arm_size+4))
#define MARKSEG if(dyn->insts) {dyn->insts[ninst].markseg = dyn->arm_size;}
#define GETMARKSEG ((dyn->insts)?dyn->insts[ninst].markseg:(dyn->arm_size+4))
#define MARKLOCK if(dyn->insts) {dyn->insts[ninst].marklock = dyn->arm_size;}
#define GETMARKLOCK ((dyn->insts)?dyn->insts[ninst].marklock:(dyn->arm_size+4))
#define MARK dyn->insts[ninst].mark = dyn->arm_size
#define GETMARK dyn->insts[ninst].mark
#define MARK2 dyn->insts[ninst].mark2 = dyn->arm_size
#define GETMARK2 dyn->insts[ninst].mark2
#define MARK3 dyn->insts[ninst].mark3 = dyn->arm_size
#define GETMARK3 dyn->insts[ninst].mark3
#define MARKF dyn->insts[ninst].markf = dyn->arm_size
#define GETMARKF dyn->insts[ninst].markf
#define MARKSEG dyn->insts[ninst].markseg = dyn->arm_size
#define GETMARKSEG dyn->insts[ninst].markseg
#define MARKLOCK dyn->insts[ninst].marklock = dyn->arm_size
#define GETMARKLOCK dyn->insts[ninst].marklock
// Branch to MARK if cond (use j64)
#define B_MARK(cond) \
@@ -395,11 +430,11 @@
j64 = GETMARKLOCK-(dyn->arm_size); \
CBNZx(reg, j64)
#define IFX(A) if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(A)))
#define IFX_PENDOR0 if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(X_PEND) || !dyn->insts[ninst].x64.need_flags))
#define IFXX(A) if(dyn->insts && (dyn->insts[ninst].x64.need_flags==(A)))
#define IFX2X(A, B) if(dyn->insts && (dyn->insts[ninst].x64.need_flags==(A) || dyn->insts[ninst].x64.need_flags==(B) || dyn->insts[ninst].x64.need_flags==((A)|(B))))
#define IFXN(A, B) if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(A) && !(dyn->insts[ninst].x64.need_flags&(B))))
#define IFX(A) if((dyn->insts[ninst].x64.need_flags&(A)))
#define IFX_PENDOR0 if((dyn->insts[ninst].x64.need_flags&(X_PEND) || !dyn->insts[ninst].x64.need_flags))
#define IFXX(A) if((dyn->insts[ninst].x64.need_flags==(A)))
#define IFX2X(A, B) if((dyn->insts[ninst].x64.need_flags==(A) || dyn->insts[ninst].x64.need_flags==(B) || dyn->insts[ninst].x64.need_flags==((A)|(B))))
#define IFXN(A, B) if((dyn->insts[ninst].x64.need_flags&(A) && !(dyn->insts[ninst].x64.need_flags&(B))))
// Generate FCOM with s1 and s2 scratch regs (the VCMP is already done)
#define FCOM(s1, s2, s3) \
@@ -554,12 +589,12 @@
#ifndef BARRIER_NEXT
#define BARRIER_NEXT(A)
#endif
#define UFLAG_OP1(A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op1));}
#define UFLAG_OP2(A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op2));}
#define UFLAG_OP12(A1, A2) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STRxw_U12(A1, xEmu, offsetof(x64emu_t, op1));STRxw_U12(A2, 0, offsetof(x64emu_t, op2));}
#define UFLAG_RES(A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, res));}
#define UFLAG_DF(r, A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {SET_DF(r, A)}
#define UFLAG_IF if(dyn->insts && dyn->insts[ninst].x64.need_flags)
#define UFLAG_OP1(A) if(dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op1));}
#define UFLAG_OP2(A) if(dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op2));}
#define UFLAG_OP12(A1, A2) if(dyn->insts[ninst].x64.need_flags) {STRxw_U12(A1, xEmu, offsetof(x64emu_t, op1));STRxw_U12(A2, 0, offsetof(x64emu_t, op2));}
#define UFLAG_RES(A) if(dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, res));}
#define UFLAG_DF(r, A) if(dyn->insts[ninst].x64.need_flags) {SET_DF(r, A)}
#define UFLAG_IF if(dyn->insts[ninst].x64.need_flags)
#ifndef DEFAULT
#define DEFAULT *ok = -1; BARRIER(2)
#endif
+8 -4
View File
@@ -3,6 +3,7 @@
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include "debug.h"
#include "box64context.h"
@@ -14,6 +15,7 @@
#include "box64stack.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynablock.h"
#include "dynarec_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
@@ -45,7 +47,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
INIT;
while(ok) {
ip = addr;
if(dyn->insts && (dyn->insts[ninst].x64.barrier==1)) {
if((dyn->insts[ninst].x64.barrier==1)) {
dyn->last_ip = 0;
NEW_BARRIER_INST;
}
@@ -90,17 +92,18 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
INST_EPILOG;
if(dyn->insts && dyn->insts[ninst+1].x64.barrier) {
if(dyn->insts[ninst+1].x64.barrier) {
fpu_purgecache(dyn, ninst, x1, x2, x3);
if(dyn->insts[ninst+1].x64.barrier!=2) {
dyn->state_flags = 0;
dyn->dfnone = 0;
}
}
if(!ok && !need_epilog && dyn->insts && (addr < (dyn->start+dyn->isize))) {
if(!ok && !need_epilog && (addr < (dyn->start+dyn->isize))) {
ok = 1;
}
if(!ok && !need_epilog && !dyn->insts && getProtection(addr+3)&~PROT_CUSTOM)
#if STEP == 0
if(!ok && !need_epilog && box64_dynarec_bigblock && getProtection(addr+3)&~PROT_CUSTOM && !IsInHotPage(addr+3))
if(*(uint32_t*)addr!=0) { // check if need to continue (but is next 4 bytes are 0, stop)
uintptr_t next = get_closest_next(dyn, addr);
if(next && (
@@ -113,6 +116,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
dynarec_log(LOG_DEBUG, "Cannot extend block %p -> %p (%02X %02X %02X %02X %02X %02X %02X %02x)\n", (void*)addr, (void*)next, PK(0), PK(1), PK(2), PK(3), PK(4), PK(5), PK(6), PK(7));
}
}
#endif
if(ok<0) {ok = 0; need_epilog=1;}
++ninst;
#if STEP == 0
+10 -2
View File
@@ -5,8 +5,16 @@
#define SETFLAGS(A, B)
#define READFLAGS(A)
#define EMIT(A)
#define JUMP(A) add_next(dyn, (uintptr_t)A)
#define NEW_INST ++dyn->size
#define JUMP(A) add_next(dyn, (uintptr_t)A); dyn->insts[ninst].x64.jmp = A
#define BARRIER(A) dyn->insts[ninst].x64.barrier = A
#define BARRIER_NEXT(A) if(ninst<dyn->size) dyn->insts[ninst+1].x64.barrier = A
#define NEW_INST \
if(dyn->size+3>=dyn->cap) { \
dyn->insts = (instruction_arm64_t*)realloc(dyn->insts, sizeof(instruction_arm64_t)*dyn->cap*2); \
memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_arm64_t)*dyn->cap); \
dyn->cap *= 2; \
} \
++dyn->size
#define INST_EPILOG
#define INST_NAME(name)
#define DEFAULT \
+1 -4
View File
@@ -6,12 +6,9 @@
#define EMIT(A)
#define READFLAGS(A) dyn->insts[ninst].x64.use_flags = A
#define SETFLAGS(A,B) {dyn->insts[ninst].x64.set_flags = A; dyn->insts[ninst].x64.state_flags = B;}
#define JUMP(A) dyn->insts[ninst].x64.jmp = A
#define BARRIER(A) dyn->insts[ninst].x64.barrier = A
#define BARRIER_NEXT(A) if(ninst<dyn->size) dyn->insts[ninst+1].x64.barrier = A
#define NEW_INST \
dyn->insts[ninst].x64.addr = ip; \
if(ninst) dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr;
#define INST_EPILOG
#define INST_EPILOG
#define INST_NAME(name)
+3 -1
View File
@@ -4,8 +4,9 @@
#include "dynarec_private.h"
typedef struct x64emu_s x64emu_t;
typedef struct dynablock_s dynablock_t;
typedef struct instruction_arm_s {
typedef struct instruction_arm64_s {
instruction_x64_t x64;
uintptr_t address; // (start) address of the arm emited instruction
uintptr_t epilog; // epilog of current instruction (can be start of next, of barrier stuff)
@@ -50,6 +51,7 @@ typedef struct dynarec_arm_s {
uintptr_t* sons_x64; // the x64 address of potential dynablock sons
void** sons_arm; // the arm address of potential dynablock sons
int sons_size; // number of potential dynablock sons
dynablock_t* dynablock;
} dynarec_arm_t;
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
+23 -15
View File
@@ -185,7 +185,7 @@ int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
uintptr_t end = head->multiblock_offs[j] + head->multiblock_size[j];
start &= ~balign;
if( (head->e_type == ET_DYN) ||
(((bstart>=start) && (bstart<=end)) || ((bend>=start) && (bend<=end)) || ((bstart<start) && (bend>end))))
(((bstart>=start) && (bstart<=end+0x1000)) || ((bend>=start) && (bend<=end)) || ((bstart<start) && (bend>end))))
{
// merge
ok = 1;
@@ -289,12 +289,20 @@ int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head)
if(head->PHEntries[i].p_type == PT_LOAD) {
Elf64_Phdr * e = &head->PHEntries[i];
char* dest = (char*)e->p_paddr + head->delta;
printf_log(LOG_DEBUG, "Loading block #%zu @%p (0x%lx/0x%lx)\n", i, dest, e->p_filesz, e->p_memsz);
fseeko64(f, e->p_offset, SEEK_SET);
if(e->p_filesz) {
if(fread(dest, e->p_filesz, 1, f)!=1) {
printf_log(LOG_NONE, "Fail to read PT_LOAD part #%zu (size=%ld)\n", i, e->p_filesz);
return 1;
printf_log(LOG_DEBUG, "MMap block #%zu @%p offset=%p (0x%lx/0x%lx)\n", i, dest, (void*)e->p_offset, e->p_filesz, e->p_memsz);
void* p = (void*)-1;
if(e->p_memsz==e->p_filesz && !(e->p_align&0xfff)) {
printf_log(LOG_DEBUG, "MMap block #%zu @%p offset=%p (0x%zx/0x%zx, flags:0x%x)\n", i, dest, (void*)e->p_offset, e->p_filesz, e->p_memsz, e->p_flags);
mmap(dest, e->p_filesz, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fileno(f), e->p_offset);
}
if(p!=dest) {
printf_log(LOG_DEBUG, "Loading block #%zu %p (0x%zx/0x%zx)\n",i, dest, e->p_filesz, e->p_memsz);
fseeko64(f, e->p_offset, SEEK_SET);
if(e->p_filesz) {
if(fread(dest, e->p_filesz, 1, f)!=1) {
printf_log(LOG_NONE, "Fail to read PT_LOAD part #%zu (size=%zd)\n", i, e->p_filesz);
return 1;
}
}
}
#ifdef DYNAREC
@@ -440,12 +448,12 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
case R_X86_64_GLOB_DAT:
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername) && FindR64COPYRel(my_context->elfs[0], symname, &globoffs, &globp, version, vername)) {
// set global offs / size for the symbol
offs = sym->st_value + head->delta;
offs = sym->st_value;
end = offs + sym->st_size;
if(sym->st_size) {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) size=%ld on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname);
//memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
AddWeakSymbol(GetGlobalData(maplib), symname, offs, sym->st_size, version, vername);
if(sym->st_size && offs) {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) size=%ld on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)(offs + head->delta), (void*)globoffs, sym->st_size, symname);
memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
AddWeakSymbol(GetGlobalData(maplib), symname, offs + head->delta, sym->st_size, version, vername);
} else {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) null sized on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, symname);
}
@@ -570,7 +578,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
uint64_t *p = (uint64_t*)(rela[i].r_offset + head->delta);
uintptr_t offs = 0;
uintptr_t end = 0;
elfheader_t* h_tls = head;
elfheader_t* h_tls = NULL;//head;
int version = head->VerSym?((Elf64_Half*)((uintptr_t)head->VerSym+head->delta))[ELF64_R_SYM(rela[i].r_info)]:-1;
if(version!=-1) version &=0x7fff;
const char* vername = GetSymbolVersion(head, version);
@@ -740,7 +748,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
offs = getElfIndex(my_context, h_tls);
}
if(p) {
printf_dump(LOG_NEVER, "Apply %s %s @%p with sym=%s (%p -> %p)\n", "R_X86_64_DTPMOD64", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs);
printf_dump(LOG_NEVER, "Apply %s %s @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", "R_X86_64_DTPMOD64", p, symname, *(void**)p, (void*)offs);
*p = offs;
} else {
printf_log(LOG_NONE, "Warning, Symbol %s or Elf not found, but R_X86_64_DTPMOD64 Slot Offset is NULL \n", symname);
@@ -756,7 +764,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
}
// return -1;
} else {
if(h_tls)
if(!symname || symname[0]=='\0' || bind==STB_LOCAL)
offs = sym->st_value;
if(p) {
int64_t tlsoffset = offs; // it's not an offset in elf memory
+1
View File
@@ -31,6 +31,7 @@
#define GETEX_OFFS(D, O) opex=GetExO(emu, rex, nextop, D, O)
#define GETGX opgx=GetGx(emu, rex, nextop)
#define GETEM(D) opem=GetEm(emu, rex, nextop, D)
#define GETEM32(D) opem=GetEm32O(emu, rex, nextop, D, 0)
#define GETGM opgm=GetGm(emu, rex, nextop)
#define ED oped
#define GD opgd
+1
View File
@@ -1526,6 +1526,7 @@ x64emurun:
fini:
printf_log(LOG_DEBUG, "End of X86 run (%p), RIP=%p, Stack=%p, unimp=%d, emu->fork=%d, emu->uc_link=%p, emu->quit=%d\n", emu, (void*)R_RIP, (void*)R_RSP, unimp, emu->fork, emu->uc_link, emu->quit);
if(unimp) {
R_RIP = emu->old_ip;
emu->quit = 1;
+34 -1
View File
@@ -430,6 +430,24 @@ int Run660F(x64emu_t *emu, rex_t rex)
GX->sq[i] = EX->sd[i];
break;
case 0x39: /* PMINSD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
if(GX->sd[i]>EX->sd[i])
GX->sd[i] = EX->sd[i];
break;
case 0x3A: /* PMAXSD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
if(GX->sd[i]<EX->sd[i])
GX->sd[i] = EX->sd[i];
break;
case 0xDB: /* AESIMC Gx, Ex */
nextop = F8;
GETEX(0);
@@ -647,7 +665,10 @@ int Run660F(x64emu_t *emu, rex_t rex)
GETED(1);
GETGX;
tmp8u = F8;
GX->ud[tmp8u&0x3] = ED->dword[0];
if(rex.w)
GX->q[tmp8u&0x1] = ED->q[0];
else
GX->ud[tmp8u&0x3] = ED->dword[0];
break;
case 0x40: /* DPPS Gx, Ex, Ib */
@@ -1132,6 +1153,18 @@ int Run660F(x64emu_t *emu, rex_t rex)
GX->ud[i] = (GX->ud[i]==EX->ud[i])?0xffffffff:0;
break;
case 0x7C: /* HADDPD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->d[0] += GX->d[1];
if(EX==GX) {
GX->d[1] = GX->d[0];
} else {
GX->d[1] = EX->d[0] + EX->d[1];
}
break;
case 0x7E: /* MOVD Ed, Gx */
nextop = F8;
GETED(0);
+14
View File
@@ -65,6 +65,20 @@ int Run670F(x64emu_t *emu, rex_t rex, int rep)
CLEAR_FLAG(F_OF); CLEAR_FLAG(F_AF); CLEAR_FLAG(F_SF);
break;
case 0x6F: /* MOVQ Gm, Em */
nextop = F8;
GETEM32(0);
GETGM;
GM->q = EM->q;
break;
case 0x7F: /* MOVQ Em, Gm */
nextop = F8;
GETEM32(0);
GETGM;
EM->q = GM->q;
break;
default:
return 1;
}
+16 -1
View File
@@ -32,14 +32,21 @@ int32_t EXPORT my___libc_start_main(x64emu_t* emu, int *(main) (int, char * *, c
{
(void)argc; (void)ubp_av; (void)fini; (void)rtld_fini; (void)stack_end;
// let's cheat and set all args...
if(init) {
Push64(emu, GetRBP(emu)); // set frame pointer
SetRBP(emu, GetRSP(emu)); // save RSP
SetRSP(emu, GetRSP(emu)&~0xFLL); // Align RSP
PushExit(emu);
SetRDX(emu, (uint64_t)my_context->envv);
SetRSI(emu, (uint64_t)my_context->argv);
SetRDI(emu, (uint64_t)my_context->argc);
R_RIP=(uint64_t)*init;
printf_log(LOG_DEBUG, "Calling init(%p) from __libc_start_main\n", *init);
DynaRun(emu);
if(emu->error) // any error, don't bother with more
return 0;
SetRSP(emu, GetRBP(emu)); // restore RSP
SetRBP(emu, Pop64(emu)); // restore RBP
emu->quit = 0;
}
printf_log(LOG_DEBUG, "Transfert to main(%d, %p, %p)=>%p from __libc_start_main\n", my_context->argc, my_context->argv, my_context->envv, main);
@@ -1276,6 +1283,14 @@ sse_regs_t* GetEx32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr
} else return (sse_regs_t*)GetECommon32O(emu, rex, m, delta, offset);
}
mmx87_regs_t* GetEm32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
{
uint8_t m = v&0xC7; // filter Ed
if(m>=0xC0) {
return &emu->mmx[(m&0x07)];
} else return (mmx87_regs_t*)GetECommon32O(emu, rex, m, delta, offset);
}
reg64_t* GetGd(x64emu_t *emu, rex_t rex, uint8_t v)
{
+1
View File
@@ -94,6 +94,7 @@ reg64_t* GetGd(x64emu_t *emu, rex_t rex, uint8_t v);
#define GetGw GetGd
reg64_t* GetGb(x64emu_t *emu, rex_t rex, uint8_t v);
mmx87_regs_t* GetGm(x64emu_t *emu, rex_t rex, uint8_t v);
mmx87_regs_t* GetEm32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
sse_regs_t* GetGx(x64emu_t *emu, rex_t rex, uint8_t v);
void UpdateFlags(x64emu_t *emu);
+3 -3
View File
@@ -218,10 +218,10 @@ int RunF20F(x64emu_t *emu, rex_t rex)
tmp8s = 0;
switch(tmp8u&7) {
case 0: tmp8s=(GX->d[0] == EX->d[0]); break;
case 1: tmp8s=isless(GX->d[0], EX->d[0]); break;
case 2: tmp8s=islessequal(GX->d[0], EX->d[0]); break;
case 1: tmp8s=isless(GX->d[0], EX->d[0]) && !(isnan(GX->d[0]) || isnan(EX->d[0])); break;
case 2: tmp8s=islessequal(GX->d[0], EX->d[0]) && !(isnan(GX->d[0]) || isnan(EX->d[0])); break;
case 3: tmp8s=isnan(GX->d[0]) || isnan(EX->d[0]); break;
case 4: tmp8s=(GX->d[0] != EX->d[0]); break;
case 4: tmp8s=isnan(GX->d[0]) || isnan(EX->d[0]) || (GX->d[0] != EX->d[0]); break;
case 5: tmp8s=isnan(GX->d[0]) || isnan(EX->d[0]) || isgreaterequal(GX->d[0], EX->d[0]); break;
case 6: tmp8s=isnan(GX->d[0]) || isnan(EX->d[0]) || isgreater(GX->d[0], EX->d[0]); break;
case 7: tmp8s=!isnan(GX->d[0]) && !isnan(EX->d[0]); break;
+3 -3
View File
@@ -318,10 +318,10 @@ int RunF30F(x64emu_t *emu, rex_t rex)
tmp8s = 0;
switch(tmp8u&7) {
case 0: tmp8s=(GX->f[0] == EX->f[0]); break;
case 1: tmp8s=isless(GX->f[0], EX->f[0]); break;
case 2: tmp8s=islessequal(GX->f[0], EX->f[0]); break;
case 1: tmp8s=isless(GX->f[0], EX->f[0]) && !(isnan(GX->f[0]) || isnan(EX->f[0])); break;
case 2: tmp8s=islessequal(GX->f[0], EX->f[0]) && !(isnan(GX->f[0]) || isnan(EX->f[0])); break;
case 3: tmp8s=isnan(GX->f[0]) || isnan(EX->f[0]); break;
case 4: tmp8s=(GX->f[0] != EX->f[0]); break;
case 4: tmp8s=isnan(GX->f[0]) || isnan(EX->f[0]) || (GX->f[0] != EX->f[0]); break;
case 5: tmp8s=isnan(GX->f[0]) || isnan(EX->f[0]) || isgreaterequal(GX->f[0], EX->f[0]); break;
case 6: tmp8s=isnan(GX->f[0]) || isnan(EX->f[0]) || isgreater(GX->f[0], EX->f[0]); break;
case 7: tmp8s=!isnan(GX->f[0]) && !isnan(EX->f[0]); break;
+2
View File
@@ -132,6 +132,8 @@ scwrap_t syscallwrap[] = {
{ 96, __NR_gettimeofday, 2},
{ 97, __NR_getrlimit, 2},
{ 101, __NR_ptrace, 4},
{ 118, __NR_getresuid, 3},
{ 120, __NR_getresgid, 3},
{ 125, __NR_capget, 2},
{ 126, __NR_capset, 2},
{ 127, __NR_rt_sigpending, 2},
+3
View File
@@ -153,6 +153,9 @@ int my_arch_prctl(x64emu_t *emu, int code, void* addr)
my_context->segtls[3].present = 1;
pthread_setspecific(my_context->segtls[3].key, (void*)my_context->segtls[3].base);
return 0;
case ARCH_GET_FS:
*(void**)addr = GetSegmentBase(emu->segs[_FS]);
return 0;
}
// other are unsupported
printf_log(LOG_INFO, "warning, call to unsupported arch_prctl(0x%x, %p)\n", code, addr);
+1 -3
View File
@@ -45,10 +45,8 @@ uint32_t getProtection(uintptr_t addr);
void loadProtectionFromMap();
#ifdef DYNAREC
void protectDB(uintptr_t addr, size_t size);
void protectDBnolock(uintptr_t addr, size_t size);
void unprotectDB(uintptr_t addr, size_t size);
void lockDB();
void unlockDB();
int isprotectedDB(uintptr_t addr, size_t size);
#endif
void* find32bitBlock(size_t size);
void* findBlockNearHint(void* hint, size_t size);
+3
View File
@@ -13,11 +13,14 @@ extern int box64_dynarec_dump;
extern int box64_dynarec_trace;
extern int box64_dynarec_forced;
extern uintptr_t box64_nodynarec_start, box64_nodynarec_end;
extern int box64_dynarec_bigblock;
extern int box64_dynarec_strongmem;
#ifdef ARM64
extern int arm64_asimd;
extern int arm64_aes;
extern int arm64_pmull;
extern int arm64_crc32;
extern int arm64_atomics;
#endif
#endif
extern int dlsym_error; // log dlsym error
+6 -1
View File
@@ -9,7 +9,7 @@ typedef struct kh_dynablocks_s kh_dynablocks_t;
uint32_t X31_hash_code(void* addr, int len);
dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct);
void FreeDynablockList(dynablocklist_t** dynablocks);
void FreeDynablock(dynablock_t* db);
void FreeDynablock(dynablock_t* db, int need_lock);
void MarkDynablock(dynablock_t* db);
//return 1 if Dynareblock is empty
int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
@@ -29,4 +29,9 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr)
// Create and Add an new dynablock in the list, handling direct/map
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* created);
// for use in signal handler
void cancelFillBlock();
int IsInHotPage(uintptr_t addr);
void AddHotPage(uintptr_t addr);
#endif //__DYNABLOCK_H_
+1
View File
@@ -4,6 +4,7 @@
typedef struct dynablock_s dynablock_t;
typedef struct x64emu_s x64emu_t;
void CancelBlock64();
void* FillBlock64(dynablock_t* block, uintptr_t addr);
#endif //__DYNAREC_ARM_H_
+3 -3
View File
@@ -2,11 +2,11 @@
#define _GLOBAL_SYMBOLS_H_
//GTK stuff
//void my_checkGlobalGdkDisplay();
//void my_setGlobalGThreadsInit();
void my_checkGlobalGdkDisplay();
void my_setGlobalGThreadsInit();
//void** my_GetGTKDisplay();
//void** my_GetGthreadsGotInitialized(); // defined in wrappedgthread2
void** my_GetGthreadsGotInitialized(); // defined in wrappedgthread2
// NCurse / TInfo
void my_checkGlobalTInfo();
+338
View File
@@ -0,0 +1,338 @@
#ifndef __GTKCLASS_H__
#define __GTKCLASS_H__
#include <stdint.h>
#include <stddef.h>
#include "globalsymbols.h"
typedef struct box64context_s box64context_t;
typedef struct bridge_s bridge_t;
typedef struct my_GValue_s
{
size_t g_type;
union {
int v_int;
int64_t v_int64;
uint64_t v_uint64;
float v_float;
double v_double;
void* v_pointer;
} data[2];
} my_GValue_t;
typedef struct my_GObjectClass_s
{
size_t g_type_class;
void* construct_properties;
void* (*constructor) (int type, uint32_t n_construct_properties, void* construct_properties);
void (*set_property) (void* object, uint32_t property_id, void* value, void* pspec);
void (*get_property) (void* object, uint32_t property_id, void* value, void* pspec);
void (*dispose) (void* object);
void (*finalize) (void* object);
void (*dispatch_properties_changed) (void* object, uint32_t n_pspecs, void* pspecs);
void (*notify) (void* object, void* pspec);
void (*constructed) (void* object);
uint32_t flags;
void* pdummy[6];
} my_GObjectClass_t;
typedef struct my_GtkObjectClass_s
{
my_GObjectClass_t parent_class;
void (*set_arg) (void* object, void* arg, uint32_t arg_id);
void (*get_arg) (void* object, void* arg, uint32_t arg_id);
void (*destroy) (void* object);
} my_GtkObjectClass_t;
typedef struct my_GtkWidgetClass_s
{
my_GtkObjectClass_t parent_class;
uint32_t activate_signal;
uint32_t set_scroll_adjustments_signal;
void (*dispatch_child_properties_changed) (void* widget, uint32_t n_pspecs, void* pspecs);
void (* show) (void* widget);
void (* show_all) (void* widget);
void (* hide) (void* widget);
void (* hide_all) (void* widget);
void (* map) (void* widget);
void (* unmap) (void* widget);
void (* realize) (void* widget);
void (* unrealize) (void* widget);
void (* size_request) (void* widget, void* requisition);
void (* size_allocate) (void* widget, void* allocation);
void (* state_changed) (void* widget, int previous_state);
void (* parent_set) (void* widget, void* previous_parent);
void (* hierarchy_changed) (void* widget, void* previous_toplevel);
void (* style_set) (void* widget, void* previous_style);
void (* direction_changed) (void* widget, int previous_direction);
void (* grab_notify) (void* widget, int was_grabbed);
void (* child_notify) (void* widget, void* pspec);
int (* mnemonic_activate) (void* widget, int group_cycling);
void (* grab_focus) (void* widget);
int (* focus) (void* widget, int direction);
int (* event) (void* widget, void* event);
int (* button_press_event) (void* widget, void* event);
int (* button_release_event) (void* widget, void* event);
int (* scroll_event) (void* widget, void* event);
int (* motion_notify_event) (void* widget, void* event);
int (* delete_event) (void* widget, void* event);
int (* destroy_event) (void* widget, void* event);
int (* expose_event) (void* widget, void* event);
int (* key_press_event) (void* widget, void* event);
int (* key_release_event) (void* widget, void* event);
int (* enter_notify_event) (void* widget, void* event);
int (* leave_notify_event) (void* widget, void* event);
int (* configure_event) (void* widget, void* event);
int (* focus_in_event) (void* widget, void* event);
int (* focus_out_event) (void* widget, void* event);
int (* map_event) (void* widget, void* event);
int (* unmap_event) (void* widget, void* event);
int (* property_notify_event) (void* widget, void* event);
int (* selection_clear_event) (void* widget, void* event);
int (* selection_request_event) (void* widget, void* event);
int (* selection_notify_event) (void* widget, void* event);
int (* proximity_in_event) (void* widget, void* event);
int (* proximity_out_event) (void* widget, void* event);
int (* visibility_notify_event) (void* widget, void* event);
int (* client_event) (void* widget, void* event);
int (* no_expose_event) (void* widget, void* event);
int (* window_state_event) (void* widget, void* event);
void (* selection_get) (void* widget, void* selection_data, uint32_t info, uint32_t time_);
void (* selection_received) (void* widget, void* selection_data, uint32_t time_);
void (* drag_begin) (void* widget, void* context);
void (* drag_end) (void* widget, void* context);
void (* drag_data_get) (void* widget, void* context, void* selection_data, uint32_t info, uint32_t time_);
void (* drag_data_delete) (void* widget, void* context);
void (* drag_leave) (void* widget, void* context,uint32_t time_);
int (* drag_motion) (void* widget, void* context, int32_t x, int32_t y, uint32_t time_);
int (* drag_drop) (void* widget, void* context, int32_t x, int32_t y, uint32_t time_);
void (* drag_data_received) (void* widget, void* context, int32_t x, int32_t y, void* selection_data, uint32_t info, uint32_t time_);
int (* popup_menu) (void* widget);
int (* show_help) (void* widget, int help_type);
void*(*get_accessible) (void* widget);
void (*screen_changed) (void* widget, void* previous_screen);
int (*can_activate_accel) (void* widget, uint32_t signal_id);
int (*grab_broken_event) (void* widget, void* event);
void (* composited_changed) (void* widget);
int (* query_tooltip) (void* widget, int32_t x, int32_t y, int keyboard_tooltip, void* tooltip);
void (*_gtk_reserved5) (void);
void (*_gtk_reserved6) (void);
void (*_gtk_reserved7) (void);
} my_GtkWidgetClass_t;
typedef struct my_GtkContainerClass_s
{
my_GtkWidgetClass_t parent_class;
void (*add) (void* container, void* widget);
void (*remove) (void* container, void* widget);
void (*check_resize) (void* container);
void (*forall) (void* container, int include_internals, void* callback, void* callback_data);
void (*set_focus_child) (void* container, void* widget);
int (*child_type) (void* container);
void* (*composite_name) (void* container, void* child);
void (*set_child_property) (void* container, void* child, uint32_t property_id, void* value, void* pspec);
void (*get_child_property) (void* container, void* child, uint32_t property_id, void* value, void* pspec);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkContainerClass_t;
typedef struct my_GtkActionClass_s
{
my_GObjectClass_t parent_class;
void (* activate) (void* action);
int menu_item_type;
int toolbar_item_type;
void* (* create_menu_item) (void* action);
void* (* create_tool_item) (void* action);
void (* connect_proxy) (void* action, void* proxy);
void (* disconnect_proxy) (void* action, void* proxy);
void* (* create_menu) (void* action);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkActionClass_t;
typedef struct my_GtkMiscClass_s
{
my_GtkWidgetClass_t parent_class;
} my_GtkMiscClass_t;
typedef struct my_GtkLabelClass_s
{
my_GtkMiscClass_t parent_class;
void (* move_cursor) (void* label, int step, int count, int extend_selection);
void (* copy_clipboard) (void* label);
void (* populate_popup) (void* label, void* menu);
int (*activate_link) (void* label, void* uri);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
} my_GtkLabelClass_t;
typedef struct my_GtkTreeViewClass_s
{
my_GtkContainerClass_t parent_class;
void (* set_scroll_adjustments) (void* tree_view, void* hadjustment, void* vadjustment);
void (* row_activated) (void* tree_view, void* path, void* column);
int (* test_expand_row) (void* tree_view, void* iter, void* path);
int (* test_collapse_row) (void* tree_view, void* iter, void* path);
void (* row_expanded) (void* tree_view, void* iter, void* path);
void (* row_collapsed) (void* tree_view, void* iter, void* path);
void (* columns_changed) (void* tree_view);
void (* cursor_changed) (void* tree_view);
int (* move_cursor) (void* tree_view, int step, int count);
int (* select_all) (void* tree_view);
int (* unselect_all) (void* tree_view);
int (* select_cursor_row) (void* tree_view, int start_editing);
int (* toggle_cursor_row) (void* tree_view);
int (* expand_collapse_cursor_row) (void* tree_view, int logical, int expand, int open_all);
int (* select_cursor_parent) (void* tree_view);
int (* start_interactive_search) (void* tree_view);
void (*_gtk_reserved0) (void);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkTreeViewClass_t;
typedef struct my_GtkBinClass_s
{
my_GtkContainerClass_t parent_class;
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkBinClass_t;
typedef struct my_GtkWindowClass_s {
my_GtkBinClass_t parent_class;
void (* set_focus) (void* window, void* focus);
int (* frame_event) (void* window, void* event);
void (* activate_focus) (void* window);
void (* activate_default) (void* window);
void (* move_focus) (void* window, int direction);
void (*keys_changed) (void* window);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkWindowClass_t;
typedef struct my_MetaFramesClass_s
{
my_GtkWindowClass_t parent_class;
} my_MetaFramesClass_t;
typedef struct my_GtkTableClass_s
{
my_GtkContainerClass_t parent_class;
} my_GtkTableClass_t;
typedef struct my_GtkFixedClass_s
{
my_GtkContainerClass_t parent_class;
} my_GtkFixedClass_t;
// GTypeValueTable
typedef struct my_GTypeValueTable_s {
void (*value_init) (void* value);
void (*value_free) (void* value);
void (*value_copy) (void* src_value, void* dest_value);
void* (*value_peek_pointer) (void* value);
void* collect_format;
void* (*collect_value) (void* value, uint32_t n_collect_values, void* collect_values, uint32_t collect_flags);
void* lcopy_format;
void* (*lcopy_value) (void* value, uint32_t n_collect_values, void* collect_values, uint32_t collect_flags);
} my_GTypeValueTable_t;
// GTypeInfo
typedef void (*GBaseInitFunc) (void* g_class);
typedef void (*GBaseFinalizeFunc) (void* g_class);
typedef void (*GClassInitFunc) (void* g_class, void* class_data);
typedef void (*GClassFinalizeFunc) (void* g_class, void* class_data);
typedef void (*GInstanceInitFunc) (void* instance, void* g_class);
typedef struct my_GTypeInfo_s {
uint16_t class_size;
GBaseInitFunc base_init;
GBaseFinalizeFunc base_finalize;
GClassInitFunc class_init;
GClassFinalizeFunc class_finalize;
void* class_data;
uint16_t instance_size;
uint16_t n_preallocs;
GInstanceInitFunc instance_init;
my_GTypeValueTable_t* value_table;
} my_GTypeInfo_t;
// GtkTypeInfo
typedef GBaseInitFunc GtkClassInitFunc;
typedef GInstanceInitFunc GtkObjectInitFunc;
typedef struct my_GtkTypeInfo_s {
void* type_name;
uint32_t object_size;
uint32_t class_size;
GtkClassInitFunc class_init_func;
GtkObjectInitFunc object_init_func;
void* reserved_1;
void* reserved_2;
GtkClassInitFunc base_class_init_func;
} my_GtkTypeInfo_t ;
my_GTypeValueTable_t* findFreeGTypeValueTable(my_GTypeValueTable_t* fcts);
my_GTypeInfo_t* findFreeGTypeInfo(my_GTypeInfo_t* fcts, size_t parent);
my_GtkTypeInfo_t* findFreeGtkTypeInfo(my_GtkTypeInfo_t* fcts, size_t parent);
void InitGTKClass(bridge_t *bridge);
void FiniGTKClass();
#define GTKCLASSES() \
GTKCLASS(GObject) \
GTKCLASS(GtkObject) \
GTKCLASS(GtkWidget) \
GTKCLASS(GtkContainer) \
GTKCLASS(GtkAction) \
GTKCLASS(GtkLabel) \
GTKCLASS(GtkMisc) \
GTKCLASS(GtkTreeView) \
GTKCLASS(GtkBin) \
GTKCLASS(GtkWindow) \
GTKCLASS(GtkTable) \
GTKCLASS(GtkFixed) \
GTKCLASS(MetaFrames) \
#define GTKCLASS(A) void Set##A##ID(size_t id);
GTKCLASSES()
#undef GTKCLASS
void SetGTypeName(void* f);
void AutoBridgeGtk(void*(*ref)(size_t), void(*unref)(void*));
void* wrapCopyGTKClass(void* cl, size_t type);
void* unwrapCopyGTKClass(void* klass, size_t type);
typedef struct my_signal_s {
uint64_t sign; // signature
void* data;
uintptr_t c_handler;
uintptr_t destroy;
} my_signal_t;
// some random sign to identify a my_signal_t
#define SIGN 0xFB3405EB4510AA00LL
my_signal_t* new_mysignal(void* f, void* data, void* destroy);
void my_signal_delete(my_signal_t* sig);
int my_signal_is_valid(void* sig);
int my_signal_cb(void* a, void* b, void* c, void* d);
void my_add_signal_offset(size_t klass, uint32_t offset, int n);
#endif //__GTKCLASS_H__
+72 -50
View File
@@ -21,31 +21,31 @@ typedef struct {
void *reg_save_area;
} va_list[1];
*/
#define CREATE_SYSV_VALIST(A) \
va_list sysv_varargs; \
#define CREATE_SYSV_VALIST(A) \
va_list sysv_varargs; \
sysv_varargs->gp_offset=X64_VA_MAX_REG; \
sysv_varargs->fp_offset=X64_VA_MAX_XMM; \
sysv_varargs->reg_save_area=A; \
sysv_varargs->overflow_arg_area=A;
sysv_varargs->reg_save_area=(A); \
sysv_varargs->overflow_arg_area=A
#define CONVERT_VALIST(A) \
va_list sysv_varargs; \
sysv_varargs->gp_offset=A->gp_offset; \
sysv_varargs->fp_offset=A->fp_offset; \
sysv_varargs->reg_save_area=A->reg_save_area; \
sysv_varargs->overflow_arg_area=A->overflow_arg_area;
#define CONVERT_VALIST(A) \
va_list sysv_varargs; \
sysv_varargs->gp_offset=(A)->gp_offset; \
sysv_varargs->fp_offset=(A)->fp_offset; \
sysv_varargs->reg_save_area=(A)->reg_save_area; \
sysv_varargs->overflow_arg_area=(A)->overflow_arg_area;
#define CREATE_VALIST_FROM_VAARG(STACK, SCRATCH, N) \
va_list sysv_varargs; \
sysv_varargs->gp_offset=(6-((N<6)?N:6))*8;\
sysv_varargs->fp_offset=(6*8); \
sysv_varargs->reg_save_area=SCRATCH; \
sysv_varargs->overflow_arg_area=STACK; \
{ \
uint64_t *p = (uint64_t*)SCRATCH; \
p[0]=R_RDI; p[1]=R_RSI; p[2]=R_RDX; \
p[3]=R_RCX; p[4]=R_R8; p[5]=R_R9; \
memcpy(&p[6], emu->xmm, 8*16); \
va_list sysv_varargs; \
sysv_varargs->gp_offset=(6-(((N)<6)?(N):6))*8; \
sysv_varargs->fp_offset=(6*8); \
sysv_varargs->reg_save_area=(SCRATCH); \
sysv_varargs->overflow_arg_area=(STACK); \
{ \
uint64_t *p = (uint64_t*)(SCRATCH); \
p[0]=R_RDI; p[1]=R_RSI; p[2]=R_RDX; \
p[3]=R_RCX; p[4]=R_R8; p[5]=R_R9; \
memcpy(&p[6], emu->xmm, 8*16); \
}
@@ -66,40 +66,55 @@ typedef struct va_list {
va_list sysv_varargs; \
sysv_varargs.__gr_offs=(8*8); \
sysv_varargs.__vr_offs=(8*16); \
sysv_varargs.__stack=A;
sysv_varargs.__stack=(A)
#define CONVERT_VALIST(A) \
va_list sysv_varargs; \
sysv_varargs.__gr_offs=-(6*8)+A->gp_offset; \
sysv_varargs.__vr_offs=-(8*16)+(A->fp_offset-X64_VA_MAX_REG); \
sysv_varargs.__stack=A->overflow_arg_area; \
sysv_varargs.__gr_top=A->reg_save_area + X64_VA_MAX_REG; \
sysv_varargs.__vr_top=A->reg_save_area + X64_VA_MAX_XMM;
#define CONVERT_VALIST(A) \
va_list sysv_varargs; \
sysv_varargs.__gr_offs=-(6*8)+(A)->gp_offset; \
sysv_varargs.__vr_offs=-(8*16)+((A)->fp_offset-X64_VA_MAX_REG); \
sysv_varargs.__stack=(A)->overflow_arg_area; \
sysv_varargs.__gr_top=(A)->reg_save_area + X64_VA_MAX_REG; \
sysv_varargs.__vr_top=(A)->reg_save_area + X64_VA_MAX_XMM;
#define CREATE_VALIST_FROM_VAARG(STACK, SCRATCH, N) \
va_list sysv_varargs; \
sysv_varargs.__gr_offs=(8*(2+((N<6)?N:6))); \
sysv_varargs.__vr_offs=0; \
sysv_varargs.__stack=STACK; \
sysv_varargs.__gr_top=SCRATCH + X64_VA_MAX_REG; \
sysv_varargs.__vr_top=SCRATCH + X64_VA_MAX_XMM; \
{ \
uint64_t *p = (uint64_t*)SCRATCH; \
p[0]=R_RDI; p[1]=R_RSI; p[2]=R_RDX; \
p[3]=R_RCX; p[4]=R_R8; p[5]=R_R9; \
memcpy(&p[6], emu->xmm, 8*16); \
#define CREATE_VALIST_FROM_VAARG(STACK, SCRATCH, N) \
va_list sysv_varargs; \
sysv_varargs.__gr_offs=-(6*8)+(8*(((N)<6)?(N):6)); \
sysv_varargs.__vr_offs=-(8*16); \
sysv_varargs.__stack=(STACK); \
sysv_varargs.__gr_top=(void*)((uintptr_t)(SCRATCH) + X64_VA_MAX_REG); \
sysv_varargs.__vr_top=(void*)((uintptr_t)(SCRATCH) + X64_VA_MAX_XMM); \
{ \
uintptr_t *p = (uintptr_t*)(SCRATCH); \
p[0]=R_RDI; p[1]=R_RSI; p[2]=R_RDX; \
p[3]=R_RCX; p[4]=R_R8; p[5]=R_R9; \
memcpy(&p[6], emu->xmm, 8*16); \
}
#elif defined(__powerpc64__)
// TODO, is this correct?
#elif defined(__loongarch64) || defined(__powerpc64__)
#define CREATE_SYSV_VALIST(A) \
va_list sysv_varargs; \
sysv_varargs->gpr=8; \
sysv_varargs->fpr=8; \
sysv_varargs->overflow_arg_area=A;
#define CONVERT_VALIST(A) \
#error TODO!
va_list sysv_varargs = (va_list)A
// not creating CONVERT_VALIST(A) on purpose
// this one will create a VA_LIST from x64_va_list using only GPRS and 100 stack element
#define CREATE_VALIST_FROM_VALIST(VA, SCRATCH) \
va_list sysv_varargs; \
{ \
uintptr_t *p = (uintptr_t*)(SCRATCH); \
int n = (X64_VA_MAX_REG - (VA)->gp_offset)/8; \
if(n) memcpy(&p[0], (VA)->reg_save_area, n*8); \
memcpy(&p[n], (VA)->overflow_arg_area, 100*8); \
sysv_varargs = (va_list)p; \
}
// this is an approximation, and if the va_list have some float/double, it will fail!
// if the funciton needs more than 100 args, it will also fail
#define CREATE_VALIST_FROM_VAARG(STACK, SCRATCH, N) \
va_list sysv_varargs; \
{ \
uintptr_t *p = (uintptr_t*)(SCRATCH); \
p[0]=R_RDI; p[1]=R_RSI; p[2]=R_RDX; \
p[3]=R_RCX; p[4]=R_R8; p[5]=R_R9; \
memcpy(&p[6], STACK, 100*8); \
sysv_varargs = (va_list)&p[N]; \
}
#else
#error Unknown architecture!
#endif
@@ -115,9 +130,14 @@ typedef struct x64emu_s x64emu_t;
// 1st pos is of vaarg is 0, not 1!
void myStackAlign(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int xmm, int pos);
void myStackAlignScanf(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int pos);
void myStackAlignGVariantNew(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int xmm, int pos);
void myStackAlignW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int xmm, int pos);
void myStackAlignScanfW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int pos);
#ifndef CONVERT_VALIST
void myStackAlignValist(x64emu_t* emu, const char* fmt, uint64_t* mystack, x64_va_list_t va);
void myStackAlignWValist(x64emu_t* emu, const char* fmt, uint64_t* mystack, x64_va_list_t va);
void myStackAlignScanfValist(x64emu_t* emu, const char* fmt, uint64_t* mystack, x64_va_list_t va);
void myStackAlignScanfWValist(x64emu_t* emu, const char* fmt, uint64_t* mystack, x64_va_list_t va);
#endif
struct x64_stat64 { /* x86_64 arm64 */
uint64_t st_dev; /* 0 */ /* 0 */
@@ -149,3 +169,5 @@ void AlignEpollEvent(void* dest, void* source, int nbr); // x86 -> Arm
void UnalignSemidDs(void *dest, const void* source);
void AlignSemidDs(void *dest, const void* source);
uintptr_t getVArgs(x64emu_t* emu, int pos, uintptr_t* b, int N);
+2 -4
View File
@@ -24,7 +24,6 @@
// *********** GTK *****************
#if 0
EXPORT void* gdk_display = NULL; // in case it's used...
void my_checkGlobalGdkDisplay()
@@ -38,7 +37,7 @@ void my_setGlobalGThreadsInit()
int val = 1;
uintptr_t globoffs, globend;
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, "g_threads_got_initialized", &globoffs, &globend, -1, NULL)) {
printf_log(LOG_DEBUG, "Global g_threads_got_initialized workaround, @%p <= %p\n", (void*)globoffs, (void*)val);
printf_log(LOG_DEBUG, "Global g_threads_got_initialized workaround, @%p <= %d\n", (void*)globoffs, val);
memcpy((void*)globoffs, &val, sizeof(val));
}
}
@@ -50,14 +49,13 @@ void** my_GetGTKDisplay()
return &gdk_display;
char* name = getGDKX11LibName();
library_t * lib = GetLibInternal(name?name:"libgtk-1.2.so.0");
library_t * lib = GetLibInternal(name?name:"libgdk-x11-2.0.so.0");
if(!lib) return &gdk_display; // mmm, that will crash later probably
void* s = dlsym(GetHandle(lib), "gdk_display");
gdk_display = *(void**)s;
return s;
}
#endif
// **************** NCurses ****************
EXPORT int COLS;
EXPORT int LINES;
+14 -14
View File
@@ -451,8 +451,8 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin
// nope, not found
return 0;
}
//void** my_GetGTKDisplay();
//void** my_GetGthreadsGotInitialized();
void** my_GetGTKDisplay();
void** my_GetGthreadsGotInitialized();
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername)
{
if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end, self, version, vername)) {
@@ -470,18 +470,18 @@ int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
return 1;
}
// some special case symbol, defined inside box64 itself
//if(!strcmp(name, "gdk_display")) {
// *start = (uintptr_t)my_GetGTKDisplay();
// *end = *start+sizeof(void*);
// printf_log(LOG_INFO, "Using global gdk_display for gdk-x11 (%p:%p)\n", start, *(void**)start);
// return 1;
//}
//if(!strcmp(name, "g_threads_got_initialized")) {
// *start = (uintptr_t)my_GetGthreadsGotInitialized();
// *end = *start+sizeof(int);
// printf_log(LOG_INFO, "Using global g_threads_got_initialized for gthread2 (%p:%p)\n", start, *(void**)start);
// return 1;
//}
if(!strcmp(name, "gdk_display")) {
*start = (uintptr_t)my_GetGTKDisplay();
*end = *start+sizeof(void*);
printf_log(LOG_INFO, "Using global gdk_display for gdk-x11 (%p:%p)\n", start, *(void**)start);
return 1;
}
if(!strcmp(name, "g_threads_got_initialized")) {
*start = (uintptr_t)my_GetGthreadsGotInitialized();
*end = *start+sizeof(int);
printf_log(LOG_INFO, "Using global g_threads_got_initialized for gthread2 (%p:%p)\n", start, *(void**)start);
return 1;
}
// not found...
return 0;
}
+8 -1
View File
@@ -262,6 +262,13 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box64context_t*
lib->priv.n.localsymbols = kh_init(mapsymbols);
printf_log(LOG_INFO, "Using emulated %s\n", libname);
#ifdef DYNAREC
if(libname && strstr(libname, "libmonobdwgc-2.0.so")) {
printf_log(LOG_INFO, "MonoBleedingEdge detected, disable Dynarec BigBlock and enable Dynarec StrongMem\n");
box64_dynarec_bigblock = 0;
box64_dynarec_strongmem = 1;
}
#endif
return 1;
}
return 0;
@@ -376,7 +383,7 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x64emu_t*
}
#ifdef HAVE_TRACE
if(trace_func) {
if (GetGlobalSymbolStartEnd(my_context->maplib, trace_func, &trace_start, &trace_end, elf_header, -1, NULL)) {
if (GetGlobalSymbolStartEnd(local_maplib, trace_func, &trace_start, &trace_end, elf_header, -1, NULL)) {
SetTraceEmu(trace_start, trace_end);
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end);
free(trace_func);
+25 -13
View File
@@ -98,22 +98,23 @@ GO("libuuid.so.1", libuuid)
GO("libresolv.so.2", libresolv)
GO("libpulse-simple.so.0", pulsesimple)
GO("libpulse.so.0", pulse)
//GO("libsndfile.so.1", libsndfile)
//GO("libgtk-x11-2.0.so.0", gtkx112)
//GO("libgdk-x11-2.0.so.0", gdkx112)
GO("libsndfile.so.1", libsndfile)
GO("libgtk-x11-2.0.so.0", gtkx112)
GO("libgdk-x11-2.0.so.0", gdkx112)
//GO("libgtk-3.so.0", gtk3)
//GO("libgdk-3.so.0", gdk3)
//GO("libgdk_pixbuf-2.0.so.0", gdkpixbuf2)
//GO("libgio-2.0.so.0", gio2)
//GO("libgmodule-2.0.so.0", gmodule2)
//GO("libgobject-2.0.so.0", gobject2)
//GO("libglib-2.0.so.0", glib2)
//GO("libgthread-2.0.so.0", gthread2)
GO("libgdk_pixbuf-2.0.so.0", gdkpixbuf2)
GO("libgconf-2.so.4", gconf2)
GO("libgio-2.0.so.0", gio2)
GO("libgmodule-2.0.so.0", gmodule2)
GO("libgobject-2.0.so.0", gobject2)
GO("libglib-2.0.so.0", glib2)
GO("libgthread-2.0.so.0", gthread2)
//GO("libgstreamer-0.10.so.0", gstreamer010)
//GO("libgstinterfaces-0.10.so.0", gstinterfaces010)
//GO("libdbusmenu-gtk.so.4", dbusmenugtk)
//GO("libdbusmenu-glib.so.4", dbusmenuglib)
//GO("libdbus-glib-1.so.2", dbusglib1)
GO("libdbus-glib-1.so.2", dbusglib1)
//GO("libgudev-1.0.so.0", gudev1)
//GO("libappindicator.so.1", appindicator)
GO("libatk-1.0.so.0", atk)
@@ -135,6 +136,7 @@ GO("libSM.so.6", libsm)
GO("libICE.so.6", libice)
//GO("libusb-1.0.so.0", libusb1)
GO("libncursesw.so.5", libncursesw)
GO("libncursesw.so.6", libncursesw6)
GO("libform.so.5", libform)
GO("libformw.so.5", libformw)
GO("libncurses.so.5", libncurses)
@@ -152,9 +154,9 @@ GO("libcups.so.2", libcups)
//GO("libvulkan.so", vulkan)
//GO("libwayland-client.so.0", waylandclient)
GO("libxml2.so.2", xml2)
//GO("libxslt.so.1", xslt)
//GO("libldap_r-2.4.so.2", ldapr)
//GO("liblber-2.4.so.2", lber)
GO("libxslt.so.1", xslt)
GO("libldap_r-2.4.so.2", ldapr)
GO("liblber-2.4.so.2", lber)
//GO("libnsl.so.1", nsl)
//GO("liblcms2.so.2", lcms2)
GO("libkrb5.so.3", krb5)
@@ -162,6 +164,16 @@ GO("libgssapi_krb5.so.2", gssapikrb5)
GO("libgssapi.so.3", gssapi)
//GO("libtiff.so.5", libtiff)
//GO("libfuse.so.2", libfuse)
GO("libnss3.so", nss3)
GO("libnssutil3.so", nssutil3)
GO("libsmime3.so", smime3)
GO("libnspr4.so", nspr4)
GO("libplds4.so", plds4)
GO("libplc4.so", plc4)
GO("libssl3.so", ssl3)
GO("libnsl.so.1", nsl)
GO("libselinux.so.1", selinux)
GO("libsecret-1.so.0", secret1)
GO("ld-linux-x86-64.so.2", ldlinux)
+516 -184
View File
@@ -499,190 +499,6 @@ void myStackAlignScanfW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t*
}
}
#if 0
void myStackAlignGVariantNew(const char* fmt, uint32_t* st, uint32_t* mystack)
{
if (!fmt)
return;
const char *p = fmt;
int state = 0;
int inblocks = 0;
int tmp;
do {
switch(state) {
case 0: // Nothing
switch(*p) {
case 'b': // gboolean
case 'y': // guchar
case 'n': // gint16
case 'q': // guint16
case 'i': // gint32
case 'u': // guint32
case 'h': // gint32
case 's': // const gchar*
case 'o':
case 'g':
case 'v': // GVariant*
case '*': // GVariant* of any type
case '?': // GVariant* of basic type
case 'r': // GVariant* of tuple type
*mystack = *st;
++mystack;
++st;
break;
case 'x': // gint64
case 't': // guint64
case 'd': // gdouble
if ((((uint32_t)mystack)&0x7)!=0)
++mystack;
*(uint64_t*)mystack = *(uint64_t*)st;
st+=2; mystack+=2;
break;
case '{':
case '(': ++inblocks; break;
case '}':
case ')': --inblocks; break;
case 'a': state = 1; break; // GVariantBuilder* or GVariantIter**
case 'm': state = 2; break; // maybe types
case '@': state = 3; break; // GVariant* of type [type]
case '^': state = 4; break; // pointer value
case '&': break; // pointer: do nothing
}
break;
case 1: // Arrays
switch(*p) {
case '{':
case '(': ++tmp; break;
case '}':
case ')': --tmp; break;
}
if (*p == 'a') break;
if (tmp == 0) {
*mystack = *st;
++mystack;
++st;
state = 0;
}
break;
case 2: // Maybe-types
switch(*p) {
case 'b': // gboolean
case 'y': // guchar
case 'n': // gint16
case 'q': // guint16
case 'i': // gint32
case 'u': // guint32
case 'h': // gint32
case 'x': // gint64
case 't': // guint64
case 'd': // gdouble
case '{':
case '}':
case '(':
case ')':
// Add a gboolean or gboolean*, no char increment
*mystack = *st;
++mystack;
++st;
--p;
state = 0;
break;
case 'a': // GVariantBuilder* or GVariantIter**
case 's': // const gchar*
case 'o':
case 'g':
case 'v': // GVariant*
case '@': // GVariant* of type [type]
case '*': // GVariant* of any type
case '?': // GVariant* of basic type
case 'r': // GVariant* of tuple type
case '&': // pointer
case '^': // pointer value
// Just maybe-NULL
--p;
state = 0;
break;
default: // Default to add a gboolean & reinit state?
*mystack = *st;
++mystack;
++st;
--p;
state = 0;
}
break;
case 3: // GVariant*
switch(*p) {
case '{':
case '(': ++tmp; break;
case '}':
case ')': --tmp; break;
case 'a': // GVariantBuilder* or GVariantIter**
do { ++p; } while(*p == 'a'); // Use next character which is not an array (array definition)
switch(*p) {
case '{':
case '(': ++tmp; break;
case '}':
case ')': --tmp; break;
}
break;
}
if (tmp == 0) {
*mystack = *st;
++mystack;
++st;
state = 0;
}
break;
case 4: // ^
if (*p == 'a') state = 5;
else if (*p == '&') state = 8;
else state = 0; //???
break;
case 5: // ^a
if ((*p == 's') || (*p == 'o') || (*p == 'y')) {
*mystack = *st;
++mystack;
++st;
state = 0;
} else if (*p == '&') state = 6;
else if (*p == 'a') state = 7;
else state = 0; //???
break;
case 6: // ^a&
if ((*p == 's') || (*p == 'o')) {
*mystack = *st;
++mystack;
++st;
state = 0;
} else if (*p == 'a') state = 7;
else state = 0; //???
break;
case 7: // ^aa / ^a&a
if (*p == 'y') {
*mystack = *st;
++mystack;
++st;
state = 0;
} else state = 0; //???
case 8: // ^&
if (*p == 'a') state = 9;
else state = 0; //???
case 9: // ^&a
if (*p == 'y') {
*mystack = *st;
++mystack;
++st;
state = 0;
} else state = 0; //???
}
++p;
} while (*p && (inblocks || state));
}
#endif
#undef st_atime
#undef st_mtime
@@ -801,3 +617,519 @@ void AlignSemidDs(void *dest, const void* source)
arm_struct->sem_ctime = x64_struct->sem_ctime;
arm_struct->sem_nsems = x64_struct->sem_nsems;
}
uintptr_t getVArgs(x64emu_t* emu, int pos, uintptr_t* b, int N)
{
if((pos+N)>5)
return b[pos+N-6];
return emu->regs[regs_abi[pos+N]].q[0];
}
#ifndef CONVERT_VALIST
void myStackAlignValist(x64emu_t* emu, const char* fmt, uint64_t* mystack, x64_va_list_t va)
{
if(!fmt)
return;
// loop...
const char* p = fmt;
int state = 0;
#ifndef HAVE_LD80BITS
double d;
long double ld;
#endif
int x = 0;
uintptr_t *area = (uintptr_t*)va->reg_save_area; // the direct registers copy
uintptr_t *st = (uintptr_t*)va->overflow_arg_area; // the stack arguments
uintptr_t gprs = va->gp_offset;
uintptr_t fprs = va->fp_offset;
while(*p)
{
switch(state) {
case 0:
switch(*p) {
case '%': state = 1; ++p; break;
default:
++p;
}
break;
case 1: // normal
case 2: // l
case 3: // ll
case 4: // L
case 5: // z
switch(*p) {
case '%': state = 0; ++p; break; //%% = back to 0
case 'l': ++state; if (state>3) state=3; ++p; break;
case 'L': state = 4; ++p; break;
case 'z': state = 5; ++p; break;
case 'a':
case 'A':
case 'e':
case 'E':
case 'g':
case 'G':
case 'F':
case 'f': state += 10; break; // float
case 'd':
case 'i':
case 'o':
case 'u':
case 'x':
case 'X': state += 20; break; // int
case 'h': ++p; break; // ignored...
case '\'':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
case '+':
case '-': ++p; break; // formating, ignored
case 'm': state = 0; ++p; break; // no argument
case 'n':
case 'p':
case 'S':
case 's': state = 30; break; // pointers
case '$': ++p; break; // should issue a warning, it's not handled...
case '*':
if(gprs<X64_VA_MAX_REG) {
*mystack = area[gprs/8];
gprs+=8;
} else {
*mystack = *st;
++st;
}
++mystack;
++p;
break; // fetch an int in the stack....
case ' ': state=0; ++p; break;
default:
state=20; // other stuff, put an int...
}
break;
case 11: //double
case 12: //%lg, still double
case 13: //%llg, still double
case 15: //%zg, meh.. double?
if(fprs<X64_VA_MAX_XMM) {
*mystack = area[fprs/8];
fprs+=8;
mystack++;
} else {
*mystack = *st;
st++; mystack++;
}
state = 0;
++p;
break;
case 14: //%LG long double
if((((uintptr_t)st)&0xf)!=0)
st++;
#ifdef HAVE_LD80BITS
if((((uintptr_t)mystack)&0xf)!=0)
mystack++;
memcpy(mystack, st, 16);
st+=2; mystack+=2;
#else
// there is 128bits long double on ARM64, but they need 128bit alignment
if((((uintptr_t)mystack)&0xf)!=0)
mystack++;
LD2D((void*)st, &d);
ld = d ;
memcpy(mystack, &ld, 16);
st+=2; mystack+=2;
#endif
state = 0;
++p;
break;
case 20: // fallback
case 21:
case 22:
case 23: // 64bits int
case 24: // normal int / pointer
case 25: // size_t int
case 30:
if(gprs<X64_VA_MAX_REG) {
*mystack = area[gprs/8];
gprs+=8;
} else {
*mystack = *st;
++st;
}
++mystack;
state = 0;
++p;
break;
default:
// whaaaat?
state = 0;
}
}
}
void myStackAlignWValist(x64emu_t* emu, const char* fmt, uint64_t* mystack, x64_va_list_t va)
{
// loop...
const wchar_t* p = (const wchar_t*)fmt;
int state = 0;
#ifndef HAVE_LD80BITS
double d;
long double ld;
#endif
int x = 0;
uintptr_t *area = (uintptr_t*)va->reg_save_area; // the direct registers copy
uintptr_t *st = (uintptr_t*)va->overflow_arg_area; // the stack arguments
uintptr_t gprs = va->gp_offset;
uintptr_t fprs = va->fp_offset;
while(*p)
{
switch(state) {
case 0:
switch(*p) {
case '%': state = 1; ++p; break;
default:
++p;
}
break;
case 1: // normal
case 2: // l
case 3: // ll
case 4: // L
case 5: // z
switch(*p) {
case '%': state = 0; ++p; break; //%% = back to 0
case 'l': ++state; if (state>3) state=3; ++p; break;
case 'L': state = 4; ++p; break;
case 'z': state = 5; ++p; break;
case 'a':
case 'A':
case 'e':
case 'E':
case 'g':
case 'G':
case 'F':
case 'f': state += 10; break; // float
case 'd':
case 'i':
case 'o':
case 'u':
case 'x':
case 'X': state += 20; break; // int
case 'h': ++p; break; // ignored...
case '\'':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
case '+':
case '-': ++p; break; // formating, ignored
case 'm': state = 0; ++p; break; // no argument
case 'n':
case 'p':
case 'S':
case 's': state = 30; break; // pointers
case '$': ++p; break; // should issue a warning, it's not handled...
case '*':
if(gprs<X64_VA_MAX_REG) {
*mystack = area[gprs/8];
gprs+=8;
} else {
*mystack = *st;
++st;
}
++mystack;
++p;
break; // fetch an int in the stack....
case ' ': state=0; ++p; break;
default:
state=20; // other stuff, put an int...
}
break;
case 11: //double
case 12: //%lg, still double
case 13: //%llg, still double
case 15: //%zg, meh .. double
if(fprs<X64_VA_MAX_XMM) {
*mystack = area[fprs/8];
fprs+=8;
mystack++;
} else {
*mystack = *st;
st++; mystack++;
}
state = 0;
++p;
break;
case 14: //%LG long double
if((((uintptr_t)st)&0xf)!=0)
st++;
#ifdef HAVE_LD80BITS
if((((uintptr_t)mystack)&0xf)!=0)
mystack++;
memcpy(mystack, st, 16);
st+=2; mystack+=2;
#else
// there is 128bits long double on ARM64, but they need 128bit alignment
if((((uintptr_t)mystack)&0xf)!=0)
mystack++;
LD2D((void*)st, &d);
ld = d ;
memcpy(mystack, &ld, 16);
st+=2; mystack+=2;
#endif
state = 0;
++p;
break;
case 20: // fallback
case 21:
case 22:
case 23: // 64bits int
case 24: // normal int / pointer
case 25: // size_t int
case 30:
if(gprs<X64_VA_MAX_REG) {
*mystack = area[gprs/8];
gprs+=8;
} else {
*mystack = *st;
++st;
}
++mystack;
state = 0;
++p;
break;
default:
// whaaaattt?
state = 0;
}
}
}
void myStackAlignScanfValist(x64emu_t* emu, const char* fmt, uint64_t* mystack, x64_va_list_t va)
{
if(!fmt)
return;
// loop...
const char* p = fmt;
int state = 0;
int ign = 0;
uintptr_t *area = (uintptr_t*)va->reg_save_area; // the direct registers copy
uintptr_t *st = (uintptr_t*)va->overflow_arg_area; // the stack arguments
uintptr_t gprs = va->gp_offset;
uintptr_t fprs = va->fp_offset;
while(*p)
{
switch(state) {
case 0:
ign = 0;
switch(*p) {
case '%': state = 1; ++p; break;
default:
++p;
}
break;
case 1: // normal
case 2: // l
case 3: // ll
case 4: // L
case 5: // z
switch(*p) {
case '%': state = 0; ++p; break; //%% = back to 0
case 'l': ++state; if (state>3) state=3; ++p; break;
case 'L': state = 4; ++p; break;
case 'z': state = 5; ++p; break;
case 'a':
case 'A':
case 'e':
case 'E':
case 'g':
case 'G':
case 'F':
case 'f': state += 10; break; // float
case 'd':
case 'i':
case 'o':
case 'u':
case 'x':
case 'X': state += 20; break; // int
case 'h': ++p; break; // ignored...
case '\'':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
case '+':
case '-': ++p; break; // formating, ignored
case 'm': state = 0; ++p; break; // no argument
case 'n':
case 'p':
case 'S':
case 's': state = 30; break; // pointers
case '$': ++p; break; // should issue a warning, it's not handled...
case '*': ign=1; ++p; break; // ignore arg
case ' ': state=0; ++p; break;
default:
state=20; // other stuff, put an int...
}
break;
case 11: //double
case 12: //%lg, still double
case 13: //%llg, still double
case 14: //%Lg long double
case 15: //%zg
case 20: // fallback
case 21:
case 22:
case 23: // 64bits int
case 24: // normal int / pointer
case 25: // size_t int
case 30:
if(!ign) {
if(gprs<X64_VA_MAX_REG) {
*mystack = area[gprs/8];
gprs+=8;
} else {
*mystack = *st;
++st;
}
++mystack;
}
state = 0;
++p;
break;
default:
// whaaaat?
state = 0;
}
}
}
void myStackAlignScanfWValist(x64emu_t* emu, const char* fmt, uint64_t* mystack, x64_va_list_t va)
{
if(!fmt)
return;
// loop...
const wchar_t* p = (const wchar_t*)fmt;
int state = 0;
int ign = 0;
uintptr_t *area = (uintptr_t*)va->reg_save_area; // the direct registers copy
uintptr_t *st = (uintptr_t*)va->overflow_arg_area; // the stack arguments
uintptr_t gprs = va->gp_offset;
uintptr_t fprs = va->fp_offset;
while(*p)
{
switch(state) {
case 0:
ign = 0;
switch(*p) {
case '%': state = 1; ++p; break;
default:
++p;
}
break;
case 1: // normal
case 2: // l
case 3: // ll
case 4: // L
case 5: // z
switch(*p) {
case '%': state = 0; ++p; break; //%% = back to 0
case 'l': ++state; if (state>3) state=3; ++p; break;
case 'L': state = 4; ++p; break;
case 'z': state = 5; ++p; break;
case 'a':
case 'A':
case 'e':
case 'E':
case 'g':
case 'G':
case 'F':
case 'f': state += 10; break; // float
case 'd':
case 'i':
case 'o':
case 'u':
case 'x':
case 'X': state += 20; break; // int
case 'h': ++p; break; // ignored...
case '\'':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
case '+':
case '-': ++p; break; // formating, ignored
case 'm': state = 0; ++p; break; // no argument
case 'n':
case 'p':
case 'S':
case 's': state = 30; break; // pointers
case '$': ++p; break; // should issue a warning, it's not handled...
case '*': ign = 1; ++p; break; // ignore arg
case ' ': state=0; ++p; break;
default:
state=20; // other stuff, put an int...
}
break;
case 11: //double
case 12: //%lg, still double
case 13: //%llg, still double
case 14: //%Lg long double
case 15: //%zg
case 20: // fallback
case 21:
case 22:
case 23: // 64bits int
case 24: // normal int / pointer
case 25: // size_t int
case 30:
if(!ign) {
if(gprs<X64_VA_MAX_REG) {
*mystack = area[gprs/8];
gprs+=8;
} else {
*mystack = *st;
++st;
}
++mystack;
}
state = 0;
++p;
break;
default:
// whaaaat?
state = 0;
}
}
}
#endif
+49 -9
View File
@@ -290,7 +290,7 @@ uint64_t RunFunctionHandler(int* exit, x64_ucontext_t* sigcontext, uintptr_t fnc
emu->segs_serial[i] = 0;
if(nargs>6)
R_RSP -= (nargs-6)*4; // need to push in reverse order
R_RSP -= (nargs-6)*sizeof(void*); // need to push in reverse order
uint64_t *p = (uint64_t*)R_RSP;
@@ -310,10 +310,10 @@ uint64_t RunFunctionHandler(int* exit, x64_ucontext_t* sigcontext, uintptr_t fnc
int oldquitonlongjmp = emu->quitonlongjmp;
emu->quitonlongjmp = 2;
//EmuCall(emu, fnc); // avoid DynaCall for now
DynaCall(emu, fnc);
EmuCall(emu, fnc); // avoid DynaCall for now
//DynaCall(emu, fnc);
if(nargs>6)
R_RSP+=((nargs-6)*4);
R_RSP+=((nargs-6)*sizeof(void*));
emu->quitonlongjmp = oldquitonlongjmp;
@@ -705,6 +705,11 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void
relockMutex(Locks);
}
extern __thread void* current_helper;
#ifdef DYNAREC
static pthread_mutex_t mutex_dynarec_prot;
#endif
void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
{
// sig==SIGSEGV || sig==SIGBUS || sig==SIGILL here!
@@ -728,7 +733,7 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
#elif defined __x86_64__
void * pc = (void*)p->uc_mcontext.gregs[X64_RIP];
#elif defined __powerpc64__
void * pc = (void*)p->uc_mcontext.uc_regs->gregs[PT_NIP];
void * pc = (void*)p->uc_mcontext.gp_regs[PT_NIP];
#else
void * pc = NULL; // unknow arch...
#warning Unhandled architecture
@@ -736,15 +741,30 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
int Locks = unlockMutex();
uint32_t prot = getProtection((uintptr_t)addr);
#ifdef DYNAREC
if((Locks & (1<<8)) && (sig==SIGSEGV) && current_helper) {//1<<8 is mutex_dyndump
relockMutex(Locks);
cancelFillBlock(); // Segfault inside a Fillblock, cancel it's creation...
}
dynablock_t* db = NULL;
int db_searched = 0;
if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_DYNAREC)) {
// access error, unprotect the block (and mark them dirty)
unprotectDB((uintptr_t)addr, 1); // unprotect 1 byte... But then, the whole page will be unprotected
pthread_mutex_lock(&mutex_dynarec_prot);
// check if SMC inside block
db = FindDynablockFromNativeAddress(pc);
db_searched = 1;
dynarec_log(LOG_DEBUG, "SIGSEGV with Access error on %p for %p , db=%p(%p), prot=0x%x\n", pc, addr, db, db?((void*)db->x64_addr):NULL, prot);
static uintptr_t repeated_page = 0;
dynarec_log(LOG_DEBUG, "SIGSEGV with Access error on %p for %p , db=%p(%p), prot=0x%x (old page=%p)\n", pc, addr, db, db?((void*)db->x64_addr):NULL, prot, (void*)repeated_page);
static int repeated_count = 0;
if(repeated_page == ((uintptr_t)addr&~0xfff)) {
++repeated_count; // Access eoor multiple time on same page, disable dynarec on this page a few time...
dynarec_log(LOG_DEBUG, "Detecting a Hotpage at %p (%d)\n", (void*)repeated_page, repeated_count);
AddHotPage(repeated_page);
} else {
repeated_page = (uintptr_t)addr&~0xfff;
repeated_count = 0;
}
// access error, unprotect the block (and mark them dirty)
unprotectDB((uintptr_t)addr, 1); // unprotect 1 byte... But then, the whole page will be unprotected
if(db && ((addr>=db->x64_addr && addr<(db->x64_addr+db->x64_size)) || db->need_test)) {
// dynablock got auto-dirty! need to get out of it!!!
emu_jmpbuf_t* ejb = GetJmpBuf();
@@ -779,17 +799,21 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
dynarec_log(LOG_INFO, "Dynablock unprotected, getting out!\n");
}
relockMutex(Locks);
pthread_mutex_unlock(&mutex_dynarec_prot);
siglongjmp(ejb->jmpbuf, 2);
}
dynarec_log(LOG_INFO, "Warning, Auto-SMC (%p for db %p/%p) detected, but jmpbuffer not ready!\n", (void*)addr, db, (void*)db->x64_addr);
}
// done
if(prot&PROT_WRITE) {
if((prot&PROT_WRITE) || (prot&PROT_DYNAREC)) {
pthread_mutex_unlock(&mutex_dynarec_prot);
// if there is no write permission, don't return and continue to program signal handling
relockMutex(Locks);
return;
}
pthread_mutex_unlock(&mutex_dynarec_prot);
} else if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&(PROT_READ|PROT_WRITE))) {
pthread_mutex_lock(&mutex_dynarec_prot);
db = FindDynablockFromNativeAddress(pc);
db_searched = 1;
if(db && db->x64_addr>= addr && (db->x64_addr+db->x64_size)<addr) {
@@ -806,6 +830,7 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
glitch_addr = addr;
glitch_prot = prot;
relockMutex(Locks);
pthread_mutex_unlock(&mutex_dynarec_prot);
return; // try again
}
dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for %p, db=%p, prot=0x%x\n", pc, addr, db, prot);
@@ -813,6 +838,7 @@ dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for
glitch_addr = NULL;
glitch_prot = 0;
}
pthread_mutex_unlock(&mutex_dynarec_prot);
}
#else
void* db = NULL;
@@ -1275,7 +1301,17 @@ EXPORT int my_swapcontext(x64emu_t* emu, void* ucp1, void* ucp2)
my_setcontext(emu, ucp2);
return 0;
}
#ifdef DYNAREC
static void atfork_child_dynarec_prot(void)
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&mutex_dynarec_prot, &attr);
pthread_mutexattr_destroy(&attr);
}
#endif
void init_signal_helper(box64context_t* context)
{
// setup signal handling
@@ -1294,6 +1330,10 @@ void init_signal_helper(box64context_t* context)
sigaction(SIGILL, &action, NULL);
pthread_once(&sigstack_key_once, sigstack_key_alloc);
#ifdef DYNAREC
atfork_child_dynarec_prot();
pthread_atfork(NULL, NULL, atfork_child_dynarec_prot);
#endif
}
void fini_signal_helper()
+17 -4
View File
@@ -8,6 +8,7 @@
#include <errno.h>
#include <setjmp.h>
#include <sys/mman.h>
#include <dlfcn.h>
#include "debug.h"
#include "box64context.h"
@@ -28,8 +29,12 @@
#include "dynablock.h"
#endif
void _pthread_cleanup_push_defer(void* buffer, void* routine, void* arg); // declare hidden functions
void _pthread_cleanup_pop_restore(void* buffer, int exec);
//void _pthread_cleanup_push_defer(void* buffer, void* routine, void* arg); // declare hidden functions
//void _pthread_cleanup_pop_restore(void* buffer, int exec);
typedef void (*vFppp_t)(void*, void*, void*);
typedef void (*vFpi_t)(void*, int);
static vFppp_t real_pthread_cleanup_push_defer = NULL;
static vFpi_t real_pthread_cleanup_pop_restore = NULL;
void _pthread_cleanup_push(void* buffer, void* routine, void* arg); // declare hidden functions
void _pthread_cleanup_pop(void* buffer, int exec);
@@ -417,6 +422,11 @@ EXPORT int my_pthread_attr_setstackaddr(x64emu_t* emu, pthread_attr_t* attr, voi
return pthread_attr_setstack(getAlignedAttr(attr), addr, size);
//return pthread_attr_setstackaddr(getAlignedAttr(attr), addr);
}
EXPORT int my_pthread_getattr_np(x64emu_t* emu, pthread_t thread_id, pthread_attr_t* attr)
{
(void)emu;
return pthread_getattr_np(thread_id, getAlignedAttrWithInit(attr, 0));
}
#endif
EXPORT int my_pthread_create(x64emu_t *emu, void* t, void* attr, void* start_routine, void* arg)
@@ -663,7 +673,7 @@ EXPORT int my_pthread_cond_wait(x64emu_t* emu, pthread_cond_t* cond, void* mutex
EXPORT void my__pthread_cleanup_push_defer(x64emu_t* emu, void* buffer, void* routine, void* arg)
{
(void)emu;
_pthread_cleanup_push_defer(buffer, findcleanup_routineFct(routine), arg);
real_pthread_cleanup_push_defer(buffer, findcleanup_routineFct(routine), arg);
}
EXPORT void my__pthread_cleanup_push(x64emu_t* emu, void* buffer, void* routine, void* arg)
@@ -675,7 +685,7 @@ EXPORT void my__pthread_cleanup_push(x64emu_t* emu, void* buffer, void* routine,
EXPORT void my__pthread_cleanup_pop_restore(x64emu_t* emu, void* buffer, int exec)
{
(void)emu;
_pthread_cleanup_pop_restore(buffer, exec);
real_pthread_cleanup_pop_restore(buffer, exec);
}
EXPORT void my__pthread_cleanup_pop(x64emu_t* emu, void* buffer, int exec)
@@ -1130,6 +1140,9 @@ emu_jmpbuf_t* GetJmpBuf()
void init_pthread_helper()
{
real_pthread_cleanup_push_defer = (vFppp_t)dlsym(NULL, "_pthread_cleanup_push_defer");
real_pthread_cleanup_pop_restore = (vFpi_t)dlsym(NULL, "_pthread_cleanup_pop_restore");
InitCancelThread();
pthread_key_create(&jmpbuf_key, emujmpbuf_destroy);
}
+47 -16
View File
@@ -42,6 +42,8 @@ int box64_pagesize;
int box64_dynarec = 1;
int box64_dynarec_dump = 0;
int box64_dynarec_forced = 0;
int box64_dynarec_bigblock = 1;
int box64_dynarec_strongmem = 0;
uintptr_t box64_nodynarec_start = 0;
uintptr_t box64_nodynarec_end = 0;
#ifdef ARM64
@@ -49,6 +51,7 @@ int arm64_asimd = 0;
int arm64_aes = 0;
int arm64_pmull = 0;
int arm64_crc32 = 0;
int arm64_atomics = 0;
#endif
#else //DYNAREC
int box64_dynarec = 0;
@@ -92,14 +95,21 @@ void openFTrace()
char tmp[500];
char* p = t;
if(p && strstr(t, "%pid")) {
strcpy(tmp, p);
char* c = strstr(tmp, "%pid");
*c = 0; // cut
char pid[10];
sprintf(pid, "%d", getpid());
strcat(tmp, pid);
c = strstr(p, "%pid") + strlen("%pid");
strcat(tmp, c);
int next = 0;
do {
strcpy(tmp, p);
char* c = strstr(tmp, "%pid");
*c = 0; // cut
char pid[16];
if(next)
sprintf(pid, "%d-%d", getpid(), next);
else
sprintf(pid, "%d", getpid());
strcat(tmp, pid);
c = strstr(p, "%pid") + strlen("%pid");
strcat(tmp, c);
++next;
} while (FileExist(tmp, IS_FILE));
p = tmp;
ftrace_has_pid = 1;
}
@@ -149,6 +159,8 @@ void GatherDynarecExtensions()
arm64_pmull = 1;
if(hwcap&HWCAP_AES)
arm64_aes = 1;
if(hwcap&HWCAP_ATOMICS)
arm64_atomics = 1;
printf_log(LOG_INFO, "Dynarec for ARM64, with extension: ASIMD");
if(arm64_aes)
printf_log(LOG_INFO, " AES");
@@ -156,6 +168,8 @@ void GatherDynarecExtensions()
printf_log(LOG_INFO, " CRC32");
if(arm64_pmull)
printf_log(LOG_INFO, " PMULL");
if(arm64_atomics)
printf_log(LOG_INFO, " ATOMICS");
printf_log(LOG_INFO, " PageSize:%d\n", box64_pagesize);
#endif
}
@@ -250,6 +264,24 @@ void LoadLogEnv()
if(box64_dynarec_forced)
printf_log(LOG_INFO, "Dynarec is Forced on all addresses\n");
}
p = getenv("BOX64_DYNAREC_BIGBLOCK");
if(p) {
if(strlen(p)==1) {
if(p[0]>='0' && p[0]<='1')
box64_dynarec_bigblock = p[0]-'0';
}
if(!box64_dynarec_bigblock)
printf_log(LOG_INFO, "Dynarec will not try to make big block\n");
}
p = getenv("BOX64_DYNAREC_STRONGMEM");
if(p) {
if(strlen(p)==1) {
if(p[0]>='0' && p[0]<='2')
box64_dynarec_strongmem = p[0]-'0';
}
if(box64_dynarec_strongmem)
printf_log(LOG_INFO, "Dynarec will try to emulate a strong memory model%s\n", (box64_dynarec_strongmem==1)?" with limited performace loss":"");
}
p = getenv("BOX64_NODYNAREC");
if(p) {
if (strchr(p,'-')) {
@@ -826,10 +858,7 @@ int main(int argc, const char **argv, const char **env) {
// check BOX64_LD_LIBRARY_PATH and load it
LoadEnvVars(my_context);
if(argv[0][0]=='/')
my_context->box64path = strdup(argv[0]);
else
my_context->box64path = ResolveFile(argv[0], &my_context->box64_path);
my_context->box64path = ResolveFile(argv[0], &my_context->box64_path);
// prepare all other env. var
my_context->envc = CountEnv(environ?environ:env);
printf_log(LOG_INFO, "Counted %d Env var\n", my_context->envc);
@@ -871,10 +900,7 @@ int main(int argc, const char **argv, const char **env) {
}
// lets build argc/argv stuff
printf_log(LOG_INFO, "Looking for %s\n", prog);
if(strchr(prog, '/'))
my_context->argv[0] = strdup(prog);
else
my_context->argv[0] = ResolveFile(prog, &my_context->box64_path);
my_context->argv[0] = ResolveFile(prog, &my_context->box64_path);
// check if box86 is present
{
my_context->box86path = strdup(my_context->box64path);
@@ -911,6 +937,11 @@ int main(int argc, const char **argv, const char **env) {
printf_log(LOG_INFO, "steam-runtime-check-requirements detected, faking All is good!\n");
exit(0); // exiting, not testing anything
}
// special case for steam-runtime-check-requirements to fake 64bits suport
if(strstr(prgname, "steamwebhelper")==prgname) {
printf_log(LOG_INFO, "steamwebhelper, ignoring for now!\n");
exit(0); // exiting
}
// special case for UnrealLinux.bin, it doesn't like "full path resolution"
if(!strcmp(prog, "UnrealLinux.bin") && my_context->argv[0]) {
free(my_context->argv[0]);
+11 -2
View File
@@ -4,7 +4,9 @@
#include <string.h>
#include <dlfcn.h>
#include <pthread.h>
#include <sys/mman.h>
#include <wrappedlibs.h>
#include "custommem.h"
#include "bridge.h"
#include "bridge_private.h"
@@ -33,12 +35,18 @@ typedef struct bridge_s {
kh_bridgemap_t *bridgemap;
} bridge_t;
// from src/wrapped/wrappedlibc.c
void* my_mmap(x64emu_t* emu, void* addr, unsigned long length, int prot, int flags, int fd, int64_t offset);
int my_munmap(x64emu_t* emu, void* addr, unsigned long length);
brick_t* NewBrick()
{
brick_t* ret = (brick_t*)calloc(1, sizeof(brick_t));
if(posix_memalign((void**)&ret->b, box64_pagesize, NBRICK*sizeof(onebridge_t))) {
void* ptr = my_mmap(thread_get_emu(), NULL, NBRICK * sizeof(onebridge_t), PROT_READ | PROT_WRITE, MAP_PRIVATE | 0x40 | MAP_ANONYMOUS, -1, 0); // 0x40 is MAP_32BIT
if(ptr == MAP_FAILED) {
printf_log(LOG_NONE, "Warning, cannot allocate 0x%lx aligned bytes for bridge, will probably crash later\n", NBRICK*sizeof(onebridge_t));
}
ret->b = ptr;
return ret;
}
@@ -56,13 +64,14 @@ void FreeBridge(bridge_t** bridge)
if(!bridge || !*bridge)
return;
brick_t *b = (*bridge)->head;
x64emu_t* emu = thread_get_emu();
while(b) {
brick_t *n = b->next;
#ifdef DYNAREC
if(getProtection((uintptr_t)b->b)&PROT_DYNAREC)
unprotectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t));
#endif
free(b->b);
my_munmap(emu, b->b, NBRICK*sizeof(onebridge_t));
free(b);
b = n;
}
+4 -4
View File
@@ -21,7 +21,7 @@ uint64_t RunFunction(box64context_t *context, uintptr_t fnc, int nargs, ...)
x64emu_t *emu = thread_get_emu();
if(nargs>6)
R_ESP -= (nargs-6)*4; // need to push in reverse order
R_ESP -= (nargs-6)*sizeof(void*); // need to push in reverse order
uint64_t *p = (uint64_t*)R_RSP;
@@ -40,7 +40,7 @@ uint64_t RunFunction(box64context_t *context, uintptr_t fnc, int nargs, ...)
DynaCall(emu, fnc);
if(nargs>6)
R_ESP+=((nargs-6)*4);
R_ESP+=((nargs-6)*sizeof(void*));
uint64_t ret = R_RAX;
@@ -51,7 +51,7 @@ EXPORTDYN
uint64_t RunFunctionWithEmu(x64emu_t *emu, int QuitOnLongJump, uintptr_t fnc, int nargs, ...)
{
if(nargs>6)
R_ESP -= (nargs-6)*4; // need to push in reverse order
R_ESP -= (nargs-6)*sizeof(void*); // need to push in reverse order
uint64_t *p = (uint64_t*)R_RSP;
@@ -78,7 +78,7 @@ uint64_t RunFunctionWithEmu(x64emu_t *emu, int QuitOnLongJump, uintptr_t fnc, in
DynaCall(emu, fnc);
if(oldip==R_RIP && nargs>6)
R_ESP+=((nargs-6)*4); // restore stack only if EIP is the one expected (else, it means return value is not the one expected)
R_ESP+=((nargs-6)*sizeof(void*)); // restore stack only if EIP is the one expected (else, it means return value is not the one expected)
emu->quit = old_quit;
emu->quitonlongjmp = oldlong;
+1 -1
View File
@@ -60,7 +60,7 @@ char* ResolveFile(const char* filename, path_collection_t* paths)
return realpath(p, NULL);
}
return NULL;
return strdup(filename); //NULL;
}
int FileIsX64ELF(const char* filename)
+1537
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappeddbusglib1DEFS_H_
#define __wrappeddbusglib1DEFS_H_
#endif // __wrappeddbusglib1DEFS_H_
@@ -0,0 +1,28 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappeddbusglib1TYPES_H_
#define __wrappeddbusglib1TYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
typedef void (*vFppp_t)(void*, void*, void*);
typedef void (*vFpppp_t)(void*, void*, void*, void*);
typedef void (*vFppppp_t)(void*, void*, void*, void*, void*);
typedef void* (*pFpppppiV_t)(void*, void*, void*, void*, void*, int64_t, ...);
typedef void* (*pFpppppiiV_t)(void*, void*, void*, void*, void*, int64_t, int64_t, ...);
#define SUPER() ADDED_FUNCTIONS() \
GO(dbus_g_type_collection_value_iterate, vFppp_t) \
GO(dbus_g_type_map_value_iterate, vFppp_t) \
GO(dbus_g_proxy_disconnect_signal, vFpppp_t) \
GO(dbus_g_proxy_connect_signal, vFppppp_t) \
GO(dbus_g_proxy_begin_call, pFpppppiV_t) \
GO(dbus_g_proxy_begin_call_with_timeout, pFpppppiiV_t)
#endif // __wrappeddbusglib1TYPES_H_
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappeddbusglib1UNDEFS_H_
#define __wrappeddbusglib1UNDEFS_H_
#endif // __wrappeddbusglib1UNDEFS_H_
+4
View File
@@ -12,6 +12,8 @@
#endif
typedef void (*vFppp_t)(void*, void*, void*);
typedef int64_t (*iFpiV_t)(void*, int64_t, ...);
typedef int64_t (*iFpiA_t)(void*, int64_t, va_list);
typedef void (*vFpppp_t)(void*, void*, void*, void*);
typedef int64_t (*iFpipp_t)(void*, int64_t, void*, void*);
typedef int64_t (*iFppip_t)(void*, void*, int64_t, void*);
@@ -24,6 +26,8 @@ typedef int64_t (*iFpppppp_t)(void*, void*, void*, void*, void*, void*);
GO(dbus_connection_remove_filter, vFppp_t) \
GO(dbus_timeout_set_data, vFppp_t) \
GO(dbus_watch_set_data, vFppp_t) \
GO(dbus_message_append_args, iFpiV_t) \
GO(dbus_message_append_args_valist, iFpiA_t) \
GO(dbus_connection_set_dispatch_status_function, vFpppp_t) \
GO(dbus_connection_set_wakeup_main_function, vFpppp_t) \
GO(dbus_connection_set_data, iFpipp_t) \
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgconf2DEFS_H_
#define __wrappedgconf2DEFS_H_
#endif // __wrappedgconf2DEFS_H_
@@ -0,0 +1,17 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgconf2TYPES_H_
#define __wrappedgconf2TYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
#define SUPER() ADDED_FUNCTIONS()
#endif // __wrappedgconf2TYPES_H_
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgconf2UNDEFS_H_
#define __wrappedgconf2UNDEFS_H_
#endif // __wrappedgconf2UNDEFS_H_
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgdkpixbuf2DEFS_H_
#define __wrappedgdkpixbuf2DEFS_H_
#endif // __wrappedgdkpixbuf2DEFS_H_
@@ -0,0 +1,19 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgdkpixbuf2TYPES_H_
#define __wrappedgdkpixbuf2TYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
typedef void* (*pFpiiiiiipp_t)(void*, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, void*, void*);
#define SUPER() ADDED_FUNCTIONS() \
GO(gdk_pixbuf_new_from_data, pFpiiiiiipp_t)
#endif // __wrappedgdkpixbuf2TYPES_H_
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgdkpixbuf2UNDEFS_H_
#define __wrappedgdkpixbuf2UNDEFS_H_
#endif // __wrappedgdkpixbuf2UNDEFS_H_
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgdkx112DEFS_H_
#define __wrappedgdkx112DEFS_H_
#endif // __wrappedgdkx112DEFS_H_
@@ -0,0 +1,29 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgdkx112TYPES_H_
#define __wrappedgdkx112TYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
typedef void (*vFpp_t)(void*, void*);
typedef int64_t (*iFpp_t)(void*, void*);
typedef void (*vFppp_t)(void*, void*, void*);
typedef int64_t (*iFiipp_t)(int64_t, int64_t, void*, void*);
typedef int64_t (*iFiippp_t)(int64_t, int64_t, void*, void*, void*);
#define SUPER() ADDED_FUNCTIONS() \
GO(gdk_init, vFpp_t) \
GO(gdk_init_check, iFpp_t) \
GO(gdk_event_handler_set, vFppp_t) \
GO(gdk_window_add_filter, vFppp_t) \
GO(gdk_window_remove_filter, vFppp_t) \
GO(gdk_input_add, iFiipp_t) \
GO(gdk_input_add_full, iFiippp_t)
#endif // __wrappedgdkx112TYPES_H_
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgdkx112UNDEFS_H_
#define __wrappedgdkx112UNDEFS_H_
#endif // __wrappedgdkx112UNDEFS_H_
+8
View File
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgio2DEFS_H_
#define __wrappedgio2DEFS_H_
#endif // __wrappedgio2DEFS_H_
+81
View File
@@ -0,0 +1,81 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgio2TYPES_H_
#define __wrappedgio2TYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
typedef void (*vFppp_t)(void*, void*, void*);
typedef void (*vFippp_t)(int64_t, void*, void*, void*);
typedef void (*vFppip_t)(void*, void*, int64_t, void*);
typedef void (*vFpppp_t)(void*, void*, void*, void*);
typedef uint64_t (*uFpppp_t)(void*, void*, void*, void*);
typedef uintptr_t (*LFpppp_t)(void*, void*, void*, void*);
typedef void* (*pFpppp_t)(void*, void*, void*, void*);
typedef void (*vFpippp_t)(void*, int64_t, void*, void*, void*);
typedef void (*vFppipV_t)(void*, void*, int64_t, void*, ...);
typedef void (*vFppipA_t)(void*, void*, int64_t, void*, va_list);
typedef void (*vFpipppp_t)(void*, int64_t, void*, void*, void*, void*);
typedef void (*vFiippppV_t)(int64_t, int64_t, void*, void*, void*, void*, ...);
typedef void (*vFiupippp_t)(int64_t, uint64_t, void*, int64_t, void*, void*, void*);
typedef void (*vFippippp_t)(int64_t, void*, void*, int64_t, void*, void*, void*);
typedef void (*vFppipppp_t)(void*, void*, int64_t, void*, void*, void*, void*);
typedef void (*vFpppuipV_t)(void*, void*, void*, uint64_t, int64_t, void*, ...);
typedef uint64_t (*uFipipppp_t)(int64_t, void*, int64_t, void*, void*, void*, void*);
typedef uint64_t (*uFppipppp_t)(void*, void*, int64_t, void*, void*, void*, void*);
typedef uint64_t (*uFppppppp_t)(void*, void*, void*, void*, void*, void*, void*);
typedef void* (*pFpppuipV_t)(void*, void*, void*, uint64_t, int64_t, void*, ...);
typedef void (*vFppiipppp_t)(void*, void*, int64_t, int64_t, void*, void*, void*, void*);
typedef void (*vFpppiippp_t)(void*, void*, void*, int64_t, int64_t, void*, void*, void*);
typedef uint64_t (*uFipippppp_t)(int64_t, void*, int64_t, void*, void*, void*, void*, void*);
typedef void (*vFiippppppp_t)(int64_t, int64_t, void*, void*, void*, void*, void*, void*, void*);
typedef void (*vFpippppppp_t)(void*, int64_t, void*, void*, void*, void*, void*, void*, void*);
typedef void (*vFpppiipppp_t)(void*, void*, void*, int64_t, int64_t, void*, void*, void*, void*);
typedef void* (*pFiippppppp_t)(int64_t, int64_t, void*, void*, void*, void*, void*, void*, void*);
typedef uint64_t (*uFppppppippp_t)(void*, void*, void*, void*, void*, void*, int64_t, void*, void*, void*);
typedef void (*vFpppppppiippp_t)(void*, void*, void*, void*, void*, void*, void*, int64_t, int64_t, void*, void*, void*);
#define SUPER() ADDED_FUNCTIONS() \
GO(g_simple_async_result_set_op_res_gpointer, vFppp_t) \
GO(g_bus_get, vFippp_t) \
GO(g_simple_async_result_run_in_thread, vFppip_t) \
GO(g_dbus_connection_close, vFpppp_t) \
GO(g_dbus_connection_flush, vFpppp_t) \
GO(g_simple_async_report_gerror_in_idle, vFpppp_t) \
GO(g_simple_async_report_take_gerror_in_idle, vFpppp_t) \
GO(g_dbus_connection_add_filter, uFpppp_t) \
GO(g_cancellable_connect, LFpppp_t) \
GO(g_simple_async_result_new, pFpppp_t) \
GO(g_simple_async_result_new_from_error, pFpppp_t) \
GO(g_simple_async_result_new_take_error, pFpppp_t) \
GO(g_async_initable_init_async, vFpippp_t) \
GO(g_simple_async_result_set_error, vFppipV_t) \
GO(g_simple_async_result_set_error_va, vFppipA_t) \
GO(g_dbus_connection_new_for_address, vFpipppp_t) \
GO(g_async_initable_new_async, vFiippppV_t) \
GO(g_async_initable_newv_async, vFiupippp_t) \
GO(g_async_initable_new_valist_async, vFippippp_t) \
GO(g_dbus_connection_new, vFppipppp_t) \
GO(g_simple_async_report_error_in_idle, vFpppuipV_t) \
GO(g_bus_watch_name, uFipipppp_t) \
GO(g_bus_own_name_on_connection, uFppipppp_t) \
GO(g_bus_watch_name_on_connection, uFppipppp_t) \
GO(g_dbus_connection_register_object, uFppppppp_t) \
GO(g_simple_async_result_new_error, pFpppuipV_t) \
GO(g_dbus_connection_send_message_with_reply, vFppiipppp_t) \
GO(g_dbus_proxy_call, vFpppiippp_t) \
GO(g_bus_own_name, uFipippppp_t) \
GO(g_dbus_proxy_new_for_bus, vFiippppppp_t) \
GO(g_dbus_proxy_new, vFpippppppp_t) \
GO(g_dbus_proxy_call_with_unix_fd_list, vFpppiipppp_t) \
GO(g_dbus_object_manager_client_new_for_bus_sync, pFiippppppp_t) \
GO(g_dbus_connection_signal_subscribe, uFppppppippp_t) \
GO(g_dbus_connection_call, vFpppppppiippp_t)
#endif // __wrappedgio2TYPES_H_
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgio2UNDEFS_H_
#define __wrappedgio2UNDEFS_H_
#endif // __wrappedgio2UNDEFS_H_
+8
View File
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedglib2DEFS_H_
#define __wrappedglib2DEFS_H_
#endif // __wrappedglib2DEFS_H_
+158
View File
@@ -0,0 +1,158 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedglib2TYPES_H_
#define __wrappedglib2TYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
typedef void (*vFp_t)(void*);
typedef void* (*pFp_t)(void*);
typedef void (*vFpp_t)(void*, void*);
typedef void (*vFpV_t)(void*, ...);
typedef int64_t (*iFpp_t)(void*, void*);
typedef int64_t (*iFpV_t)(void*, ...);
typedef uint64_t (*uFpp_t)(void*, void*);
typedef void* (*pFup_t)(uint64_t, void*);
typedef void* (*pFpu_t)(void*, uint64_t);
typedef void* (*pFpp_t)(void*, void*);
typedef void* (*pFpV_t)(void*, ...);
typedef void* (*pFpA_t)(void*, va_list);
typedef void (*vFppp_t)(void*, void*, void*);
typedef void (*vFppV_t)(void*, void*, ...);
typedef void (*vFppA_t)(void*, void*, va_list);
typedef int64_t (*iFppp_t)(void*, void*, void*);
typedef int64_t (*iFppV_t)(void*, void*, ...);
typedef uint64_t (*uFipp_t)(int64_t, void*, void*);
typedef uint64_t (*uFupp_t)(uint64_t, void*, void*);
typedef uint64_t (*uFppp_t)(void*, void*, void*);
typedef void* (*pFppp_t)(void*, void*, void*);
typedef void* (*pFppV_t)(void*, void*, ...);
typedef void (*vFpipV_t)(void*, int64_t, void*, ...);
typedef void (*vFpipA_t)(void*, int64_t, void*, va_list);
typedef void (*vFpupp_t)(void*, uint64_t, void*, void*);
typedef void (*vFpppp_t)(void*, void*, void*, void*);
typedef int64_t (*iFpLpp_t)(void*, uintptr_t, void*, void*);
typedef int64_t (*iFpLpV_t)(void*, uintptr_t, void*, ...);
typedef uint64_t (*uFippp_t)(int64_t, void*, void*, void*);
typedef uint64_t (*uFpipp_t)(void*, int64_t, void*, void*);
typedef void* (*pFpipV_t)(void*, int64_t, void*, ...);
typedef void* (*pFpipA_t)(void*, int64_t, void*, va_list);
typedef void* (*pFpupp_t)(void*, uint64_t, void*, void*);
typedef void* (*pFppip_t)(void*, void*, int64_t, void*);
typedef void* (*pFpppp_t)(void*, void*, void*, void*);
typedef void (*vFpiLpp_t)(void*, int64_t, uintptr_t, void*, void*);
typedef void (*vFppipV_t)(void*, void*, int64_t, void*, ...);
typedef uint64_t (*uFiippp_t)(int64_t, int64_t, void*, void*, void*);
typedef uint64_t (*uFiuppp_t)(int64_t, uint64_t, void*, void*, void*);
typedef int64_t (*iFpupppp_t)(void*, uint64_t, void*, void*, void*, void*);
typedef uint64_t (*uFpiippp_t)(void*, int64_t, int64_t, void*, void*, void*);
typedef void* (*pFppuipp_t)(void*, void*, uint64_t, int64_t, void*, void*);
typedef void* (*pFppLiiip_t)(void*, void*, uintptr_t, int64_t, int64_t, int64_t, void*);
typedef int64_t (*iFpppipppp_t)(void*, void*, void*, int64_t, void*, void*, void*, void*);
typedef int64_t (*iFpppipppppp_t)(void*, void*, void*, int64_t, void*, void*, void*, void*, void*, void*);
typedef int64_t (*iFpppippppppp_t)(void*, void*, void*, int64_t, void*, void*, void*, void*, void*, void*, void*);
#define SUPER() ADDED_FUNCTIONS() \
GO(g_atexit, vFp_t) \
GO(g_completion_new, pFp_t) \
GO(g_main_context_get_poll_func, pFp_t) \
GO(g_private_new, pFp_t) \
GO(g_ptr_array_new_with_free_func, pFp_t) \
GO(g_set_print_handler, pFp_t) \
GO(g_set_printerr_handler, pFp_t) \
GO(g_array_set_clear_func, vFpp_t) \
GO(g_array_sort, vFpp_t) \
GO(g_completion_set_compare, vFpp_t) \
GO(g_list_free_full, vFpp_t) \
GO(g_main_context_set_poll_func, vFpp_t) \
GO(g_ptr_array_set_free_func, vFpp_t) \
GO(g_ptr_array_sort, vFpp_t) \
GO(g_source_set_funcs, vFpp_t) \
GO(g_thread_foreach, vFpp_t) \
GO(g_print, vFpV_t) \
GO(g_printerr, vFpV_t) \
GO(g_source_remove_by_funcs_user_data, iFpp_t) \
GO(g_vprintf, iFpp_t) \
GO(g_printf, iFpV_t) \
GO(g_idle_add, uFpp_t) \
GO(g_printf_string_upper_bound, uFpp_t) \
GO(g_ptr_array_new_full, pFup_t) \
GO(g_source_new, pFpu_t) \
GO(g_hash_table_new, pFpp_t) \
GO(g_list_sort, pFpp_t) \
GO(g_log_set_default_handler, pFpp_t) \
GO(g_slist_sort, pFpp_t) \
GO(g_strdup_vprintf, pFpp_t) \
GO(g_build_filename, pFpV_t) \
GO(g_markup_printf_escaped, pFpV_t) \
GO(g_strdup_printf, pFpV_t) \
GO(g_strjoin, pFpV_t) \
GO(g_variant_new, pFpV_t) \
GO(g_markup_vprintf_escaped, pFpA_t) \
GO(g_strjoinv, pFpA_t) \
GO(g_variant_new_parsed_va, pFpA_t) \
GO(g_array_sort_with_data, vFppp_t) \
GO(g_hash_table_foreach, vFppp_t) \
GO(g_ptr_array_foreach, vFppp_t) \
GO(g_ptr_array_sort_with_data, vFppp_t) \
GO(g_static_private_set, vFppp_t) \
GO(g_string_append_printf, vFppV_t) \
GO(g_string_printf, vFppV_t) \
GO(g_variant_get, vFppV_t) \
GO(g_string_append_vprintf, vFppA_t) \
GO(g_string_vprintf, vFppA_t) \
GO(g_vasprintf, iFppp_t) \
GO(g_vfprintf, iFppp_t) \
GO(g_vsprintf, iFppp_t) \
GO(g_fprintf, iFppV_t) \
GO(g_sprintf, iFppV_t) \
GO(g_child_watch_add, uFipp_t) \
GO(g_timeout_add, uFupp_t) \
GO(g_timeout_add_seconds, uFupp_t) \
GO(g_hash_table_foreach_remove, uFppp_t) \
GO(g_hash_table_foreach_steal, uFppp_t) \
GO(g_hash_table_find, pFppp_t) \
GO(g_list_find_custom, pFppp_t) \
GO(g_list_sort_with_data, pFppp_t) \
GO(g_queue_find_custom, pFppp_t) \
GO(g_slist_find_custom, pFppp_t) \
GO(g_slist_foreach, pFppp_t) \
GO(g_slist_insert_sorted, pFppp_t) \
GO(g_slist_sort_with_data, pFppp_t) \
GO(g_variant_new_va, pFppp_t) \
GO(g_build_path, pFppV_t) \
GO(g_log, vFpipV_t) \
GO(g_logv, vFpipA_t) \
GO(g_datalist_id_set_data_full, vFpupp_t) \
GO(g_source_set_callback, vFpppp_t) \
GO(g_vsnprintf, iFpLpp_t) \
GO(g_snprintf, iFpLpV_t) \
GO(g_idle_add_full, uFippp_t) \
GO(g_io_add_watch, uFpipp_t) \
GO(g_log_set_handler, uFpipp_t) \
GO(g_error_new, pFpipV_t) \
GO(g_error_new_valist, pFpipA_t) \
GO(g_datalist_id_dup_data, pFpupp_t) \
GO(g_thread_create, pFppip_t) \
GO(g_hash_table_new_full, pFpppp_t) \
GO(g_slist_insert_sorted_with_data, pFpppp_t) \
GO(g_qsort_with_data, vFpiLpp_t) \
GO(g_set_error, vFppipV_t) \
GO(g_child_watch_add_full, uFiippp_t) \
GO(g_timeout_add_full, uFiuppp_t) \
GO(g_timeout_add_seconds_full, uFiuppp_t) \
GO(g_datalist_id_replace_data, iFpupppp_t) \
GO(g_io_add_watch_full, uFpiippp_t) \
GO(g_variant_new_from_data, pFppuipp_t) \
GO(g_thread_create_full, pFppLiiip_t) \
GO(g_spawn_async, iFpppipppp_t) \
GO(g_spawn_sync, iFpppipppppp_t) \
GO(g_spawn_async_with_pipes, iFpppippppppp_t)
#endif // __wrappedglib2TYPES_H_
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedglib2UNDEFS_H_
#define __wrappedglib2UNDEFS_H_
#endif // __wrappedglib2UNDEFS_H_
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgmodule2DEFS_H_
#define __wrappedgmodule2DEFS_H_
#endif // __wrappedgmodule2DEFS_H_
@@ -0,0 +1,17 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgmodule2TYPES_H_
#define __wrappedgmodule2TYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
#define SUPER() ADDED_FUNCTIONS()
#endif // __wrappedgmodule2TYPES_H_
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgmodule2UNDEFS_H_
#define __wrappedgmodule2UNDEFS_H_
#endif // __wrappedgmodule2UNDEFS_H_
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgobject2DEFS_H_
#define __wrappedgobject2DEFS_H_
#endif // __wrappedgobject2DEFS_H_
@@ -0,0 +1,75 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgobject2TYPES_H_
#define __wrappedgobject2TYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
typedef void* (*pFp_t)(void*);
typedef int64_t (*iFpp_t)(void*, void*);
typedef void* (*pFpp_t)(void*, void*);
typedef void (*vFiip_t)(int64_t, int64_t, void*);
typedef void (*vFLLp_t)(uintptr_t, uintptr_t, void*);
typedef void (*vFppV_t)(void*, void*, ...);
typedef void (*vFppA_t)(void*, void*, va_list);
typedef uintptr_t (*LFppp_t)(void*, void*, void*);
typedef void* (*pFLpV_t)(uintptr_t, void*, ...);
typedef void* (*pFLpA_t)(uintptr_t, void*, va_list);
typedef void* (*pFppp_t)(void*, void*, void*);
typedef void* (*pFppV_t)(void*, void*, ...);
typedef void (*vFpuuV_t)(void*, uint64_t, uint64_t, ...);
typedef void (*vFpupp_t)(void*, uint64_t, void*, void*);
typedef void (*vFpupA_t)(void*, uint64_t, void*, va_list);
typedef void (*vFpppp_t)(void*, void*, void*, void*);
typedef uintptr_t (*LFLppi_t)(uintptr_t, void*, void*, int64_t);
typedef uintptr_t (*LFupppp_t)(uint64_t, void*, void*, void*, void*);
typedef uintptr_t (*LFLpppi_t)(uintptr_t, void*, void*, void*, int64_t);
typedef uintptr_t (*LFppppi_t)(void*, void*, void*, void*, int64_t);
typedef uintptr_t (*LFpppppu_t)(void*, void*, void*, void*, void*, uint64_t);
typedef uint64_t (*uFpiupppp_t)(void*, int64_t, uint64_t, void*, void*, void*, void*);
typedef uintptr_t (*LFLpLpLpi_t)(uintptr_t, void*, uintptr_t, void*, uintptr_t, void*, int64_t);
typedef uintptr_t (*LFpiupppp_t)(void*, int64_t, uint64_t, void*, void*, void*, void*);
typedef uint64_t (*uFpLiupppLuV_t)(void*, uintptr_t, int64_t, uint64_t, void*, void*, void*, uintptr_t, uint64_t, ...);
typedef uint64_t (*uFpLippppLup_t)(void*, uintptr_t, int64_t, void*, void*, void*, void*, uintptr_t, uint64_t, void*);
typedef uint64_t (*uFpLippppLuA_t)(void*, uintptr_t, int64_t, void*, void*, void*, void*, uintptr_t, uint64_t, va_list);
#define SUPER() ADDED_FUNCTIONS() \
GO(g_type_class_peek_parent, pFp_t) \
GO(g_param_type_register_static, iFpp_t) \
GO(g_value_array_sort, pFpp_t) \
GO(g_value_register_transform_func, vFiip_t) \
GO(g_type_add_interface_static, vFLLp_t) \
GO(g_object_get, vFppV_t) \
GO(g_object_set, vFppV_t) \
GO(g_object_get_valist, vFppA_t) \
GO(g_object_set_valist, vFppA_t) \
GO(g_boxed_type_register_static, LFppp_t) \
GO(g_object_new, pFLpV_t) \
GO(g_object_new_valist, pFLpA_t) \
GO(g_value_array_sort_with_data, pFppp_t) \
GO(g_object_connect, pFppV_t) \
GO(g_signal_emit, vFpuuV_t) \
GO(g_param_spec_set_qdata_full, vFpupp_t) \
GO(g_signal_emit_valist, vFpupA_t) \
GO(g_object_set_data_full, vFpppp_t) \
GO(g_type_register_static, LFLppi_t) \
GO(g_signal_add_emission_hook, LFupppp_t) \
GO(g_type_register_fundamental, LFLpppi_t) \
GO(g_signal_connect_object, LFppppi_t) \
GO(g_signal_connect_data, LFpppppu_t) \
GO(g_signal_handlers_block_matched, uFpiupppp_t) \
GO(g_signal_handlers_disconnect_matched, uFpiupppp_t) \
GO(g_signal_handlers_unblock_matched, uFpiupppp_t) \
GO(g_type_register_static_simple, LFLpLpLpi_t) \
GO(g_signal_handler_find, LFpiupppp_t) \
GO(g_signal_new, uFpLiupppLuV_t) \
GO(g_signal_newv, uFpLippppLup_t) \
GO(g_signal_new_valist, uFpLippppLuA_t)
#endif // __wrappedgobject2TYPES_H_
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgobject2UNDEFS_H_
#define __wrappedgobject2UNDEFS_H_
#endif // __wrappedgobject2UNDEFS_H_
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgthread2DEFS_H_
#define __wrappedgthread2DEFS_H_
#endif // __wrappedgthread2DEFS_H_
@@ -0,0 +1,20 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgthread2TYPES_H_
#define __wrappedgthread2TYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
typedef void (*vFp_t)(void*);
#define SUPER() ADDED_FUNCTIONS() \
GO(g_thread_init, vFp_t) \
GO(g_thread_init_with_errorcheck_mutexes, vFp_t)
#endif // __wrappedgthread2TYPES_H_
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgthread2UNDEFS_H_
#define __wrappedgthread2UNDEFS_H_
#endif // __wrappedgthread2UNDEFS_H_
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgtkx112DEFS_H_
#define __wrappedgtkx112DEFS_H_
#endif // __wrappedgtkx112DEFS_H_
@@ -0,0 +1,98 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedgtkx112TYPES_H_
#define __wrappedgtkx112TYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
typedef float (*fFp_t)(void*);
typedef void* (*pFi_t)(int64_t);
typedef void (*vFpp_t)(void*, void*);
typedef int64_t (*iFpp_t)(void*, void*);
typedef void* (*pFiV_t)(int64_t, ...);
typedef void* (*pFpi_t)(void*, int64_t);
typedef void (*vFppp_t)(void*, void*, void*);
typedef void (*vFppV_t)(void*, void*, ...);
typedef void (*vFppA_t)(void*, void*, va_list);
typedef uint64_t (*uFupp_t)(uint64_t, void*, void*);
typedef void (*vFppiV_t)(void*, void*, int64_t, ...);
typedef void (*vFppup_t)(void*, void*, uint64_t, void*);
typedef void (*vFpppp_t)(void*, void*, void*, void*);
typedef int64_t (*iFpppp_t)(void*, void*, void*, void*);
typedef uintptr_t (*LFpppp_t)(void*, void*, void*, void*);
typedef void (*vFpippp_t)(void*, int64_t, void*, void*, void*);
typedef void (*vFppupp_t)(void*, void*, uint64_t, void*, void*);
typedef void (*vFppppp_t)(void*, void*, void*, void*, void*);
typedef void (*vFpuipuV_t)(void*, uint64_t, int64_t, void*, uint64_t, ...);
typedef int64_t (*iFppuppp_t)(void*, void*, uint64_t, void*, void*, void*);
typedef int64_t (*iFpppppp_t)(void*, void*, void*, void*, void*, void*);
typedef uint64_t (*uFiipppp_t)(int64_t, int64_t, void*, void*, void*, void*);
typedef void (*vFpppppuu_t)(void*, void*, void*, void*, void*, uint64_t, uint64_t);
typedef void* (*pFppppppi_t)(void*, void*, void*, void*, void*, void*, int64_t);
typedef void* (*pFppppppp_t)(void*, void*, void*, void*, void*, void*, void*);
typedef uintptr_t (*LFppppppii_t)(void*, void*, void*, void*, void*, void*, int64_t, int64_t);
typedef void* (*pFpppppppi_t)(void*, void*, void*, void*, void*, void*, void*, int64_t);
typedef void* (*pFpippppppp_t)(void*, int64_t, void*, void*, void*, void*, void*, void*, void*);
typedef void* (*pFpipppppppi_t)(void*, int64_t, void*, void*, void*, void*, void*, void*, void*, int64_t);
#define SUPER() ADDED_FUNCTIONS() \
GO(gtk_spin_button_get_value_as_float, fFp_t) \
GO(gtk_type_class, pFi_t) \
GO(gtk_builder_connect_signals, vFpp_t) \
GO(gtk_init, vFpp_t) \
GO(gtk_init_check, iFpp_t) \
GO(gtk_type_unique, iFpp_t) \
GO(gtk_list_store_new, pFiV_t) \
GO(gtk_tree_store_new, pFiV_t) \
GO(gtk_type_check_object_cast, pFpi_t) \
GO(gtk_builder_connect_signals_full, vFppp_t) \
GO(gtk_clipboard_request_text, vFppp_t) \
GO(gtk_container_forall, vFppp_t) \
GO(gtk_container_foreach, vFppp_t) \
GO(gtk_menu_attach_to_widget, vFppp_t) \
GO(gtk_tree_model_foreach, vFppp_t) \
GO(gtk_dialog_add_buttons, vFppV_t) \
GO(gtk_list_store_set, vFppV_t) \
GO(gtk_message_dialog_format_secondary_markup, vFppV_t) \
GO(gtk_message_dialog_format_secondary_text, vFppV_t) \
GO(gtk_tree_model_get, vFppV_t) \
GO(gtk_widget_style_get, vFppV_t) \
GO(gtk_list_store_set_valist, vFppA_t) \
GO(gtk_tree_model_get_valist, vFppA_t) \
GO(gtk_widget_style_get_valist, vFppA_t) \
GO(gtk_timeout_add, uFupp_t) \
GO(gtk_list_store_insert_with_values, vFppiV_t) \
GO(gtk_action_group_add_actions, vFppup_t) \
GO(gtk_clipboard_request_contents, vFpppp_t) \
GO(gtk_object_set_data_full, vFpppp_t) \
GO(gtk_stock_set_translate_func, vFpppp_t) \
GO(gtk_tree_sortable_set_default_sort_func, vFpppp_t) \
GO(gtk_tree_view_set_search_equal_func, vFpppp_t) \
GO(gtk_text_iter_backward_find_char, iFpppp_t) \
GO(gtk_text_iter_forward_find_char, iFpppp_t) \
GO(gtk_signal_connect, LFpppp_t) \
GO(gtk_tree_sortable_set_sort_func, vFpippp_t) \
GO(gtk_action_group_add_actions_full, vFppupp_t) \
GO(gtk_cell_layout_set_cell_data_func, vFppppp_t) \
GO(gtk_binding_entry_add_signal, vFpuipuV_t) \
GO(gtk_clipboard_set_with_data, iFppuppp_t) \
GO(gtk_clipboard_set_with_owner, iFppuppp_t) \
GO(gtk_init_with_args, iFpppppp_t) \
GO(gtk_input_add_full, uFiipppp_t) \
GO(gtk_menu_popup, vFpppppuu_t) \
GO(gtk_toolbar_insert_stock, pFppppppi_t) \
GO(gtk_toolbar_append_item, pFppppppp_t) \
GO(gtk_toolbar_prepend_item, pFppppppp_t) \
GO(gtk_signal_connect_full, LFppppppii_t) \
GO(gtk_toolbar_insert_item, pFpppppppi_t) \
GO(gtk_toolbar_append_element, pFpippppppp_t) \
GO(gtk_toolbar_prepend_element, pFpippppppp_t) \
GO(gtk_toolbar_insert_element, pFpipppppppi_t)
#endif // __wrappedgtkx112TYPES_H_
Loaded 100 of 227 files, more files were not shown because too many files have changed in this diff. Show more