mirror of
https://github.com/ptitSeb/box64.git
synced 2026-11-08 17:39:19 -10:00
Compare commits
104
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe90260cee | ||
|
|
841003bc47 | ||
|
|
27cf5c81b2 | ||
|
|
323783bf49 | ||
|
|
fbd9604dc1 | ||
|
|
5494d417c0 | ||
|
|
472037cba2 | ||
|
|
1b19d8b909 | ||
|
|
c2909c32ab | ||
|
|
a7c0c01bf4 | ||
|
|
d80226ec61 | ||
|
|
da81ba5be8 | ||
|
|
f81874277c | ||
|
|
d93b97ee92 | ||
|
|
4812d20da5 | ||
|
|
734e7cd47c | ||
|
|
d052b35c40 | ||
|
|
2bd3a3ccfa | ||
|
|
1886c454ca | ||
|
|
91ee1afe24 | ||
|
|
d867f578df | ||
|
|
b48ba048ed | ||
|
|
35a21d8932 | ||
|
|
81ec174e2a | ||
|
|
400ea800d9 | ||
|
|
0e1215268a | ||
|
|
a72d257443 | ||
|
|
6a99a4b359 | ||
|
|
b6764d1d6f | ||
|
|
d5e105ce62 | ||
|
|
45ee1e3c3c | ||
|
|
b1d0dde0b4 | ||
|
|
cb06d28383 | ||
|
|
36bfcd21d4 | ||
|
|
faa48276e5 | ||
|
|
8e5d32430a | ||
|
|
ac2d5b17dd | ||
|
|
0e2c63d9fb | ||
|
|
71b446774c | ||
|
|
dac71e9f7b | ||
|
|
e1a2230e9c | ||
|
|
82bd4431e6 | ||
|
|
7262288502 | ||
|
|
bcb0bdea77 | ||
|
|
4ca58d1f99 | ||
|
|
0c27b82ff3 | ||
|
|
289deb3655 | ||
|
|
8d69c17839 | ||
|
|
348cb57240 | ||
|
|
46f71f3947 | ||
|
|
0ba4b04078 | ||
|
|
5a5f572162 | ||
|
|
fb5bc122cc | ||
|
|
4c328d0fca | ||
|
|
dbce2758b2 | ||
|
|
837f7edd55 | ||
|
|
f054fb3a5f | ||
|
|
96831b144c | ||
|
|
d75116dab7 | ||
|
|
8da46ee305 | ||
|
|
4cac721e74 | ||
|
|
3fda41cbf6 | ||
|
|
053d5e9b8d | ||
|
|
40cb14bf31 | ||
|
|
27d18e4169 | ||
|
|
5403002a36 | ||
|
|
22f1a6c5ca | ||
|
|
783e9a4b74 | ||
|
|
202a067a61 | ||
|
|
f2d1a8bc70 | ||
|
|
b6bc7922b3 | ||
|
|
7e4af27ba7 | ||
|
|
06bbf93bf8 | ||
|
|
e08bdd644b | ||
|
|
1c5ddfafcd | ||
|
|
0f4db4c230 | ||
|
|
960ce86289 | ||
|
|
b2bd3103d8 | ||
|
|
745fd1b702 | ||
|
|
6df1b65249 | ||
|
|
510f8d45e8 | ||
|
|
c5d328a5da | ||
|
|
1430c811cd | ||
|
|
ec2eadd893 | ||
|
|
56c272c17a | ||
|
|
6f92db542b | ||
|
|
8531750631 | ||
|
|
9414ece323 | ||
|
|
c64cb5b92b | ||
|
|
2b1e12dafd | ||
|
|
b4ca2be9e0 | ||
|
|
203de52d71 | ||
|
|
c48333db44 | ||
|
|
e3552befe9 | ||
|
|
6141421f92 | ||
|
|
911ecc4489 | ||
|
|
63ab450d87 | ||
|
|
bcc29168cd | ||
|
|
4a9b0128d7 | ||
|
|
6cc56ac5f7 | ||
|
|
f53c967e18 | ||
|
|
b309933571 | ||
|
|
c7e8044f92 | ||
|
|
29720048e2 |
No files matched your search
Executable
+24
@@ -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
|
||||
+49
-2
@@ -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()
|
||||
@@ -129,6 +152,7 @@ set(ELFLOADER_SRC
|
||||
"${BOX64_ROOT}/src/box64context.c"
|
||||
"${BOX64_ROOT}/src/build_info.c"
|
||||
"${BOX64_ROOT}/src/custommem.c"
|
||||
"${BOX64_ROOT}/src/mailbox.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec.c"
|
||||
"${BOX64_ROOT}/src/elfs/elfloader.c"
|
||||
"${BOX64_ROOT}/src/elfs/elfparser.c"
|
||||
@@ -180,6 +204,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 +223,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 +257,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 +265,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 +302,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 +321,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"
|
||||
@@ -415,7 +462,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()
|
||||
|
||||
@@ -1,5 +1,33 @@
|
||||
Current Version
|
||||
======
|
||||
* 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
|
||||
======
|
||||
|
||||
@@ -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
@@ -4,6 +4,9 @@
|
||||
Linux Userspace x86_64 Emulator with a twist
|
||||
|
||||
----
|
||||

|
||||
|
||||
[中文](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/))
|
||||
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
# box64
|
||||
|
||||

|
||||
Linux上用户空间的x86_64应用模拟器
|
||||
|
||||
----
|
||||

