mirror of
https://github.com/ptitSeb/box86.git
synced 2026-11-08 17:39:19 -10:00
Compare commits
87
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32accd0e77 | ||
|
|
c4b3fc25e0 | ||
|
|
676b02b5aa | ||
|
|
3c8e34f691 | ||
|
|
630f42e9e2 | ||
|
|
58b0338dff | ||
|
|
80c77bad96 | ||
|
|
771ff1b2e2 | ||
|
|
cef87f7f7d | ||
|
|
e8d4ffc782 | ||
|
|
85397e9895 | ||
|
|
8194ad9728 | ||
|
|
b82f203a9d | ||
|
|
151e2ae3a4 | ||
|
|
0072524d5d | ||
|
|
949417f412 | ||
|
|
21fea0f195 | ||
|
|
9c1317f899 | ||
|
|
127a48f199 | ||
|
|
66b8c58cc1 | ||
|
|
39bb606c06 | ||
|
|
626826f33e | ||
|
|
a9082f60b6 | ||
|
|
3b394b8f0d | ||
|
|
a108a23c56 | ||
|
|
51baede9c1 | ||
|
|
d601b42ddc | ||
|
|
d430332c45 | ||
|
|
63fae1b6c8 | ||
|
|
c45d3d80ab | ||
|
|
57e9e95411 | ||
|
|
68fb291c83 | ||
|
|
f3ee727bc4 | ||
|
|
21ed47c4cb | ||
|
|
2147d92d9d | ||
|
|
1465ff8aad | ||
|
|
ac895e3dad | ||
|
|
983a3d9926 | ||
|
|
ecec73547f | ||
|
|
6ed82e7f7d | ||
|
|
83a9b2cab5 | ||
|
|
666e41a0cb | ||
|
|
c78be09d7f | ||
|
|
21023e9802 | ||
|
|
38c07f2a2f | ||
|
|
e6d124aed4 | ||
|
|
8335a8c2d9 | ||
|
|
6f7a513051 | ||
|
|
43189a2914 | ||
|
|
3bf9e4d989 | ||
|
|
fe3419957e | ||
|
|
f8c8a5d596 | ||
|
|
9ee7f84015 | ||
|
|
36b316746b | ||
|
|
0131572edf | ||
|
|
d74e873a85 | ||
|
|
be53b823d3 | ||
|
|
e5b6c8b6e0 | ||
|
|
ecf7bfd848 | ||
|
|
2a7b848d0e | ||
|
|
fa5fa7b5c0 | ||
|
|
b7283b8d9d | ||
|
|
b8d72023c5 | ||
|
|
e10a710591 | ||
|
|
9ee030a566 | ||
|
|
a8e96764b5 | ||
|
|
c43f1d882c | ||
|
|
1e67cefc43 | ||
|
|
5cdc1b9fa2 | ||
|
|
ab75a3e2d3 | ||
|
|
21d097853b | ||
|
|
2e3bdbefc7 | ||
|
|
a19773cfb0 | ||
|
|
1988eb0366 | ||
|
|
54d5aaa11d | ||
|
|
205ec1f4dc | ||
|
|
005367ea3c | ||
|
|
8ac9bc30a2 | ||
|
|
f0691e56fc | ||
|
|
bc06c277ec | ||
|
|
1341a4a55f | ||
|
|
82cf77b9d9 | ||
|
|
10db79df4a | ||
|
|
bce188e217 | ||
|
|
220a64af1f | ||
|
|
e73fa8f3fb | ||
|
|
053a75f5d5 |
No files matched your search
@@ -572,6 +572,7 @@ if(ARM_DYNAREC)
|
||||
|
||||
"${BOX86_ROOT}/src/dynarec/dynarec_arm.c"
|
||||
"${BOX86_ROOT}/src/dynarec/dynarec_arm_functions.c"
|
||||
"${BOX86_ROOT}/src/dynarec/dynarec_arm_jmpnext.c"
|
||||
"${BOX86_ROOT}/src/dynarec/arm_printer.c"
|
||||
"${BOX86_ROOT}/src/emu/x86test.c"
|
||||
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
v0.3.2
|
||||
======
|
||||
* Better syscall handling
|
||||
* Fixed some wrapped functions, added some others
|
||||
* Introduced another wrapper helper
|
||||
* Added some more opcodes
|
||||
* Added a cosimulation mode (to compare the behaviour of the dynarec against the interpreter)
|
||||
* Added support of FASTNAN for some more opcodes
|
||||
* Reduced memory footprint
|
||||
* Added BOX86_NOSANDBOX (adds an argument to the command line)
|
||||
* Added an ukrainian translation
|
||||
=> Mostly a stability update with improved elfloader, fixed opcodes and refined profiles
|
||||
|
||||
v0.3.0
|
||||
======
|
||||
* Added rcfile handling: box86 now read `/etc/box86.box86rc` and `~/.box86rc` and apply per process parameters
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@
|
||||
|
||||
Linux Userspace x86 Emulator with a twist
|
||||
|
||||
[View changelog](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box86/blob/master/docs/README_CN.md) | [Report an error](https://github.com/ptitSeb/box86/issues/new)
|
||||
[View changelog](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box86/blob/master/docs/README_CN.md) | [Українська](https://github.com/ptitSeb/box86/blob/master/docs/README_UK.md) | [Report an error](https://github.com/ptitSeb/box86/issues/new)
|
||||
|
||||
     
|
||||
|
||||
@@ -88,7 +88,7 @@ So, your settings in `~/.bashrc` may override the setting from your command line
|
||||
Notes about Unity game emulation
|
||||
----
|
||||
|
||||
Running Unity games shoudl generaly work now, but you should also note that many Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers) for now.
|
||||
Running Unity games should generaly work now, but you should also note that many Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers) for now.
|
||||
Hint: on Pi4, use `MESA_GL_VERSION_OVERRIDE=3.2` and with Panfrost use `PAN_MESA_DEBUG=gl3` to use higher profile if the game starts then quits before showing anything.
|
||||
|
||||
----
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
Linux用户空间的x86应用模拟器
|
||||
|
||||
[更新历史](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [English](https://github.com/ptitSeb/box86/blob/master/docs/README.md) | [报告错误](https://github.com/ptitSeb/box86/issues/new)
|
||||
[更新历史](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [English](https://github.com/ptitSeb/box86/blob/master/docs/README.md) | [Українська](https://github.com/ptitSeb/box86/blob/master/docs/README_UK.md) | [报告错误](https://github.com/ptitSeb/box86/issues/new)
|
||||
|
||||
     
|
||||
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||

|
||||
|
||||
Емулятор простіра користувача x86_64 із родзинкою
|
||||
|
||||
[Дивитись журнал змін](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box86/blob/master/docs/README_CN.md) | [Українська](https://github.com/ptitSeb/box86/blob/master/docs/README_UK.md) | [Повідомити про помилку](https://github.com/ptitSeb/box86/issues/new)
|
||||
|
||||
     
|
||||
|
||||
----
|
||||
|
||||
Box86 дозволяє запускати x86 Linux програми (наприклад, ігри) на системах Linux відмінних від x86, наприклад ARM (хост-система має мати 32-розрядний порядок редагування).
|
||||
|
||||
Вам *ПОТРІБНА* 32-розрядна підсистема для запуску та створення Box86. Box86 марний лише на 64-розрядних системах. Крім того, вам *ПОТРІБЕН* 32-розрядний інструментарій для створення Box86. Ланцюжок інструментів, який підтримує лише 64-розрядні версії, не компілює Box86, і ви отримаєте помилки (зазвичай на aarch64 ви отримуєте що «-marm» не розпізнається, і вам знадобиться середовище з мультиархітектурою або chroot).
|
||||
|
||||
Оскільки Box86 використовує рідні версії деяких «системних» бібліотек, таких як libc, libm, SDL і OpenGL, його легко інтегрувати та використовувати з більшістю програм, а продуктивність у багатьох випадках може бути напрочуд високою. Подивіться на цей стендовий аналіз для прикладу [тут](https://box86.org/index.php/2021/06/game-performances/). Це також означає, що вам знадобиться 32-бітний простір користувача на 64-бітній ОС, наприклад `armhf` поверх `aarch64` 64-бітної ОС.
|
||||
|
||||
Більшість x86-ігор потребують OpenGL, тому на платформах ARM може знадобитися таке рішення, як [gl4es](https://github.com/ptitSeb/gl4es). (Деякі платформи ARM підтримують лише OpenGL ES і/або їх реалізація OpenGL хитра. (див. OpenGL на Android))
|
||||
|
||||
Box86 інтегрується з DynaRec (динамічний рекомпілятор) для платформ ARM64 і RV64 забезпечуючи підвищення швидкості в 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/).
|
||||
|
||||
Багато ігор просто працюють без особливих налаштувань, наприклад: WorldOfGoo, Airline Tycoon Deluxe і FTL. Багато ігор GameMaker Linux також працюють нормально. (є довгий список, серед них UNDERTALE, A Risk of Rain і Cook Serve Delicious). Ігри Unity3D також працюють добре, але вимога OpenGL може бути проблемою на деяких платформах ARM.
|
||||
|
||||
Якщо ви серйозно ставитеся до розробки Box86, вам слід встановити ccache та створити Box86 з ним. (Використовуйте, наприклад, ccmake.)
|
||||
Щоб увімкнути TRACE (тобто скидання в stdout усіх окремих виконаних інструкцій x86 із дампом регістрів), вам також знадобиться [бібліотека Zydis](https://github.com/zyantific/zydis), доступна у вашій системі.
|
||||
|
||||
Деякі внутрішні коди операцій x86 використовують частини «Бібліотеки емулятора Realmode X86», дивіться [x86primop.c](../src/emu/x86primop.c) для детальної інформації про авторські права.
|
||||
|
||||
----
|
||||
Компіляція/Встановлення
|
||||
----
|
||||
> Інструкцію зі складання Box86 можна знайти [тут](COMPILE.md).\
|
||||
> Інструкцію з встановлення Wine для Box86 можна знайти [тут](X86WINE.md).
|
||||
|
||||
----
|
||||
|
||||
Ось 6 відео, перші 2 відео – це відео "Airline Tycoon Deluxe" і "Heretic 2", які працюють на GigaHertz OpenPandora (друге використовує Dynarec), а наступні 2 відео – це відео "Bit.Trip.Runner" і "Neverwinter Night", які працюють на ODroid XU4 (без dynarec), а останні 2 відео на Pi4: Shovel Knight (відео від @ITotalJustice) і Freedom Planet (відео від @djazz), також без Dynarec.
|
||||
|
||||
|
||||
[](https://www.youtube.com/watch?v=bLt0hMoFDLk) [](https://www.youtube.com/watch?v=MM7kWYts7IA) [](https://www.youtube.com/watch?v=8hr71S029Hg) [](https://www.youtube.com/watch?v=B4YN37z3-ws) [](https://www.youtube.com/watch?v=xk8Q30mxqPg) [](https://www.youtube.com/watch?v=_QMRMVvYrqU)
|
||||
|
||||
Ви можете знайти багато інших відео про Box86 у YouTube каналах [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ), [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) або [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA).
|
||||
|
||||
Список сумісності доступний тут: https://github.com/ptitSeb/box86-compatibility-list/issues
|
||||
|
||||
<img src="img/Box86Icon.png" width="96" height="96">
|
||||
|
||||
Логотип і піктограма зроблені @grayduck, дякую!
|
||||
|
||||
Зауважте, що цей проект не слід плутати з [86box](https://github.com/86Box/86Box), гарним емулятором "повної системи", що спеціалізується на ранньому (до відносно недавньому) апаратному забезпеченні ПК.
|
||||
|
||||
----
|
||||
|
||||
Використання
|
||||
----
|
||||
|
||||
Є кілька змінних середовища для керування поведінкою Box86.
|
||||
|
||||
Дивіться [тут](USAGE.md) для перегляду всіх змінних середовища та того, що вони роблять.
|
||||
|
||||
Примітка: Dynarec від Box86 використовує механізм із захистом пам’яті та обробником сигналу помилки сегментів для обробки JIT коду. Простіше кажучи, якщо ви хочете використовувати GDB для налагодження запущеної програми, яка використовує JIT-код (наприклад, mono/Unity3D), ви все одно матимете багато «звичайних» помилок сегментів. Пропонується використовувати щось на зразок `handle SIGSEGV nostop` в GDB, щоб не зупинятися на кожній помилці сегмента, і, можливо, поставити точку зупину всередині `my_memprotectionhandler` в `signals.c`, якщо ви хочете перехопити помилки сегментів.
|
||||
|
||||
----
|
||||
|
||||
Історія версій/Журнал змін
|
||||
----
|
||||
|
||||
Історія версій доступна [тут](docs/CHANGELOG.md).
|
||||
|
||||
----
|
||||
|
||||
Примітки щодо 64-розрядних платформ
|
||||
----
|
||||
|
||||
Оскільки Box86 працює шляхом прямого перекладу викликів функцій із x86 на хост-систему, хост-система (на якій працює Box86) повинна мати 32-розрядні бібліотеки. Box86 не містить 32-біт <-> 64-біт перекладу. Отже, щоб запустити Box86, наприклад, на платформі ARM64, вам потрібно буде зібрати Box86 для 32-бітної ARM, а також потрібно мати chroot з 32-бітними бібліотеками.
|
||||
|
||||
Якщо ви дивитесь на 64-розрядну версію box86, подивіться на [Box64](https://github.com/ptitSeb/box64): він може запускати двійкові файли x86_64 на 64-розрядних платформах. Але зауважте, що вам все одно потрібен Box86 (і 32-розрядний chroot) для запуску бінарних файлів x86 (як це також трапляється в реальному Linux x86_64, для запуску якого потрібні бібліотеки x86 і двійковий файл в multiarch).
|
||||
|
||||
----
|
||||
|
||||
Примітки щодо конфігурації Box86
|
||||
----
|
||||
|
||||
Box86 тепер має конфігураційні файли. Завантажуються 2 файли: `/etc/box4.box86rc` і `~/.box86rc`. Обидва файли мають однаковий синтаксис і в основному є файлами ini. Розділ у квадратних дужках визначає назву процесу, а решта — встановлють змінну середовища. Подивіться на [використання](docs/USAGE.md), щоб дізнатися, які параметри можна використовувати. Box86 поставляється з файлом за замовчуванням, який слід інсталювати для кращої стабільності. Файл знаходиться в `system/box86.box86rc` і має бути встановлено в `/etc/box86.box86rc`. Якщо з певних причин ви не хочете встановлювати цей файл у `/etc`, принаймні скопіюйте його в `~/.box86rc` або гра може не працювати належним чином. Зауважте, що пріоритетом є: `~/.bashrc` > `/etc/box86.box86rc` > командний рядок
|
||||
Таким чином, ваші налаштування в `~/.bashrc` можуть замінити налаштування з вашого командного рядка...
|
||||
|
||||
----
|
||||
|
||||
Примітки щодо емуляції ігор Unity
|
||||
----
|
||||
|
||||
Запуск ігор Unity має працювати, але ви також повинні зауважити, що для багатьох ігор Unity3D потрібен OpenGL 3+, який може бути складно забезпечити на ARM SBC (одноплатних комп’ютерах). Крім того, багато нових ігор Unity3D (наприклад, KSP) використовують стиснуті текстури BC7, які не підтримуються багатьма інтегрованими GPU ARM.
|
||||
Підказка: в Pi4 використовуйте `MESA_GL_VERSION_OVERRIDE=3.2`, а в Panfrost — `PAN_MESA_DEBUG=gl3`, щоб використовувати вищий профіль, якщо гра запускається, а потім завершується, перш ніж щось показує.
|
||||
|
||||
----
|
||||
|
||||
Примітки щодо Steam
|
||||
----
|
||||
|
||||
Linux версія Steam тепер може працювати з Box86, але вам також потрібен Box64, щоб його можна було повністю використовувати.
|
||||
Рекомендується запускати Steam у small режимі, оскільки він використовує менше пам’яті, але steamwebhelper (64-бітний процес) усе одно завантажуватиметься, навіть якщо він не використовується.
|
||||
Екран входу не може працювати без steamwebhelper, і буде показувати лише порожні вікна без належного налаштування box64 у системі.
|
||||
Зауважте, що Steam використовуватиме багато пам’яті та ледве поміститься в систему з 4 ГБ оперативної пам’яті. Він більше не працюватиме в системі з меншим об’ємом пам’яті (як обхідний шлях, створіть файл підкачки, увійдіть і поставте прапорець «запам’ятати мене», використовуйте box64rc, щоб вимкнути steamwebhelper і запускати лише в малому режимі без підкачки після першого входу в систему)
|
||||
Останнє зауваження: Steam BigPicture працюватиме, але також потрібен steamwebhelper (і box64) і багато пам’яті. Він не запуститься в системі лише з 4 ГБ оперативної пам’яті без файлу підкачки.
|
||||
- Якщо у вас виникли проблеми зі встановленням Steam, ви можете знайти `install_steam.sh` у кореневій папці сховища box86. Цей простий скрипт завантажить і встановить Steam у вашу домашню папку, а потім створить ярлик steam у `/usr/local/bin` (для цього він запитає дозвіл sudo). Просто використовуйте `steam` для запуску після встановлення. Зауважте, що інсталяція, яка знаходиться в папці Home, працюватиме лише для одного користувача. Не використовуйте цей скрипт, якщо вам потрібна багатокористувацька інсталяція.
|
||||
- Щоб уникнути повідомлення «libc.so.6 відсутній», ви можете використовувати `STEAMOS=1` і `STEAM_RUNTIME=1` як змінні середовища (воно автоматично з’являється, якщо ви використовували сценарій `install_steam.sh`)
|
||||
|
||||
Щоб вимкнути `steamwebhelper`, коли Box64 встановлений і працює, створіть (або відредагуйте) `~/.box64rc` і додайте у ньому:
|
||||
```
|
||||
[steamwebhelper]
|
||||
BOX64_EXIT=1
|
||||
```
|
||||
І тоді `steamwebhelper` буде вимкнено. Прокоментуйте `#` ці 2 рядки, щоб увімкнути його знову.
|
||||
|
||||
----
|
||||
|
||||
Примітки щодо Wine
|
||||
----
|
||||
|
||||
Wine тепер підтримується. Інтегровани програми Wine працює як і багато програм та ігор для Windows. Не забувайте, що більшість ігор для Windows використовують Direct3D, для цього може знадобитися повний драйвер OpenGL і якомога більш високий профіль (і gl4es з бекендом ES2 наразі мають проблеми з Wine).
|
||||
Примітка: якщо ви плануєте використовувати box86 з Wine на Raspberry Pi 3 або ранішої версії, ці моделі використовують ОС за замовчуванням, яка має ядро з розділенням 2/2 (тобто 2G місця для програми користувача та 2 Г місця для ядра). Це несумісно з програмами Wine, яким потрібен доступ до пам’яті > 2 Гб адреси. Тож вам потрібно буде переналаштувати ядро для розділення 3G/1G.
|
||||
|
||||
----
|
||||
|
||||
Примітки щодо Vulkan
|
||||
----
|
||||
|
||||
Box86 вже використовує Vulkan. Якщо у вашій системі є 32-розрядний драйвер Vulkan, Box86 використовуватиме його за потреби. Профіль 1.0, 1.1, 1.2 і 1.3, з деякими розширеннями, має бути в порядку. DXVK, включаючи 2.0, працює. Я знаю, що деякі демонстраційні версії працюють на Pi4 (демонстраційні версії Sascha Willems для x86 працюють так само, як якщо б створювати безпосередньо на armhf). Зауважте, що драйвер Vulkan для Pi4 наразі НЕ підтримує DXVK (обгортка Wine DirectX->Vulkan). Це не проблема Box86, у драйвері відсутні розширення (підтримка апаратного забезпечення) та кілька інших речей, через які DXVK не працює на pi4. З боку Panfrost, PanVK трохи молодий, і я ще не тестував DXVK з ним.
|
||||
|
||||
----
|
||||
Останнє слово
|
||||
----
|
||||
|
||||
Я хочу подякувати всім, хто зробив внесок у розвиток box86.
|
||||
Є багато способів зробити свій внесок: код, фінанси, апаратне забезпечення та реклама!
|
||||
Отже, без особливого порядку, я хочу подякувати:
|
||||
* За основний внесок у код: rajdakin, icecream95, M-HT
|
||||
* За великий фінансовий внесок: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
|
||||
* За внесок у апаратне забезпечення: [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [Команда TwisterOS](https://twisteros.com/)
|
||||
* За постійну рекламу Box86: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[Команда TwisterOS](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg)
|
||||
|
||||
І я також дякую багатьом іншим людям, які хоч раз брали участь у проекті.
|
||||
|
||||
(Якщо ви використовуєте Box86 у своєму проекті, будь ласка, не забудьте згадати про це!)
|
||||
@@ -175,11 +175,26 @@ Handling of HotPage (Page beeing both executed and writen)
|
||||
* 0 : Don't track hotpage
|
||||
* 1-255 : Trak HotPage, and disable execution of a page beeing writen for N attempts (default is 16)
|
||||
|
||||
#### BOX86_DYNAREC_FASTPAGE *
|
||||
Will use a faster handling of HotPage (Page being both executed and written)
|
||||
* 0 : use regular hotpage (Default)
|
||||
* 1 : Use faster hotpage, taking the risk of running obsolete JIT code (might be faster, but more prone to crash)
|
||||
|
||||
#### BOX86_DYNAREC_BLEEDING_EDGE *
|
||||
Detect MonoBleedingEdge and apply conservative settings
|
||||
* 0 : Don't detect MonoBleedingEdge
|
||||
* 1 : Detect MonoBleedingEdge, and apply BIGBLOCK=0 STRONGMEM=1 if detected (Default)
|
||||
|
||||
#### BOX86_DYNAREC_JVM *
|
||||
Detect libjvm and apply conservative settings
|
||||
* 0 : Don't detect libjvm
|
||||
* 1 : Detect libjvm, and apply BIGBLOCK=0 STRONGMEM=1 if detected (Default)
|
||||
|
||||
#### BOX86_DYNAREC_WAIT *
|
||||
Behavior with FillBlock is not availble (FillBlock build Dynarec blocks and is not multithreaded)
|
||||
* 0 : Dynarec will not wait for FillBlock to ready and use Interpreter instead (might speedup a bit massive multithread or JIT programs)
|
||||
* 1 : Dynarec will wait for FillBlock to be ready (Default)
|
||||
|
||||
#### BOX86_SSE_FLUSHTO0 *
|
||||
Handling of SSE Flush to 0 flags
|
||||
* 0 : Just track the flag (Default)
|
||||
@@ -190,6 +205,11 @@ Handling of x87 80bits long double
|
||||
* 0 : Try to handle 80bits long double as precise as possible (Default)
|
||||
* 1 : Handle them as double
|
||||
|
||||
#### BOX86_LIBCEF *
|
||||
Detect libcef and apply malloc_hack settings
|
||||
* 0 : Don't detect libcef
|
||||
* 1 : Detect libcef, and apply MALLOC_HACK=2 if detected (Default)
|
||||
|
||||
#### BOX86_LIBGL *
|
||||
* libXXXX set the name for libGL (defaults to libGL.so.1).
|
||||
* /PATH/TO/libGLXXX : Sets the name and path for libGL
|
||||
@@ -286,3 +306,8 @@ Will use yyyy as x86_64 interpretor, to launch x64_64 binaries
|
||||
|
||||
#### BOX86_NORCFILES
|
||||
If the env var exist, no rc files (like /etc/box86.box86rc and ~/.box86rc) will be loaded
|
||||
|
||||
#### BOX86_NOSANDBOX
|
||||
* 0 : Nothing special
|
||||
* 1 : Added "--no-sandbox" to command line arguments (usefull for chrome based programs)
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ rm ~/wine.tgz # clean up
|
||||
|
||||
# Install shortcuts (make launcher & symlinks. Credits: grayduck, Botspot)
|
||||
echo -e '#!/bin/bash\nsetarch linux32 -L '"$HOME/wine/bin/wine "'"$@"' | sudo tee -a /usr/local/bin/wine >/dev/null # Create a script to launch wine programs as 32bit only
|
||||
#sudo ln -s ~/wine/bin/wine /usr/local/bin/wine # You could aslo just make a symlink, but box86 only works for 32bit apps at the moment
|
||||
#sudo ln -s ~/wine/bin/wine /usr/local/bin/wine # You could also just make a symlink, but box86 only works for 32bit apps at the moment
|
||||
sudo ln -s ~/wine/bin/wineboot /usr/local/bin/wineboot
|
||||
sudo ln -s ~/wine/bin/winecfg /usr/local/bin/winecfg
|
||||
sudo ln -s ~/wine/bin/wineserver /usr/local/bin/wineserver
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ echo "#!/bin/bash
|
||||
export STEAMOS=1
|
||||
export STEAM_RUNTIME=1
|
||||
export DBUS_FATAL_WARNINGS=0
|
||||
~/steam/bin/steam -noreactlogin steam://open/minigameslist $@" > steam
|
||||
~/steam/bin/steam steam://open/minigameslist $@" > steam
|
||||
|
||||
# make script executable and move
|
||||
chmod +x steam
|
||||
|
||||
+1
-1
@@ -1834,7 +1834,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
|
||||
start = (start >> 4) + ((start & 0xF) << 1);
|
||||
}
|
||||
|
||||
char tmp[6];
|
||||
char tmp[7];
|
||||
for (int cur = start; cur < start + size - 1; ++cur) {
|
||||
sprintf(tmp, "%c%d, ", regChr, cur);
|
||||
strcat(ret, tmp);
|
||||
|
||||
+37
-14
@@ -679,12 +679,12 @@ class Clauses:
|
||||
return isinstance(o, Clauses) and (self.clauses == o.clauses)
|
||||
|
||||
JumbledFunctions = CustOrderedDictList[Clause, Function]
|
||||
FilesSpecific = Dict[Filename, FileSpec]
|
||||
FileSpecifics = Dict[Filename, FileSpec]
|
||||
|
||||
SortedGlobals = CustOrderedDictList[Clauses, FunctionType]
|
||||
SortedRedirects = CustOrderedDictList[Clauses, FunctionType]
|
||||
|
||||
def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions, FilesSpecific]:
|
||||
def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions, FileSpecifics]:
|
||||
"""
|
||||
readFiles
|
||||
|
||||
@@ -693,7 +693,7 @@ def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions,
|
||||
|
||||
gbls: JumbledFunctions = CustOrderedDictList()
|
||||
redirects: JumbledFunctions = CustOrderedDictList()
|
||||
filespecs: FilesSpecific = {}
|
||||
filespecs: FileSpecifics = {}
|
||||
|
||||
symbols: Dict[str, Filename] = {}
|
||||
need_halt: bool = False
|
||||
@@ -880,7 +880,7 @@ def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions,
|
||||
|
||||
return gbls, redirects, filespecs
|
||||
|
||||
def sortArrays(gbl_funcs: JumbledFunctions, red_funcs: JumbledFunctions, filespecs: FilesSpecific) \
|
||||
def sortArrays(gbl_funcs: JumbledFunctions, red_funcs: JumbledFunctions, filespecs: FileSpecifics) \
|
||||
-> Tuple[SortedGlobals, SortedRedirects]:
|
||||
# First sort file specific stuff
|
||||
for fn in filespecs:
|
||||
@@ -944,13 +944,13 @@ def sortArrays(gbl_funcs: JumbledFunctions, red_funcs: JumbledFunctions, filespe
|
||||
redirects[red_vals[funtype]].append(funtype)
|
||||
redirects.sort(key=Clauses.splitdef)
|
||||
|
||||
def fail(): assert(False)
|
||||
def fail(): assert False
|
||||
for clauses in redirects:
|
||||
redirects[clauses].sort(key=lambda v: fail() if v.redirected is None else v.splitchar() + v.redirected.splitchar())
|
||||
|
||||
return gbls, redirects
|
||||
|
||||
def checkRun(root: str, gbls: SortedGlobals, redirects: SortedRedirects, filesspec: FilesSpecific) -> Optional[str]:
|
||||
def checkRun(root: str, gbls: SortedGlobals, redirects: SortedRedirects, filespecs: FileSpecifics) -> Optional[str]:
|
||||
# Check if there was any new functions compared to last run
|
||||
functions_list: str = ""
|
||||
for clauses in gbls:
|
||||
@@ -960,18 +960,18 @@ def checkRun(root: str, gbls: SortedGlobals, redirects: SortedRedirects, filessp
|
||||
for v in redirects[clauses]:
|
||||
assert(v.redirected is not None)
|
||||
functions_list = functions_list + "#" + str(clauses) + " " + v.orig + " -> " + v.redirected.orig + "\n"
|
||||
for filename in sorted(filesspec.keys()):
|
||||
for filename in sorted(filespecs.keys()):
|
||||
functions_list = functions_list + filename + ":\n"
|
||||
for st in filesspec[filename].structs:
|
||||
struct = filesspec[filename].structs[st]
|
||||
for st in filespecs[filename].structs:
|
||||
struct = filespecs[filename].structs[st]
|
||||
functions_list = functions_list + \
|
||||
"% " + st + " " + struct.name + " " + struct.repl + "\n"
|
||||
for _bare in filesspec[filename].typedefs:
|
||||
for _bare in filespecs[filename].typedefs:
|
||||
functions_list = functions_list + "- " + _bare.orig + ":\n"
|
||||
for fn in filesspec[filename].typedefs[_bare]:
|
||||
for fn in filespecs[filename].typedefs[_bare]:
|
||||
if fn.no_dlsym: continue
|
||||
functions_list = functions_list + " - " + fn.name + "\n"
|
||||
for funtype in filesspec[filename].structsuses:
|
||||
for funtype in filespecs[filename].structsuses:
|
||||
assert(funtype.redirected is not None)
|
||||
functions_list = functions_list + "% " + funtype.orig + " -> " + funtype.redirected.orig + "\n"
|
||||
|
||||
@@ -992,7 +992,7 @@ def checkRun(root: str, gbls: SortedGlobals, redirects: SortedRedirects, filessp
|
||||
return functions_list
|
||||
|
||||
def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobals, redirects: SortedRedirects, \
|
||||
filespecs: FilesSpecific) -> None:
|
||||
filespecs: FileSpecifics) -> None:
|
||||
# Files header and guard
|
||||
files_header = {
|
||||
"wrapper.c": """
|
||||
@@ -1148,6 +1148,13 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
|
||||
for fhdr in files_header:
|
||||
files_guard[fhdr] = trim(files_guard[fhdr])
|
||||
|
||||
# TODO: put the informations below in a structure (like in box64, where
|
||||
# typedefs & co. are stored in an ABI-specific structure)
|
||||
|
||||
return_x87: str = "DKdf"
|
||||
if any(c not in FileSpec.values for c in return_x87):
|
||||
raise NotImplementedError("Invalid character")
|
||||
|
||||
# Typedefs
|
||||
# E v c w i I C W u U f d D K l L p V O S 2 P G N M s
|
||||
tdtypes = ["x86emu_t*", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "_2uint_struct_t", "void*", "void*", "...", "...", "void*"]
|
||||
@@ -1309,6 +1316,22 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
|
||||
if not clauses.empty():
|
||||
file.write("#endif\n")
|
||||
|
||||
# Finally, write predicate functions
|
||||
|
||||
# isRetX87Wrapper
|
||||
file.write("\nint isRetX87Wrapper(wrapper_t fun) {\n")
|
||||
for clauses in gbls:
|
||||
empty = True
|
||||
for funtype in gbls[clauses]:
|
||||
if funtype.orig[0] in return_x87: # TODO: put this in a function (functions would request the ABI for more info)
|
||||
if empty and (not clauses.empty()):
|
||||
file.write("#if " + str(clauses) + "\n")
|
||||
empty = False
|
||||
file.write("\tif (fun == &" + funtype.orig + ") return 1;\n")
|
||||
if not empty:
|
||||
file.write("#endif\n")
|
||||
file.write("\treturn 0;\n}\n")
|
||||
|
||||
file.write(files_guard["wrapper.c"].format(lbr="{", rbr="}", version=ver))
|
||||
|
||||
# Rewrite the wrapper.h file:
|
||||
@@ -1398,6 +1421,6 @@ if __name__ == '__main__':
|
||||
if v == "--":
|
||||
limit.append(i)
|
||||
Define.defines = list(map(DefineType, sys.argv[2:limit[0]]))
|
||||
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.0.0.10") != 0:
|
||||
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.0.0.11") != 0:
|
||||
exit(2)
|
||||
exit(0)
|
||||
+44
-15
@@ -212,7 +212,7 @@ box86context_t *NewBox86Context(int argc)
|
||||
#ifdef BUILD_LIB
|
||||
context->deferedInit = 0;
|
||||
#else
|
||||
context->deferedInit = 1;
|
||||
context->deferredInit = 1;
|
||||
#endif
|
||||
context->sel_serial = 1;
|
||||
|
||||
@@ -222,11 +222,12 @@ box86context_t *NewBox86Context(int argc)
|
||||
context->local_maplib = NewLibrarian(context, 1);
|
||||
context->versym = NewDictionnary();
|
||||
context->system = NewBridge();
|
||||
context->globaldefver = NewDefaultVersion();
|
||||
context->weakdefver = NewDefaultVersion();
|
||||
// Cannot use Bridge name as the map is not initialized yet
|
||||
// create vsyscall
|
||||
context->vsyscall = AddBridge(context->system, iFEv, x86Syscall, 0, NULL);
|
||||
addAlternate((void*)0xffffe400, (void*)context->vsyscall);
|
||||
// create exit bridge
|
||||
context->exit_bridge = AddBridge(context->system, NULL, NULL, 0, NULL);
|
||||
#ifdef BUILD_LIB
|
||||
context->box86lib = RTLD_DEFAULT; // not ideal
|
||||
#else
|
||||
@@ -248,6 +249,8 @@ box86context_t *NewBox86Context(int argc)
|
||||
context->canary[/*getrand(4)*/0] = 0;
|
||||
printf_log(LOG_DEBUG, "Setting up canary (for Stack protector) at GS:0x14, value:%08X\n", *(uint32_t*)context->canary);
|
||||
|
||||
context->globdata = NewMapSymbols();
|
||||
|
||||
initAllHelpers(context);
|
||||
|
||||
return context;
|
||||
@@ -290,8 +293,8 @@ void FreeBox86Context(box86context_t** context)
|
||||
if(ctx->zydis)
|
||||
DeleteX86Trace(ctx);
|
||||
|
||||
if(ctx->deferedInitList)
|
||||
box_free(ctx->deferedInitList);
|
||||
if(ctx->deferredInitList)
|
||||
box_free(ctx->deferredInitList);
|
||||
|
||||
/*box_free(ctx->argv);*/
|
||||
|
||||
@@ -352,12 +355,13 @@ void FreeBox86Context(box86context_t** context)
|
||||
}
|
||||
}
|
||||
|
||||
free_neededlib(&ctx->neededlibs);
|
||||
free_neededlib(ctx->neededlibs);
|
||||
ctx->neededlibs = NULL;
|
||||
|
||||
if(ctx->emu_sig)
|
||||
FreeX86Emu(&ctx->emu_sig);
|
||||
FreeDefaultVersion(&ctx->globaldefver);
|
||||
FreeDefaultVersion(&ctx->weakdefver);
|
||||
|
||||
FreeMapSymbols(&ctx->globdata);
|
||||
|
||||
finiAllHelpers(ctx);
|
||||
|
||||
@@ -379,20 +383,45 @@ void FreeBox86Context(box86context_t** context)
|
||||
}
|
||||
|
||||
int AddElfHeader(box86context_t* ctx, elfheader_t* head) {
|
||||
int idx = ctx->elfsize;
|
||||
if(idx==ctx->elfcap) {
|
||||
// resize...
|
||||
ctx->elfcap += 16;
|
||||
ctx->elfs = (elfheader_t**)box_realloc(ctx->elfs, sizeof(elfheader_t*) * ctx->elfcap);
|
||||
int idx = 0;
|
||||
while(idx<ctx->elfsize && ctx->elfs[idx]) idx++;
|
||||
if(idx == ctx->elfsize) {
|
||||
if(idx==ctx->elfcap) {
|
||||
// resize...
|
||||
ctx->elfcap += 16;
|
||||
ctx->elfs = (elfheader_t**)box_realloc(ctx->elfs, sizeof(elfheader_t*) * ctx->elfcap);
|
||||
}
|
||||
ctx->elfs[idx] = head;
|
||||
ctx->elfsize++;
|
||||
} else {
|
||||
ctx->elfs[idx] = head;
|
||||
}
|
||||
ctx->elfs[idx] = head;
|
||||
ctx->elfsize++;
|
||||
printf_log(LOG_DEBUG, "Adding \"%s\" as #%d in elf collection\n", ElfName(head), idx);
|
||||
return idx;
|
||||
}
|
||||
|
||||
void RemoveElfHeader(box86context_t* ctx, elfheader_t* head) {
|
||||
if(GetTLSBase(head)) {
|
||||
// should remove the tls info
|
||||
int tlsbase = GetTLSBase(head);
|
||||
/*if(tlsbase == -ctx->tlssize) {
|
||||
// not really correct, but will do for now
|
||||
ctx->tlssize -= GetTLSSize(head);
|
||||
if(!(++ctx->sel_serial))
|
||||
++ctx->sel_serial;
|
||||
}*/
|
||||
}
|
||||
for(int i=0; i<ctx->elfsize; ++i)
|
||||
if(ctx->elfs[i] == head) {
|
||||
ctx->elfs[i] = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int AddTLSPartition(box86context_t* context, int tlssize) {
|
||||
int oldsize = context->tlssize;
|
||||
// should in fact first try to map a hole, but rewinding all elfs and checking filled space, like with the mapmem utilities
|
||||
context->tlssize += tlssize;
|
||||
context->tlsdata = box_realloc(context->tlsdata, context->tlssize);
|
||||
memmove(context->tlsdata+tlssize, context->tlsdata, oldsize); // move to the top, using memmove as regions will probably overlap
|
||||
|
||||
+1
-1
@@ -3,6 +3,6 @@
|
||||
|
||||
#define BOX86_MAJOR 0
|
||||
#define BOX86_MINOR 3
|
||||
#define BOX86_REVISION 1
|
||||
#define BOX86_REVISION 2
|
||||
|
||||
#endif //__BOX86_VERSION_H_
|
||||
+566
-496
File diff suppressed because it is too large.
Load diff
@@ -390,6 +390,8 @@ Op is 20-27
|
||||
#define LDRD_IMM8(reg, addr, imm8) EMIT(c__ | 0b000<<25 | 1<<24 | (((imm8)<0)?0:1)<<23 | 1<<22 | 0<<21 | 0<<20 | ((reg) << 12) | ((addr) << 16) | ((abs(imm8))&0xf0)<<(8-4) | (0b1101<<4) | ((abs(imm8))&0x0f) )
|
||||
// ldrd reg, reg+1, [addr, +rm], reg must be even, reg+1 is implicit
|
||||
#define LDRD_REG(reg, addr, rm) EMIT(c__ | 0b000<<25 | 1<<24 | 1<<23 | 0<<22 | 0<<21 | 0<<20 | ((reg) << 12) | ((addr) << 16) | 0b1101<<4 | (rm) )
|
||||
// ldr reg, [pc+imm]
|
||||
#define LDR_literal(reg, imm12) EMIT(c__ | 0b010<<25 | 1<<24 | (((imm12)>=0)?1:0)<<23 | 0<<21 | 1<<20 | 0b1111<<16 | (reg)<<12 | (abs(imm12)))
|
||||
|
||||
// str reg, [addr, #+/-imm9]
|
||||
#define STR_IMM9(reg, addr, imm9) EMIT(0xe5000000 | (((imm9)<0)?0:1)<<23 | ((reg) << 12) | ((addr) << 16) | brIMM(imm9) )
|
||||
|
||||
@@ -335,9 +335,9 @@ NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 1 @<1> Rm @ param=1 char align[4
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> Rm @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> Rm @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
.extern LinkNext
|
||||
|
||||
.global arm_next
|
||||
.4byte 0 // NULL pointer before arm64_next, for getDB
|
||||
arm_next:
|
||||
// emu is r0
|
||||
//stm r0, {r4-r12,r14} // don't put put back reg value in emu, faster but more tricky to debug
|
||||
|
||||
@@ -159,7 +159,7 @@ const char* print_register_list_fpu(uint8_t start, uint8_t size, uint8_t double_
|
||||
start = (start >> 4) + ((start & 0xF) << 1);
|
||||
}
|
||||
|
||||
char tmp[6];
|
||||
char tmp[7];
|
||||
for (int cur = start; cur < start + size - 1; ++cur) {
|
||||
sprintf(tmp, "%c%d, ", regChr, cur);
|
||||
strcat(ret, tmp);
|
||||
@@ -3049,7 +3049,7 @@ const char* arm_print(uint32_t opcode) {
|
||||
int param1_1 = (opcode >> 5) & 0x1;
|
||||
int param2_1 = (opcode >> 4) & 0x1;
|
||||
|
||||
char align[4];
|
||||
char align[5];
|
||||
if (param2_1 == 1) {
|
||||
sprintf(align, ":%d", 16 << size);
|
||||
} else {
|
||||
@@ -3064,7 +3064,7 @@ const char* arm_print(uint32_t opcode) {
|
||||
int param1_1 = (opcode >> 5) & 0x1;
|
||||
int param2_1 = (opcode >> 4) & 0x1;
|
||||
|
||||
char align[4];
|
||||
char align[5];
|
||||
if (param2_1 == 1) {
|
||||
sprintf(align, ":%d", 16 << size);
|
||||
} else {
|
||||
@@ -3080,7 +3080,7 @@ const char* arm_print(uint32_t opcode) {
|
||||
int param1_1 = (opcode >> 5) & 0x1;
|
||||
int param2_1 = (opcode >> 4) & 0x1;
|
||||
|
||||
char align[4];
|
||||
char align[5];
|
||||
if (param2_1 == 1) {
|
||||
sprintf(align, ":%d", 16 << size);
|
||||
} else {
|
||||
|
||||
+175
-276
@@ -41,21 +41,37 @@ uint32_t X31_hash_code(void* addr, int len)
|
||||
return (uint32_t)h;
|
||||
}
|
||||
|
||||
dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct)
|
||||
dynablock_t* InvalidDynablock(dynablock_t* db, int need_lock)
|
||||
{
|
||||
if(!textsz) {
|
||||
printf_log(LOG_NONE, "Error, creating a NULL sized Dynablock\n");
|
||||
return NULL;
|
||||
if(db) {
|
||||
if(db->gone)
|
||||
return NULL; // already in the process of deletion!
|
||||
dynarec_log(LOG_DEBUG, "InvalidDynablock(%p), db->block=%p x86=%p:%p already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size-1, db->gone);
|
||||
if(need_lock)
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
// remove jumptable
|
||||
setJumpTableDefault(db->x86_addr);
|
||||
db->done = 0;
|
||||
db->gone = 1;
|
||||
if(need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
dynablocklist_t* ret = (dynablocklist_t*)box_calloc(1, sizeof(dynablocklist_t));
|
||||
ret->text = text;
|
||||
ret->textsz = textsz;
|
||||
if(direct && textsz) {
|
||||
ret->direct = (dynablock_t**)box_calloc(textsz, sizeof(dynablock_t*));
|
||||
if(!ret->direct) {printf_log(LOG_NONE, "Warning, fail to create direct block for dynablock @%p\n", (void*)text);}
|
||||
return db;
|
||||
}
|
||||
|
||||
void FreeInvalidDynablock(dynablock_t* db, int need_lock)
|
||||
{
|
||||
if(db) {
|
||||
if(!db->gone)
|
||||
return; // already in the process of deletion!
|
||||
dynarec_log(LOG_DEBUG, "FreeInvalidDynablock(%p), db->block=%p x86=%p:%p already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size-1, db->gone);
|
||||
if(need_lock)
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
FreeDynarecMap((uintptr_t)db->actual_block);
|
||||
customFree(db);
|
||||
if(need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
dynarec_log(LOG_DEBUG, "New Dynablocklist %p, from %p->%p\n", ret, (void*)text, (void*)(text+textsz));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FreeDynablock(dynablock_t* db, int need_lock)
|
||||
@@ -63,224 +79,100 @@ void FreeDynablock(dynablock_t* db, int need_lock)
|
||||
if(db) {
|
||||
if(db->gone)
|
||||
return; // already in the process of deletion!
|
||||
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x86=%p:%p already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size, db->gone);
|
||||
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x86=%p:%p already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size-1, db->gone);
|
||||
if(need_lock)
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
db->done = 0;
|
||||
db->gone = 1;
|
||||
// remove from direct if there
|
||||
uintptr_t startdb = db->parent->text;
|
||||
uintptr_t enddb = db->parent->text + db->parent->textsz;
|
||||
if(db->parent->direct) {
|
||||
uintptr_t addr = (uintptr_t)db->x86_addr;
|
||||
if(addr>=startdb && addr<enddb)
|
||||
db->parent->direct[addr-startdb] = NULL;
|
||||
}
|
||||
// remove jumptable
|
||||
setJumpTableDefault(db->x86_addr);
|
||||
// remove and free the sons
|
||||
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->block, db->size);
|
||||
FreeDynarecMap(db, (uintptr_t)db->block, db->size);
|
||||
box_free(db->instsize);
|
||||
|
||||
box_free(db);
|
||||
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->actual_block, db->size);
|
||||
db->done = 0;
|
||||
db->gone = 1;
|
||||
if(db->previous)
|
||||
FreeInvalidDynablock(db->previous, 0);
|
||||
FreeDynarecMap((uintptr_t)db->actual_block);
|
||||
customFree(db);
|
||||
if(need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
}
|
||||
|
||||
void FreeDynablockList(dynablocklist_t** dynablocks)
|
||||
{
|
||||
if(!dynablocks)
|
||||
return;
|
||||
if(!*dynablocks)
|
||||
return;
|
||||
dynarec_log(LOG_DEBUG, "Free Dynablocklist %p, with Direct Blocks %p\n", *dynablocks, (*dynablocks)->direct);
|
||||
if((*dynablocks)->direct) {
|
||||
for (int i=0; i<(*dynablocks)->textsz; ++i) {
|
||||
if((*dynablocks)->direct[i])
|
||||
FreeDynablock((*dynablocks)->direct[i], my_context?1:0);
|
||||
}
|
||||
box_free((*dynablocks)->direct);
|
||||
}
|
||||
(*dynablocks)->direct = NULL;
|
||||
|
||||
box_free(*dynablocks);
|
||||
*dynablocks = NULL;
|
||||
}
|
||||
|
||||
void MarkDynablock(dynablock_t* db)
|
||||
{
|
||||
if(db) {
|
||||
if(db->need_test)
|
||||
return; // already done
|
||||
db->need_test = 1;
|
||||
setJumpTableDefault(db->x86_addr);
|
||||
dynarec_log(LOG_DEBUG, "MarkDynablock %p %p-%p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1);
|
||||
if(!setJumpTableIfRef(db->x86_addr, db->jmpnext, db->block)) {
|
||||
dynablock_t* old = db;
|
||||
db = getDB((uintptr_t)old->x86_addr);
|
||||
if(!old->gone && db!=old) {
|
||||
printf_log(LOG_INFO, "Warning, couldn't mark block as dirty for %p, block=%p, current_block=%p\n", old->x86_addr, old, db);
|
||||
// the block is lost, need to invalidate it...
|
||||
old->gone = 1;
|
||||
old->done = 0;
|
||||
if(!db || db->previous)
|
||||
FreeInvalidDynablock(old, 1);
|
||||
else
|
||||
db->previous = old;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t StartDynablockList(dynablocklist_t* db)
|
||||
{
|
||||
if(db)
|
||||
return db->text;
|
||||
return 0;
|
||||
}
|
||||
uintptr_t EndDynablockList(dynablocklist_t* db)
|
||||
{
|
||||
if(db)
|
||||
return db->text+db->textsz-1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2, uintptr_t end2)
|
||||
static int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2, uintptr_t end2)
|
||||
{
|
||||
if(start1 > end2 || start2 > end1)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
|
||||
static int MarkedDynablock(dynablock_t* db)
|
||||
{
|
||||
if(!dynablocks)
|
||||
return;
|
||||
if(!dynablocks->direct)
|
||||
return;
|
||||
uintptr_t startdb = dynablocks->text;
|
||||
uintptr_t enddb = startdb + dynablocks->textsz -1;
|
||||
uintptr_t start = addr;
|
||||
uintptr_t end = addr+size-1;
|
||||
if(start<startdb)
|
||||
start = startdb;
|
||||
if(end>enddb)
|
||||
end = enddb;
|
||||
dynablock_t *db;
|
||||
if(end>startdb && start<enddb)
|
||||
for(uintptr_t i = start; i<end; ++i)
|
||||
if((db=dynablocks->direct[i-startdb]))
|
||||
if(IntervalIntersects((uintptr_t)db->x86_addr, (uintptr_t)db->x86_addr+db->x86_size-1, addr, addr+size+1))
|
||||
MarkDynablock(db);
|
||||
}
|
||||
|
||||
void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
if(!dynablocks)
|
||||
return;
|
||||
|
||||
if(dynablocks->direct) {
|
||||
int need_lock = my_context?1:0;
|
||||
dynablock_t* db;
|
||||
int ret;
|
||||
khint_t k;
|
||||
kh_dynablocks_t *blocks = kh_init(dynablocks);
|
||||
// copy in a temporary list
|
||||
if(dynablocks->direct) {
|
||||
uintptr_t startdb = dynablocks->text;
|
||||
uintptr_t enddb = startdb + dynablocks->textsz;
|
||||
uintptr_t start = addr;
|
||||
uintptr_t end = addr+size;
|
||||
if(start<startdb)
|
||||
start = startdb;
|
||||
if(end>enddb)
|
||||
end = enddb;
|
||||
if(end>startdb && start<enddb)
|
||||
for(uintptr_t i = start; i<end; ++i) {
|
||||
db = (dynablock_t*)arm_lock_xchg(&dynablocks->direct[i-startdb], 0);
|
||||
if(db) {
|
||||
if(db->parent==dynablocks) {
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
|
||||
kh_value(blocks, k) = db;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// purge the list
|
||||
kh_foreach_value(blocks, db,
|
||||
FreeDynablock(db, need_lock);
|
||||
);
|
||||
kh_destroy(dynablocks, blocks);
|
||||
if(db) {
|
||||
if(getNeedTest((uintptr_t)db->x86_addr))
|
||||
return 1; // already done
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
|
||||
|
||||
void MarkRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
if(!dynablocks)
|
||||
// Mark will try to find *any* blocks that intersect the range to mark
|
||||
if(!db)
|
||||
return;
|
||||
if(dynablocks->direct) {
|
||||
uintptr_t new_addr = addr - dynablocks->maxsz;
|
||||
uintptr_t new_size = size + dynablocks->maxsz;
|
||||
MarkDirectDynablock(dynablocks, new_addr, new_size);
|
||||
// the blocks check before
|
||||
for(int idx=(new_addr)>>DYNAMAP_SHIFT; idx<(addr>>DYNAMAP_SHIFT); ++idx)
|
||||
MarkDirectDynablock(getDB(idx), new_addr, new_size);
|
||||
dynarec_log(LOG_DEBUG, "MarkRangeDynablock %p-%p .. startdb=%p, sizedb=%p\n", (void*)addr, (void*)addr+size-1, (void*)db->x86_addr, (void*)db->x86_size);
|
||||
if(IntervalIntersects((uintptr_t)db->x86_addr, (uintptr_t)db->x86_addr+db->x86_size-1, addr, addr+size+1))
|
||||
MarkDynablock(db);
|
||||
}
|
||||
|
||||
int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
if(!db)
|
||||
return 1;
|
||||
|
||||
int need_lock = my_context?1:0;
|
||||
if(IntervalIntersects((uintptr_t)db->x86_addr, (uintptr_t)db->x86_addr+db->x86_size-1, addr, addr+size+1)) {
|
||||
FreeDynablock(db, need_lock);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
dynablock_t* FindDynablockDynablocklist(void* addr, kh_dynablocks_t* dynablocks)
|
||||
dynablock_t *AddNewDynablock(uintptr_t addr)
|
||||
{
|
||||
if(!dynablocks)
|
||||
return NULL;
|
||||
dynablock_t* db;
|
||||
kh_foreach_value(dynablocks, db,
|
||||
const uintptr_t s = (uintptr_t)db->block;
|
||||
const uintptr_t e = (uintptr_t)db->block+db->size;
|
||||
if((uintptr_t)addr>=s && (uintptr_t)addr<e)
|
||||
return db;
|
||||
)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static dynablocklist_t* getDBFromAddress(uintptr_t addr)
|
||||
{
|
||||
const int idx = (addr>>DYNAMAP_SHIFT);
|
||||
return getDB(idx);
|
||||
}
|
||||
|
||||
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* created)
|
||||
{
|
||||
if(!dynablocks) {
|
||||
dynarec_log(LOG_INFO, "Warning: Ask to create a dynablock with a NULL dynablocklist (addr=%p)\n", (void*)addr);
|
||||
*created = 0;
|
||||
dynablock_t* block;
|
||||
#if 0
|
||||
// check if memory as the correct flags
|
||||
int prot = getProtection(addr);
|
||||
if(!(prot&(PROT_EXEC|PROT_DYNAREC|PROT_DYNAREC_R))) {
|
||||
dynarec_log(LOG_VERBOSE, "Block asked on a memory with no execution flags 0x%02X\n", prot);
|
||||
return NULL;
|
||||
}
|
||||
if((addr<dynablocks->text) || (addr>=(dynablocks->text+dynablocks->textsz))) {
|
||||
// this should be useless
|
||||
//dynarec_log(LOG_INFO, "Warning: Refused to create a Direct Block that is out-of-bound: dynablocks=%p (%p:%p), addr=%p\n", dynablocks, (void*)(dynablocks->text), (void*)(dynablocks->text+dynablocks->textsz), (void*)addr);
|
||||
//*created = 0;
|
||||
//return NULL;
|
||||
return AddNewDynablock(getDBFromAddress(addr), addr, created);
|
||||
}
|
||||
dynablock_t* block = NULL;
|
||||
// first, check if it exist in direct access mode
|
||||
if(dynablocks->direct) {
|
||||
block = dynablocks->direct[addr-dynablocks->text];
|
||||
if(block) {
|
||||
dynarec_log(LOG_VERBOSE, "Block already exist in Direct Map\n");
|
||||
*created = 0;
|
||||
return block;
|
||||
}
|
||||
}
|
||||
|
||||
if (!*created)
|
||||
return block;
|
||||
|
||||
if(!dynablocks->direct) {
|
||||
dynablock_t** p = (dynablock_t**)box_calloc(dynablocks->textsz, sizeof(dynablock_t*));
|
||||
if(arm_lock_storeifnull(&dynablocks->direct, p)!=NULL)
|
||||
box_free(p); // someone already create the direct array, too late...
|
||||
}
|
||||
|
||||
#endif
|
||||
// create and add new block
|
||||
dynarec_log(LOG_VERBOSE, "Ask for DynaRec Block creation @%p\n", (void*)addr);
|
||||
|
||||
block = (dynablock_t*)box_calloc(1, sizeof(dynablock_t));
|
||||
block->parent = dynablocks;
|
||||
dynablock_t* tmp = (dynablock_t*)arm_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], block, NULL);
|
||||
if(tmp != block) {
|
||||
// a block appeard!
|
||||
box_free(block);
|
||||
*created = 0;
|
||||
return tmp;
|
||||
}
|
||||
*created = 1;
|
||||
block = (dynablock_t*)customCalloc(1, sizeof(dynablock_t));
|
||||
return block;
|
||||
}
|
||||
|
||||
@@ -296,118 +188,117 @@ void cancelFillBlock()
|
||||
return NULL if block is not found / cannot be created.
|
||||
Don't create if create==0
|
||||
*/
|
||||
static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current, int need_lock)
|
||||
static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, int need_lock)
|
||||
{
|
||||
if(hasAlternate((void*)addr))
|
||||
return NULL;
|
||||
// try the quickest way first: get parent of current and check if ok!
|
||||
dynablocklist_t *dynablocks = NULL;
|
||||
dynablock_t* block = NULL;
|
||||
if(current && current->done) {
|
||||
dynablocks = current->parent;
|
||||
if(dynablocks && !(addr>=dynablocks->text && addr<(dynablocks->text+dynablocks->textsz)))
|
||||
dynablocks = NULL;
|
||||
}
|
||||
// nope, lets do the long way
|
||||
if(!dynablocks) {
|
||||
dynablocks = getDBFromAddress(addr);
|
||||
if(!dynablocks) {
|
||||
dynablocks = GetDynablocksFromAddress(emu->context, addr);
|
||||
if(!dynablocks)
|
||||
dynablock_t* block = getDB(addr);
|
||||
if(block || !create)
|
||||
return block;
|
||||
|
||||
if(need_lock) {
|
||||
if(box86_dynarec_wait) {
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
} else {
|
||||
if(mutex_trylock(&my_context->mutex_dyndump)) // FillBlock not available for now
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
// check direct first, without lock
|
||||
if(dynablocks->direct/* && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz))*/)
|
||||
if((block = dynablocks->direct[addr-dynablocks->text]))
|
||||
return block;
|
||||
|
||||
int created = create;
|
||||
if(need_lock)
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
block = AddNewDynablock(dynablocks, addr, &created);
|
||||
if(!created) {
|
||||
if(need_lock)
|
||||
block = getDB(addr); // just in case
|
||||
if(block) {
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
return block; // existing block...
|
||||
return block;
|
||||
}
|
||||
}
|
||||
|
||||
block = AddNewDynablock(addr);
|
||||
|
||||
// fill the block
|
||||
block->x86_addr = (void*)addr;
|
||||
if(sigsetjmp(&dynarec_jmpbuf, 1)) {
|
||||
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr);
|
||||
FreeDynablock(block, 0);
|
||||
if(need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
return NULL;
|
||||
}
|
||||
void* ret = FillBlock(block, filladdr);
|
||||
if(need_lock)
|
||||
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*)arm_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], 0, 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 been written
|
||||
}
|
||||
box_free(block);
|
||||
customFree(block);
|
||||
block = NULL;
|
||||
}
|
||||
// check size
|
||||
if(block && block->x86_size) {
|
||||
if(block) {
|
||||
int blocksz = block->x86_size;
|
||||
if(dynablocks->maxsz<blocksz) {
|
||||
dynablocks->maxsz = blocksz;
|
||||
for(int idx=(addr>>DYNAMAP_SHIFT)+1; idx<=((addr+blocksz)>>DYNAMAP_SHIFT); ++idx) {
|
||||
dynablocklist_t* dblist;
|
||||
if((dblist = getDB(idx)))
|
||||
if(dblist->maxsz<blocksz)
|
||||
dblist->maxsz = blocksz;
|
||||
}
|
||||
}
|
||||
//protectDB((uintptr_t)block->x86_addr, block->x86_size); // already protected in FillBlock
|
||||
// but check if it already need test
|
||||
if(block->need_test)
|
||||
return NULL;
|
||||
if(blocksz>my_context->max_db_size)
|
||||
my_context->max_db_size = blocksz;
|
||||
// fill-in jumptable
|
||||
addJumpTableIfDefault(block->x86_addr, block->block);
|
||||
if(!addJumpTableIfDefault(block->x86_addr, block->dirty?block->jmpnext:block->block)) {
|
||||
FreeDynablock(block, 0);
|
||||
block = getDB(addr);
|
||||
MarkDynablock(block); // just in case...
|
||||
} else {
|
||||
if(block->x86_size)
|
||||
block->done = 1; // don't validate the block if the size is null, but keep the block
|
||||
}
|
||||
}
|
||||
if(need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
|
||||
dynarec_log(LOG_DEBUG, " --- DynaRec Block %s @%p:%p (%p, 0x%x bytes)\n", created?"created":"recycled", (void*)addr, (void*)(addr+((block)?block->x86_size:0)), (block)?block->block:0, (block)?block->size:0);
|
||||
dynarec_log(LOG_DEBUG, "%04d| --- DynaRec Block created @%p:%p (%p, 0x%x bytes)\n", GetTID(), (void*)addr, (void*)(addr+((block)?block->x86_size:1)-1), (block)?block->block:0, (block)?block->size:0);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t** current)
|
||||
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create)
|
||||
{
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current, 1);
|
||||
if(db && db->done && db->block && (db->need_test)) {
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, 1);
|
||||
if(db && db->done && db->block && getNeedTest(addr)) {
|
||||
if(db->always_test)
|
||||
sched_yield(); // just calm down...
|
||||
if(AreaInHotPage((uintptr_t)db->x86_addr, (uintptr_t)db->x86_addr + db->x86_size - 1)) {
|
||||
emu->test.test = 0;
|
||||
dynarec_log(LOG_DEBUG, "Not running block %p from %p:%p with for %p because it's in a hotpage\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, (void*)addr);
|
||||
return NULL;
|
||||
if(box86_dynarec_fastpage) {
|
||||
uint32_t hash = X31_hash_code(db->x86_addr, db->x86_size);
|
||||
if(hash==db->hash) { // seems ok, run it without reprotecting it
|
||||
setJumpTableIfRef(db->x86_addr, db->block, db->jmpnext);
|
||||
return db;
|
||||
}
|
||||
db->done = 0; // invalidating the block, it's already not good
|
||||
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, hash, db->hash, (void*)addr);
|
||||
// Free db, it's now invalid!
|
||||
FreeDynablock(db, 1);
|
||||
return NULL; // not building a new one, it's still a hotpage
|
||||
} else {
|
||||
dynarec_log(LOG_INFO, "Not running block %p from %p:%p with for %p because it's in a hotpage\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if(mutex_trylock(&my_context->mutex_dyndump)) {
|
||||
emu->test.test = 0;
|
||||
return NULL;
|
||||
}
|
||||
uint32_t hash = (getProtection((uintptr_t)db->x86_addr)&PROT_READ)?X31_hash_code(db->x86_addr, db->x86_size):0;
|
||||
uint32_t hash = X31_hash_code(db->x86_addr, db->x86_size);
|
||||
int need_lock = mutex_trylock(&my_context->mutex_dyndump);
|
||||
if(hash!=db->hash) {
|
||||
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size, hash, db->hash, (void*)addr);
|
||||
// no more current if it gets invalidated too
|
||||
if(*current && db->x86_addr>=(*current)->x86_addr && (db->x86_addr+db->x86_size)<(*current)->x86_addr)
|
||||
*current = NULL;
|
||||
db->done = 0; // invalidating the block
|
||||
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, hash, db->hash, (void*)addr);
|
||||
// Free db, it's now invalid!
|
||||
FreeDynablock(db, 0);
|
||||
dynablock_t* old = InvalidDynablock(db, need_lock);
|
||||
// start again... (will create a new block)
|
||||
db = internalDBGetBlock(emu, addr, addr, create, *current, 0);
|
||||
db = internalDBGetBlock(emu, addr, addr, create, need_lock);
|
||||
if(db) {
|
||||
if(db->previous)
|
||||
FreeInvalidDynablock(db->previous, need_lock);
|
||||
db->previous = old;
|
||||
} else
|
||||
FreeInvalidDynablock(old, need_lock);
|
||||
} else {
|
||||
db->need_test = 0;
|
||||
dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, db->hash, (void*)addr);
|
||||
protectDB((uintptr_t)db->x86_addr, db->x86_size);
|
||||
// fill back jumptable
|
||||
addJumpTableIfDefault(db->x86_addr, db->block);
|
||||
if(isprotectedDB((uintptr_t)db->x86_addr, db->x86_size) && !db->always_test) {
|
||||
setJumpTableIfRef(db->x86_addr, db->block, db->jmpnext);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
if(!need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
if(!db || !db->block || !db->done)
|
||||
emu->test.test = 0;
|
||||
@@ -418,26 +309,34 @@ dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "Creating AlternateBlock at %p for %p\n", (void*)addr, (void*)filladdr);
|
||||
int create = 1;
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 1);
|
||||
if(db && db->done && db->block && (db->need_test)) {
|
||||
if(mutex_trylock(&my_context->mutex_dyndump)) {
|
||||
emu->test.test = 0;
|
||||
return NULL;
|
||||
}
|
||||
uint32_t hash = (getProtection((uintptr_t)db->x86_addr)&PROT_READ)?X31_hash_code(db->x86_addr, db->x86_size):0;
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, 1);
|
||||
if(db && db->done && db->block && getNeedTest(filladdr)) {
|
||||
if(db->always_test)
|
||||
sched_yield(); // just calm down...
|
||||
int need_lock = mutex_trylock(&my_context->mutex_dyndump);
|
||||
uint32_t hash = X31_hash_code(db->x86_addr, db->x86_size);
|
||||
if(hash!=db->hash) {
|
||||
db->done = 0; // invalidating the block
|
||||
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size, hash, db->hash, (void*)addr);
|
||||
// Free db, it's now invalid!
|
||||
FreeDynablock(db, 0);
|
||||
dynablock_t* old = InvalidDynablock(db, need_lock);
|
||||
// start again... (will create a new block)
|
||||
db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 0);
|
||||
db = internalDBGetBlock(emu, addr, filladdr, create, need_lock);
|
||||
if(db) {
|
||||
if(db->previous)
|
||||
FreeInvalidDynablock(db->previous, need_lock);
|
||||
db->previous = old;
|
||||
} else
|
||||
FreeInvalidDynablock(old, need_lock);
|
||||
} else {
|
||||
db->need_test = 0;
|
||||
protectDB((uintptr_t)db->x86_addr, db->x86_size);
|
||||
// fill back jumptable
|
||||
addJumpTableIfDefault(db->x86_addr, db->block);
|
||||
if(isprotectedDB((uintptr_t)db->x86_addr, db->x86_size) && !db->always_test) {
|
||||
setJumpTableIfRef(db->x86_addr, db->block, db->jmpnext);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
if(!need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
if(!db || !db->block || !db->done)
|
||||
emu->test.test = 0;
|
||||
|
||||
@@ -1,33 +1,26 @@
|
||||
#ifndef __DYNABLOCK_PRIVATE_H_
|
||||
#define __DYNABLOCK_PRIVATE_H_
|
||||
|
||||
typedef struct dynablocklist_s dynablocklist_t;
|
||||
|
||||
typedef struct instsize_s {
|
||||
unsigned char x86:4;
|
||||
unsigned char nat:4;
|
||||
} instsize_t;
|
||||
|
||||
typedef struct dynablock_s {
|
||||
dynablocklist_t* parent;
|
||||
void* block;
|
||||
void* block; // block-sizeof(void*) == self
|
||||
void* actual_block; // the actual start of the block (so block-sizeof(void*))
|
||||
struct dynablock_s* previous; // a previous block that might need to be freed
|
||||
int size;
|
||||
void* x86_addr;
|
||||
uintptr_t x86_size;
|
||||
uint32_t hash;
|
||||
uint8_t need_test;
|
||||
uint8_t done;
|
||||
uint8_t gone;
|
||||
uint8_t dummy;
|
||||
uint8_t always_test;
|
||||
uint8_t dirty; // if need to be tested as soon as it's created
|
||||
int isize;
|
||||
instsize_t* instsize;
|
||||
void* jmpnext; // a branch jmpnext code when block is marked
|
||||
} dynablock_t;
|
||||
|
||||
typedef struct dynablocklist_s {
|
||||
uintptr_t text;
|
||||
int textsz;
|
||||
int maxsz; // maxblock size (for this block or previous block)
|
||||
dynablock_t** direct; // direct mapping (waste of space, so the array is created at first write)
|
||||
} dynablocklist_t;
|
||||
|
||||
#endif //__DYNABLOCK_PRIVATE_H_
|
||||
+18
-17
@@ -45,26 +45,27 @@ void* LinkNext(x86emu_t* emu, uintptr_t addr, void* x2)
|
||||
printf_log(LOG_NONE, "Warning, jumping to NULL address from %p (db=%p, x86addr=%p/%s)\n", x2, db, x86addr, pcname);
|
||||
}
|
||||
#endif
|
||||
dynablock_t* current = NULL;
|
||||
void * jblock;
|
||||
dynablock_t* block = DBGetBlock(emu, addr, 1, ¤t);
|
||||
dynablock_t* block = NULL;
|
||||
if(hasAlternate((void*)addr)) {
|
||||
printf_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr);
|
||||
addr = (uintptr_t)getAlternate((void*)addr);
|
||||
R_EIP = addr;
|
||||
printf_log(LOG_INFO, " -> %p\n", (void*)addr);
|
||||
block = DBGetBlock(emu, addr, 1);
|
||||
} else
|
||||
block = DBGetBlock(emu, addr, 1);
|
||||
if(!block) {
|
||||
// no block, let link table as is...
|
||||
if(hasAlternate((void*)addr)) {
|
||||
printf_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr);
|
||||
addr = (uintptr_t)getAlternate((void*)addr);
|
||||
R_EIP = addr;
|
||||
printf_log(LOG_INFO, " -> %p\n", (void*)addr);
|
||||
block = DBGetBlock(emu, addr, 1, ¤t);
|
||||
}
|
||||
if(!block) {
|
||||
#ifdef HAVE_TRACE
|
||||
#ifdef HAVE_TRACE
|
||||
if(LOG_INFO<=box86_dynarec_log) {
|
||||
dynablock_t* db = FindDynablockFromNativeAddress(x2);
|
||||
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x86addr=%p)\n", (void*)addr, x2, db, db?(void*)getX86Address(db, (uintptr_t)x2):NULL);
|
||||
#endif
|
||||
//tableupdate(arm_epilog, addr, table);
|
||||
return arm_epilog;
|
||||
elfheader_t* h = FindElfAddress(my_context, (uintptr_t)x2);
|
||||
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p(elf=%s))\n", (void*)addr, x2, db, db?(void*)getX86Address(db, (uintptr_t)x2-4):NULL, h?ElfName(h):"(none)");
|
||||
}
|
||||
#endif
|
||||
//tableupdate(arm_epilog, addr, table);
|
||||
return arm_epilog;
|
||||
}
|
||||
if(!block->done) {
|
||||
// not finished yet... leave linker
|
||||
@@ -125,7 +126,7 @@ void DynaCall(x86emu_t* emu, uintptr_t addr)
|
||||
dynablock_t* block = NULL;
|
||||
dynablock_t* current = NULL;
|
||||
while(!emu->quit) {
|
||||
block = (skip==2)?NULL:DBGetBlock(emu, R_EIP, 1, ¤t);
|
||||
block = (skip==2)?NULL:DBGetBlock(emu, R_EIP, 1);
|
||||
current = block;
|
||||
if(!block || !block->block || !block->done) {
|
||||
skip = 0;
|
||||
@@ -220,7 +221,7 @@ int DynaRun(x86emu_t* emu)
|
||||
dynablock_t* block = NULL;
|
||||
dynablock_t* current = NULL;
|
||||
while(!emu->quit) {
|
||||
block = (skip==2)?NULL:DBGetBlock(emu, R_EIP, 1, ¤t);
|
||||
block = (skip==2)?NULL:DBGetBlock(emu, R_EIP, 1);
|
||||
current = block;
|
||||
if(!block || !block->block || !block->done) {
|
||||
skip = 0;
|
||||
|
||||
+138
-91
@@ -73,8 +73,8 @@ void add_next(dynarec_arm_t *dyn, uintptr_t addr) {
|
||||
}
|
||||
// add slots
|
||||
if(dyn->next_sz == dyn->next_cap) {
|
||||
dyn->next_cap += 16;
|
||||
dyn->next = (uintptr_t*)box_realloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
|
||||
dyn->next_cap += 64;
|
||||
dyn->next = (uintptr_t*)dynaRealloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
|
||||
}
|
||||
dyn->next[dyn->next_sz++] = addr;
|
||||
}
|
||||
@@ -243,35 +243,31 @@ int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n)
|
||||
return (i==n)?1:0;
|
||||
}
|
||||
|
||||
static instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x86_size, int arm_size)
|
||||
void addInst(instsize_t* insts, size_t* size, int x86_size, int native_size)
|
||||
{
|
||||
// x86 instruction is <16 bytes
|
||||
int toadd;
|
||||
if(x86_size>arm_size)
|
||||
if(x86_size>native_size)
|
||||
toadd = 1 + x86_size/15;
|
||||
else
|
||||
toadd = 1 + arm_size/15;
|
||||
if((*size)+toadd>(*cap)) {
|
||||
*cap = (*size)+toadd;
|
||||
insts = (instsize_t*)box_realloc(insts, (*cap)*sizeof(instsize_t));
|
||||
}
|
||||
toadd = 1 + native_size/15;
|
||||
while(toadd) {
|
||||
if(x86_size>15)
|
||||
insts[*size].x86 = 15;
|
||||
else
|
||||
insts[*size].x86 = x86_size;
|
||||
x86_size -= insts[*size].x86;
|
||||
if(arm_size>15)
|
||||
if(native_size>15)
|
||||
insts[*size].nat = 15;
|
||||
else
|
||||
insts[*size].nat = arm_size;
|
||||
arm_size -= insts[*size].nat;
|
||||
insts[*size].nat = native_size;
|
||||
native_size -= insts[*size].nat;
|
||||
++(*size);
|
||||
--toadd;
|
||||
}
|
||||
return insts;
|
||||
}
|
||||
|
||||
|
||||
static void fillPredecessors(dynarec_arm_t* dyn)
|
||||
{
|
||||
int pred_sz = 1; // to be safe
|
||||
@@ -283,6 +279,13 @@ static void fillPredecessors(dynarec_arm_t* dyn)
|
||||
++dyn->insts[dyn->insts[i].x86.jmp_insts].pred_sz;
|
||||
}
|
||||
}
|
||||
// remove "has_next" from orphean branch
|
||||
for(int i=0; i<dyn->size-1; ++i) {
|
||||
if(!dyn->insts[i].x86.has_next) {
|
||||
if(dyn->insts[i+1].x86.has_next && !dyn->insts[i+1].pred_sz)
|
||||
dyn->insts[i+1].x86.has_next = 0;
|
||||
}
|
||||
}
|
||||
// second the "has_next"
|
||||
for(int i=0; i<dyn->size-1; ++i) {
|
||||
if(dyn->insts[i].x86.has_next) {
|
||||
@@ -290,7 +293,7 @@ static void fillPredecessors(dynarec_arm_t* dyn)
|
||||
++dyn->insts[i+1].pred_sz;
|
||||
}
|
||||
}
|
||||
dyn->predecessor = (int*)box_malloc(pred_sz*sizeof(int));
|
||||
dyn->predecessor = (int*)dynaMalloc(pred_sz*sizeof(int));
|
||||
// fill pred pointer
|
||||
int* p = dyn->predecessor;
|
||||
for(int i=0; i<dyn->size; ++i) {
|
||||
@@ -307,8 +310,6 @@ static void fillPredecessors(dynarec_arm_t* dyn)
|
||||
dyn->insts[j].pred[dyn->insts[j].pred_sz++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// updateNeed goes backward, from last intruction to top
|
||||
@@ -351,43 +352,77 @@ static int updateNeed(dynarec_arm_t* dyn, int ninst, uint8_t need) {
|
||||
else
|
||||
updateNeed(dyn, dyn->insts[ninst].pred[i], need);
|
||||
}
|
||||
if(!ok)
|
||||
return ninst - 1;
|
||||
--ninst;
|
||||
if(!ok)
|
||||
return ninst;
|
||||
}
|
||||
return ninst;
|
||||
}
|
||||
|
||||
void* current_helper = NULL;
|
||||
|
||||
void CancelBlock(int need_lock)
|
||||
{
|
||||
if(need_lock)
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
dynarec_arm_t* helper = (dynarec_arm_t*)current_helper;
|
||||
current_helper = NULL;
|
||||
if(helper) {
|
||||
dynaFree(helper->next);
|
||||
dynaFree(helper->insts);
|
||||
dynaFree(helper->predecessor);
|
||||
if(helper->dynablock && helper->dynablock->actual_block) {
|
||||
FreeDynarecMap((uintptr_t)helper->dynablock->actual_block);
|
||||
helper->dynablock->actual_block = NULL;
|
||||
}
|
||||
}
|
||||
if(need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
|
||||
uintptr_t arm_pass0(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
uintptr_t arm_pass1(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
uintptr_t arm_pass2(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
uintptr_t arm_pass3(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
|
||||
void* current_helper = NULL;
|
||||
|
||||
void CancelBlock()
|
||||
{
|
||||
dynarec_arm_t* helper = (dynarec_arm_t*)current_helper;
|
||||
current_helper = NULL;
|
||||
if(!helper)
|
||||
return;
|
||||
box_free(helper->next);
|
||||
box_free(helper->insts);
|
||||
box_free(helper->predecessor);
|
||||
if(helper->dynablock && helper->dynablock->block)
|
||||
FreeDynarecMap(helper->dynablock, (uintptr_t)helper->dynablock->block, helper->dynablock->size);
|
||||
}
|
||||
void arm_epilog();
|
||||
void arm_next();
|
||||
|
||||
void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
|
||||
block->isize = 0;
|
||||
block->done = 0;
|
||||
block->size = 0;
|
||||
block->block = NULL;
|
||||
block->need_test = 0;
|
||||
size_t sz = 8*sizeof(void*);
|
||||
void* actual_p = (void*)AllocDynarecMap(sz);
|
||||
void* p = actual_p + sizeof(void*);
|
||||
if(actual_p==NULL) {
|
||||
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
|
||||
CancelBlock(0);
|
||||
return NULL;
|
||||
}
|
||||
block->size = sz;
|
||||
block->actual_block = actual_p;
|
||||
block->block = p;
|
||||
block->jmpnext = p;
|
||||
*(dynablock_t**)actual_p = block;
|
||||
*(void**)(p+4*sizeof(void*)) = arm_epilog;
|
||||
CreateJmpNext(block->jmpnext, p+4*sizeof(void*));
|
||||
// all done...
|
||||
__clear_cache(actual_p, actual_p+sz); // need to clear the cache before execution...
|
||||
return block;
|
||||
}
|
||||
|
||||
void* FillBlock(dynablock_t* block, uintptr_t addr) {
|
||||
/*
|
||||
A Block must have this layout:
|
||||
|
||||
0x0000..0x0003 : dynablock_t* : self
|
||||
0x0004..4+4*n : actual Native instructions, (n is the total number)
|
||||
B .. B+3 : dynablock_t* : self (as part of JmpNext, that simulate another block)
|
||||
B+4 .. B+15 : 3 Native code for jmpnext (or jmp epilog in case of empty block)
|
||||
B+16 .. B+19 : jmpnext (or jmp_epilog) address
|
||||
B+20 .. B+31 : empty (in case an architecture needs more than 3 opcodes)
|
||||
B+32 .. B+32+sz : instsize (compressed array with each instruction lenght on x86 and native side)
|
||||
|
||||
*/
|
||||
dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
if(IsInHotPage(addr)) {
|
||||
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock on hotpage for %p\n", (void*)addr);
|
||||
@@ -397,10 +432,6 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
dynarec_log(LOG_DEBUG, "Asked to fill a block in fobidden zone\n");
|
||||
return CreateEmptyBlock(block, addr);
|
||||
}
|
||||
if(!isJumpTableDefault((void*)addr)) {
|
||||
dynarec_log(LOG_DEBUG, "Asked to fill a block at %p, but JumpTable is not default\n", (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
if(current_helper) {
|
||||
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock at %p as anothor one is going on\n", (void*)addr);
|
||||
return NULL;
|
||||
@@ -414,23 +445,23 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
helper.start = addr;
|
||||
uintptr_t start = addr;
|
||||
helper.cap = 64; // needs epilog handling
|
||||
helper.insts = (instruction_arm_t*)box_calloc(helper.cap, sizeof(instruction_arm_t));
|
||||
helper.insts = (instruction_arm_t*)dynaCalloc(helper.cap, sizeof(instruction_arm_t));
|
||||
// pass 0, addresses, x86 jump addresses, overall size of the block
|
||||
uintptr_t end = arm_pass0(&helper, addr);
|
||||
// no need for next anymore
|
||||
box_free(helper.next);
|
||||
dynaFree(helper.next);
|
||||
helper.next_sz = helper.next_cap = 0;
|
||||
helper.next = NULL;
|
||||
// basic checks
|
||||
if(!helper.size) {
|
||||
dynarec_log(LOG_DEBUG, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
|
||||
CancelBlock();
|
||||
return (void*)block;
|
||||
CancelBlock(0);
|
||||
return CreateEmptyBlock(block, addr);
|
||||
}
|
||||
if(!isprotectedDB(addr, 1)) {
|
||||
dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr);
|
||||
AddHotPage(addr);
|
||||
CancelBlock();
|
||||
CancelBlock(0);
|
||||
return NULL;
|
||||
}
|
||||
// already protect the block and compute hash signature
|
||||
@@ -443,6 +474,8 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
if(helper.insts[i].x86.jmp) {
|
||||
uintptr_t j = helper.insts[i].x86.jmp;
|
||||
if(j<start || j>=end || j==helper.insts[i].x86.addr) {
|
||||
if(j==helper.insts[i].x86.addr) // if there is a loop on some opcode, make the block "always to tested"
|
||||
helper.always_test = 1;
|
||||
helper.insts[i].x86.jmp_insts = -1;
|
||||
helper.insts[i].x86.need_after |= X_PEND;
|
||||
} else {
|
||||
@@ -470,24 +503,69 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
// pass 2, instruction size
|
||||
arm_pass2(&helper, addr);
|
||||
// ok, now allocate mapped memory, with executable flag on
|
||||
int sz = helper.arm_size;
|
||||
void* p = (void*)AllocDynarecMap(block, sz);
|
||||
if(p==NULL) {
|
||||
dynarec_log(LOG_DEBUG, "AllocDynarecMap(%p, %d) failed, cancelling block\n", block, sz);
|
||||
CancelBlock();
|
||||
size_t insts_rsize = (helper.insts_size+2)*sizeof(instsize_t);
|
||||
insts_rsize = (insts_rsize+7)&~7; // round the size...
|
||||
size_t arm_size = (helper.arm_size+7)&~7; // round the size...
|
||||
// ok, now allocate mapped memory, with executable flag on
|
||||
size_t sz = sizeof(void*) + arm_size + 8*sizeof(void*) + insts_rsize;
|
||||
// dynablock_t* block (arm insts) jmpnext code instsize
|
||||
void* actual_p = (void*)AllocDynarecMap(sz);
|
||||
void* p = (void*)(((uintptr_t)actual_p) + sizeof(void*));
|
||||
void* next = p + arm_size;
|
||||
void* instsize = next + 8*sizeof(void*);
|
||||
if(actual_p==NULL) {
|
||||
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
|
||||
CancelBlock(0);
|
||||
return NULL;
|
||||
}
|
||||
helper.block = p;
|
||||
// pass 3, emit (log emit arm opcode)
|
||||
block->actual_block = actual_p;
|
||||
helper.arm_start = (uintptr_t)p;
|
||||
helper.jmp_next = (uintptr_t)next+sizeof(void*);
|
||||
helper.instsize = (instsize_t*)instsize;
|
||||
*(dynablock_t**)actual_p = block;
|
||||
// pass 3, emit (log emit native opcode)
|
||||
if(box86_dynarec_dump) {
|
||||
dynarec_log(LOG_NONE, "%s%04d|Emitting %d bytes for %d x86 bytes", (box86_dynarec_dump>1)?"\e[01;36m":"", GetTID(), helper.arm_size, helper.isize);
|
||||
printFunctionAddr(helper.start, " => ");
|
||||
dynarec_log(LOG_NONE, "%s\n", (box86_dynarec_dump>1)?"\e[m":"");
|
||||
}
|
||||
size_t oldarmsize = helper.arm_size;
|
||||
size_t oldinstsize = helper.insts_size;
|
||||
helper.arm_size = 0;
|
||||
helper.insts_size = 0; // reset
|
||||
arm_pass3(&helper, addr);
|
||||
if(sz!=helper.arm_size) {
|
||||
printf_log(LOG_NONE, "BOX86: Warning, size difference in block between pass2 (%d) & pass3 (%d)!\n", sz, helper.arm_size);
|
||||
// keep size of instructions for signal handling
|
||||
block->instsize = instsize;
|
||||
// ok, free the helper now
|
||||
dynaFree(helper.insts);
|
||||
helper.insts = NULL;
|
||||
helper.instsize = NULL;
|
||||
dynaFree(helper.predecessor);
|
||||
helper.predecessor = NULL;
|
||||
block->size = sz;
|
||||
block->isize = helper.size;
|
||||
block->block = p;
|
||||
block->jmpnext = next+sizeof(void*);
|
||||
block->always_test = helper.always_test;
|
||||
block->dirty = block->always_test;
|
||||
*(dynablock_t**)next = block;
|
||||
*(void**)(next+5*sizeof(void*)) = arm_next;
|
||||
CreateJmpNext(block->jmpnext, next+5*sizeof(void*));
|
||||
//block->x86_addr = (void*)start;
|
||||
block->x86_size = end-start;
|
||||
// all done...
|
||||
__clear_cache(actual_p, actual_p+sz); // need to clear the cache before execution...
|
||||
block->hash = X31_hash_code(block->x86_addr, block->x86_size);
|
||||
// Check if something changed, to abbort if it as
|
||||
if((block->hash != hash)) {
|
||||
dynarec_log(LOG_DEBUG, "Warning, a block changed while being processed hash(%p:%zu)=%x/%x\n", block->x86_addr, block->x86_size, block->hash, hash);
|
||||
AddHotPage(addr);
|
||||
CancelBlock(0);
|
||||
return NULL;
|
||||
}
|
||||
if((oldarmsize!=helper.arm_size)) {
|
||||
printf_log(LOG_NONE, "BOx86: Warning, size difference in block between pass2 (%zu) & pass3 (%zu)!\n", sz, helper.arm_size);
|
||||
uint8_t *dump = (uint8_t*)helper.start;
|
||||
printf_log(LOG_NONE, "Dump of %d x86 opcodes:\n", helper.size);
|
||||
for(int i=0; i<helper.size; ++i) {
|
||||
@@ -497,50 +575,19 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
printf_log(LOG_NONE, "\t%d -> %d\n", helper.insts[i].size2, helper.insts[i].size);
|
||||
}
|
||||
printf_log(LOG_NONE, " ------------\n");
|
||||
}
|
||||
// all done...
|
||||
__clear_cache(p, p+sz); // need to clear the cache before execution...
|
||||
// keep size of instructions for signal handling
|
||||
{
|
||||
size_t cap = 1;
|
||||
for(int i=0; i<helper.size; ++i)
|
||||
cap += 1 + ((helper.insts[i].x86.size>helper.insts[i].size)?helper.insts[i].x86.size:helper.insts[i].size)/15;
|
||||
size_t size = 0;
|
||||
block->instsize = (instsize_t*)box_calloc(cap, sizeof(instsize_t));
|
||||
for(int i=0; i<helper.size; ++i)
|
||||
block->instsize = addInst(block->instsize, &size, &cap, helper.insts[i].x86.size, helper.insts[i].size/4);
|
||||
block->instsize = addInst(block->instsize, &size, &cap, 0, 0); // add a "end of block" mark, just in case
|
||||
}
|
||||
// ok, free the helper now
|
||||
box_free(helper.insts);
|
||||
helper.insts = NULL;
|
||||
box_free(helper.next);
|
||||
helper.next = NULL;
|
||||
block->size = sz;
|
||||
block->isize = helper.size;
|
||||
block->block = p;
|
||||
block->need_test = 0;
|
||||
//block->x86_addr = (void*)start;
|
||||
block->x86_size = end-start;
|
||||
if(box86_dynarec_largest<block->x86_size)
|
||||
box86_dynarec_largest = block->x86_size;
|
||||
block->hash = X31_hash_code(block->x86_addr, block->x86_size);
|
||||
// Check if something changed, to abbort if it as
|
||||
if(block->hash != hash) {
|
||||
dynarec_log(LOG_INFO, "Warning, a block changed while beeing processed hash(%p:%d)=%x/%x\n", block->x86_addr, block->x86_size, block->hash, hash);
|
||||
CancelBlock();
|
||||
AddHotPage(addr);
|
||||
CancelBlock(0);
|
||||
return NULL;
|
||||
}
|
||||
if(insts_rsize/sizeof(instsize_t)<helper.insts_size) {
|
||||
printf_log(LOG_NONE, "BOX86: Warning, ists_size difference in block between pass2 (%zu) and pass3 (%zu), allocated: %zu\n", oldinstsize, helper.insts_size, insts_rsize/sizeof(instsize_t));
|
||||
}
|
||||
if(!isprotectedDB(addr, end-addr)) {
|
||||
dynarec_log(LOG_DEBUG, "Warning, block unprotected while beeing processed %p:%zd, cancelling\n", block->x86_addr, block->x86_size);
|
||||
dynarec_log(LOG_DEBUG, "Warning, block unprotected while being processed %p:%zu, marking as need_test\n", block->x86_addr, block->x86_size);
|
||||
AddHotPage(addr);
|
||||
block->need_test = 1;
|
||||
block->dirty = 1;
|
||||
//protectDB(addr, end-addr);
|
||||
}
|
||||
box_free(helper.predecessor);
|
||||
helper.predecessor = NULL;
|
||||
current_helper = NULL;
|
||||
block->done = 1;
|
||||
//block->done = 1;
|
||||
return (void*)block;
|
||||
}
|
||||
@@ -27,6 +27,8 @@
|
||||
#include "dynarec_arm_functions.h"
|
||||
#include "dynarec_arm_helper.h"
|
||||
|
||||
int isRetX87Wrapper(wrapper_t fun);
|
||||
|
||||
uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
|
||||
{
|
||||
uint8_t nextop, opcode;
|
||||
@@ -1245,6 +1247,15 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
AND_REG_LSL_IMM5(xFlags, xFlags, x1, 0);
|
||||
ORR_IMM8(xFlags, xFlags, 2, 0);
|
||||
SET_DFNONE(x1);
|
||||
if(box86_wine) { // should this be done all the time?
|
||||
TSTS_IMM8_ROR(xFlags, 0x1, 12); // 0x100 == F_TF
|
||||
B_NEXT(cEQ);
|
||||
MOV32(x1, addr);
|
||||
STM(xEmu, (1<<xEAX)|(1<<xEBX)|(1<<xECX)|(1<<xEDX)|(1<<xESI)|(1<<xEDI)|(1<<xESP)|(1<<xEBP));
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, ip));
|
||||
CALL(arm_singlestep, -1, 0);
|
||||
BFC(xFlags, F_TF, 1); // should not be needed
|
||||
}
|
||||
break;
|
||||
case 0x9E:
|
||||
INST_NAME("SAHF");
|
||||
@@ -2165,8 +2176,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
tmp = dyn->insts[ninst].pass2choice = 1;
|
||||
else if ((getProtection(u32)&PROT_READ) && (PKa(u32+0)==0x8B) && (((PKa(u32+1))&0xC7)==0x04) && (PKa(u32+2)==0x24) && (PKa(u32+3)==0xC3))
|
||||
tmp = dyn->insts[ninst].pass2choice = 2;
|
||||
/*else if(isNativeCall(dyn, u32, &dyn->insts[ninst].natcall, &dyn->insts[ninst].retn))
|
||||
tmp = dyn->insts[ninst].pass2choice = 3;*/
|
||||
else if(isNativeCall(dyn, u32, &dyn->insts[ninst].natcall, &dyn->insts[ninst].retn))
|
||||
tmp = dyn->insts[ninst].pass2choice = 3;
|
||||
else
|
||||
tmp = dyn->insts[ninst].pass2choice = 0;
|
||||
#else
|
||||
@@ -2188,8 +2199,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
gd = xEAX+((u8&0x38)>>3);
|
||||
MOV32(gd, addr);
|
||||
break;
|
||||
// disabling this to avoid fetching data outside current block (in case this part changed, this block will not been marck as dirty)
|
||||
/*case 3:
|
||||
case 3:
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
|
||||
BARRIER(BARRIER_FULL);
|
||||
BARRIER_NEXT(BARRIER_FULL);
|
||||
@@ -2197,7 +2207,10 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
PUSH1(x2);
|
||||
MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall-1)), dyn->insts[ninst].retn);
|
||||
// calling a native function
|
||||
x87_forget(dyn, ninst, x3, x14, 0);
|
||||
if(isRetX87Wrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2))) {
|
||||
// return value will be on the stack, so the stack depth needs to be updated
|
||||
x87_purgecache(dyn, ninst, 0, x3, x14, x1);
|
||||
}
|
||||
if((box86_log<2) && !cycle_log && dyn->insts[ninst].natcall) { // call the wrapper directly
|
||||
uintptr_t ncall[2];
|
||||
memcpy(ncall, (void*)(dyn->insts[ninst].natcall+2), 2*sizeof(void*)); // the wrapper + function
|
||||
@@ -2228,7 +2241,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
B_NEXT(cNE); // not quitting, so lets continue
|
||||
MARK;
|
||||
jump_to_epilog(dyn, 0, xEIP, ninst);
|
||||
break;*/
|
||||
break;
|
||||
default:
|
||||
if((box86_dynarec_safeflags>1) || (ninst && dyn->insts[ninst-1].x86.set_flags)) {
|
||||
READFLAGS(X_PEND); // that's suspicious
|
||||
@@ -2267,11 +2280,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("JMP Ib");
|
||||
i32 = F8S;
|
||||
}
|
||||
JUMP(addr+i32, 0);
|
||||
JUMP((uintptr_t)getAlternate((void*)(addr+i32)), 0);
|
||||
if(dyn->insts[ninst].x86.jmp_insts==-1) {
|
||||
// out of the block
|
||||
fpu_purgecache(dyn, ninst, 1, x1, x2, x3);
|
||||
jump_to_next(dyn, addr+i32, 0, ninst);
|
||||
jump_to_next(dyn, (uintptr_t)getAlternate((void*)(addr+i32)), 0, ninst);
|
||||
} else {
|
||||
// inside the block
|
||||
CacheTransform(dyn, ninst, CHECK_CACHE(), x1, x2, x3);
|
||||
@@ -2286,9 +2299,19 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
*ok = 0;
|
||||
break;
|
||||
|
||||
case 0xEE:
|
||||
INST_NAME("OUT dx, al");
|
||||
//ignored!
|
||||
case 0xEC: /* IN AL, DX */
|
||||
case 0xED: /* IN EAX, DX */
|
||||
case 0xEE: /* OUT DX, AL */
|
||||
case 0xEF: /* OUT DX, EAX */
|
||||
INST_NAME(opcode==0xEC?"IN AL, DX":(opcode==0xED?"IN EAX, DX":(opcode==0xEE?"OUT DX? AL":"OUT DX, EAX")));
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
STM(xEmu, (1<<xEAX)|(1<<xECX)|(1<<xEDX)|(1<<xEBX)|(1<<xESP)|(1<<xEBP)|(1<<xESI)|(1<<xEDI)|(1<<xFlags));
|
||||
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
|
||||
CALL(arm_priv, -1, 0);
|
||||
LDR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
|
||||
jump_to_epilog(dyn, 0, xEIP, ninst);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
break;
|
||||
|
||||
case 0xF0:
|
||||
@@ -2779,13 +2802,16 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ORRS_IMM8(xFlags, xFlags, 1, 0);
|
||||
break;
|
||||
case 0xFA:
|
||||
INST_NAME("CLI");
|
||||
BFC(xFlags, F_IF, 1);
|
||||
break;
|
||||
case 0xFB:
|
||||
INST_NAME("STI");
|
||||
MOVW(x1, 1);
|
||||
BFI(xFlags, x1, F_IF, 1);
|
||||
INST_NAME(opcode==0xFA?"STI":"CLI");
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
STM(xEmu, (1<<xEAX)|(1<<xECX)|(1<<xEDX)|(1<<xEBX)|(1<<xESP)|(1<<xEBP)|(1<<xESI)|(1<<xEDI)|(1<<xFlags));
|
||||
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
|
||||
CALL(arm_priv, -1, 0);
|
||||
LDR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
|
||||
jump_to_epilog(dyn, 0, xEIP, ninst);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
break;
|
||||
case 0xFC:
|
||||
INST_NAME("CLD");
|
||||
@@ -2838,13 +2864,13 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 2: // CALL Ed
|
||||
INST_NAME("CALL Ed");
|
||||
PASS2IF((box86_dynarec_safeflags>1) ||
|
||||
PASS2IF((box86_dynarec_safeflags>1) ||
|
||||
((ninst && dyn->insts[ninst-1].x86.set_flags)
|
||||
|| ((ninst>1) && dyn->insts[ninst-2].x86.set_flags)), 1)
|
||||
{
|
||||
READFLAGS(X_PEND); // that's suspicious
|
||||
} else {
|
||||
//SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
|
||||
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
|
||||
}
|
||||
GETEDH(xEIP);
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
|
||||
@@ -702,8 +702,22 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
q1 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
v0 = fpu_get_scratch_quad(dyn);
|
||||
if(q1==q0 || !box86_dynarec_fastnan)
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
else
|
||||
v1 = q1;
|
||||
VRSQRTEQ_F32(v0, q0);
|
||||
VMULQ_F32(v1, v0, q0);
|
||||
VRSQRTSQ_F32(v1, v1, v0);
|
||||
VMULQ_F32(q1, v1, v0);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
VCEQQ_F32(v1, q1, q1); // 00 is nan
|
||||
VANDQ(q1, q1, v1); // if nan, remove
|
||||
VBICQ(v0, v0, v1); // if nan, keep
|
||||
VORRQ(q1, q1, v0);
|
||||
}
|
||||
break;
|
||||
case 0x53:
|
||||
INST_NAME("RCPPS Gx, Ex");
|
||||
@@ -711,8 +725,15 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
q1 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
if(q0 == q1)
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
else
|
||||
v1 = q1;
|
||||
v0 = fpu_get_scratch_quad(dyn);
|
||||
VRECPEQ_F32(v0, q0);
|
||||
VRECPSQ_F32(v1, v0, q0);
|
||||
VMULQ_F32(q1, v0, v1);
|
||||
break;
|
||||
case 0x54:
|
||||
INST_NAME("ANDPS Gx, Ex");
|
||||
@@ -1677,7 +1698,20 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("XRSTOR Ed (not implemented");
|
||||
FAKEED;
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
STM(xEmu, (1<<xEAX)|(1<<xECX)|(1<<xEDX)|(1<<xEBX)|(1<<xESP)|(1<<xEBP)|(1<<xESI)|(1<<xEDI)|(1<<xFlags));
|
||||
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
|
||||
CALL(arm_ud, -1, 0);
|
||||
LDR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
|
||||
jump_to_epilog(dyn, 0, xEIP, ninst);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("CLFLUSH Ed");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization?\n");
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL_(arm_clflush, -1, 0);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "dynarec_arm_functions.h"
|
||||
#include "bridge.h"
|
||||
#include "arm_printer.h"
|
||||
#include "custommem.h"
|
||||
|
||||
void arm_fstp(x86emu_t* emu, void* p)
|
||||
{
|
||||
@@ -175,6 +176,18 @@ void arm_ud(x86emu_t* emu)
|
||||
emit_signal(emu, SIGILL, (void*)R_EIP, 0);
|
||||
}
|
||||
|
||||
void arm_priv(x86emu_t* emu)
|
||||
{
|
||||
emu->test.test = 0;
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 0);
|
||||
}
|
||||
|
||||
void arm_singlestep(x86emu_t* emu)
|
||||
{
|
||||
emu->test.test = 0;
|
||||
emit_signal(emu, SIGTRAP, (void*)R_EIP, 1);
|
||||
}
|
||||
|
||||
void arm_fsave(x86emu_t* emu, uint8_t* ed)
|
||||
{
|
||||
fpu_savenv(emu, (char*)ed, 0);
|
||||
@@ -210,6 +223,10 @@ void arm_fprem1(x86emu_t* emu)
|
||||
emu->sw.f.F87_C0 = ((tmp64s>>2)&1);
|
||||
}
|
||||
|
||||
void arm_clflush(x86emu_t* emu, void* p)
|
||||
{
|
||||
cleanDBFromAddressRange((uintptr_t)p, 8, 0);
|
||||
}
|
||||
|
||||
// Get a FPU single scratch reg
|
||||
int fpu_get_scratch_single(dynarec_arm_t* dyn)
|
||||
@@ -705,13 +722,13 @@ int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int
|
||||
#define PK(a) *(uint8_t*)(addr+a)
|
||||
#define PK32(a) *(uint32_t*)(addr+a)
|
||||
|
||||
if(!addr)
|
||||
if(!addr || !getProtection(addr))
|
||||
return 0;
|
||||
if(PK(0)==0xff && PK(1)==0x25) { // absolute jump, maybe the GOT
|
||||
uintptr_t a1 = (PK32(2)); // need to add a check to see if the address is from the GOT !
|
||||
addr = (uintptr_t)getAlternate(*(void**)a1);
|
||||
}
|
||||
if(addr<0x10000) // too low, that is suspicious
|
||||
if(addr<0x10000 || !getProtection(addr)) // too low, that is suspicious
|
||||
return 0;
|
||||
onebridge_t *b = (onebridge_t*)(addr);
|
||||
if(b->CC==0xCC && b->S=='S' && b->C=='C' && b->w!=(wrapper_t)0 && b->f!=(uintptr_t)PltResolver) {
|
||||
|
||||
@@ -23,12 +23,16 @@ void arm_fsave(x86emu_t* emu, uint8_t* ed);
|
||||
void arm_frstor(x86emu_t* emu, uint8_t* ed);
|
||||
void arm_fprem1(x86emu_t* emu);
|
||||
|
||||
void arm_clflush(x86emu_t* emu, void* p);
|
||||
|
||||
int64_t arm_fist64_0(double d);
|
||||
int64_t arm_fist64_1(double d);
|
||||
int64_t arm_fist64_2(double d);
|
||||
int64_t arm_fist64_3(double d);
|
||||
|
||||
void arm_ud(x86emu_t* emu);
|
||||
void arm_priv(x86emu_t* emu);
|
||||
void arm_singlestep(x86emu_t* emu);
|
||||
|
||||
#define FPUFIRST 8
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86context.h"
|
||||
@@ -176,8 +177,8 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
|
||||
uint32_t m = nextop&0xC7;
|
||||
uint32_t n = (m>>6)&3;
|
||||
int32_t offset = 0;
|
||||
if(!n && m==6) {
|
||||
offset = F16;
|
||||
if(!n && (m&7)==6) {
|
||||
offset = F16S;
|
||||
MOVW(ret, offset);
|
||||
} else {
|
||||
switch(n) {
|
||||
@@ -1873,11 +1874,11 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
if(dyn->f.pending!=SF_PENDING) {
|
||||
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, df));
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
j32 = (GETMARK3)-(dyn->arm_size+8);
|
||||
j32 = (GETMARKF2)-(dyn->arm_size+8);
|
||||
Bcond(cEQ, j32);
|
||||
}
|
||||
CALL_(UpdateFlags, -1, 0);
|
||||
MARK3;
|
||||
MARKF2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1936,3 +1937,64 @@ void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
MVN_REG_LSR_REG(s4, s4, s3);
|
||||
BFI(xFlags, s4, F_PF, 1);
|
||||
}
|
||||
|
||||
void fpu_reset_cache(dynarec_arm_t* dyn, int ninst, int reset_n)
|
||||
{
|
||||
MESSAGE(LOG_DEBUG, "Reset Caches with %d\n",reset_n);
|
||||
#if STEP > 1
|
||||
// for STEP 2 & 3, just need to refrest with current, and undo the changes (push & swap)
|
||||
dyn->n = dyn->insts[ninst].n;
|
||||
neoncacheUnwind(&dyn->n);
|
||||
#ifdef HAVE_TRACE
|
||||
if(box86_dynarec_dump)
|
||||
if(memcmp(&dyn->n, &dyn->insts[reset_n].n, sizeof(neon_cache_t))) {
|
||||
MESSAGE(LOG_DEBUG, "Warning, difference in neoncache: reset=");
|
||||
for(int i=0; i<24; ++i)
|
||||
if(dyn->insts[reset_n].n.neoncache[i].v)
|
||||
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->insts[reset_n].n.neoncache[i].t, dyn->insts[reset_n].n.neoncache[i].n));
|
||||
if(dyn->insts[reset_n].n.combined1 || dyn->insts[reset_n].n.combined2)
|
||||
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->insts[reset_n].n.swapped?"SWP":"CMB", dyn->insts[reset_n].n.combined1, dyn->insts[reset_n].n.combined2);
|
||||
if(dyn->insts[reset_n].n.stack_push || dyn->insts[reset_n].n.stack_pop)
|
||||
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->insts[reset_n].n.stack_push, -dyn->insts[reset_n].n.stack_pop);
|
||||
MESSAGE(LOG_DEBUG, " ==> ");
|
||||
for(int i=0; i<24; ++i)
|
||||
if(dyn->insts[ninst].n.neoncache[i].v)
|
||||
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->insts[ninst].n.neoncache[i].t, dyn->insts[ninst].n.neoncache[i].n));
|
||||
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2)
|
||||
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->insts[ninst].n.swapped?"SWP":"CMB", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2);
|
||||
if(dyn->insts[ninst].n.stack_push || dyn->insts[ninst].n.stack_pop)
|
||||
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->insts[ninst].n.stack_push, -dyn->insts[ninst].n.stack_pop);
|
||||
MESSAGE(LOG_DEBUG, " -> ");
|
||||
for(int i=0; i<24; ++i)
|
||||
if(dyn->n.neoncache[i].v)
|
||||
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->n.neoncache[i].t, dyn->n.neoncache[i].n));
|
||||
if(dyn->n.combined1 || dyn->n.combined2)
|
||||
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->n.swapped?"SWP":"CMB", dyn->n.combined1, dyn->n.combined2);
|
||||
if(dyn->n.stack_push || dyn->n.stack_pop)
|
||||
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->n.stack_push, -dyn->n.stack_pop);
|
||||
MESSAGE(LOG_DEBUG, "\n");
|
||||
}
|
||||
#endif //HAVE_TRACE
|
||||
#else
|
||||
dyn->n = dyn->insts[reset_n].n;
|
||||
#endif
|
||||
}
|
||||
|
||||
// propagate ST stack state, especial stack pop that are deferred
|
||||
void fpu_propagate_stack(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
if(dyn->n.stack_pop) {
|
||||
for(int j=0; j<24; ++j)
|
||||
if((dyn->n.neoncache[j].t == NEON_CACHE_ST_D || dyn->n.neoncache[j].t == NEON_CACHE_ST_F)) {
|
||||
if(dyn->n.neoncache[j].n<dyn->n.stack_pop)
|
||||
dyn->n.neoncache[j].v = 0;
|
||||
else
|
||||
dyn->n.neoncache[j].n-=dyn->n.stack_pop;
|
||||
}
|
||||
dyn->n.stack_pop = 0;
|
||||
}
|
||||
dyn->n.stack = dyn->n.stack_next;
|
||||
dyn->n.news = 0;
|
||||
dyn->n.stack_push = 0;
|
||||
dyn->n.swapped = 0;
|
||||
}
|
||||
@@ -260,17 +260,19 @@
|
||||
// CALL_1RD will use S as scratch. Return value in D0, 1 ARG in R
|
||||
#define CALL_1RD(F, R, S, M) call_rd(dyn, ninst, F, R, S, M, 0);
|
||||
|
||||
#define MARK if(dyn->insts) {dyn->insts[ninst].mark = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARK ((dyn->insts)?dyn->insts[ninst].mark:(dyn->arm_size+4))
|
||||
#define MARK2 if(dyn->insts) {dyn->insts[ninst].mark2 = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARK2 ((dyn->insts)?dyn->insts[ninst].mark2:(dyn->arm_size+4))
|
||||
#define MARK3 if(dyn->insts) {dyn->insts[ninst].mark3 = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARK3 ((dyn->insts)?dyn->insts[ninst].mark3:(dyn->arm_size+4))
|
||||
#define MARKF if(dyn->insts) {dyn->insts[ninst].markf = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARKF ((dyn->insts)?dyn->insts[ninst].markf:(dyn->arm_size+4))
|
||||
#define MARKSEG if(dyn->insts) {dyn->insts[ninst].markseg = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARKSEG ((dyn->insts)?dyn->insts[ninst].markseg:(dyn->arm_size+4))
|
||||
#define MARKLOCK if(dyn->insts) {dyn->insts[ninst].marklock = (uintptr_t)dyn->arm_size;}
|
||||
#define MARK if(dyn->insts) {dyn->insts[ninst].mark = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARK ((dyn->insts)?dyn->insts[ninst].mark:(dyn->arm_size+4))
|
||||
#define MARK2 if(dyn->insts) {dyn->insts[ninst].mark2 = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARK2 ((dyn->insts)?dyn->insts[ninst].mark2:(dyn->arm_size+4))
|
||||
#define MARK3 if(dyn->insts) {dyn->insts[ninst].mark3 = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARK3 ((dyn->insts)?dyn->insts[ninst].mark3:(dyn->arm_size+4))
|
||||
#define MARKF if(dyn->insts) {dyn->insts[ninst].markf = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARKF ((dyn->insts)?dyn->insts[ninst].markf:(dyn->arm_size+4))
|
||||
#define MARKF2 if(dyn->insts) {dyn->insts[ninst].markf2 = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARKF2 ((dyn->insts)?dyn->insts[ninst].markf2:(dyn->arm_size+4))
|
||||
#define MARKSEG if(dyn->insts) {dyn->insts[ninst].markseg = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARKSEG ((dyn->insts)?dyn->insts[ninst].markseg:(dyn->arm_size+4))
|
||||
#define MARKLOCK if(dyn->insts) {dyn->insts[ninst].marklock = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARKLOCK ((dyn->insts)?dyn->insts[ninst].marklock:(dyn->arm_size+4))
|
||||
|
||||
// Branch to MARK if cond (use j32)
|
||||
@@ -547,6 +549,8 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
|
||||
#define fpu_pushcache STEPNAME(fpu_pushcache)
|
||||
#define fpu_popcache STEPNAME(fpu_popcache)
|
||||
#define fpu_reset STEPNAME(fpu_reset)
|
||||
#define fpu_reset_cache STEPNAME(fpu_reset_cache)
|
||||
#define fpu_propagate_stack STEPNAME(fpu_propagate_stack)
|
||||
#define fpu_purgecache STEPNAME(fpu_purgecache)
|
||||
#define x87_purgecache STEPNAME(x87_purgecache)
|
||||
#define mmx_purgecache STEPNAME(mmx_purgecache)
|
||||
@@ -740,6 +744,10 @@ int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
|
||||
// common coproc helpers
|
||||
// reset the cache
|
||||
void fpu_reset(dynarec_arm_t* dyn);
|
||||
// reset the cache with n
|
||||
void fpu_reset_cache(dynarec_arm_t* dyn, int ninst, int reset_n);
|
||||
// propagate stack state
|
||||
void fpu_propagate_stack(dynarec_arm_t* dyn, int ninst);
|
||||
// purge the FPU cache (needs 3 scratch registers) next=1 if for a conditionnal branch jumping out of block (no tracking updated)
|
||||
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3);
|
||||
void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "arm_emitter.h"
|
||||
|
||||
#define EMIT(A) *block = (A); ++block
|
||||
void CreateJmpNext(void* addr, void* next)
|
||||
{
|
||||
uint32_t* block = (uint32_t*)addr;
|
||||
LDR_literal(x2, ((intptr_t)next - (intptr_t)addr)-8);
|
||||
BX(x2);
|
||||
}
|
||||
@@ -56,44 +56,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
dyn->f.pending = 0;
|
||||
fpu_reset(dyn);
|
||||
} else {
|
||||
MESSAGE(LOG_DEBUG, "Reset Caches with %d\n",reset_n);
|
||||
#if STEP > 1
|
||||
// for STEP 2 & 3, just need to refrest with current, and undo the changes (push & swap)
|
||||
dyn->n = dyn->insts[ninst].n;
|
||||
neoncacheUnwind(&dyn->n);
|
||||
#ifdef HAVE_TRACE
|
||||
if(box86_dynarec_dump)
|
||||
if(memcmp(&dyn->n, &dyn->insts[reset_n].n, sizeof(neon_cache_t))) {
|
||||
MESSAGE(LOG_DEBUG, "Warning, difference in neoncache: reset=");
|
||||
for(int i=0; i<24; ++i)
|
||||
if(dyn->insts[reset_n].n.neoncache[i].v)
|
||||
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->insts[reset_n].n.neoncache[i].t, dyn->insts[reset_n].n.neoncache[i].n));
|
||||
if(dyn->insts[reset_n].n.combined1 || dyn->insts[reset_n].n.combined2)
|
||||
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->insts[reset_n].n.swapped?"SWP":"CMB", dyn->insts[reset_n].n.combined1, dyn->insts[reset_n].n.combined2);
|
||||
if(dyn->insts[reset_n].n.stack_push || dyn->insts[reset_n].n.stack_pop)
|
||||
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->insts[reset_n].n.stack_push, -dyn->insts[reset_n].n.stack_pop);
|
||||
MESSAGE(LOG_DEBUG, " ==> ");
|
||||
for(int i=0; i<24; ++i)
|
||||
if(dyn->insts[ninst].n.neoncache[i].v)
|
||||
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->insts[ninst].n.neoncache[i].t, dyn->insts[ninst].n.neoncache[i].n));
|
||||
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2)
|
||||
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->insts[ninst].n.swapped?"SWP":"CMB", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2);
|
||||
if(dyn->insts[ninst].n.stack_push || dyn->insts[ninst].n.stack_pop)
|
||||
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->insts[ninst].n.stack_push, -dyn->insts[ninst].n.stack_pop);
|
||||
MESSAGE(LOG_DEBUG, " -> ");
|
||||
for(int i=0; i<24; ++i)
|
||||
if(dyn->n.neoncache[i].v)
|
||||
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->n.neoncache[i].t, dyn->n.neoncache[i].n));
|
||||
if(dyn->n.combined1 || dyn->n.combined2)
|
||||
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->n.swapped?"SWP":"CMB", dyn->n.combined1, dyn->n.combined2);
|
||||
if(dyn->n.stack_push || dyn->n.stack_pop)
|
||||
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->n.stack_push, -dyn->n.stack_pop);
|
||||
MESSAGE(LOG_DEBUG, "\n");
|
||||
}
|
||||
#endif //HAVE_TRACE
|
||||
#else
|
||||
dyn->n = dyn->insts[reset_n].n;
|
||||
#endif
|
||||
fpu_reset_cache(dyn, ninst, reset_n);
|
||||
dyn->f = dyn->insts[reset_n].f_exit;
|
||||
if(dyn->insts[ninst].x86.barrier&BARRIER_FLOAT) {
|
||||
MESSAGE(LOG_DEBUG, "Apply Barrier Float\n");
|
||||
@@ -107,21 +70,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
}
|
||||
reset_n = -1;
|
||||
}
|
||||
// propagate ST stack state, especial stack pop that are defered
|
||||
if(dyn->n.stack_pop) {
|
||||
for(int j=0; j<24; ++j)
|
||||
if((dyn->n.neoncache[j].t == NEON_CACHE_ST_D || dyn->n.neoncache[j].t == NEON_CACHE_ST_F)) {
|
||||
if(dyn->n.neoncache[j].n<dyn->n.stack_pop)
|
||||
dyn->n.neoncache[j].v = 0;
|
||||
else
|
||||
dyn->n.neoncache[j].n-=dyn->n.stack_pop;
|
||||
}
|
||||
dyn->n.stack_pop = 0;
|
||||
}
|
||||
dyn->n.stack = dyn->n.stack_next;
|
||||
dyn->n.news = 0;
|
||||
dyn->n.stack_push = 0;
|
||||
dyn->n.swapped = 0;
|
||||
fpu_propagate_stack(dyn, ninst);
|
||||
NEW_INST;
|
||||
if(!ninst) {
|
||||
GOTEST(x1, x2);
|
||||
@@ -176,13 +125,26 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
dyn->f.dfnone = 0;
|
||||
}
|
||||
}
|
||||
#ifndef PROT_READ
|
||||
#define PROT_READ 1
|
||||
#endif
|
||||
#if STEP != 0
|
||||
if(!ok && !need_epilog && (addr < (dyn->start+dyn->isize))) {
|
||||
ok = 1;
|
||||
// we use the 1st predecessor here
|
||||
int ii = ninst+1;
|
||||
while(ii<dyn->size && !dyn->insts[ii].pred_sz)
|
||||
++ii;
|
||||
if(ii<dyn->size && !dyn->insts[ii].pred_sz) {
|
||||
while(ii<dyn->size && (!dyn->insts[ii].pred_sz || (dyn->insts[ii].pred_sz==1 && dyn->insts[ii].pred[0]==ii-1))) {
|
||||
// may need to skip opcodes to advance
|
||||
++ninst;
|
||||
NEW_INST;
|
||||
MESSAGE(LOG_DEBUG, "Skipping unused opcode\n");
|
||||
INST_NAME("Skipped opcode");
|
||||
INST_EPILOG;
|
||||
addr += dyn->insts[ii].x86.size;
|
||||
++ii;
|
||||
}
|
||||
}
|
||||
if((dyn->insts[ii].x86.barrier&BARRIER_FULL)==BARRIER_FULL)
|
||||
reset_n = -2; // hack to say Barrier!
|
||||
else {
|
||||
@@ -194,20 +156,18 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
}
|
||||
}
|
||||
#else
|
||||
#ifndef PROT_READ
|
||||
#define PROT_READ 1
|
||||
#endif
|
||||
if(dyn->forward) {
|
||||
if(dyn->forward_to == addr) {
|
||||
if(dyn->forward_to == addr && !need_epilog) {
|
||||
// we made it!
|
||||
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Forward extend block %p -> %p\n", (void*)dyn->forward, (void*)dyn->forward_to);
|
||||
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Forward extend block for %d bytes %p -> %p\n", dyn->forward_to-dyn->forward, (void*)dyn->forward, (void*)dyn->forward_to);
|
||||
dyn->forward = 0;
|
||||
dyn->forward_to = 0;
|
||||
dyn->forward_size = 0;
|
||||
dyn->forward_ninst = 0;
|
||||
ok = 1; // in case it was 0
|
||||
} else if ((dyn->forward_to < addr) || !ok) {
|
||||
// something when wrong! rollback
|
||||
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Could not forward extend block %p -> %p\n", (void*)dyn->forward, (void*)dyn->forward_to);
|
||||
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Could not forward extend block for %d bytes %p -> %p\n", dyn->forward_to-dyn->forward, (void*)dyn->forward, (void*)dyn->forward_to);
|
||||
ok = 0;
|
||||
dyn->size = dyn->forward_size;
|
||||
ninst = dyn->forward_ninst;
|
||||
@@ -218,12 +178,12 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
dyn->forward_ninst = 0;
|
||||
}
|
||||
// else just continue
|
||||
} else if(!ok && !need_epilog && box86_dynarec_bigblock && (getProtection(addr+3)&PROT_READ))
|
||||
} else if(!ok && !need_epilog && box86_dynarec_bigblock && (getProtection(addr+3)&~PROT_READ))
|
||||
if(*(uint32_t*)addr!=0) { // check if need to continue (but is next 4 bytes are 0, stop)
|
||||
uintptr_t next = get_closest_next(dyn, addr);
|
||||
if(next && (
|
||||
(((next-addr)<15) && is_nops(dyn, addr, next-addr))
|
||||
/*&& box86_dynarec_bigblock*/))
|
||||
/*||(((next-addr)<30) && is_instructions(dyn, addr, next-addr))*/ ))
|
||||
{
|
||||
ok = 1;
|
||||
// need to find back that instruction to copy the caches, as previous version cannot be used anymore
|
||||
@@ -234,30 +194,73 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
ii=ninst;
|
||||
}
|
||||
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Extend block %p, %p -> %p (ninst=%d, jump from %d)\n", dyn, (void*)addr, (void*)next, ninst, reset_n);
|
||||
} else if(next && (next-addr<box86_dynarec_forward)
|
||||
&& (getProtection(next)&PROT_READ)/*box86_dynarec_bigblock>=forwardblock*/) {
|
||||
dyn->forward = addr;
|
||||
dyn->forward_to = next;
|
||||
dyn->forward_size = dyn->size;
|
||||
dyn->forward_ninst = ninst;
|
||||
reset_n = -2;
|
||||
ok = 1;
|
||||
} else if(next && (next-addr)<box86_dynarec_forward && (getProtection(next)&PROT_READ)/*box86_dynarec_bigblock>=stopblock*/) {
|
||||
if(!((box86_dynarec_bigblock<stopblock) && !isJumpTableDefault((void*)next))) {
|
||||
if(dyn->forward) {
|
||||
if(next<dyn->forward_to)
|
||||
dyn->forward_to = next;
|
||||
reset_n = -2;
|
||||
ok = 1;
|
||||
} else {
|
||||
dyn->forward = addr;
|
||||
dyn->forward_to = next;
|
||||
dyn->forward_size = dyn->size;
|
||||
dyn->forward_ninst = ninst;
|
||||
reset_n = -2;
|
||||
ok = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(ok<0) {ok = 0; need_epilog=1;}
|
||||
if(ok<0) {
|
||||
ok = 0; need_epilog=1;
|
||||
#if STEP == 0
|
||||
if(ninst) {
|
||||
--ninst;
|
||||
if(!dyn->insts[ninst].x86.barrier) {
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
}
|
||||
dyn->insts[ninst].x86.need_after |= X_PEND;
|
||||
++ninst;
|
||||
}
|
||||
if(dyn->forward) {
|
||||
// stopping too soon
|
||||
dyn->size = dyn->forward_size;
|
||||
ninst = dyn->forward_ninst+1;
|
||||
addr = dyn->forward;
|
||||
dyn->forward = 0;
|
||||
dyn->forward_to = 0;
|
||||
dyn->forward_size = 0;
|
||||
dyn->forward_ninst = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
++ninst;
|
||||
#if STEP == 0
|
||||
if(ok && (((box86_dynarec_bigblock<stopblock) && !isJumpTableDefault((void*)addr))
|
||||
|| (addr>=box86_nodynarec_start && addr<box86_nodynarec_end)
|
||||
/*|| (dyn->size >= 2000)*/)) // is this still needed? maybe it should be a parameter?
|
||||
|| (addr>=box86_nodynarec_start && addr<box86_nodynarec_end)))
|
||||
#else
|
||||
if(ok && (ninst==dyn->size))
|
||||
#endif
|
||||
{
|
||||
#if STEP == 0
|
||||
if(dyn->forward) {
|
||||
// stopping too soon
|
||||
dyn->size = dyn->forward_size;
|
||||
ninst = dyn->forward_ninst+1;
|
||||
addr = dyn->forward;
|
||||
dyn->forward = 0;
|
||||
dyn->forward_to = 0;
|
||||
dyn->forward_size = 0;
|
||||
dyn->forward_ninst = 0;
|
||||
}
|
||||
#endif
|
||||
int j32;
|
||||
MAYUSE(j32);
|
||||
MESSAGE(LOG_DEBUG, "Stopping block %p (%d / %d)\n",(void*)init_addr, ninst, dyn->size);
|
||||
MESSAGE(LOG_DEBUG, "Stopping block %p (%d / %d)\n",(void*)init_addr, ninst, dyn->size);
|
||||
if(!box86_dynarec_dump && addr>=box86_nodynarec_start && addr<box86_nodynarec_end)
|
||||
dynarec_log(LOG_INFO, "Stopping block in no-dynarec zone\n");
|
||||
--ninst;
|
||||
if(!dyn->insts[ninst].x86.barrier) {
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
dyn->isize = addr-sav_addr;\
|
||||
dyn->insts[ninst].x86.addr = addr;\
|
||||
if(ninst) dyn->insts[ninst-1].x86.size = dyn->insts[ninst].x86.addr - dyn->insts[ninst-1].x86.addr
|
||||
|
||||
#define MESSAGE(A, ...)
|
||||
#define MAYSETFLAGS() dyn->insts[ninst].x86.may_set = 1
|
||||
#define READFLAGS(A) \
|
||||
@@ -15,13 +16,13 @@
|
||||
dyn->f.pending=(B)&SF_SET_PENDING; \
|
||||
dyn->f.dfnone=((B)&SF_SET)?1:0;
|
||||
#define EMIT(A)
|
||||
#define JUMP(A, C) if((A)>addr) add_next(dyn, (uintptr_t)(A)); dyn->insts[ninst].x86.jmp = A; dyn->insts[ninst].x86.jmp_cond = C
|
||||
#define JUMP(A, C) add_next(dyn, (uintptr_t)A); dyn->insts[ninst].x86.jmp = A; dyn->insts[ninst].x86.jmp_cond = C
|
||||
#define BARRIER(A) if(A!=BARRIER_MAYBE) {fpu_purgecache(dyn, ninst, 0, x1, x2, x3); dyn->insts[ninst].x86.barrier = A;} else dyn->insts[ninst].barrier_maybe = 1
|
||||
#define BARRIER_NEXT(A) dyn->insts[ninst+1].x86.barrier = A
|
||||
#define NEW_INST \
|
||||
++dyn->size; \
|
||||
if(dyn->size+3>=dyn->cap) { \
|
||||
dyn->insts = (instruction_arm_t*)box_realloc(dyn->insts, sizeof(instruction_arm_t)*dyn->cap*2); \
|
||||
dyn->insts = (instruction_arm_t*)dynaRealloc(dyn->insts, sizeof(instruction_arm_t)*dyn->cap*2);\
|
||||
memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_arm_t)*dyn->cap); \
|
||||
dyn->cap *= 2; \
|
||||
} \
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#define FINI
|
||||
#define MESSAGE(A, ...)
|
||||
#define EMIT(A)
|
||||
|
||||
#define NEW_INST \
|
||||
dyn->insts[ninst].f_entry = dyn->f; \
|
||||
dyn->n.combined1 = dyn->n.combined2 = 0;\
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
#define INIT dyn->arm_size = 0
|
||||
#define FINI if(ninst) {dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size);}
|
||||
#define FINI \
|
||||
if(ninst) { \
|
||||
dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size); \
|
||||
dyn->insts_size += 1+((dyn->insts[ninst].x86.size>dyn->insts[ninst].size)?dyn->insts[ninst].x86.size:dyn->insts[ninst].size)/15; \
|
||||
}
|
||||
|
||||
#define MESSAGE(A, ...)
|
||||
#define EMIT(A) dyn->insts[ninst].size+=4; dyn->arm_size+=4
|
||||
#define EMIT(A) do{dyn->insts[ninst].size+=4; dyn->arm_size+=4;}while(0)
|
||||
#define NEW_INST \
|
||||
if(ninst) { \
|
||||
dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size); \
|
||||
dyn->insts_size += 1+((dyn->insts[ninst-1].x86.size>dyn->insts[ninst-1].size)?dyn->insts[ninst-1].x86.size:dyn->insts[ninst-1].size)/15; \
|
||||
}
|
||||
#define INST_EPILOG dyn->insts[ninst].epilog = dyn->arm_size;
|
||||
#define INST_NAME(name)
|
||||
@@ -1,13 +1,20 @@
|
||||
#define INIT
|
||||
#define FINI
|
||||
#define EMIT(A) \
|
||||
if(box86_dynarec_dump) print_opcode(dyn, ninst, (uint32_t)(A)); \
|
||||
*(uint32_t*)(dyn->block) = A; \
|
||||
dyn->block += 4; dyn->arm_size += 4; \
|
||||
dyn->insts[ninst].size2 += 4
|
||||
#define FINI \
|
||||
if(ninst) \
|
||||
addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst].x86.size, dyn->insts[ninst].size/4); \
|
||||
addInst(dyn->instsize, &dyn->insts_size, 0, 0);
|
||||
#define EMIT(A) \
|
||||
do{ \
|
||||
if(box86_dynarec_dump) print_opcode(dyn, ninst, (uint32_t)(A)); \
|
||||
if((uintptr_t)dyn->block<(uintptr_t)dyn->next-sizeof(void*))\
|
||||
*(uint32_t*)(dyn->block) = (uint32_t)(A); \
|
||||
dyn->block += 4; dyn->arm_size += 4; \
|
||||
dyn->insts[ninst].size2 += 4; \
|
||||
}while(0)
|
||||
|
||||
#define MESSAGE(A, ...) if(box86_dynarec_dump) dynarec_log(LOG_NONE, __VA_ARGS__)
|
||||
// warning, there is some logic, handing of sons, in newinst_pass3
|
||||
#define NEW_INST
|
||||
#define NEW_INST \
|
||||
if(ninst) \
|
||||
addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst-1].x86.size, dyn->insts[ninst-1].size/4);
|
||||
#define INST_EPILOG
|
||||
#define INST_NAME(name) inst_name_pass3(dyn, ninst, name)
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
typedef struct instsize_s instsize_t;
|
||||
|
||||
#define BARRIER_MAYBE 8
|
||||
|
||||
@@ -68,7 +69,7 @@ typedef struct instruction_arm_s {
|
||||
int pred_sz; // size of predecessor list
|
||||
int *pred; // predecessor array
|
||||
uintptr_t mark, mark2, mark3;
|
||||
uintptr_t markf;
|
||||
uintptr_t markf, markf2;
|
||||
uintptr_t markseg;
|
||||
uintptr_t marklock;
|
||||
int pass2choice;// value for choices that are fixed on pass2 for pass3
|
||||
@@ -90,6 +91,7 @@ typedef struct dynarec_arm_s {
|
||||
void* block; // memory pointer where next instruction is emited
|
||||
uintptr_t arm_start; // start of the arm code
|
||||
int arm_size; // size of emitted arm code
|
||||
uintptr_t jmp_next; // address of the jump_next address
|
||||
flagcache_t f;
|
||||
neoncache_t n; // cache for the 8..31 double reg from fpu, plus x87 stack delta
|
||||
uintptr_t* next; // variable array of "next" jump address
|
||||
@@ -97,12 +99,15 @@ typedef struct dynarec_arm_s {
|
||||
int next_cap;
|
||||
int* predecessor;// single array of all predecessor
|
||||
dynablock_t* dynablock;
|
||||
instsize_t* instsize;
|
||||
size_t insts_size; // size of the instruction size array (calculated)
|
||||
uint8_t smread; // for strongmem model emulation
|
||||
uint8_t smwrite; // for strongmem model emulation
|
||||
uintptr_t forward; // address of the last end of code while testing forward
|
||||
uintptr_t forward_to; // address of the next jump to (to check if everything is ok)
|
||||
int32_t forward_size; // size at the forward point
|
||||
int forward_ninst; // ninst at the forward point
|
||||
uint8_t always_test;
|
||||
} dynarec_arm_t;
|
||||
|
||||
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
|
||||
@@ -110,4 +115,6 @@ uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr);
|
||||
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n);
|
||||
int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n);
|
||||
|
||||
void CreateJmpNext(void* addr, void* next);
|
||||
|
||||
#endif //__DYNAREC_ARM_PRIVATE_H_
|
||||
@@ -44,4 +44,17 @@ typedef struct instruction_x86_s {
|
||||
|
||||
void printf_x86_instruction(zydis_dec_t* dec, instruction_x86_t* inst, const char* name);
|
||||
|
||||
//#define USE_CUSTOM_MEM
|
||||
#ifdef USE_CUSTOM_MEM
|
||||
#define dynaMalloc customMalloc
|
||||
#define dynaCalloc customCalloc
|
||||
#define dynaRealloc customRealloc
|
||||
#define dynaFree customFree
|
||||
#else
|
||||
#define dynaMalloc box_malloc
|
||||
#define dynaCalloc box_calloc
|
||||
#define dynaRealloc box_realloc
|
||||
#define dynaFree box_free
|
||||
#endif
|
||||
|
||||
#endif //__DYNAREC_PRIVATE_H_
|
||||
@@ -233,9 +233,9 @@ NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 1 @<1> Rm @ param=1 char align[4
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> Rm @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> Rm @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
|
||||
+326
-162
@@ -60,11 +60,14 @@ elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec)
|
||||
h->path = (char*)box_malloc(1);
|
||||
h->path[0] = '\0';
|
||||
}
|
||||
|
||||
|
||||
h->mapsymbols = NewMapSymbols();
|
||||
h->weaksymbols = NewMapSymbols();
|
||||
h->localsymbols = NewMapSymbols();
|
||||
|
||||
h->globaldefver = NewDefaultVersion();
|
||||
h->weakdefver = NewDefaultVersion();
|
||||
h->refcnt = 1;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
@@ -73,14 +76,9 @@ void FreeElfHeader(elfheader_t** head)
|
||||
if(!head || !*head)
|
||||
return;
|
||||
elfheader_t *h = *head;
|
||||
#ifdef DYNAREC
|
||||
/*if(h->text) {
|
||||
dynarec_log(LOG_INFO, "Free Dynarec block for %s\n", h->path);
|
||||
cleanDBFromAddressRange(my_context, h->text, h->textsz, 1);
|
||||
}*/ // will be free at the end, no need to free it now
|
||||
#endif
|
||||
box_free(h->name);
|
||||
box_free(h->path);
|
||||
if(my_context)
|
||||
RemoveElfHeader(my_context, h);
|
||||
|
||||
box_free(h->PHEntries);
|
||||
box_free(h->SHEntries);
|
||||
box_free(h->SHStrTab);
|
||||
@@ -93,8 +91,13 @@ void FreeElfHeader(elfheader_t** head)
|
||||
FreeMapSymbols(&h->mapsymbols);
|
||||
FreeMapSymbols(&h->weaksymbols);
|
||||
FreeMapSymbols(&h->localsymbols);
|
||||
|
||||
FreeDefaultVersion(&h->globaldefver);
|
||||
FreeDefaultVersion(&h->weakdefver);
|
||||
|
||||
FreeElfMemory(h);
|
||||
|
||||
box_free(h->name);
|
||||
box_free(h->path);
|
||||
box_free(h);
|
||||
|
||||
*head = NULL;
|
||||
@@ -158,12 +161,17 @@ const char* ElfName(elfheader_t* head)
|
||||
return "(noelf)";
|
||||
return head->name;
|
||||
}
|
||||
|
||||
const char* ElfPath(elfheader_t* head)
|
||||
{
|
||||
if(!head)
|
||||
return NULL;
|
||||
return head->path;
|
||||
}
|
||||
int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
|
||||
{
|
||||
uintptr_t offs = 0;
|
||||
if(!head->vaddr && box86_load_addr) {
|
||||
offs = box86_load_addr;
|
||||
offs = (uintptr_t)findBlockNearHint((void*)box86_load_addr, head->memsz);
|
||||
box86_load_addr += head->memsz*(1+mainbin);
|
||||
box86_load_addr = (box86_load_addr+0xffffffLL)&~0xffffffLL;
|
||||
}
|
||||
@@ -296,6 +304,13 @@ void FreeElfMemory(elfheader_t* head)
|
||||
else
|
||||
for(int i=0; i<head->multiblock_n; ++i)
|
||||
munmap(head->multiblock[i], head->multiblock_size[i]);
|
||||
#ifdef DYNAREC
|
||||
for(int i=0; i<head->multiblock_n; ++i) {
|
||||
dynarec_log(LOG_INFO, "Free DynaBlocks for %s\n", head->path);
|
||||
cleanDBFromAddressRange((uintptr_t)head->multiblock[i], head->multiblock_size[i], 1);
|
||||
freeProtection((uintptr_t)head->multiblock[i], head->multiblock_size[i]);
|
||||
}
|
||||
#endif
|
||||
box_free(head->multiblock);
|
||||
box_free(head->multiblock_size);
|
||||
box_free(head->multiblock_offs);
|
||||
@@ -353,6 +368,23 @@ int LoadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded)
|
||||
{
|
||||
if(!verneeded || !head)
|
||||
return 1;
|
||||
if(!head->VerDef || !verneeded->VerNeed)
|
||||
return 1;
|
||||
int cnt = GetNeededVersionCnt(verneeded, libname);
|
||||
for (int i=0; i<cnt; ++i) {
|
||||
const char* vername = GetNeededVersionString(verneeded, libname, i);
|
||||
if(vername && !GetVersionIndice(head, vername)) {
|
||||
printf_log(/*LOG_DEBUG*/LOG_INFO, "Discarding %s for missing version %s\n", head->path, vername);
|
||||
return 0; // missing version
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ReloadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
|
||||
{
|
||||
(void)context;
|
||||
@@ -402,7 +434,7 @@ int FindR386COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint32_t*
|
||||
if(version2!=-1) version2 &= 0x7fff;
|
||||
if(version && !version2) version2=-1; // match a versionned symbol against a global "local" symbol
|
||||
const char* vername2 = GetSymbolVersion(h, version2);
|
||||
if(SameVersionnedSymbol(name, version, vername, symname, version2, vername2)) {
|
||||
if(SameVersionedSymbol(name, version, vername, symname, version2, vername2)) {
|
||||
*offs = sym->st_value + h->delta;
|
||||
*p = (uint32_t*)(rel[i].r_offset + h->delta);
|
||||
return 1;
|
||||
@@ -422,7 +454,7 @@ int FindR386COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint32_t*
|
||||
if(version2!=-1) version2 &= 0x7fff;
|
||||
if(version && !version2) version2=-1; // match a versionned symbol against a global "local" symbol
|
||||
const char* vername2 = GetSymbolVersion(h, version2);
|
||||
if(SameVersionnedSymbol(name, version, vername, symname, version2, vername2)) {
|
||||
if(SameVersionedSymbol(name, version, vername, symname, version2, vername2)) {
|
||||
*offs = sym->st_value + h->delta;
|
||||
*p = (uint32_t*)(rela[i].r_offset + h->delta + rela[i].r_addend);
|
||||
return 1;
|
||||
@@ -436,6 +468,13 @@ int FindR386COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint32_t*
|
||||
int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head, int cnt, Elf32_Rel *rel, int* need_resolv)
|
||||
{
|
||||
int ret_ok = 0;
|
||||
const char* old_globdefver = NULL;
|
||||
const char* old_weakdefver = NULL;
|
||||
int old_bind = -1;
|
||||
const char* old_symname = NULL;
|
||||
uintptr_t old_offs = 0;
|
||||
uintptr_t old_end = 0;
|
||||
int old_version = -1;
|
||||
for (int i=0; i<cnt; ++i) {
|
||||
int t = ELF32_R_TYPE(rel[i].r_info);
|
||||
Elf32_Sym *sym = &head->DynSym[ELF32_R_SYM(rel[i].r_info)];
|
||||
@@ -450,32 +489,62 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
|
||||
int version = head->VerSym?((Elf32_Half*)((uintptr_t)head->VerSym+head->delta))[ELF32_R_SYM(rel[i].r_info)]:-1;
|
||||
if(version!=-1) version &=0x7fff;
|
||||
const char* vername = GetSymbolVersion(head, version);
|
||||
const char* defver = GetDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname);
|
||||
const char* globdefver = NULL;
|
||||
const char* weakdefver = NULL;
|
||||
if(old_bind==bind && old_symname==symname) {
|
||||
globdefver = old_globdefver;
|
||||
weakdefver = old_weakdefver;
|
||||
} else {
|
||||
old_globdefver = globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(maplib, local_maplib, 0, symname);
|
||||
old_weakdefver = weakdefver = (bind==STB_WEAK)?GetMaplibDefaultVersion(maplib, local_maplib, 1, symname):NULL;
|
||||
}
|
||||
if(bind==STB_LOCAL) {
|
||||
if(!symname || !symname[0]) {
|
||||
offs = sym->st_value + head->delta;
|
||||
end = offs + sym->st_size;
|
||||
} else {
|
||||
if(!offs && !end && local_maplib)
|
||||
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
|
||||
if(!offs && !end)
|
||||
GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername);
|
||||
if(old_version==version && old_bind==bind && old_symname==symname) {
|
||||
offs = old_offs;
|
||||
end = old_end;
|
||||
} else {
|
||||
if(local_maplib)
|
||||
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
if(!offs && !end)
|
||||
GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// this is probably very very wrong. A proprer way to get reloc need to be writen, but this hack seems ok for now
|
||||
// this is probably very very wrong. A proprer way to get reloc need to be written, but this hack seems ok for now
|
||||
// at least it work for half-life, unreal, ut99, zsnes, Undertale, ColinMcRae Remake, FTL, ShovelKnight...
|
||||
/*if(bind==STB_GLOBAL && (ndx==10 || ndx==19) && t!=R_386_GLOB_DAT) {
|
||||
offs = sym->st_value + head->delta;
|
||||
end = offs + sym->st_size;
|
||||
}*/
|
||||
// so weak symbol are the one left
|
||||
if(!offs && !end) {
|
||||
if(!offs && !end && local_maplib)
|
||||
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
|
||||
if(!offs && !end)
|
||||
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername);
|
||||
if(bind==STB_WEAK) {
|
||||
if(old_version==version && old_bind==bind && old_symname==symname) {
|
||||
offs = old_offs;
|
||||
end = old_end;
|
||||
} else {
|
||||
GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
if(!offs && !end && local_maplib)
|
||||
GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
}
|
||||
} else {
|
||||
if(old_version==version && old_bind==bind && old_symname==symname) {
|
||||
offs = old_offs;
|
||||
end = old_end;
|
||||
} else {
|
||||
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
if(!offs && !end && local_maplib)
|
||||
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
}
|
||||
}
|
||||
}
|
||||
old_bind = bind;
|
||||
old_symname = symname;
|
||||
old_offs = offs;
|
||||
old_end = end;
|
||||
uintptr_t globoffs, globend;
|
||||
uint32_t* globp;
|
||||
uintptr_t tmp = 0;
|
||||
@@ -503,23 +572,23 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
|
||||
globoffs = offs;
|
||||
globend = end;
|
||||
offs = end = 0;
|
||||
GetSizedSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end, size, version, vername, 1, defver); // try globaldata symbols first
|
||||
GetSizedSymbolStartEnd(my_context->globdata, symname, &offs, &end, size, version, vername, 1, globdefver); // try globaldata symbols first
|
||||
if(!offs && local_maplib)
|
||||
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername);
|
||||
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername, globdefver, weakdefver);
|
||||
if(!offs)
|
||||
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, size, version, vername);
|
||||
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, size, version, vername, globdefver, weakdefver);
|
||||
if(!offs) {offs = globoffs; end = globend;}
|
||||
if(offs) {
|
||||
// add r_addend to p?
|
||||
printf_dump(LOG_NEVER, "Apply R_386_COPY @%p with sym=%s (ver=%d/%s), @%p size=%zd\n", p, symname, version, vername?vername:"(none)", (void*)offs, sym->st_size);
|
||||
if(p!=(void*)(offs))
|
||||
memmove(p, (void*)(offs), sym->st_size);
|
||||
if(p!=(void*)offs)
|
||||
memmove(p, (void*)offs, sym->st_size);
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply RELA R_386_COPY @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
}
|
||||
break;
|
||||
case R_386_GLOB_DAT:
|
||||
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername) && FindR386COPYRel(my_context->elfs[0], symname, &globoffs, &globp, size, version, vername)) {
|
||||
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername, globdefver) && FindR386COPYRel(my_context->elfs[0], symname, &globoffs, &globp, size, version, vername)) {
|
||||
// set global offs / size for the symbol
|
||||
offs = sym->st_value + head->delta;
|
||||
end = offs + sym->st_size;
|
||||
@@ -528,7 +597,8 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
|
||||
(bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, globp, (void*)(p?(*p):0),
|
||||
(void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname, version, vername?vername:"(none)");
|
||||
//memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
|
||||
AddUniqueSymbol(GetGlobalData(maplib), symname, offs, sym->st_size, version, vername);
|
||||
AddUniqueSymbol(GetGlobalData(maplib), symname, globoffs, sym->st_size, version, vername);
|
||||
AddUniqueSymbol(my_context->globdata, symname, offs, sym->st_size, version, vername);
|
||||
} else {
|
||||
printf_dump(LOG_NEVER, "Apply %s R_386_GLOB_DAT with R_386_COPY @%p/%p (%p/%p -> %p/%p) null sized on sym=%s (ver=%d/%s)\n",
|
||||
(bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, globp, (void*)(p?(*p):0),
|
||||
@@ -537,7 +607,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
|
||||
*p = globoffs;
|
||||
} else {
|
||||
// Look for same symbol already loaded but not in self (so no need for local_maplib here)
|
||||
if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername)) {
|
||||
if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername, globdefver)) {
|
||||
offs = globoffs;
|
||||
end = globend;
|
||||
}
|
||||
@@ -687,6 +757,13 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
|
||||
int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head, int cnt, Elf32_Rela *rela, int* need_resolv)
|
||||
{
|
||||
int ret_ok = 0;
|
||||
const char* old_globdefver = NULL;
|
||||
const char* old_weakdefver = NULL;
|
||||
int old_bind = -1;
|
||||
const char* old_symname = NULL;
|
||||
uintptr_t old_offs = 0;
|
||||
uintptr_t old_end = 0;
|
||||
int old_version = -1;
|
||||
for (int i=0; i<cnt; ++i) {
|
||||
int t = ELF32_R_TYPE(rela[i].r_info);
|
||||
Elf32_Sym *sym = &head->DynSym[ELF32_R_SYM(rela[i].r_info)];
|
||||
@@ -701,16 +778,29 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
|
||||
int version = head->VerSym?((Elf32_Half*)((uintptr_t)head->VerSym+head->delta))[ELF32_R_SYM(rela[i].r_info)]:-1;
|
||||
if(version!=-1) version &=0x7fff;
|
||||
const char* vername = GetSymbolVersion(head, version);
|
||||
const char* defver = GetDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname);
|
||||
const char* globdefver = NULL;
|
||||
const char* weakdefver = NULL;
|
||||
if(old_bind==bind && old_symname==symname) {
|
||||
globdefver = old_globdefver;
|
||||
weakdefver = old_weakdefver;
|
||||
} else {
|
||||
old_globdefver = globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(maplib, local_maplib, 0, symname);
|
||||
old_weakdefver = weakdefver = (bind==STB_WEAK)?GetMaplibDefaultVersion(maplib, local_maplib, 1, symname):NULL;
|
||||
}
|
||||
if(bind==STB_LOCAL) {
|
||||
if(!symname || !symname[0]) {
|
||||
offs = sym->st_value + head->delta;
|
||||
end = offs + sym->st_size;
|
||||
} else {
|
||||
if(!offs && !end && local_maplib)
|
||||
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
|
||||
if(!offs && !end)
|
||||
GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername);
|
||||
if(old_version==version && old_bind==bind && old_symname==symname) {
|
||||
offs = old_offs;
|
||||
end = old_end;
|
||||
} else {
|
||||
if(local_maplib)
|
||||
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
if(!offs && !end)
|
||||
GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// this is probably very very wrong. A proprer way to get reloc need to be writen, but this hack seems ok for now
|
||||
@@ -720,18 +810,35 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
|
||||
end = offs + sym->st_size;
|
||||
}*/
|
||||
// so weak symbol are the one left
|
||||
if(!offs && !end) {
|
||||
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername);
|
||||
if(!offs && !end && local_maplib) {
|
||||
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
|
||||
if(bind==STB_WEAK) {
|
||||
if(old_version==version && old_bind==bind && old_symname==symname) {
|
||||
offs = old_offs;
|
||||
end = old_end;
|
||||
} else {
|
||||
GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
if(!offs && !end && local_maplib)
|
||||
GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
}
|
||||
} else {
|
||||
if(old_version==version && old_bind==bind && old_symname==symname) {
|
||||
offs = old_offs;
|
||||
end = old_end;
|
||||
} else {
|
||||
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
if(!offs && !end && local_maplib)
|
||||
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
}
|
||||
}
|
||||
}
|
||||
old_bind = bind;
|
||||
old_symname = symname;
|
||||
old_offs = offs;
|
||||
old_end = end;
|
||||
uintptr_t globoffs, globend;
|
||||
uint32_t* globp;
|
||||
uintptr_t tmp = 0;
|
||||
intptr_t delta;
|
||||
switch(ELF32_R_TYPE(rela[i].r_info)) {
|
||||
switch(t) {
|
||||
case R_386_NONE:
|
||||
// can be ignored
|
||||
printf_dump(LOG_NEVER, "Ignoring [%d] %s %p (%p)\n", i, DumpRelType(t), p, (void*)(p?(*p):0));
|
||||
@@ -753,11 +860,11 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
|
||||
globoffs = offs;
|
||||
globend = end;
|
||||
offs = end = 0;
|
||||
GetSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end, version, vername, 1, defver); // try globaldata symbols first
|
||||
GetSizedSymbolStartEnd(my_context->globdata, symname, &offs, &end, size, version, vername, 1, globdefver); // try globaldata symbols first
|
||||
if(!offs && local_maplib)
|
||||
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername);
|
||||
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername, globdefver, weakdefver);
|
||||
if(!offs)
|
||||
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, size, version, vername);
|
||||
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, size, version, vername, globdefver, weakdefver);
|
||||
if(!offs) {offs = globoffs; end = globend;}
|
||||
if(offs) {
|
||||
// add r_addend to p?
|
||||
@@ -769,7 +876,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
|
||||
}
|
||||
break;
|
||||
case R_386_GLOB_DAT:
|
||||
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername) && FindR386COPYRel(my_context->elfs[0], symname, &globoffs, &globp, size, version, vername)) {
|
||||
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername, globdefver) && FindR386COPYRel(my_context->elfs[0], symname, &globoffs, &globp, size, version, vername)) {
|
||||
// set global offs / size for the symbol
|
||||
offs = sym->st_value + head->delta;
|
||||
end = offs + sym->st_size;
|
||||
@@ -778,7 +885,8 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
|
||||
(bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, globp, (void*)(p?(*p):0),
|
||||
(void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname, version, vername?vername:"(none)");
|
||||
//memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
|
||||
AddUniqueSymbol(GetGlobalData(maplib), symname, offs, sym->st_size, version, vername);
|
||||
AddUniqueSymbol(GetGlobalData(maplib), symname, globoffs, sym->st_size, version, vername);
|
||||
AddUniqueSymbol(my_context->globdata, symname, offs, sym->st_size, version, vername);
|
||||
} else {
|
||||
printf_dump(LOG_NEVER, "Apply %s R_386_GLOB_DAT with R_386_COPY @%p/%p (%p/%p -> %p/%p) null sized on sym=%s (ver=%d/%s)\n",
|
||||
(bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, globp, (void*)(p?(*p):0),
|
||||
@@ -787,7 +895,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
|
||||
*p = globoffs;
|
||||
} else {
|
||||
// Look for same symbol already loaded but not in self (so no need for local_maplib here)
|
||||
if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername)) {
|
||||
if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername, globdefver)) {
|
||||
offs = globoffs;
|
||||
end = globend;
|
||||
}
|
||||
@@ -932,9 +1040,13 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
|
||||
}
|
||||
return bindnow?ret_ok:0;
|
||||
}
|
||||
void checkHookedSymbols(lib_t *maplib, elfheader_t* h); // in mallochook.c
|
||||
|
||||
int RelocateElf(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head)
|
||||
{
|
||||
if(0 && (head->flags&DF_BIND_NOW) && !bindnow) { // disable for now, needs more symbol in a fow libs like gtk and nss3
|
||||
bindnow = 1;
|
||||
printf_log(LOG_DEBUG, "Forcing %s to Bind Now\n", head->name);
|
||||
}
|
||||
if(head->rel) {
|
||||
int cnt = head->relsz / head->relent;
|
||||
DumpRelTable(head, cnt, (Elf32_Rel *)(head->rel + head->delta), "Rel");
|
||||
@@ -949,13 +1061,16 @@ int RelocateElf(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* he
|
||||
if(RelocateElfRELA(maplib, local_maplib, bindnow, head, cnt, (Elf32_Rela *)(head->rela + head->delta), NULL))
|
||||
return -1;
|
||||
}
|
||||
checkHookedSymbols(maplib, head);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head)
|
||||
{
|
||||
int need_resolver = 0;
|
||||
if(0 && (head->flags&DF_BIND_NOW) && !bindnow) { // disable for now, needs more symbol in a fow libs like gtk and nss3
|
||||
bindnow = 1;
|
||||
printf_log(LOG_DEBUG, "Forcing %s to Bind Now\n", head->name);
|
||||
}
|
||||
if(head->pltrel) {
|
||||
int cnt = head->pltsz / head->pltent;
|
||||
if(head->pltrel==DT_REL) {
|
||||
@@ -1058,6 +1173,7 @@ uintptr_t GetLastByte(elfheader_t* h)
|
||||
#define STB_GNU_UNIQUE 10
|
||||
#endif
|
||||
|
||||
void checkHookedSymbols(elfheader_t* h); // in mallochook.c
|
||||
void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h)
|
||||
{
|
||||
if(box86_dump && h->DynSym) DumpDynSym(h);
|
||||
@@ -1068,41 +1184,29 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
|
||||
int type = ELF32_ST_TYPE(h->SymTab[i].st_info);
|
||||
int vis = h->SymTab[i].st_other&0x3;
|
||||
size_t sz = h->SymTab[i].st_size;
|
||||
// check "@@" default version symbol to add that information, regardless of size or type
|
||||
if(symname && strstr(symname, "@@")) {
|
||||
char symnameversionned[strlen(symname)+1];
|
||||
strcpy(symnameversionned, symname);
|
||||
// extract symname@@vername
|
||||
char* p = strchr(symnameversionned, '@');
|
||||
*p=0;
|
||||
p+=2;
|
||||
symname = AddDictionnary(my_context->versym, symnameversionned);
|
||||
const char* vername = AddDictionnary(my_context->versym, p);
|
||||
AddDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname, vername);
|
||||
printf_dump(LOG_NEVER, "Adding %s Default Version \"%s\" for Symbol\"%s\"\n", (bind==STB_WEAK)?"Weak":"Global", vername, symname);
|
||||
}
|
||||
if((type==STT_OBJECT || type==STT_FUNC || type==STT_COMMON || type==STT_TLS || type==STT_NOTYPE)
|
||||
&& (vis==STV_DEFAULT || vis==STV_PROTECTED || (vis==STV_HIDDEN && bind==STB_LOCAL)) && (h->SymTab[i].st_shndx!=0)) {
|
||||
if(strstr(symname, "@@")) {
|
||||
char symnameversionned[strlen(symname)+1];
|
||||
strcpy(symnameversionned, symname);
|
||||
// extract symname@@vername
|
||||
char* p = strchr(symnameversionned, '@');
|
||||
if(sz && strstr(symname, "@@")) {
|
||||
char symnameversioned[strlen(symname)+1];
|
||||
strcpy(symnameversioned, symname);
|
||||
// extact symname@@vername
|
||||
char* p = strchr(symnameversioned, '@');
|
||||
*p=0;
|
||||
p+=2;
|
||||
symname = AddDictionnary(my_context->versym, symnameversionned);
|
||||
symname = AddDictionnary(my_context->versym, symnameversioned);
|
||||
const char* vername = AddDictionnary(my_context->versym, p);
|
||||
if(!sz || ((bind==STB_GNU_UNIQUE /*|| (bind==STB_GLOBAL && type==STT_FUNC)*/) && FindGlobalSymbol(maplib, symname, 2, p)))
|
||||
AddDefaultVersion((bind==STB_WEAK)?h->weakdefver:h->globaldefver, symname, vername);
|
||||
if((bind==STB_GNU_UNIQUE /*|| (bind==STB_GLOBAL && type==STT_FUNC)*/) && FindGlobalSymbol(maplib, symname, 2, p))
|
||||
continue;
|
||||
uintptr_t offs = (type==STT_TLS)?h->SymTab[i].st_value:(h->SymTab[i].st_value + h->delta);
|
||||
printf_dump(LOG_NEVER, "Adding Default Versionned Symbol(bind=%s) \"%s@%s\" with offset=%p sz=%zu\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, vername, (void*)offs, sz);
|
||||
printf_dump(LOG_NEVER, "Adding Default Versioned Symbol(bind=%s) \"%s@%s\" with offset=%p sz=%zu\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, vername, (void*)offs, sz);
|
||||
if(bind==STB_LOCAL)
|
||||
AddSymbol(localsymbols, symname, offs, sz, 0, vername);
|
||||
AddSymbol(localsymbols, symname, offs, sz, 2, vername);
|
||||
else // add in local and global map
|
||||
if(bind==STB_WEAK) {
|
||||
AddSymbol(weaksymbols, symname, offs, sz, 0, vername);
|
||||
AddSymbol(weaksymbols, symname, offs, sz, 2, vername);
|
||||
} else {
|
||||
AddSymbol(mapsymbols, symname, offs, sz, 0, vername);
|
||||
AddSymbol(mapsymbols, symname, offs, sz, 2, vername);
|
||||
}
|
||||
} else {
|
||||
int to_add = 1;
|
||||
@@ -1133,17 +1237,17 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
|
||||
uintptr_t offs = (type==STT_TLS)?h->DynSym[i].st_value:(h->DynSym[i].st_value + h->delta);
|
||||
size_t sz = h->DynSym[i].st_size;
|
||||
int version = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1;
|
||||
int add_default = (version!=-1 && (version&0x7fff)>1 && !(version&0x8000) && !GetDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname))?1:0;
|
||||
int add_default = (version!=-1 && (version&0x7fff)>1 && !(version&0x8000) && !GetMaplibDefaultVersion(my_context->maplib, (maplib==my_context->maplib)?NULL:maplib, (bind==STB_WEAK)?1:0, symname))?1:0;
|
||||
if(version!=-1) version &= 0x7fff;
|
||||
const char* vername = GetSymbolVersion(h, version);
|
||||
if(add_default) {
|
||||
AddDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname, vername);
|
||||
AddDefaultVersion((bind==STB_WEAK)?h->weakdefver:h->globaldefver, symname, vername);
|
||||
printf_dump(LOG_NEVER, "Adding Default Version \"%s\" for Symbol\"%s\"\n", vername, symname);
|
||||
}
|
||||
int to_add = 1;
|
||||
if(!to_add || (bind==STB_GNU_UNIQUE && FindGlobalSymbol(maplib, symname, version, vername)))
|
||||
continue;
|
||||
printf_dump(LOG_NEVER, "Adding Versionned Symbol(bind=%s) \"%s\" (ver=%d/%s) with offset=%p sz=%zu\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, version, vername?vername:"(none)", (void*)offs, sz);
|
||||
printf_dump(LOG_NEVER, "Adding Versioned Symbol(bind=%s) \"%s\" (ver=%d/%s) with offset=%p sz=%zu\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, version, vername?vername:"(none)", (void*)offs, sz);
|
||||
if(bind==STB_LOCAL)
|
||||
AddSymbol(localsymbols, symname, offs, sz, version, vername);
|
||||
else // add in local and global map
|
||||
@@ -1154,7 +1258,7 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkHookedSymbols(h);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1171,8 +1275,10 @@ $PLATFORM – Expands to the processor type of the current machine (see the
|
||||
uname(1) man page description of the -i option). For more details of this token
|
||||
expansion, see “System Specific Shared Objects”
|
||||
*/
|
||||
int LoadNeededLibs(elfheader_t* h, lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, box86context_t* box86, x86emu_t* emu)
|
||||
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, box86context_t *box86, x86emu_t* emu)
|
||||
{
|
||||
if(h->needed) // already done
|
||||
return 0;
|
||||
DumpDynamicRPath(h);
|
||||
// update RPATH first
|
||||
for (uint32_t i=0; i<h->numDynamic; ++i)
|
||||
@@ -1210,39 +1316,49 @@ int LoadNeededLibs(elfheader_t* h, lib_t* maplib, needed_libs_t* neededlibs, lib
|
||||
box_free(origin);
|
||||
is_origin = 1;
|
||||
}
|
||||
while(strstr(rpath, "${PLATFORM}")) {
|
||||
char* platform = box_strdup("i686");
|
||||
char* p = strrchr(platform, '/');
|
||||
if(p) *p = '\0'; // remove file name to have only full path, without last '/'
|
||||
char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("${PLATFORM}")+strlen(platform)+1);
|
||||
p = strstr(rpath, "${PLATFORM}");
|
||||
memcpy(tmp, rpath, p-rpath);
|
||||
strcat(tmp, platform);
|
||||
strcat(tmp, p+strlen("${PLATFORM}"));
|
||||
if(rpath!=rpathref)
|
||||
box_free(rpath);
|
||||
rpath = tmp;
|
||||
box_free(platform);
|
||||
}
|
||||
if(strchr(rpath, '$')) {
|
||||
printf_log(LOG_INFO, "BOX86: Warning, RPATH with $ variable not supported yet (%s)\n", rpath);
|
||||
} else {
|
||||
printf_log(LOG_DEBUG, "Prepending path \"%s\" to BOX86_LD_LIBRARY_PATH\n", rpath);
|
||||
if(is_origin) {
|
||||
// also add rpath/i686
|
||||
char tmp[strlen(rpath)+strlen("/i686")+1];
|
||||
strcpy(tmp, rpath);
|
||||
strcat(tmp, "/i686");
|
||||
PrependList(&box86->box86_ld_lib, tmp, 1);
|
||||
}
|
||||
PrependList(&box86->box86_ld_lib, rpath, 1);
|
||||
}
|
||||
if(rpath!=rpathref)
|
||||
box_free(rpath);
|
||||
}
|
||||
|
||||
if(!h->neededlibs && neededlibs)
|
||||
h->neededlibs = neededlibs;
|
||||
|
||||
DumpDynamicNeeded(h);
|
||||
int cnt = 0;
|
||||
for (uint32_t i=0; i<h->numDynamic; ++i)
|
||||
// count the number of needed libs, and also grab soname
|
||||
for (uint32_t i=0; i<h->numDynamic; ++i) {
|
||||
if(h->Dynamic[i].d_tag==DT_NEEDED)
|
||||
++cnt;
|
||||
const char* nlibs[cnt];
|
||||
if(h->Dynamic[i].d_tag==DT_SONAME)
|
||||
h->soname = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
|
||||
}
|
||||
h->needed = new_neededlib(cnt);
|
||||
if(h == my_context->elfs[0])
|
||||
my_context->neededlibs = h->needed;
|
||||
int j=0;
|
||||
for (uint32_t i=0; i<h->numDynamic; ++i)
|
||||
if(h->Dynamic[i].d_tag==DT_NEEDED)
|
||||
nlibs[j++] = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
|
||||
h->needed->names[j++] = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
|
||||
|
||||
// TODO: Add LD_LIBRARY_PATH and RPATH handling
|
||||
if(AddNeededLib(maplib, neededlibs, deplib, local, bindnow, nlibs, cnt, box86, emu)) {
|
||||
if(AddNeededLib(maplib, local, bindnow, h->needed, h, box86, emu)) {
|
||||
printf_log(LOG_INFO, "Error loading one of needed lib\n");
|
||||
if(!allow_missing_libs)
|
||||
return 1; //error...
|
||||
@@ -1289,30 +1405,35 @@ void MarkElfInitDone(elfheader_t* h)
|
||||
if(h)
|
||||
h->init_done = 1;
|
||||
}
|
||||
void startMallocHook();
|
||||
void RunElfInitPltResolver(elfheader_t* h, x86emu_t *emu)
|
||||
{
|
||||
if(!h || h->init_done)
|
||||
return;
|
||||
|
||||
uintptr_t p = h->initentry + h->delta;
|
||||
h->init_done = 1;
|
||||
for(int i=0; i<h->neededlibs->size; ++i) {
|
||||
library_t *lib = h->neededlibs->libs[i];
|
||||
for(int i=0; i<h->needed->size; ++i) {
|
||||
library_t *lib = h->needed->libs[i];
|
||||
elfheader_t *lib_elf = GetElf(lib);
|
||||
if(lib_elf)
|
||||
RunElfInitPltResolver(lib_elf, emu);
|
||||
}
|
||||
printf_log(LOG_DEBUG, "Calling Init for %s %p\n", ElfName(h), (void*)p);
|
||||
if(h->initentry)
|
||||
RunSafeFunction(my_context, p, 3, my_context->argc, my_context->argv, my_context->envv);
|
||||
RunSafeFunction(p, 3, my_context->argc, my_context->argv, my_context->envv);
|
||||
printf_log(LOG_DEBUG, "Done Init for %s\n", ElfName(h));
|
||||
// and check init array now
|
||||
Elf32_Addr *addr = (Elf32_Addr*)(h->initarray + h->delta);
|
||||
for (int i=0; i<h->initarray_sz; ++i) {
|
||||
printf_log(LOG_DEBUG, "Calling Init[%d] for %s %p\n", i, ElfName(h), (void*)addr[i]);
|
||||
RunSafeFunction(my_context, (uintptr_t)addr[i], 3, my_context->argc, my_context->argv, my_context->envv);
|
||||
if(addr[i]) {
|
||||
printf_log(LOG_DEBUG, "Calling Init[%d] for %s %p\n", i, ElfName(h), (void*)addr[i]);
|
||||
RunSafeFunction((uintptr_t)addr[i], 3, my_context->argc, my_context->argv, my_context->envv);
|
||||
}
|
||||
}
|
||||
|
||||
if(h->malloc_hook_2)
|
||||
startMallocHook();
|
||||
|
||||
h->fini_done = 0; // can be fini'd now (in case it was re-inited)
|
||||
printf_log(LOG_DEBUG, "All Init Done for %s\n", ElfName(h));
|
||||
return;
|
||||
@@ -1328,44 +1449,55 @@ void RunElfInit(elfheader_t* h, x86emu_t *emu)
|
||||
// Refresh no-file part of TLS in case default value changed
|
||||
RefreshElfTLS(h);
|
||||
// check if in deferedInit
|
||||
if(context->deferedInit) {
|
||||
if(context->deferedInitSz==context->deferedInitCap) {
|
||||
context->deferedInitCap += 4;
|
||||
context->deferedInitList = (elfheader_t**)box_realloc(context->deferedInitList, context->deferedInitCap*sizeof(elfheader_t*));
|
||||
if(context->deferredInit) {
|
||||
if(context->deferredInitSz==context->deferredInitCap) {
|
||||
context->deferredInitCap += 4;
|
||||
context->deferredInitList = (elfheader_t**)box_realloc(context->deferredInitList, context->deferredInitCap*sizeof(elfheader_t*));
|
||||
}
|
||||
context->deferedInitList[context->deferedInitSz++] = h;
|
||||
context->deferredInitList[context->deferredInitSz++] = h;
|
||||
return;
|
||||
}
|
||||
printf_log(LOG_DEBUG, "Calling Init for %s %p\n", ElfName(h), (void*)p);
|
||||
h->init_done = 1;
|
||||
for(int i=0; i<h->needed->size; ++i) {
|
||||
library_t *lib = h->needed->libs[i];
|
||||
elfheader_t *lib_elf = GetElf(lib);
|
||||
if(lib_elf)
|
||||
RunElfInit(lib_elf, emu);
|
||||
}
|
||||
printf_dump(LOG_DEBUG, "Calling Init for %s @%p\n", ElfName(h), (void*)p);
|
||||
if(h->initentry)
|
||||
RunFunctionWithEmu(emu, 0, p, 3, context->argc, context->argv, context->envv);
|
||||
printf_log(LOG_DEBUG, "Done Init for %s\n", ElfName(h));
|
||||
printf_dump(LOG_DEBUG, "Done Init for %s\n", ElfName(h));
|
||||
// and check init array now
|
||||
Elf32_Addr *addr = (Elf32_Addr*)(h->initarray + h->delta);
|
||||
for (int i=0; i<h->initarray_sz; ++i) {
|
||||
printf_log(LOG_DEBUG, "Calling Init[%d] for %s %p\n", i, ElfName(h), (void*)addr[i]);
|
||||
RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 3, context->argc, context->argv, context->envv);
|
||||
for (size_t i=0; i<h->initarray_sz; ++i) {
|
||||
if(addr[i]) {
|
||||
printf_dump(LOG_DEBUG, "Calling Init[%zu] for %s @%p\n", i, ElfName(h), (void*)addr[i]);
|
||||
RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 3, context->argc, context->argv, context->envv);
|
||||
}
|
||||
}
|
||||
|
||||
if(h->malloc_hook_2)
|
||||
startMallocHook();
|
||||
|
||||
h->fini_done = 0; // can be fini'd now (in case it was re-inited)
|
||||
printf_log(LOG_DEBUG, "All Init Done for %s\n", ElfName(h));
|
||||
printf_dump(LOG_DEBUG, "All Init Done for %s\n", ElfName(h));
|
||||
return;
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
void RunDeferedElfInit(x86emu_t *emu)
|
||||
void RunDeferredElfInit(x86emu_t *emu)
|
||||
{
|
||||
box86context_t* context = GetEmuContext(emu);
|
||||
if(!context->deferedInit)
|
||||
if(!context->deferredInit)
|
||||
return;
|
||||
context->deferedInit = 0;
|
||||
if(!context->deferedInitList)
|
||||
context->deferredInit = 0;
|
||||
if(!context->deferredInitList)
|
||||
return;
|
||||
int Sz = context->deferedInitSz;
|
||||
elfheader_t** List = context->deferedInitList;
|
||||
context->deferedInitList = NULL;
|
||||
context->deferedInitCap = context->deferedInitSz = 0;
|
||||
int Sz = context->deferredInitSz;
|
||||
elfheader_t** List = context->deferredInitList;
|
||||
context->deferredInitList = NULL;
|
||||
context->deferredInitCap = context->deferredInitSz = 0;
|
||||
for (int i=0; i<Sz; ++i)
|
||||
RunElfInit(List[i], emu);
|
||||
box_free(List);
|
||||
@@ -1373,7 +1505,7 @@ void RunDeferedElfInit(x86emu_t *emu)
|
||||
|
||||
void RunElfFini(elfheader_t* h, x86emu_t *emu)
|
||||
{
|
||||
if(!h || h->fini_done)
|
||||
if(!h || h->fini_done || !h->init_done)
|
||||
return;
|
||||
h->fini_done = 1;
|
||||
#ifdef ANDROID
|
||||
@@ -1420,7 +1552,7 @@ uint32_t GetBaseSize(elfheader_t* h)
|
||||
return h->memsz;
|
||||
}
|
||||
|
||||
int IsAddressInElfSpace(elfheader_t* h, uintptr_t addr)
|
||||
int IsAddressInElfSpace(const elfheader_t* h, uintptr_t addr)
|
||||
{
|
||||
if(!h)
|
||||
return 0;
|
||||
@@ -1450,7 +1582,23 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin
|
||||
const char* ret = NULL;
|
||||
uintptr_t s = 0;
|
||||
uint32_t size = 0;
|
||||
if(!h)
|
||||
#ifdef HAVE_TRACE
|
||||
if(!h) {
|
||||
if(getProtection((uintptr_t)p)&(PROT_READ)) {
|
||||
if(*(uint8_t*)(p)==0xCC && *(uint8_t*)(p+1)=='S' && *(uint8_t*)(p+2)=='C') {
|
||||
ret = getBridgeName(*(void**)(p+3+4));
|
||||
if(ret) {
|
||||
if(start)
|
||||
*start = (uintptr_t)p;
|
||||
if(sz)
|
||||
*sz = 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
if(!h || h->fini_done)
|
||||
return ret;
|
||||
|
||||
for (uint32_t i=0; (i<h->numSymTab) && (distance!=0); ++i) {
|
||||
@@ -1488,7 +1636,7 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char* VersionnedName(const char* name, int ver, const char* vername)
|
||||
const char* VersionedName(const char* name, int ver, const char* vername)
|
||||
{
|
||||
if(ver<0)
|
||||
return name;
|
||||
@@ -1508,7 +1656,7 @@ const char* VersionnedName(const char* name, int ver, const char* vername)
|
||||
return AddDictionnary(my_context->versym, buf);
|
||||
}
|
||||
|
||||
int SameVersionnedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2)
|
||||
int SameVersionedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2)
|
||||
{
|
||||
if(strcmp(name1, name2)) //name are different, no need to go further
|
||||
return 0;
|
||||
@@ -1532,12 +1680,12 @@ void* GetDTatOffset(box86context_t* context, int index, int offset)
|
||||
|
||||
int32_t GetTLSBase(elfheader_t* h)
|
||||
{
|
||||
return h->tlsbase;
|
||||
return h?h->tlsbase:0;
|
||||
}
|
||||
|
||||
uint32_t GetTLSSize(elfheader_t* h)
|
||||
{
|
||||
return h->tlssize;
|
||||
return h?h->tlssize:0;
|
||||
}
|
||||
|
||||
void* GetTLSPointer(box86context_t* context, elfheader_t* h)
|
||||
@@ -1607,8 +1755,9 @@ void* ElfSetBrk(void* newbrk)
|
||||
}
|
||||
|
||||
#ifdef DYNAREC
|
||||
dynablocklist_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t addr)
|
||||
dynablock_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t addr)
|
||||
{
|
||||
(void)context;
|
||||
// if we are here, the there is not block in standard "space"
|
||||
/*dynablocklist_t* ret = getDBFromAddress(addr);
|
||||
if(ret) {
|
||||
@@ -1616,7 +1765,7 @@ dynablocklist_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t add
|
||||
}*/
|
||||
if(box86_dynarec_forced) {
|
||||
addDBFromAddressRange(addr, 1);
|
||||
return getDB(addr>>DYNAMAP_SHIFT);
|
||||
return getDB(addr);
|
||||
}
|
||||
//check if address is in an elf... if yes, grant a block (should I warn)
|
||||
Dl_info info;
|
||||
@@ -1629,26 +1778,6 @@ dynablocklist_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t add
|
||||
}
|
||||
#endif
|
||||
|
||||
kh_mapsymbols_t* GetMapSymbols(elfheader_t* h)
|
||||
{
|
||||
if(!h)
|
||||
return NULL;
|
||||
return h->mapsymbols;
|
||||
}
|
||||
kh_mapsymbols_t* GetWeakSymbols(elfheader_t* h)
|
||||
{
|
||||
if(!h)
|
||||
return NULL;
|
||||
return h->weaksymbols;
|
||||
}
|
||||
kh_mapsymbols_t* GetLocalSymbols(elfheader_t* h)
|
||||
{
|
||||
if(!h)
|
||||
return NULL;
|
||||
return h->localsymbols;
|
||||
}
|
||||
|
||||
|
||||
typedef struct my_dl_phdr_info_s {
|
||||
void* dlpi_addr;
|
||||
const char* dlpi_name;
|
||||
@@ -1671,14 +1800,14 @@ GO(4)
|
||||
|
||||
// dl_iterate_phdr ...
|
||||
#define GO(A) \
|
||||
static uintptr_t my_dl_iterate_phdr_fct_##A = 0; \
|
||||
static int my_dl_iterate_phdr_##A(struct dl_phdr_info* a, size_t b, void* c)\
|
||||
{ \
|
||||
if(!a->dlpi_name) \
|
||||
return 0; \
|
||||
if(!a->dlpi_name[0]) /*don't send informations about box86 itself*/ \
|
||||
return 0; \
|
||||
return RunFunction(my_context, my_dl_iterate_phdr_fct_##A, 3, a, b, c); \
|
||||
static uintptr_t my_dl_iterate_phdr_fct_##A = 0; \
|
||||
static int my_dl_iterate_phdr_##A(struct dl_phdr_info* a, size_t b, void* c) \
|
||||
{ \
|
||||
if(!a->dlpi_name) \
|
||||
return 0; \
|
||||
if(!a->dlpi_name[0]) /*don't send informations about box86 itself*/ \
|
||||
return 0; \
|
||||
return RunFunctionFmt(my_dl_iterate_phdr_fct_##A, "pLp", a, b, c); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
@@ -1801,6 +1930,25 @@ void ElfAttachLib(elfheader_t* head, library_t* lib)
|
||||
head->lib = lib;
|
||||
}
|
||||
|
||||
kh_mapsymbols_t* GetMapSymbols(elfheader_t* h)
|
||||
{
|
||||
if(!h)
|
||||
return NULL;
|
||||
return h->mapsymbols;
|
||||
}
|
||||
kh_mapsymbols_t* GetWeakSymbols(elfheader_t* h)
|
||||
{
|
||||
if(!h)
|
||||
return NULL;
|
||||
return h->weaksymbols;
|
||||
}
|
||||
kh_mapsymbols_t* GetLocalSymbols(elfheader_t* h)
|
||||
{
|
||||
if(!h)
|
||||
return NULL;
|
||||
return h->localsymbols;
|
||||
}
|
||||
|
||||
typedef struct search_symbol_s{
|
||||
const char* name;
|
||||
void* addr;
|
||||
@@ -1858,7 +2006,7 @@ int dl_iterate_phdr_findsymbol(struct dl_phdr_info* info, size_t size, void* dat
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* GetNativeSymbolUnversionned(void* lib, const char* name)
|
||||
void* GetNativeSymbolUnversioned(void* lib, const char* name)
|
||||
{
|
||||
// try to find "name" in loaded elf, whithout checking for the symbol version (like dlsym, but no version check)
|
||||
search_symbol_t s;
|
||||
@@ -1873,6 +2021,16 @@ void* GetNativeSymbolUnversionned(void* lib, const char* name)
|
||||
return s.addr;
|
||||
}
|
||||
|
||||
kh_defaultversion_t* GetGlobalDefaultVersion(elfheader_t* h)
|
||||
{
|
||||
return h?h->globaldefver:NULL;
|
||||
}
|
||||
kh_defaultversion_t* GetWeakDefaultVersion(elfheader_t* h)
|
||||
{
|
||||
return h?h->weakdefver:NULL;
|
||||
}
|
||||
|
||||
|
||||
uintptr_t pltResolver = ~(uintptr_t)0;
|
||||
EXPORT void PltResolver(x86emu_t* emu)
|
||||
{
|
||||
@@ -1880,6 +2038,7 @@ EXPORT void PltResolver(x86emu_t* emu)
|
||||
int slot = (int)Pop32(emu);
|
||||
elfheader_t *h = (elfheader_t*)addr;
|
||||
printf_dump(LOG_DEBUG, "PltResolver: Addr=%p, Slot=%d Return=%p: elf is %s (VerSym=%p)\n", (void*)addr, slot, *(void**)(R_ESP), h->name, h->VerSym);
|
||||
|
||||
Elf32_Rel * rel = (Elf32_Rel *)(h->jmprel + h->delta + slot);
|
||||
|
||||
Elf32_Sym *sym = &h->DynSym[ELF32_R_SYM(rel->r_info)];
|
||||
@@ -1894,11 +2053,15 @@ EXPORT void PltResolver(x86emu_t* emu)
|
||||
|
||||
library_t* lib = h->lib;
|
||||
lib_t* local_maplib = GetMaplib(lib);
|
||||
GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, version, vername);
|
||||
if(!offs && !end && local_maplib)
|
||||
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername);
|
||||
const char* globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==local_maplib)?NULL:local_maplib, 0, symname);
|
||||
const char* weakdefver = (bind==STB_WEAK)?GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==local_maplib)?NULL:local_maplib, 1, symname):NULL;
|
||||
GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, version, vername, globdefver, weakdefver);
|
||||
if(!offs && !end && local_maplib) {
|
||||
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, globdefver, weakdefver);
|
||||
}
|
||||
if(!offs && !end && !version)
|
||||
GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, -1, NULL);
|
||||
GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, -1, NULL, globdefver, weakdefver);
|
||||
|
||||
|
||||
if (!offs) {
|
||||
printf_log(LOG_NONE, "Error: PltResolver: Symbol %s(ver %d: %s%s%s) not found, cannot apply R_386_JMP_SLOT %p (%p) in %s\n", symname, version, symname, vername?"@":"", vername?vername:"", p, *(void**)p, h->name);
|
||||
@@ -1910,6 +2073,7 @@ EXPORT void PltResolver(x86emu_t* emu)
|
||||
printf_dump(LOG_DEBUG, "symbol %s from %s but elf not initialized yet, run Init now (from %s)\n", symname, ElfName(sym_elf), ElfName(h));
|
||||
RunElfInitPltResolver(sym_elf, emu);
|
||||
}
|
||||
offs = (uintptr_t)getAlternate((void*)offs);
|
||||
|
||||
if(p) {
|
||||
printf_dump(LOG_DEBUG, " Apply %s R_386_JMP_SLOT %p with sym=%s(ver %d: %s%s%s) (%p -> %p / %s)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, version, symname, vername?"@":"", vername?vername:"",*(void**)p, (void*)offs, ElfName(FindElfAddress(my_context, offs)));
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
#ifndef __ELFLOADER_PRIVATE_H_
|
||||
#define __ELFLOADER_PRIVATE_H_
|
||||
|
||||
#ifdef DYNAREC
|
||||
typedef struct dynablocklist_s dynablocklist_t;
|
||||
#endif
|
||||
|
||||
typedef struct library_s library_t;
|
||||
typedef struct needed_libs_s needed_libs_t;
|
||||
typedef struct kh_mapsymbols_s kh_mapsymbols_t;
|
||||
@@ -15,6 +11,7 @@ typedef struct kh_mapsymbols_s kh_mapsymbols_t;
|
||||
struct elfheader_s {
|
||||
char* name;
|
||||
char* path; // Resolved path to file
|
||||
char* soname; // soname of the elf
|
||||
uint16_t numPHEntries;
|
||||
Elf32_Phdr *PHEntries;
|
||||
uint16_t numSHEntries;
|
||||
@@ -38,6 +35,7 @@ struct elfheader_s {
|
||||
Elf32_Verdef* VerDef;
|
||||
int szVerDef;
|
||||
int e_type;
|
||||
uint32_t flags;
|
||||
|
||||
intptr_t delta; // should be 0
|
||||
|
||||
@@ -70,6 +68,9 @@ struct elfheader_s {
|
||||
int textsz;
|
||||
uintptr_t bss;
|
||||
int bsssz;
|
||||
uintptr_t ehframe;
|
||||
uintptr_t ehframe_end;
|
||||
uintptr_t ehframehdr;
|
||||
|
||||
uintptr_t paddr;
|
||||
uintptr_t vaddr;
|
||||
@@ -87,6 +88,8 @@ struct elfheader_s {
|
||||
|
||||
int init_done;
|
||||
int fini_done;
|
||||
int refcnt; // ref count for the elf
|
||||
int malloc_hook_2; // this elf hook malloc, hacking it
|
||||
|
||||
char* memory; // char* and not void* to allow math on memory pointer
|
||||
void** multiblock;
|
||||
@@ -95,11 +98,13 @@ struct elfheader_s {
|
||||
int multiblock_n;
|
||||
|
||||
library_t *lib;
|
||||
needed_libs_t *neededlibs;
|
||||
needed_libs_t *needed;
|
||||
|
||||
kh_mapsymbols_t *mapsymbols;
|
||||
kh_mapsymbols_t *weaksymbols;
|
||||
kh_mapsymbols_t *localsymbols;
|
||||
kh_defaultversion_t *globaldefver; // the global default version for symbols (the XXX@@vvvv of symbols)
|
||||
kh_defaultversion_t *weakdefver; // the weak default version for symbols (the XXX@@vvvv of symbols)
|
||||
};
|
||||
|
||||
#define R_386_NONE 0
|
||||
|
||||
@@ -273,6 +273,10 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
h->VerDef = (Elf32_Verdef*)ptr;
|
||||
printf_dump(LOG_DEBUG, "The DT_VERDEF is at address %p\n", h->VerDef);
|
||||
break;
|
||||
case DT_FLAGS:
|
||||
h->flags = val;
|
||||
printf_dump(LOG_DEBUG, "The DT_FLAGS is 0x%x\n", h->flags);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(h->rel) {
|
||||
@@ -351,6 +355,17 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
h->bsssz = h->SHEntries[ii].sh_size;
|
||||
printf_dump(LOG_DEBUG, "The .bss is at address %p, and is %d big\n", (void*)h->bss, h->bsssz);
|
||||
}
|
||||
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".eh_frame");
|
||||
if(ii) {
|
||||
h->ehframe = (uintptr_t)(h->SHEntries[ii].sh_addr);
|
||||
h->ehframe_end = h->ehframe + h->SHEntries[ii].sh_size;
|
||||
printf_dump(LOG_DEBUG, "The .eh_frame section is at address %p..%p\n", (void*)h->ehframe, (void*)h->ehframe_end);
|
||||
}
|
||||
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".eh_frame_hdr");
|
||||
if(ii) {
|
||||
h->ehframehdr = (uintptr_t)(h->SHEntries[ii].sh_addr);
|
||||
printf_dump(LOG_DEBUG, "The .eh_frame_hdr section is at address %p\n", (void*)h->ehframehdr);
|
||||
}
|
||||
|
||||
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynstr", "DynSym Strings", SHT_STRTAB, (void**)&h->DynStr, NULL);
|
||||
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynsym", "DynSym", SHT_DYNSYM, (void**)&h->DynSym, &h->numDynSym);
|
||||
@@ -399,3 +414,59 @@ const char* GetParentSymbolVersion(elfheader_t* h, int index)
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int GetVersionIndice(elfheader_t* h, const char* vername)
|
||||
{
|
||||
if(!vername)
|
||||
return 0;
|
||||
if(h->VerDef) {
|
||||
Elf32_Verdef *def = (Elf32_Verdef*)((uintptr_t)h->VerDef + h->delta);
|
||||
while(def) {
|
||||
Elf32_Verdaux *aux = (Elf32_Verdaux*)((uintptr_t)def + def->vd_aux);
|
||||
if(!strcmp(h->DynStr+aux->vda_name, vername))
|
||||
return def->vd_ndx;
|
||||
def = def->vd_next?((Elf32_Verdef*)((uintptr_t)def + def->vd_next)):NULL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetNeededVersionCnt(elfheader_t* h, const char* libname)
|
||||
{
|
||||
if(!libname)
|
||||
return 0;
|
||||
if(h->VerNeed) {
|
||||
Elf32_Verneed *ver = (Elf32_Verneed*)((uintptr_t)h->VerNeed + h->delta);
|
||||
while(ver) {
|
||||
char *filename = h->DynStr + ver->vn_file;
|
||||
Elf32_Vernaux *aux = (Elf32_Vernaux*)((uintptr_t)ver + ver->vn_aux);
|
||||
if(!strcmp(filename, libname))
|
||||
return ver->vn_cnt;
|
||||
ver = ver->vn_next?((Elf32_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx)
|
||||
{
|
||||
if(!libname)
|
||||
return 0;
|
||||
if(h->VerNeed) {
|
||||
Elf32_Verneed *ver = (Elf32_Verneed*)((uintptr_t)h->VerNeed + h->delta);
|
||||
while(ver) {
|
||||
char *filename = h->DynStr + ver->vn_file;
|
||||
Elf32_Vernaux *aux = (Elf32_Vernaux*)((uintptr_t)ver + ver->vn_aux);
|
||||
if(!strcmp(filename, libname)) {
|
||||
for(int j=0; j<ver->vn_cnt; ++j) {
|
||||
if(j==idx)
|
||||
return h->DynStr+aux->vna_name;
|
||||
aux = (Elf32_Vernaux*)((uintptr_t)aux + aux->vna_next);
|
||||
}
|
||||
return NULL; // idx out of bound, return NULL...
|
||||
}
|
||||
ver = ver->vn_next?((Elf32_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
+1
-1
@@ -107,7 +107,7 @@
|
||||
case 7: base = R_BX; break; \
|
||||
} \
|
||||
switch((m>>6)&3) { \
|
||||
case 0: if(m==6) base = F16; break; \
|
||||
case 0: if(m&7==6) base = F16S; break; \
|
||||
case 1: base += F8S; break; \
|
||||
case 2: base += F16S; break; \
|
||||
} \
|
||||
|
||||
+1
-12
@@ -54,17 +54,6 @@ uint32_t* GetParityTab()
|
||||
return x86emu_parity_tab;
|
||||
}
|
||||
|
||||
void PushExit(x86emu_t* emu)
|
||||
{
|
||||
uintptr_t endMarker = AddCheckBridge(my_context->system, NULL, NULL, 0, "(ExitEmulation)");
|
||||
Push(emu, endMarker);
|
||||
}
|
||||
|
||||
void* GetExit()
|
||||
{
|
||||
return (void*)AddCheckBridge(my_context->system, NULL, NULL, 0, "(ExitEmulation)");
|
||||
}
|
||||
|
||||
static void internalX86Setup(x86emu_t* emu, box86context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
|
||||
{
|
||||
emu->context = context;
|
||||
@@ -512,8 +501,8 @@ uint64_t ReadTSC(x86emu_t* emu)
|
||||
uint64_t ret;
|
||||
__asm__ volatile("rdtsc" : "=A"(ret));
|
||||
return ret;
|
||||
#if 0
|
||||
#elif defined(__ARM_ARCH)
|
||||
#if 0
|
||||
#if (__ARM_ARCH >= 6)
|
||||
static int init = 1;
|
||||
if(init) {
|
||||
|
||||
+40
-63
@@ -65,10 +65,12 @@ int Run(x86emu_t *emu, int step)
|
||||
if(emu->quit)
|
||||
return 0;
|
||||
if(addr==0) {
|
||||
emu->quit = 1;
|
||||
printf_log(LOG_INFO, "%04d|Ask to run at NULL, quit silently\n", GetTID());
|
||||
print_cycle_log(LOG_INFO);
|
||||
return 0;
|
||||
// emu->quit = 1;
|
||||
// printf_log(LOG_INFO, "%04d|Ask to run at NULL, quit silently\n", GetTID());
|
||||
// print_cycle_log(LOG_INFO);
|
||||
// return 0;
|
||||
// Some program, like C# Vara.exe, need to trigger that segfault to actually run... (ticket #830à)
|
||||
printf_log(LOG_INFO, "%04d|Ask to run at NULL, will segfault\n", GetTID());
|
||||
}
|
||||
//ref opcode: http://ref.x64asm.net/geek32.html#xA1
|
||||
printf_log(LOG_DEBUG, "Run X86 (%p), RIP=%p, Stack=%p\n", emu, (void*)addr, (void*)R_ESP);
|
||||
@@ -421,46 +423,14 @@ x86emurun:
|
||||
GD.dword[0] = imul32(emu, ED->dword[0], (uint32_t)tmp32s);
|
||||
break;
|
||||
case 0x6C: /* INSB */
|
||||
tmp32u = rep?R_ECX:1;
|
||||
while(tmp32u--) {
|
||||
*(int8_t*)(R_EDI+GetESBaseEmu(emu)) = 0; // faking port read, using explicit ES segment
|
||||
if(ACCESS_FLAG(F_DF))
|
||||
R_EDI-=1;
|
||||
else
|
||||
R_EDI+=1;
|
||||
}
|
||||
if(rep)
|
||||
R_ECX = 0;
|
||||
break;
|
||||
case 0x6D: /* INSD */
|
||||
tmp32u = rep?R_ECX:1;
|
||||
while(tmp32u--) {
|
||||
*(int32_t*)(R_EDI+GetESBaseEmu(emu)) = 0; // faking port read, using explicit ES segment
|
||||
if(ACCESS_FLAG(F_DF))
|
||||
R_EDI-=4;
|
||||
else
|
||||
R_EDI+=4;
|
||||
}
|
||||
if(rep)
|
||||
R_ECX = 0;
|
||||
break;
|
||||
case 0x6E: /* OUTSB */
|
||||
// faking port write, using explicit ES segment
|
||||
if(ACCESS_FLAG(F_DF))
|
||||
R_ESI-=rep?R_ECX:1;
|
||||
else
|
||||
R_ESI+=1?R_ECX:1;
|
||||
if(rep)
|
||||
R_ECX = 0;
|
||||
break;
|
||||
case 0x6F: /* OUTSD */
|
||||
// faking port write, using explicit ES segment
|
||||
if(ACCESS_FLAG(F_DF))
|
||||
R_ESI-=(rep?R_ECX:1)*4;
|
||||
else
|
||||
R_ESI+=(rep?R_ECX:1)*4;
|
||||
if(rep)
|
||||
R_ECX = 0;
|
||||
#ifndef TEST_INTERPRETER
|
||||
// this is a privilege opcode
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 0);
|
||||
STEP;
|
||||
#endif
|
||||
break;
|
||||
|
||||
#define GOCOND(BASE, PREFIX, CONDITIONAL) \
|
||||
@@ -734,6 +704,15 @@ x86emurun:
|
||||
case 0x9D: /* POPF */
|
||||
emu->eflags.x32 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1
|
||||
RESET_FLAGS(emu);
|
||||
#ifndef TEST_INTERPRETER
|
||||
if(ACCESS_FLAG(F_TF)) {
|
||||
R_EIP = addr;
|
||||
emit_signal(emu, SIGTRAP, (void*)addr, 1);
|
||||
if(emu->quit) goto fini;
|
||||
CLEAR_FLAG(F_TF);
|
||||
STEP;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 0x9E: /* SAHF */
|
||||
tmp8u = emu->regs[_AX].byte[1];
|
||||
@@ -1355,20 +1334,14 @@ x86emurun:
|
||||
STEP2;
|
||||
break;
|
||||
case 0xE4: /* IN AL, Ib */
|
||||
tmp32s = F8; // port address
|
||||
R_AL = 0; // nothing... should do a warning maybe?
|
||||
break;
|
||||
case 0xE5: /* IN EAX, Ib */
|
||||
tmp32s = F8; // port address
|
||||
R_EAX = 0; // nothing... should do a warning maybe?
|
||||
break;
|
||||
case 0xE6: /* OUT Ib, AL */
|
||||
tmp32s = F8; // port address
|
||||
//nothing goes out...
|
||||
break;
|
||||
case 0xE7: /* OUT Ib, EAX */
|
||||
tmp32s = F8; // port address
|
||||
//nothing goes out...
|
||||
#ifndef TEST_INTERPRETER
|
||||
// this is a privilege opcode
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 0);
|
||||
STEP;
|
||||
#endif
|
||||
break;
|
||||
case 0xE8: /* CALL Id */
|
||||
tmp32s = F32S; // call is relative
|
||||
@@ -1379,6 +1352,7 @@ x86emurun:
|
||||
case 0xE9: /* JMP Id */
|
||||
tmp32s = F32S; // jmp is relative
|
||||
addr += tmp32s;
|
||||
addr = (uintptr_t)getAlternate((void*)addr);
|
||||
STEP2;
|
||||
break;
|
||||
|
||||
@@ -1388,13 +1362,14 @@ x86emurun:
|
||||
STEP2;
|
||||
break;
|
||||
case 0xEC: /* IN AL, DX */
|
||||
R_AL = 0; // nothing... should do a warning maybe?
|
||||
break;
|
||||
case 0xED: /* IN EAX, DX */
|
||||
R_EAX = 0; // nothing... should do a warning maybe?
|
||||
break;
|
||||
case 0xEE: /* OUT DX, AL */
|
||||
//nothing goes out...
|
||||
case 0xEF: /* OUT DX, EAX */
|
||||
#ifndef TEST_INTERPRETER
|
||||
// this is a privilege opcode
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 0);
|
||||
STEP;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0xF0: /* LOCK */
|
||||
@@ -1417,10 +1392,10 @@ x86emurun:
|
||||
break;
|
||||
|
||||
case 0xF4: /* HLT */
|
||||
// this is a privilege opcode... should an error be called instead?
|
||||
#ifndef TEST_INTERPRETER
|
||||
sched_yield();
|
||||
STEP2;
|
||||
// this is a privilege opcode
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 0);
|
||||
STEP;
|
||||
#endif
|
||||
break;
|
||||
case 0xF5: /* CMC */
|
||||
@@ -1496,10 +1471,12 @@ x86emurun:
|
||||
SET_FLAG(F_CF);
|
||||
break;
|
||||
case 0xFA: /* CLI */
|
||||
CLEAR_FLAG(F_IF); //not really handled...
|
||||
break;
|
||||
case 0xFB: /* STI */
|
||||
SET_FLAG(F_IF);
|
||||
#ifndef TEST_INTERPRETER
|
||||
// this is a privilege opcode
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 0);
|
||||
STEP;
|
||||
#endif
|
||||
break;
|
||||
case 0xFC: /* CLD */
|
||||
CLEAR_FLAG(F_DF);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "signals.h"
|
||||
#ifdef DYNAREC
|
||||
#include "../dynarec/arm_lock_helper.h"
|
||||
#include "custommem.h"
|
||||
#endif
|
||||
|
||||
#include "modrm.h"
|
||||
@@ -1059,6 +1060,13 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
|
||||
applyFlushTo0(emu);
|
||||
#endif
|
||||
break;
|
||||
case 7: /* CLFLUSH Ed */
|
||||
GET_ED_(0);
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(box86_dynarec)
|
||||
cleanDBFromAddressRange((uintptr_t)ED, 8, 0);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -890,7 +890,7 @@ void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
|
||||
const uint8_t pk1 = PK(1);
|
||||
if(((pk1>>3)&7)==2 || ((pk1>>3)&7)==4) { // jmp/call near
|
||||
uintptr_t nextaddr = (uintptr_t)getAlternate((void*)evalED(emu, ip+1));
|
||||
printf_log(LOG_NONE, " => %p", nextaddr);
|
||||
printf_log(LOG_NONE, " => %p", (void*)nextaddr);
|
||||
printFunctionAddr(nextaddr, " / ");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <stdint.h>
|
||||
#include "regs.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "box86context.h"
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
|
||||
static inline uint8_t Fetch8(x86emu_t *emu) {return *(uint8_t*)(R_EIP++);}
|
||||
@@ -52,6 +53,12 @@ static inline void Push(x86emu_t *emu, uint32_t v)
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void PushExit(x86emu_t* emu)
|
||||
{
|
||||
R_ESP -= 4;
|
||||
*((uint32_t*)R_ESP) = my_context->exit_bridge;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// the op code definition can be found here: http://ref.x86asm.net/geek32.html
|
||||
static inline reg32_t* GetECommon(x86emu_t* emu, uint32_t m)
|
||||
|
||||
@@ -51,6 +51,7 @@ int32_t my___sendmmsg(x86emu_t* emu, int32_t fd, void* msgvec, uint32_t vlen, ui
|
||||
#endif
|
||||
#endif
|
||||
typedef struct x86_sigaction_s x86_sigaction_t;
|
||||
typedef struct x86_sigaction_restorer_s x86_sigaction_restorer_t;
|
||||
|
||||
|
||||
int32_t my_getrandom(x86emu_t* emu, void* buf, uint32_t buflen, uint32_t flags);
|
||||
@@ -67,6 +68,7 @@ int32_t my_epoll_ctl(x86emu_t* emu, int32_t epfd, int32_t op, int32_t fd, void*
|
||||
int32_t my_epoll_wait(x86emu_t* emu, int32_t epfd, void* events, int32_t maxevents, int32_t timeout);
|
||||
#endif
|
||||
int my_sigaction(x86emu_t* emu, int signum, const x86_sigaction_t *act, x86_sigaction_t *oldact);
|
||||
int my_syscall_sigaction(x86emu_t* emu, int signum, const x86_sigaction_restorer_t *act, x86_sigaction_restorer_t *oldact, int sigsetsize);
|
||||
int32_t my_execve(x86emu_t* emu, const char* path, char* const argv[], char* const envp[]);
|
||||
void* my_mmap(x86emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int offset);
|
||||
void* my_mmap64(x86emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int64_t offset);
|
||||
@@ -139,6 +141,9 @@ scwrap_t syscallwrap[] = {
|
||||
{ 19, __NR_lseek, 3 },
|
||||
{ 20, __NR_getpid, 0 },
|
||||
{ 24, __NR_getuid, 0 },
|
||||
#ifdef __NR_alarm
|
||||
{ 27, __NR_alarm, 1 },
|
||||
#endif
|
||||
{ 33, __NR_access, 2 },
|
||||
{ 37, __NR_kill, 2 },
|
||||
{ 38, __NR_rename, 2 },
|
||||
@@ -156,12 +161,14 @@ scwrap_t syscallwrap[] = {
|
||||
{ 63, __NR_dup2, 2 },
|
||||
{ 64, __NR_getppid, 0 },
|
||||
{ 66, __NR_setsid, 0 },
|
||||
//{ 67, __NR_sigaction, 3 },
|
||||
{ 75, __NR_setrlimit, 2 },
|
||||
#ifdef __NR_getrlimit
|
||||
{ 76, __NR_getrlimit, 2 },
|
||||
#endif
|
||||
{ 77, __NR_getrusage, 2 },
|
||||
{ 78, __NR_gettimeofday, 2 },
|
||||
{ 80, __NR_getgroups, 2 },
|
||||
{ 83, __NR_symlink, 2 },
|
||||
#ifdef __NR_select
|
||||
{ 82, __NR_select, 5 },
|
||||
@@ -205,6 +212,7 @@ scwrap_t syscallwrap[] = {
|
||||
//{ 122, __NR_uname, 1 },
|
||||
//{ 123, __NR_modify_ldt },
|
||||
//{ 125, __NR_mprotect, 3 },
|
||||
{ 126, __NR_sigprocmask, 3 },
|
||||
{ 136, __NR_personality, 1 },
|
||||
{ 140, __NR__llseek, 5 },
|
||||
{ 141, __NR_getdents, 3 },
|
||||
@@ -480,6 +488,13 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_alarm
|
||||
case 27:
|
||||
R_EAX = alarm(R_EBX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
case 45: // sys_brk
|
||||
R_EAX = (uintptr_t)ElfSetBrk((void*)R_EBX);
|
||||
@@ -496,6 +511,11 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
case 67: // sys_sigaction
|
||||
R_EAX = (uint32_t)my_syscall_sigaction(emu, R_EBX, (x86_sigaction_restorer_t*)R_ECX, (x86_sigaction_restorer_t*)R_EDX, R_ESI);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
#ifndef __NR_getrlimit
|
||||
case 76: // sys_getrlimit... this is the old version, using the new one. Maybe some tranform is needed?
|
||||
R_EAX = getrlimit(R_EBX, (void*)R_ECX);
|
||||
@@ -803,8 +823,14 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
|
||||
return (uint32_t)close(i32(4));
|
||||
case 11: // execve
|
||||
return (uint32_t)my_execve(emu, p(4), p(8), p(12));
|
||||
#ifndef __NR_alarm
|
||||
case 27:
|
||||
return alarm(R_EBX);
|
||||
#endif
|
||||
case 45: // brk
|
||||
return (uintptr_t)ElfSetBrk(p(4));
|
||||
case 67: // sys_sigaction
|
||||
return my_syscall_sigaction(emu, u32(4), (x86_sigaction_restorer_t*)p(8), (x86_sigaction_restorer_t*)p(12), u32(16));
|
||||
case 91: // munmap
|
||||
return (uint32_t)my_munmap(emu, p(4), u32(8));
|
||||
#ifndef __NR_socketcall
|
||||
|
||||
@@ -305,6 +305,7 @@ void fpu_fxsave(x86emu_t* emu, void* ed)
|
||||
p->ControlWord = emu->cw.x16;
|
||||
p->StatusWord = emu->sw.x16;
|
||||
p->MxCsr = emu->mxcsr.x32;
|
||||
p->MxCsr_Mask = 0;
|
||||
uint8_t tags = 0;
|
||||
for (int i=0; i<8; ++i)
|
||||
tags |= (emu->p_regs[i].tag==0b11)?0:(1<<(i*2));
|
||||
|
||||
+26
-15
@@ -17,6 +17,7 @@ typedef struct bridge_s bridge_t;
|
||||
typedef struct dlprivate_s dlprivate_t;
|
||||
typedef struct kh_symbolmap_s kh_symbolmap_t;
|
||||
typedef struct kh_defaultversion_s kh_defaultversion_t;
|
||||
typedef struct kh_mapsymbols_s kh_mapsymbols_t;
|
||||
typedef struct library_s library_t;
|
||||
typedef struct linkmap_s linkmap_t;
|
||||
typedef struct kh_fts_s kh_fts_t;
|
||||
@@ -30,7 +31,6 @@ typedef struct atfork_fnc_s {
|
||||
} atfork_fnc_t;
|
||||
#ifdef DYNAREC
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
typedef struct dynablocklist_s dynablocklist_t;
|
||||
typedef struct mmaplist_s mmaplist_t;
|
||||
typedef struct kh_dynablocks_s kh_dynablocks_t;
|
||||
#endif
|
||||
@@ -38,6 +38,7 @@ typedef struct kh_dynablocks_s kh_dynablocks_t;
|
||||
#define DYNAMAP_SIZE (1<<(32-DYNAMAP_SHIFT))
|
||||
#define JMPTABL_SHIFT 16
|
||||
#define JMPTABL_SIZE (1<<(32-JMPTABL_SHIFT))
|
||||
#define JMPTABLE_MASK ((1<<JMPTABL_SHIFT)-1)
|
||||
|
||||
typedef void* (*procaddress_t)(const char* name);
|
||||
typedef void* (*vkprocaddress_t)(void* instance, const char* name);
|
||||
@@ -56,9 +57,15 @@ void free_tlsdatasize(void* p);
|
||||
typedef struct needed_libs_s {
|
||||
int cap;
|
||||
int size;
|
||||
library_t **libs;
|
||||
char** names;
|
||||
library_t** libs;
|
||||
} needed_libs_t;
|
||||
void free_neededlib(needed_libs_t* needed); // defined in library.c
|
||||
|
||||
void free_neededlib(needed_libs_t* needed);
|
||||
needed_libs_t* new_neededlib(int n);
|
||||
needed_libs_t* copy_neededlib(needed_libs_t* needed);
|
||||
void add1_neededlib(needed_libs_t* needed);
|
||||
void add1lib_neededlib(needed_libs_t* needed, library_t* lib, const char* name);
|
||||
|
||||
typedef struct base_segment_s {
|
||||
uintptr_t base;
|
||||
@@ -100,7 +107,8 @@ typedef struct box86context_s {
|
||||
int elfcap;
|
||||
int elfsize; // number of elf loaded
|
||||
|
||||
needed_libs_t neededlibs; // needed libs for main elf
|
||||
needed_libs_t *neededlibs; // needed libs for main elf
|
||||
needed_libs_t *preload;
|
||||
|
||||
uintptr_t ep; // entry point
|
||||
|
||||
@@ -109,18 +117,18 @@ typedef struct box86context_s {
|
||||
|
||||
lib_t *maplib; // lib and symbols handling
|
||||
lib_t *local_maplib; // libs and symbols openned has local (only collection of libs, no symbols)
|
||||
dic_t *versym; // dictionnary of versionned symbols
|
||||
dic_t *versym; // dictionnary of versioned symbols
|
||||
kh_mapsymbols_t *globdata; // GLOBAL_DAT relocation for COPY mapping in main elf
|
||||
|
||||
kh_threadstack_t *stacksizes; // stack sizes attributes for thread (temporary)
|
||||
bridge_t *system; // other bridges
|
||||
uintptr_t exit_bridge; // exit bridge value
|
||||
uintptr_t vsyscall; // vsyscall bridge value
|
||||
dlprivate_t *dlprivate; // dlopen library map
|
||||
kh_symbolmap_t *alwrappers; // the map of wrapper for alGetProcAddress
|
||||
kh_symbolmap_t *almymap; // link to the mysymbolmap if libOpenAL
|
||||
kh_symbolmap_t *vkwrappers; // the map of wrapper for VulkanProcs (TODO: check SDL2)
|
||||
kh_symbolmap_t *vkmymap; // link to the mysymbolmap of libGL
|
||||
kh_defaultversion_t *globaldefver; // the global default version for symbols (the XXX@@vvvv of symbols)
|
||||
kh_defaultversion_t *weakdefver; // the weak default version for symbols (the XXX@@vvvv of symbols)
|
||||
vkprocaddress_t vkprocaddress;
|
||||
|
||||
#ifndef DYNAREC
|
||||
@@ -139,6 +147,7 @@ typedef struct box86context_s {
|
||||
uint32_t mutex_thread;
|
||||
uint32_t mutex_bridge;
|
||||
uint32_t mutex_dyndump;
|
||||
uintptr_t max_db_size; // the biggest (in x86_64 instructions bytes) built dynablock
|
||||
int trace_dynarec;
|
||||
pthread_mutex_t mutex_lock; // this is for the Test interpreter
|
||||
#endif
|
||||
@@ -155,10 +164,10 @@ typedef struct box86context_s {
|
||||
void* sdl2allocrw; // AllocRW/FreeRW functions from SDL2
|
||||
void* sdl2freerw;
|
||||
|
||||
int deferedInit;
|
||||
elfheader_t **deferedInitList;
|
||||
int deferedInitSz;
|
||||
int deferedInitCap;
|
||||
int deferredInit;
|
||||
elfheader_t **deferredInitList;
|
||||
int deferredInitSz;
|
||||
int deferredInitCap;
|
||||
|
||||
pthread_key_t tlskey; // then tls key to have actual tlsdata
|
||||
void* tlsdata; // the initial global tlsdata
|
||||
@@ -167,9 +176,9 @@ typedef struct box86context_s {
|
||||
|
||||
uintptr_t *auxval_start;
|
||||
|
||||
cleanup_t *cleanups; // atexit functions
|
||||
int clean_sz;
|
||||
int clean_cap;
|
||||
cleanup_t *cleanups; // atexit functions
|
||||
int clean_sz;
|
||||
int clean_cap;
|
||||
#ifndef NOALIGN
|
||||
kh_fts_t *ftsmap;
|
||||
#endif
|
||||
@@ -206,7 +215,7 @@ typedef struct box86context_s {
|
||||
#else
|
||||
int GetTID();
|
||||
#define mutex_lock(A) {int tid = GetTID(); while(arm_lock_storeifnull(A, (void*)tid)) sched_yield();}
|
||||
#define mutex_trylock(A) arm_lock_storeifnull(A, (void*)GetTID())
|
||||
#define mutex_trylock(A) (uintptr_t)arm_lock_storeifnull(A, (void*)GetTID())
|
||||
#define mutex_unlock(A) arm_lock_storeifref(A, NULL, (void*)GetTID())
|
||||
#endif
|
||||
|
||||
@@ -222,6 +231,8 @@ void print_cycle_log(int loglevel);
|
||||
|
||||
// return the index of the added header
|
||||
int AddElfHeader(box86context_t* ctx, elfheader_t* head);
|
||||
// remove an elf from list (but list is never reduced, so there can be holes)
|
||||
void RemoveElfHeader(box86context_t* ctx, elfheader_t* head);
|
||||
|
||||
// return the tlsbase (negative) for the new TLS partition created (no partition index is stored in the context)
|
||||
int AddTLSPartition(box86context_t* context, int tlssize);
|
||||
|
||||
@@ -14,7 +14,7 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
|
||||
uintptr_t CheckBridged(bridge_t* bridge, void* fnc);
|
||||
int IsBridge(void* func);
|
||||
uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name);
|
||||
uintptr_t AddAutomaticBridge(x86emu_t* emu, bridge_t* bridge, wrapper_t w, void* fnc, int N);
|
||||
uintptr_t AddAutomaticBridge(x86emu_t* emu, bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name);
|
||||
void* GetNativeFnc(uintptr_t fnc);
|
||||
void* GetNativeFncOrFnc(uintptr_t fnc);
|
||||
|
||||
|
||||
@@ -5,11 +5,15 @@
|
||||
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
|
||||
uint32_t RunFunction(box86context_t *context, uintptr_t fnc, int nargs, ...);
|
||||
uint32_t RunFunction(uintptr_t fnc, int nargs, ...);
|
||||
// using a fmt description
|
||||
uint32_t RunFunctionFmt(uintptr_t fnc, const char* fmt, ...);
|
||||
// use thread local emu to run the function (context is unused now)
|
||||
uint64_t RunFunction64(box86context_t *context, uintptr_t fnc, int nargs, ...);
|
||||
uint64_t RunFunction64(uintptr_t fnc, int nargs, ...);
|
||||
// using a fmt description and returning a 64bit value
|
||||
uint64_t RunFunctionFmt64(uintptr_t fnc, const char* fmt, ...);
|
||||
// use emu state to run function
|
||||
uint32_t RunFunctionWithEmu(x86emu_t *emu, int QuitOnLongJump, uintptr_t fnc, int nargs, ...);
|
||||
|
||||
uint32_t RunSafeFunction(box86context_t *context, uintptr_t fnc, int nargs, ...);
|
||||
uint32_t RunSafeFunction(uintptr_t fnc, int nargs, ...);
|
||||
#endif //__CALLBACK_H__
|
||||
+21
-14
@@ -18,36 +18,43 @@ void customFree(void* p);
|
||||
|
||||
#ifdef DYNAREC
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
typedef struct dynablocklist_s dynablocklist_t;
|
||||
// custom protection flag to mark Page that are Write protected for Dynarec purpose
|
||||
uintptr_t AllocDynarecMap(dynablock_t* db, int size);
|
||||
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size);
|
||||
uintptr_t AllocDynarecMap(size_t size);
|
||||
void FreeDynarecMap(uintptr_t addr);
|
||||
|
||||
void addDBFromAddressRange(uintptr_t addr, uintptr_t size);
|
||||
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy);
|
||||
void addDBFromAddressRange(uintptr_t addr, size_t size);
|
||||
void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy);
|
||||
|
||||
dynablocklist_t* getDB(uintptr_t idx);
|
||||
void addJumpTableIfDefault(void* addr, void* jmp);
|
||||
dynablock_t* getDB(uintptr_t idx);
|
||||
int getNeedTest(uintptr_t idx);
|
||||
int addJumpTableIfDefault(void* addr, void* jmp); // return 1 if write was succesfull
|
||||
int setJumpTableIfRef(void* addr, void* jmp, void* ref); // return 1 if write was succesfull
|
||||
void setJumpTableDefault(void* addr);
|
||||
void setJumpTableDefaultRef(void* addr, void* jmp);
|
||||
int isJumpTableDefault(void* addr);
|
||||
uintptr_t getJumpTable();
|
||||
uintptr_t getJumpTableAddress(uintptr_t addr);
|
||||
uintptr_t getJumpAddress(uintptr_t addr);
|
||||
#endif
|
||||
|
||||
#define PROT_DYNAREC 0x80
|
||||
#define PROT_DYNAREC_R 0x40
|
||||
#define PROT_NOPROT 0x20
|
||||
#define PROT_CUSTOM (PROT_DYNAREC | PROT_DYNAREC_R | PROT_NOPROT)
|
||||
#define PROT_MMAP 0x10
|
||||
#define PROT_DYN (PROT_DYNAREC | PROT_DYNAREC_R | PROT_NOPROT)
|
||||
#define PROT_CUSTOM (PROT_DYNAREC | PROT_DYNAREC_R | PROT_MMAP | PROT_NOPROT)
|
||||
|
||||
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
|
||||
void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
|
||||
void updateProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void setProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void setProtection_mmap(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void freeProtection(uintptr_t addr, size_t size);
|
||||
void refreshProtection(uintptr_t addr);
|
||||
uint32_t getProtection(uintptr_t addr);
|
||||
void forceProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
|
||||
void freeProtection(uintptr_t addr, uintptr_t size);
|
||||
int getMmapped(uintptr_t addr);
|
||||
void loadProtectionFromMap();
|
||||
#ifdef DYNAREC
|
||||
void protectDB(uintptr_t addr, uintptr_t size);
|
||||
void unprotectDB(uintptr_t addr, uintptr_t size, int mark); // if mark==0, the blocks are not marked as potentially dirty
|
||||
void protectDB(uintptr_t addr, size_t size);
|
||||
void unprotectDB(uintptr_t addr, size_t size, int mark); // if mark==0, the blocks are not marked as potentially dirty
|
||||
int isprotectedDB(uintptr_t addr, size_t size);
|
||||
int IsInHotPage(uintptr_t addr);
|
||||
int AreaInHotPage(uintptr_t start, uintptr_t end);
|
||||
|
||||
+9
-1
@@ -24,18 +24,24 @@ extern uintptr_t box86_nodynarec_start, box86_nodynarec_end;
|
||||
extern int box86_dynarec_fastnan;
|
||||
extern int box86_dynarec_fastround;
|
||||
extern int box86_dynarec_hotpage;
|
||||
extern int box86_dynarec_wait;
|
||||
extern int box86_dynarec_fastpage;
|
||||
extern int box86_dynarec_bleeding_edge;
|
||||
extern int box86_dynarec_test;
|
||||
extern int box86_dynarec_jvm;
|
||||
#ifdef ARM
|
||||
extern int arm_vfp; // vfp version (3 or 4), with 32 registers is mendatory
|
||||
extern int arm_swap;
|
||||
extern int arm_div;
|
||||
#endif
|
||||
#endif
|
||||
extern int box86_libcef;
|
||||
extern int dlsym_error; // log dlsym error
|
||||
extern int cycle_log; // if using rolling logs
|
||||
extern int trace_xmm; // include XMM reg in trace?
|
||||
extern int trace_emm; // include EMM reg in trace?
|
||||
extern int box86_nosandbox;
|
||||
extern int box86_malloc_hack;
|
||||
extern int box86_sse_flushto0;
|
||||
extern int box86_x87_no80bits;
|
||||
extern int allow_missing_libs;
|
||||
@@ -43,6 +49,7 @@ extern int box86_prefer_wrapped;
|
||||
extern int box86_prefer_emulated;
|
||||
extern int box86_steam;
|
||||
extern int box86_wine;
|
||||
extern int box86_musl;
|
||||
extern int box86_nopulse; // disabling the use of wrapped pulseaudio
|
||||
extern int box86_nogtk; // disabling the use of wrapped gtk
|
||||
extern int box86_novulkan; // disabling the use of wrapped vulkan
|
||||
@@ -58,6 +65,7 @@ extern uintptr_t fmod_smc_start, fmod_smc_end; // to handle libfmod (from Unreal
|
||||
extern uint32_t default_fs;
|
||||
extern int jit_gdb; // launch gdb when a segfault is trapped
|
||||
extern int box86_tcmalloc_minimal; // when using tcmalloc_minimal
|
||||
extern int box86_isglibc234; // is the program linked with glibc 2.34+
|
||||
extern int box86_x11threads;
|
||||
extern int box86_x11glx;
|
||||
extern char* box86_libGL;
|
||||
@@ -92,7 +100,7 @@ void init_malloc_hook();
|
||||
#define box_free free
|
||||
#define box_memalign memalign
|
||||
#else
|
||||
extern size_t(*box_malloc_usable_size)(void*);
|
||||
extern size_t(*box_malloc_usable_size)(const void*);
|
||||
extern void* __libc_malloc(size_t);
|
||||
extern void* __libc_realloc(void*, size_t);
|
||||
extern void* __libc_calloc(size_t, size_t);
|
||||
|
||||
+7
-16
@@ -3,31 +3,22 @@
|
||||
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
typedef struct dynablocklist_s dynablocklist_t;
|
||||
typedef struct kh_dynablocks_s kh_dynablocks_t;
|
||||
|
||||
uint32_t X31_hash_code(void* addr, int len);
|
||||
dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct);
|
||||
void FreeDynablockList(dynablocklist_t** dynablocks);
|
||||
void FreeDynablock(dynablock_t* db, int need_lock);
|
||||
void MarkDynablock(dynablock_t* db);
|
||||
void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
|
||||
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
|
||||
void MarkRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size);
|
||||
int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size);
|
||||
void FreeInvalidDynablock(dynablock_t* db, int need_lock);
|
||||
dynablock_t* InvalidDynablock(dynablock_t* db, int need_lock);
|
||||
|
||||
dynablock_t* FindDynablockFromNativeAddress(void* addr); // defined in box86context.h
|
||||
dynablock_t* FindDynablockDynablocklist(void* addr, kh_dynablocks_t* dynablocks);
|
||||
dynablock_t* FindDynablockFromNativeAddress(void* addr); // defined in box64context.h
|
||||
|
||||
uintptr_t StartDynablockList(dynablocklist_t* db);
|
||||
uintptr_t EndDynablockList(dynablocklist_t* db);
|
||||
void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
|
||||
|
||||
// Handling of Dynarec block (i.e. an exectable chunk of x86 translated code)
|
||||
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t** current); // return NULL if block is not found / cannot be created. Don't create if create==0
|
||||
// Handling of Dynarec block (i.e. an exectable chunk of x64 translated code)
|
||||
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create); // return NULL if block is not found / cannot be created. Don't create if create==0
|
||||
dynablock_t* DBAlternateBlock(x86emu_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();
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
typedef struct instsize_s instsize_t;
|
||||
|
||||
void addInst(instsize_t* insts, size_t* size, int x86_size, int arm_size);
|
||||
|
||||
void CancelBlock();
|
||||
void* FillBlock(dynablock_t* block, uintptr_t addr);
|
||||
|
||||
+24
-18
@@ -9,67 +9,73 @@ typedef struct kh_mapsymbols_s kh_mapsymbols_t;
|
||||
typedef struct box86context_s box86context_t;
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
typedef struct needed_libs_s needed_libs_t;
|
||||
typedef struct kh_defaultversion_s kh_defaultversion_t;
|
||||
#ifdef DYNAREC
|
||||
typedef struct dynablocklist_s dynablocklist_t;
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
#endif
|
||||
|
||||
elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec); // exec : 0 = lib, 1 = exec
|
||||
void FreeElfHeader(elfheader_t** head);
|
||||
const char* ElfName(elfheader_t* head);
|
||||
const char* ElfPath(elfheader_t* head);
|
||||
void ElfAttachLib(elfheader_t* head, library_t* lib);
|
||||
|
||||
// return 0 if OK
|
||||
int CalcLoadAddr(elfheader_t* head);
|
||||
int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin);
|
||||
void FreeElfMemory(elfheader_t* head);
|
||||
int LoadElfMemory(FILE* f, box86context_t* context, elfheader_t* head);
|
||||
int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded);
|
||||
int ReloadElfMemory(FILE* f, box86context_t* context, elfheader_t* head);
|
||||
int RelocateElf(lib_t* maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
|
||||
int RelocateElfPlt(lib_t* maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
|
||||
void CalcStack(elfheader_t* h, uint32_t* stacksz, uint32_t* stackalign);
|
||||
int RelocateElf(lib_t *maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
|
||||
int RelocateElfPlt(lib_t *maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
|
||||
void CalcStack(elfheader_t* h, uint32_t* stacksz, size_t* stackalign);
|
||||
uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h);
|
||||
uintptr_t GetLastByte(elfheader_t* h);
|
||||
void AddSymbols(lib_t* maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h);
|
||||
int LoadNeededLibs(elfheader_t* h, lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, box86context_t* box86, x86emu_t* emu);
|
||||
void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h);
|
||||
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, box86context_t *box86, x86emu_t* emu);
|
||||
uintptr_t GetElfInit(elfheader_t* h);
|
||||
uintptr_t GetElfFini(elfheader_t* h);
|
||||
void RefreshElfTLS(elfheader_t* h);
|
||||
void RunElfInit(elfheader_t* h, x86emu_t* emu);
|
||||
void RunElfFini(elfheader_t* h, x86emu_t* emu);
|
||||
void RunDeferedElfInit(x86emu_t* emu);
|
||||
void RunElfInit(elfheader_t* h, x86emu_t *emu);
|
||||
void RunElfFini(elfheader_t* h, x86emu_t *emu);
|
||||
void RunDeferredElfInit(x86emu_t *emu);
|
||||
void MarkElfInitDone(elfheader_t* h);
|
||||
void* GetBaseAddress(elfheader_t* h);
|
||||
void* GetElfDelta(elfheader_t* h);
|
||||
uint32_t GetBaseSize(elfheader_t* h);
|
||||
int IsAddressInElfSpace(elfheader_t* h, uintptr_t addr);
|
||||
elfheader_t* FindElfAddress(box86context_t* context, uintptr_t addr);
|
||||
int IsAddressInElfSpace(const elfheader_t* h, uintptr_t addr);
|
||||
elfheader_t* FindElfAddress(box86context_t *context, uintptr_t addr);
|
||||
const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uint32_t* sz);
|
||||
int32_t GetTLSBase(elfheader_t* h);
|
||||
uint32_t GetTLSSize(elfheader_t* h);
|
||||
void* GetTLSPointer(box86context_t* context, elfheader_t* h);
|
||||
void* GetDTatOffset(box86context_t* context, int index, int offset);
|
||||
#ifdef DYNAREC
|
||||
dynablocklist_t* GetDynablocksFromAddress(box86context_t* context, uintptr_t addr);
|
||||
dynablocklist_t* GetDynablocksFromElf(elfheader_t* h);
|
||||
dynablock_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t addr);
|
||||
#endif
|
||||
void ResetSpecialCaseMainElf(elfheader_t* h);
|
||||
void CreateMemorymapFile(box86context_t* context, int fd);
|
||||
void* GetDynamicSection(elfheader_t* h);
|
||||
void* ElfGetBrk(elfheader_t* h);
|
||||
void* ElfSetBrk(void* newbrk);
|
||||
|
||||
int ElfCheckIfUseTCMallocMinimal(elfheader_t* h); // return 1 if tcmalloc is used
|
||||
|
||||
const char* GetSymbolVersion(elfheader_t* h, int version);
|
||||
const char* GetParentSymbolVersion(elfheader_t* h, int index);
|
||||
const char* VersionnedName(const char* name, int ver, const char* vername);
|
||||
int SameVersionnedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2);
|
||||
const char* VersionedName(const char* name, int ver, const char* vername);
|
||||
int SameVersionedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2);
|
||||
int GetVersionIndice(elfheader_t* h, const char* vername);
|
||||
int GetNeededVersionCnt(elfheader_t* h, const char* libname);
|
||||
const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx);
|
||||
|
||||
kh_mapsymbols_t* GetMapSymbols(elfheader_t* h);
|
||||
kh_mapsymbols_t* GetWeakSymbols(elfheader_t* h);
|
||||
kh_mapsymbols_t* GetLocalSymbols(elfheader_t* h);
|
||||
kh_defaultversion_t* GetGlobalDefaultVersion(elfheader_t* h);
|
||||
kh_defaultversion_t* GetWeakDefaultVersion(elfheader_t* h);
|
||||
|
||||
void* GetNativeSymbolUnversionned(void* lib, const char* name);
|
||||
void* GetNativeSymbolUnversioned(void* lib, const char* name);
|
||||
|
||||
void AddMainElfToLinkmap(elfheader_t* lib);
|
||||
|
||||
#endif //__ELF_LOADER_H_
|
||||
@@ -10,8 +10,10 @@ void** my_GetGthreadsGotInitialized(); // defined in wrappedgthread2
|
||||
|
||||
// NCurse / TInfo
|
||||
void my_checkGlobalTInfo();
|
||||
void my_updateGlobalTInfo(void);
|
||||
|
||||
// getopt
|
||||
void my_checkGlobalOpt();
|
||||
void my_updateGlobalOpt(void);
|
||||
|
||||
#endif //_GLOBAL_SYMBOLS_H_
|
||||
+15
-8
@@ -10,28 +10,35 @@ typedef struct dlprivate_s dlprivate_t;
|
||||
typedef struct box86context_s box86context_t;
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
typedef struct elfheader_s elfheader_t;
|
||||
typedef struct box86context_s box86context_t;
|
||||
typedef struct needed_libs_s needed_libs_t;
|
||||
typedef struct kh_mapoffsets_s kh_mapoffsets_t;
|
||||
typedef char* cstr_t;
|
||||
|
||||
lib_t *NewLibrarian(box86context_t* context, int ownlibs);
|
||||
void FreeLibrarian(lib_t **maplib, x86emu_t* emu);
|
||||
dlprivate_t *NewDLPrivate();
|
||||
dlprivate_t *NewDLPrivate(void);
|
||||
void FreeDLPrivate(dlprivate_t **lib);
|
||||
|
||||
box86context_t* GetLibrarianContext(lib_t* maplib);
|
||||
kh_mapsymbols_t* GetGlobalData(lib_t* maplib);
|
||||
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, const char** paths, int npath, box86context_t* box86, x86emu_t* emu); // 0=success, 1=error
|
||||
int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, elfheader_t* verneeded, box86context_t* box86, x86emu_t* emu); // 0=success, 1=error
|
||||
void RemoveNeededLib(lib_t* maplib, int local, needed_libs_t* needed, box86context_t* box86, x86emu_t* emu);
|
||||
library_t* GetLibMapLib(lib_t* maplib, const char* name);
|
||||
library_t* GetLibInternal(const char* name);
|
||||
void promoteLocalLibGlobal(library_t* lib);
|
||||
int isLibLocal(library_t* lib);
|
||||
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername);
|
||||
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername);
|
||||
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername);
|
||||
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername);
|
||||
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername);
|
||||
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername, const char* globdefver, const char* weakdefver);
|
||||
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver);
|
||||
int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver);
|
||||
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, const char* defver);
|
||||
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver);
|
||||
elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername);
|
||||
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername);
|
||||
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername, const char* defver);
|
||||
|
||||
void MapLibRemoveLib(lib_t* maplib, library_t* lib);
|
||||
|
||||
const char* GetMaplibDefaultVersion(lib_t *maplib, lib_t *local_maplib, int isweak, const char* symname);
|
||||
|
||||
const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, const char** libname, void** base, library_t** lib);
|
||||
|
||||
|
||||
+11
-10
@@ -15,25 +15,26 @@ typedef struct elfheader_s elfheader_t;
|
||||
#define LIB_EMULATED 1
|
||||
#define LIB_UNNKNOW -1
|
||||
|
||||
library_t *NewLibrary(const char* path, box86context_t* box86);
|
||||
library_t *NewLibrary(const char* path, box86context_t* box86, elfheader_t* verneeded);
|
||||
int AddSymbolsLibrary(lib_t* maplib, library_t* lib, x86emu_t* emu);
|
||||
int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x86emu_t* emu);
|
||||
int ReloadLibrary(library_t* lib, x86emu_t* emu);
|
||||
void InactiveLibrary(library_t* lib);
|
||||
void Free1Library(library_t **lib, x86emu_t* emu);
|
||||
|
||||
char* GetNameLib(library_t *lib);
|
||||
int IsSameLib(library_t* lib, const char* path); // check if lib is same (path -> name)
|
||||
int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int *weak, int version, const char* vername, int local);
|
||||
int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local);
|
||||
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local);
|
||||
needed_libs_t* GetNeededLibs(library_t* lib);
|
||||
int GetNeededLibN(library_t* lib);
|
||||
int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver);
|
||||
int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver);
|
||||
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver);
|
||||
char** GetNeededLibsNames(library_t* lib);
|
||||
int GetNeededLibsN(library_t* lib);
|
||||
library_t* GetNeededLib(library_t* lib, int idx);
|
||||
lib_t* GetMaplib(library_t* lib);
|
||||
|
||||
int GetElfIndex(library_t* lib); // -1 if no elf (i.e. wrapped)
|
||||
elfheader_t* GetElf(library_t* lib); // NULL if no elf (i.e. wrapped)
|
||||
void* GetHandle(library_t* lib); // NULL if not wrapped
|
||||
void IncRefCount(library_t* lib, x86emu_t* emu);
|
||||
int DecRefCount(library_t** lib, x86emu_t* emu); // might unload the lib!
|
||||
int GetRefCount(library_t* lib);
|
||||
|
||||
#endif //__LIBRARY_H_
|
||||
void SetDlOpenIdx(library_t* lib, int dlopen);
|
||||
#endif //__LIBRARY_H_
|
||||
+1
-1
@@ -7,7 +7,7 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
_CS, _DS, _SS, _ES, _FS, _GS
|
||||
_ES, _CS, _SS, _DS, _FS, _GS
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -9,12 +9,14 @@ typedef struct versymbols_s versymbols_t;
|
||||
|
||||
KHASH_MAP_DECLARE_STR(mapsymbols, versymbols_t)
|
||||
|
||||
kh_mapsymbols_t* NewMapSymbols();
|
||||
kh_mapsymbols_t* NewMapSymbols(void);
|
||||
void FreeMapSymbols(kh_mapsymbols_t** map);
|
||||
|
||||
// replace if already there
|
||||
void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername);
|
||||
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local, const char* defver);
|
||||
// Update addr and sz of existing symbols
|
||||
void ForceUpdateSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz);
|
||||
// don't add if already there
|
||||
void AddUniqueSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername);
|
||||
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local, const char* defver);
|
||||
@@ -23,7 +25,7 @@ const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* offs,
|
||||
|
||||
// default version handling
|
||||
KHASH_MAP_DECLARE_STR(defaultversion, const char*)
|
||||
kh_defaultversion_t* NewDefaultVersion();
|
||||
kh_defaultversion_t* NewDefaultVersion(void);
|
||||
void FreeDefaultVersion(kh_defaultversion_t** def);
|
||||
|
||||
void AddDefaultVersion(kh_defaultversion_t* def, const char* symname, const char* vername);
|
||||
|
||||
@@ -7,7 +7,7 @@ typedef struct box86context_s box86context_t;
|
||||
|
||||
typedef int (*wrappedlib_init_t)(library_t * lib, box86context_t* box86); // 0 = success
|
||||
typedef void (*wrappedlib_fini_t)(library_t * lib);
|
||||
typedef int (*wrappedlib_get_t)(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz, size_t size, int* weak, int version, const char* vername, int local);
|
||||
typedef int (*wrappedlib_get_t)(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t size, int* weak, int version, const char* vername, int local, const char* defver);
|
||||
|
||||
void setNeededLibs(library_t* lib, int n, ...);
|
||||
#define SETALT(A) lib->w.altmy = box_strdup(#A)
|
||||
@@ -19,4 +19,4 @@ typedef struct wrappedlib_s {
|
||||
wrappedlib_fini_t fini;
|
||||
} wrappedlib_t;
|
||||
|
||||
#endif //__WRAPPEDLIBS_H__
|
||||
#endif //__WRAPPEDLIBS_H__
|
||||
@@ -35,8 +35,6 @@ void ResetSegmentsCache(x86emu_t *emu);
|
||||
const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip);
|
||||
|
||||
void StopEmu(x86emu_t* emu, const char* reason);
|
||||
void PushExit(x86emu_t* emu);
|
||||
void* GetExit();
|
||||
void EmuCall(x86emu_t* emu, uintptr_t addr);
|
||||
void AddCleanup(x86emu_t *emu, void *p);
|
||||
void AddCleanup1Arg(x86emu_t *emu, void *p, void* a);
|
||||
|
||||
@@ -16,10 +16,24 @@
|
||||
|
||||
// workaround for Globals symbols
|
||||
|
||||
#define GLOB(A) \
|
||||
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL)) { \
|
||||
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p <= %p\n", (void*)globoffs, &A); \
|
||||
memcpy((void*)globoffs, &A, sizeof(A)); \
|
||||
#define GLOB(A, B) \
|
||||
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, NULL)) { \
|
||||
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p <- %p\n", (void*)globoffs, &A); \
|
||||
memcpy((void*)globoffs, &A, sizeof(A)); \
|
||||
} \
|
||||
if (B && GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, B)) { \
|
||||
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p <- %p\n", (void*)globoffs, &A); \
|
||||
memcpy((void*)globoffs, &A, sizeof(A)); \
|
||||
}
|
||||
|
||||
#define TOGLOB(A, B) \
|
||||
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, NULL)) { \
|
||||
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p -> %p\n", (void*)globoffs, &A); \
|
||||
memcpy(&A, (void*)globoffs, sizeof(A)); \
|
||||
} \
|
||||
if (B && GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, B)) { \
|
||||
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p -> %p\n", (void*)globoffs, &A); \
|
||||
memcpy(&A, (void*)globoffs, sizeof(A)); \
|
||||
}
|
||||
|
||||
|
||||
@@ -29,14 +43,14 @@ EXPORT void* gdk_display = NULL; // in case it's used...
|
||||
void my_checkGlobalGdkDisplay()
|
||||
{
|
||||
uintptr_t globoffs, globend;
|
||||
GLOB(gdk_display)
|
||||
GLOB(gdk_display, NULL)
|
||||
}
|
||||
|
||||
void my_setGlobalGThreadsInit()
|
||||
{
|
||||
int val = 1;
|
||||
uintptr_t globoffs, globend;
|
||||
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, "g_threads_got_initialized", &globoffs, &globend, -1, NULL)) {
|
||||
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, "g_threads_got_initialized", &globoffs, &globend, -1, NULL, NULL)) {
|
||||
printf_log(LOG_DEBUG, "Global g_threads_got_initialized workaround, @%p <= %p\n", (void*)globoffs, (void*)val);
|
||||
memcpy((void*)globoffs, &val, sizeof(val));
|
||||
}
|
||||
@@ -74,29 +88,55 @@ EXPORT void* ttytype;
|
||||
void my_checkGlobalTInfo()
|
||||
{
|
||||
uintptr_t globoffs, globend;
|
||||
GLOB(COLS)
|
||||
GLOB(LINES)
|
||||
GLOB(TABSIZE)
|
||||
GLOB(curscr)
|
||||
GLOB(newscr)
|
||||
GLOB(stdscr)
|
||||
GLOB(acs_map)
|
||||
GLOB(UP)
|
||||
GLOB(BC)
|
||||
GLOB(PC)
|
||||
GLOB(ospeed)
|
||||
GLOB(ttytype)
|
||||
GLOB(COLS, NULL)
|
||||
GLOB(LINES, NULL)
|
||||
GLOB(TABSIZE, NULL)
|
||||
GLOB(curscr, NULL)
|
||||
GLOB(newscr, NULL)
|
||||
GLOB(stdscr, NULL)
|
||||
GLOB(acs_map, NULL)
|
||||
GLOB(UP, NULL)
|
||||
GLOB(BC, NULL)
|
||||
GLOB(PC, NULL)
|
||||
GLOB(ospeed, NULL)
|
||||
GLOB(ttytype, NULL)
|
||||
}
|
||||
|
||||
void my_updateGlobalTInfo()
|
||||
{
|
||||
uintptr_t globoffs, globend;
|
||||
TOGLOB(COLS, NULL)
|
||||
TOGLOB(LINES, NULL)
|
||||
TOGLOB(TABSIZE, NULL)
|
||||
TOGLOB(curscr, NULL)
|
||||
TOGLOB(newscr, NULL)
|
||||
TOGLOB(stdscr, NULL)
|
||||
TOGLOB(acs_map, NULL)
|
||||
TOGLOB(UP, NULL)
|
||||
TOGLOB(BC, NULL)
|
||||
TOGLOB(PC, NULL)
|
||||
TOGLOB(ospeed, NULL)
|
||||
TOGLOB(ttytype, NULL)
|
||||
}
|
||||
|
||||
// **************** getopts ****************
|
||||
EXPORT char *optarg;
|
||||
EXPORT int optind, opterr, optopt;
|
||||
|
||||
void my_updateGlobalOpt()
|
||||
{
|
||||
uintptr_t globoffs, globend;
|
||||
TOGLOB(optarg, "GLIBC_2.2.5");
|
||||
TOGLOB(optind, "GLIBC_2.2.5");
|
||||
TOGLOB(opterr, "GLIBC_2.2.5");
|
||||
TOGLOB(optopt, "GLIBC_2.2.5");
|
||||
}
|
||||
|
||||
void my_checkGlobalOpt()
|
||||
{
|
||||
uintptr_t globoffs, globend;
|
||||
GLOB(optarg);
|
||||
GLOB(optind);
|
||||
GLOB(opterr);
|
||||
GLOB(optopt);
|
||||
GLOB(optarg, "GLIBC_2.2.5");
|
||||
GLOB(optind, "GLIBC_2.2.5");
|
||||
GLOB(opterr, "GLIBC_2.2.5");
|
||||
GLOB(optopt, "GLIBC_2.2.5");
|
||||
}
|
||||
+277
-161
@@ -12,7 +12,6 @@
|
||||
#include "x86emu.h"
|
||||
#include "box86context.h"
|
||||
#include "elfloader.h"
|
||||
#include "symbols.h"
|
||||
|
||||
#include "bridge.h"
|
||||
|
||||
@@ -20,7 +19,6 @@ KHASH_MAP_IMPL_INT(mapoffsets, cstr_t);
|
||||
|
||||
lib_t *NewLibrarian(box86context_t* context, int ownlibs)
|
||||
{
|
||||
(void)context;
|
||||
lib_t *maplib = (lib_t*)box_calloc(1, sizeof(lib_t));
|
||||
|
||||
maplib->mapoffsets = kh_init(mapoffsets);
|
||||
@@ -31,39 +29,7 @@ lib_t *NewLibrarian(box86context_t* context, int ownlibs)
|
||||
|
||||
return maplib;
|
||||
}
|
||||
static void freeLibraryRecurse(lib_t *maplib, x86emu_t *emu, int idx, char *freed, library_t* owner) {
|
||||
if (freed[idx]) return; // Already freed
|
||||
|
||||
library_t *lib = maplib->libraries[idx];
|
||||
if(lib==owner) return; // don't free owner of maplib
|
||||
freed[idx] = 1; // Avoid infinite loops
|
||||
printf_log(LOG_DEBUG, "Unloading %s\n", lib->name);
|
||||
for (int i = lib->dependedby.size - 1; i >= 0; --i) {
|
||||
int j;
|
||||
for (j = 0; j < maplib->libsz; ++j) {
|
||||
if (lib->dependedby.libs[i] == maplib->libraries[j]) break;
|
||||
}
|
||||
if (j == maplib->libsz) {
|
||||
// dependant lib already freed
|
||||
// library as been freed already
|
||||
continue;
|
||||
}
|
||||
if (freed[j] == 1) {
|
||||
printf_log(LOG_DEBUG, "Cyclic dependancy detected (cycle is between %s and %s)\n", lib->name, lib->dependedby.libs[i]->name);
|
||||
continue;
|
||||
}
|
||||
freeLibraryRecurse(maplib, emu, j, freed, owner);
|
||||
if (freed[idx] != 1) {
|
||||
printf_log(LOG_DEBUG, "Note: library already freed (cyclic dependancy break)\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
library_t *ptr = maplib->libraries[idx];
|
||||
if(maplib->ownlibs/* && (!maplib->owner || ptr->maplib==maplib)*/)
|
||||
Free1Library(&ptr, emu);
|
||||
freed[idx] = 2;
|
||||
}
|
||||
|
||||
void FreeLibrarian(lib_t **maplib, x86emu_t *emu)
|
||||
{
|
||||
// should that be in reverse order?
|
||||
@@ -72,26 +38,13 @@ void FreeLibrarian(lib_t **maplib, x86emu_t *emu)
|
||||
|
||||
library_t* owner = (*maplib)->owner;
|
||||
(*maplib)->owner = NULL; // to avoid recursive free...
|
||||
|
||||
if((*maplib)->ownlibs && (*maplib)->libsz) {
|
||||
printf_log(LOG_DEBUG, "Closing %d libs from maplib %p\n", (*maplib)->libsz, *maplib);
|
||||
char *freed = (char*)box_calloc((*maplib)->libsz, sizeof(char));
|
||||
if (!freed) {
|
||||
printf_log(LOG_INFO, "Failed to malloc freed table, using old algorithm (a crash is likely)\n");
|
||||
for (int i=(*maplib)->libsz-1; i>=0; --i)
|
||||
if((*maplib)->libraries[i]!=owner) {
|
||||
printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
|
||||
Free1Library(&(*maplib)->libraries[i], emu);
|
||||
}
|
||||
} else {
|
||||
for (int i=(*maplib)->libsz-1; i>=0; --i) {
|
||||
freeLibraryRecurse(*maplib, emu, i, freed, owner);
|
||||
}
|
||||
memset((*maplib)->libraries, 0, (*maplib)->libsz*sizeof(library_t*)); // NULL = 0 anyway
|
||||
(*maplib)->libsz = 0;
|
||||
box_free(freed);
|
||||
|
||||
/*if((*maplib)->ownlibs && (*maplib)->libsz) {
|
||||
for(int i=0; i<(*maplib)->libsz; ++i) {
|
||||
printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
|
||||
DecRefCount(&(*maplib)->libraries[i], emu);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
box_free((*maplib)->libraries);
|
||||
(*maplib)->libraries = NULL;
|
||||
|
||||
@@ -111,7 +64,6 @@ void FreeLibrarian(lib_t **maplib, x86emu_t *emu)
|
||||
|
||||
box86context_t* GetLibrarianContext(lib_t* maplib)
|
||||
{
|
||||
(void)maplib;
|
||||
return my_context;
|
||||
}
|
||||
|
||||
@@ -153,8 +105,6 @@ void MapLibAddLib(lib_t* maplib, library_t* lib)
|
||||
++maplib->libsz;
|
||||
}
|
||||
|
||||
static void MapLibRemoveLib(lib_t* maplib, library_t* lib);
|
||||
|
||||
static void MapLibAddMapLib(lib_t* dest, library_t* lib_src, lib_t* src)
|
||||
{
|
||||
if(!src)
|
||||
@@ -175,7 +125,7 @@ static void MapLibAddMapLib(lib_t* dest, library_t* lib_src, lib_t* src)
|
||||
FreeLibrarian(&src, NULL);
|
||||
}
|
||||
|
||||
static void MapLibRemoveLib(lib_t* maplib, library_t* lib)
|
||||
void MapLibRemoveLib(lib_t* maplib, library_t* lib)
|
||||
{
|
||||
if(!maplib || !lib)
|
||||
return;
|
||||
@@ -206,14 +156,36 @@ static void MapLibRemoveMapLib(lib_t* dest, lib_t* src)
|
||||
}
|
||||
}
|
||||
|
||||
int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, const char* path, box86context_t* box86, x86emu_t* emu)
|
||||
void promoteLocalLibGlobal(library_t* lib)
|
||||
{
|
||||
if(!lib || !my_context)
|
||||
return;
|
||||
// promote lib from local to global...
|
||||
// for add the depending local libs...
|
||||
if(lib->maplib) {
|
||||
MapLibAddMapLib(my_context->maplib, lib, lib->maplib);
|
||||
}
|
||||
if(!libraryInMapLib(my_context->maplib, lib))
|
||||
MapLibAddLib(my_context->maplib, lib);
|
||||
MapLibRemoveMapLib(my_context->local_maplib, my_context->maplib);
|
||||
}
|
||||
|
||||
int isLibLocal(library_t* lib)
|
||||
{
|
||||
if(!lib || !my_context)
|
||||
return 0;
|
||||
return libraryInMapLib(my_context->local_maplib, lib);
|
||||
}
|
||||
|
||||
static int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int n, elfheader_t* verneeded, box86context_t* box86, x86emu_t* emu)
|
||||
{
|
||||
const char* path = needed->names[n];
|
||||
printf_log(LOG_DEBUG, "Trying to add \"%s\" to maplib%s\n", path, local?" (local)":"");
|
||||
// first check if lib is already loaded
|
||||
library_t *lib = getLib(my_context->maplib, path);
|
||||
if(lib) {
|
||||
add_neededlib(neededlibs, lib);
|
||||
if (lib && deplib) add_dependedbylib(&lib->dependedby, deplib);
|
||||
IncRefCount(lib, emu); // increment cntref
|
||||
needed->libs[n] = lib;
|
||||
printf_log(LOG_DEBUG, "Already present in maplib => success\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -221,6 +193,8 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib
|
||||
lib = getLib(my_context->local_maplib, path);
|
||||
if(lib) {
|
||||
printf_log(LOG_DEBUG, "Already present in local_maplib => success\n");
|
||||
needed->libs[n] = lib;
|
||||
IncRefCount(lib, emu); // increment cntref
|
||||
if(local) {
|
||||
// add lib to maplib...
|
||||
if(maplib) {
|
||||
@@ -234,28 +208,17 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib
|
||||
}
|
||||
} else {
|
||||
// promote lib from local to global...
|
||||
// for add the depending local libs...
|
||||
if(lib->maplib) {
|
||||
MapLibAddMapLib(my_context->maplib, lib, lib->maplib);
|
||||
}
|
||||
if(!libraryInMapLib(my_context->maplib, lib))
|
||||
MapLibAddLib(my_context->maplib, lib);
|
||||
MapLibRemoveMapLib(my_context->local_maplib, my_context->maplib);
|
||||
promoteLocalLibGlobal(lib);
|
||||
}
|
||||
add_neededlib(neededlibs, lib);
|
||||
if (lib && deplib) add_dependedbylib(&lib->dependedby, deplib);
|
||||
return 0;
|
||||
}
|
||||
// load a new one
|
||||
lib = NewLibrary(path, box86);
|
||||
needed->libs[n] = lib = NewLibrary(path, box86, verneeded);
|
||||
if(!lib) {
|
||||
printf_log(LOG_DEBUG, "Faillure to create lib => fail\n");
|
||||
return 1; //Error
|
||||
}
|
||||
|
||||
add_neededlib(neededlibs, lib);
|
||||
if (lib && deplib) add_dependedbylib(&lib->dependedby, deplib);
|
||||
|
||||
// add lib now
|
||||
if(local) {
|
||||
MapLibAddLib(my_context->local_maplib, lib);
|
||||
@@ -287,38 +250,49 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib
|
||||
printf_log(LOG_DEBUG, "Failure to add lib linkmap\n");
|
||||
return 1;
|
||||
}
|
||||
lm->l_addr = (Elf32_Addr)GetElfDelta(my_context->elfs[lib->e.elf_index]);
|
||||
lm->l_addr = (Elf32_Addr)GetElfDelta(lib->e.elf);
|
||||
lm->l_name = lib->name;
|
||||
lm->l_ld = GetDynamicSection(my_context->elfs[lib->e.elf_index]);
|
||||
lm->l_ld = GetDynamicSection(lib->e.elf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, library_t* lib, box86context_t* box86, x86emu_t* emu)
|
||||
int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, elfheader_t* verneeded, box86context_t* box86, x86emu_t* emu)
|
||||
{
|
||||
(void)neededlibs; (void)deplib;
|
||||
if(!lib) // no lib, error is already detected, no need to return a new one
|
||||
return 0;
|
||||
if(!maplib)
|
||||
maplib = (local)?lib->maplib:my_context->maplib;
|
||||
|
||||
int mainelf = GetElfIndex(lib);
|
||||
elfheader_t* mainelf = GetElf(lib);
|
||||
|
||||
if(mainelf==-1) {
|
||||
if(!mainelf) {
|
||||
// It's a native libs, nothing else to do
|
||||
} else {
|
||||
// it's an emulated lib,
|
||||
// load dependancies and launch init sequence
|
||||
if(LoadNeededLibs(box86->elfs[mainelf], maplib, &lib->needed, lib, 0, bindnow, box86, emu)) {
|
||||
if(LoadNeededLibs(mainelf, maplib, 0, bindnow, box86, emu)) {
|
||||
printf_log(LOG_DEBUG, "Failure to Add dependant lib => fail\n");
|
||||
return 1;
|
||||
}
|
||||
// some special case, where dependancies may not be correct
|
||||
if(!strcmp(GetNameLib(lib), "libCgGL.so")) {
|
||||
const char* libs[] = {"libGL.so.1"};
|
||||
AddNeededLib(maplib, &lib->needed, lib, 0, 0, libs, 1, box86, emu);
|
||||
char* names[] = {"libGL.so.1"}; // TODO: it will never be uninit...
|
||||
library_t* libs[] = { NULL };
|
||||
needed_libs_t tmp = {0};
|
||||
tmp.size = tmp.cap = 1;
|
||||
tmp.names = names;
|
||||
tmp.libs = libs;
|
||||
AddNeededLib(maplib, 0, 0, &tmp, verneeded, box86, emu);
|
||||
}
|
||||
if(!strcmp(GetNameLib(lib), "libmss.so.6")) {
|
||||
const char* libs[] = {"libSDL-1.2.so.0", "libdl.so.2"};
|
||||
AddNeededLib(maplib, &lib->needed, lib, 0, 0, libs, 2, box86, emu);
|
||||
char* names[] = {"libSDL-1.2.so.0", "libdl.so.2"}; // TODO: they will never be uninit...
|
||||
library_t* libs[] = { NULL, NULL };
|
||||
needed_libs_t tmp = {0};
|
||||
tmp.size = tmp.cap = 2;
|
||||
tmp.names = names;
|
||||
tmp.libs = libs;
|
||||
AddNeededLib(maplib, 0, 0, &tmp, verneeded, box86, emu);
|
||||
}
|
||||
|
||||
// finalize the lib
|
||||
@@ -332,30 +306,54 @@ int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* depli
|
||||
|
||||
return 0;
|
||||
}
|
||||
void AddNeededLib_remove(lib_t* maplib, int local, library_t** lib, box86context_t* box86, x86emu_t* emu)
|
||||
{
|
||||
|
||||
if(!lib || !*lib) // no lib, error is already detected, no need to return a new one
|
||||
return;
|
||||
if(!maplib)
|
||||
maplib = (local)?(*lib)->maplib:my_context->maplib;
|
||||
|
||||
DecRefCount(lib, emu);
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, const char** paths, int npath, box86context_t* box86, x86emu_t* emu)
|
||||
int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, elfheader_t* verneeded, box86context_t* box86, x86emu_t* emu)
|
||||
{
|
||||
if(!needed) // no needed libs, no problems
|
||||
return 0;
|
||||
box86_mapclean = 0;
|
||||
if(!neededlibs) {
|
||||
neededlibs = box_calloc(1, sizeof(needed_libs_t));
|
||||
}
|
||||
int idx = neededlibs->size;
|
||||
int ret = 0;
|
||||
// Add libs and symbol
|
||||
for(int i=0; i<npath; ++i) {
|
||||
if(AddNeededLib_add(maplib, neededlibs, deplib, local, paths[i], box86, emu)) {
|
||||
printf_log(strchr(paths[i],'/')?LOG_DEBUG:LOG_INFO, "Error loading needed lib %s\n", paths[i]);
|
||||
return 1;
|
||||
for(int i=0; i<needed->size; ++i) {
|
||||
if(AddNeededLib_add(maplib, local, needed, i, verneeded, box86, emu)) {
|
||||
printf_log(strchr(needed->names[i],'/')?LOG_DEBUG:LOG_INFO, "Error loading needed lib %s\n", needed->names[i]);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
int idx_end = neededlibs->size;
|
||||
// error while loadind lib, unload...
|
||||
if(ret) {
|
||||
return ret;
|
||||
}
|
||||
// add dependant libs and init them
|
||||
for (int i=idx; i<idx_end; ++i)
|
||||
if(AddNeededLib_init(maplib, neededlibs, deplib, local, bindnow, neededlibs->libs[i], box86, emu)) {
|
||||
printf_log(LOG_INFO, "Error initializing needed lib %s\n", neededlibs->libs[i]->name);
|
||||
if(!allow_missing_libs) return 1;
|
||||
for (int i=0; i<needed->size; ++i)
|
||||
if(AddNeededLib_init(maplib, local, bindnow, needed->libs[i], verneeded, box86, emu)) {
|
||||
printf_log(LOG_INFO, "Error initializing needed lib %s\n", needed->names[i]);
|
||||
if(!allow_missing_libs) ret = 1;
|
||||
}
|
||||
return 0;
|
||||
// error while loadind lib, unload...
|
||||
return ret;
|
||||
}
|
||||
EXPORTDYN
|
||||
void RemoveNeededLib(lib_t* maplib, int local, needed_libs_t* needed, box86context_t* box86, x86emu_t* emu)
|
||||
{
|
||||
if(!needed) // no needed libs, no problems
|
||||
return;
|
||||
for(int i=0; i<needed->size; ++i) {
|
||||
if(box86_log>=LOG_DEBUG && needed->libs[i])
|
||||
printf_log(LOG_DEBUG, "Will remove after failed init %s\n", needed->names[i]);
|
||||
AddNeededLib_remove(maplib, local, &needed->libs[i], box86, emu);
|
||||
}
|
||||
}
|
||||
|
||||
library_t* GetLibMapLib(lib_t* maplib, const char* name)
|
||||
@@ -376,7 +374,9 @@ EXPORTDYN
|
||||
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername)
|
||||
{
|
||||
uintptr_t start = 0, end = 0;
|
||||
if(GetGlobalSymbolStartEnd(maplib, name, &start, &end, (void*)1, version, vername))
|
||||
const char *globdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 0, name);
|
||||
const char *weakdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 1, name);
|
||||
if(GetGlobalSymbolStartEnd(maplib, name, &start, &end, (void*)1, version, vername, globdefver, weakdefver))
|
||||
return start;
|
||||
return 0;
|
||||
}
|
||||
@@ -388,7 +388,7 @@ static int isLocal(elfheader_t* self, library_t* l)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername)
|
||||
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername, const char* globdefver, const char* weakdefver)
|
||||
{
|
||||
assert(self); // need self for this one
|
||||
//search for the self, to start "next"
|
||||
@@ -400,39 +400,41 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
|
||||
}
|
||||
if(go<0)
|
||||
go = 0; // not found...
|
||||
if(maplib)
|
||||
for(int i=go; i<maplib->libsz; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 0))
|
||||
if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self))
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 0, globdefver))
|
||||
if(*start)
|
||||
return 1;
|
||||
}
|
||||
if(maplib)
|
||||
for(int i=go; i<maplib->libsz; ++i)
|
||||
if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
|
||||
GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 0);
|
||||
if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self))
|
||||
GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 0, weakdefver);
|
||||
// loop done, weak symbol found
|
||||
if(weak && *start)
|
||||
return 1;
|
||||
// if self defined, give it another chance with self...
|
||||
if(self) {
|
||||
if(my_context->elfs[0]!=self) {
|
||||
const char* defver = GetDefaultVersion(my_context->globaldefver, name);
|
||||
if(GetSizedSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, size, version, vername, 1, defver))
|
||||
if(GetSizedSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, size, version, vername, 1, globdefver))
|
||||
if(*start)
|
||||
return 1;
|
||||
defver = GetDefaultVersion(my_context->weakdefver, name);
|
||||
if(GetSizedSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, size, version, vername, 1, defver))
|
||||
if(GetSizedSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, size, version, vername, 1, weakdefver))
|
||||
if(*start)
|
||||
weak = 1;
|
||||
}
|
||||
if(maplib)
|
||||
for(int i=0; i<go; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1))
|
||||
if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self))
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, globdefver))
|
||||
if(*start)
|
||||
return 1;
|
||||
}
|
||||
if(maplib)
|
||||
for(int i=0; i<go; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
|
||||
GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1);
|
||||
if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self))
|
||||
GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, weakdefver);
|
||||
}
|
||||
if(weak && *start)
|
||||
return 1;
|
||||
@@ -440,39 +442,51 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
|
||||
// nope, not found
|
||||
return 0;
|
||||
}
|
||||
static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername)
|
||||
static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver)
|
||||
{
|
||||
int weak = 0;
|
||||
size_t size = 0;
|
||||
// check with default version...
|
||||
const char* defver = GetDefaultVersion(my_context->globaldefver, name);
|
||||
// search non-weak symbol, from older to newer (first GLOBAL object wins)
|
||||
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, defver))
|
||||
// search in needed libs from preloaded first, in order
|
||||
if(my_context->preload)
|
||||
for(int i=0; i<my_context->preload->size; ++i)
|
||||
if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->preload->libs[i]), globdefver))
|
||||
if(*start)
|
||||
return 1;
|
||||
// search non-weak symbol, from older to newer (first GLOBAL object wins, starting with self)
|
||||
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, globdefver))
|
||||
if(*start)
|
||||
return 1;
|
||||
// TODO: create a temporary map to search lib only 1 time, and in order of needed...
|
||||
// search in needed libs from neededlibs first, in order
|
||||
for(int i=0; i<my_context->neededlibs.size; ++i)
|
||||
if(GetLibGlobalSymbolStartEnd(my_context->neededlibs.libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs.libs[i])))
|
||||
if(*start)
|
||||
return 1;
|
||||
if(my_context->neededlibs)
|
||||
for(int i=0; i<my_context->neededlibs->size; ++i)
|
||||
if(GetLibGlobalSymbolStartEnd(my_context->neededlibs->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs->libs[i]), globdefver))
|
||||
if(*start) {
|
||||
return 1;
|
||||
}
|
||||
// search in global symbols
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i])))
|
||||
if(*start)
|
||||
return 1;
|
||||
if(maplib) {
|
||||
if(self && self!=my_context->elfs[0] && self!=(void*)1)
|
||||
if(GetSymbolStartEnd(GetMapSymbols(self), name, start, end, version, vername, 1, globdefver))
|
||||
if(*start)
|
||||
return 1;
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), globdefver))
|
||||
if(*start) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check with default version...
|
||||
defver = GetDefaultVersion(my_context->weakdefver, name);
|
||||
int ok = 0;
|
||||
// GetSymbolStartEnd should not change start/end if symbol is not found
|
||||
if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, defver))
|
||||
if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, weakdefver))
|
||||
if(*start)
|
||||
ok = 1;
|
||||
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i])))
|
||||
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), weakdefver))
|
||||
if(*start)
|
||||
ok = 1;
|
||||
}
|
||||
@@ -481,15 +495,15 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin
|
||||
}
|
||||
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)
|
||||
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver)
|
||||
{
|
||||
if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end, self, version, vername)) {
|
||||
if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end, self, version, vername, globdefver, weakdefver)) {
|
||||
if(start && end && *end==*start) { // object is of 0 sized, try to see an "_END" object of null size
|
||||
uintptr_t start2, end2;
|
||||
char* buff = (char*)box_malloc(strlen(name) + strlen("_END") + 1);
|
||||
char* buff = (char*)malloc(strlen(name) + strlen("_END") + 1);
|
||||
strcpy(buff, name);
|
||||
strcat(buff, "_END");
|
||||
if(GetGlobalSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, version, vername)) {
|
||||
if(GetGlobalSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, version, vername, globdefver, weakdefver)) {
|
||||
if(end2>*end && start2==end2)
|
||||
*end = end2;
|
||||
}
|
||||
@@ -514,6 +528,106 @@ int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int GetGlobalWeakSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver)
|
||||
{
|
||||
int weak = 0;
|
||||
size_t size = 0;
|
||||
// search in needed libs from preloaded first, in order
|
||||
if(my_context->preload)
|
||||
for(int i=0; i<my_context->preload->size; ++i)
|
||||
if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->preload->libs[i]), globdefver))
|
||||
if(*start)
|
||||
return 1;
|
||||
// search non-weak symbol, from older to newer (first GLOBAL object wins)
|
||||
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, globdefver))
|
||||
if(*start)
|
||||
return 1;
|
||||
// TODO: create a temporary map to search lib only 1 time, and in order of needed...
|
||||
// search in needed libs from neededlibs first, in order
|
||||
if(my_context->neededlibs)
|
||||
for(int i=0; i<my_context->neededlibs->size; ++i)
|
||||
if(GetLibGlobalSymbolStartEnd(my_context->neededlibs->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs->libs[i]), globdefver))
|
||||
if(*start)
|
||||
return 1;
|
||||
// search in global symbols
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), globdefver))
|
||||
if(*start)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// check with default version...
|
||||
int ok = 0;
|
||||
// GetSymbolStartEnd should not change start/end if symbol is not found
|
||||
if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, weakdefver))
|
||||
if(*start)
|
||||
ok = 1;
|
||||
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), weakdefver))
|
||||
if(*start)
|
||||
ok = 1;
|
||||
}
|
||||
// nope, not found
|
||||
return (ok && *start)?1:0;
|
||||
}
|
||||
int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver)
|
||||
{
|
||||
if(GetGlobalWeakSymbolStartEnd_internal(maplib, name, start, end, self, version, vername, globdefver, weakdefver)) {
|
||||
if(start && end && *end==*start) { // object is of 0 sized, try to see an "_END" object of null size
|
||||
uintptr_t start2, end2;
|
||||
char* buff = (char*)malloc(strlen(name) + strlen("_END") + 1);
|
||||
strcpy(buff, name);
|
||||
strcat(buff, "_END");
|
||||
if(GetGlobalWeakSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, version, vername, globdefver, weakdefver)) {
|
||||
if(end2>*end && start2==end2)
|
||||
*end = end2;
|
||||
}
|
||||
box_free(buff);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
// some special case symbol, defined inside box86 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;
|
||||
}
|
||||
// not found...
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* GetMaplibDefaultVersion(lib_t *maplib, lib_t* local_maplib, int isweak, const char* symname)
|
||||
{
|
||||
const char* ret = GetDefaultVersion(isweak?GetWeakDefaultVersion(my_context->elfs[0]):GetGlobalDefaultVersion(my_context->elfs[0]), symname);
|
||||
if(ret)
|
||||
return ret;
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
elfheader_t *h = GetElf(maplib->libraries[i]);
|
||||
if(h)
|
||||
ret = GetDefaultVersion(isweak?GetWeakDefaultVersion(h):GetGlobalDefaultVersion(h), symname);
|
||||
if(ret)
|
||||
return ret;
|
||||
}
|
||||
if(local_maplib)
|
||||
for(int i=0; i<local_maplib->libsz; ++i) {
|
||||
elfheader_t *h = GetElf(local_maplib->libraries[i]);
|
||||
if(h)
|
||||
ret = GetDefaultVersion(isweak?GetWeakDefaultVersion(h):GetGlobalDefaultVersion(h), symname);
|
||||
if(ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername)
|
||||
{
|
||||
uintptr_t start = 0;
|
||||
@@ -522,63 +636,65 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co
|
||||
int weak = 0;
|
||||
elfheader_t* ret = NULL;
|
||||
// check with default version...
|
||||
const char* defver = GetDefaultVersion(my_context->globaldefver, name);
|
||||
const char* defver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 0, name);
|
||||
|
||||
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, &start, &end, version, vername, 1, defver))
|
||||
return my_context->elfs[0];
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1)) {
|
||||
int idx = GetElfIndex(maplib->libraries[i]);
|
||||
if(idx==-1) {
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1, defver)) {
|
||||
elfheader_t* h = GetElf(maplib->libraries[i]);
|
||||
if(!h) {
|
||||
printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i]));
|
||||
return NULL;
|
||||
}
|
||||
if(weak)
|
||||
ret = my_context->elfs[idx];
|
||||
ret = h;
|
||||
else
|
||||
return my_context->elfs[idx];
|
||||
return h;
|
||||
}
|
||||
}
|
||||
|
||||
defver = GetDefaultVersion(my_context->weakdefver, name);
|
||||
defver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 1, name);
|
||||
if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, &start, &end, version, vername, 1, defver))
|
||||
ret = my_context->elfs[0];
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1)) {
|
||||
int idx = GetElfIndex(maplib->libraries[i]);
|
||||
if(idx==-1) {
|
||||
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1, defver)) {
|
||||
elfheader_t* h = GetElf(maplib->libraries[i]);
|
||||
if(!h) {
|
||||
printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i]));
|
||||
return NULL;
|
||||
}
|
||||
if(weak)
|
||||
ret = my_context->elfs[idx];
|
||||
ret = h;
|
||||
else
|
||||
return my_context->elfs[idx];
|
||||
return h;
|
||||
}
|
||||
}
|
||||
// return what has been found (maybe nothing)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername)
|
||||
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, const char* defver)
|
||||
{
|
||||
int weak = 0;
|
||||
size_t size = 0;
|
||||
// check global GLOB_DAT kind of symbols
|
||||
if(GetSymbolStartEnd(GetGlobalData(maplib), name, start, end, version, vername, 1, defver))
|
||||
if(*start || *end)
|
||||
return 1;
|
||||
// check with default version...
|
||||
const char* defver = GetDefaultVersion(my_context->globaldefver, name);
|
||||
|
||||
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, 1, defver))
|
||||
if(*start || *end)
|
||||
return 1;
|
||||
for(int i=0; i<maplib->libsz; ++i)
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1))
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, defver))
|
||||
if(*start || *end)
|
||||
return 1;
|
||||
// nope, not found
|
||||
return 0;
|
||||
}
|
||||
|
||||
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername)
|
||||
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername, const char* defver)
|
||||
{
|
||||
uintptr_t start, end;
|
||||
size_t size = 0;
|
||||
@@ -586,7 +702,7 @@ int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, c
|
||||
// check with default version...
|
||||
for(int i=0; i<maplib->libsz; ++i)
|
||||
if(GetElfIndex(maplib->libraries[i])==-1)
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1))
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1, defver))
|
||||
if(start || end)
|
||||
return 1;
|
||||
// nope, not found
|
||||
@@ -594,22 +710,23 @@ int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, c
|
||||
|
||||
}
|
||||
|
||||
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername)
|
||||
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver)
|
||||
{
|
||||
// check with default version...
|
||||
int weak;
|
||||
size_t size = 0;
|
||||
const char* defver = globdefver?globdefver:weakdefver;
|
||||
|
||||
if(my_context->elfs[0]==self || !self) {
|
||||
if(GetSymbolStartEnd(GetLocalSymbols(my_context->elfs[0]), name, start, end, version, vername, 1, NULL))
|
||||
if(GetSymbolStartEnd(GetLocalSymbols(my_context->elfs[0]), name, start, end, version, vername, 1, defver))
|
||||
if(*start || *end)
|
||||
return 1;
|
||||
if(self)
|
||||
return 0;
|
||||
}
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || my_context->elfs[GetElfIndex(maplib->libraries[i])]==self)) {
|
||||
if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1))
|
||||
if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || GetElf(maplib->libraries[i])==self)) {
|
||||
if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, defver))
|
||||
if(*start || *end)
|
||||
return 1;
|
||||
if(self)
|
||||
@@ -623,7 +740,6 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui
|
||||
|
||||
const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, const char** libname, void** base, library_t** lib)
|
||||
{
|
||||
(void)maplib;
|
||||
// first, search in self...
|
||||
const char* ret = NULL;
|
||||
uintptr_t offs = 0;
|
||||
@@ -645,15 +761,15 @@ const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, c
|
||||
*lib = NULL; // main elf
|
||||
else {
|
||||
for(int i=0; i<my_context->maplib->libsz; ++i) {
|
||||
int idx = GetElfIndex(my_context->maplib->libraries[i]);
|
||||
if((idx!=-1) && (my_context->elfs[idx]==h)) {
|
||||
elfheader_t* head = GetElf(my_context->maplib->libraries[i]);
|
||||
if((head) && (head==h)) {
|
||||
*lib = my_context->maplib->libraries[i];
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
for(int i=0; i<my_context->local_maplib->libsz; ++i) {
|
||||
int idx = GetElfIndex(my_context->local_maplib->libraries[i]);
|
||||
if((idx!=-1) && (my_context->elfs[idx]==h)) {
|
||||
elfheader_t* head = GetElf(my_context->local_maplib->libraries[i]);
|
||||
if((head) && (head==h)) {
|
||||
*lib = my_context->local_maplib->libraries[i];
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@ typedef struct lib_s {
|
||||
int ownlibs;
|
||||
library_t *owner; // in case that maplib is owned by a lib
|
||||
|
||||
box86context_t* context;
|
||||
|
||||
bridge_t *bridge; // all x86 -> arm bridge
|
||||
} lib_t;
|
||||
|
||||
|
||||
+348
-244
File diff suppressed because it is too large.
Load diff
@@ -13,8 +13,8 @@ typedef struct bridge_s bridge_t;
|
||||
typedef struct elfheader_s elfheader_t;
|
||||
typedef struct kh_bridgemap_s kh_bridgemap_t;
|
||||
typedef struct kh_mapsymbols_s kh_mapsymbols_t;
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
|
||||
|
||||
typedef struct symbol2_s {
|
||||
@@ -37,25 +37,24 @@ typedef struct wlib_s {
|
||||
void* lib; // dlopen result
|
||||
void* priv; // actual private
|
||||
char* altprefix; // if function names are mangled..
|
||||
int needed;
|
||||
char** neededlibs;
|
||||
needed_libs_t* needed;
|
||||
kh_symbolmap_t *symbolmap;
|
||||
kh_symbolmap_t *wsymbolmap;
|
||||
kh_symbolmap_t *mysymbolmap;
|
||||
kh_symbolmap_t *wmysymbolmap;
|
||||
kh_symbolmap_t *stsymbolmap;
|
||||
kh_symbolmap_t *wstsymbolmap;
|
||||
kh_symbol2map_t *symbol2map;
|
||||
kh_datamap_t *datamap;
|
||||
kh_datamap_t *wdatamap;
|
||||
kh_datamap_t *mydatamap;
|
||||
char *altmy; // to avoid duplicate symbol, like with SDL1/SDL2
|
||||
int refcnt; // refcounting the lib
|
||||
} wlib_t;
|
||||
|
||||
typedef struct elib_s {
|
||||
int elf_index;
|
||||
int finalized;
|
||||
elfheader_t *elf;
|
||||
int finalized;
|
||||
} elib_t;
|
||||
|
||||
typedef struct library_s {
|
||||
@@ -63,27 +62,20 @@ typedef struct library_s {
|
||||
char* path; // original path
|
||||
int nbdot; // nombre of "." after .so
|
||||
int type; // 0: native(wrapped) 1: emulated(elf) -1: undetermined
|
||||
int active;
|
||||
wrappedlib_fini_t fini;
|
||||
wrappedlib_get_t getglobal; // get global symbol (not weak)
|
||||
wrappedlib_get_t getweak; // get weak symbol
|
||||
wrappedlib_get_t getlocal; // get local symbol
|
||||
wrappedlib_get_t getglobal; // get global (non-weak)
|
||||
wrappedlib_get_t getweak; // get weak symbol
|
||||
wrappedlib_get_t getlocal; // get local symbol
|
||||
union {
|
||||
wlib_t w;
|
||||
elib_t e;
|
||||
}; // private lib data
|
||||
needed_libs_t needed;
|
||||
needed_libs_t dependedby;
|
||||
int refcnt; // refcounting the lib
|
||||
}; // private lib data
|
||||
lib_t *maplib; // local maplib, for dlopen'd library with LOCAL binding (most of the dlopen)
|
||||
kh_bridgemap_t *gbridgemap; // global symbol bridgemap
|
||||
kh_bridgemap_t *wbridgemap; // weak symbol bridgemap
|
||||
kh_bridgemap_t *lbridgemap; // local symbol bridgemap
|
||||
int dlopen; // idx to the dlopen idx (or 0 if not dlopen)
|
||||
} library_t;
|
||||
void add_neededlib(needed_libs_t* needed, library_t* lib);
|
||||
void free_neededlib(needed_libs_t* needed);
|
||||
void add_dependedbylib(needed_libs_t* dependedby, library_t* lib);
|
||||
void free_dependedbylib(needed_libs_t* dependedby);
|
||||
|
||||
// type for map elements
|
||||
typedef struct map_onesymbol_s {
|
||||
@@ -99,11 +91,11 @@ typedef struct map_onesymbol2_s {
|
||||
} map_onesymbol2_t;
|
||||
typedef struct map_onedata_s {
|
||||
const char* name;
|
||||
uint32_t sz;
|
||||
uint32_t sz; // TODO: convert to size_t
|
||||
int weak;
|
||||
} map_onedata_t;
|
||||
|
||||
int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr, uint32_t *size, int* weak, int version, const char* vername, int local); // Add bridges to functions
|
||||
int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size, int *weak, int version, const char* vername, int local); // Add bridges to functions
|
||||
|
||||
typedef struct linkmap_s {
|
||||
// actual struct link_map
|
||||
@@ -117,7 +109,13 @@ typedef struct linkmap_s {
|
||||
} linkmap_t;
|
||||
|
||||
linkmap_t* getLinkMapLib(library_t* lib);
|
||||
linkmap_t* getLinkMapElf(elfheader_t* h);
|
||||
linkmap_t* addLinkMapLib(library_t* lib);
|
||||
void removeLinkMapLib(library_t* lib);
|
||||
|
||||
int FiniLibrary(library_t* lib, x86emu_t* emu);
|
||||
void Free1Library(library_t **lib, x86emu_t* emu);
|
||||
|
||||
void RemoveDlopen(library_t** lib, int idx); // defined in wrappedlibdl.c
|
||||
|
||||
#endif //__LIBRARY_PRIVATE_H_
|
||||
+19
-5
@@ -17,7 +17,7 @@ typedef struct onesymbol_s {
|
||||
} onesymbol_t;
|
||||
|
||||
typedef struct versymbol_s {
|
||||
int version; // -1 = no-version, 0=local, 1=global, X=versionned
|
||||
int version; // -1 = no-version, 0=local, 1=global, X=versioned
|
||||
const char* vername; // NULL or version name if version=X
|
||||
onesymbol_t sym;
|
||||
} versymbol_t;
|
||||
@@ -94,7 +94,7 @@ static versymbol_t* FindVersion(versymbols_t* s, size_t size, const char* vernam
|
||||
return &s->syms[i];
|
||||
return NULL;
|
||||
}
|
||||
/* static versymbol_t* FindFirstVersion(versymbols_t* s, size_t size)
|
||||
static versymbol_t* FindFirstVersion(versymbols_t* s, size_t size)
|
||||
{
|
||||
if(!s || !s->sz)
|
||||
return NULL;
|
||||
@@ -102,7 +102,7 @@ static versymbol_t* FindVersion(versymbols_t* s, size_t size, const char* vernam
|
||||
if(s->syms[i].version>1 && (!size || (size==s->syms[i].sym.sz)))
|
||||
return &s->syms[i];
|
||||
return NULL;
|
||||
} */
|
||||
}
|
||||
|
||||
// Match version (so ver=0:0, ver=1:-1/1/X, ver=-1:any, ver=X:1/"name")
|
||||
static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername, size_t size, int local, const char* defver)
|
||||
@@ -122,7 +122,7 @@ static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername,
|
||||
if(!ret) ret = FindNoVersion(s, size);
|
||||
if(!ret) ret = FindVersionGlobal(s, size);
|
||||
if(!ret && defver) ret = FindVersion(s, size, defver);
|
||||
//if(!ret) ret = FindFirstVersion(s);
|
||||
//if(!ret) ret = FindFirstVersion(s, size);
|
||||
return ret;
|
||||
}
|
||||
if(ver==-2) {
|
||||
@@ -170,6 +170,19 @@ void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, ui
|
||||
v->syms[idx].sym.sz = sz;
|
||||
}
|
||||
|
||||
void ForceUpdateSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz)
|
||||
{
|
||||
int ret;
|
||||
khint_t k = kh_put(mapsymbols, mapsymbols, name, &ret);
|
||||
versymbols_t * v = &kh_val(mapsymbols, k);
|
||||
if(ret) {v->sz = v->cap = 0; v->syms = NULL;}
|
||||
// now check if that version already exist, and update record and exit if yes
|
||||
for(int i=0; i<v->sz; ++i) {
|
||||
v->syms[i].sym.offs = addr;
|
||||
v->syms[i].sym.sz = sz;
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local, const char* defver)
|
||||
{
|
||||
if(!mapsymbols)
|
||||
@@ -289,5 +302,6 @@ const char* GetDefaultVersion(kh_defaultversion_t* def, const char* symname)
|
||||
khint_t k = kh_get(defaultversion, def, symname);
|
||||
if(k==kh_end(def))
|
||||
return NULL;
|
||||
return kh_value(def, k);
|
||||
else
|
||||
return kh_value(def, k);
|
||||
}
|
||||
+10
-10
@@ -41,20 +41,20 @@ GO(3)
|
||||
// compare
|
||||
#ifdef NOALIGN
|
||||
#define GO(A) \
|
||||
static uintptr_t my_compare_fct_##A = 0; \
|
||||
static int my_compare_##A(FTSENT* a, FTSENT* b) \
|
||||
{ \
|
||||
return (int)RunFunction(my_context, my_compare_fct_##A, 2, a, b);\
|
||||
static uintptr_t my_compare_fct_##A = 0; \
|
||||
static int my_compare_##A(FTSENT* a, FTSENT* b) \
|
||||
{ \
|
||||
return (int)RunFunctionFmt(my_compare_fct_##A, "pp", a, b); \
|
||||
}
|
||||
#else
|
||||
#define GO(A) \
|
||||
static uintptr_t my_compare_fct_##A = 0; \
|
||||
static int my_compare_##A(FTSENT* a, FTSENT* b) \
|
||||
{ \
|
||||
x86_ftsent_t x86_a, x86_b; \
|
||||
UnalignFTSENT(&x86_a, a); \
|
||||
UnalignFTSENT(&x86_b, b); \
|
||||
return (int)RunFunction(my_context, my_compare_fct_##A, 2, x86_a, x86_b);\
|
||||
static int my_compare_##A(FTSENT* a, FTSENT* b) \
|
||||
{ \
|
||||
x86_ftsent_t x86_a, x86_b; \
|
||||
UnalignFTSENT(&x86_a, a); \
|
||||
UnalignFTSENT(&x86_b, b); \
|
||||
return (int)RunFunctionFmt(my_compare_fct_##A, "pp", x86_a, x86_b); \
|
||||
}
|
||||
#endif
|
||||
SUPER()
|
||||
|
||||
@@ -41,10 +41,10 @@ GO(4)
|
||||
|
||||
// chunkfun
|
||||
#define GO(A) \
|
||||
static uintptr_t my_chunkfun_fct_##A = 0; \
|
||||
static void* my_chunkfun_##A(size_t a) \
|
||||
{ \
|
||||
return (void*)RunFunction(my_context, my_chunkfun_fct_##A, 1, a); \
|
||||
static uintptr_t my_chunkfun_fct_##A = 0; \
|
||||
static void* my_chunkfun_##A(size_t a) \
|
||||
{ \
|
||||
return (void*)RunFunctionFmt(my_chunkfun_fct_##A, "L", a); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
@@ -74,10 +74,10 @@ static void* reverse_chunkfunFct(library_t* lib, void* fct)
|
||||
}
|
||||
// freefun
|
||||
#define GO(A) \
|
||||
static uintptr_t my_freefun_fct_##A = 0; \
|
||||
static void my_freefun_##A(void* a) \
|
||||
{ \
|
||||
RunFunction(my_context, my_freefun_fct_##A, 1, a); \
|
||||
static uintptr_t my_freefun_fct_##A = 0; \
|
||||
static void my_freefun_##A(void* a) \
|
||||
{ \
|
||||
RunFunctionFmt(my_freefun_fct_##A, "p", a); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
@@ -211,7 +211,7 @@ void actual_obstack_alloc_failed_handler()
|
||||
{
|
||||
if(ref_obstack_alloc_failed_handler == my_obstack_alloc_failed_handler)
|
||||
real_obstack_alloc_failed_handler();
|
||||
RunFunction(my_context, (uintptr_t)my_obstack_alloc_failed_handler, 0);
|
||||
RunFunctionFmt((uintptr_t)my_obstack_alloc_failed_handler, "");
|
||||
}
|
||||
void obstackSetup()
|
||||
{
|
||||
|
||||
@@ -72,20 +72,20 @@ EXPORT int32_t my_native_close(SDL1_RWops_t *context)
|
||||
}
|
||||
EXPORT int32_t my_emulated_seek(SDL1_RWops_t *context, int32_t offset, int32_t whence)
|
||||
{
|
||||
return (int32_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->seek, 3, context->hidden.my.orig, offset, whence);
|
||||
return (int32_t)RunFunctionFmt((uintptr_t)context->hidden.my.orig->seek, "pii", context->hidden.my.orig, offset, whence);
|
||||
}
|
||||
EXPORT int32_t my_emulated_read(SDL1_RWops_t *context, void *ptr, int32_t size, int32_t maxnum)
|
||||
{
|
||||
return (int32_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->read, 4, context->hidden.my.orig, ptr, size, maxnum);
|
||||
return (int32_t)RunFunctionFmt((uintptr_t)context->hidden.my.orig->read, "ppii", context->hidden.my.orig, ptr, size, maxnum);
|
||||
}
|
||||
|
||||
EXPORT int32_t my_emulated_write(SDL1_RWops_t *context, const void *ptr, int32_t size, int32_t num)
|
||||
{
|
||||
return (int32_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->write, 4, context->hidden.my.orig, ptr, size, num);
|
||||
return (int32_t)RunFunctionFmt((uintptr_t)context->hidden.my.orig->write, "ppii", context->hidden.my.orig, ptr, size, num);
|
||||
}
|
||||
EXPORT int32_t my_emulated_close(SDL1_RWops_t *context)
|
||||
{
|
||||
return (int32_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->close, 1, context->hidden.my.orig);
|
||||
return (int32_t)RunFunctionFmt((uintptr_t)context->hidden.my.orig->close, "p", context->hidden.my.orig);
|
||||
}
|
||||
|
||||
SDL1_RWops_t* AddNativeRW(x86emu_t* emu, SDL1_RWops_t* ops)
|
||||
|
||||
@@ -77,27 +77,23 @@ EXPORT int32_t my2_native_close(SDL2_RWops_t *context)
|
||||
}
|
||||
EXPORT int64_t my2_emulated_size(SDL2_RWops_t *context)
|
||||
{
|
||||
return (int64_t)RunFunction64(my_context, (uintptr_t)context->hidden.my.orig->size, 1, context->hidden.my.orig);
|
||||
return (int64_t)RunFunctionFmt64((uintptr_t)context->hidden.my.orig->size, "p", context->hidden.my.orig);
|
||||
}
|
||||
EXPORT int64_t my2_emulated_seek(SDL2_RWops_t *context, int64_t offset, int32_t whence)
|
||||
{
|
||||
return (int64_t)RunFunction64(my_context,
|
||||
(uintptr_t)context->hidden.my.orig->seek, 4, context->hidden.my.orig,
|
||||
(void*)(uintptr_t)(offset&0xffffffff),
|
||||
(void*)(uintptr_t)((offset>>32)&0xffffffff),
|
||||
whence);
|
||||
return (int64_t)RunFunctionFmt64((uintptr_t)context->hidden.my.orig->seek, "pIi", context->hidden.my.orig, offset, whence);
|
||||
}
|
||||
EXPORT int32_t my2_emulated_read(SDL2_RWops_t *context, void *ptr, int32_t size, int32_t maxnum)
|
||||
{
|
||||
return (int32_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->read, 4, context->hidden.my.orig, ptr, size, maxnum);
|
||||
return (int32_t)RunFunctionFmt((uintptr_t)context->hidden.my.orig->read, "ppii", context->hidden.my.orig, ptr, size, maxnum);
|
||||
}
|
||||
EXPORT int32_t my2_emulated_write(SDL2_RWops_t *context, const void *ptr, int32_t size, int32_t num)
|
||||
{
|
||||
return (int32_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->write, 4, context->hidden.my.orig, ptr, size, num);
|
||||
return (int32_t)RunFunctionFmt((uintptr_t)context->hidden.my.orig->write, "ppii", context->hidden.my.orig, ptr, size, num);
|
||||
}
|
||||
EXPORT int32_t my2_emulated_close(SDL2_RWops_t *context)
|
||||
{
|
||||
return (int32_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->close, 1, context->hidden.my.orig);
|
||||
return (int32_t)RunFunctionFmt((uintptr_t)context->hidden.my.orig->close, "p", context->hidden.my.orig);
|
||||
}
|
||||
|
||||
SDL2_RWops_t* AddNativeRW2(x86emu_t* emu, SDL2_RWops_t* ops)
|
||||
|
||||
+50
-21
@@ -304,6 +304,8 @@ uint32_t RunFunctionHandler(int* exit, int dynarec, i386_ucontext_t* sigcontext,
|
||||
int oldquitonlongjmp = emu->quitonlongjmp;
|
||||
emu->quitonlongjmp = 2;
|
||||
|
||||
emu->eflags.x32 &= ~(1<<F_TF); // this one needs to cleared
|
||||
|
||||
if(dynarec)
|
||||
DynaCall(emu, fnc);
|
||||
else
|
||||
@@ -594,8 +596,8 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 17;
|
||||
else if(sig==SIGSEGV) {
|
||||
if((uintptr_t)info->si_addr == sigcontext->uc_mcontext.gregs[REG_EIP]) {
|
||||
sigcontext->uc_mcontext.gregs[REG_ERR] = 0x0010; // execution flag issue (probably)
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = (info->si_code == SEGV_ACCERR)?13:14;
|
||||
sigcontext->uc_mcontext.gregs[REG_ERR] = (info->si_errno==0x1234)?0:0x0010; // execution flag issue (probably), unless it's a #GP(0)
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = (info->si_code == SEGV_ACCERR || (info->si_errno==0x1234) || (uintptr_t)info->si_addr==0)?13:14;
|
||||
} else if((info->si_code==SEGV_ACCERR) && !(prot&PROT_WRITE)) {
|
||||
sigcontext->uc_mcontext.gregs[REG_ERR] = 0x0002; // write flag issue
|
||||
/*if(abs((intptr_t)info->si_addr-(intptr_t)sigcontext->uc_mcontext.gregs[REG_ESP])<16)
|
||||
@@ -603,7 +605,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
|
||||
else*/
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 14; // PAGE_FAULT
|
||||
} else {
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = (info->si_code == SEGV_ACCERR)?13:14;
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = (info->si_code == SEGV_ACCERR)?14:13;
|
||||
//REG_ERR seems to be INT:8 CODE:8. So for write access segfault it's 0x0002 For a read it's 0x0004 (and 8 for exec). For an int 2d it could be 0x2D01 for example
|
||||
sigcontext->uc_mcontext.gregs[REG_ERR] = 0x0004; // read error? there is no execute control in box86 anyway
|
||||
}
|
||||
@@ -618,6 +620,8 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
|
||||
}
|
||||
else if(sig==SIGILL)
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 6;
|
||||
else if(sig==SIGTRAP)
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = info->si_code;
|
||||
// call the signal handler
|
||||
i386_mcontext_t sigmcontext_copy = sigcontext->uc_mcontext;
|
||||
// save old value from emu
|
||||
@@ -686,7 +690,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
|
||||
//relockMutex(Locks); // do not relock mutex, because of the siglongjmp, whatever was running is canceled
|
||||
#ifdef DYNAREC
|
||||
if(Locks & is_dyndump_locked)
|
||||
CancelBlock();
|
||||
CancelBlock(1);
|
||||
#endif
|
||||
siglongjmp(ejb->jmpbuf, 1);
|
||||
}
|
||||
@@ -728,6 +732,9 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
|
||||
}
|
||||
|
||||
extern void* current_helper;
|
||||
#ifdef DYNAREC
|
||||
static uint32_t mutex_dynarec_prot = 0;
|
||||
#endif
|
||||
|
||||
void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
{
|
||||
@@ -759,19 +766,20 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
#endif
|
||||
#ifdef DYNAREC
|
||||
if((Locks & is_dyndump_locked) && (sig==SIGSEGV) && current_helper) {
|
||||
relockMutex(Locks);
|
||||
CancelBlock();
|
||||
CancelBlock(0);
|
||||
cancelFillBlock(); // Segfault inside a Fillblock
|
||||
relockMutex(Locks);
|
||||
}
|
||||
dynablock_t* db = NULL;
|
||||
int db_searched = 0;
|
||||
if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_CUSTOM)) {
|
||||
mutex_lock(&mutex_dynarec_prot);
|
||||
// access error, unprotect the block (and mark them dirty)
|
||||
unprotectDB((uintptr_t)addr, 1, 1); // unprotect 1 byte... But then, the whole page will be unprotected
|
||||
// check if SMC inside block
|
||||
db = FindDynablockFromNativeAddress(pc);
|
||||
db_searched = 1;
|
||||
int db_need_test = db?db->need_test:0;
|
||||
int db_need_test = (db && !box86_dynarec_fastpage)?getNeedTest((uintptr_t)db->x86_addr):0;
|
||||
dynarec_log(LOG_INFO/*LOG_DEBUG*/, "SIGSEGV with Access error on %p for %p , db=%p(%p)\n", pc, addr, db, db?((void*)db->x86_addr):NULL);
|
||||
static uintptr_t repeated_page = 0;
|
||||
static int repeated_count = 0;
|
||||
@@ -810,41 +818,49 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
dynarec_log(LOG_INFO, "Dynablock %p(%p) unprotected, getting out (arm pc=%p, x86_pc=%p, special=%d)!\n", db, db->x86_addr, pc, (void*)ejb->emu->ip.dword[0], special);
|
||||
}
|
||||
//relockMutex(Locks); // do not relock because of he siglongjmp
|
||||
#ifdef DYNAREC
|
||||
mutex_unlock(&mutex_dynarec_prot);
|
||||
if(Locks & is_dyndump_locked)
|
||||
CancelBlock();
|
||||
CancelBlock(1);
|
||||
ejb->emu->test.clean = 0;
|
||||
#endif
|
||||
siglongjmp(ejb->jmpbuf, 2);
|
||||
}
|
||||
dynarec_log(LOG_INFO, "Warning, Auto-SMC (%p for db %p/%p) detected, but jmpbuffer not ready!\n", (void*)addr, db, (void*)db->x86_addr);
|
||||
}
|
||||
// done
|
||||
if(prot&PROT_WRITE) {
|
||||
mutex_unlock(&mutex_dynarec_prot);
|
||||
// if there is no write permission, don't return and continue to program signal handling
|
||||
relockMutex(Locks);
|
||||
return;
|
||||
}
|
||||
mutex_unlock(&mutex_dynarec_prot);
|
||||
} else if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_DYNAREC_R)) {
|
||||
// unprotect and continue to signal handler, because Write is not there on purpose
|
||||
unprotectDB((uintptr_t)addr, 1, 1); // unprotect 1 byte... But then, the whole page will be unprotected
|
||||
} else if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&(PROT_READ|PROT_WRITE))) {
|
||||
mutex_lock(&mutex_dynarec_prot);
|
||||
db = FindDynablockFromNativeAddress(pc);
|
||||
db_searched = 1;
|
||||
if(db && db->x86_addr>= addr && (db->x86_addr+db->x86_size)<addr) {
|
||||
dynarec_log(LOG_INFO, "Warning, addr inside current dynablock!\n");
|
||||
}
|
||||
if(addr && pc && db) {
|
||||
static void* glitch_pc = NULL;
|
||||
static void* glitch_addr = NULL;
|
||||
static int glitch_prot = 0;
|
||||
// mark stuff as unclean
|
||||
cleanDBFromAddressRange(((uintptr_t)addr)&~(box86_pagesize-1), box86_pagesize, 0);
|
||||
static void* glitch_pc = NULL;
|
||||
static void* glitch_addr = NULL;
|
||||
static int glitch_prot = 0;
|
||||
if(addr && pc /*&& db*/) {
|
||||
if((glitch_pc!=pc || glitch_addr!=addr || glitch_prot!=prot)) {
|
||||
// probably a glitch due to intensive multitask...
|
||||
dynarec_log(/*LOG_DEBUG*/LOG_INFO, "SIGSEGV with Access error on %p for %p , db=%p, retrying\n", pc, addr, db);
|
||||
dynarec_log(/*LOG_DEBUG*/LOG_INFO, "SIGSEGV with Access error on %p for %p, db=%p, prot=0x%x, retrying\n", pc, addr, db, prot);
|
||||
glitch_pc = pc;
|
||||
glitch_addr = addr;
|
||||
glitch_prot = prot;
|
||||
relockMutex(Locks);
|
||||
sched_yield(); // give time to the other process
|
||||
mutex_unlock(&mutex_dynarec_prot);
|
||||
return; // try again
|
||||
}
|
||||
dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for %p, db=%p, prot=0x%x\n", pc, addr, db, prot);
|
||||
glitch_pc = NULL;
|
||||
glitch_addr = NULL;
|
||||
glitch_prot = 0;
|
||||
@@ -860,16 +876,20 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
glitch2_addr = addr;
|
||||
glitch2_prot = prot;
|
||||
sched_yield(); // give time to the other process
|
||||
forceProtection((uintptr_t)addr, 1, prot); // force the protection
|
||||
refreshProtection((uintptr_t)addr);
|
||||
relockMutex(Locks);
|
||||
sched_yield(); // give time to the other process
|
||||
mutex_unlock(&mutex_dynarec_prot);
|
||||
return; // try again
|
||||
}
|
||||
glitch2_pc = NULL;
|
||||
glitch2_addr = NULL;
|
||||
glitch2_prot = 0;
|
||||
}
|
||||
mutex_unlock(&mutex_dynarec_prot);
|
||||
}
|
||||
if(!db_searched)
|
||||
db = FindDynablockFromNativeAddress(pc);
|
||||
#else
|
||||
void* db = NULL;
|
||||
#endif
|
||||
@@ -940,7 +960,7 @@ exit(-1);
|
||||
emu->init_stack, emu->init_stack+emu->size_stack, emu->stack2free, (void*)R_EBP,
|
||||
addr, info->si_code, prot, db, db?db->block:0, db?(db->block+db->size):0,
|
||||
db?db->x86_addr:0, db?(db->x86_addr+db->x86_size):0,
|
||||
getAddrFunctionName((uintptr_t)(db?db->x86_addr:0)), (db?db->need_test:0)?"need_stest":"clean", db?db->hash:0, hash);
|
||||
getAddrFunctionName((uintptr_t)(db?db->x86_addr:0)), (db?getNeedTest((uintptr_t)db->x86_addr):0)?"need_stest":"clean", db?db->hash:0, hash);
|
||||
#if defined(ARM)
|
||||
static const char* reg_name[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
|
||||
if(db)
|
||||
@@ -1024,7 +1044,7 @@ void emit_signal(x86emu_t* emu, int sig, void* addr, int code)
|
||||
void* db = NULL;
|
||||
siginfo_t info = {0};
|
||||
info.si_signo = sig;
|
||||
info.si_errno = 0;
|
||||
info.si_errno = (sig==SIGSEGV)?0x1234:0; // Mark as a sign this is a #GP(0) (like privileged instruction)
|
||||
info.si_code = code;
|
||||
info.si_addr = addr;
|
||||
printf_log(LOG_INFO, "Emit Signal %d at IP=%p / addr=%p, code=%d\n", sig, (void*)R_EIP, addr, code);
|
||||
@@ -1321,7 +1341,7 @@ EXPORT int my_makecontext(x86emu_t* emu, void* ucp, void* fnc, int32_t argc, int
|
||||
}
|
||||
// push the return value
|
||||
--esp;
|
||||
*esp = (uintptr_t)GetExit();
|
||||
*esp = my_context->exit_bridge;
|
||||
u->uc_mcontext.gregs[REG_ESP] = (uintptr_t)esp;
|
||||
|
||||
return 0;
|
||||
@@ -1336,7 +1356,12 @@ EXPORT int my_swapcontext(x86emu_t* emu, void* ucp1, void* ucp2)
|
||||
my_setcontext(emu, ucp2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DYNAREC
|
||||
static void atfork_child_dynarec_prot(void)
|
||||
{
|
||||
arm_lock_stored(&mutex_dynarec_prot, 0);
|
||||
}
|
||||
#endif
|
||||
void init_signal_helper(box86context_t* context)
|
||||
{
|
||||
// setup signal handling
|
||||
@@ -1355,6 +1380,10 @@ void init_signal_helper(box86context_t* context)
|
||||
sigaction(SIGILL, &action, NULL);
|
||||
|
||||
pthread_once(&sigstack_key_once, sigstack_key_alloc);
|
||||
#ifdef DYNAREC
|
||||
atfork_child_dynarec_prot();
|
||||
pthread_atfork(NULL, NULL, atfork_child_dynarec_prot);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fini_signal_helper()
|
||||
|
||||
+10
-10
@@ -312,7 +312,7 @@ EXPORT int my_pthread_create(x86emu_t *emu, void* t, void* attr, void* start_rou
|
||||
if(box86_dynarec) {
|
||||
// pre-creation of the JIT code for the entry point of the thread
|
||||
dynablock_t *current = NULL;
|
||||
DBGetBlock(emu, (uintptr_t)start_routine, 1, ¤t);
|
||||
DBGetBlock(emu, (uintptr_t)start_routine, 1);
|
||||
}
|
||||
#endif
|
||||
// create thread
|
||||
@@ -336,7 +336,7 @@ void* my_prepare_thread(x86emu_t *emu, void* f, void* arg, int ssize, void** pet
|
||||
if(box86_dynarec) {
|
||||
// pre-creation of the JIT code for the entry point of the thread
|
||||
dynablock_t *current = NULL;
|
||||
DBGetBlock(emu, (uintptr_t)f, 1, ¤t);
|
||||
DBGetBlock(emu, (uintptr_t)f, 1);
|
||||
}
|
||||
#endif
|
||||
*pet = et;
|
||||
@@ -440,10 +440,10 @@ GO(29)
|
||||
|
||||
// key_destructor
|
||||
#define GO(A) \
|
||||
static uintptr_t my_key_destructor_fct_##A = 0; \
|
||||
static void my_key_destructor_##A(void* a) \
|
||||
{ \
|
||||
RunFunction(my_context, my_key_destructor_fct_##A, 1, a);\
|
||||
static uintptr_t my_key_destructor_fct_##A = 0; \
|
||||
static void my_key_destructor_##A(void* a) \
|
||||
{ \
|
||||
RunFunctionFmt(my_key_destructor_fct_##A, "p", a); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
@@ -462,10 +462,10 @@ static void* findkey_destructorFct(void* fct)
|
||||
}
|
||||
// cleanup_routine
|
||||
#define GO(A) \
|
||||
static uintptr_t my_cleanup_routine_fct_##A = 0; \
|
||||
static void my_cleanup_routine_##A(void* a) \
|
||||
{ \
|
||||
RunFunction(my_context, my_cleanup_routine_fct_##A, 1, a);\
|
||||
static uintptr_t my_cleanup_routine_fct_##A = 0; \
|
||||
static void my_cleanup_routine_##A(void* a) \
|
||||
{ \
|
||||
RunFunctionFmt(my_cleanup_routine_fct_##A, "p", a); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
|
||||
+30
-3
@@ -553,6 +553,15 @@ typedef enum VkStructureType {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR = 1000269004,
|
||||
VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR = 1000269005,
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT = 1000273000,
|
||||
VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT = 1000274000,
|
||||
VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT = 1000274001,
|
||||
VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT = 1000274002,
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT = 1000275000,
|
||||
VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_EXT = 1000275001,
|
||||
VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODES_CREATE_INFO_EXT = 1000275002,
|
||||
VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_EXT = 1000275003,
|
||||
VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_SCALING_CREATE_INFO_EXT = 1000275004,
|
||||
VK_STRUCTURE_TYPE_RELEASE_SWAPCHAIN_IMAGES_INFO_EXT = 1000275005,
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV = 1000277000,
|
||||
VK_STRUCTURE_TYPE_GRAPHICS_SHADER_GROUP_CREATE_INFO_NV = 1000277001,
|
||||
VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV = 1000277002,
|
||||
@@ -569,6 +578,9 @@ typedef enum VkStructureType {
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT = 1000284000,
|
||||
VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT = 1000284001,
|
||||
VK_STRUCTURE_TYPE_DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT = 1000284002,
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_BIAS_CONTROL_FEATURES_EXT = 1000283000,
|
||||
VK_STRUCTURE_TYPE_DEPTH_BIAS_INFO_EXT = 1000283001,
|
||||
VK_STRUCTURE_TYPE_DEPTH_BIAS_REPRESENTATION_INFO_EXT = 1000283002,
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT = 1000286000,
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT = 1000286001,
|
||||
VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT = 1000287000,
|
||||
@@ -1048,6 +1060,19 @@ typedef struct my_vkhead_s {
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT: \
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT: \
|
||||
case VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR: \
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT: \
|
||||
case VK_STRUCTURE_TYPE_DEPTH_BIAS_INFO_EXT: \
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR: \
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR: \
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT: \
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT: \
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_BIAS_CONTROL_FEATURES_EXT: \
|
||||
case VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT: \
|
||||
case VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT: \
|
||||
case VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODES_CREATE_INFO_EXT: \
|
||||
case VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_EXT: \
|
||||
case VK_STRUCTURE_TYPE_PRESENT_ID_KHR: \
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO: \
|
||||
|
||||
#define CH(C, B, A) \
|
||||
case C: \
|
||||
@@ -1117,6 +1142,8 @@ typedef struct my_vkhead_s {
|
||||
CH(VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO, "uPpu", A) \
|
||||
CH(VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, "uPUiiUiiiffff", A) \
|
||||
CH(VK_STRUCTURE_TYPE_OPTICAL_FLOW_IMAGE_FORMAT_PROPERTIES_NV, "uPi", A) \
|
||||
CH(VK_STRUCTURE_TYPE_RELEASE_SWAPCHAIN_IMAGES_INFO_EXT, "uPUup", A) \
|
||||
CH(VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES, "uPSuuu", A) \
|
||||
|
||||
|
||||
//--------------------------------------------------------------
|
||||
@@ -1135,7 +1162,7 @@ GO(4)
|
||||
static uintptr_t my_vkDebugReportCallback_fct_##A = 0; \
|
||||
static int my_vkDebugReportCallback_##A(int a, int b, uint64_t c, size_t d, int e, void* f, void* g, void* h) \
|
||||
{ \
|
||||
return (int)RunFunction(my_context, my_vkDebugReportCallback_fct_##A, 9, a, b, c&0xffffffff, c>>32, d, e, f, g, h); \
|
||||
return (int)RunFunctionFmt(my_vkDebugReportCallback_fct_##A, "iiULuppp", a, b, c, d, e, f, g, h); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
@@ -1639,8 +1666,8 @@ static void* unalignTox86(my_vkhead_t* src, int cnt)
|
||||
CHANGE(return vkunalignStruct(src, s, cnt))
|
||||
default:
|
||||
// no need to unalign, but follow next...
|
||||
if(cnt>1) printf_log(LOG_INFO, "Warning, unalignTox86 of %d struct %d not uspported\n", cnt, src->sType);
|
||||
src->pNext = unalignTox86(src->pNext, 1);
|
||||
//if(cnt>1) printf_log(LOG_INFO, "Warning, unalignTox86 of %d struct %d not uspported\n", cnt, src->sType);
|
||||
src->pNext = unalignTox86(src->pNext, cnt);
|
||||
return src;
|
||||
}
|
||||
}
|
||||
|
||||
+130
-42
@@ -51,6 +51,9 @@ int box86_dynarec_log = LOG_NONE;
|
||||
uintptr_t box86_pagesize;
|
||||
uintptr_t box86_load_addr = 0;
|
||||
int box86_showbt = 0;
|
||||
int box86_isglibc234 = 0;
|
||||
int box86_nosandbox = 0;
|
||||
int box86_malloc_hack = 0;
|
||||
#ifdef DYNAREC
|
||||
int box86_dynarec = 1;
|
||||
int box86_dynarec_dump = 0;
|
||||
@@ -65,6 +68,9 @@ int box86_dynarec_fastround = 1;
|
||||
int box86_dynarec_safeflags = 1;
|
||||
int box86_dynarec_hotpage = 16;
|
||||
int box86_dynarec_bleeding_edge = 1;
|
||||
int box86_dynarec_jvm = 1;
|
||||
int box86_dynarec_wait = 1;
|
||||
int box86_dynarec_fastpage = 0;
|
||||
uintptr_t box86_nodynarec_start = 0;
|
||||
uintptr_t box86_nodynarec_end = 0;
|
||||
int box86_dynarec_test = 0;
|
||||
@@ -77,6 +83,7 @@ int arm_v8 = 0;
|
||||
#else //DYNAREC
|
||||
int box86_dynarec = 0;
|
||||
#endif
|
||||
int box86_libcef = 1;
|
||||
int dlsym_error = 0;
|
||||
int cycle_log = 0;
|
||||
int trace_xmm = 0;
|
||||
@@ -109,6 +116,7 @@ int box86_prefer_wrapped = 0;
|
||||
int box86_prefer_emulated = 0;
|
||||
int box86_steam = 0;
|
||||
int box86_wine = 0;
|
||||
int box86_musl = 0;
|
||||
int box86_nopulse = 0;
|
||||
int box86_nogtk = 0;
|
||||
int box86_novulkan = 0;
|
||||
@@ -416,6 +424,15 @@ void LoadLogEnv()
|
||||
else
|
||||
printf_log(LOG_INFO, "Dynarec will play %s safe with x86 flags\n", (box86_dynarec_safeflags==1)?"moderatly":"it");
|
||||
}
|
||||
p = getenv("BOX86_DYNAREC_WAIT");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[0]<='1')
|
||||
box86_dynarec_wait = p[0]-'0';
|
||||
}
|
||||
if(!box86_dynarec_wait)
|
||||
printf_log(LOG_INFO, "Dynarec will not wait for FillBlock to ready and use Interpreter instead\n");
|
||||
}
|
||||
p = getenv("BOX86_DYNAREC_HOTPAGE");
|
||||
if(p) {
|
||||
int val = -1;
|
||||
@@ -428,6 +445,15 @@ void LoadLogEnv()
|
||||
else
|
||||
printf_log(LOG_INFO, "Dynarec will not tag HotPage\n");
|
||||
}
|
||||
p = getenv("BOX86_DYNAREC_FASTPAGE");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[0]<='1')
|
||||
box86_dynarec_fastpage = p[0]-'0';
|
||||
}
|
||||
if(box86_dynarec_fastpage)
|
||||
printf_log(LOG_INFO, "Dynarec will use Fast HotPage\n");
|
||||
}
|
||||
p = getenv("BOX86_DYNAREC_BLEEDING_EDGE");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
@@ -437,6 +463,15 @@ void LoadLogEnv()
|
||||
if(!box86_dynarec_bleeding_edge)
|
||||
printf_log(LOG_INFO, "Dynarec will not detect MonoBleedingEdge\n");
|
||||
}
|
||||
p = getenv("BOX86_DYNAREC_JVM");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[0]<='1')
|
||||
box86_dynarec_jvm = p[0]-'0';
|
||||
}
|
||||
if(!box86_dynarec_jvm)
|
||||
printf_log(LOG_INFO, "Dynarec will not detect libjvm\n");
|
||||
}
|
||||
p = getenv("BOX86_NODYNAREC");
|
||||
if(p) {
|
||||
if (strchr(p,'-')) {
|
||||
@@ -495,6 +530,15 @@ void LoadLogEnv()
|
||||
#endif
|
||||
#endif
|
||||
// Other BOX86 env. var.
|
||||
p = getenv("BOX86_LIBCEF");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[0]<='1')
|
||||
box86_libcef = p[0]-'0';
|
||||
}
|
||||
if(!box86_libcef)
|
||||
printf_log(LOG_INFO, "Dynarec will not detect libcef\n");
|
||||
}
|
||||
p = getenv("BOX86_LOAD_ADDR");
|
||||
if(p) {
|
||||
if(sscanf(p, "0x%zx", &box86_load_addr)!=1)
|
||||
@@ -571,6 +615,19 @@ void LoadLogEnv()
|
||||
if(allow_missing_symbols)
|
||||
printf_log(LOG_INFO, "Allow missing needed symbols\n");
|
||||
}
|
||||
p = getenv("BOX86_MALLOC_HACK");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[0]<='0'+2)
|
||||
box86_malloc_hack = p[0]-'0';
|
||||
}
|
||||
if(!box86_malloc_hack) {
|
||||
if(box86_malloc_hack==1) {
|
||||
printf_log(LOG_INFO, "Malloc hook will not be redirected\n");
|
||||
} else
|
||||
printf_log(LOG_INFO, "Malloc hook will check for mmap/free occurrences\n");
|
||||
}
|
||||
}
|
||||
p = getenv("BOX86_NOPULSE");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
@@ -904,28 +961,31 @@ void LoadEnvVars(box86context_t *context)
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
void setupTraceInit(box86context_t* context)
|
||||
void setupTraceInit()
|
||||
{
|
||||
#ifdef HAVE_TRACE
|
||||
char* p = trace_init;
|
||||
if(p) {
|
||||
setbuf(stdout, NULL);
|
||||
uintptr_t trace_start=0, trace_end=0;
|
||||
uintptr_t s_trace_start=0, s_trace_end=0;
|
||||
if (strcmp(p, "1")==0)
|
||||
SetTraceEmu(0, 0);
|
||||
else if (strchr(p,'-')) {
|
||||
if(sscanf(p, "%d-%d", &trace_start, &trace_end)!=2) {
|
||||
if(sscanf(p, "0x%X-0x%X", &trace_start, &trace_end)!=2)
|
||||
sscanf(p, "%x-%x", &trace_start, &trace_end);
|
||||
if(sscanf(p, "%zd-%zd", &s_trace_start, &s_trace_end)!=2) {
|
||||
if(sscanf(p, "0x%zX-0x%zX", &s_trace_start, &s_trace_end)!=2)
|
||||
sscanf(p, "%zx-%zx", &s_trace_start, &s_trace_end);
|
||||
}
|
||||
if(trace_start || trace_end)
|
||||
SetTraceEmu(trace_start, trace_end);
|
||||
if(s_trace_start || s_trace_end)
|
||||
SetTraceEmu(s_trace_start, s_trace_end);
|
||||
} else {
|
||||
if (GetGlobalSymbolStartEnd(my_context->maplib, p, &trace_start, &trace_end, NULL, -1, NULL)) {
|
||||
SetTraceEmu(trace_start, trace_end);
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)trace_start, (void*)trace_end);
|
||||
if (GetGlobalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, NULL, NULL)) {
|
||||
SetTraceEmu(s_trace_start, s_trace_end);
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end);
|
||||
} else if(GetLocalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, NULL, NULL)) {
|
||||
SetTraceEmu(s_trace_start, s_trace_end);
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end);
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Warning, symbol to Traced (\"%s\") not found, disabling trace\n", p);
|
||||
printf_log(LOG_NONE, "Warning, symbol to trace (\"%s\") not found, disabling trace\n", p);
|
||||
SetTraceEmu(0, 100); // disabling trace, mostly
|
||||
}
|
||||
}
|
||||
@@ -935,43 +995,41 @@ void setupTraceInit(box86context_t* context)
|
||||
if (strcmp(p, "0"))
|
||||
SetTraceEmu(0, 1);
|
||||
}
|
||||
#else
|
||||
(void)context;
|
||||
#endif
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
void setupTrace(box86context_t* context)
|
||||
void setupTrace()
|
||||
{
|
||||
#ifdef HAVE_TRACE
|
||||
char* p = box86_trace;
|
||||
if(p) {
|
||||
setbuf(stdout, NULL);
|
||||
uintptr_t trace_start=0, trace_end=0;
|
||||
uintptr_t s_trace_start=0, s_trace_end=0;
|
||||
if (strcmp(p, "1")==0)
|
||||
SetTraceEmu(0, 0);
|
||||
else if (strchr(p,'-')) {
|
||||
if(sscanf(p, "%d-%d", &trace_start, &trace_end)!=2) {
|
||||
if(sscanf(p, "0x%X-0x%X", &trace_start, &trace_end)!=2)
|
||||
sscanf(p, "%x-%x", &trace_start, &trace_end);
|
||||
if(sscanf(p, "%zd-%zd", &s_trace_start, &s_trace_end)!=2) {
|
||||
if(sscanf(p, "0x%zX-0x%zX", &s_trace_start, &s_trace_end)!=2)
|
||||
sscanf(p, "%zx-%zx", &s_trace_start, &s_trace_end);
|
||||
}
|
||||
if(trace_start || trace_end) {
|
||||
SetTraceEmu(trace_start, trace_end);
|
||||
if(!trace_start && trace_end==1) {
|
||||
if(s_trace_start || s_trace_end) {
|
||||
SetTraceEmu(s_trace_start, s_trace_end);
|
||||
if(!s_trace_start && s_trace_end==1) {
|
||||
printf_log(LOG_INFO, "TRACE enabled but inactive\n");
|
||||
} else {
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)trace_start, (void*)trace_end);
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (GetGlobalSymbolStartEnd(my_context->maplib, p, &trace_start, &trace_end, NULL, -1, NULL)) {
|
||||
SetTraceEmu(trace_start, trace_end);
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)trace_start, (void*)trace_end);
|
||||
} else if(GetLocalSymbolStartEnd(my_context->maplib, p, &trace_start, &trace_end, NULL, -1, NULL)) {
|
||||
SetTraceEmu(trace_start, trace_end);
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)trace_start, (void*)trace_end);
|
||||
if (GetGlobalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, NULL, NULL)) {
|
||||
SetTraceEmu(s_trace_start, s_trace_end);
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end);
|
||||
} else if(GetLocalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, NULL, NULL)) {
|
||||
SetTraceEmu(s_trace_start, s_trace_end);
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end);
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Warning, symbol to Traced (\"%s\") not found, trying to set trace later\n", p);
|
||||
printf_log(LOG_NONE, "Warning, symbol to trace (\"%s\") not found, trying to set trace later\n", p);
|
||||
SetTraceEmu(0, 1); // disabling trace, mostly
|
||||
if(trace_func)
|
||||
box_free(trace_func);
|
||||
@@ -979,8 +1037,6 @@ void setupTrace(box86context_t* context)
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)context;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1204,8 +1260,13 @@ int main(int argc, const char **argv, char **env)
|
||||
wine_prereserve(prereserve);
|
||||
// special case for winedbg, doesn't work anyway
|
||||
if(argv[nextarg+1] && strstr(argv[nextarg+1], "winedbg")==argv[nextarg+1]) {
|
||||
printf_log(LOG_NONE, "winedbg detected, not launching it!\n");
|
||||
exit(0); // exiting, it doesn't work anyway
|
||||
if(getenv("BOX86_WINEDBG")) {
|
||||
box86_nobanner = 1;
|
||||
box86_log = 0;
|
||||
} else {
|
||||
printf_log(LOG_NONE, "winedbg detected, not launching it!\n");
|
||||
exit(0); // exiting, it doesn't work anyway
|
||||
}
|
||||
}
|
||||
box86_wine = 1;
|
||||
}
|
||||
@@ -1370,6 +1431,19 @@ int main(int argc, const char **argv, char **env)
|
||||
my_context->argv[i] = box_strdup(argv[i+nextarg]);
|
||||
printf_log(LOG_INFO, "argv[%i]=\"%s\"\n", i, my_context->argv[i]);
|
||||
}
|
||||
if(box86_nosandbox)
|
||||
{
|
||||
// check if sandbox is already there
|
||||
int there = 0;
|
||||
for(int i=1; i<my_context->argc && !there; ++i)
|
||||
if(!strcmp(my_context->argv[i], "--no-sandbox"))
|
||||
there = 1;
|
||||
if(!there) {
|
||||
my_context->argv = (char**)box_realloc(my_context->argv, (my_context->argc+1)*sizeof(char*));
|
||||
my_context->argv[my_context->argc] = box_strdup("--no-sandbox");
|
||||
my_context->argc++;
|
||||
}
|
||||
}
|
||||
|
||||
// check if file exist
|
||||
if(!my_context->argv[0] || !FileExist(my_context->argv[0], IS_FILE)) {
|
||||
@@ -1585,6 +1659,9 @@ int main(int argc, const char **argv, char **env)
|
||||
setupTraceInit(my_context);
|
||||
// export symbols
|
||||
AddSymbols(my_context->maplib, GetMapSymbols(elf_header), GetWeakSymbols(elf_header), GetLocalSymbols(elf_header), elf_header);
|
||||
box86_isglibc234 = GetVersionIndice(elf_header, "GLIBC_2.34")?1:0;
|
||||
if(box86_isglibc234)
|
||||
printf_log(LOG_DEBUG, "Program linked with GLIBC 2.34+\n");
|
||||
if(wine_preloaded) {
|
||||
uintptr_t wineinfo = FindSymbol(GetMapSymbols(elf_header), "wine_main_preload_info", -1, NULL, 1, NULL);
|
||||
if(!wineinfo) wineinfo = FindSymbol(GetWeakSymbols(elf_header), "wine_main_preload_info", -1, NULL, 1, NULL);
|
||||
@@ -1601,15 +1678,24 @@ int main(int argc, const char **argv, char **env)
|
||||
AddMainElfToLinkmap(elf_header);
|
||||
// pre-load lib if needed
|
||||
if(ld_preload.size) {
|
||||
for(int i=0; i<ld_preload.size; ++i)
|
||||
if(AddNeededLib(my_context->maplib, &my_context->neededlibs, NULL, 0, 0, (const char**)&ld_preload.paths[i], 1, my_context, emu)) {
|
||||
printf_log(LOG_INFO, "Warning, cannot pre-load the lib (%s)\n", ld_preload.paths[i]);
|
||||
}
|
||||
my_context->preload = new_neededlib(0);
|
||||
for(int i=0; i<ld_preload.size; ++i) {
|
||||
needed_libs_t* tmp = new_neededlib(1);
|
||||
tmp->names[0] = ld_preload.paths[i];
|
||||
if(AddNeededLib(my_context->maplib, 0, 0, tmp, elf_header, my_context, emu)) {
|
||||
printf_log(LOG_INFO, "Warning, cannot pre-load of %s\n", tmp->names[0]);
|
||||
RemoveNeededLib(my_context->maplib, 0, tmp, my_context, emu);
|
||||
} else {
|
||||
for(int j=0; j<tmp->size; ++j)
|
||||
add1lib_neededlib(my_context->preload, tmp->libs[j], tmp->names[j]);
|
||||
free_neededlib(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
FreeCollection(&ld_preload);
|
||||
// Call librarian to load all dependant elf
|
||||
if(LoadNeededLibs(elf_header, my_context->maplib, &my_context->neededlibs, NULL, 0, 0, my_context, emu)) {
|
||||
printf_log(LOG_NONE, "Error: loading needed libs in elf %s\n", my_context->fullpath);
|
||||
if(LoadNeededLibs(elf_header, my_context->maplib, 0, 0, my_context, emu)) {
|
||||
printf_log(LOG_NONE, "Error: loading needed libs in elf %s\n", my_context->argv[0]);
|
||||
FreeBox86Context(&my_context);
|
||||
return -1;
|
||||
}
|
||||
@@ -1623,24 +1709,26 @@ int main(int argc, const char **argv, char **env)
|
||||
// and handle PLT
|
||||
RelocateElfPlt(my_context->maplib, NULL, 0, elf_header);
|
||||
// defered init
|
||||
RunDeferedElfInit(emu);
|
||||
setupTraceInit();
|
||||
RunDeferredElfInit(emu);
|
||||
// update TLS of main elf
|
||||
RefreshElfTLS(elf_header);
|
||||
// do some special case check, _IO_2_1_stderr_ and friends, that are setup by libc, but it's already done here, so need to do a copy
|
||||
ResetSpecialCaseMainElf(elf_header);
|
||||
// init...
|
||||
setupTrace(my_context);
|
||||
setupTrace();
|
||||
// get entrypoint
|
||||
my_context->ep = GetEntryPoint(my_context->maplib, elf_header);
|
||||
|
||||
atexit(endBox86);
|
||||
loadProtectionFromMap();
|
||||
|
||||
// emulate!
|
||||
printf_log(LOG_DEBUG, "Start x86emu on Main\n");
|
||||
// Stack is ready, with stacked: NULL env NULL argv argc
|
||||
SetEIP(emu, my_context->ep);
|
||||
ResetFlags(emu);
|
||||
PushExit(emu); // push to pop it just after
|
||||
Push32(emu, my_context->exit_bridge); // push to pop it just after
|
||||
SetEDX(emu, Pop32(emu)); // EDX is exit function
|
||||
DynaRun(emu);
|
||||
// Get EAX
|
||||
|
||||
+444
-131
@@ -4,22 +4,22 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/mman.h>
|
||||
#include <dlfcn.h>
|
||||
#ifdef ANDROID
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#include "box86context.h"
|
||||
#include "debug.h"
|
||||
#include "callback.h"
|
||||
#include "librarian.h"
|
||||
#include "elfs/elfloader_private.h"
|
||||
#include "custommem.h"
|
||||
#include "symbols.h"
|
||||
|
||||
/*
|
||||
This file here is for handling overriding of malloc functions
|
||||
|
||||
Libraries like tcmalloc overrides all malloc/free/new/delete function and implement a custom version.
|
||||
Problem is, box64 is already loaded in memoery, and already using system libc malloc for many of it's things
|
||||
Problem is, box86 is already loaded in memoery, and already using system libc malloc for many of it's things
|
||||
before those lib are even loaded in memory.
|
||||
Also, those override function can be define in the main executable, or in a lib loaded directly by the exectable
|
||||
or even in a lib loaded later using dlsym.
|
||||
@@ -27,8 +27,8 @@
|
||||
The 2 different strategies to handle this can be defined as "Embrace" and "Exterminate" (as it cannot simply be ignored,
|
||||
or you end up with mixing free/realloc from one lib and malloc/free from libc)
|
||||
|
||||
In the "Embrace" strategy, the overriden malloc function are taken into account as soon as possible, and are used for all loaded lib, including native
|
||||
In the "Exterminate" strategy, the overriden malloc function are erased, and replaced with libc malloc as soon as they are defined.
|
||||
In the "Embrace" strategy, the overridden malloc function are taken into account as soon as possible, and are used for all loaded lib, including native
|
||||
In the "Exterminate" strategy, the overridden malloc function are erased, and replaced with libc malloc as soon as they are defined.
|
||||
|
||||
The advantage of "Embrace" is that the system will run the function it supposed to be using, and potential side-effect and staticaly linked functions
|
||||
will run as intended.
|
||||
@@ -43,67 +43,74 @@
|
||||
*/
|
||||
|
||||
#include "bridge.h"
|
||||
#include "tools/bridge_private.h"
|
||||
#include "wrapper.h"
|
||||
|
||||
#define SUPER() \
|
||||
GO(malloc, pFL); \
|
||||
GO(free, vFp); \
|
||||
GO(calloc, pFLL); \
|
||||
GO(realloc, pFpL); \
|
||||
GO(aligned_alloc, pFLL); \
|
||||
GO(memalign, pFLL); \
|
||||
GO(posix_memalign, iFpLL); \
|
||||
GO(pvalloc, pFL); \
|
||||
GO(valloc, pFL); \
|
||||
GO(cfree, vFp); \
|
||||
GO(malloc_usable_size, LFp) ; \
|
||||
GO2(_Znwm, pFL); \
|
||||
GO2(_ZnwmRKSt9nothrow_t, pFLp); \
|
||||
GO2(_Znam, pFL); \
|
||||
GO2(_ZnamRKSt9nothrow_t, pFLp); \
|
||||
GO2(_ZdaPv, vFp); \
|
||||
GO2(_ZdaPvm, vFpL); \
|
||||
GO2(_ZdaPvmSt11align_val_t, vFpLL); \
|
||||
GO2(_ZdlPv, vFp); \
|
||||
GO2(_ZdlPvm, vFpL); \
|
||||
GO2(_ZnwmSt11align_val_t, pFLL); \
|
||||
GO2(_ZnwmSt11align_val_tRKSt9nothrow_t, pFLLp); \
|
||||
GO2(_ZnamSt11align_val_t, pFLL); \
|
||||
GO2(_ZnamSt11align_val_tRKSt9nothrow_t, pFLLp); \
|
||||
GO2(_ZdlPvRKSt9nothrow_t, vFpp); \
|
||||
GO2(_ZdaPvSt11align_val_tRKSt9nothrow_t, vFpLp);\
|
||||
GO2(_ZdlPvmSt11align_val_t, vFpLL); \
|
||||
GO2(_ZdaPvRKSt9nothrow_t, vFpp); \
|
||||
GO2(_ZdaPvSt11align_val_t, vFpL); \
|
||||
GO2(_ZdlPvSt11align_val_t, vFpL); \
|
||||
GO2(_ZdlPvSt11align_val_tRKSt9nothrow_t, vFpLp);\
|
||||
GO2(tc_calloc, pFLL); \
|
||||
GO2(tc_cfree, vFp); \
|
||||
GO2(tc_delete, vFp); \
|
||||
GO2(tc_deletearray, vFp); \
|
||||
GO2(tc_deletearray_nothrow, vFpp); \
|
||||
GO2(tc_delete_nothrow, vFpp); \
|
||||
GO2(tc_free, vFp); \
|
||||
GO2(tc_malloc, pFL); \
|
||||
GO2(tc_malloc_size, LFp); \
|
||||
GO2(tc_new, pFL); \
|
||||
GO2(tc_new_nothrow, pFLp); \
|
||||
GO2(tc_newarray, pFL); \
|
||||
GO2(tc_newarray_nothrow, pFLp); \
|
||||
GO2(tc_pvalloc, pFL); \
|
||||
GO2(tc_valloc, pFL); \
|
||||
GO2(tc_memalign, pFLL); \
|
||||
GO2(tc_malloc_skip_new_handler_weak, pFL); \
|
||||
GO2(tc_mallocopt, iFii); \
|
||||
GO2(tc_malloc_stats, vFv); \
|
||||
GO2(tc_malloc_skip_new_handler, pFL); \
|
||||
GO2S(tc_mallinfo, pFp); \
|
||||
GO2(tc_posix_memalign, iFpLL); \
|
||||
GO2(tc_realloc, pFpL); \
|
||||
GO(malloc, pFL) \
|
||||
GO(free, vFp) \
|
||||
GO(calloc, pFLL) \
|
||||
GO(realloc, pFpL) \
|
||||
GO(aligned_alloc, pFLL) \
|
||||
GO(memalign, pFLL) \
|
||||
GO(posix_memalign, iFpLL) \
|
||||
GO(pvalloc, pFL) \
|
||||
GO(valloc, pFL) \
|
||||
GO(cfree, vFp) \
|
||||
GO(malloc_usable_size, LFp) \
|
||||
GO2(_Znwm, pFL) \
|
||||
GO2(_ZnwmRKSt9nothrow_t, pFLp) \
|
||||
GO2(_Znam, pFL) \
|
||||
GO2(_ZnamRKSt9nothrow_t, pFLp) \
|
||||
GO2(_ZdaPv, vFp) \
|
||||
GO2(_ZdaPvm, vFpL) \
|
||||
GO2(_ZdaPvmSt11align_val_t, vFpLL) \
|
||||
GO2(_ZdlPv, vFp) \
|
||||
GO2(_ZdlPvm, vFpL) \
|
||||
GO2(_ZnwmSt11align_val_t, pFLL) \
|
||||
GO2(_ZnwmSt11align_val_tRKSt9nothrow_t, pFLLp) \
|
||||
GO2(_ZnamSt11align_val_t, pFLL) \
|
||||
GO2(_ZnamSt11align_val_tRKSt9nothrow_t, pFLLp) \
|
||||
GO2(_ZdlPvRKSt9nothrow_t, vFpp) \
|
||||
GO2(_ZdaPvSt11align_val_tRKSt9nothrow_t, vFpLp) \
|
||||
GO2(_ZdlPvmSt11align_val_t, vFpLL) \
|
||||
GO2(_ZdaPvRKSt9nothrow_t, vFpp) \
|
||||
GO2(_ZdaPvSt11align_val_t, vFpL) \
|
||||
GO2(_ZdlPvSt11align_val_t, vFpL) \
|
||||
GO2(_ZdlPvSt11align_val_tRKSt9nothrow_t, vFpLp) \
|
||||
GO2(tc_calloc, pFLL) \
|
||||
GO2(tc_cfree, vFp) \
|
||||
GO2(tc_delete, vFp) \
|
||||
GO2(tc_deletearray, vFp) \
|
||||
GO2(tc_deletearray_nothrow, vFpp) \
|
||||
GO2(tc_delete_nothrow, vFpp) \
|
||||
GO2(tc_free, vFp) \
|
||||
GO2(tc_malloc, pFL) \
|
||||
GO2(tc_malloc_size, LFp) \
|
||||
GO2(tc_new, pFL) \
|
||||
GO2(tc_new_nothrow, pFLp) \
|
||||
GO2(tc_newarray, pFL) \
|
||||
GO2(tc_newarray_nothrow, pFLp) \
|
||||
GO2(tc_pvalloc, pFL) \
|
||||
GO2(tc_valloc, pFL) \
|
||||
GO2(tc_memalign, pFLL) \
|
||||
GO2(tc_malloc_skip_new_handler_weak, pFL) \
|
||||
GO2(tc_mallocopt, iFii) \
|
||||
GO2(tc_malloc_stats, vFv) \
|
||||
GO2(tc_malloc_skip_new_handler, pFL) \
|
||||
GO2(tc_mallinfo, pFp) \
|
||||
GO2(tc_posix_memalign, iFpLL) \
|
||||
GO2(tc_realloc, pFpL) \
|
||||
GO2(safer_scalable_aligned_realloc, pFpLLp) \
|
||||
GO2(safer_scalable_free, vFpp) \
|
||||
GO2(safer_scalable_msize, LFpp) \
|
||||
GO2(safer_scalable_realloc, pFpLp) \
|
||||
GO2(scalable_aligned_free, vFp) \
|
||||
GO2(scalable_aligned_malloc, pFLL) \
|
||||
GO2(scalable_msize, LFp) \
|
||||
|
||||
//GO2(tc_set_new_mode, iFi);
|
||||
//GO2(tc_version, iFi);
|
||||
|
||||
//GO2(tc_set_new_mode, iFi)
|
||||
//GO2(tc_version, iFi)
|
||||
|
||||
typedef void (vFv_t) (void);
|
||||
typedef int (iFv_t) (void);
|
||||
@@ -115,19 +122,32 @@ typedef void* (*pFp_t) (void*);
|
||||
typedef size_t(*LFp_t) (void*);
|
||||
typedef int (*iFii_t) (int, int);
|
||||
typedef void (*vFpp_t) (void*, void*);
|
||||
typedef size_t(*LFpp_t) (void*, void*);
|
||||
typedef void (*vFpL_t) (void*, size_t);
|
||||
typedef void* (*pFLL_t) (size_t, size_t);
|
||||
typedef void* (*pFLLp_t)(size_t, size_t, void* p);
|
||||
typedef void (*vFpLp_t)(void*, size_t, void*);
|
||||
typedef void* (*pFpLp_t)(void*, size_t, void*);
|
||||
typedef void (*vFpLL_t)(void*, size_t, size_t);
|
||||
typedef void* (*pFpLLp_t)(void*, size_t, size_t, void*);
|
||||
|
||||
#ifdef ANDROID
|
||||
#define box_malloc_usable_size malloc_usable_size
|
||||
#else
|
||||
size_t(*box_malloc_usable_size)(void*) = NULL;
|
||||
void*(*__libc_malloc)(size_t) = NULL;
|
||||
void*(*__libc_realloc)(size_t, void*) = NULL;
|
||||
void*(*__libc_calloc)(size_t, size_t) = NULL;
|
||||
void (*__libc_free)(void*) = NULL;
|
||||
void*(*__libc_memalign)(size_t, size_t) = NULL;
|
||||
#endif
|
||||
size_t(*box_malloc_usable_size)(const void*) = NULL;
|
||||
|
||||
int GetTID();
|
||||
uint32_t getProtection(uintptr_t addr);
|
||||
// malloc_hack "2" handling
|
||||
// mmap history
|
||||
static int malloc_hack_2 = 0;
|
||||
|
||||
#define ALLOC 0
|
||||
#define FREE 1
|
||||
|
||||
char* box_strdup(const char* s) {
|
||||
char* ret = box_calloc(1, strlen(s)+1);
|
||||
@@ -155,43 +175,95 @@ char* box_realpath(const char* path, char* ret)
|
||||
|
||||
static size_t pot(size_t l) {
|
||||
size_t ret = 0;
|
||||
while (l>(1u<<ret)) ++ret;
|
||||
while (l>(1<<ret)) ++ret;
|
||||
return 1<<ret;
|
||||
}
|
||||
#ifndef ANDROID
|
||||
|
||||
static int ispot(size_t l) {
|
||||
return pot(l)==l;
|
||||
}
|
||||
|
||||
#define GO(A, B) static uintptr_t real_##A = 0;
|
||||
#define GO2(A, B) static uintptr_t real_##A = 0;
|
||||
SUPER()
|
||||
#undef GO2
|
||||
#undef GO
|
||||
|
||||
// redefining all libc memory allocation routines
|
||||
EXPORT void* malloc(size_t l)
|
||||
{
|
||||
if(malloc_hack_2 && ALLOC && real_malloc) {
|
||||
return (void*)RunFunctionFmt(real_malloc, "L", l);
|
||||
}
|
||||
return box_calloc(1, l);
|
||||
}
|
||||
|
||||
EXPORT void free(void* p)
|
||||
{
|
||||
if(malloc_hack_2 && FREE && p) {
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real_free)
|
||||
RunFunctionFmt(real_free, "p", p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
box_free(p);
|
||||
}
|
||||
|
||||
EXPORT void* calloc(size_t n, size_t s)
|
||||
{
|
||||
if(malloc_hack_2 && ALLOC && real_calloc) {
|
||||
return (void*)RunFunctionFmt(real_calloc, "LL", n,s);
|
||||
}
|
||||
return box_calloc(n, s);
|
||||
}
|
||||
|
||||
EXPORT void* realloc(void* p, size_t s)
|
||||
{
|
||||
if(malloc_hack_2)
|
||||
if(getMmapped((uintptr_t)p) || (!p && ALLOC && real_realloc)) {
|
||||
void* ret = p;
|
||||
if(real_realloc) {
|
||||
ret = (void*)RunFunctionFmt(real_realloc, "pL", p, s);
|
||||
} else {
|
||||
// found! Will realloc using regular malloc then copy from old address as much as possible, but need to check size first
|
||||
ret = box_malloc(s);
|
||||
printf_log(LOG_DEBUG, "Malloc_Hack_2: hacking realloc(%p, %zu)", p, s);
|
||||
while(s && !(getProtection((uintptr_t)p+s)&PROT_READ)) {if(s>box86_pagesize) s-=box86_pagesize; else s=0;}
|
||||
memcpy(ret, p, s);
|
||||
printf_log(LOG_DEBUG, " -> %p (copied %zu from old)\n", ret, s);
|
||||
// Mmaped, free with original function
|
||||
if(real_free)
|
||||
RunFunctionFmt(real_free, "p", p);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return box_realloc(p, s);
|
||||
}
|
||||
|
||||
EXPORT void* aligned_alloc(size_t align, size_t size)
|
||||
{
|
||||
if(malloc_hack_2 && ALLOC && real_aligned_alloc) {
|
||||
return (void*)RunFunctionFmt(real_aligned_alloc, "LL", align, size);
|
||||
}
|
||||
return box_memalign(align, size);
|
||||
}
|
||||
|
||||
EXPORT void* memalign(size_t align, size_t size)
|
||||
{
|
||||
if(malloc_hack_2 && ALLOC && real_aligned_alloc) {
|
||||
return (void*)RunFunctionFmt(real_aligned_alloc, "LL", align, size);
|
||||
}
|
||||
return box_memalign(align, size);
|
||||
}
|
||||
|
||||
EXPORT int posix_memalign(void** p, size_t align, size_t size)
|
||||
{
|
||||
if(malloc_hack_2 && ALLOC && real_posix_memalign) {
|
||||
return RunFunctionFmt(real_posix_memalign, "pLL", p, align, size);
|
||||
}
|
||||
if(align%sizeof(void*) || pot(align)!=align)
|
||||
return EINVAL;
|
||||
void* ret = box_memalign(align, size);
|
||||
@@ -201,140 +273,275 @@ EXPORT int posix_memalign(void** p, size_t align, size_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT size_t malloc_usable_size(void* p)
|
||||
{
|
||||
return box_malloc_usable_size(p);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
EXPORT void* valloc(size_t size)
|
||||
{
|
||||
if(malloc_hack_2 && ALLOC && real_valloc) {
|
||||
return (void*)RunFunctionFmt(real_valloc, "L", size);
|
||||
}
|
||||
return box_memalign(box86_pagesize, size);
|
||||
}
|
||||
|
||||
EXPORT void* pvalloc(size_t size)
|
||||
{
|
||||
if(malloc_hack_2 && ALLOC && real_pvalloc) {
|
||||
return (void*)RunFunctionFmt(real_pvalloc, "L", size);
|
||||
}
|
||||
return box_memalign(box86_pagesize, (size+box86_pagesize-1)&~(box86_pagesize-1));
|
||||
}
|
||||
|
||||
EXPORT void cfree(void* p)
|
||||
{
|
||||
if(malloc_hack_2 && FREE && p) {
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real_free)
|
||||
RunFunctionFmt(real_free, "p", p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
box_free(p);
|
||||
}
|
||||
|
||||
EXPORT size_t malloc_usable_size(const void* p)
|
||||
{
|
||||
if(malloc_hack_2 && real_malloc_usable_size) {
|
||||
if(getMmapped((uintptr_t)p))
|
||||
return RunFunctionFmt(real_malloc_usable_size, "p", p);
|
||||
}
|
||||
return box_malloc_usable_size(p);
|
||||
}
|
||||
|
||||
EXPORT void* my__Znwm(size_t sz) //operator new(size_t)
|
||||
{
|
||||
if(malloc_hack_2 && real__Znwm) {
|
||||
return (void*)RunFunctionFmt(real__Znwm, "L", sz);
|
||||
}
|
||||
return box_malloc(sz);
|
||||
}
|
||||
|
||||
EXPORT void* my__ZnwmRKSt9nothrow_t(size_t sz, void* p) //operator new(size_t, std::nothrow_t const&)
|
||||
{
|
||||
(void)p;
|
||||
if(malloc_hack_2 && real__ZnwmRKSt9nothrow_t) {
|
||||
return (void*)RunFunctionFmt(real__ZnwmRKSt9nothrow_t, "Lp", sz, p);
|
||||
}
|
||||
return box_malloc(sz);
|
||||
}
|
||||
|
||||
EXPORT void* my__Znam(size_t sz) //operator new[](size_t)
|
||||
{
|
||||
if(malloc_hack_2 && real__Znam) {
|
||||
return (void*)RunFunctionFmt(real__Znam, "L", sz);
|
||||
}
|
||||
return box_malloc(sz);
|
||||
}
|
||||
|
||||
EXPORT void* my__ZnamRKSt9nothrow_t(size_t sz, void* p) //operator new[](size_t, std::nothrow_t const&)
|
||||
{
|
||||
(void)p;
|
||||
if(malloc_hack_2 && real__ZnamRKSt9nothrow_t) {
|
||||
return (void*)RunFunctionFmt(real__ZnamRKSt9nothrow_t, "Lp", sz, p);
|
||||
}
|
||||
return box_malloc(sz);
|
||||
}
|
||||
|
||||
|
||||
EXPORT void my__ZdaPv(void* p) //operator delete[](void*)
|
||||
{
|
||||
if(malloc_hack_2 && p) {
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real__ZdaPv)
|
||||
RunFunctionFmt(real__ZdaPv, "p", p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
box_free(p);
|
||||
}
|
||||
|
||||
EXPORT void my__ZdaPvm(void* p, size_t sz) //operator delete[](void*, size_t)
|
||||
{
|
||||
(void)sz;
|
||||
if(malloc_hack_2 && p) {
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real__ZdaPvm)
|
||||
RunFunctionFmt(real__ZdaPvm, "pL", p, sz);
|
||||
return;
|
||||
}
|
||||
}
|
||||
box_free(p);
|
||||
}
|
||||
|
||||
EXPORT void my__ZdaPvmSt11align_val_t(void* p, size_t sz, size_t align) //operator delete[](void*, unsigned long, std::align_val_t)
|
||||
{
|
||||
(void)sz; (void)align;
|
||||
if(malloc_hack_2 && p) {
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real__ZdaPvmSt11align_val_t)
|
||||
RunFunctionFmt(real__ZdaPvmSt11align_val_t, "pLL", p, sz, align);
|
||||
return;
|
||||
}
|
||||
}
|
||||
box_free(p);
|
||||
}
|
||||
|
||||
EXPORT void my__ZdlPv(void* p) //operator delete(void*)
|
||||
{
|
||||
if(malloc_hack_2 && p) {
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real__ZdlPv)
|
||||
RunFunctionFmt(real__ZdlPv, "p", p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
box_free(p);
|
||||
}
|
||||
|
||||
EXPORT void my__ZdlPvm(void* p, size_t sz) //operator delete(void*, size_t)
|
||||
{
|
||||
(void)sz;
|
||||
if(malloc_hack_2 && p) {
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real__ZdlPvm)
|
||||
RunFunctionFmt(real__ZdlPvm, "pL", p, sz);
|
||||
return;
|
||||
}
|
||||
}
|
||||
box_free(p);
|
||||
}
|
||||
|
||||
EXPORT void* my__ZnwmSt11align_val_t(size_t sz, size_t align) //// operator new(unsigned long, std::align_val_t)
|
||||
{
|
||||
if(malloc_hack_2 && real__ZnwmSt11align_val_t) {
|
||||
return (void*)RunFunctionFmt(real__ZnwmSt11align_val_t, "LL", sz, align);
|
||||
}
|
||||
return box_memalign(align, sz);
|
||||
}
|
||||
|
||||
EXPORT void* my__ZnwmSt11align_val_tRKSt9nothrow_t(size_t sz, size_t align, void* p) //// operator new(unsigned long, std::align_val_t, std::nothrow_t const&)
|
||||
{
|
||||
(void)p;
|
||||
if(malloc_hack_2 && real__ZnwmSt11align_val_tRKSt9nothrow_t) {
|
||||
return (void*)RunFunctionFmt(real__ZnwmSt11align_val_tRKSt9nothrow_t, "LLp", sz, align, p);
|
||||
}
|
||||
return box_memalign(align, sz);
|
||||
}
|
||||
|
||||
EXPORT void* my__ZnamSt11align_val_t(size_t sz, size_t align) //// operator new[](unsigned long, std::align_val_t)
|
||||
{
|
||||
if(malloc_hack_2 && real__ZnamSt11align_val_t) {
|
||||
return (void*)RunFunctionFmt(real__ZnamSt11align_val_t, "LL", sz, align);
|
||||
}
|
||||
return box_memalign(align, sz);
|
||||
}
|
||||
|
||||
EXPORT void* my__ZnamSt11align_val_tRKSt9nothrow_t(size_t sz, size_t align, void* p) //// operator new[](unsigned long, std::align_val_t, std::nothrow_t const&)
|
||||
{
|
||||
(void)p;
|
||||
if(malloc_hack_2 && real__ZnamSt11align_val_tRKSt9nothrow_t) {
|
||||
return (void*)RunFunctionFmt(real__ZnamSt11align_val_tRKSt9nothrow_t, "LLp", sz, align, p);
|
||||
}
|
||||
return box_memalign(align, sz);
|
||||
}
|
||||
|
||||
EXPORT void my__ZdlPvRKSt9nothrow_t(void* p, void* n) //operator delete(void*, std::nothrow_t const&)
|
||||
{
|
||||
(void)n;
|
||||
if(malloc_hack_2 && p) {
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real__ZdlPvRKSt9nothrow_t)
|
||||
RunFunctionFmt(real__ZdlPvRKSt9nothrow_t, "pp", p, n);
|
||||
return;
|
||||
}
|
||||
}
|
||||
box_free(p);
|
||||
}
|
||||
|
||||
EXPORT void my__ZdaPvSt11align_val_tRKSt9nothrow_t(void* p, size_t align, void* n) //operator delete[](void*, std::align_val_t, std::nothrow_t const&)
|
||||
{
|
||||
(void)align; (void)n;
|
||||
if(malloc_hack_2 && p) {
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real_free)
|
||||
RunFunctionFmt(real_free, "p", p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
box_free(p);
|
||||
}
|
||||
|
||||
EXPORT void my__ZdlPvmSt11align_val_t(void* p, size_t sz, size_t align) //operator delete(void*, unsigned long, std::align_val_t)
|
||||
{
|
||||
(void)sz; (void)align;
|
||||
if(malloc_hack_2 && p) {
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real_free)
|
||||
RunFunctionFmt(real_free, "p", p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
box_free(p);
|
||||
}
|
||||
|
||||
EXPORT void my__ZdaPvRKSt9nothrow_t(void* p, void* n) //operator delete[](void*, std::nothrow_t const&)
|
||||
{
|
||||
(void)n;
|
||||
if(malloc_hack_2 && p) {
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real_free)
|
||||
RunFunctionFmt(real_free, "p", p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
box_free(p);
|
||||
}
|
||||
|
||||
EXPORT void my__ZdaPvSt11align_val_t(void* p, size_t align) //operator delete[](void*, std::align_val_t)
|
||||
{
|
||||
(void)align;
|
||||
if(malloc_hack_2 && p) {
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real_free)
|
||||
RunFunctionFmt(real_free, "p", p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
box_free(p);
|
||||
}
|
||||
|
||||
EXPORT void my__ZdlPvSt11align_val_t(void* p, size_t align) //operator delete(void*, std::align_val_t)
|
||||
{
|
||||
(void)align;
|
||||
if(malloc_hack_2 && p) {
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real_free)
|
||||
RunFunctionFmt(real_free, "p", p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
box_free(p);
|
||||
}
|
||||
|
||||
EXPORT void my__ZdlPvSt11align_val_tRKSt9nothrow_t(void* p, size_t align, void* n) //operator delete(void*, std::align_val_t, std::nothrow_t const&)
|
||||
{
|
||||
(void)align; (void)n;
|
||||
if(malloc_hack_2 && p) {
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real__ZdlPvSt11align_val_tRKSt9nothrow_t)
|
||||
RunFunctionFmt(real__ZdlPvSt11align_val_tRKSt9nothrow_t, "pLp", p, align, n);
|
||||
return;
|
||||
}
|
||||
}
|
||||
box_free(p);
|
||||
}
|
||||
|
||||
@@ -360,13 +567,11 @@ EXPORT void my_tc_deletearray(void* p)
|
||||
|
||||
EXPORT void my_tc_deletearray_nothrow(void* p, void* n)
|
||||
{
|
||||
(void)n;
|
||||
box_free(p);
|
||||
}
|
||||
|
||||
EXPORT void my_tc_delete_nothrow(void* p, void* n)
|
||||
{
|
||||
(void)n;
|
||||
box_free(p);
|
||||
}
|
||||
|
||||
@@ -392,19 +597,17 @@ EXPORT void* my_tc_new(size_t s)
|
||||
|
||||
EXPORT void* my_tc_new_nothrow(size_t s, void* n)
|
||||
{
|
||||
(void)n;
|
||||
return box_calloc(1, s);
|
||||
return box_calloc(1, s);
|
||||
}
|
||||
|
||||
EXPORT void* my_tc_newarray(size_t s)
|
||||
{
|
||||
return box_calloc(1, s);
|
||||
return box_calloc(1, s);
|
||||
}
|
||||
|
||||
EXPORT void* my_tc_newarray_nothrow(size_t s, void* n)
|
||||
{
|
||||
(void)n;
|
||||
return box_calloc(1, s);
|
||||
return box_calloc(1, s);
|
||||
}
|
||||
|
||||
EXPORT void* my_tc_pvalloc(size_t size)
|
||||
@@ -429,7 +632,6 @@ EXPORT void* my_tc_malloc_skip_new_handler_weak(size_t s)
|
||||
|
||||
EXPORT int my_tc_mallocopt(int param, int value)
|
||||
{
|
||||
(void)param; (void)value;
|
||||
// ignoring...
|
||||
return 1;
|
||||
}
|
||||
@@ -478,66 +680,129 @@ EXPORT void* my_tc_realloc(void* p, size_t s)
|
||||
/*
|
||||
EXPORT int my_tc_version(int i)
|
||||
{
|
||||
(void)i;
|
||||
return 2;
|
||||
}
|
||||
*/
|
||||
|
||||
EXPORT void* my_safer_scalable_aligned_realloc(void* p, size_t size, size_t align, void *old)
|
||||
{
|
||||
if(!ispot(align)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if(align <= 8)
|
||||
return box_realloc(p, size);
|
||||
size_t old_size = box_malloc_usable_size(p);
|
||||
if(old_size>=size)
|
||||
return p;
|
||||
void* new_p = box_memalign(align, size);
|
||||
memcpy(new_p, p, (old_size<size)?old_size:size);
|
||||
box_free(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
EXPORT void my_safer_scalable_free(void*p , void* old)
|
||||
{
|
||||
box_free(p);
|
||||
}
|
||||
|
||||
EXPORT size_t my_safer_scalable_msize(void* p, void* old)
|
||||
{
|
||||
return box_malloc_usable_size(p);
|
||||
}
|
||||
|
||||
EXPORT void* my_safer_scalable_realloc(void* p, size_t size, void* old)
|
||||
{
|
||||
return box_realloc(p, size);
|
||||
}
|
||||
|
||||
EXPORT void my_scalable_aligned_free(void* p)
|
||||
{
|
||||
box_free(p);
|
||||
}
|
||||
|
||||
EXPORT void* my_scalable_aligned_malloc(size_t size, size_t align)
|
||||
{
|
||||
if(!ispot(align)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if(align <= 8)
|
||||
return box_malloc(size);
|
||||
return box_memalign(align, size);
|
||||
}
|
||||
|
||||
EXPORT void* my_scalable_aligned_realloc(void* p, size_t size, size_t align)
|
||||
{
|
||||
if(!ispot(align)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if(align <= 8)
|
||||
return box_realloc(p, size);
|
||||
size_t old_size = box_malloc_usable_size(p);
|
||||
if(old_size>=size)
|
||||
return p;
|
||||
void* new_p = box_memalign(align, size);
|
||||
memcpy(new_p, p, (old_size<size)?old_size:size);
|
||||
box_free(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
EXPORT size_t my_scalable_msize(void* p)
|
||||
{
|
||||
return box_malloc_usable_size(p);
|
||||
}
|
||||
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct reloc_jmp_s {
|
||||
uint8_t _ff;
|
||||
uint8_t _25;
|
||||
uint32_t _00;
|
||||
void* addr;
|
||||
} reloc_jmp_t;
|
||||
typedef struct simple_jmp_s {
|
||||
uint8_t _e9;
|
||||
uint32_t delta;
|
||||
} simple_jmp_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
static void addRelocJmp(void* offs, void* where, size_t size, const char* name)
|
||||
static void addRelocJmp(void* offs, void* where, size_t size, const char* name, elfheader_t* h, uintptr_t *real)
|
||||
{
|
||||
simple_jmp_t s_jmp = {0};
|
||||
size_t sz = 0;
|
||||
intptr_t off32 = (intptr_t)where - ((intptr_t)offs+5);
|
||||
void* p = NULL;
|
||||
s_jmp._e9 = 0xe9;
|
||||
s_jmp.delta = (uint32_t)off32;
|
||||
p = &s_jmp;
|
||||
sz = sizeof(s_jmp);
|
||||
if(size>=sz)
|
||||
memcpy(offs, p, sz);
|
||||
else {
|
||||
printf_log(LOG_INFO, "Warning, cannot redirect %s, too small %zu vs %zu\n", name, size, sz);
|
||||
if(real && !*real) {
|
||||
*real = (uintptr_t)offs;
|
||||
}
|
||||
addAlternate(offs, where);
|
||||
}
|
||||
|
||||
void checkHookedSymbols(lib_t *maplib, elfheader_t* h)
|
||||
void checkHookedSymbols(elfheader_t* h)
|
||||
{
|
||||
(void)maplib;
|
||||
int hooked = 0;
|
||||
for (uint32_t i=0; i<h->numDynSym && hooked<2; ++i) {
|
||||
if(box86_malloc_hack==1)
|
||||
return;
|
||||
for (size_t i=0; i<h->numDynSym && hooked<2; ++i) {
|
||||
const char * symname = h->DynStr+h->DynSym[i].st_name;
|
||||
int bind = ELF64_ST_BIND(h->DynSym[i].st_info);
|
||||
int type = ELF64_ST_TYPE(h->DynSym[i].st_info);
|
||||
int vis = h->DynSym[i].st_other&0x3;
|
||||
if((type==STT_FUNC)
|
||||
&& (vis==STV_DEFAULT || vis==STV_PROTECTED) && (h->DynSym[i].st_shndx!=0 && h->DynSym[i].st_shndx<=65521)) {
|
||||
// uintptr_t offs = h->DynSym[i].st_value + h->delta;
|
||||
uintptr_t offs = h->DynSym[i].st_value + h->delta;
|
||||
size_t sz = h->DynSym[i].st_size;
|
||||
if(bind!=STB_LOCAL && bind!=STB_WEAK && sz>=sizeof(simple_jmp_t)) {
|
||||
#define GO(A, B) if(!strcmp(symname, #A)) ++hooked;
|
||||
if(bind!=STB_LOCAL && bind!=STB_WEAK && sz>=sizeof(reloc_jmp_t)) {
|
||||
#define GO(A, B) if(!strcmp(symname, #A)) ++hooked; else if(!strcmp(symname, "__libc_" #A)) ++hooked;
|
||||
#define GO2(A, B)
|
||||
#define GO2S(A, B)
|
||||
SUPER()
|
||||
#undef GO
|
||||
#undef GO2
|
||||
#undef GO2S
|
||||
}
|
||||
}
|
||||
}
|
||||
if(hooked<2)
|
||||
return; // only redirect on lib that hooked / redefined the operators
|
||||
printf_log(LOG_INFO, "Redirecting overriden malloc function for %s\n", ElfName(h));
|
||||
for (uint32_t i=0; i<h->numDynSym; ++i) {
|
||||
printf_log(LOG_INFO, "Redirecting overridden malloc%s function for %s\n", malloc_hack_2?" with hack":"", ElfName(h));
|
||||
for (size_t i=0; i<h->numDynSym; ++i) {
|
||||
const char * symname = h->DynStr+h->DynSym[i].st_name;
|
||||
int bind = ELF64_ST_BIND(h->DynSym[i].st_info);
|
||||
int type = ELF64_ST_TYPE(h->DynSym[i].st_info);
|
||||
@@ -547,29 +812,77 @@ void checkHookedSymbols(lib_t *maplib, elfheader_t* h)
|
||||
uintptr_t offs = h->DynSym[i].st_value + h->delta;
|
||||
size_t sz = h->DynSym[i].st_size;
|
||||
if(bind!=STB_LOCAL && bind!=STB_WEAK) {
|
||||
#define GO(A, B) if(!strcmp(symname, "__libc_" #A)) {uintptr_t alt = AddCheckBridge(my_context->system, B, A, 0, #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, #A);}
|
||||
#define GO(A, B) if(!strcmp(symname, "__libc_" #A)) {uintptr_t alt = AddCheckBridge(my_context->system, B, A, 0, #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, "__libc_" #A, h, NULL);}
|
||||
#define GO2(A, B)
|
||||
#define GO2S(A, B)
|
||||
SUPER()
|
||||
#undef GO
|
||||
#undef GO2
|
||||
#undef GO2S
|
||||
#define GO(A, B) if(!strcmp(symname, #A)) {uintptr_t alt = AddCheckBridge(my_context->system, B, A, 0, #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, #A);}
|
||||
#define GO2(A, B) if(!strcmp(symname, #A)) {uintptr_t alt = AddCheckBridge(my_context->system, B, my_##A, 0, #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, #A);}
|
||||
#define GO2S(A, B) if(!strcmp(symname, #A)) {uintptr_t alt = AddCheckBridge(my_context->system, B, my_##A, 4, #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, #A);}
|
||||
#define GO(A, B) if(!strcmp(symname, #A)) {uintptr_t alt = AddCheckBridge(my_context->system, B, A, 0, #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, #A, h, &real_##A);}
|
||||
#define GO2(A, B) if(!strcmp(symname, #A)) {uintptr_t alt = AddCheckBridge(my_context->system, B, my_##A, 0, "my_" #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, "my_" #A, h, &real_##A);}
|
||||
SUPER()
|
||||
#undef GO
|
||||
#undef GO2
|
||||
#undef GO2S
|
||||
}
|
||||
}
|
||||
}
|
||||
if(box86_malloc_hack==2)
|
||||
h->malloc_hook_2 = 1;
|
||||
}
|
||||
|
||||
void startMallocHook()
|
||||
{
|
||||
malloc_hack_2 = 1;
|
||||
}
|
||||
void endMallocHook()
|
||||
{
|
||||
malloc_hack_2 = 0;
|
||||
}
|
||||
|
||||
EXPORT int my___TBB_internal_find_original_malloc(int n, char* names[], void* ptr[])
|
||||
{
|
||||
int ret = 1;
|
||||
#define GO(A, B) else if(!strcmp(names[i], #A)) {ptr[i] = A;}
|
||||
#define GO2(A, B)
|
||||
for (int i=0; i<n; ++i)
|
||||
if (0) {}
|
||||
SUPER()
|
||||
else ret = 0;
|
||||
return ret;
|
||||
#undef GO
|
||||
#undef GO2
|
||||
}
|
||||
|
||||
EXPORT void my___TBB_call_with_my_server_info(void* cb, void* server)
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
EXPORT int my___TBB_make_rml_server(void* factory, void* server, void* client)
|
||||
{
|
||||
// nothing
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT void my___RML_close_factory(void* server)
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
EXPORT int my___RML_open_factory(void* factory, void* server_version, int client_version)
|
||||
{
|
||||
// nothing
|
||||
return 0;
|
||||
}
|
||||
|
||||
void init_malloc_hook() {
|
||||
#ifndef ANDROID
|
||||
box_malloc_usable_size = dlsym(RTLD_NEXT, "malloc_usable_size");
|
||||
#ifdef ANDROID
|
||||
__libc_malloc = dlsym(RTLD_NEXT, "malloc");
|
||||
__libc_realloc = dlsym(RTLD_NEXT, "realloc");
|
||||
__libc_calloc = dlsym(RTLD_NEXT, "calloc");
|
||||
__libc_free = dlsym(RTLD_NEXT, "free");
|
||||
__libc_memalign = dlsym(RTLD_NEXT, "memalign");
|
||||
#endif
|
||||
box_malloc_usable_size = dlsym(RTLD_NEXT, "malloc_usable_size");
|
||||
#if 0
|
||||
#define GO(A, B)
|
||||
#define GO2(A, B) box_##A = (B##_t)dlsym(RTLD_NEXT, #A); if(box_##A == (B##_t)A) box_##A = NULL;
|
||||
@@ -579,4 +892,4 @@ void init_malloc_hook() {
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef SUPER
|
||||
#undef SUPER
|
||||
+2
-3
@@ -126,7 +126,6 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
|
||||
uintptr_t CheckBridged(bridge_t* bridge, void* fnc)
|
||||
{
|
||||
// check if function alread have a bridge (the function wrapper will not be tested)
|
||||
if (!fnc) return 0;
|
||||
khint_t k = kh_get(bridgemap, bridge->bridgemap, (uint32_t)fnc);
|
||||
if(k==kh_end(bridge->bridgemap))
|
||||
return 0;
|
||||
@@ -151,13 +150,13 @@ uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const
|
||||
return ret;
|
||||
}
|
||||
|
||||
uintptr_t AddAutomaticBridge(x86emu_t* emu, bridge_t* bridge, wrapper_t w, void* fnc, int N)
|
||||
uintptr_t AddAutomaticBridge(x86emu_t* emu, bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name)
|
||||
{
|
||||
if(!fnc)
|
||||
return 0;
|
||||
uintptr_t ret = CheckBridged(bridge, fnc);
|
||||
if(!ret)
|
||||
ret = AddBridge(bridge, w, fnc, N, NULL);
|
||||
ret = AddBridge(bridge, w, fnc, N, name);
|
||||
if(!hasAlternate(fnc)) {
|
||||
printf_log(LOG_DEBUG, "Adding AutomaticBridge for %p to %p\n", fnc, (void*)ret);
|
||||
addAlternate(fnc, (void*)ret);
|
||||
|
||||
+157
-6
@@ -14,9 +14,8 @@
|
||||
#include "dynarec.h"
|
||||
|
||||
EXPORTDYN
|
||||
uint32_t RunSafeFunction(box86context_t *context, uintptr_t fnc, int nargs, ...)
|
||||
uint32_t RunSafeFunction(uintptr_t fnc, int nargs, ...)
|
||||
{
|
||||
(void)context;
|
||||
x86emu_t *emu = thread_get_emu();
|
||||
|
||||
Push(emu, R_EBP); // push rbp
|
||||
@@ -62,9 +61,8 @@ uint32_t RunSafeFunction(box86context_t *context, uintptr_t fnc, int nargs, ...)
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
uint32_t RunFunction(box86context_t *context, uintptr_t fnc, int nargs, ...)
|
||||
uint32_t RunFunction(uintptr_t fnc, int nargs, ...)
|
||||
{
|
||||
(void)context;
|
||||
x86emu_t *emu = thread_get_emu();
|
||||
|
||||
R_ESP -= nargs*4; // need to push in reverse order
|
||||
@@ -88,9 +86,8 @@ uint32_t RunFunction(box86context_t *context, uintptr_t fnc, int nargs, ...)
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
uint64_t RunFunction64(box86context_t *context, uintptr_t fnc, int nargs, ...)
|
||||
uint64_t RunFunction64(uintptr_t fnc, int nargs, ...)
|
||||
{
|
||||
(void)context;
|
||||
x86emu_t *emu = thread_get_emu();
|
||||
|
||||
R_ESP -= nargs*4; // need to push in reverse order
|
||||
@@ -113,6 +110,160 @@ uint64_t RunFunction64(box86context_t *context, uintptr_t fnc, int nargs, ...)
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
uint32_t RunFunctionFmt(uintptr_t fnc, const char* fmt, ...)
|
||||
{
|
||||
x86emu_t *emu = thread_get_emu();
|
||||
int nargs = 0;
|
||||
int ni = 0;
|
||||
int ndf = 0;
|
||||
for (int i=0; fmt[i]; ++i) {
|
||||
switch(fmt[i]) {
|
||||
case 'd':
|
||||
case 'I':
|
||||
case 'U': nargs+=2; break;
|
||||
case 'f':
|
||||
case 'p':
|
||||
case 'i':
|
||||
case 'u':
|
||||
case 'L':
|
||||
case 'l':
|
||||
case 'w':
|
||||
case 'W':
|
||||
case 'c':
|
||||
case 'C': ++nargs; break;
|
||||
default:
|
||||
++nargs; break;
|
||||
}
|
||||
}
|
||||
int align = nargs&1;
|
||||
int stackn = align + nargs;
|
||||
|
||||
Push(emu, R_EBP); // push ebp
|
||||
R_EBP = R_ESP; // mov ebp, esp
|
||||
|
||||
R_ESP -= stackn*sizeof(void*); // need to push in reverse order
|
||||
|
||||
uint32_t *p = (uint32_t*)R_ESP;
|
||||
|
||||
#define GO(c, B, B2, N) case c: *((B*)p) = va_arg(va, B2); p+=N; break
|
||||
va_list va;
|
||||
va_start (va, fmt);
|
||||
for (int i=0; fmt[i]; ++i) {
|
||||
switch(fmt[i]) {
|
||||
GO('f', float, double, 1);
|
||||
GO('d', double, double, 2);
|
||||
GO('p', void*, void*, 1);
|
||||
GO('i', int, int, 1);
|
||||
GO('u', uint32_t, uint32_t, 1);
|
||||
GO('I', int64_t, int64_t, 2);
|
||||
GO('U', uint64_t, uint64_t, 2);
|
||||
GO('L', uint32_t, uint32_t, 1);
|
||||
GO('l', int32_t, int32_t, 1);
|
||||
GO('w', int16_t, int, 1);
|
||||
GO('W', uint16_t, int, 1);
|
||||
GO('c', int8_t, int, 1);
|
||||
GO('C', uint8_t, int, 1);
|
||||
default:
|
||||
printf_log(LOG_NONE, "Error, unhandled arg %d: '%c' in RunFunctionFmt\n", i, fmt[i]);
|
||||
*p = va_arg(va, uint32_t);
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
va_end (va);
|
||||
|
||||
uintptr_t oldip = R_EIP;
|
||||
DynaCall(emu, fnc);
|
||||
R_ESP+=(nargs*4);
|
||||
|
||||
if(oldip==R_EIP) {
|
||||
R_ESP = R_EBP; // mov esp, ebp
|
||||
R_EBP = Pop(emu); // pop ebp
|
||||
}
|
||||
|
||||
uint32_t ret = R_EAX;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
uint64_t RunFunctionFmt64(uintptr_t fnc, const char* fmt, ...)
|
||||
{
|
||||
x86emu_t *emu = thread_get_emu();
|
||||
int nargs = 0;
|
||||
int ni = 0;
|
||||
int ndf = 0;
|
||||
for (int i=0; fmt[i]; ++i) {
|
||||
switch(fmt[i]) {
|
||||
case 'd':
|
||||
case 'I':
|
||||
case 'U': nargs+=2; break;
|
||||
case 'f':
|
||||
case 'p':
|
||||
case 'i':
|
||||
case 'u':
|
||||
case 'L':
|
||||
case 'l':
|
||||
case 'w':
|
||||
case 'W':
|
||||
case 'c':
|
||||
case 'C': ++nargs; break;
|
||||
default:
|
||||
++nargs; break;
|
||||
}
|
||||
}
|
||||
int align = nargs&1;
|
||||
int stackn = align + nargs;
|
||||
|
||||
Push(emu, R_EBP); // push ebp
|
||||
R_EBP = R_ESP; // mov ebp, esp
|
||||
|
||||
R_ESP -= stackn*sizeof(void*); // need to push in reverse order
|
||||
|
||||
uint32_t *p = (uint32_t*)R_ESP;
|
||||
|
||||
#define GO(c, B, B2, N) case c: *((B*)p) = va_arg(va, B2); p+=N; break
|
||||
va_list va;
|
||||
va_start (va, fmt);
|
||||
for (int i=0; fmt[i]; ++i) {
|
||||
switch(fmt[i]) {
|
||||
GO('f', float, double, 1);
|
||||
GO('d', double, double, 2);
|
||||
GO('p', void*, void*, 1);
|
||||
GO('i', int, int, 1);
|
||||
GO('u', uint32_t, uint32_t, 1);
|
||||
GO('I', int64_t, int64_t, 2);
|
||||
GO('U', uint64_t, uint64_t, 2);
|
||||
GO('L', uint32_t, uint32_t, 1);
|
||||
GO('l', int32_t, int32_t, 1);
|
||||
GO('w', int16_t, int, 1);
|
||||
GO('W', uint16_t, int, 1);
|
||||
GO('c', int8_t, int, 1);
|
||||
GO('C', uint8_t, int, 1);
|
||||
default:
|
||||
printf_log(LOG_NONE, "Error, unhandled arg %d: '%c' in RunFunctionFmt\n", i, fmt[i]);
|
||||
*p = va_arg(va, uint32_t);
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
va_end (va);
|
||||
|
||||
uintptr_t oldip = R_EIP;
|
||||
DynaCall(emu, fnc);
|
||||
R_ESP+=(nargs*4);
|
||||
|
||||
if(oldip==R_EIP) {
|
||||
R_ESP = R_EBP; // mov esp, ebp
|
||||
R_EBP = Pop(emu); // pop ebp
|
||||
}
|
||||
|
||||
uint64_t ret = (uint64_t)R_EAX | ((uint64_t)R_EDX)<<32;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
uint32_t RunFunctionWithEmu(x86emu_t *emu, int QuitOnLongJump, uintptr_t fnc, int nargs, ...)
|
||||
{
|
||||
|
||||
@@ -50,7 +50,8 @@ char* ResolveFile(const char* filename, path_collection_t* paths)
|
||||
for (int i=0; i<paths->size; ++i) {
|
||||
if(paths->paths[i][0]!='/') {
|
||||
// not an absolute path...
|
||||
getcwd(p, sizeof(p));
|
||||
char* dummy = getcwd(p, sizeof(p));
|
||||
(void)dummy;
|
||||
if(p[strlen(p)-1]!='/')
|
||||
strcat(p, "/");
|
||||
strcat(p, paths->paths[i]);
|
||||
|
||||
+344
-344
@@ -57,7 +57,7 @@ static uintptr_t my_##NAME##_fct_##A = 0; \
|
||||
static RET my_##NAME##_##A DEF \
|
||||
{ \
|
||||
printf_log(LOG_DEBUG, "Calling " #NAME "_" #A " wrapper\n"); \
|
||||
return (RET)RunFunction(my_context, my_##NAME##_fct_##A, N, __VA_ARGS__);\
|
||||
return (RET)RunFunctionFmt(my_##NAME##_fct_##A, N, __VA_ARGS__);\
|
||||
}
|
||||
|
||||
#define FIND(A, NAME) \
|
||||
@@ -110,7 +110,7 @@ static void autobridge_##NAME##_##A(wrapper_t W, void* fct) \
|
||||
fct = GetNativeFnc((uintptr_t)fct); \
|
||||
if(!fct) \
|
||||
return; \
|
||||
AddAutomaticBridge(thread_get_emu(), my_bridge, W, fct, 0); \
|
||||
AddAutomaticBridge(thread_get_emu(), my_bridge, W, fct, 0, #NAME "_" #A); \
|
||||
}
|
||||
|
||||
#define WRAPPER(A, NAME, RET, DEF, N, ...) \
|
||||
@@ -128,14 +128,14 @@ AUTOBRIDGE(A, NAME)
|
||||
|
||||
// ----- GObjectClass ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GObject, constructor, void*, (int type, uint32_t n_construct_properties, void* construct_properties), 3, type, n_construct_properties, construct_properties);
|
||||
WRAPPER(GObject, set_property, void, (void* object, uint32_t property_id, void* value, void* pspec), 4, object, property_id, value, pspec);
|
||||
WRAPPER(GObject, get_property, void, (void* object, uint32_t property_id, void* value, void* pspec), 4, object, property_id, value, pspec);
|
||||
WRAPPER(GObject, dispose, void, (void* object), 1, object);
|
||||
WRAPPER(GObject, finalize, void, (void* object), 1, object);
|
||||
WRAPPER(GObject, dispatch_properties_changed, void*, (int type, uint32_t n_pspecs, void* pspecs), 3, type, n_pspecs, pspecs);
|
||||
WRAPPER(GObject, notify, void*, (int type, void* pspecs), 2, type, pspecs);
|
||||
WRAPPER(GObject, constructed, void, (void* object), 1, object);
|
||||
WRAPPER(GObject, constructor, void*, (int type, uint32_t n_construct_properties, void* construct_properties), "iup", type, n_construct_properties, construct_properties);
|
||||
WRAPPER(GObject, set_property, void, (void* object, uint32_t property_id, void* value, void* pspec), "pupp", object, property_id, value, pspec);
|
||||
WRAPPER(GObject, get_property, void, (void* object, uint32_t property_id, void* value, void* pspec), "pupp", object, property_id, value, pspec);
|
||||
WRAPPER(GObject, dispose, void, (void* object), "p", object);
|
||||
WRAPPER(GObject, finalize, void, (void* object), "p", object);
|
||||
WRAPPER(GObject, dispatch_properties_changed, void*, (int type, uint32_t n_pspecs, void* pspecs), "iup", type, n_pspecs, pspecs);
|
||||
WRAPPER(GObject, notify, void*, (int type, void* pspecs), "ip", type, pspecs);
|
||||
WRAPPER(GObject, constructed, void, (void* object), "p", object);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(constructor, pFiup); \
|
||||
@@ -172,14 +172,14 @@ static void bridgeGObjectClass(my_GObjectClass_t* class)
|
||||
|
||||
// ----- GInitiallyUnownedClass ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GInitiallyUnowned, constructor, void*, (int type, uint32_t n_construct_properties, void* construct_properties), 3, type, n_construct_properties, construct_properties);
|
||||
WRAPPER(GInitiallyUnowned, set_property, void, (void* object, uint32_t property_id, void* value, void* pspec), 4, object, property_id, value, pspec);
|
||||
WRAPPER(GInitiallyUnowned, get_property, void, (void* object, uint32_t property_id, void* value, void* pspec), 4, object, property_id, value, pspec);
|
||||
WRAPPER(GInitiallyUnowned, dispose, void, (void* object), 1, object);
|
||||
WRAPPER(GInitiallyUnowned, finalize, void, (void* object), 1, object);
|
||||
WRAPPER(GInitiallyUnowned, dispatch_properties_changed, void*, (int type, uint32_t n_pspecs, void* pspecs), 3, type, n_pspecs, pspecs);
|
||||
WRAPPER(GInitiallyUnowned, notify, void*, (int type, void* pspecs), 2, type, pspecs);
|
||||
WRAPPER(GInitiallyUnowned, constructed, void, (void* object), 1, object);
|
||||
WRAPPER(GInitiallyUnowned, constructor, void*, (int type, uint32_t n_construct_properties, void* construct_properties), "iup", type, n_construct_properties, construct_properties);
|
||||
WRAPPER(GInitiallyUnowned, set_property, void, (void* object, uint32_t property_id, void* value, void* pspec), "pupp", object, property_id, value, pspec);
|
||||
WRAPPER(GInitiallyUnowned, get_property, void, (void* object, uint32_t property_id, void* value, void* pspec), "pupp", object, property_id, value, pspec);
|
||||
WRAPPER(GInitiallyUnowned, dispose, void, (void* object), "p", object);
|
||||
WRAPPER(GInitiallyUnowned, finalize, void, (void* object), "p", object);
|
||||
WRAPPER(GInitiallyUnowned, dispatch_properties_changed, void*, (int type, uint32_t n_pspecs, void* pspecs), "iup", type, n_pspecs, pspecs);
|
||||
WRAPPER(GInitiallyUnowned, notify, void*, (int type, void* pspecs), "ip", type, pspecs);
|
||||
WRAPPER(GInitiallyUnowned, constructed, void, (void* object), "p", object);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(constructor, pFiup); \
|
||||
@@ -216,9 +216,9 @@ static void bridgeGInitiallyUnownedClass(my_GInitiallyUnownedClass_t* class)
|
||||
|
||||
// ----- GtkObjectClass ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GtkObject, set_arg, void, (void* object, void* arg, uint32_t arg_id), 3, object, arg, arg_id);
|
||||
WRAPPER(GtkObject, get_arg, void, (void* object, void* arg, uint32_t arg_id), 3, object, arg, arg_id);
|
||||
WRAPPER(GtkObject, destroy, void, (void* object), 1, object);
|
||||
WRAPPER(GtkObject, set_arg, void, (void* object, void* arg, uint32_t arg_id), "ppu", object, arg, arg_id);
|
||||
WRAPPER(GtkObject, get_arg, void, (void* object, void* arg, uint32_t arg_id), "ppu", object, arg, arg_id);
|
||||
WRAPPER(GtkObject, destroy, void, (void* object), "p", object);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(set_arg, vFppu); \
|
||||
@@ -253,72 +253,72 @@ static void bridgeGtkObjectClass(my_GtkObjectClass_t* class)
|
||||
|
||||
// ----- GtkWidget2Class ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GtkWidget2, dispatch_child_properties_changed, void, (void* widget, uint32_t n_pspecs, void* pspecs), 3, widget, n_pspecs, pspecs);
|
||||
WRAPPER(GtkWidget2, show, void, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget2, show_all, void, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget2, hide, void, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget2, hide_all, void, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget2, map, void, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget2, unmap, void, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget2, realize, void, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget2, unrealize, void, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget2, size_request, void, (void* widget, void* requisition), 2, widget, requisition);
|
||||
WRAPPER(GtkWidget2, size_allocate, void, (void* widget, void* allocation), 2, widget, allocation);
|
||||
WRAPPER(GtkWidget2, state_changed, void, (void* widget, int previous_state), 2, widget, previous_state);
|
||||
WRAPPER(GtkWidget2, parent_set, void, (void* widget, void* previous_parent), 2, widget, previous_parent);
|
||||
WRAPPER(GtkWidget2, hierarchy_changed, void, (void* widget, void* previous_toplevel), 2, widget, previous_toplevel);
|
||||
WRAPPER(GtkWidget2, style_set, void, (void* widget, void* previous_style), 2, widget, previous_style);
|
||||
WRAPPER(GtkWidget2, direction_changed, void, (void* widget, int previous_direction), 2, widget, previous_direction);
|
||||
WRAPPER(GtkWidget2, grab_notify, void, (void* widget, int was_grabbed), 2, widget, was_grabbed);
|
||||
WRAPPER(GtkWidget2, child_notify, void, (void* widget, void* pspec), 2, widget, pspec);
|
||||
WRAPPER(GtkWidget2, mnemonic_activate, int, (void* widget, int group_cycling), 2, widget, group_cycling);
|
||||
WRAPPER(GtkWidget2, grab_focus, void, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget2, focus, int, (void* widget, int direction), 2, widget, direction);
|
||||
WRAPPER(GtkWidget2, event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, button_press_event,int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, button_release_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, scroll_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, motion_notify_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, delete_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, destroy_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, expose_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, key_press_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, key_release_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, enter_notify_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, leave_notify_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, configure_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, focus_in_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, focus_out_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, map_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, unmap_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, property_notify_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, selection_clear_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, selection_request_event,int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, selection_notify_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, proximity_in_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, proximity_out_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, visibility_notify_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, client_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, no_expose_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, window_state_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, selection_get, void, (void* widget, void* selection_data, uint32_t info, uint32_t time_), 4, widget, selection_data, info, time_);
|
||||
WRAPPER(GtkWidget2, selection_received, void, (void* widget, void* selection_data, uint32_t time_), 3, widget, selection_data, time_);
|
||||
WRAPPER(GtkWidget2, drag_begin, void, (void* widget, void* context), 2, widget, context);
|
||||
WRAPPER(GtkWidget2, drag_end, void, (void* widget, void* context), 2, widget, context);
|
||||
WRAPPER(GtkWidget2, drag_data_get, void, (void* widget, void* context, void* selection_data, uint32_t info, uint32_t time_), 5, widget, context, selection_data, info, time_);
|
||||
WRAPPER(GtkWidget2, drag_data_delete, void, (void* widget, void* context), 2, widget, context);
|
||||
WRAPPER(GtkWidget2, drag_leave, void, (void* widget, void* context, uint32_t time_), 3, widget, context, time_);
|
||||
WRAPPER(GtkWidget2, drag_motion, int, (void* widget, void* context, int32_t x, int32_t y, uint32_t time_), 5, widget, context, x, y, time_);
|
||||
WRAPPER(GtkWidget2, drag_drop, int, (void* widget, void* context, int32_t x, int32_t y, uint32_t time_), 5, widget, context, x, y, time_);
|
||||
WRAPPER(GtkWidget2, drag_data_received, void, (void* widget, void* context, int32_t x, int32_t y, void* selection_data, uint32_t info, uint32_t time_), 7, widget, context, x, y, selection_data, info, time_);
|
||||
WRAPPER(GtkWidget2, popup_menu, int , (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget2, show_help, int , (void* widget, int help_type), 2, widget, help_type);
|
||||
WRAPPER(GtkWidget2, get_accessible, void*, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget2, screen_changed, void , (void* widget, void* previous_screen), 2, widget, previous_screen);
|
||||
WRAPPER(GtkWidget2, can_activate_accel, int , (void* widget, uint32_t signal_id), 2, widget, signal_id);
|
||||
WRAPPER(GtkWidget2, grab_broken_event, int , (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget2, composited_changed, void , (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget2, query_tooltip, int , (void* widget, int32_t x, int32_t y, int keyboard_tooltip, void* tooltip), 5, widget, x, y, keyboard_tooltip, tooltip);
|
||||
WRAPPER(GtkWidget2, dispatch_child_properties_changed, void, (void* widget, uint32_t n_pspecs, void* pspecs), "pup", widget, n_pspecs, pspecs);
|
||||
WRAPPER(GtkWidget2, show, void, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget2, show_all, void, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget2, hide, void, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget2, hide_all, void, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget2, map, void, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget2, unmap, void, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget2, realize, void, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget2, unrealize, void, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget2, size_request, void, (void* widget, void* requisition), "pp", widget, requisition);
|
||||
WRAPPER(GtkWidget2, size_allocate, void, (void* widget, void* allocation), "pp", widget, allocation);
|
||||
WRAPPER(GtkWidget2, state_changed, void, (void* widget, int previous_state), "pi", widget, previous_state);
|
||||
WRAPPER(GtkWidget2, parent_set, void, (void* widget, void* previous_parent), "pp", widget, previous_parent);
|
||||
WRAPPER(GtkWidget2, hierarchy_changed, void, (void* widget, void* previous_toplevel), "pp", widget, previous_toplevel);
|
||||
WRAPPER(GtkWidget2, style_set, void, (void* widget, void* previous_style), "pp", widget, previous_style);
|
||||
WRAPPER(GtkWidget2, direction_changed, void, (void* widget, int previous_direction), "pi", widget, previous_direction);
|
||||
WRAPPER(GtkWidget2, grab_notify, void, (void* widget, int was_grabbed), "pi", widget, was_grabbed);
|
||||
WRAPPER(GtkWidget2, child_notify, void, (void* widget, void* pspec), "pp", widget, pspec);
|
||||
WRAPPER(GtkWidget2, mnemonic_activate, int, (void* widget, int group_cycling), "pi", widget, group_cycling);
|
||||
WRAPPER(GtkWidget2, grab_focus, void, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget2, focus, int, (void* widget, int direction), "pi", widget, direction);
|
||||
WRAPPER(GtkWidget2, event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, button_press_event,int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, button_release_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, scroll_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, motion_notify_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, delete_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, destroy_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, expose_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, key_press_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, key_release_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, enter_notify_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, leave_notify_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, configure_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, focus_in_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, focus_out_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, map_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, unmap_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, property_notify_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, selection_clear_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, selection_request_event,int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, selection_notify_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, proximity_in_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, proximity_out_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, visibility_notify_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, client_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, no_expose_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, window_state_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, selection_get, void, (void* widget, void* selection_data, uint32_t info, uint32_t time_), "ppuu", widget, selection_data, info, time_);
|
||||
WRAPPER(GtkWidget2, selection_received, void, (void* widget, void* selection_data, uint32_t time_), "ppu", widget, selection_data, time_);
|
||||
WRAPPER(GtkWidget2, drag_begin, void, (void* widget, void* context), "pp", widget, context);
|
||||
WRAPPER(GtkWidget2, drag_end, void, (void* widget, void* context), "pp", widget, context);
|
||||
WRAPPER(GtkWidget2, drag_data_get, void, (void* widget, void* context, void* selection_data, uint32_t info, uint32_t time_), "pppuu", widget, context, selection_data, info, time_);
|
||||
WRAPPER(GtkWidget2, drag_data_delete, void, (void* widget, void* context), "pp", widget, context);
|
||||
WRAPPER(GtkWidget2, drag_leave, void, (void* widget, void* context, uint32_t time_), "ppu", widget, context, time_);
|
||||
WRAPPER(GtkWidget2, drag_motion, int, (void* widget, void* context, int32_t x, int32_t y, uint32_t time_), "ppiiu", widget, context, x, y, time_);
|
||||
WRAPPER(GtkWidget2, drag_drop, int, (void* widget, void* context, int32_t x, int32_t y, uint32_t time_), "ppiiu", widget, context, x, y, time_);
|
||||
WRAPPER(GtkWidget2, drag_data_received, void, (void* widget, void* context, int32_t x, int32_t y, void* selection_data, uint32_t info, uint32_t time_), "ppiipuu", widget, context, x, y, selection_data, info, time_);
|
||||
WRAPPER(GtkWidget2, popup_menu, int , (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget2, show_help, int , (void* widget, int help_type), "pi", widget, help_type);
|
||||
WRAPPER(GtkWidget2, get_accessible, void*, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget2, screen_changed, void , (void* widget, void* previous_screen), "pp", widget, previous_screen);
|
||||
WRAPPER(GtkWidget2, can_activate_accel, int , (void* widget, uint32_t signal_id), "pu", widget, signal_id);
|
||||
WRAPPER(GtkWidget2, grab_broken_event, int , (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget2, composited_changed, void , (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget2, query_tooltip, int , (void* widget, int32_t x, int32_t y, int keyboard_tooltip, void* tooltip), "piiip", widget, x, y, keyboard_tooltip, tooltip);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(dispatch_child_properties_changed, vFpup); \
|
||||
@@ -417,88 +417,88 @@ static void bridgeGtkWidget2Class(my_GtkWidget2Class_t* class)
|
||||
|
||||
// ----- GtkWidget3Class ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GtkWidget3, dispatch_child_properties_changed, void, (void* widget, uint32_t n_pspecs, void* pspecs), 3, widget, n_pspecs, pspecs);
|
||||
WRAPPER(GtkWidget3, destroy, void, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget3, show, void, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget3, show_all, void, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget3, hide, void, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget3, map, void, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget3, unmap, void, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget3, realize, void, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget3, unrealize, void, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget3, size_allocate, void, (void* widget, void* allocation), 2, widget, allocation);
|
||||
WRAPPER(GtkWidget3, state_changed, void, (void* widget, int previous_state), 2, widget, previous_state);
|
||||
WRAPPER(GtkWidget3, state_flags_changed, void, (void* widget, int previous_state_flags), 2, widget, previous_state_flags);
|
||||
WRAPPER(GtkWidget3, parent_set, void, (void* widget, void* previous_parent), 2, widget, previous_parent);
|
||||
WRAPPER(GtkWidget3, hierarchy_changed, void, (void* widget, void* previous_toplevel), 2, widget, previous_toplevel);
|
||||
WRAPPER(GtkWidget3, style_set, void, (void* widget, void* previous_style), 2, widget, previous_style);
|
||||
WRAPPER(GtkWidget3, direction_changed, void, (void* widget, int previous_direction), 2, widget, previous_direction);
|
||||
WRAPPER(GtkWidget3, grab_notify, void, (void* widget, int was_grabbed), 2, widget, was_grabbed);
|
||||
WRAPPER(GtkWidget3, child_notify, void, (void* widget, void* child_property), 2, widget, child_property);
|
||||
WRAPPER(GtkWidget3, draw, int, (void* widget, void* cr), 2, widget, cr);
|
||||
WRAPPER(GtkWidget3, get_request_mode, int, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget3, get_preferred_height, void, (void* widget, void* minimum_height, void* natural_height), 3, widget, minimum_height, natural_height);
|
||||
WRAPPER(GtkWidget3, get_preferred_width_for_height, void, (void* widget, int height, void* minimum_width, void* natural_width), 4, widget, height, minimum_width, natural_width);
|
||||
WRAPPER(GtkWidget3, get_preferred_width, void, (void* widget, void* minimum_width, void* natural_width), 3, widget, minimum_width, natural_width);
|
||||
WRAPPER(GtkWidget3, get_preferred_height_for_width, void, (void* widget, int width, void* minimum_height, void* natural_height), 4, widget, width, minimum_height, natural_height);
|
||||
WRAPPER(GtkWidget3, mnemonic_activate, int, (void* widget, int group_cycling), 2, widget, group_cycling);
|
||||
WRAPPER(GtkWidget3, grab_focus, void, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget3, focus, int, (void* widget, int direction), 2, widget, direction);
|
||||
WRAPPER(GtkWidget3, move_focus, void, (void* widget, int direction), 2, widget, direction);
|
||||
WRAPPER(GtkWidget3, keynav_failed, int, (void* widget, int direction), 2, widget, direction);
|
||||
WRAPPER(GtkWidget3, event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, button_press_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, button_release_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, scroll_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, motion_notify_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, delete_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, destroy_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, key_press_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, key_release_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, enter_notify_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, leave_notify_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, configure_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, focus_in_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, focus_out_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, map_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, unmap_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, property_notify_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, selection_clear_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, selection_request_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, selection_notify_event, int,(void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, proximity_in_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, proximity_out_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, visibility_notify_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, window_state_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, damage_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, grab_broken_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, selection_get, void, (void* widget, void* selection_data, uint32_t info, uint32_t time_), 4, widget, selection_data, info, time_);
|
||||
WRAPPER(GtkWidget3, selection_received, void, (void* widget, void* selection_data, uint32_t time_), 3, widget, selection_data, time_);
|
||||
WRAPPER(GtkWidget3, drag_begin, void, (void* widget, void* context), 2, widget, context);
|
||||
WRAPPER(GtkWidget3, drag_end, void, (void* widget, void* context), 2, widget, context);
|
||||
WRAPPER(GtkWidget3, drag_data_get, void, (void* widget, void* context, void* selection_data, uint32_t info, uint32_t time_), 5, widget, context, selection_data, info, time_);
|
||||
WRAPPER(GtkWidget3, drag_data_delete, void, (void* widget, void* context), 2, widget, context);
|
||||
WRAPPER(GtkWidget3, drag_leave, void, (void* widget, void* context, uint32_t time_), 3, widget, context, time_);
|
||||
WRAPPER(GtkWidget3, drag_motion, int, (void* widget, void* context, int x, int y, uint32_t time_), 5, widget, context, x, y, time_);
|
||||
WRAPPER(GtkWidget3, drag_drop, int, (void* widget, void* context, int x, int y, uint32_t time_), 5, widget, context, x, y, time_);
|
||||
WRAPPER(GtkWidget3, drag_data_received, void, (void* widget, void* context, int x, int y, void* selection_data, uint32_t info, uint32_t time_), 7, widget, context, x, y, selection_data, info, time_);
|
||||
WRAPPER(GtkWidget3, drag_failed, int, (void* widget, void* context, int result), 3, widget, context, result);
|
||||
WRAPPER(GtkWidget3, popup_menu, int, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget3, show_help, int, (void* widget, int help_type), 2, widget, help_type);
|
||||
WRAPPER(GtkWidget3, get_accessible, void*, (void *widget), 1, widget);
|
||||
WRAPPER(GtkWidget3, screen_changed, void, (void* widget, void* previous_screen), 2, widget, previous_screen);
|
||||
WRAPPER(GtkWidget3, can_activate_accel, int, (void* widget, uint32_t signal_id), 2, widget, signal_id);
|
||||
WRAPPER(GtkWidget3, composited_changed, void, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget3, query_tooltip, int, (void* widget, int x, int y, int keyboard_tooltip, void* tooltip), 5, widget, x, y, keyboard_tooltip, tooltip);
|
||||
WRAPPER(GtkWidget3, compute_expand, void, (void* widget, void* hexpand_p, void* vexpand_p), 3, widget, hexpand_p, vexpand_p);
|
||||
WRAPPER(GtkWidget3, adjust_size_request, void, (void* widget, int orientation, void* minimum_size, void* natural_size), 4, widget, orientation, minimum_size, natural_size);
|
||||
WRAPPER(GtkWidget3, adjust_size_allocation, void, (void*widget, int orientation, void* minimum_size, void* natural_size, void* allocated_pos, void* allocated_size), 6, widget, orientation, minimum_size, natural_size, allocated_pos, allocated_size);
|
||||
WRAPPER(GtkWidget3, style_updated, void, (void* widget), 1, widget);
|
||||
WRAPPER(GtkWidget3, touch_event, int, (void* widget, void* event), 2, widget, event);
|
||||
WRAPPER(GtkWidget3, get_preferred_height_and_baseline_for_width, void, (void* widget, int width, void* minimum_height, void* natural_height, void* minimum_baseline, void* natural_baseline), 6, widget, width, minimum_height, natural_height, minimum_baseline, natural_baseline);
|
||||
WRAPPER(GtkWidget3, adjust_baseline_request, void, (void* widget, void* minimum_baseline, void* natural_baseline), 3, widget, minimum_baseline, natural_baseline);
|
||||
WRAPPER(GtkWidget3, adjust_baseline_allocation, void, (void* widget, void* baseline), 2, widget, baseline);
|
||||
WRAPPER(GtkWidget3, queue_draw_region, void, (void* widget, void* region), 2, widget, region);
|
||||
WRAPPER(GtkWidget3, dispatch_child_properties_changed, void, (void* widget, uint32_t n_pspecs, void* pspecs), "pup", widget, n_pspecs, pspecs);
|
||||
WRAPPER(GtkWidget3, destroy, void, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget3, show, void, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget3, show_all, void, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget3, hide, void, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget3, map, void, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget3, unmap, void, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget3, realize, void, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget3, unrealize, void, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget3, size_allocate, void, (void* widget, void* allocation), "pp", widget, allocation);
|
||||
WRAPPER(GtkWidget3, state_changed, void, (void* widget, int previous_state), "pi", widget, previous_state);
|
||||
WRAPPER(GtkWidget3, state_flags_changed, void, (void* widget, int previous_state_flags), "pi", widget, previous_state_flags);
|
||||
WRAPPER(GtkWidget3, parent_set, void, (void* widget, void* previous_parent), "pp", widget, previous_parent);
|
||||
WRAPPER(GtkWidget3, hierarchy_changed, void, (void* widget, void* previous_toplevel), "pp", widget, previous_toplevel);
|
||||
WRAPPER(GtkWidget3, style_set, void, (void* widget, void* previous_style), "pp", widget, previous_style);
|
||||
WRAPPER(GtkWidget3, direction_changed, void, (void* widget, int previous_direction), "pi", widget, previous_direction);
|
||||
WRAPPER(GtkWidget3, grab_notify, void, (void* widget, int was_grabbed), "pi", widget, was_grabbed);
|
||||
WRAPPER(GtkWidget3, child_notify, void, (void* widget, void* child_property), "pp", widget, child_property);
|
||||
WRAPPER(GtkWidget3, draw, int, (void* widget, void* cr), "pp", widget, cr);
|
||||
WRAPPER(GtkWidget3, get_request_mode, int, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget3, get_preferred_height, void, (void* widget, void* minimum_height, void* natural_height), "ppp", widget, minimum_height, natural_height);
|
||||
WRAPPER(GtkWidget3, get_preferred_width_for_height, void, (void* widget, int height, void* minimum_width, void* natural_width), "pipp", widget, height, minimum_width, natural_width);
|
||||
WRAPPER(GtkWidget3, get_preferred_width, void, (void* widget, void* minimum_width, void* natural_width), "ppp", widget, minimum_width, natural_width);
|
||||
WRAPPER(GtkWidget3, get_preferred_height_for_width, void, (void* widget, int width, void* minimum_height, void* natural_height), "pipp", widget, width, minimum_height, natural_height);
|
||||
WRAPPER(GtkWidget3, mnemonic_activate, int, (void* widget, int group_cycling), "pi", widget, group_cycling);
|
||||
WRAPPER(GtkWidget3, grab_focus, void, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget3, focus, int, (void* widget, int direction), "pi", widget, direction);
|
||||
WRAPPER(GtkWidget3, move_focus, void, (void* widget, int direction), "pi", widget, direction);
|
||||
WRAPPER(GtkWidget3, keynav_failed, int, (void* widget, int direction), "pi", widget, direction);
|
||||
WRAPPER(GtkWidget3, event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, button_press_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, button_release_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, scroll_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, motion_notify_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, delete_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, destroy_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, key_press_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, key_release_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, enter_notify_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, leave_notify_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, configure_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, focus_in_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, focus_out_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, map_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, unmap_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, property_notify_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, selection_clear_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, selection_request_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, selection_notify_event, int,(void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, proximity_in_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, proximity_out_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, visibility_notify_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, window_state_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, damage_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, grab_broken_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, selection_get, void, (void* widget, void* selection_data, uint32_t info, uint32_t time_), "ppuu", widget, selection_data, info, time_);
|
||||
WRAPPER(GtkWidget3, selection_received, void, (void* widget, void* selection_data, uint32_t time_), "ppu", widget, selection_data, time_);
|
||||
WRAPPER(GtkWidget3, drag_begin, void, (void* widget, void* context), "pp", widget, context);
|
||||
WRAPPER(GtkWidget3, drag_end, void, (void* widget, void* context), "pp", widget, context);
|
||||
WRAPPER(GtkWidget3, drag_data_get, void, (void* widget, void* context, void* selection_data, uint32_t info, uint32_t time_), "pppuu", widget, context, selection_data, info, time_);
|
||||
WRAPPER(GtkWidget3, drag_data_delete, void, (void* widget, void* context), "pp", widget, context);
|
||||
WRAPPER(GtkWidget3, drag_leave, void, (void* widget, void* context, uint32_t time_), "ppu", widget, context, time_);
|
||||
WRAPPER(GtkWidget3, drag_motion, int, (void* widget, void* context, int x, int y, uint32_t time_), "ppiiu", widget, context, x, y, time_);
|
||||
WRAPPER(GtkWidget3, drag_drop, int, (void* widget, void* context, int x, int y, uint32_t time_), "ppiiu", widget, context, x, y, time_);
|
||||
WRAPPER(GtkWidget3, drag_data_received, void, (void* widget, void* context, int x, int y, void* selection_data, uint32_t info, uint32_t time_), "ppiipuu", widget, context, x, y, selection_data, info, time_);
|
||||
WRAPPER(GtkWidget3, drag_failed, int, (void* widget, void* context, int result), "ppi", widget, context, result);
|
||||
WRAPPER(GtkWidget3, popup_menu, int, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget3, show_help, int, (void* widget, int help_type), "pi", widget, help_type);
|
||||
WRAPPER(GtkWidget3, get_accessible, void*, (void *widget), "p", widget);
|
||||
WRAPPER(GtkWidget3, screen_changed, void, (void* widget, void* previous_screen), "pp", widget, previous_screen);
|
||||
WRAPPER(GtkWidget3, can_activate_accel, int, (void* widget, uint32_t signal_id), "pu", widget, signal_id);
|
||||
WRAPPER(GtkWidget3, composited_changed, void, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget3, query_tooltip, int, (void* widget, int x, int y, int keyboard_tooltip, void* tooltip), "piiip", widget, x, y, keyboard_tooltip, tooltip);
|
||||
WRAPPER(GtkWidget3, compute_expand, void, (void* widget, void* hexpand_p, void* vexpand_p), "ppp", widget, hexpand_p, vexpand_p);
|
||||
WRAPPER(GtkWidget3, adjust_size_request, void, (void* widget, int orientation, void* minimum_size, void* natural_size), "pipp", widget, orientation, minimum_size, natural_size);
|
||||
WRAPPER(GtkWidget3, adjust_size_allocation, void, (void*widget, int orientation, void* minimum_size, void* natural_size, void* allocated_pos, void* allocated_size), "pipppp", widget, orientation, minimum_size, natural_size, allocated_pos, allocated_size);
|
||||
WRAPPER(GtkWidget3, style_updated, void, (void* widget), "p", widget);
|
||||
WRAPPER(GtkWidget3, touch_event, int, (void* widget, void* event), "pp", widget, event);
|
||||
WRAPPER(GtkWidget3, get_preferred_height_and_baseline_for_width, void, (void* widget, int width, void* minimum_height, void* natural_height, void* minimum_baseline, void* natural_baseline), "pipppp", widget, width, minimum_height, natural_height, minimum_baseline, natural_baseline);
|
||||
WRAPPER(GtkWidget3, adjust_baseline_request, void, (void* widget, void* minimum_baseline, void* natural_baseline), "ppp", widget, minimum_baseline, natural_baseline);
|
||||
WRAPPER(GtkWidget3, adjust_baseline_allocation, void, (void* widget, void* baseline), "pp", widget, baseline);
|
||||
WRAPPER(GtkWidget3, queue_draw_region, void, (void* widget, void* region), "pp", widget, region);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(dispatch_child_properties_changed, vFpup); \
|
||||
@@ -614,15 +614,15 @@ static void bridgeGtkWidget3Class(my_GtkWidget3Class_t* class)
|
||||
|
||||
// ----- GtkContainer2Class ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GtkContainer2, add, void, (void* container, void* widget), 2, container, widget);
|
||||
WRAPPER(GtkContainer2, remove, void, (void* container, void* widget), 2, container, widget);
|
||||
WRAPPER(GtkContainer2, check_resize, void, (void* container), 1, container);
|
||||
WRAPPER(GtkContainer2, forall, void, (void* container, int include_internals, void* callback, void* callback_data), 4, container, include_internals, AddCheckBridge(my_bridge, vFpp, callback, 0, NULL), callback_data);
|
||||
WRAPPER(GtkContainer2, set_focus_child, void, (void* container, void* widget), 2, container, widget);
|
||||
WRAPPER(GtkContainer2, child_type, int, (void* container), 1, container);
|
||||
WRAPPER(GtkContainer2, composite_name, void*, (void* container, void* child), 2, container, child);
|
||||
WRAPPER(GtkContainer2, set_child_property, void, (void* container, void* child, uint32_t property_id, void* value, void* pspec), 5, container, child, property_id, value, pspec);
|
||||
WRAPPER(GtkContainer2, get_child_property, void, (void* container, void* child, uint32_t property_id, void* value, void* pspec), 5, container, child, property_id, value, pspec);
|
||||
WRAPPER(GtkContainer2, add, void, (void* container, void* widget), "pp", container, widget);
|
||||
WRAPPER(GtkContainer2, remove, void, (void* container, void* widget), "pp", container, widget);
|
||||
WRAPPER(GtkContainer2, check_resize, void, (void* container), "p", container);
|
||||
WRAPPER(GtkContainer2, forall, void, (void* container, int include_internals, void* callback, void* callback_data), "pipp", container, include_internals, AddCheckBridge(my_bridge, vFpp, callback, 0, NULL), callback_data);
|
||||
WRAPPER(GtkContainer2, set_focus_child, void, (void* container, void* widget), "pp", container, widget);
|
||||
WRAPPER(GtkContainer2, child_type, int, (void* container), "p", container);
|
||||
WRAPPER(GtkContainer2, composite_name, void*, (void* container, void* child), "pp", container, child);
|
||||
WRAPPER(GtkContainer2, set_child_property, void, (void* container, void* child, uint32_t property_id, void* value, void* pspec), "ppupp", container, child, property_id, value, pspec);
|
||||
WRAPPER(GtkContainer2, get_child_property, void, (void* container, void* child, uint32_t property_id, void* value, void* pspec), "ppupp", container, child, property_id, value, pspec);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(add, vFpp); \
|
||||
@@ -664,12 +664,12 @@ static void bridgeGtkContainer2Class(my_GtkContainer2Class_t* class)
|
||||
|
||||
// ----- GtkActionClass ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GtkAction, activate, void, (void* action), 1, action);
|
||||
WRAPPER(GtkAction, create_menu_item, void*, (void* action), 1, action);
|
||||
WRAPPER(GtkAction, create_tool_item, void*, (void* action), 1, action);
|
||||
WRAPPER(GtkAction, connect_proxy, void , (void* action, void* proxy), 2, action, proxy);
|
||||
WRAPPER(GtkAction, disconnect_proxy, void , (void* action, void* proxy), 2, action, proxy);
|
||||
WRAPPER(GtkAction, create_menu, void*, (void* action), 1, action);
|
||||
WRAPPER(GtkAction, activate, void, (void* action), "p", action);
|
||||
WRAPPER(GtkAction, create_menu_item, void*, (void* action), "p", action);
|
||||
WRAPPER(GtkAction, create_tool_item, void*, (void* action), "p", action);
|
||||
WRAPPER(GtkAction, connect_proxy, void , (void* action, void* proxy), "pp", action, proxy);
|
||||
WRAPPER(GtkAction, disconnect_proxy, void , (void* action, void* proxy), "pp", action, proxy);
|
||||
WRAPPER(GtkAction, create_menu, void*, (void* action), "p", action);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(activate, vFp); \
|
||||
@@ -726,10 +726,10 @@ static void bridgeGtkMisc2Class(my_GtkMisc2Class_t* class)
|
||||
|
||||
// ----- GtkLabel2Class ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GtkMisc2, move_cursor, void, (void* label, int step, int count, int extend_selection), 4, label, step, count, extend_selection);
|
||||
WRAPPER(GtkMisc2, copy_clipboard, void, (void* label), 1, label);
|
||||
WRAPPER(GtkMisc2, populate_popup, void, (void* label, void* menu), 2, label, menu);
|
||||
WRAPPER(GtkMisc2, activate_link, int, (void* label, void* uri), 2, label, uri);
|
||||
WRAPPER(GtkMisc2, move_cursor, void, (void* label, int step, int count, int extend_selection), "piii", label, step, count, extend_selection);
|
||||
WRAPPER(GtkMisc2, copy_clipboard, void, (void* label), "p", label);
|
||||
WRAPPER(GtkMisc2, populate_popup, void, (void* label, void* menu), "pp", label, menu);
|
||||
WRAPPER(GtkMisc2, activate_link, int, (void* label, void* uri), "pp", label, uri);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(move_cursor, vFpiii); \
|
||||
@@ -765,22 +765,22 @@ static void bridgeGtkLabel2Class(my_GtkLabel2Class_t* class)
|
||||
|
||||
// ----- GtkTreeView2Class ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GtkTreeView2, set_scroll_adjustments, void, (void* tree_view, void* hadjustment, void* vadjustment), 3, tree_view, hadjustment, vadjustment);
|
||||
WRAPPER(GtkTreeView2, row_activated, void, (void* tree_view, void* path, void* column), 3, tree_view, path, column);
|
||||
WRAPPER(GtkTreeView2, test_expand_row, int, (void* tree_view, void* iter, void* path), 3, tree_view, iter, path);
|
||||
WRAPPER(GtkTreeView2, test_collapse_row, int, (void* tree_view, void* iter, void* path), 3, tree_view, iter, path);
|
||||
WRAPPER(GtkTreeView2, row_expanded, void, (void* tree_view, void* iter, void* path), 3, tree_view, iter, path);
|
||||
WRAPPER(GtkTreeView2, row_collapsed, void, (void* tree_view, void* iter, void* path), 3, tree_view, iter, path);
|
||||
WRAPPER(GtkTreeView2, columns_changed, void, (void* tree_view), 1, tree_view);
|
||||
WRAPPER(GtkTreeView2, cursor_changed, void, (void* tree_view), 1, tree_view);
|
||||
WRAPPER(GtkTreeView2, move_cursor, int, (void* tree_view, int step, int count), 3, tree_view, step, count);
|
||||
WRAPPER(GtkTreeView2, select_all, int, (void* tree_view), 1, tree_view);
|
||||
WRAPPER(GtkTreeView2, unselect_all, int, (void* tree_view), 1, tree_view);
|
||||
WRAPPER(GtkTreeView2, select_cursor_row, int, (void* tree_view, int start_editing), 2, tree_view, start_editing);
|
||||
WRAPPER(GtkTreeView2, toggle_cursor_row, int, (void* tree_view), 1, tree_view);
|
||||
WRAPPER(GtkTreeView2, expand_collapse_cursor_row, int, (void* tree_view, int logical, int expand, int open_all), 4, tree_view, logical, expand, open_all);
|
||||
WRAPPER(GtkTreeView2, select_cursor_parent, int, (void* tree_view), 1, tree_view);
|
||||
WRAPPER(GtkTreeView2, start_interactive_search, int, (void* tree_view), 1, tree_view);
|
||||
WRAPPER(GtkTreeView2, set_scroll_adjustments, void, (void* tree_view, void* hadjustment, void* vadjustment), "ppp", tree_view, hadjustment, vadjustment);
|
||||
WRAPPER(GtkTreeView2, row_activated, void, (void* tree_view, void* path, void* column), "ppp", tree_view, path, column);
|
||||
WRAPPER(GtkTreeView2, test_expand_row, int, (void* tree_view, void* iter, void* path), "ppp", tree_view, iter, path);
|
||||
WRAPPER(GtkTreeView2, test_collapse_row, int, (void* tree_view, void* iter, void* path), "ppp", tree_view, iter, path);
|
||||
WRAPPER(GtkTreeView2, row_expanded, void, (void* tree_view, void* iter, void* path), "ppp", tree_view, iter, path);
|
||||
WRAPPER(GtkTreeView2, row_collapsed, void, (void* tree_view, void* iter, void* path), "ppp", tree_view, iter, path);
|
||||
WRAPPER(GtkTreeView2, columns_changed, void, (void* tree_view), "p", tree_view);
|
||||
WRAPPER(GtkTreeView2, cursor_changed, void, (void* tree_view), "p", tree_view);
|
||||
WRAPPER(GtkTreeView2, move_cursor, int, (void* tree_view, int step, int count), "pii", tree_view, step, count);
|
||||
WRAPPER(GtkTreeView2, select_all, int, (void* tree_view), "p", tree_view);
|
||||
WRAPPER(GtkTreeView2, unselect_all, int, (void* tree_view), "p", tree_view);
|
||||
WRAPPER(GtkTreeView2, select_cursor_row, int, (void* tree_view, int start_editing), "pi", tree_view, start_editing);
|
||||
WRAPPER(GtkTreeView2, toggle_cursor_row, int, (void* tree_view), "p", tree_view);
|
||||
WRAPPER(GtkTreeView2, expand_collapse_cursor_row, int, (void* tree_view, int logical, int expand, int open_all), "piii", tree_view, logical, expand, open_all);
|
||||
WRAPPER(GtkTreeView2, select_cursor_parent, int, (void* tree_view), "p", tree_view);
|
||||
WRAPPER(GtkTreeView2, start_interactive_search, int, (void* tree_view), "p", tree_view);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(set_scroll_adjustments, vFppp); \
|
||||
@@ -847,12 +847,12 @@ static void bridgeGtkBin2Class(my_GtkBin2Class_t* class)
|
||||
|
||||
// ----- GtkWindow2Class ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GtkWindow2, set_focus, void, (void* window, void* focus), 2, window, focus);
|
||||
WRAPPER(GtkWindow2, frame_event, int, (void* window, void* event), 2, window, event);
|
||||
WRAPPER(GtkWindow2, activate_focus, void, (void* window), 1, window);
|
||||
WRAPPER(GtkWindow2, activate_default, void, (void* window), 1, window);
|
||||
WRAPPER(GtkWindow2, move_focus, void, (void* window, int direction), 2, window, direction);
|
||||
WRAPPER(GtkWindow2, keys_changed, void, (void* window), 1, window);
|
||||
WRAPPER(GtkWindow2, set_focus, void, (void* window, void* focus), "pp", window, focus);
|
||||
WRAPPER(GtkWindow2, frame_event, int, (void* window, void* event), "pp", window, event);
|
||||
WRAPPER(GtkWindow2, activate_focus, void, (void* window), "p", window);
|
||||
WRAPPER(GtkWindow2, activate_default, void, (void* window), "p", window);
|
||||
WRAPPER(GtkWindow2, move_focus, void, (void* window, int direction), "pi", window, direction);
|
||||
WRAPPER(GtkWindow2, keys_changed, void, (void* window), "p", window);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(set_focus, vFpp); \
|
||||
@@ -945,8 +945,8 @@ static void bridgeMetaFrames2Class(my_MetaFrames2Class_t* class)
|
||||
|
||||
// ----- GDBusObjectManagerClientClass ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GDBusObjectManagerClient,interface_proxy_signal, void, (void* manager, void* object_proxy, void* interface_proxy, void* sender_name, void* signal_name, void* parameters), 6, manager, object_proxy, interface_proxy, sender_name, signal_name, parameters);
|
||||
WRAPPER(GDBusObjectManagerClient,interface_proxy_properties_changed, void, (void* manager, void* object_proxy, void* interface_proxy, void* changed_properties, void* invalidated_properties), 5, manager, object_proxy, interface_proxy, changed_properties, invalidated_properties);
|
||||
WRAPPER(GDBusObjectManagerClient,interface_proxy_signal, void, (void* manager, void* object_proxy, void* interface_proxy, void* sender_name, void* signal_name, void* parameters), "pppppp", manager, object_proxy, interface_proxy, sender_name, signal_name, parameters);
|
||||
WRAPPER(GDBusObjectManagerClient,interface_proxy_properties_changed, void, (void* manager, void* object_proxy, void* interface_proxy, void* changed_properties, void* invalidated_properties), "ppppp", manager, object_proxy, interface_proxy, changed_properties, invalidated_properties);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(interface_proxy_signal, vFpppppp); \
|
||||
@@ -982,12 +982,12 @@ static void bridgeGDBusObjectManagerClientClass(my_GDBusObjectManagerClientClass
|
||||
|
||||
// ----- GtkButton2Class ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GtkButton2, pressed, void, (void* button), 1, button);
|
||||
WRAPPER(GtkButton2, released, void, (void* button), 1, button);
|
||||
WRAPPER(GtkButton2, clicked, void, (void* button), 1, button);
|
||||
WRAPPER(GtkButton2, enter, void, (void* button), 1, button);
|
||||
WRAPPER(GtkButton2, leave, void, (void* button), 1, button);
|
||||
WRAPPER(GtkButton2, activate, void, (void* button), 1, button);
|
||||
WRAPPER(GtkButton2, pressed, void, (void* button), "p", button);
|
||||
WRAPPER(GtkButton2, released, void, (void* button), "p", button);
|
||||
WRAPPER(GtkButton2, clicked, void, (void* button), "p", button);
|
||||
WRAPPER(GtkButton2, enter, void, (void* button), "p", button);
|
||||
WRAPPER(GtkButton2, leave, void, (void* button), "p", button);
|
||||
WRAPPER(GtkButton2, activate, void, (void* button), "p", button);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(pressed, vFp); \
|
||||
@@ -1027,8 +1027,8 @@ static void bridgeGtkButton2Class(my_GtkButton2Class_t* class)
|
||||
|
||||
// ----- GtkComboBox2Class ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GtkComboBox2, changed, void, (void* combo_box), 1, combo_box);
|
||||
WRAPPER(GtkComboBox2, get_active_text, void*, (void* combo_box), 1, combo_box);
|
||||
WRAPPER(GtkComboBox2, changed, void, (void* combo_box), "p", combo_box);
|
||||
WRAPPER(GtkComboBox2, get_active_text, void*, (void* combo_box), "p", combo_box);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(changed, vFp); \
|
||||
@@ -1064,7 +1064,7 @@ static void bridgeGtkComboBox2Class(my_GtkComboBox2Class_t* class)
|
||||
|
||||
// ----- GtkToggleButton2Class ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GtkToggleButton2, toggled, void, (void* toggle_button), 1, toggle_button);
|
||||
WRAPPER(GtkToggleButton2, toggled, void, (void* toggle_button), "p", toggle_button);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(toggled, vFp); \
|
||||
@@ -1099,7 +1099,7 @@ static void bridgeGtkToggleButton2Class(my_GtkToggleButton2Class_t* class)
|
||||
|
||||
// ----- GtkCheckButton2Class ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GtkCheckButton2, draw_indicator, void, (void* check_button, void* area), 2, check_button, area);
|
||||
WRAPPER(GtkCheckButton2, draw_indicator, void, (void* check_button, void* area), "pp", check_button, area);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(draw_indicator, vFpp); \
|
||||
@@ -1134,17 +1134,17 @@ static void bridgeGtkCheckButton2Class(my_GtkCheckButton2Class_t* class)
|
||||
|
||||
// ----- GtkEntry2Class ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GtkEntry2, populate_popup, void, (void* entry, void* menu), 2, entry, menu);
|
||||
WRAPPER(GtkEntry2, activate, void, (void* entry), 1, entry);
|
||||
WRAPPER(GtkEntry2, move_cursor, void, (void* entry, int step, int count, int extend_selection), 4, entry, step, count, extend_selection);
|
||||
WRAPPER(GtkEntry2, insert_at_cursor, void, (void* entry, void* str), 2, entry, str);
|
||||
WRAPPER(GtkEntry2, delete_from_cursor, void, (void* entry, int type, int count), 3, entry, type, count);
|
||||
WRAPPER(GtkEntry2, backspace, void, (void* entry), 1, entry);
|
||||
WRAPPER(GtkEntry2, cut_clipboard, void, (void* entry), 1, entry);
|
||||
WRAPPER(GtkEntry2, copy_clipboard, void, (void* entry), 1, entry);
|
||||
WRAPPER(GtkEntry2, paste_clipboard, void, (void* entry), 1, entry);
|
||||
WRAPPER(GtkEntry2, toggle_overwrite, void, (void* entry), 1, entry);
|
||||
WRAPPER(GtkEntry2, get_text_area_size, void, (void* entry, void* x, void* y, void* width, void* height), 5, entry, x, y, width, height);
|
||||
WRAPPER(GtkEntry2, populate_popup, void, (void* entry, void* menu), "2", entry, menu);
|
||||
WRAPPER(GtkEntry2, activate, void, (void* entry), "p", entry);
|
||||
WRAPPER(GtkEntry2, move_cursor, void, (void* entry, int step, int count, int extend_selection), "piii", entry, step, count, extend_selection);
|
||||
WRAPPER(GtkEntry2, insert_at_cursor, void, (void* entry, void* str), "pp", entry, str);
|
||||
WRAPPER(GtkEntry2, delete_from_cursor, void, (void* entry, int type, int count), "pii", entry, type, count);
|
||||
WRAPPER(GtkEntry2, backspace, void, (void* entry), "p", entry);
|
||||
WRAPPER(GtkEntry2, cut_clipboard, void, (void* entry), "p", entry);
|
||||
WRAPPER(GtkEntry2, copy_clipboard, void, (void* entry), "p", entry);
|
||||
WRAPPER(GtkEntry2, paste_clipboard, void, (void* entry), "p", entry);
|
||||
WRAPPER(GtkEntry2, toggle_overwrite, void, (void* entry), "p", entry);
|
||||
WRAPPER(GtkEntry2, get_text_area_size, void, (void* entry, void* x, void* y, void* width, void* height), "ppppp", entry, x, y, width, height);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(populate_popup, vFpp); \
|
||||
@@ -1188,11 +1188,11 @@ static void bridgeGtkEntry2Class(my_GtkEntry2Class_t* class)
|
||||
|
||||
// ----- GtkSpinButton2Class ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GtkSpinButton2, input, int, (void* spin_button, void* new_value), 2, spin_button, new_value);
|
||||
WRAPPER(GtkSpinButton2, output, int, (void* spin_button), 1, spin_button);
|
||||
WRAPPER(GtkSpinButton2, value_changed, void, (void* spin_button), 1, spin_button);
|
||||
WRAPPER(GtkSpinButton2, change_value, void, (void* spin_button, int scroll), 2, spin_button, scroll);
|
||||
WRAPPER(GtkSpinButton2, wrapped, void, (void* spin_button), 1, spin_button);
|
||||
WRAPPER(GtkSpinButton2, input, int, (void* spin_button, void* new_value), "pp", spin_button, new_value);
|
||||
WRAPPER(GtkSpinButton2, output, int, (void* spin_button), "p", spin_button);
|
||||
WRAPPER(GtkSpinButton2, value_changed, void, (void* spin_button), "p", spin_button);
|
||||
WRAPPER(GtkSpinButton2, change_value, void, (void* spin_button, int scroll), "pi", spin_button, scroll);
|
||||
WRAPPER(GtkSpinButton2, wrapped, void, (void* spin_button), "p", spin_button);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(input, iFpp); \
|
||||
@@ -1230,9 +1230,9 @@ static void bridgeGtkSpinButton2Class(my_GtkSpinButton2Class_t* class)
|
||||
|
||||
// ----- GtkProgress2Class ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GtkProgress2, paint, void, (void* progress), 1, progress);
|
||||
WRAPPER(GtkProgress2, update, void, (void* progress), 1, progress);
|
||||
WRAPPER(GtkProgress2, act_mode_enter, void, (void* progress), 1, progress);
|
||||
WRAPPER(GtkProgress2, paint, void, (void* progress), "p", progress);
|
||||
WRAPPER(GtkProgress2, update, void, (void* progress), "p", progress);
|
||||
WRAPPER(GtkProgress2, act_mode_enter, void, (void* progress), "p", progress);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(paint, vFp); \
|
||||
@@ -1300,7 +1300,7 @@ static void bridgeGtkProgressBar2Class(my_GtkProgressBar2Class_t* class)
|
||||
|
||||
// ----- GtkFrame2Class ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GtkFrame2, compute_child_allocation, void, (void* frame, void* allocation), 2, frame, allocation);
|
||||
WRAPPER(GtkFrame2, compute_child_allocation, void, (void* frame, void* allocation), "pp", frame, allocation);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(compute_child_allocation, vFpp); \
|
||||
@@ -1334,15 +1334,15 @@ static void bridgeGtkFrame2Class(my_GtkFrame2Class_t* class)
|
||||
|
||||
// ----- GtkMenuShell2Class ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GtkMenuShell2,deactivate, void, (void* menu_shell), 1, menu_shell);
|
||||
WRAPPER(GtkMenuShell2,selection_done, void, (void* menu_shell), 1, menu_shell);
|
||||
WRAPPER(GtkMenuShell2,move_current, void, (void* menu_shell, int direction), 2, menu_shell, direction);
|
||||
WRAPPER(GtkMenuShell2,activate_current, void,(void* menu_shell, int force_hide), 2, menu_shell, force_hide);
|
||||
WRAPPER(GtkMenuShell2,cancel, void, (void* menu_shell), 1, menu_shell);
|
||||
WRAPPER(GtkMenuShell2,select_item, void, (void* menu_shell, void* menu_item), 2, menu_shell, menu_item);
|
||||
WRAPPER(GtkMenuShell2,insert, void, (void* menu_shell, void* child, int position), 3, menu_shell, child, position);
|
||||
WRAPPER(GtkMenuShell2,get_popup_delay, int, (void* menu_shell), 1, menu_shell);
|
||||
WRAPPER(GtkMenuShell2,move_selected, int, (void* menu_shell, int distance), 2, menu_shell, distance);
|
||||
WRAPPER(GtkMenuShell2,deactivate, void, (void* menu_shell), "p", menu_shell);
|
||||
WRAPPER(GtkMenuShell2,selection_done, void, (void* menu_shell), "p", menu_shell);
|
||||
WRAPPER(GtkMenuShell2,move_current, void, (void* menu_shell, int direction), "pi", menu_shell, direction);
|
||||
WRAPPER(GtkMenuShell2,activate_current, void,(void* menu_shell, int force_hide), "pi", menu_shell, force_hide);
|
||||
WRAPPER(GtkMenuShell2,cancel, void, (void* menu_shell), "p", menu_shell);
|
||||
WRAPPER(GtkMenuShell2,select_item, void, (void* menu_shell, void* menu_item), "pp", menu_shell, menu_item);
|
||||
WRAPPER(GtkMenuShell2,insert, void, (void* menu_shell, void* child, int position), "ppi", menu_shell, child, position);
|
||||
WRAPPER(GtkMenuShell2,get_popup_delay, int, (void* menu_shell), "p", menu_shell);
|
||||
WRAPPER(GtkMenuShell2,move_selected, int, (void* menu_shell, int distance), "pi", menu_shell, distance);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(deactivate, vFp); \
|
||||
@@ -1416,7 +1416,7 @@ static void bridgeGtkMenuBar2Class(my_GtkMenuBar2Class_t* class)
|
||||
|
||||
// ----- GstObjectClass ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GstObject, deep_notify, void, (void* object, void* origin, void* pspec), 3, object, origin, pspec);
|
||||
WRAPPER(GstObject, deep_notify, void, (void* object, void* origin, void* pspec), "ppp", object, origin, pspec);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(deep_notify, vFppp); \
|
||||
@@ -1450,8 +1450,8 @@ static void bridgeGstObjectClass(my_GstObjectClass_t* class)
|
||||
|
||||
// ----- GstAllocatorClass ------
|
||||
// wrapper x86 -> natives of callbacks
|
||||
WRAPPER(GstAllocator, alloc, void*, (void *allocator, size_t size, void *params), 3, allocator, size, params);
|
||||
WRAPPER(GstAllocator,free, void, (void *allocator, void *memory), 2, allocator, memory);
|
||||
WRAPPER(GstAllocator, alloc, void*, (void *allocator, size_t size, void *params), "pLp", allocator, size, params);
|
||||
WRAPPER(GstAllocator,free, void, (void *allocator, void *memory), "pp", allocator, memory);
|
||||
|
||||
#define SUPERGO() \
|
||||
GO(alloc, pFpLp); \
|
||||
@@ -1633,35 +1633,35 @@ SUPER()
|
||||
#undef GO
|
||||
// Then the static functions callback that may be used with the structure
|
||||
#define GO(A) \
|
||||
static uintptr_t fct_funcs_value_init_##A = 0; \
|
||||
static void my_funcs_value_init_##A(void* value) { \
|
||||
static uintptr_t fct_funcs_value_init_##A = 0; \
|
||||
static void my_funcs_value_init_##A(void* value) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_funcs_value_init_" #A " wrapper\n"); \
|
||||
RunFunction(my_context, fct_funcs_value_init_##A, 1, value); \
|
||||
RunFunctionFmt(fct_funcs_value_init_##A, "p", value); \
|
||||
} \
|
||||
static uintptr_t fct_funcs_value_free_##A = 0; \
|
||||
static void my_funcs_value_free_##A(void* value) { \
|
||||
static uintptr_t fct_funcs_value_free_##A = 0; \
|
||||
static void my_funcs_value_free_##A(void* value) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_funcs_value_free_" #A " wrapper\n"); \
|
||||
RunFunction(my_context, fct_funcs_value_free_##A, 1, value); \
|
||||
RunFunctionFmt(fct_funcs_value_free_##A, "p", value); \
|
||||
} \
|
||||
static uintptr_t fct_funcs_value_copy_##A = 0; \
|
||||
static void my_funcs_value_copy_##A(void* source, void* dest) { \
|
||||
static uintptr_t fct_funcs_value_copy_##A = 0; \
|
||||
static void my_funcs_value_copy_##A(void* source, void* dest) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_funcs_value_copy_" #A " wrapper\n"); \
|
||||
RunFunction(my_context, fct_funcs_value_copy_##A, 2, source, dest); \
|
||||
RunFunctionFmt(fct_funcs_value_copy_##A, "pp", source, dest); \
|
||||
} \
|
||||
static uintptr_t fct_funcs_value_peek_pointer_##A = 0; \
|
||||
static void* my_funcs_value_peek_pointer_##A(void* value) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_funcs_value_peek_pointer_" #A " wrapper\n"); \
|
||||
return (void*)RunFunction(my_context, fct_funcs_value_peek_pointer_##A, 1, value); \
|
||||
static uintptr_t fct_funcs_value_peek_pointer_##A = 0; \
|
||||
static void* my_funcs_value_peek_pointer_##A(void* value) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_funcs_value_peek_pointer_" #A " wrapper\n"); \
|
||||
return (void*)RunFunctionFmt(fct_funcs_value_peek_pointer_##A, "p", value); \
|
||||
} \
|
||||
static uintptr_t fct_funcs_collect_value_##A = 0; \
|
||||
static void* my_funcs_collect_value_##A(void* value, uint32_t n, void* collect, uint32_t flags) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_funcs_collect_value_" #A " wrapper\n"); \
|
||||
return (void*)RunFunction(my_context, fct_funcs_collect_value_##A, 4, value, n, collect, flags); \
|
||||
static uintptr_t fct_funcs_collect_value_##A = 0; \
|
||||
static void* my_funcs_collect_value_##A(void* value, uint32_t n, void* collect, uint32_t flags) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_funcs_collect_value_" #A " wrapper\n"); \
|
||||
return (void*)RunFunctionFmt(fct_funcs_collect_value_##A, "pupu", value, n, collect, flags);\
|
||||
} \
|
||||
static uintptr_t fct_funcs_lcopy_value_##A = 0; \
|
||||
static void* my_funcs_lcopy_value_##A(void* value, uint32_t n, void* collect, uint32_t flags) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_funcs_lcopy_value_" #A " wrapper\n"); \
|
||||
return (void*)RunFunction(my_context, fct_funcs_lcopy_value_##A, 4, value, n, collect, flags); \
|
||||
static uintptr_t fct_funcs_lcopy_value_##A = 0; \
|
||||
static void* my_funcs_lcopy_value_##A(void* value, uint32_t n, void* collect, uint32_t flags) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_funcs_lcopy_value_" #A " wrapper\n"); \
|
||||
return (void*)RunFunctionFmt(fct_funcs_lcopy_value_##A, "pupu", value, n, collect, flags); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
@@ -1699,10 +1699,10 @@ my_GTypeValueTable_t* findFreeGTypeValueTable(my_GTypeValueTable_t* fcts)
|
||||
|
||||
// signal2 ...
|
||||
#define GO(A) \
|
||||
static uintptr_t my_signal2_fct_##A = 0; \
|
||||
static void* my_signal2_##A(void* a, void* b) \
|
||||
{ \
|
||||
return (void*)RunFunction(my_context, my_signal2_fct_##A, 2, a, b); \
|
||||
static uintptr_t my_signal2_fct_##A = 0; \
|
||||
static void* my_signal2_##A(void* a, void* b) \
|
||||
{ \
|
||||
return (void*)RunFunctionFmt(my_signal2_fct_##A, "pp", a, b); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
@@ -1721,10 +1721,10 @@ static void* find_signal2_Fct(void* fct)
|
||||
}
|
||||
// signal3 ...
|
||||
#define GO(A) \
|
||||
static uintptr_t my_signal3_fct_##A = 0; \
|
||||
static void* my_signal3_##A(void* a, void* b, void* c) \
|
||||
{ \
|
||||
return (void*)RunFunction(my_context, my_signal3_fct_##A, 3, a, b, c); \
|
||||
static uintptr_t my_signal3_fct_##A = 0; \
|
||||
static void* my_signal3_##A(void* a, void* b, void* c) \
|
||||
{ \
|
||||
return (void*)RunFunctionFmt(my_signal3_fct_##A, "ppp", a, b, c); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
@@ -1743,10 +1743,10 @@ static void* find_signal3_Fct(void* fct)
|
||||
}
|
||||
// signal4 ...
|
||||
#define GO(A) \
|
||||
static uintptr_t my_signal4_fct_##A = 0; \
|
||||
static void* my_signal4_##A(void* a, void* b, void* c, void* d) \
|
||||
{ \
|
||||
return (void*)RunFunction(my_context, my_signal4_fct_##A, 4, a, b, c, d); \
|
||||
static uintptr_t my_signal4_fct_##A = 0; \
|
||||
static void* my_signal4_##A(void* a, void* b, void* c, void* d) \
|
||||
{ \
|
||||
return (void*)RunFunctionFmt(my_signal4_fct_##A, "pppp", a, b, c, d); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
@@ -1765,10 +1765,10 @@ static void* find_signal4_Fct(void* fct)
|
||||
}
|
||||
// signal5 ...
|
||||
#define GO(A) \
|
||||
static uintptr_t my_signal5_fct_##A = 0; \
|
||||
static void* my_signal5_##A(void* a, void* b, void* c, void* d, void* e) \
|
||||
{ \
|
||||
return (void*)RunFunction(my_context, my_signal5_fct_##A, 5, a, b, c, d, e);\
|
||||
static uintptr_t my_signal5_fct_##A = 0; \
|
||||
static void* my_signal5_##A(void* a, void* b, void* c, void* d, void* e) \
|
||||
{ \
|
||||
return (void*)RunFunctionFmt(my_signal5_fct_##A, "ppppp", a, b, c, d, e); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
@@ -1787,10 +1787,10 @@ static void* find_signal5_Fct(void* fct)
|
||||
}
|
||||
// signal6 ...
|
||||
#define GO(A) \
|
||||
static uintptr_t my_signal6_fct_##A = 0; \
|
||||
static void* my_signal6_##A(void* a, void* b, void* c, void* d, void* e, void* f) \
|
||||
{ \
|
||||
return (void*)RunFunction(my_context, my_signal6_fct_##A, 6, a, b, c, d, e, f); \
|
||||
static uintptr_t my_signal6_fct_##A = 0; \
|
||||
static void* my_signal6_##A(void* a, void* b, void* c, void* d, void* e, void* f) \
|
||||
{ \
|
||||
return (void*)RunFunctionFmt(my_signal6_fct_##A, "pppppp", a, b, c, d, e, f); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
@@ -1809,10 +1809,10 @@ static void* find_signal6_Fct(void* fct)
|
||||
}
|
||||
// signal7 ...
|
||||
#define GO(A) \
|
||||
static uintptr_t my_signal7_fct_##A = 0; \
|
||||
static void* my_signal7_##A(void* a, void* b, void* c, void* d, void* e, void* f, void* g) \
|
||||
{ \
|
||||
return (void*)RunFunction(my_context, my_signal7_fct_##A, 7, a, b, c, d, e, f, g); \
|
||||
static uintptr_t my_signal7_fct_##A = 0; \
|
||||
static void* my_signal7_##A(void* a, void* b, void* c, void* d, void* e, void* f, void* g) \
|
||||
{ \
|
||||
return (void*)RunFunctionFmt(my_signal7_fct_##A, "ppppppp", a, b, c, d, e, f, g); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
@@ -1896,41 +1896,41 @@ SUPER()
|
||||
#undef GO
|
||||
// Then the static functions callback that may be used with the structure
|
||||
#define GO(A) \
|
||||
static int fct_parent_##A = 0 ; \
|
||||
static uintptr_t fct_funcs_base_init_##A = 0; \
|
||||
static int my_funcs_base_init_##A(void* g_class) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_funcs_base_init_" #A " wrapper\n"); \
|
||||
return (int)RunFunction(my_context, fct_funcs_base_init_##A, 1, g_class); \
|
||||
static int fct_parent_##A = 0 ; \
|
||||
static uintptr_t fct_funcs_base_init_##A = 0; \
|
||||
static int my_funcs_base_init_##A(void* g_class) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_funcs_base_init_" #A " wrapper\n"); \
|
||||
return (int)RunFunctionFmt(fct_funcs_base_init_##A, "p", g_class); \
|
||||
} \
|
||||
static uintptr_t fct_funcs_base_finalize_##A = 0; \
|
||||
static int my_funcs_base_finalize_##A(void* g_class) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_funcs_base_finalize_" #A " wrapper\n"); \
|
||||
return (int)RunFunction(my_context, fct_funcs_base_finalize_##A, 1, g_class); \
|
||||
static uintptr_t fct_funcs_base_finalize_##A = 0; \
|
||||
static int my_funcs_base_finalize_##A(void* g_class) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_funcs_base_finalize_" #A " wrapper\n"); \
|
||||
return (int)RunFunctionFmt(fct_funcs_base_finalize_##A, "p", g_class); \
|
||||
} \
|
||||
static uintptr_t fct_funcs_class_init_##A = 0; \
|
||||
static int my_funcs_class_init_##A(void* g_class, void* data) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_funcs_class_init_" #A " wrapper\n"); \
|
||||
/*wrapGTKClass(g_class, fct_parent_##A);*/ \
|
||||
int ret = (int)RunFunction(my_context, fct_funcs_class_init_##A, 2, g_class, data); \
|
||||
unwrapGTKClass(g_class, fct_parent_##A); \
|
||||
bridgeGTKClass(g_class, fct_parent_##A); \
|
||||
my_unwrap_signal_offset(g_class); \
|
||||
return ret; \
|
||||
static uintptr_t fct_funcs_class_init_##A = 0; \
|
||||
static int my_funcs_class_init_##A(void* g_class, void* data) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_funcs_class_init_" #A " wrapper\n"); \
|
||||
/*wrapGTKClass(g_class, fct_parent_##A);*/ \
|
||||
int ret = (int)RunFunctionFmt(fct_funcs_class_init_##A, "pp", g_class, data); \
|
||||
unwrapGTKClass(g_class, fct_parent_##A); \
|
||||
bridgeGTKClass(g_class, fct_parent_##A); \
|
||||
my_unwrap_signal_offset(g_class); \
|
||||
return ret; \
|
||||
} \
|
||||
static uintptr_t fct_funcs_class_finalize_##A = 0; \
|
||||
static int my_funcs_class_finalize_##A(void* g_class, void* data) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_funcs_class_finalize_" #A " wrapper\n"); \
|
||||
wrapGTKClass(g_class, fct_parent_##A); \
|
||||
int ret = (int)RunFunction(my_context, fct_funcs_class_finalize_##A, 2, g_class, data); \
|
||||
unwrapGTKClass(g_class, fct_parent_##A); \
|
||||
bridgeGTKClass(g_class, fct_parent_##A); \
|
||||
my_unwrap_signal_offset(g_class); \
|
||||
return ret; \
|
||||
static uintptr_t fct_funcs_class_finalize_##A = 0; \
|
||||
static int my_funcs_class_finalize_##A(void* g_class, void* data) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_funcs_class_finalize_" #A " wrapper\n"); \
|
||||
wrapGTKClass(g_class, fct_parent_##A); \
|
||||
int ret = (int)RunFunctionFmt(fct_funcs_class_finalize_##A, "pp", g_class, data); \
|
||||
unwrapGTKClass(g_class, fct_parent_##A); \
|
||||
bridgeGTKClass(g_class, fct_parent_##A); \
|
||||
my_unwrap_signal_offset(g_class); \
|
||||
return ret; \
|
||||
} \
|
||||
static uintptr_t fct_funcs_instance_init_##A = 0; \
|
||||
static int my_funcs_instance_init_##A(void* instance, void* data) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_funcs_instance_init_" #A " wrapper\n"); \
|
||||
return (int)RunFunction(my_context, fct_funcs_instance_init_##A, 2, instance, data); \
|
||||
static uintptr_t fct_funcs_instance_init_##A = 0; \
|
||||
static int my_funcs_instance_init_##A(void* instance, void* data) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_funcs_instance_init_" #A " wrapper\n"); \
|
||||
return (int)RunFunctionFmt(fct_funcs_instance_init_##A, "pp", instance, data); \
|
||||
}
|
||||
|
||||
SUPER()
|
||||
@@ -1984,20 +1984,20 @@ static int fct_gtk_parent_##A = 0 ; \
|
||||
static uintptr_t fct_gtk_class_init_##A = 0; \
|
||||
static int my_gtk_class_init_##A(void* g_class) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_gtk_class_init_" #A " wrapper\n"); \
|
||||
int ret = (int)RunFunction(my_context, fct_gtk_class_init_##A, 1, g_class); \
|
||||
int ret = (int)RunFunctionFmt(fct_gtk_class_init_##A, "p", g_class);\
|
||||
unwrapGTKClass(g_class, fct_gtk_parent_##A); \
|
||||
bridgeGTKClass(g_class, fct_gtk_parent_##A); \
|
||||
return ret; \
|
||||
} \
|
||||
static uintptr_t fct_gtk_object_init_##A = 0; \
|
||||
static int my_gtk_object_init_##A(void* object, void* data) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_gtk_object_init_" #A " wrapper\n"); \
|
||||
return (int)RunFunction(my_context, fct_gtk_object_init_##A, 2, object, data); \
|
||||
static uintptr_t fct_gtk_object_init_##A = 0; \
|
||||
static int my_gtk_object_init_##A(void* object, void* data) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_gtk_object_init_" #A " wrapper\n"); \
|
||||
return (int)RunFunctionFmt(fct_gtk_object_init_##A, "pp", object, data); \
|
||||
} \
|
||||
static uintptr_t fct_gtk_base_class_init_##A = 0; \
|
||||
static int my_gtk_base_class_init_##A(void* instance, void* data) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_gtk_base_class_init_" #A " wrapper\n"); \
|
||||
return (int)RunFunction(my_context, fct_gtk_base_class_init_##A, 2, instance, data); \
|
||||
static uintptr_t fct_gtk_base_class_init_##A = 0; \
|
||||
static int my_gtk_base_class_init_##A(void* instance, void* data) { \
|
||||
printf_log(LOG_DEBUG, "Calling fct_gtk_base_class_init_" #A " wrapper\n"); \
|
||||
return (int)RunFunctionFmt(fct_gtk_base_class_init_##A, "pp", instance, data); \
|
||||
}
|
||||
|
||||
SUPER()
|
||||
@@ -2108,7 +2108,7 @@ void my_signal_delete(my_signal_t* sig)
|
||||
}
|
||||
uintptr_t d = sig->destroy;
|
||||
if(d) {
|
||||
RunFunction(my_context, d, 1, sig->data);
|
||||
RunFunctionFmt(d, "p", sig->data);
|
||||
}
|
||||
printf_log(LOG_DEBUG, "gtk Data deleted, sig=%p, data=%p, destroy=%p\n", sig, sig->data, (void*)d);
|
||||
box_free(sig);
|
||||
@@ -2150,10 +2150,10 @@ int my_signal_cb(void* a, void* b, void* c, void* d)
|
||||
}
|
||||
printf_log(LOG_DEBUG, "gtk Signal called, sig=%p, NArgs=%d\n", sig, i);
|
||||
switch(i) {
|
||||
case 1: return (int)RunFunction(my_context, sig->c_handler, 1, sig->data);
|
||||
case 2: return (int)RunFunction(my_context, sig->c_handler, 2, a, sig->data);
|
||||
case 3: return (int)RunFunction(my_context, sig->c_handler, 3, a, b, sig->data);
|
||||
case 4: return (int)RunFunction(my_context, sig->c_handler, 4, a, b, c, sig->data);
|
||||
case 1: return (int)RunFunctionFmt(sig->c_handler, "p", sig->data);
|
||||
case 2: return (int)RunFunctionFmt(sig->c_handler, "pp", a, sig->data);
|
||||
case 3: return (int)RunFunctionFmt(sig->c_handler, "ppp", a, b, sig->data);
|
||||
case 4: return (int)RunFunctionFmt(sig->c_handler, "pppp", a, b, c, sig->data);
|
||||
}
|
||||
printf_log(LOG_NONE, "Warning, Gtk signal callback but no data found!");
|
||||
return 0;
|
||||
|
||||
@@ -71,6 +71,8 @@ void my_cpuid(x86emu_t* emu, uint32_t tmp32u)
|
||||
R_EAX |= cpu<<24;
|
||||
}
|
||||
R_EDX = 1 // fpu
|
||||
| 1<<2 // debugging extension (checked by Burnout Paradise
|
||||
| 1<<3 // Large Page Extension
|
||||
| 1<<4 // rdtsc
|
||||
| 1<<8 // cmpxchg8
|
||||
| 1<<11 // sep (sysenter & sysexit)
|
||||
|
||||
+12
-2
@@ -49,6 +49,9 @@ ENTRYSTRING_(BOX86_BASH, bash) \
|
||||
ENTRYINT(BOX86_JITGDB, jit_gdb, 0, 2, 2) \
|
||||
ENTRYSTRING_(BOX86_BOX64, box64) \
|
||||
ENTRYSTRING_(BOX86_LD_PRELOAD, ld_preload) \
|
||||
ENTRYBOOL(BOX86_NOSANDBOX, box86_nosandbox) \
|
||||
ENTRYBOOL(BOX86_LIBCEF, box86_libcef) \
|
||||
ENTRYINT(BOX86_MALLOC_HACK, box86_malloc_hack, 0, 2, 2) \
|
||||
|
||||
#ifdef HAVE_TRACE
|
||||
#define SUPER2() \
|
||||
@@ -81,7 +84,10 @@ ENTRYBOOL(BOX86_DYNAREC_FASTNAN, box86_dynarec_fastnan) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_FASTROUND, box86_dynarec_fastround) \
|
||||
ENTRYINT(BOX86_DYNAREC_SAFEFLAGS, box86_dynarec_safeflags, 0, 2, 2) \
|
||||
ENTRYINT(BOX86_DYNAREC_HOTPAGE, box86_dynarec_hotpage, 0, 255, 8) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_FASTPAGE, box86_dynarec_fastpage) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_WAIT, box86_dynarec_wait) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_BLEEDING_EDGE, box86_dynarec_bleeding_edge) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_JVM, box86_dynarec_jvm) \
|
||||
ENTRYSTRING_(BOX86_NODYNAREC, box86_nodynarec) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_TEST, box86_dynarec_test) \
|
||||
|
||||
@@ -91,14 +97,17 @@ IGNORE(BOX86_DYNAREC) \
|
||||
IGNORE(BOX86_DYNAREC_DUMP) \
|
||||
IGNORE(BOX86_DYNAREC_LOG) \
|
||||
IGNORE(BOX86_DYNAREC_BIGBLOCK) \
|
||||
IGNORE(BOX64_DYNAREC_FORWARD) \
|
||||
IGNORE(BOX86_DYNAREC_FORWARD) \
|
||||
IGNORE(BOX86_DYNAREC_STRONGMEM) \
|
||||
IGNORE(BOX86_DYNAREC_X87DOUBLE) \
|
||||
IGNORE(BOX86_DYNAREC_FASTNAN) \
|
||||
IGNORE(BOX86_DYNAREC_FASTROUND) \
|
||||
IGNORE(BOX86_DYNAREC_SAFEFLAGS) \
|
||||
IGNORE(BOX86_DYNAREC_HOTPAGE) \
|
||||
IGNORE(BOX86_DYNAREC_FASTPAGE) \
|
||||
IGNORE(BOX86_DYNAREC_WAIT) \
|
||||
IGNORE(BOX86_DYNAREC_BLEEDING_EDGE) \
|
||||
IGNORE(BOX86_DYNAREC_JVM) \
|
||||
IGNORE(BOX86_NODYNAREC) \
|
||||
IGNORE(BOX86_DYNAREC_TEST) \
|
||||
|
||||
@@ -492,8 +501,9 @@ void ApplyParams(const char* name, path_collection_t* preload)
|
||||
uintptr_t no_start = 0, no_end = 0;
|
||||
char* p;
|
||||
no_start = strtoul(param->box86_nodynarec, &p, 0);
|
||||
if(p!=param->box86_nodynarec) {
|
||||
if(p!=param->box86_nodynarec && p[0]=='-') {
|
||||
char* p2;
|
||||
++p;
|
||||
no_end = strtoul(p, &p2, 0);
|
||||
if(p2!=p && no_end>no_start) {
|
||||
box86_nodynarec_start = no_start;
|
||||
|
||||
@@ -818,7 +818,6 @@
|
||||
#() iFiuwp
|
||||
#() iFiuii
|
||||
#() iFiuui
|
||||
#() iFiupp
|
||||
#() iFipii
|
||||
#() iFipip
|
||||
#() iFipui
|
||||
@@ -962,8 +961,11 @@
|
||||
#() LFpLpp
|
||||
#() LFppii
|
||||
#() LFppip
|
||||
#() LFppLu
|
||||
#() LFppLL
|
||||
#() LFppLp
|
||||
#() LFpppi
|
||||
#() LFpppL
|
||||
#() LFpppp
|
||||
#() pFEipi
|
||||
#() pFEipp
|
||||
@@ -1016,6 +1018,7 @@
|
||||
#() pFpdIU
|
||||
#() pFplpl
|
||||
#() pFpLip
|
||||
#() pFpLLp
|
||||
#() pFppii
|
||||
#() pFppiu
|
||||
#() pFppiL
|
||||
@@ -1194,6 +1197,7 @@
|
||||
#() vFppppp
|
||||
#() iFEiipp
|
||||
#() iFEiipV
|
||||
#() iFEiupp
|
||||
#() iFEipuu
|
||||
#() iFEippi
|
||||
#() iFEippL
|
||||
@@ -1335,6 +1339,7 @@
|
||||
#() lFppiip
|
||||
#() LFEpppp
|
||||
#() LFuiCiu
|
||||
#() LFLpppL
|
||||
#() LFLpppp
|
||||
#() LFpuipp
|
||||
#() LFpuppi
|
||||
@@ -1394,6 +1399,7 @@
|
||||
#() pFppuup
|
||||
#() pFppddi
|
||||
#() pFppLLi
|
||||
#() pFppLpp
|
||||
#() pFpppii
|
||||
#() pFpppip
|
||||
#() pFpppui
|
||||
@@ -2773,6 +2779,9 @@ wrappedglib2:
|
||||
- g_spawn_async_with_pipes
|
||||
wrappedgmodule2:
|
||||
wrappedgmp:
|
||||
- vFppp:
|
||||
- __gmp_get_memory_functions
|
||||
- __gmp_set_memory_functions
|
||||
wrappedgnutls:
|
||||
- vFp:
|
||||
- gnutls_global_set_log_function
|
||||
@@ -2851,6 +2860,7 @@ wrappedgstreamer:
|
||||
- gst_caps_set_simple
|
||||
- gst_structure_remove_fields
|
||||
- iFppp:
|
||||
- gst_caps_foreach
|
||||
- gst_structure_get_valist
|
||||
- iFppV:
|
||||
- gst_structure_get
|
||||
@@ -3170,6 +3180,8 @@ wrappedlibc:
|
||||
- iFiiip:
|
||||
- iFiiiN:
|
||||
- iFiiII:
|
||||
- iFiupp:
|
||||
- ptrace
|
||||
- iFipii:
|
||||
- iFipuu:
|
||||
- iFippi:
|
||||
@@ -4025,6 +4037,11 @@ wrappedlibxxf86vm:
|
||||
- XF86VidModeGetGamma
|
||||
- XF86VidModeSetGamma
|
||||
wrappedlibz:
|
||||
- iFp:
|
||||
- deflateEnd
|
||||
- inflateEnd
|
||||
- iFpi:
|
||||
- inflate
|
||||
- iFppi:
|
||||
- inflateInit_
|
||||
- iFpipi:
|
||||
@@ -4339,6 +4356,7 @@ wrappedsdl2:
|
||||
- SDL_IsJoystickHIDAPI
|
||||
- SDL_IsJoystickXInput
|
||||
- IFp:
|
||||
- SDL_RWsize
|
||||
- SDL_RWtell
|
||||
- uFp:
|
||||
- SDL_ReadBE16
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedalureDEFS_H_
|
||||
#define __wrappedalureDEFS_H_
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedalureTYPES_H_
|
||||
#define __wrappedalureTYPES_H_
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedalureUNDEFS_H_
|
||||
#define __wrappedalureUNDEFS_H_
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedalutDEFS_H_
|
||||
#define __wrappedalutDEFS_H_
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedalutTYPES_H_
|
||||
#define __wrappedalutTYPES_H_
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedalutUNDEFS_H_
|
||||
#define __wrappedalutUNDEFS_H_
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedappindicator3DEFS_H_
|
||||
#define __wrappedappindicator3DEFS_H_
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedappindicator3TYPES_H_
|
||||
#define __wrappedappindicator3TYPES_H_
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedappindicator3UNDEFS_H_
|
||||
#define __wrappedappindicator3UNDEFS_H_
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedappindicatorDEFS_H_
|
||||
#define __wrappedappindicatorDEFS_H_
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedappindicatorTYPES_H_
|
||||
#define __wrappedappindicatorTYPES_H_
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedappindicatorUNDEFS_H_
|
||||
#define __wrappedappindicatorUNDEFS_H_
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedatkbridgeDEFS_H_
|
||||
#define __wrappedatkbridgeDEFS_H_
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedatkbridgeTYPES_H_
|
||||
#define __wrappedatkbridgeTYPES_H_
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedatkbridgeUNDEFS_H_
|
||||
#define __wrappedatkbridgeUNDEFS_H_
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedatkDEFS_H_
|
||||
#define __wrappedatkDEFS_H_
|
||||
|
||||
Loaded 100 of 689 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user