|
||||
|
||||
[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,请不要忘记提及!)
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
+30
-13
@@ -6,6 +6,9 @@
|
||||
#include <signal.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#ifdef DYNAREC
|
||||
#include "dynarec/arm64_lock.h"
|
||||
#endif
|
||||
#include "box64context.h"
|
||||
#include "debug.h"
|
||||
#include "elfloader.h"
|
||||
@@ -123,11 +126,11 @@ static void init_mutexes(box64context_t* context)
|
||||
pthread_mutex_init(&context->mutex_once, &attr);
|
||||
pthread_mutex_init(&context->mutex_once2, &attr);
|
||||
pthread_mutex_init(&context->mutex_trace, &attr);
|
||||
#ifndef DYNAREC
|
||||
pthread_mutex_init(&context->mutex_lock, &attr);
|
||||
#else
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_init(&context->mutex_dyndump, &attr);
|
||||
#endif
|
||||
#else
|
||||
pthread_mutex_init(&context->mutex_lock, &attr);
|
||||
#endif
|
||||
pthread_mutex_init(&context->mutex_tls, &attr);
|
||||
pthread_mutex_init(&context->mutex_thread, &attr);
|
||||
pthread_mutex_init(&context->mutex_bridge, &attr);
|
||||
@@ -135,10 +138,24 @@ static void init_mutexes(box64context_t* context)
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
}
|
||||
|
||||
void startMailbox(void);
|
||||
void haltMailbox(void);
|
||||
static void atfork_prepare_box64context(void)
|
||||
{
|
||||
// semaphores will go in undetermined state
|
||||
haltMailbox();
|
||||
}
|
||||
static void atfork_parent_box64context(void)
|
||||
{
|
||||
// reinit mailbox only
|
||||
init_mutexes(my_context);
|
||||
startMailbox();
|
||||
}
|
||||
static void atfork_child_box64context(void)
|
||||
{
|
||||
// (re)init mutex if it was lock before the fork
|
||||
// reinit mutexes and mailbox
|
||||
init_mutexes(my_context);
|
||||
startMailbox();
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
@@ -169,9 +186,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();
|
||||
@@ -180,7 +197,7 @@ box64context_t *NewBox64Context(int argc)
|
||||
context->argv = (char**)calloc(context->argc+1, sizeof(char*));
|
||||
|
||||
init_mutexes(context);
|
||||
pthread_atfork(NULL, NULL, atfork_child_box64context);
|
||||
pthread_atfork(atfork_prepare_box64context, atfork_parent_box64context, atfork_child_box64context);
|
||||
|
||||
pthread_key_create(&context->tlskey, free_tlsdatasize);
|
||||
|
||||
@@ -273,11 +290,11 @@ void FreeBox64Context(box64context_t** context)
|
||||
pthread_mutex_destroy(&ctx->mutex_once);
|
||||
pthread_mutex_destroy(&ctx->mutex_once2);
|
||||
pthread_mutex_destroy(&ctx->mutex_trace);
|
||||
#ifndef DYNAREC
|
||||
pthread_mutex_destroy(&ctx->mutex_lock);
|
||||
#else
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_destroy(&ctx->mutex_dyndump);
|
||||
#endif
|
||||
#else
|
||||
pthread_mutex_destroy(&ctx->mutex_lock);
|
||||
#endif
|
||||
pthread_mutex_destroy(&ctx->mutex_tls);
|
||||
pthread_mutex_destroy(&ctx->mutex_thread);
|
||||
pthread_mutex_destroy(&ctx->mutex_bridge);
|
||||
|
||||
+1
-1
@@ -3,6 +3,6 @@
|
||||
|
||||
#define BOX64_MAJOR 0
|
||||
#define BOX64_MINOR 1
|
||||
#define BOX64_REVISION 4
|
||||
#define BOX64_REVISION 5
|
||||
|
||||
#endif //__BOX64_VERSION_H_
|
||||
+198
-158
@@ -32,8 +32,9 @@
|
||||
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];
|
||||
@@ -43,7 +44,6 @@ static uintptr_t box64_jmptbldefault0[1<<JMPTABL_SHIFT];
|
||||
#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;
|
||||
static int inited = 0;
|
||||
@@ -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,11 @@ 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);
|
||||
//pthread_mutex_lock(&mutex_mmap);
|
||||
#ifndef USE_MMAP
|
||||
void *p = NULL;
|
||||
if(posix_memalign(&p, box64_pagesize, size)) {
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
//pthread_mutex_unlock(&mutex_mmap);
|
||||
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", size);
|
||||
return 0;
|
||||
}
|
||||
@@ -444,7 +508,7 @@ 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);
|
||||
//pthread_mutex_unlock(&mutex_mmap);
|
||||
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", size);
|
||||
return 0;
|
||||
}
|
||||
@@ -459,17 +523,17 @@ 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);
|
||||
//pthread_mutex_unlock(&mutex_mmap);
|
||||
return (uintptr_t)p;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&mutex_mmap);
|
||||
//pthread_mutex_lock(&mutex_mmap);
|
||||
|
||||
uintptr_t ret = FindFreeDynarecMap(db, size);
|
||||
if(!ret)
|
||||
ret = AddNewDynarecMap(db, size);
|
||||
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
//pthread_mutex_unlock(&mutex_mmap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -479,7 +543,7 @@ 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);
|
||||
//pthread_mutex_lock(&mutex_mmap);
|
||||
#ifndef USE_MMAP
|
||||
free((void*)addr);
|
||||
#else
|
||||
@@ -491,12 +555,12 @@ 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);
|
||||
//pthread_mutex_unlock(&mutex_mmap);
|
||||
return;
|
||||
}
|
||||
pthread_mutex_lock(&mutex_mmap);
|
||||
//pthread_mutex_lock(&mutex_mmap);
|
||||
ActuallyFreeDynarecMap(db, addr, size);
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
//pthread_mutex_unlock(&mutex_mmap);
|
||||
}
|
||||
|
||||
dynablocklist_t* getDB(uintptr_t idx)
|
||||
@@ -526,17 +590,17 @@ void addDBFromAddressRange(uintptr_t addr, size_t size)
|
||||
int idx1 = (i )&((1<<DYNAMAP_SHIFT)-1);
|
||||
if(!dynmap123[idx3]) {
|
||||
dynablocklist_t*** p = (dynablocklist_t***)calloc(1<<DYNAMAP_SHIFT, sizeof(dynablocklist_t**));
|
||||
if(arm64_lock_storeifnull(&dynmap123[idx3], p)!=p)
|
||||
if(arm64_lock_storeifnull(&dynmap123[idx3], (uint64_t)p)!=(uint64_t)p)
|
||||
free(p);
|
||||
}
|
||||
if(!dynmap123[idx3][idx2]) {
|
||||
dynablocklist_t** p = (dynablocklist_t**)calloc(1<<DYNAMAP_SHIFT, sizeof(dynablocklist_t*));
|
||||
if(arm64_lock_storeifnull(&dynmap123[idx3][idx2], p)!=p)
|
||||
if(arm64_lock_storeifnull(&dynmap123[idx3][idx2], (uint64_t)p)!=(uint64_t)p)
|
||||
free(p);
|
||||
}
|
||||
if(!dynmap123[idx3][idx2][idx1]) {
|
||||
dynablocklist_t* p = NewDynablockList(i<<DYNAMAP_SHIFT, 1<<DYNAMAP_SHIFT, 0);
|
||||
if(arm64_lock_storeifnull(&dynmap123[idx3][idx2][idx1], p)!=p)
|
||||
if(arm64_lock_storeifnull(&dynmap123[idx3][idx2][idx1], (uint64_t)p)!=(uint64_t)p)
|
||||
FreeDynablockList(&p);
|
||||
}
|
||||
}
|
||||
@@ -565,13 +629,13 @@ void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy)
|
||||
if(destroy) {
|
||||
if(FreeRangeDynablock(dblist, addr, size) && 0) { // dblist is empty, check if we can delete more...
|
||||
// disabling this for now. It seems to cause random crash in Terraria
|
||||
if(!arm64_lock_storeifref(&dynmap123[idx3][idx2][idx1], NULL, dblist)) {
|
||||
if(!arm64_lock_storeifref(&dynmap123[idx3][idx2][idx1], 0, (uint64_t)dblist)) {
|
||||
dynablocklist_t** p = dynmap123[idx3][idx2];
|
||||
if(dynmapempty((void**)p)) {
|
||||
if(!arm64_lock_storeifref(&dynmap123[idx3][idx2], NULL, p)) {
|
||||
if(!arm64_lock_storeifref(&dynmap123[idx3][idx2], 0, (uint64_t)p)) {
|
||||
dynablocklist_t*** p2 = dynmap123[idx3];
|
||||
if(dynmapempty((void**)p2)) {
|
||||
if(!arm64_lock_storeifref(&dynmap123[idx3], NULL, p2)) {
|
||||
if(!arm64_lock_storeifref(&dynmap123[idx3], 0, (uint64_t)p2)) {
|
||||
free(p2);
|
||||
}
|
||||
}
|
||||
@@ -603,25 +667,25 @@ void addJumpTableIfDefault64(void* addr, void* jmp)
|
||||
uintptr_t*** tbl = (uintptr_t***)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t**));
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
|
||||
tbl[i] = box64_jmptbldefault1;
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3], tbl, box64_jmptbldefault2)!=tbl)
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3], (uint64_t)tbl, (uint64_t)box64_jmptbldefault2)!=(uint64_t)tbl)
|
||||
free(tbl);
|
||||
}
|
||||
if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1) {
|
||||
uintptr_t** tbl = (uintptr_t**)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t*));
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
|
||||
tbl[i] = box64_jmptbldefault0;
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2], tbl, box64_jmptbldefault1)!=tbl)
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2], (uint64_t)tbl, (uint64_t)box64_jmptbldefault1)!=(uint64_t)tbl)
|
||||
free(tbl);
|
||||
}
|
||||
if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0) {
|
||||
uintptr_t* tbl = (uintptr_t*)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
|
||||
tbl[i] = (uintptr_t)arm64_next;
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1], tbl, box64_jmptbldefault0)!=tbl)
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1], (uint64_t)tbl, (uint64_t)box64_jmptbldefault0)!=(uint64_t)tbl)
|
||||
free(tbl);
|
||||
}
|
||||
|
||||
arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1][idx0], jmp, arm64_next);
|
||||
arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1][idx0], (uint64_t)jmp, (uint64_t)arm64_next);
|
||||
}
|
||||
void setJumpTableDefault64(void* addr)
|
||||
{
|
||||
@@ -673,21 +737,21 @@ uintptr_t getJumpTableAddress64(uintptr_t addr)
|
||||
uintptr_t*** tbl = (uintptr_t***)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t**));
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
|
||||
tbl[i] = box64_jmptbldefault1;
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3], tbl, box64_jmptbldefault2)!=tbl)
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3], (uint64_t)tbl, (uint64_t)box64_jmptbldefault2)!=(uint64_t)tbl)
|
||||
free(tbl);
|
||||
}
|
||||
if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1) {
|
||||
uintptr_t** tbl = (uintptr_t**)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t*));
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
|
||||
tbl[i] = box64_jmptbldefault0;
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2], tbl, box64_jmptbldefault1)!=tbl)
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2], (uint64_t)tbl, (uint64_t)box64_jmptbldefault1)!=(uint64_t)tbl)
|
||||
free(tbl);
|
||||
}
|
||||
if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0) {
|
||||
uintptr_t* tbl = (uintptr_t*)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
|
||||
tbl[i] = (uintptr_t)arm64_next;
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1], tbl, box64_jmptbldefault0)!=tbl)
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1], (uint64_t)tbl, (uint64_t)box64_jmptbldefault0)!=(uint64_t)tbl)
|
||||
free(tbl);
|
||||
}
|
||||
|
||||
@@ -695,9 +759,9 @@ 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 internalProtectDB(uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "protectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||
dynarec_log(LOG_DEBUG, "internalProtectDB %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;
|
||||
@@ -719,32 +783,35 @@ void protectDBnolock(uintptr_t addr, uintptr_t size)
|
||||
}
|
||||
}
|
||||
|
||||
void protectDB(uintptr_t addr, size_t size)
|
||||
int internalIsprotectedDB(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);
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
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;
|
||||
}
|
||||
const uintptr_t ii = i&(MEMPROT_SIZE-1);
|
||||
uint8_t prot = kh_value(memprot, k)[ii];
|
||||
if(!(prot&PROT_DYNAREC)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Add the Write flag from an adress range, and mark all block as dirty
|
||||
// no log, as it can be executed inside a signal handler
|
||||
void unprotectDB(uintptr_t addr, size_t size)
|
||||
void internalUnprotectDB(uintptr_t addr, size_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "unprotectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||
dynarec_log(LOG_DEBUG, "internalUnprotectDB %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;
|
||||
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);
|
||||
@@ -760,20 +827,18 @@ void unprotectDB(uintptr_t addr, size_t size)
|
||||
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void updateProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
void internalUpdateProtection(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);
|
||||
dynarec_log(LOG_DEBUG, "internalUpdateProtection %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;
|
||||
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);
|
||||
@@ -804,16 +869,14 @@ void updateProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
}
|
||||
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)
|
||||
void internalSetProtection(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);
|
||||
dynarec_log(LOG_DEBUG, "internalSetProtection %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;
|
||||
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);
|
||||
@@ -826,16 +889,14 @@ void setProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
memset(kh_value(memprot, k)+start, prot|PROT_ALLOC, finish-start+1);
|
||||
i+=finish-start; // +1 from the "for" loop
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
void allocProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
void internalAllocProtection(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);
|
||||
dynarec_log(LOG_DEBUG, "internalAllocProtection %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;
|
||||
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);
|
||||
@@ -852,10 +913,9 @@ void allocProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
}
|
||||
i+=finish-start; // +1 from the "for" loop
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
void loadProtectionFromMap()
|
||||
void internalLoadProtectionFromMap()
|
||||
{
|
||||
char buf[500];
|
||||
FILE *f = fopen("/proc/self/maps", "r");
|
||||
@@ -868,7 +928,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);
|
||||
internalAllocProtection(s, e-s, prot);
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
@@ -882,12 +942,11 @@ static int blockempty(uint8_t* mem)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void freeProtection(uintptr_t addr, size_t size)
|
||||
void internalFreeProtection(uintptr_t addr, size_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "freeProtection %p:%p\n", (void*)addr, (void*)(addr+size-1));
|
||||
dynarec_log(LOG_DEBUG, "internalFreeProtection %p:%p\n", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
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);
|
||||
@@ -903,21 +962,15 @@ void freeProtection(uintptr_t addr, size_t size)
|
||||
i+=finish-start; // +1 from the "for" loop
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
uint32_t getProtection(uintptr_t addr)
|
||||
uint32_t internalGetProtection(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);
|
||||
return 0;
|
||||
}
|
||||
if (k == kh_end(memprot)) return 0;
|
||||
const uintptr_t idx = ((addr&0xffffffff)>>MEMPROT_SHIFT);
|
||||
uint32_t ret = kh_val(memprot, k)[idx];
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -969,20 +1022,14 @@ static uintptr_t maxFree(uintptr_t addr, uintptr_t sz)
|
||||
addr &= ~0xffffffffLL;
|
||||
} while(1);
|
||||
}
|
||||
void* find32bitBlock(size_t size)
|
||||
{
|
||||
return findBlockNearHint(LOWEST, size);
|
||||
}
|
||||
void* find47bitBlock(size_t size)
|
||||
void* internalFind47bitBlock(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,51 +1040,47 @@ 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;
|
||||
}
|
||||
void* find47bitBlockNearHint(void* hint, size_t size)
|
||||
void* internalFind47bitBlockNearHint(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;
|
||||
}
|
||||
void* findBlockNearHint(void* hint, size_t size)
|
||||
void* internalFindBlockNearHint(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;
|
||||
}
|
||||
void* internalFind32bitBlock(size_t size)
|
||||
{
|
||||
return internalFindBlockNearHint(LOWEST, size);
|
||||
}
|
||||
#undef LOWEST
|
||||
|
||||
int unlockCustommemMutex()
|
||||
@@ -1050,7 +1093,6 @@ int unlockCustommemMutex()
|
||||
ret|=(1<<B); \
|
||||
}
|
||||
GO(mutex_blocks, 0)
|
||||
GO(mutex_prot, 1)
|
||||
#ifdef DYNAREC
|
||||
GO(mutex_mmap, 2)
|
||||
#endif
|
||||
@@ -1065,7 +1107,6 @@ void relockCustommemMutex(int locks)
|
||||
pthread_mutex_lock(&A); \
|
||||
|
||||
GO(mutex_blocks, 0)
|
||||
GO(mutex_prot, 1)
|
||||
#ifdef DYNAREC
|
||||
GO(mutex_mmap, 2)
|
||||
#endif
|
||||
@@ -1078,7 +1119,6 @@ static void init_mutexes(void)
|
||||
pthread_mutexattr_init(&attr);
|
||||
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
|
||||
@@ -1146,6 +1186,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]) {
|
||||
@@ -1188,6 +1229,5 @@ void fini_custommem_helper(box64context_t *ctx)
|
||||
free(p_blocks[i].block);
|
||||
#endif
|
||||
free(p_blocks);
|
||||
pthread_mutex_destroy(&mutex_prot);
|
||||
pthread_mutex_destroy(&mutex_blocks);
|
||||
}
|
||||
@@ -88,7 +88,7 @@ arm64_lock_xchg:
|
||||
ret
|
||||
|
||||
arm64_lock_storeifnull:
|
||||
// address is x0, value is x1, x1 store to x0 only if [x0] is 0. return new [x0] value (so x1 or old value)
|
||||
// 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
|
||||
@@ -99,7 +99,7 @@ arm64_lock_storeifnull_exit:
|
||||
ret
|
||||
|
||||
arm64_lock_storeifref:
|
||||
// address is x0, value is x1, x1 store to x0 only if [x0] is x3. return new [x0] value (so x1 or old value)
|
||||
// address is x0, value is x1, x1 store to x0 only if [x0] is x2, return new [x0] value (so x1 or old value)
|
||||
ldaxr x3, [x0]
|
||||
cmp x2, x3
|
||||
bne arm64_lock_storeifref_exit
|
||||
|
||||
@@ -27,13 +27,13 @@ extern void arm64_lock_read_dq(uint64_t * a, uint64_t* b, void* addr);
|
||||
// STLXRD of ADDR, return 0 if ok, 1 if not
|
||||
extern int arm64_lock_write_dq(uint64_t a, uint64_t b, void* addr);
|
||||
|
||||
// Atomicaly exchange value at [p] with val, return old p
|
||||
// Atomically exchange value at [p] with val, return old p
|
||||
extern uintptr_t arm64_lock_xchg(void* p, uintptr_t val);
|
||||
|
||||
// Atomicaly store value to [p] only if [p] is NULL. Return new [p] value (so val or old)
|
||||
extern void* arm64_lock_storeifnull(void*p, void* val);
|
||||
// Atomically store val to [p] only if [p] is 0. Return new [p] value (so val or old)
|
||||
extern uint64_t arm64_lock_storeifnull(void* p, uint64_t val);
|
||||
|
||||
// Atomicaly store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
extern void* arm64_lock_storeifref(void*p, void* val, void* ref);
|
||||
// Atomically store val to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
extern uint64_t arm64_lock_storeifref(void* p, uint64_t val, uint64_t ref);
|
||||
|
||||
#endif //__ARM64_LOCK__H__
|
||||
#endif //__ARM64_LOCK__H__
|
||||
@@ -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
|
||||
|
||||
+24
-22
@@ -2,6 +2,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64context.h"
|
||||
@@ -81,7 +82,9 @@ void FreeDynablock(dynablock_t* db)
|
||||
// only the father free the DynarecMap
|
||||
if(!db->father) {
|
||||
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->block, db->size);
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
FreeDynarecMap(db, (uintptr_t)db->block, db->size);
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
free(db->sons);
|
||||
free(db->instsize);
|
||||
@@ -269,7 +272,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
|
||||
|
||||
if(!dynablocks->direct) {
|
||||
dynablock_t** p = (dynablock_t**)calloc(dynablocks->textsz, sizeof(dynablock_t*));
|
||||
if(arm64_lock_storeifnull(&dynablocks->direct, p)!=p)
|
||||
if(arm64_lock_storeifnull(&dynablocks->direct, (uint64_t)p) != (uint64_t)p)
|
||||
free(p); // someone already create the direct array, too late...
|
||||
}
|
||||
|
||||
@@ -278,7 +281,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
|
||||
|
||||
block = (dynablock_t*)calloc(1, sizeof(dynablock_t));
|
||||
block->parent = dynablocks;
|
||||
dynablock_t* tmp = (dynablock_t*)arm64_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], block);
|
||||
dynablock_t* tmp = (dynablock_t*)arm64_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], (uint64_t)block);
|
||||
if(tmp != block) {
|
||||
// a block appeard!
|
||||
free(block);
|
||||
@@ -290,6 +293,14 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
|
||||
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
|
||||
@@ -323,29 +334,26 @@ 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(sigsetjmp(&dynarec_jmpbuf, 1)) {
|
||||
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
void* ret = FillBlock64(block, filladdr);
|
||||
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);
|
||||
if(old!=block && old) {// put it back in place, strange things are happening here!
|
||||
void* old = (void*)arm64_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], 0, (uint64_t)block);
|
||||
if(old != block && old) {
|
||||
// put it back in place, strange things are happening here!
|
||||
dynarec_log(LOG_INFO, "Warning, a wild block appeared at %p: %p\n", (void*)addr, old);
|
||||
// doing nothing else, the block has not be writen
|
||||
// doing nothing else, the block has not been written
|
||||
}
|
||||
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) {
|
||||
int blocksz = block->x64_size;
|
||||
@@ -358,8 +366,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
dblist->maxsz = blocksz;
|
||||
}
|
||||
}
|
||||
lockDB();
|
||||
protectDBnolock((uintptr_t)block->x64_addr, block->x64_size);
|
||||
protectDB((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,7 +374,6 @@ 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);
|
||||
@@ -392,13 +398,11 @@ dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, dynablock_t**
|
||||
db = internalDBGetBlock(emu, addr, addr, create, *current);
|
||||
} 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();
|
||||
}
|
||||
}
|
||||
return db;
|
||||
@@ -420,13 +424,11 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr)
|
||||
db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
|
||||
} 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();
|
||||
}
|
||||
}
|
||||
return db;
|
||||
|
||||
+18
-5
@@ -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, ¤t);
|
||||
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, ¤t);
|
||||
}
|
||||
if(!block) {
|
||||
#ifdef HAVE_TRACE
|
||||
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
|
||||
printf_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
|
||||
|
||||
@@ -338,20 +338,23 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
block->done = 1;
|
||||
return (void*)block;
|
||||
}
|
||||
// protect the 1st page
|
||||
protectDB(addr, 1);
|
||||
// init the helper
|
||||
dynarec_arm_t helper = {0};
|
||||
helper.start = addr;
|
||||
uintptr_t start = addr;
|
||||
uintptr_t end = arm_pass0(&helper, addr);
|
||||
if(!helper.size) {
|
||||
dynarec_log(LOG_DEBUG, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
|
||||
if(!helper.size || !isprotectedDB(addr, 1)) {
|
||||
dynarec_log(LOG_DEBUG, "Warning, null-sized dynarec block (%p) or write on purge on pass0\n", (void*)addr);
|
||||
block->done = 1;
|
||||
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((addr&~0xfff)!=(end&~0xfff)) // need to protect some other pages too
|
||||
protectDB(addr, end-addr); //end is 1byte after actual end
|
||||
uint32_t hash = X31_hash_code((void*)addr, end-addr);
|
||||
// pass 1, addresses, x64 jump addresses, flags
|
||||
arm_pass1(&helper, addr);
|
||||
@@ -422,7 +425,15 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
}
|
||||
printf_log(LOG_NONE, "Table64 \t%d -> %d\n", oldtable64size*8, helper.table64size*8);
|
||||
printf_log(LOG_NONE, " ------------\n");
|
||||
//TODO: Cancel block and return empty one
|
||||
|
||||
free(helper.insts);
|
||||
free(helper.next);
|
||||
free(helper.table64);
|
||||
free(helper.sons_x64);
|
||||
free(helper.sons_arm);
|
||||
FreeDynarecMap(block, (uintptr_t)p, sz);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
// add table64 if needed
|
||||
if(helper.table64size) {
|
||||
@@ -453,7 +464,7 @@ 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 || !isprotectedDB(addr, end-addr)) {
|
||||
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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,6 +151,79 @@ 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);\
|
||||
@@ -160,6 +281,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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -313,6 +313,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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
+22
-14
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -38,6 +38,7 @@ uintptr_t getJumpTableAddress64(uintptr_t addr);
|
||||
#define PROT_ALLOC 0x40
|
||||
#define PROT_CUSTOM (PROT_DYNAREC|PROT_ALLOC)
|
||||
|
||||
// Implemented in mailbox.c
|
||||
void updateProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void setProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void freeProtection(uintptr_t addr, size_t size);
|
||||
@@ -45,10 +46,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);
|
||||
|
||||
+6
-3
@@ -1,6 +1,8 @@
|
||||
#ifndef __DEBUG_H_
|
||||
#define __DEBUG_H_
|
||||
#ifndef __DEBUG_H__
|
||||
#define __DEBUG_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct box64context_s box64context_t;
|
||||
extern int box64_log; // log level
|
||||
@@ -18,6 +20,7 @@ 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
|
||||
@@ -60,4 +63,4 @@ extern FILE* ftrace;
|
||||
#define EXPORTDYN
|
||||
#endif
|
||||
|
||||
#endif //__DEBUG_H_
|
||||
#endif //__DEBUG_H__
|
||||
@@ -29,4 +29,7 @@ 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();
|
||||
|
||||
#endif //__DYNABLOCK_H_
|
||||
@@ -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();
|
||||
|
||||
Executable
+338
@@ -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__
|
||||
+73
-41
@@ -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,28 +66,28 @@ 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__)
|
||||
@@ -100,6 +100,31 @@ typedef struct va_list {
|
||||
|
||||
#define CONVERT_VALIST(A) \
|
||||
#error TODO!
|
||||
#elif defined(__loongarch64)
|
||||
#define CREATE_SYSV_VALIST(A) \
|
||||
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 +140,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 +179,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);
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
+22
-10
@@ -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)
|
||||
@@ -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
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -736,6 +736,8 @@ 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)) //1<<8 is building_dynablock
|
||||
cancelFillBlock(); // Segfault inside a Fillblock, just cancel it's creation, don't relock mutexes
|
||||
dynablock_t* db = NULL;
|
||||
int db_searched = 0;
|
||||
if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_DYNAREC)) {
|
||||
@@ -805,6 +807,7 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
glitch_pc = pc;
|
||||
glitch_addr = addr;
|
||||
glitch_prot = prot;
|
||||
cleanDBFromAddressRange(((uintptr_t)addr)&~0xfff, 0x1000, 0);
|
||||
relockMutex(Locks);
|
||||
return; // try again
|
||||
}
|
||||
|
||||
+17
-4
@@ -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);
|
||||
}
|
||||
|
||||
+328
@@ -0,0 +1,328 @@
|
||||
#include "mailbox.h"
|
||||
|
||||
#include <semaphore.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "custommem.h"
|
||||
#include "debug.h"
|
||||
|
||||
//#define DEBUG_MAILBOX
|
||||
|
||||
// === REQUESTS ===
|
||||
|
||||
typedef enum available_bits_s {
|
||||
AVAILABLE_BITS_32 = 32,
|
||||
AVAILABLE_BITS_47 = 47,
|
||||
AVAILABLE_BITS_MAX = 0,
|
||||
} available_bits_e;
|
||||
|
||||
typedef struct request_s {
|
||||
enum request_type_e {
|
||||
REQUEST_HALT,
|
||||
REQUEST_UPD_PROTECT,
|
||||
REQUEST_SET_PROTECT,
|
||||
REQUEST_FRE_PROTECT,
|
||||
REQUEST_GET_PROTECT,
|
||||
REQUEST_LOD_PROTECT,
|
||||
#ifdef DYNAREC
|
||||
REQUEST_PROT_DB,
|
||||
REQUEST_UNPROT_DB,
|
||||
REQUEST_ISPROT_DB,
|
||||
#endif
|
||||
REQUEST_FIND,
|
||||
REQUEST_FIND_HINT,
|
||||
} type;
|
||||
sem_t *answered;
|
||||
void *ansBuf;
|
||||
union {
|
||||
struct {
|
||||
uintptr_t addr;
|
||||
} protect;
|
||||
struct {
|
||||
uintptr_t addr;
|
||||
size_t size;
|
||||
} size_protect;
|
||||
struct {
|
||||
uintptr_t addr;
|
||||
size_t size;
|
||||
uint32_t prot;
|
||||
} prot_protect;
|
||||
struct {
|
||||
available_bits_e availablebits;
|
||||
uintptr_t size;
|
||||
} find;
|
||||
struct {
|
||||
available_bits_e availablebits;
|
||||
uintptr_t size;
|
||||
void* hint;
|
||||
} find_near;
|
||||
} data;
|
||||
#ifdef DEBUG_MAILBOX
|
||||
int reqno;
|
||||
#endif
|
||||
} request_t;
|
||||
|
||||
request_t curHdr;
|
||||
sem_t empty;
|
||||
sem_t full;
|
||||
sem_t finished;
|
||||
|
||||
static void sendRequest(request_t *rhdr, void *ans) {
|
||||
#ifdef DEBUG_MAILBOX
|
||||
static int reqno = 0;
|
||||
rhdr->reqno = ++reqno;
|
||||
printf_log(LOG_DEBUG, "[REQ%05u] Sending request %02X (ans=%p)\n", rhdr->reqno, rhdr->type, ans);
|
||||
#endif
|
||||
rhdr->ansBuf = ans;
|
||||
if (ans) {
|
||||
sem_t answered;
|
||||
sem_init(&answered, 0, 0);
|
||||
rhdr->answered = &answered;
|
||||
#ifdef DEBUG_MAILBOX
|
||||
printf_log(LOG_DEBUG, "[REQ%05u] Will wait for answer\n", rhdr->reqno);
|
||||
#endif
|
||||
sem_wait(&empty);
|
||||
curHdr = *rhdr;
|
||||
sem_post(&full);
|
||||
sem_wait(&answered);
|
||||
} else {
|
||||
sem_wait(&empty);
|
||||
curHdr = *rhdr;
|
||||
sem_post(&full);
|
||||
}
|
||||
#ifdef DEBUG_MAILBOX
|
||||
printf_log(LOG_DEBUG, "[REQ%05u] Done, leaving\n", rhdr->reqno);
|
||||
#endif
|
||||
}
|
||||
|
||||
// A function per request (avoids exposing dangerous internal functions)
|
||||
void updateProtection(uintptr_t addr, size_t size, uint32_t prot) {
|
||||
request_t req;
|
||||
req.type = REQUEST_UPD_PROTECT;
|
||||
req.data.prot_protect.addr = addr;
|
||||
req.data.prot_protect.size = size;
|
||||
req.data.prot_protect.prot = prot;
|
||||
void *none = NULL;
|
||||
sendRequest(&req, &none); // Need to wait for completion
|
||||
}
|
||||
void setProtection(uintptr_t addr, size_t size, uint32_t prot) {
|
||||
request_t req;
|
||||
req.type = REQUEST_SET_PROTECT;
|
||||
req.data.prot_protect.addr = addr;
|
||||
req.data.prot_protect.size = size;
|
||||
req.data.prot_protect.prot = prot;
|
||||
sendRequest(&req, NULL);
|
||||
}
|
||||
void freeProtection(uintptr_t addr, size_t size) {
|
||||
request_t req;
|
||||
req.type = REQUEST_FRE_PROTECT;
|
||||
req.data.size_protect.addr = addr;
|
||||
req.data.size_protect.size = size;
|
||||
void *none = NULL;
|
||||
sendRequest(&req, &none); // Need to wait for completion
|
||||
}
|
||||
uint32_t getProtection(uintptr_t addr) {
|
||||
request_t req;
|
||||
req.type = REQUEST_GET_PROTECT;
|
||||
req.data.protect.addr = addr;
|
||||
uint32_t ret;
|
||||
sendRequest(&req, &ret);
|
||||
return ret;
|
||||
}
|
||||
void loadProtectionFromMap() {
|
||||
request_t req;
|
||||
req.type = REQUEST_LOD_PROTECT;
|
||||
void *none = NULL;
|
||||
sendRequest(&req, &none); // Need to wait for completion
|
||||
}
|
||||
#ifdef DYNAREC
|
||||
void protectDB(uintptr_t addr, size_t size) {
|
||||
request_t req;
|
||||
req.type = REQUEST_PROT_DB;
|
||||
req.data.size_protect.addr = addr;
|
||||
req.data.size_protect.size = size;
|
||||
void *none = NULL;
|
||||
sendRequest(&req, &none); // Need to wait for completion
|
||||
}
|
||||
void unprotectDB(uintptr_t addr, size_t size) {
|
||||
request_t req;
|
||||
req.type = REQUEST_UNPROT_DB;
|
||||
req.data.size_protect.addr = addr;
|
||||
req.data.size_protect.size = size;
|
||||
void *none = NULL;
|
||||
sendRequest(&req, &none); // Need to wait for completion
|
||||
}
|
||||
int isprotectedDB(uintptr_t addr, size_t size) {
|
||||
request_t req;
|
||||
req.type = REQUEST_ISPROT_DB;
|
||||
req.data.size_protect.addr = addr;
|
||||
req.data.size_protect.size = size;
|
||||
int ret;
|
||||
sendRequest(&req, &ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
void* find32bitBlock(size_t size) {
|
||||
request_t req;
|
||||
req.type = REQUEST_FIND;
|
||||
req.data.find.size = size;
|
||||
req.data.find.availablebits = AVAILABLE_BITS_32;
|
||||
void* ret;
|
||||
sendRequest(&req, &ret);
|
||||
return ret;
|
||||
}
|
||||
void* findBlockNearHint(void* hint, size_t size) {
|
||||
request_t req;
|
||||
req.type = REQUEST_FIND_HINT;
|
||||
req.data.find_near.size = size;
|
||||
req.data.find_near.availablebits = AVAILABLE_BITS_MAX;
|
||||
req.data.find_near.hint = hint;
|
||||
void* ret;
|
||||
sendRequest(&req, &ret);
|
||||
return ret;
|
||||
}
|
||||
void* find47bitBlock(size_t size) {
|
||||
request_t req;
|
||||
req.type = REQUEST_FIND;
|
||||
req.data.find.size = size;
|
||||
req.data.find.availablebits = AVAILABLE_BITS_47;
|
||||
void* ret;
|
||||
sendRequest(&req, &ret);
|
||||
return ret;
|
||||
}
|
||||
void* find47bitBlockNearHint(void* hint, size_t size) {
|
||||
request_t req;
|
||||
req.type = REQUEST_FIND_HINT;
|
||||
req.data.find_near.size = size;
|
||||
req.data.find_near.availablebits = AVAILABLE_BITS_47;
|
||||
req.data.find_near.hint = hint;
|
||||
void* ret;
|
||||
sendRequest(&req, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// === MAILBOX ===
|
||||
|
||||
void internalUpdateProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void internalSetProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void internalFreeProtection(uintptr_t addr, size_t size);
|
||||
uint32_t internalGetProtection(uintptr_t addr);
|
||||
void internalLoadProtectionFromMap();
|
||||
#ifdef DYNAREC
|
||||
void internalProtectDB(uintptr_t addr, size_t size);
|
||||
void internalUnprotectDB(uintptr_t addr, size_t size);
|
||||
int internalIsprotectedDB(uintptr_t addr, size_t size);
|
||||
#endif
|
||||
void* internalFind32bitBlock(size_t size);
|
||||
void* internalFindBlockNearHint(void* hint, size_t size);
|
||||
void* internalFind47bitBlock(size_t size);
|
||||
void* internalFind47bitBlockNearHint(void* hint, size_t size);
|
||||
|
||||
void *parse_find_req(request_t *req) {
|
||||
switch (req->data.find.availablebits) {
|
||||
case AVAILABLE_BITS_32:
|
||||
return internalFind32bitBlock(req->data.find.size);
|
||||
case AVAILABLE_BITS_47:
|
||||
return internalFind47bitBlock(req->data.find.size);
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
void *parse_find_near_req(request_t *req) {
|
||||
switch (req->data.find_near.availablebits) {
|
||||
case AVAILABLE_BITS_MAX:
|
||||
return internalFindBlockNearHint(req->data.find_near.hint, req->data.find_near.size);
|
||||
case AVAILABLE_BITS_47:
|
||||
return internalFind47bitBlockNearHint(req->data.find_near.hint, req->data.find_near.size);
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
static void runMailbox() {
|
||||
sem_init(&empty, 0, 1);
|
||||
sem_init(&full, 0, 0);
|
||||
|
||||
while (1) {
|
||||
sem_wait(&full);
|
||||
#ifdef DEBUG_MAILBOX
|
||||
printf_log(LOG_DEBUG, "[ WORKER ] Received request %05u (%02X) (ans=%p)\n", curHdr.reqno, curHdr.type, curHdr.ansBuf);
|
||||
#endif
|
||||
switch (curHdr.type) {
|
||||
case REQUEST_HALT:
|
||||
return;
|
||||
|
||||
case REQUEST_UPD_PROTECT:
|
||||
internalUpdateProtection(curHdr.data.prot_protect.addr, curHdr.data.prot_protect.size, curHdr.data.prot_protect.prot);
|
||||
break;
|
||||
case REQUEST_SET_PROTECT:
|
||||
internalSetProtection(curHdr.data.prot_protect.addr, curHdr.data.prot_protect.size, curHdr.data.prot_protect.prot);
|
||||
break;
|
||||
case REQUEST_FRE_PROTECT:
|
||||
internalFreeProtection(curHdr.data.size_protect.addr, curHdr.data.size_protect.size);
|
||||
break;
|
||||
case REQUEST_GET_PROTECT:
|
||||
*(uintptr_t*)curHdr.ansBuf = internalGetProtection(curHdr.data.protect.addr);
|
||||
break;
|
||||
case REQUEST_LOD_PROTECT:
|
||||
internalLoadProtectionFromMap();
|
||||
break;
|
||||
#ifdef DYNAREC
|
||||
case REQUEST_PROT_DB:
|
||||
internalProtectDB(curHdr.data.size_protect.addr, curHdr.data.size_protect.size);
|
||||
break;
|
||||
case REQUEST_UNPROT_DB:
|
||||
internalUnprotectDB(curHdr.data.size_protect.addr, curHdr.data.size_protect.size);
|
||||
break;
|
||||
case REQUEST_ISPROT_DB:
|
||||
*(intptr_t*)curHdr.ansBuf = internalIsprotectedDB(curHdr.data.size_protect.addr, curHdr.data.size_protect.size);
|
||||
break;
|
||||
#endif
|
||||
case REQUEST_FIND:
|
||||
*(void**)curHdr.ansBuf = parse_find_req(&curHdr);
|
||||
break;
|
||||
case REQUEST_FIND_HINT:
|
||||
*(void**)curHdr.ansBuf = parse_find_near_req(&curHdr);
|
||||
break;
|
||||
#ifdef DEBUG_MAILBOX
|
||||
default:
|
||||
printf_log(LOG_DEBUG, "[ WORKER ] AAAAAAA %X\n", curHdr.type);
|
||||
#endif
|
||||
}
|
||||
if (curHdr.ansBuf) {
|
||||
#ifdef DEBUG_MAILBOX
|
||||
printf_log(LOG_DEBUG, "[ WORKER ] Answering %X to REQ%05u\n", *(uintptr_t*)curHdr.ansBuf, curHdr.reqno);
|
||||
#endif
|
||||
sem_post(curHdr.answered);
|
||||
}
|
||||
sem_post(&empty);
|
||||
#ifdef DEBUG_MAILBOX
|
||||
printf_log(LOG_DEBUG, "[ WORKER ] Waiting for next request\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
sem_destroy(&empty);
|
||||
sem_destroy(&full);
|
||||
}
|
||||
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
pthread_t thread;
|
||||
static void *mailboxRoutine(void *arg) {
|
||||
sigset_t sigset;
|
||||
sigfillset(&sigset);
|
||||
pthread_sigmask(SIG_BLOCK, &sigset, NULL);
|
||||
runMailbox();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Declared in main.c and threads.c
|
||||
void startMailbox(void) {
|
||||
pthread_create(&thread, NULL, mailboxRoutine, NULL);
|
||||
}
|
||||
void haltMailbox(void) {
|
||||
request_t hltreq;
|
||||
hltreq.type = REQUEST_HALT;
|
||||
sendRequest(&hltreq, NULL);
|
||||
pthread_join(thread, NULL);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef __MAILBOX_H__
|
||||
#define __MAILBOX_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
|
||||
//void updateProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
//void setProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
//void freeProtection(uintptr_t addr, size_t size);
|
||||
//uint32_t getProtection(uintptr_t addr);
|
||||
//void loadProtectionFromMap();
|
||||
//#ifdef DYNAREC
|
||||
//void protectDB(uintptr_t addr, size_t size);
|
||||
//void unprotectDB(uintptr_t addr, size_t size);
|
||||
//int isprotectedDB(uintptr_t addr, size_t size);
|
||||
//#endif
|
||||
//void* find32bitBlock(size_t size);
|
||||
//void* findBlockNearHint(void* hint, size_t size);
|
||||
//void* find47bitBlock(size_t size);
|
||||
//void* find47bitBlockNearHint(void* hint, size_t size);
|
||||
|
||||
#endif // __MAILBOX_H__
|
||||
+34
-8
@@ -32,6 +32,9 @@
|
||||
#include "x64run.h"
|
||||
#include "symbols.h"
|
||||
|
||||
void startMailbox(void);
|
||||
void haltMailbox(void);
|
||||
|
||||
box64context_t *my_context = NULL;
|
||||
int box64_log = LOG_INFO; //LOG_NONE;
|
||||
int box64_dump = 0;
|
||||
@@ -49,6 +52,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 +96,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 +160,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 +169,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
|
||||
}
|
||||
@@ -699,6 +714,7 @@ void endBox64()
|
||||
int running = 1;
|
||||
int attempt = 0;
|
||||
printf_log(LOG_DEBUG, "Waiting for all threads to finish before unloading box64context\n");
|
||||
haltMailbox();
|
||||
while(running) {
|
||||
DIR *proc_dir;
|
||||
char dirname[100];
|
||||
@@ -731,7 +747,9 @@ void endBox64()
|
||||
}
|
||||
}
|
||||
// all done, free context
|
||||
startMailbox(); // Need to restart mailbox (to use protections)
|
||||
FreeBox64Context(&my_context);
|
||||
haltMailbox();
|
||||
if(libGL) {
|
||||
free(libGL);
|
||||
libGL = NULL;
|
||||
@@ -790,6 +808,9 @@ int main(int argc, const char **argv, const char **env) {
|
||||
}
|
||||
if(!box64_nobanner)
|
||||
PrintBox64Version();
|
||||
|
||||
startMailbox();
|
||||
|
||||
// precheck, for win-preload
|
||||
if(strstr(prog, "wine-preloader")==(prog+strlen(prog)-strlen("wine-preloader"))
|
||||
|| strstr(prog, "wine64-preloader")==(prog+strlen(prog)-strlen("wine64-preloader"))) {
|
||||
@@ -911,6 +932,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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Executable
+1537
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_
|
||||
@@ -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_
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedgio2DEFS_H_
|
||||
#define __wrappedgio2DEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedgio2DEFS_H_
|
||||
@@ -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_
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedglib2DEFS_H_
|
||||
#define __wrappedglib2DEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedglib2DEFS_H_
|
||||
@@ -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_
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedgtkx112UNDEFS_H_
|
||||
#define __wrappedgtkx112UNDEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedgtkx112UNDEFS_H_
|
||||
@@ -92,6 +92,7 @@ typedef int64_t (*iFpippppp_t)(void*, int64_t, void*, void*, void*, void*, void*
|
||||
GO(getauxval, LFL_t) \
|
||||
GO(malloc, pFL_t) \
|
||||
GO(__deregister_frame_info, pFp_t) \
|
||||
GO(mallinfo, pFp_t) \
|
||||
GO(__longjmp_chk, vFpi_t) \
|
||||
GO(_longjmp, vFpi_t) \
|
||||
GO(longjmp, vFpi_t) \
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedlibncursesw6DEFS_H_
|
||||
#define __wrappedlibncursesw6DEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedlibncursesw6DEFS_H_
|
||||
@@ -0,0 +1,27 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedlibncursesw6TYPES_H_
|
||||
#define __wrappedlibncursesw6TYPES_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* (*pFv_t)(void);
|
||||
typedef int64_t (*iFpV_t)(void*, ...);
|
||||
typedef int64_t (*iFppA_t)(void*, void*, va_list);
|
||||
typedef int64_t (*iFiipV_t)(int64_t, int64_t, void*, ...);
|
||||
typedef int64_t (*iFpiipV_t)(void*, int64_t, int64_t, void*, ...);
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS() \
|
||||
GO(initscr, pFv_t) \
|
||||
GO(printw, iFpV_t) \
|
||||
GO(vwprintw, iFppA_t) \
|
||||
GO(mvprintw, iFiipV_t) \
|
||||
GO(mvwprintw, iFpiipV_t)
|
||||
|
||||
#endif // __wrappedlibncursesw6TYPES_H_
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedlibncursesw6UNDEFS_H_
|
||||
#define __wrappedlibncursesw6UNDEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedlibncursesw6UNDEFS_H_
|
||||
@@ -14,6 +14,7 @@
|
||||
typedef void (*vFp_t)(void*);
|
||||
typedef int64_t (*iFp_t)(void*);
|
||||
typedef void (*vFpi_t)(void*, int64_t);
|
||||
typedef int64_t (*iFLp_t)(uintptr_t, void*);
|
||||
typedef int64_t (*iFpi_t)(void*, int64_t);
|
||||
typedef int64_t (*iFpL_t)(void*, uintptr_t);
|
||||
typedef int64_t (*iFpp_t)(void*, void*);
|
||||
@@ -48,6 +49,7 @@ typedef int64_t (*iFpppp_t)(void*, void*, void*, void*);
|
||||
GO(pthread_mutexattr_init, iFp_t) \
|
||||
GO(_pthread_cleanup_pop, vFpi_t) \
|
||||
GO(_pthread_cleanup_pop_restore, vFpi_t) \
|
||||
GO(pthread_getattr_np, iFLp_t) \
|
||||
GO(__pthread_mutexattr_settype, iFpi_t) \
|
||||
GO(pthread_attr_setdetachstate, iFpi_t) \
|
||||
GO(pthread_attr_setinheritsched, iFpi_t) \
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedlibsndfileDEFS_H_
|
||||
#define __wrappedlibsndfileDEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedlibsndfileDEFS_H_
|
||||
@@ -0,0 +1,21 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedlibsndfileTYPES_H_
|
||||
#define __wrappedlibsndfileTYPES_H_
|
||||
|
||||
#ifndef LIBNAME
|
||||
#error You should only #include this file inside a wrapped*.c file
|
||||
#endif
|
||||
#ifndef ADDED_FUNCTIONS
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
typedef int64_t (*iFp_t)(void*);
|
||||
typedef void* (*pFpipp_t)(void*, int64_t, void*, void*);
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS() \
|
||||
GO(sf_close, iFp_t) \
|
||||
GO(sf_open_virtual, pFpipp_t)
|
||||
|
||||
#endif // __wrappedlibsndfileTYPES_H_
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedlibsndfileUNDEFS_H_
|
||||
#define __wrappedlibsndfileUNDEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedlibsndfileUNDEFS_H_
|
||||
@@ -12,6 +12,7 @@
|
||||
#endif
|
||||
|
||||
typedef int64_t (*iFp_t)(void*);
|
||||
typedef int64_t (*iFpi_t)(void*, int64_t);
|
||||
typedef int64_t (*iFppi_t)(void*, void*, int64_t);
|
||||
typedef int64_t (*iFpipi_t)(void*, int64_t, void*, int64_t);
|
||||
typedef int64_t (*iFpippi_t)(void*, int64_t, void*, void*, int64_t);
|
||||
@@ -20,6 +21,7 @@ typedef int64_t (*iFpiiiiipi_t)(void*, int64_t, int64_t, int64_t, int64_t, int64
|
||||
#define SUPER() ADDED_FUNCTIONS() \
|
||||
GO(deflateEnd, iFp_t) \
|
||||
GO(inflateEnd, iFp_t) \
|
||||
GO(inflate, iFpi_t) \
|
||||
GO(inflateInit_, iFppi_t) \
|
||||
GO(deflateInit_, iFpipi_t) \
|
||||
GO(inflateInit2_, iFpipi_t) \
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappednslDEFS_H_
|
||||
#define __wrappednslDEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappednslDEFS_H_
|
||||
@@ -0,0 +1,17 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappednslTYPES_H_
|
||||
#define __wrappednslTYPES_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 // __wrappednslTYPES_H_
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappednslUNDEFS_H_
|
||||
#define __wrappednslUNDEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappednslUNDEFS_H_
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappednspr4DEFS_H_
|
||||
#define __wrappednspr4DEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappednspr4DEFS_H_
|
||||
@@ -0,0 +1,17 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappednspr4TYPES_H_
|
||||
#define __wrappednspr4TYPES_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 // __wrappednspr4TYPES_H_
|
||||
Loaded 100 of 191 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user