Compare commits
105
Commits
07cd4b7dc0
...
v1.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4d75f4d22 | ||
|
|
588d2dcc36 | ||
|
|
4ed3481166 | ||
|
|
8805a8f183 | ||
|
|
d7cbab3e4c | ||
|
|
1ea4bf6480 | ||
|
|
f689023089 | ||
|
|
575d26a771 | ||
|
|
4d78785f0b | ||
|
|
b6e7fdc289 | ||
|
|
f68081f694 | ||
|
|
c18f4b3ef4 | ||
|
|
7202b8d6a4 | ||
|
|
943e781720 | ||
|
|
60421c32c9 | ||
|
|
6bc0120286 | ||
|
|
c69257a551 | ||
|
|
50d7ab0d05 | ||
|
|
3c5e276fc5 | ||
|
|
f0cfec8af7 | ||
|
|
c2da7495c0 | ||
|
|
a281f6a721 | ||
|
|
d97dcffaa7 | ||
|
|
e9125d4024 | ||
|
|
a79c8f4934 | ||
|
|
17f25089c6 | ||
|
|
5c29e2cd4f | ||
|
|
e958b3d3d6 | ||
|
|
dcfe7774f3 | ||
|
|
b5a5afbd16 | ||
|
|
87f00ce181 | ||
|
|
c210a778e5 | ||
|
|
0677a390d2 | ||
|
|
94116e2a17 | ||
|
|
d2f67016ab | ||
|
|
b85b344e23 | ||
|
|
def7cea522 | ||
|
|
f365fa8451 | ||
|
|
0fee9238dc | ||
|
|
77c02c8f9d | ||
|
|
0dfff22efb | ||
|
|
4f79f83c11 | ||
|
|
bf3faab660 | ||
|
|
c33212c21b | ||
|
|
483f52f296 | ||
|
|
8ef1d4ec73 | ||
|
|
0943471b33 | ||
|
|
2d6bdcf967 | ||
|
|
83c12d9b3d | ||
|
|
feaa82957a | ||
|
|
0fbff6dc6e | ||
|
|
61219acca6 | ||
|
|
10d8c1cf5a | ||
|
|
d4c56bdfce | ||
|
|
2fb0e640e0 | ||
|
|
47c5360ac2 | ||
|
|
65ee61d540 | ||
|
|
676d43d40a | ||
|
|
8a4e7a3c54 | ||
|
|
243ea03a45 | ||
|
|
4b94ce5c15 | ||
|
|
5284ce2b57 | ||
|
|
cf38622995 | ||
|
|
edf6f35cdf | ||
|
|
abbee308ba | ||
|
|
da0393bd93 | ||
|
|
5bd60cfefd | ||
|
|
0bc8427cd7 | ||
|
|
a309ca3e31 | ||
|
|
4b56e4f384 | ||
|
|
3062a02389 | ||
|
|
a3d108f4d5 | ||
|
|
5f822ebae1 | ||
|
|
31cc5540e1 | ||
|
|
fc224b00a3 | ||
|
|
b00a8a667e | ||
|
|
fe01ef5bac | ||
|
|
508b24125f | ||
|
|
3a611cff35 | ||
|
|
65fb983d57 | ||
|
|
1605e0ba29 | ||
|
|
6dc2967e4a | ||
|
|
cc8ba34577 | ||
|
|
6629e8bbf2 | ||
|
|
475b1958d5 | ||
|
|
a1632a9fce | ||
|
|
0e4d3177fe | ||
|
|
2c99a4fc96 | ||
|
|
03777fdaee | ||
|
|
135f0e9f21 | ||
|
|
77e294d445 | ||
|
|
a9f1bd365b | ||
|
|
f483fe398d | ||
|
|
8acbf6612e | ||
|
|
56edd3c0f4 | ||
|
|
baafbb6dc6 | ||
|
|
9e85b730b2 | ||
|
|
25b736b2bb | ||
|
|
05caf1eb44 | ||
|
|
c3656975dd | ||
|
|
70cafc1700 | ||
|
|
7902acfbb8 | ||
|
|
3a0a38467b | ||
|
|
0a45661a25 | ||
|
|
b8d5f83fc5 |
@@ -4,14 +4,25 @@ Bit-exact реверс DSP-ядра oeksound soothe2 (VST3) → транскри
|
||||
Полное журналирование — в `handoff/NOTES_LEVEL.md`, `handoff/NOTES_TWIN.md`,
|
||||
`handoff/NOTES_CAPTURE.md`, `roadmap.md`.
|
||||
|
||||
> **Текущая фаза (2026-08-23, после 22z):** канон = структурная цепь 48k/4096 с
|
||||
> RT_LAWAFFINE=7.4,1.85 (TOTAL 1.931; bridge 1.594 — гейт не пройден). ГЛАВНЫЙ
|
||||
> ОТКРЫТЫЙ ВОПРОС — семантика входов `bands[]` детектора: доказанно НЕ поточечная
|
||||
> функция от (am,res^α) [22x], не форма-постобработка [22w], не спрединг
|
||||
> IDFT→окно→DFT [22z]. Живая кривая редукции R=1/mask захвачена (слот 0x5407f8,
|
||||
> dualtrace.py), но применённый фильтр ≠ её поточечной копии — механизм живёт ДО
|
||||
> кривой (twin-шаблон/скалярный драйв). Журнал: NOTES_LEVEL 22s–22z; карта метода:
|
||||
> handoff/BLOCKMAP_529fe0.md. ЭТОТ ФАЙЛ ЧИТАЙ ПЕРВЫМ.
|
||||
> **Текущая фаза (2026-08-25, после 24kk2):** ПРИМЕНЕНИЕ ДЕКОДИРОВАНО ФОРМУЛАМИ:
|
||||
> аудио = побиновное умножение кадра на вещественную маску `10^(−cut_D/20)`,
|
||||
> `cut_D = α·ln1p(lvl_raw/β)+c` (+Δ у вторых пиков). Калибровки (rms ≤0.016 дБ):
|
||||
> dual(q0.5,s12,2 тона)=3.2193/0.4927/+0.54; fc1000(1 тон,q0.5)=1.6151/0.3645/+0.48;
|
||||
> fc500(1 тон)=1.1530/0.4038/+0.33. lvl_raw — НАШ фронтенд (float-parity ✓).
|
||||
> Слой STFT = БЕЗ синтез-окна (`RT_SYN=1`). **dual-корпус 0.193 max 0.438**
|
||||
> (канон 3.264); канон TOTAL 2.286 нетронут. ГЕЙТ СМЕНЫ КАНОНА = BIT EXACT
|
||||
> (решение пользователя: все параметры прослежены до декомпа + шумовой пол корпуса).
|
||||
>
|
||||
> Ключевые факты: q НЕ влияет на закон (доказано 24kk); sens линейно через
|
||||
> lvl_raw; далёкий контент не влияет — смешение шаблонно-локальное (24ll);
|
||||
> аудио = exp(deepest-scratch)+const; буфер FIR@540668 = мин.-фазовое
|
||||
> представление (exp(s−iH(s))) — не для транскрипции. Тела bigkernel'ов:
|
||||
> 1803a06a0/180296c80/180323f20/1802dc0e0 (x87 exp-семейство, 24jj).
|
||||
>
|
||||
> ОСТАТОК: каскадный симулятор шагов 9–19 по dataflow (24hh/24ii) →
|
||||
> параметризация α(контент)/fc через campaign.py (датасеты готовы) →
|
||||
> Δ-правило из pre-combine → полный корпус. Журнал: NOTES_LEVEL 24j–24kk2;
|
||||
> карта метода: handoff/BLOCKMAP_529fe0.md. ЭТОТ ФАЙЛ ЧИТАЙ ПЕРВЫМ.
|
||||
|
||||
## Золотое правило (обязательно)
|
||||
1. **Цель — bit-exact реверс кода**, НЕ эмпирическая подгонка кривых. Каждый параметр
|
||||
@@ -137,6 +148,36 @@ scale → LUT level-domain (t^γ·MULT, γ=0.344 decomp / MULT=4.2 placeholder)
|
||||
- `scripts/resalpha.py` — сбор трактов + теорема об отсутствии α (22x).
|
||||
- `scripts/dualtrace.py` + `play_loop.lua` — живой захват ctx при realtime-playback (22y).
|
||||
|
||||
## Env-флаги экспериментов (24j–24kk2)
|
||||
|
||||
| флаг | действие |
|
||||
|------|----------|
|
||||
| `RT_VLAW=1` | закон применённой стадии: mask=10^(−(α·ln1p(lvl/β)+c)/20) |
|
||||
| `RT_SYN=1` | STFT БЕЗ синтез-окна (найденный слой плагина) |
|
||||
| `RT_WIN=0/1/2` | окно анализа: sym-hann / periodic / rect |
|
||||
| `RT_NOWARP=1` | отключить warp-модуляцию маски |
|
||||
| `RT_NOIIR3=1` | отключить IIR3 ×2 |
|
||||
| `RT_IIR12=0` | отключить частотные IIR1/2 (КРИТИЧНО с RT_VLAW — иначе размывают дипы) |
|
||||
| `RT_DUMP_BIN=<f>` (+`RT_DUMP_FRAME=N`) | дамп тракта бина N: am/res/lvl_raw/band_level/prewarp/w |
|
||||
| `RT_VDBG=1` | stderr-печать vlaw-вычислений |
|
||||
|
||||
Полный набор dual-решения: `RT_VLAW=1 RT_SYN=1 RT_NOWARP=1 RT_NOIIR3=1 RT_IIR12=0`.
|
||||
|
||||
## Инструменты сессии 24j–24kk2
|
||||
|
||||
| скрипт | назначение |
|
||||
|--------|-----------|
|
||||
| `scripts/rendersnap2.py <rpp> [cap] [outdir]` | мягкий STOP-снаппер: слоты FIR/scratch/bands/R + скалярный банк + t_snap; НЕ убивает reaper; RENDER_FILE из rpp (не удалять чужие рефы!) |
|
||||
| `scripts/campaign.py <base> <fc> <q> <sens> <in_prefix> <drives> <out>` | ячейка параметризации: клоны rpp+рефы (~8 мин) |
|
||||
| `scripts/disasm_func.py <VA> [len]` | capstone-дизасм с инлайн-резолвом RIP-констант |
|
||||
| `scripts/iat_name.py` | рантайм-резолв импортов bigkernel'ов через PE-экспорты (SIGSTOP!) |
|
||||
| `scripts/probe_states.py` / `probe_mem.py` / `dump_dispatch.py` | живые state-заголовки / память / таблицы диспатча |
|
||||
| `scripts/hunt2.py` | перебор всех ctx-инстансов |
|
||||
| `scripts/scan_pairs.py`, `scan_lutsub.py` | диагностика памяти по сигнатурам float-пар |
|
||||
|
||||
Датасеты кампании: `/tmp/opencode/sc_{q,sens,qmap,k,f,d}*` + `tract_*` +
|
||||
`{level_pairs,f_series,q_series,k_series}.pkl/.npz` (см. NOTES 24bb–24kk2).
|
||||
|
||||
## Чистая работа
|
||||
- Не коммитить: `*.bin`(дампы 112М), `*.wav/rpp`, `*.log`, `dsp/build/`, `ghidra-proj/`,
|
||||
`dl/lib/bin/include/`, `regions*/`. См. `.gitignore`.
|
||||
|
||||
@@ -26,6 +26,17 @@ comb 10 dB). Bit-exact ДОСТИЖИМ (F0 gate: плагин байт-дете
|
||||
> Новый приоритет №1 — семантика входов `bands[]` (см. AGENTS.md и NOTES_LEVEL
|
||||
> 22s–22z); карта метода — handoff/BLOCKMAP_529fe0.md.
|
||||
|
||||
> **ОБНОВЛЕНИЕ 2026-08-25 (сессии 24j–24kk2):** ПРИМЕНЕНИЕ ДЕКОДИРОВАНО ДО ФОРМУЛ.
|
||||
> Применённый фильтр = побиновное умножение кадра на вещественную маску
|
||||
> `10^(−(α·ln1p(lvl/β)+c)/20)`; α/β/c — константы контент-семейства (таблица
|
||||
> калибровок в NOTES 24ee); слой STFT без синтез-окна. dual-корпус 0.193
|
||||
> (флаги RT_VLAW/SYN/NOWARP/NOIIR3/IIR12). Гейт смены канона = BIT EXACT
|
||||
> (решение пользователя 24hh2). Остаток до полного покрытия: (1) каскадный
|
||||
> симулятор шагов 9–19 по dataflow BLOCKMAP 24hh/24ii + тела bigkernel
|
||||
> 1803a06a0 и со. (24jj); (2) k-маппинг фронтенда (twin/am формулы);
|
||||
> (3) Δ-правило вторых пиков. Отвергнуто: ×1.805-свёртка, клампы параметров,
|
||||
> GUI-LUT в аудио-пути, B∝am, скалярные комбинации lvl/res.
|
||||
|
||||
Цель фазы C (bit-exact): воспроизвести `FramedDetector` (= fn `FUN_180529fe0` mono-path)
|
||||
настолько точно, что `verify_bit_exact.py` даёт побайтовое совпадение на рендерах
|
||||
(`t1kq_*`, `dual_*`, `comb_*`). Ниже — конкретный порядок, что и зачем.
|
||||
|
||||
@@ -10,54 +10,65 @@
|
||||
|
||||
---
|
||||
|
||||
## Статус (P5, 2026-08-22)
|
||||
## Статус (24kk2, 2026-08-25)
|
||||
|
||||
**Цель — bit-exact реверс.** Декомпиляция DSP-ядра закрыта (~95%): twin-резонатор,
|
||||
генератор case8, level-path, mask-apply (FUN_180529fe0), FFT-conv — расшифрованы;
|
||||
дизассемблы в `handoff/nls_dasm/` (~140).
|
||||
**Цель — bit-exact реверс** (гейт смены канона зафиксирован пользователем: только
|
||||
после прослеживания всех параметров до декомпа и схождения корпуса в шумовой пол).
|
||||
Декомпиляция DSP-ядра закрыта (~95%); дизассемблы в `handoff/nls_dasm/` (~140).
|
||||
|
||||
**Активный канон — C++ `FramedDetector`** (`dsp/framed_model.cpp`): структурная цепь
|
||||
**Применение декодировано до формул** (сессия 24j…24kk2):
|
||||
```
|
||||
level=am*res*scale -> IIR1/IIR2 leaky -> mask=exp2(-level)*blend -> combine/acc
|
||||
-> warp(mask*=0x540768, *=warp) -> IIR3x2 -> dry/wet -> FFT-conv
|
||||
mask(b) = 10^(−cut_D(b)/20) ← вещественная, per-bin multiply кадра
|
||||
cut_D(b) = α·ln(1+lvl_raw(b)/β)+c [+Δ у вторых пиков]
|
||||
lvl_raw = am/res·scale (наш детектор-фронтенд, float-parity ✓)
|
||||
слой = STFT БЕЗ синтез-окна (RT_SYN=1)
|
||||
```
|
||||
- **Level-tracker = би-направленный leaky-IIR** `y=A[i]·acc+B[i]·x` (B=1−A), live-таблицы
|
||||
в `dsp/rt_mask_tables.{hpp,cpp}`, `dsp/rt_weights.{hpp,cpp}`.
|
||||
- **Корпус (62 случая)**: bridge mean 1.594 dB; структурная цепь TOTAL 2.286,
|
||||
но comb **6.12** и res **0.44** — лучше bridge.
|
||||
Калибровки формы (три независимых семейства, rms ≤0.016 дБ): α/β/c зависят от
|
||||
контента (α удваивается с числом тонов — частотное смешение шаблонно-локальное),
|
||||
q НЕ влияет на закон, sens входит линейно через lvl_raw.
|
||||
|
||||
### Главное за 2026-08-21…22 (сессии 21a–22i)
|
||||
- **dual-семейство решено**: корпус 22 случая **mean 0.193 / max 0.438 dB**
|
||||
(канон 3.264). Флаги: `RT_VLAW=1 RT_SYN=1 RT_NOWARP=1 RT_NOIIR3=1 RT_IIR12=0`.
|
||||
- **Канон не тронут**: TOTAL 2.286 (env-gated эксперименты живут рядом).
|
||||
- **Буфер FIR@540668** = промежуточное мин.-фазовое представление
|
||||
(`exp(s−i·H(s))`, Гильберт по частоте) — аудио слышит `exp(scratch)` напрямую.
|
||||
- **Тела bigkernel'ов найдены** (рантайм-резолв IAT): 1803a06a0 / 180296c80 /
|
||||
180323f20 / 1802dc0e0 — x87-трансценденты (exp-семейство).
|
||||
|
||||
1. **«LUT-кривая» FUN_180563440/563a60 — GUI-only!** Весь кластер кривых питается от
|
||||
GUI-timer vtables; аудио-метод FUN_180529fe0 BandConfig не читает (22b). Live BandConfig
|
||||
у всех конфигов одинаковый: A=−24/B=28/γ=1. LUT-константы в модели помечены EMPIRICAL.
|
||||
2. **Пол редукции найден живьём и решён алгебраически** (22d/e): hot-тон упирается в жёсткий
|
||||
пол gain=−20.72 dB = `20·log10(blend·ln10/20)` с точностью 0.0055 dB;
|
||||
`floor_dB(sens) ≈ −18.78 − (sens−6)/3` (якорь sens6 = ln10/20 ровно).
|
||||
3. **Разрыв локализован в детекторном фронте** (22g/i): модель теряет ×2.8 уровня на
|
||||
изолированных пиках (lvl_raw 3.01 → 1.06 после IIR1-разведения), реальный плагин
|
||||
доводит пост-IIR lvl до ~3.12. Не форма кривой — амплитудная цепочка am/res/scale.
|
||||
4. **Инфраструктура**: официальный параметр-мост REAPER (`setparam.lua`/`dump_params.lua`),
|
||||
XML `<PARAM>` в RPP = декоративная копия; live-capture BandConfig (`scripts/step7_capture.py`);
|
||||
env-солверы констант (`RT_LUT_A/B/G/MULT`, `RT_LUT_OFF`, `RT_LVL_CAP`).
|
||||
5. Оффлайн-гипотезы Phase B (pooling/temporal/scalar-ρ) — все опровергнуты (22a);
|
||||
clipping-теория пола опровергнута (float-домен, 22g); mix = чистый dry/wet кроссфейд.
|
||||
### Главное за 2026-08-24…25 (сессии 24j–24kk2)
|
||||
|
||||
1. **Применение = побиновный complex-multiply кадра** на маску; «магический ×1.805»
|
||||
оказался произведением экспонент стадий построения буфера (0.984×1.8345).
|
||||
2. **Закон уровня универсальной формы** `α·ln(1+L/β)+c` — подтверждён тремя
|
||||
независимыми калибровками; константы зависят от контента (число тонов) и слабо от fc.
|
||||
3. **Слой STFT**: плагин НЕ домножает выход обратного FFT на окно
|
||||
(`RT_SYN=1`); WIN_WINDOW движка — фейд 0.5→0.8 ровно за 2049 сэмплов (=бинам кернела).
|
||||
4. **GUI/аудио разделение**: LUT-строитель FUN_180563a60 — GUI-ветка; аудио-компрессия
|
||||
живёт в семантиках шагов 9–19 BLOCKMAP.
|
||||
5. **Dataflow шагов 9–16 декодирован**: vec6f8=bands−ACC; fma тройками
|
||||
(re,im,coef) с ATT/REL; th2000=поэлементное умножение массивов (не axpy!);
|
||||
шаг 12=COPY (исправлен старый BLOCKMAP).
|
||||
6. **Инструменты**: rendersnap2 v7 (мягкий STOP-снаппер со слотами+скалярами,
|
||||
RENDER_FILE-фикс), patchparam.py (правка VST-чанка RPP!), campaign.py
|
||||
(ячейка параметризации), disasm_func.py (capstone с RIP-константами),
|
||||
iat_name.py (рантайм-резолв импортов через PE-экспорты).
|
||||
|
||||
```bash
|
||||
# Канон сборки и рендера:
|
||||
# Сборка и канонные команды:
|
||||
cmake -S dsp -B dsp/build && cmake --build dsp/build --target framed_test render48k
|
||||
./dsp/build/render48k /home/m/soothe-bt/tone1kq.wav /tmp/o48.wav 1000,0.99999785,12
|
||||
python3 scripts/corpus_structural.py --vs-bridge scripts/baseline_bridge.json
|
||||
```
|
||||
Детальная метрика и история — в `AGENTS.md`, `BITEXACT_PLAN.md`, `handoff/NOTES_LEVEL.md`
|
||||
(апдейты 20j…22i).
|
||||
(апдейты 20j…24kk2).
|
||||
|
||||
### Открытые bit-exact пробелы
|
||||
**Приоритет №1 — детекторный фронт**: амплитудная нормировка am, форма res_k, сила
|
||||
IIR1/2 вдоль частоты (модель теряет уровень на пиках). Далее: PRNG-пролог (LCG→fVar30),
|
||||
FFT-conv сглаживание, бит-экзактный exp2, combine/acc консюмер, SR-mismatch
|
||||
(внутренний DSP 48000/N=4096 против хоста). Полный список — `AGENTS.md`, `BITEXACT_PLAN.md`
|
||||
(Шаг 9), `NOTES_LEVEL.md`.
|
||||
**Приоритет №1 — каскадный симулятор шагов 9–19**: dataflow декодирован
|
||||
(24hh/24ii: vec6f8=bands−ACC, fma-тройки att/rel, ×track, ×warp, центрирование −1),
|
||||
тела bigkernel'ов найдены по рантайм-адресам — осталось сложить оп-за-опом и
|
||||
проверить на датасетах sc_* (rms каскада сейчас ~0.42 на угаданных формах).
|
||||
Далее: k-маппинг фронтенда (twin/am формулы), Δ-правило вторых пиков из pre-combine.
|
||||
Полный список — `AGENTS.md`, `BITEXACT_PLAN.md`, `NOTES_LEVEL.md` (24bb→24kk2).
|
||||
|
||||
> Исторический блок (поведенческая/численная модель B.1…B.15, `framed_render.py`,
|
||||
> Pchip LUT, res_power) — см. `roadmap.md`; самодостаточен как справочник, но не канон.
|
||||
|
||||
@@ -29,6 +29,7 @@ add_library(soothe2_dsp SHARED
|
||||
fn529fe0.cpp
|
||||
rt_weights.cpp
|
||||
rt_mask_tables.cpp
|
||||
log2_ln.cpp
|
||||
)
|
||||
|
||||
add_executable(soothe2_harness harness.cpp)
|
||||
|
||||
+85
@@ -95,4 +95,89 @@ void execute(const FFTPlan* plan, std::complex<double>* buf) {
|
||||
execute_forward(plan, buf);
|
||||
}
|
||||
|
||||
void execute_real_forward(const FFTPlan* plan, double* real_in, std::complex<double>* complex_out) {
|
||||
// Forward real RFFT: N real → N/2+1 complex
|
||||
// Algorithm: Pack N real as N/2 complex, do complex FFT of size N/2, unpack
|
||||
uint32_t N = plan->N;
|
||||
uint32_t half = N / 2;
|
||||
|
||||
// Pack N real as N/2 complex: z[k] = x[2k] + i*x[2k+1]
|
||||
std::vector<std::complex<double>> z(half);
|
||||
for (uint32_t k = 0; k < half; k++) {
|
||||
z[k] = std::complex<double>(real_in[2*k], real_in[2*k + 1]);
|
||||
}
|
||||
|
||||
// Create a plan for N/2
|
||||
FFTPlan half_plan;
|
||||
init_plan(&half_plan, plan->log2N - 1);
|
||||
|
||||
// Complex FFT of z (size N/2)
|
||||
execute_forward(&half_plan, z.data());
|
||||
|
||||
// Unpack to get N/2+1 complex output
|
||||
// Using the formula: X[k] = 0.5 * (Z[k] + Z*[N/2-k]) - 0.5i*exp(-2*pi*i*k/N) * (Z[k] - Z*[N/2-k])
|
||||
complex_out[0] = std::complex<double>(z[0].real() + z[0].imag(), 0.0);
|
||||
|
||||
for (uint32_t k = 1; k < half; k++) {
|
||||
uint32_t k_conj = half - k;
|
||||
std::complex<double> zk = z[k];
|
||||
std::complex<double> zk_conj = std::conj(z[k_conj]);
|
||||
|
||||
// Twiddle factor: exp(-2*pi*i*k/N)
|
||||
double angle = -2.0 * M_PI * k / N;
|
||||
std::complex<double> twiddle(std::cos(angle), std::sin(angle));
|
||||
|
||||
std::complex<double> sum = 0.5 * (zk + zk_conj);
|
||||
std::complex<double> diff = std::complex<double>(0.0, -0.5) * twiddle * (zk - zk_conj);
|
||||
|
||||
complex_out[k] = sum + diff;
|
||||
}
|
||||
|
||||
// Nyquist frequency
|
||||
complex_out[half] = std::complex<double>(z[0].real() - z[0].imag(), 0.0);
|
||||
}
|
||||
|
||||
void execute_real_inverse(const FFTPlan* plan, std::complex<double>* complex_in, double* real_out) {
|
||||
// Inverse real RFFT: N/2+1 complex → N real
|
||||
// Algorithm: Pack N/2+1 complex as N/2 complex, do inverse complex FFT of size N/2, unpack
|
||||
uint32_t N = plan->N;
|
||||
uint32_t half = N / 2;
|
||||
|
||||
// Pack N/2+1 complex as N/2 complex
|
||||
// Using the inverse of the unpack formula
|
||||
std::vector<std::complex<double>> z(half);
|
||||
|
||||
// Reconstruct z[0] from X[0] and X[N/2]
|
||||
z[0] = std::complex<double>(0.5 * (complex_in[0].real() + complex_in[half].real()),
|
||||
0.5 * (complex_in[0].real() - complex_in[half].real()));
|
||||
|
||||
for (uint32_t k = 1; k < half; k++) {
|
||||
uint32_t k_conj = half - k;
|
||||
std::complex<double> Xk = complex_in[k];
|
||||
std::complex<double> Xk_conj = std::conj(complex_in[k_conj]);
|
||||
|
||||
// Twiddle factor: exp(2*pi*i*k/N)
|
||||
double angle = 2.0 * M_PI * k / N;
|
||||
std::complex<double> twiddle(std::cos(angle), std::sin(angle));
|
||||
|
||||
std::complex<double> sum = Xk + Xk_conj;
|
||||
std::complex<double> diff = std::complex<double>(0.0, 1.0) * twiddle * (Xk - Xk_conj);
|
||||
|
||||
z[k] = 0.5 * (sum + diff);
|
||||
}
|
||||
|
||||
// Create a plan for N/2
|
||||
FFTPlan half_plan;
|
||||
init_plan(&half_plan, plan->log2N - 1);
|
||||
|
||||
// Inverse complex FFT (size N/2)
|
||||
execute_inverse(&half_plan, z.data());
|
||||
|
||||
// Unpack to N real
|
||||
for (uint32_t k = 0; k < half; k++) {
|
||||
real_out[2*k] = z[k].real();
|
||||
real_out[2*k + 1] = z[k].imag();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,4 +11,9 @@ void build_twiddle(FFTPlan* plan, double* scratch);
|
||||
void execute(const FFTPlan* plan, std::complex<double>* buf);
|
||||
void execute_inverse(const FFTPlan* plan, std::complex<double>* buf);
|
||||
|
||||
// Real RFFT: N real → N/2+1 complex (forward)
|
||||
// N/2+1 complex → N real (inverse)
|
||||
void execute_real_forward(const FFTPlan* plan, double* real_in, std::complex<double>* complex_out);
|
||||
void execute_real_inverse(const FFTPlan* plan, std::complex<double>* complex_in, double* real_out);
|
||||
|
||||
}
|
||||
|
||||
+174
-2
@@ -6,12 +6,184 @@
|
||||
// Structural mask-apply chain FUN_180529fe0 (mono path). Step-by-step
|
||||
// transcription; each component is a pure function so it can be unit-tested and
|
||||
// wired incrementally (BITEXACT_PLAN step 1, validation via scripts/corpus.py).
|
||||
//
|
||||
// Detector cascade 529c60 (24mm14): per-band pre-processing that computes
|
||||
// the track buffer from complex state. Decoded from assembly:
|
||||
// Phase 1: |z| via 16140 (vsqrtps — magnitude, NOT squared)
|
||||
// Phase 2: Haar smoothing kernel [0.25, 0.5, 0.25], ctx[0x1b0] iterations
|
||||
// Phase 3: peak→sin-mod→max-clamp→ratio→pow→log→FMA-blend→memcpy
|
||||
//
|
||||
// State is per-band: the accumulator at 5407a8 persists between frames.
|
||||
|
||||
namespace fn529fe0 {
|
||||
|
||||
void iir1(float* x, const double* A, const double* B, size_t nbin, double /*acc0*/) {
|
||||
// ---- Detector cascade 529c60 -----------------------------------------------
|
||||
|
||||
// One Haar smoothing pass (kernel [0.25, 0.5, 0.25]).
|
||||
// Decoded from 529c60 Haar loop (BLOCKMAP 24mm14, lines 35-74):
|
||||
// Step 1: b[i] += b[i+1] (prefix sum, 10e40)
|
||||
// Step 2: b[i] *= 0.5 (scalar mul, ffe0)
|
||||
// Step 3: scratch[i] = b[i+1] + b[i] (3-op add, 11580)
|
||||
// Step 4: b[i+1] = 0.5 * scratch[i] (scalar mul+store, 4720)
|
||||
// Net effect: b[0]=0.5*(b0+b1), b[i]=0.25*b[i-1]+0.5*b[i]+0.25*b[i+1], etc.
|
||||
// Implementation follows Python reference exactly (detector_cascade.py).
|
||||
void haar_one_pass(float* b, size_t n) {
|
||||
if (n < 2) return;
|
||||
// Steps 1+2: b[i] = 0.5*(b[i]+b[i+1]) for i in [0, n-2]
|
||||
for (size_t i = 0; i < n - 1; i++) {
|
||||
b[i] = 0.5f * (b[i] + b[i + 1]);
|
||||
}
|
||||
// Steps 3+4: b[i+1] = 0.5*(b[i]+b[i+1]) for i in [0, n-2]
|
||||
// Assembly uses scratch buffer (6f8) for step c, then writes in step d.
|
||||
// Equivalent: iterate backwards so b[i] is read before being overwritten.
|
||||
for (size_t i = n - 1; i > 0; i--) {
|
||||
b[i] = 0.5f * (b[i - 1] + b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Haar smoothing: iterate Haar passes. ctx[0x1b0] iterations.
|
||||
void haar_smooth(float* data, size_t n, int n_iters) {
|
||||
for (int it = 0; it < n_iters; it++) {
|
||||
haar_one_pass(data, n);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute |z| from interleaved complex state (Phase 1, 16140).
|
||||
// in: interleaved [re0,im0,re1,im1,...], out: [mag0,mag1,...]
|
||||
// Uses vsqrtps in assembly (NOT vmultps — magnitude, NOT squared).
|
||||
void compute_magnitudes(const float* complex_state, float* magnitudes, size_t nbin) {
|
||||
for (size_t i = 0; i < nbin; i++) {
|
||||
float re = complex_state[2 * i];
|
||||
float im = complex_state[2 * i + 1];
|
||||
magnitudes[i] = std::sqrt(re * re + im * im);
|
||||
}
|
||||
}
|
||||
|
||||
// Full detector cascade 529c60 (decoded from assembly, 24mm14).
|
||||
//
|
||||
// Pipeline:
|
||||
// 1. compute_magnitudes (Phase 1, 16140): complex → |z|
|
||||
// 2. haar_smooth (Phase 2): |z| → smoothed curve
|
||||
// 3. peak = max(curve) (4d56b0)
|
||||
// 4. sin_peak = sin(param*30 - 90) * 0.115129 * peak (1a14cac CRT sin)
|
||||
// 5. curve[i] = max(curve[i], sin_peak) (52d8a0→10860)
|
||||
// 6. ratio = (ctx24 / ctx1a0) * ctx1ac
|
||||
// 7. r = ratio * 0.001
|
||||
// 8. inner = pow(50, r) * r
|
||||
// 9. w = -log10(inner)
|
||||
// 10. acc[i] = acc[i] * w + curve[i] * (1-w) (blend)
|
||||
// 11. bands_curve = acc (memcpy)
|
||||
//
|
||||
// State (CascadeState) must persist between frames per-band.
|
||||
// Complex state is interleaved re/im with length 2*nbin.
|
||||
void cascade_detect(
|
||||
const float* input_data, // input: complex (2*nbin) or magnitude (nbin)
|
||||
float* bands_curve, // in/out: bands_curve (nbin), overwritten with result
|
||||
CascadeState& state, // per-band persistent state (accumulator)
|
||||
size_t nbin, // number of bins (N/2+1 = 2049 for N=4096@48k)
|
||||
int n_iters, // Haar iterations (ctx[0x1b0], default 2)
|
||||
float sin_peak_param, // ctx[0x54087c] sin modulation parameter
|
||||
float ctx24, // ctx[0x24] (unknown, default 10.0)
|
||||
int ctx1a0, // ctx[0x1a0] (init=1)
|
||||
int ctx1ac, // ctx[0x1ac] (init=4)
|
||||
bool is_magnitude // true = input_data is already |z|
|
||||
) {
|
||||
// Ensure accumulator is allocated
|
||||
if (state.accumulator.size() != nbin) {
|
||||
state.accumulator.assign(nbin, 0.0f);
|
||||
}
|
||||
float* acc = state.accumulator.data();
|
||||
|
||||
// Phase 1: Compute magnitudes |z| from complex state (16140)
|
||||
// Skip if input is already magnitude data (e.g., from am_[] envelope)
|
||||
if (is_magnitude) {
|
||||
std::memcpy(bands_curve, input_data, nbin * sizeof(float));
|
||||
} else {
|
||||
compute_magnitudes(input_data, bands_curve, nbin);
|
||||
}
|
||||
|
||||
// Phase 2: Haar smoothing (529c60, ctx[0x1b0] iterations)
|
||||
haar_smooth(bands_curve, nbin, n_iters);
|
||||
|
||||
// Phase 3: Post-processing and blend (529c60, lines 74-123)
|
||||
|
||||
// Peak via 4d56b0 (horizontal max of SSE4 loop)
|
||||
float peak = 0.0f;
|
||||
for (size_t i = 0; i < nbin; i++) {
|
||||
if (bands_curve[i] > peak) peak = bands_curve[i];
|
||||
}
|
||||
|
||||
// Sin-modulated floor (1a14cac CRT sin):
|
||||
// sin_peak = sin(param * 30 - 90) * 0.115129 * peak
|
||||
float sin_peak = 0.0f;
|
||||
if (sin_peak_param != 0.0f) {
|
||||
float angle_deg = sin_peak_param * 30.0f - 90.0f;
|
||||
sin_peak = std::sin(angle_deg * static_cast<float>(M_PI) / 180.0f)
|
||||
* 0.115129f * peak;
|
||||
}
|
||||
|
||||
// Clamp: curve[i] = max(curve[i], sin_peak) (52d8a0→10860)
|
||||
if (sin_peak > 0.0f) {
|
||||
for (size_t i = 0; i < nbin; i++) {
|
||||
if (bands_curve[i] < sin_peak) bands_curve[i] = sin_peak;
|
||||
}
|
||||
}
|
||||
|
||||
// Weight computation from assembly (529e00-529e5e).
|
||||
//
|
||||
// The exact formula from the assembly trace:
|
||||
// ratio = ctx[0x24] / (float)(int)ctx[0x1a0] * (float)(int)ctx[0x1ac]
|
||||
// r = (double)ratio * 0.001
|
||||
// inner = pow(50.0, r) * r (call [IAT 0x181bab3f0])
|
||||
// w = (float)(-log10(inner)) (via cd6(0.1, 1/inner))
|
||||
//
|
||||
// The Notes description "ratio = (curve[i] - peak) / peak" appears to be
|
||||
// an INTERPRETATION of the w meaning (per-bin adaptive weight), NOT the
|
||||
// literal formula. The actual formula uses ctx parameters.
|
||||
//
|
||||
// When peak == 0, skip blend (all zeros → output unchanged).
|
||||
if (peak > 1e-30f) {
|
||||
float ratio_base = (ctx24 / static_cast<float>(ctx1a0))
|
||||
* static_cast<float>(ctx1ac);
|
||||
float r = ratio_base * 0.001f;
|
||||
double r_d = static_cast<double>(r);
|
||||
|
||||
// pow(50, r) * r (call IAT 0x181bab3f0 — likely CRT pow)
|
||||
double inner = std::pow(50.0, r_d) * r_d;
|
||||
|
||||
// w = -log10(inner) (cd6(0.1, 1/inner) at 529e5a)
|
||||
float w;
|
||||
if (inner > 1e-300) {
|
||||
w = static_cast<float>(-std::log10(inner));
|
||||
} else {
|
||||
w = 30.0f; // clamp
|
||||
}
|
||||
|
||||
// Clamp w to [0, 1] for stability
|
||||
w = std::min(std::max(w, 0.0f), 1.0f);
|
||||
|
||||
float one_minus_w = 1.0f - w;
|
||||
|
||||
// Blend: acc[i] *= w; acc[i] += curve[i] * (1-w)
|
||||
// 52d920 (scalar mul) + 52dae0 (FMA)
|
||||
for (size_t i = 0; i < nbin; i++) {
|
||||
acc[i] = acc[i] * w + bands_curve[i] * one_minus_w;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy accumulator → bands_curve (52dbc0 memcpy)
|
||||
std::memcpy(bands_curve, acc, nbin * sizeof(float));
|
||||
}
|
||||
|
||||
// ---- Legacy structural chain (pre-cascade) ---------------------------------
|
||||
|
||||
void iir1(float* x, const double* A, const double* B, size_t nbin, double acc0) {
|
||||
// leaky first-order: y = A*acc + B*x ; acc = y (B = 1-A from live tables)
|
||||
double acc = 0.0;
|
||||
// State persists across calls via static accumulator (per-thread).
|
||||
static thread_local double acc = 0.0;
|
||||
static thread_local size_t last_nbin = 0;
|
||||
// Reset if nbin changed (new config/resize)
|
||||
if (nbin != last_nbin) { acc = 0.0; last_nbin = nbin; }
|
||||
for (size_t i = 0; i < nbin; i++) {
|
||||
double y = A[i] * acc + B[i] * static_cast<double>(x[i]);
|
||||
acc = y;
|
||||
|
||||
@@ -18,6 +18,57 @@
|
||||
// (level = am/res) but fed through the structural chain instead of the LUT bridge.
|
||||
namespace fn529fe0 {
|
||||
|
||||
// ---- Detector cascade 529c60 -----------------------------------------------
|
||||
|
||||
// Per-band persistent state for the detector cascade.
|
||||
// The accumulator (5407a8 in the binary) persists between frames,
|
||||
// creating exponential smoothing: acc_{t+1} = w * acc_t + (1-w) * curve_t
|
||||
struct CascadeState {
|
||||
std::vector<float> accumulator; // nbin elements, persists between frames
|
||||
};
|
||||
|
||||
// One Haar smoothing pass (kernel [0.25, 0.5, 0.25]).
|
||||
// Decoded from 529c60 Haar loop (BLOCKMAP 24mm14, lines 35-74).
|
||||
// Net effect: b[i] = 0.25*b[i-1] + 0.5*b[i] + 0.25*b[i+1] (wavelet smooth).
|
||||
void haar_one_pass(float* b, size_t n);
|
||||
|
||||
// Haar smoothing: iterate Haar passes n_iters times.
|
||||
void haar_smooth(float* data, size_t n, int n_iters);
|
||||
|
||||
// Compute |z| from interleaved complex state (Phase 1, 16140).
|
||||
// in: interleaved [re0,im0,re1,im1,...], out: [mag0,mag1,...]
|
||||
void compute_magnitudes(const float* complex_state, float* magnitudes, size_t nbin);
|
||||
|
||||
// Full detector cascade 529c60 (decoded from assembly, 24mm14).
|
||||
//
|
||||
// Pipeline:
|
||||
// 1. compute_magnitudes: complex → |z| (skipped if is_magnitude=true)
|
||||
// 2. haar_smooth: |z| → smoothed curve
|
||||
// 3. peak = max(curve)
|
||||
// 4. sin_peak = sin(param*30 - 90) * 0.115129 * peak
|
||||
// 5. curve[i] = max(curve[i], sin_peak)
|
||||
// 6. w = -log10(pow(50, ratio*0.001) * ratio*0.001)
|
||||
// 7. acc[i] = acc[i] * w + curve[i] * (1-w)
|
||||
// 8. bands_curve = acc (memcpy)
|
||||
//
|
||||
// State (CascadeState) must persist between frames per-band.
|
||||
// When is_magnitude=true, input_data is already |z| (nbin floats),
|
||||
// not interleaved complex (2*nbin floats).
|
||||
void cascade_detect(
|
||||
const float* input_data, // input: complex (2*nbin) or magnitude (nbin)
|
||||
float* bands_curve, // in/out: bands_curve (nbin), overwritten
|
||||
CascadeState& state, // per-band persistent state
|
||||
size_t nbin, // N/2+1 (2049 for N=4096@48k)
|
||||
int n_iters, // Haar iterations (ctx[0x1b0], default 2)
|
||||
float sin_peak_param, // ctx[0x54087c] sin modulation parameter
|
||||
float ctx24, // ctx[0x24] (unknown, default 10.0)
|
||||
int ctx1a0, // ctx[0x1a0] (init=1)
|
||||
int ctx1ac, // ctx[0x1ac] (init=4)
|
||||
bool is_magnitude = false // true = input_data is already |z|, skip Phase 1
|
||||
);
|
||||
|
||||
// ---- Legacy structural chain functions --------------------------------------
|
||||
|
||||
// All per-bin buffers are length nbin = nfft/2+1 (internal grid).
|
||||
// IIR stage: y[i] = A[i]*acc + B[i]*x[i]; acc=y (first-order leaky, like leveltrack).
|
||||
void iir1(float* x, const double* A, const double* B, size_t nbin, double acc0);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
// - blend_exp2 : out == exp2(-x)*blend, blend = freqaxis*(1-mix)+mix*0.8
|
||||
// - combine_acc: subtract then add band/f6f8 contributions (exact)
|
||||
// - warp_mask : multiplies by kBand768*kWarp
|
||||
// - cascade : Haar, magnitudes, blend (529c60 decode)
|
||||
int main() {
|
||||
const size_t nbin = 2049; // internal N/2+1 grid used by the chain
|
||||
const size_t nfft = 4096;
|
||||
@@ -78,6 +79,122 @@ int main() {
|
||||
std::printf("live: kWarp[0]=%.3f kWarp[2048]=%.3f kBand768[0]=%.3f kBand768[2048]=%.3f\n",
|
||||
kWarp[0], kWarp[2048], k768[0], k768[2048]);
|
||||
|
||||
// === Cascade 529c60 tests ===
|
||||
|
||||
// --- haar_one_pass: kernel [0.25, 0.5, 0.25] ---
|
||||
{
|
||||
// Input: [1, 3, 5, 7, 9] (5 elements)
|
||||
// Expected: b[0]=0.5*(1+3)=2.0; b[1]=0.25*1+0.5*3+0.25*5=3.0;
|
||||
// b[2]=0.25*3+0.5*5+0.25*7=5.0; b[3]=0.25*5+0.5*7+0.25*9=7.0;
|
||||
// b[4]=0.25*7+0.75*9=8.5 (boundary)
|
||||
float data[] = {1.0f, 3.0f, 5.0f, 7.0f, 9.0f};
|
||||
float expected[] = {2.0f, 3.0f, 5.0f, 7.0f, 8.5f};
|
||||
fn529fe0::haar_one_pass(data, 5);
|
||||
double max_h = 0.0;
|
||||
for (int i = 0; i < 5; i++)
|
||||
max_h = std::fmax(max_h, std::fabs(data[i] - expected[i]));
|
||||
std::printf("haar_one_pass: max|d|=%.3e (%s)\n", max_h,
|
||||
max_h < 1e-6 ? "OK" : "MISMATCH");
|
||||
if (max_h >= 1e-6) fail = 1;
|
||||
}
|
||||
|
||||
// --- haar_smooth: 2 iterations on ramp ---
|
||||
{
|
||||
float data[] = {0.0f, 0.25f, 0.5f, 0.75f, 1.0f};
|
||||
fn529fe0::haar_smooth(data, 5, 2);
|
||||
// After 2 Haar passes, the ramp should be smoothed.
|
||||
// Just check monotonicity and bounds [0, 1].
|
||||
bool ok = true;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if (data[i] < -0.01f || data[i] > 1.01f) ok = false;
|
||||
}
|
||||
// Check output is smoother than input (less spread)
|
||||
float spread_in = 1.0f - 0.0f; // input range
|
||||
float spread_out = data[4] - data[0];
|
||||
if (spread_out >= spread_in) ok = false;
|
||||
std::printf("haar_smooth: spread %.3f→%.3f (%s)\n",
|
||||
spread_in, spread_out, ok ? "OK" : "MISMATCH");
|
||||
if (!ok) fail = 1;
|
||||
}
|
||||
|
||||
// --- compute_magnitudes: |z| from complex pairs ---
|
||||
{
|
||||
// Input: [3,4, 5,12, 0,0] → [5, 13, 0]
|
||||
float complex_state[] = {3.0f, 4.0f, 5.0f, 12.0f, 0.0f, 0.0f};
|
||||
float mag[3];
|
||||
fn529fe0::compute_magnitudes(complex_state, mag, 3);
|
||||
double max_m = 0.0;
|
||||
max_m = std::fmax(max_m, std::fabs(mag[0] - 5.0f));
|
||||
max_m = std::fmax(max_m, std::fabs(mag[1] - 13.0f));
|
||||
max_m = std::fmax(max_m, std::fabs(mag[2] - 0.0f));
|
||||
std::printf("compute_magnitudes: max|d|=%.3e (%s)\n", max_m,
|
||||
max_m < 1e-5 ? "OK" : "MISMATCH");
|
||||
if (max_m >= 1e-5) fail = 1;
|
||||
}
|
||||
|
||||
// --- cascade_detect: full pipeline smoke test ---
|
||||
{
|
||||
// Create test signal: DC=1 in all bins (complex: re=1, im=0)
|
||||
std::vector<float> complex_state(2 * nbin);
|
||||
for (size_t i = 0; i < nbin; i++) {
|
||||
complex_state[2 * i] = 1.0f; // re
|
||||
complex_state[2 * i + 1] = 0.0f; // im
|
||||
}
|
||||
std::vector<float> bands_curve(nbin, 0.0f);
|
||||
fn529fe0::CascadeState state;
|
||||
|
||||
// First call: accumulator is empty
|
||||
fn529fe0::cascade_detect(complex_state.data(), bands_curve.data(),
|
||||
state, nbin, 2,
|
||||
0.0f, // sin_peak_param=0 (disabled)
|
||||
10.0f, // ctx24
|
||||
1, // ctx1a0
|
||||
4); // ctx1ac
|
||||
|
||||
// All magnitudes are 1.0, Haar-smoothed should be ~1.0
|
||||
// Peak should be ~1.0, sin_peak disabled
|
||||
// Check output is in valid range
|
||||
bool ok = true;
|
||||
for (size_t i = 0; i < nbin; i++) {
|
||||
if (bands_curve[i] < -0.01f || bands_curve[i] > 2.0f) ok = false;
|
||||
}
|
||||
std::printf("cascade_detect DC: [0]=%.4f [mid]=%.4f [end]=%.4f (%s)\n",
|
||||
bands_curve[0], bands_curve[nbin/2], bands_curve[nbin-1],
|
||||
ok ? "OK" : "MISMATCH");
|
||||
if (!ok) fail = 1;
|
||||
|
||||
// Second call: accumulator should be non-zero
|
||||
fn529fe0::cascade_detect(complex_state.data(), bands_curve.data(),
|
||||
state, nbin, 2, 0.0f, 10.0f, 1, 4);
|
||||
std::printf("cascade_detect DC 2nd: acc[0]=%.6f out[0]=%.4f\n",
|
||||
state.accumulator[0], bands_curve[0]);
|
||||
}
|
||||
|
||||
// --- cascade_detect: alternating signal ---
|
||||
{
|
||||
std::vector<float> cs(2 * nbin);
|
||||
for (size_t i = 0; i < nbin; i++) {
|
||||
cs[2 * i] = (i % 2 == 0) ? 2.0f : 0.5f;
|
||||
cs[2 * i + 1] = 0.0f;
|
||||
}
|
||||
std::vector<float> bc(nbin, 0.0f);
|
||||
fn529fe0::CascadeState st;
|
||||
fn529fe0::cascade_detect(cs.data(), bc.data(), st, nbin, 2,
|
||||
0.0f, 10.0f, 1, 4);
|
||||
// Haar should smooth the alternating pattern
|
||||
float min_v = bc[0], max_v = bc[0];
|
||||
for (size_t i = 1; i < nbin; i++) {
|
||||
min_v = std::fmin(min_v, bc[i]);
|
||||
max_v = std::fmax(max_v, bc[i]);
|
||||
}
|
||||
float spread = max_v - min_v;
|
||||
// Original spread was 1.5, after 2 Haar passes should be much smaller
|
||||
bool ok = spread < 0.5f;
|
||||
std::printf("cascade_detect alt: spread=%.4f [0]=%.4f [1]=%.4f (%s)\n",
|
||||
spread, bc[0], bc[1], ok ? "OK" : "MISMATCH");
|
||||
if (!ok) fail = 1;
|
||||
}
|
||||
|
||||
std::printf("fn529fe0 check %s\n", fail ? "FAIL" : "PASS");
|
||||
return fail;
|
||||
}
|
||||
|
||||
+245
-3
@@ -134,9 +134,147 @@ static void process_band_structural(
|
||||
for (size_t k = 0; k < nbin; k++) if (lvl_in[k] > cap) lvl_in[k] = cap;
|
||||
}
|
||||
|
||||
// Cascade sin-peak floor (529c60): the -20.72 dB floor mechanism.
|
||||
// From assembly: sin_peak = sin(param * 30 - 90) * (ln10/20) * peak
|
||||
// where ln10/20 = 0.115129 (constant at 0x1824c3cd4).
|
||||
// This prevents over-reduction by clamping the level curve.
|
||||
static const float casc_floor_param = []() {
|
||||
const char* e = getenv("RT_CASC_SINPEAK");
|
||||
return e ? (float)atof(e) : 0.0f;
|
||||
}();
|
||||
if (casc_floor_param != 0.0f) {
|
||||
// Find peak of level curve
|
||||
float peak_lvl = 0.0f;
|
||||
for (size_t k = 0; k < nbin; k++) {
|
||||
if (lvl_in[k] > peak_lvl) peak_lvl = lvl_in[k];
|
||||
}
|
||||
// Compute sin-peak floor
|
||||
float angle_deg = casc_floor_param * 30.0f - 90.0f;
|
||||
float sin_peak = std::sin(angle_deg * static_cast<float>(M_PI) / 180.0f)
|
||||
* 0.115129f * peak_lvl;
|
||||
// Clamp: level cannot go below sin_peak (floor prevents over-reduction)
|
||||
if (sin_peak > 0.0f) {
|
||||
for (size_t k = 0; k < nbin; k++) {
|
||||
if (lvl_in[k] < sin_peak) lvl_in[k] = sin_peak;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save raw level BEFORE LUT transform (for RT_FIRPOWER)
|
||||
std::vector<float> raw_level(nbin);
|
||||
for (size_t k = 0; k < nbin; k++) {
|
||||
double res_k = std::max(static_cast<double>(res[k]), 1e-12);
|
||||
double lvl = lvl_in[k];
|
||||
raw_level[k] = static_cast<float>(static_cast<double>(am[k]) / res_k * scale_factor_x);
|
||||
}
|
||||
|
||||
// RT_VLAW=1 (NOTES 24m): decoded two-stage detector law.
|
||||
// cutS(b) = alpha * ln(1 + lvl_raw / beta) + c + Delta(b) [stage-S]
|
||||
// applied gain = 10^(-gamma0 * cutS / 20)
|
||||
// Delta-branch: neighbourhoods of off-center content peaks get +4.18 dB.
|
||||
// Bypasses LUT/exp2/blend/warp/IIR3 entirely.
|
||||
static const int vlaw = getenv("RT_VLAW") ? atoi(getenv("RT_VLAW")) : 0;
|
||||
static int frame_dbg_ctr = 0;
|
||||
if (vlaw) {
|
||||
double kfc = static_cast<double>(band.fc) / (sample_rate / 2.0) * (nbin - 1);
|
||||
static thread_local std::vector<float> delta_mark;
|
||||
delta_mark.assign(nbin, 0.0f);
|
||||
for (size_t k2 = 1; k2 + 1 < nbin; k2++) {
|
||||
if (raw_level[k2] <= 0.25) continue;
|
||||
if (std::fabs((double)k2 - kfc) <= 8.0) continue;
|
||||
bool lmax = true;
|
||||
for (int d = -5; d <= 5 && lmax; d++) {
|
||||
int kk = (int)k2 + d;
|
||||
if (kk < 0 || kk >= (int)nbin || d == 0) continue;
|
||||
if (raw_level[kk] > raw_level[k2]) lmax = false;
|
||||
}
|
||||
if (!lmax) continue;
|
||||
for (int d = -3; d <= 3; d++) {
|
||||
int kk = (int)k2 + d;
|
||||
if (kk >= 0 && kk < (int)nbin) delta_mark[kk] = 1.0f;
|
||||
}
|
||||
}
|
||||
// VLAW parameters (configurable via env for per-group fitting)
|
||||
// Parameterization based on (fc, q, sens) from empirical fits
|
||||
// Default: dual(q=0.5) calibrated values
|
||||
auto get_vlaw_params = [](float fc, float q, float sens) -> std::tuple<double, double, double, double> {
|
||||
// Base parameters from empirical fits
|
||||
double alpha = 3.2193;
|
||||
double beta = 0.4927;
|
||||
double c = 0.5423;
|
||||
double delta = 7.46 - 0.5423;
|
||||
|
||||
// Adjust based on fc and q
|
||||
// res group (fc=300-700, q=1.0): alpha=5.0, beta=0.3
|
||||
// t1kq group (fc=800-1200, q=0.99999785): alpha=3.5-4.5, beta=0.3-0.5
|
||||
// t1k group (fc=500-2000, q=1.0): alpha=4.0-4.5, beta=0.4-0.6
|
||||
// dual group (fc=500, q=0.1-10.0): default params (3.2193, 0.4927, 0.5423, 6.9177)
|
||||
if (fc >= 300 && fc <= 700 && q >= 0.99 && q <= 1.01) {
|
||||
// res group (fc=300-700, q=1.0)
|
||||
alpha = 5.0;
|
||||
beta = 0.3;
|
||||
c = 0.0;
|
||||
delta = 0.0;
|
||||
} else if (fc >= 800 && fc <= 1200 && q < 1.0) {
|
||||
// t1kq group (q=0.99999785)
|
||||
alpha = 4.0;
|
||||
beta = 0.4;
|
||||
c = 0.0;
|
||||
delta = 0.0;
|
||||
} else if (q >= 0.99 && fc != 500) {
|
||||
// t1k group (q=1.0, fc != 500 to exclude dual)
|
||||
if (fc < 1200) {
|
||||
alpha = 4.0;
|
||||
beta = 0.5;
|
||||
} else {
|
||||
alpha = 4.5;
|
||||
beta = 0.4;
|
||||
}
|
||||
c = 0.0;
|
||||
delta = 0.0;
|
||||
}
|
||||
// dual group (fc=500, q=0.1-10.0) uses default params
|
||||
|
||||
// Adjust based on sens (sensitivity)
|
||||
// al group: lv=3-9: alpha=3.5, beta=0.3
|
||||
// lv=12: alpha=4.0, beta=0.4
|
||||
// lv=18: alpha=4.5, beta=0.5
|
||||
// lv=24: alpha=4.5, beta=0.4
|
||||
if (sens < 12) {
|
||||
alpha = 3.5;
|
||||
beta = 0.3;
|
||||
} else if (sens == 12) {
|
||||
// Keep fc/q-based params
|
||||
} else if (sens < 24) {
|
||||
alpha = 4.5;
|
||||
beta = 0.5;
|
||||
} else {
|
||||
alpha = 4.5;
|
||||
beta = 0.4;
|
||||
}
|
||||
|
||||
// Override with env vars if set
|
||||
if (const char* e = getenv("RT_VLAW_ALPHA")) alpha = atof(e);
|
||||
if (const char* e = getenv("RT_VLAW_BETA")) beta = atof(e);
|
||||
if (const char* e = getenv("RT_VLAW_C")) c = atof(e);
|
||||
if (const char* e = getenv("RT_VLAW_DELTA")) delta = atof(e);
|
||||
|
||||
return {alpha, beta, c, delta};
|
||||
};
|
||||
|
||||
auto [vlaw_alpha, vlaw_beta, vlaw_c, vlaw_delta] = get_vlaw_params(band.fc, band.q, band.sens);
|
||||
|
||||
for (size_t k2 = 0; k2 < nbin; k2++) {
|
||||
// Applied-stage law: direct fit of deep-scratch vs lvl
|
||||
double cs = vlaw_alpha * std::log1p(raw_level[k2] / vlaw_beta)
|
||||
+ vlaw_c
|
||||
+ (delta_mark[k2] ? vlaw_delta : 0.0);
|
||||
band_level[k2] = static_cast<float>(std::pow(10.0, -cs / 20.0));
|
||||
}
|
||||
frame_dbg_ctr++;
|
||||
} else
|
||||
for (size_t k = 0; k < nbin; k++) {
|
||||
double res_k = std::max(static_cast<double>(res[k]), 1e-12);
|
||||
double lvl = raw_level[k];
|
||||
if (!lut_off) {
|
||||
// dB-domain LUT (FUN_180563a60) on LEVEL before IIR/exp2: keeps both
|
||||
// quiet (t1kq) and loud (t1k) inputs inside the LUT domain [A,B],
|
||||
@@ -145,6 +283,10 @@ static void process_band_structural(
|
||||
double t = (dB - LUT_A) / (LUT_B - LUT_A);
|
||||
t = std::min(std::max(t, 0.0), 1.0);
|
||||
lvl = std::pow(t, static_cast<double>(LUT_GAMMA)) * LUT_MULT;
|
||||
// RT_LUT_CAL: calibration multiplier on LUT output (empirical,
|
||||
// calibrated against plugin steady-state mask@43=0.510).
|
||||
static const double lut_cal = getenv("RT_LUT_CAL") ? atof(getenv("RT_LUT_CAL")) : 1.0;
|
||||
lvl *= lut_cal;
|
||||
}
|
||||
band_level[k] = static_cast<float>(lvl);
|
||||
}
|
||||
@@ -208,10 +350,32 @@ static void process_band_structural(
|
||||
}
|
||||
|
||||
for (size_t k = 0; k < nfft; k++) {
|
||||
double mm = std::exp2(-static_cast<double>(band_level[k]));
|
||||
double mm;
|
||||
// RT_FIRPOWER=1: FIR-style mask from raw spectrum.
|
||||
// Plugin's actual pipeline (52b550-52b8bb):
|
||||
// 1. scratch = log(raw_spectrum)
|
||||
// 2. FIR = exp(0.984 × scratch) = raw^0.984
|
||||
// 3. FIR *= hann_window (freq-domain)
|
||||
// 4. FIR *= 0x540888 (scalar)
|
||||
// 5. FIR applied via time-domain convolution (not pointwise multiply)
|
||||
//
|
||||
// For our structural chain (pointwise mask):
|
||||
// mask = raw^0.984 × hann × 0x540888
|
||||
// where hann rises from 0→1 (DC→Nyquist)
|
||||
static const int firpower = getenv("RT_FIRPOWER") ? atoi(getenv("RT_FIRPOWER")) : 0;
|
||||
if (vlaw) {
|
||||
mm = static_cast<double>(band_level[k]);
|
||||
} else if (firpower) {
|
||||
double raw = static_cast<double>(raw_level[k]);
|
||||
if (raw > 1e-12) {
|
||||
mm = std::pow(raw, 0.984);
|
||||
} else {
|
||||
mm = 1.0;
|
||||
}
|
||||
} else {
|
||||
mm = std::exp2(-static_cast<double>(band_level[k]));
|
||||
static const int noblend = getenv("RT_NOBLEND") ? atoi(getenv("RT_NOBLEND")) : 0;
|
||||
if (!noblend) mm *= f6f8[k];
|
||||
// RT_LAWAFFINE="A,S" (NOTES 22q): cut_dB = A + S*log2(lvl) — affine dB law
|
||||
static const char* la = getenv("RT_LAWAFFINE");
|
||||
if (la && lut_off) {
|
||||
double A_db = atof(la); const char* cm = strchr(la, ',');
|
||||
@@ -221,6 +385,7 @@ static void process_band_structural(
|
||||
mm = std::exp2(-y);
|
||||
}
|
||||
}
|
||||
}
|
||||
mask_out[k] = static_cast<float>(mm);
|
||||
}
|
||||
|
||||
@@ -327,6 +492,32 @@ static void process_band_structural(
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper that allows cascade curve override for process_band_structural.
|
||||
// When casc_am is non-null, it replaces the am/res level computation.
|
||||
// The cascade output IS the level curve (after Haar smooth + sin-peak floor).
|
||||
// We pass res=1.0 so that am/res = am (cascade already includes twin response).
|
||||
static void process_band_structural_am(
|
||||
const float* am,
|
||||
const float* res,
|
||||
const DetectorBand& band,
|
||||
float* mask_out,
|
||||
size_t nfft,
|
||||
float sample_rate,
|
||||
const float* casc_curve = nullptr,
|
||||
bool use_cascade = false
|
||||
) {
|
||||
if (use_cascade && casc_curve) {
|
||||
// Cascade curve IS the level. Pass with res=1.0 to skip am/res division.
|
||||
// Create a dummy res array of all 1.0
|
||||
static thread_local std::vector<float> one_res;
|
||||
size_t nbin = nfft/2 + 1;
|
||||
one_res.assign(nbin, 1.0f);
|
||||
process_band_structural(casc_curve, one_res.data(), band, mask_out, nfft, sample_rate);
|
||||
} else {
|
||||
process_band_structural(am, res, band, mask_out, nfft, sample_rate);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
FramedDetector::FramedDetector(size_t nfft, float sample_rate)
|
||||
@@ -341,6 +532,8 @@ void FramedDetector::setParams(const std::vector<DetectorBand>& bands) {
|
||||
size_t half = nfft_ / 2;
|
||||
res_.clear();
|
||||
track_.clear();
|
||||
twin_resp_complex_.clear();
|
||||
cascade_states_.clear();
|
||||
|
||||
// RT_DUMPRESPATH=<file> (NOTES 22t): static twin-response spectra per band,
|
||||
// binary {int32 band, int32 nbin, float res[nbin]} records (append).
|
||||
@@ -365,6 +558,13 @@ void FramedDetector::setParams(const std::vector<DetectorBand>& bands) {
|
||||
r[k] = std::sqrt(out[k].re * out[k].re + out[k].im * out[k].im);
|
||||
r[k] = std::max(r[k], 1e-12f);
|
||||
}
|
||||
|
||||
// Store complex response for cascade 529c60
|
||||
std::vector<std::complex<double>> complex_resp(half + 1);
|
||||
for (size_t k = 0; k <= half; k++) {
|
||||
complex_resp[k] = std::complex<double>(out[k].re, out[k].im);
|
||||
}
|
||||
twin_resp_complex_.push_back(std::move(complex_resp));
|
||||
if (rp_dump) {
|
||||
int32_t bi = static_cast<int32_t>(res_.size());
|
||||
int32_t nb = static_cast<int32_t>(r.size());
|
||||
@@ -376,6 +576,7 @@ void FramedDetector::setParams(const std::vector<DetectorBand>& bands) {
|
||||
}
|
||||
if (rp_dump) fclose(rp_dump);
|
||||
track_.assign(bands_.size(), std::vector<float>(half + 1, 1.0f));
|
||||
cascade_states_.assign(bands_.size(), fn529fe0::CascadeState());
|
||||
}
|
||||
|
||||
void FramedDetector::processFrame(const std::complex<double>* spectrum, float* mask) {
|
||||
@@ -412,6 +613,10 @@ void FramedDetector::processFrame(const std::complex<double>* spectrum, float* m
|
||||
}
|
||||
}
|
||||
|
||||
// Detector cascade 529c60: per-band pre-processor on complex twin-filtered
|
||||
// spectrum. Computes magnitudes, Haar-smooths, applies sin-peak floor.
|
||||
static const int casc_on = getenv("RT_CASC") ? atoi(getenv("RT_CASC")) : 0;
|
||||
|
||||
for (size_t k = 0; k <= half; k++) mask[k] = 1.0f;
|
||||
|
||||
if (is_internal_grid(nfft_, sample_rate_)) {
|
||||
@@ -427,10 +632,47 @@ void FramedDetector::processFrame(const std::complex<double>* spectrum, float* m
|
||||
fnfaith::band_mask_faithful(am_.data(), res_[b].data(), half + 1,
|
||||
sample_rate_, sf, fparams,
|
||||
band_mask.data());
|
||||
} else {
|
||||
// Run cascade per-band on complex twin-filtered spectrum
|
||||
// Cascade computes: |audio_spectrum × twin_response| → Haar smooth → sin-peak floor
|
||||
// Output replaces am/res in the structural chain.
|
||||
static thread_local std::vector<float> casc_curve;
|
||||
if (casc_on && nfft_ == 4096 && twin_resp_complex_.size() > b) {
|
||||
size_t nbin = half + 1;
|
||||
std::vector<float> complex_input(2 * nbin);
|
||||
casc_curve.resize(nbin);
|
||||
|
||||
// Complex multiply: band_spectrum = audio_spectrum × twin_response
|
||||
for (size_t k = 0; k <= half; k++) {
|
||||
std::complex<double> band_z = spectrum[k] * twin_resp_complex_[b][k];
|
||||
complex_input[2*k] = static_cast<float>(band_z.real());
|
||||
complex_input[2*k+1] = static_cast<float>(band_z.imag());
|
||||
}
|
||||
|
||||
fn529fe0::cascade_detect(
|
||||
complex_input.data(),
|
||||
casc_curve.data(),
|
||||
cascade_states_[b],
|
||||
nbin,
|
||||
2, // Haar iterations
|
||||
0.0f, // sin_peak_param (0 = no floor; set >0 for Step 9 floor)
|
||||
48000.0f, // ctx[0x24] = sample rate
|
||||
1, // ctx[0x1a0] = 1
|
||||
4, // ctx[0x1ac] = 4 (quality default)
|
||||
false // is_magnitude = false (input is complex)
|
||||
);
|
||||
|
||||
// Cascade output IS the level curve (Haar-smoothed magnitude).
|
||||
// Use it directly as am_ replacement — pass res=1.0 so level = am*1
|
||||
// (twin response already baked into cascade output).
|
||||
process_band_structural_am(am_.data(), res_[b].data(), bands_[b],
|
||||
band_mask.data(), nfft_, sample_rate_,
|
||||
casc_curve.data(), true);
|
||||
} else {
|
||||
process_band_structural(am_.data(), res_[b].data(), bands_[b],
|
||||
band_mask.data(), nfft_, sample_rate_);
|
||||
}
|
||||
}
|
||||
for (size_t k = 0; k <= half; k++) {
|
||||
mask[k] = std::min(band_mask[k], mask[k]);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <cstddef>
|
||||
#include <complex>
|
||||
#include <vector>
|
||||
#include "fn529fe0.hpp"
|
||||
|
||||
struct DetectorBand {
|
||||
float fc; // band center freq (Hz)
|
||||
@@ -71,6 +72,11 @@ public:
|
||||
|
||||
void processFrame(const std::complex<double>* spectrum, float* mask);
|
||||
|
||||
// Cascade state access for per-band detector cascade
|
||||
std::vector<fn529fe0::CascadeState>& cascadeStates() { return cascade_states_; }
|
||||
const std::vector<std::vector<std::complex<double>>>& twinRespComplex() const { return twin_resp_complex_; }
|
||||
std::vector<std::vector<std::complex<double>>>& twinRespComplex() { return twin_resp_complex_; }
|
||||
|
||||
private:
|
||||
size_t nfft_;
|
||||
float sample_rate_;
|
||||
@@ -82,4 +88,10 @@ private:
|
||||
std::vector<float> am_; // smoothed per-bin amplitude
|
||||
std::vector<float> f6f8_; // shared 0x5406f8 blend buffer (IIR1 out)
|
||||
std::vector<std::vector<float>> track_; // per band, per bin accumulator 0x5407c8
|
||||
|
||||
// For cascade 529c60: per-band complex twin filter responses
|
||||
std::vector<std::vector<std::complex<double>>> twin_resp_complex_;
|
||||
|
||||
// Per-band cascade states
|
||||
std::vector<fn529fe0::CascadeState> cascade_states_;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#include "log2_ln.hpp"
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
|
||||
namespace soothe2 {
|
||||
|
||||
float ln_plugin_f32(float x) {
|
||||
if (x <= 0.0f) return -INFINITY;
|
||||
|
||||
uint32_t bits;
|
||||
std::memcpy(&bits, &x, sizeof(uint32_t));
|
||||
int exp = int((bits >> 23) & 0xFF);
|
||||
uint32_t mantissa = bits & 0x7FFFFFu;
|
||||
|
||||
if (exp == 0) return -INFINITY;
|
||||
|
||||
float x_norm = mantissa * (1.0f / 8388608.0f);
|
||||
|
||||
constexpr float c0_a = -0.1517720520f;
|
||||
constexpr float c0_b = 0.1696488112f;
|
||||
constexpr float c1 = -0.1646245718f;
|
||||
constexpr float c2 = 0.1982250363f;
|
||||
constexpr float c3 = -0.2500466406f;
|
||||
constexpr float c4 = 0.3333656490f;
|
||||
constexpr float c5 = -0.5000000000f;
|
||||
constexpr float ln2 = 0.6931471825f;
|
||||
|
||||
constexpr float c0_init = c0_a * c0_b;
|
||||
|
||||
float y = c0_init + x_norm;
|
||||
y = y * x_norm + c1;
|
||||
y = y * x_norm + c2;
|
||||
y = y * x_norm + c3;
|
||||
y = y * x_norm + c4;
|
||||
y = y * x_norm + c5;
|
||||
|
||||
float ln_m = x_norm + x_norm * x_norm * y;
|
||||
|
||||
return ln2 * float(exp - 127) + ln_m;
|
||||
}
|
||||
|
||||
void ln_plugin_f32_arr(const float* in, float* out, size_t n) {
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
out[i] = ln_plugin_f32(in[i]);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace soothe2
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
namespace soothe2 {
|
||||
|
||||
// Plugin's exact ln(float) from 0x1802a24c0 (535a70 FFT-conv engine)
|
||||
// Computes natural logarithm via mantissa polynomial + exponent scaling
|
||||
// Coefficients extracted from binary at 0x181f81f80..0x181f821c0
|
||||
// Max error ~3e-6 for typical inputs (x in [1, 1.34))
|
||||
float ln_plugin_f32(float x);
|
||||
|
||||
// Vectorized version for arrays
|
||||
void ln_plugin_f32_arr(const float* in, float* out, size_t n);
|
||||
|
||||
} // namespace soothe2
|
||||
+194
-3
@@ -1,7 +1,13 @@
|
||||
#include "spectral.hpp"
|
||||
#include "fftconv.hpp"
|
||||
#include "log2_ln.hpp"
|
||||
#include "exp2_tables.hpp"
|
||||
#include "exp2.hpp"
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
SpectralProcessor::SpectralProcessor(size_t nfft, size_t hop, float sample_rate)
|
||||
: nfft_(nfft), hop_(hop), frame_count_(0), output_pos_(0),
|
||||
@@ -11,23 +17,41 @@ SpectralProcessor::SpectralProcessor(size_t nfft, size_t hop, float sample_rate)
|
||||
fft::init_plan(&plan_, static_cast<uint32_t>(std::log2(nfft_)));
|
||||
buf_ = new std::complex<double>[nfft_];
|
||||
tmp_buf_ = new std::complex<double>[nfft_];
|
||||
fir_buf_ = new std::complex<double>[nfft_];
|
||||
fir_freq_ = new std::complex<double>[nfft_];
|
||||
overlap_.resize(nfft_, 0.0f);
|
||||
mask_.resize(nfft_, 1.0f);
|
||||
|
||||
// Build FIR window: falling half of periodic Hann(4096).
|
||||
// Plugin reads window[N/2..N-1] of periodic Hann (rising 0→1).
|
||||
fir_window_.resize(nfft_);
|
||||
for (size_t i = 0; i < nfft_; i++) {
|
||||
fir_window_[i] = 0.5 * (1.0 - std::cos(2.0 * M_PI * i / nfft_));
|
||||
}
|
||||
}
|
||||
|
||||
SpectralProcessor::~SpectralProcessor() {
|
||||
delete[] window_;
|
||||
delete[] buf_;
|
||||
delete[] tmp_buf_;
|
||||
delete[] fir_buf_;
|
||||
delete[] fir_freq_;
|
||||
}
|
||||
|
||||
void SpectralProcessor::setDetectorParams(const std::vector<DetectorBand>& bands) {
|
||||
detector_.setParams(bands);
|
||||
loadWinFreq();
|
||||
}
|
||||
|
||||
void SpectralProcessor::computeWindow() {
|
||||
// RT_WIN: 0=symmetric hann (legacy), 1=periodic hann, 2=rectangular
|
||||
static const int winmode = getenv("RT_WIN") ? atoi(getenv("RT_WIN")) : 0;
|
||||
for (size_t i = 0; i < nfft_; i++) {
|
||||
window_[i] = 0.5 * (1.0 - std::cos(2.0 * M_PI * i / (nfft_ - 1)));
|
||||
double v;
|
||||
if (winmode == 1) v = 0.5 * (1.0 - std::cos(2.0 * M_PI * i / nfft_));
|
||||
else if (winmode == 2) v = 1.0;
|
||||
else v = 0.5 * (1.0 - std::cos(2.0 * M_PI * i / (nfft_ - 1)));
|
||||
window_[i] = v;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,16 +67,20 @@ void SpectralProcessor::istftFrame(std::complex<double>* in, float* out, float*
|
||||
fft::execute_inverse(&plan_, tmp_buf_);
|
||||
static bool wola_computed = false;
|
||||
static float wola_norm = 1.0f;
|
||||
// RT_SYN: 0=synthesis window = analysis window (WOLA), 1=none
|
||||
static const int synmode = getenv("RT_SYN") ? atoi(getenv("RT_SYN")) : 0;
|
||||
if (!wola_computed) {
|
||||
double wola_sum = 0.0;
|
||||
for (size_t i = 0; i < nfft_; i++) {
|
||||
wola_sum += window_[i] * window_[i];
|
||||
double w = (synmode == 1) ? 1.0 : window_[i];
|
||||
wola_sum += window_[i] * w;
|
||||
}
|
||||
wola_norm = static_cast<float>(wola_sum / hop_);
|
||||
wola_computed = true;
|
||||
}
|
||||
for (size_t i = 0; i < nfft_; i++) {
|
||||
overlap[i] += static_cast<float>(tmp_buf_[i].real() * window_[i]);
|
||||
double w = (synmode == 1) ? 1.0f : window_[i];
|
||||
overlap[i] += static_cast<float>(tmp_buf_[i].real() * w);
|
||||
}
|
||||
for (size_t i = 0; i < hop_; i++) {
|
||||
out[i] = overlap[i] / wola_norm;
|
||||
@@ -65,12 +93,145 @@ void SpectralProcessor::istftFrame(std::complex<double>* in, float* out, float*
|
||||
}
|
||||
}
|
||||
|
||||
void SpectralProcessor::loadWinFreq() {
|
||||
if (win_freq_loaded_) return;
|
||||
win_freq_loaded_ = true;
|
||||
// Try to load WIN_freq from live capture (handoff/rtwin_freq_44100.npy)
|
||||
FILE* f = fopen("handoff/rtwin_freq_44100.npy", "rb");
|
||||
if (!f) {
|
||||
// Fallback: compute periodic Hann, second half (0.5→1.0 rising)
|
||||
win_freq_.resize(nfft_ / 2 + 1);
|
||||
for (size_t i = 0; i <= nfft_ / 2; i++) {
|
||||
win_freq_[i] = static_cast<float>(0.5 * (1.0 - std::cos(2.0 * M_PI * i / nfft_)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Read numpy header
|
||||
char header[128];
|
||||
if (fread(header, 1, 6, f) != 6) { fclose(f); return; }
|
||||
// Skip to data (numpy format: magic + header_len + desc)
|
||||
fseek(f, 0, SEEK_END);
|
||||
long fsize = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
// Simple approach: skip header until '\n' appears, then read raw float32
|
||||
fseek(f, 0, SEEK_SET);
|
||||
int c;
|
||||
while ((c = fgetc(f)) != '\n' && c != EOF) {}
|
||||
// Read count (should be 8193 for 44100)
|
||||
int32_t count = 0;
|
||||
fread(&count, 4, 1, f);
|
||||
// Actually numpy header is more complex; just read all remaining as float32
|
||||
fseek(f, 0, SEEK_SET);
|
||||
// Skip to data: find first 'N' (for 'astype') then skip past it
|
||||
fseek(f, 6, SEEK_SET);
|
||||
while ((c = fgetc(f)) != '\n' && c != EOF) {}
|
||||
// Now at data start. Read until we have enough floats
|
||||
std::vector<float> raw;
|
||||
float val;
|
||||
while (fread(&val, 4, 1, f) == 1) {
|
||||
raw.push_back(val);
|
||||
}
|
||||
fclose(f);
|
||||
if (raw.size() > 0) {
|
||||
win_freq_ = raw;
|
||||
} else {
|
||||
// Fallback
|
||||
win_freq_.resize(nfft_ / 2 + 1);
|
||||
for (size_t i = 0; i <= nfft_ / 2; i++) {
|
||||
win_freq_[i] = static_cast<float>(0.5 * (1.0 - std::cos(2.0 * M_PI * i / nfft_)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpectralProcessor::buildFirFromMask(const float* mask, std::complex<double>* fir, size_t nbin) {
|
||||
// Plugin FIR construction pipeline (52b550-52b8bb) uses custom real RFFTs with twiddle operations.
|
||||
// The plugin's real RFFT (th1a90/th2180) uses buf548 (cos/sin table) and mask598 (SIMD masks)
|
||||
// in FMA-complex operations that are NOT standard FFT butterflies.
|
||||
//
|
||||
// Our implementation uses a simplified approach: ln → negate → exp2 → IFFT → window → FFT
|
||||
// This is NOT bit-exact but provides reasonable results for most cases.
|
||||
//
|
||||
// To achieve bit-exact FIR construction, we would need to:
|
||||
// 1. Reverse-engineer the exact twiddle operations from disassembly
|
||||
// 2. Implement custom FMA-complex operations with buf548 and mask598
|
||||
// 3. Match the plugin's exact sequence (opA → opB → EXP → opC → window → opD)
|
||||
//
|
||||
// The default path (no FIRCONV) provides better results (1.825 dB TOTAL) than
|
||||
// the FIR construction path (10.377 dB TOTAL), so we use the default path.
|
||||
|
||||
const size_t half = nfft_ / 2;
|
||||
const size_t nfft = nfft_;
|
||||
|
||||
// Compute ln(mask) and negate
|
||||
std::vector<std::complex<double>> H(nfft);
|
||||
for (size_t i = 0; i <= half; i++) {
|
||||
float m = mask[i];
|
||||
if (m > 1e-12f) {
|
||||
float ln_m = soothe2::ln_plugin_f32(m);
|
||||
ln_m = -ln_m;
|
||||
H[i] = std::complex<double>(static_cast<double>(ln_m), 0.0);
|
||||
} else {
|
||||
H[i] = std::complex<double>(0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
// Zero upper half
|
||||
for (size_t i = half + 1; i < nfft; i++) {
|
||||
H[i] = std::complex<double>(0.0, 0.0);
|
||||
}
|
||||
|
||||
// IFFT to time domain
|
||||
fft::execute_inverse(&plan_, H.data());
|
||||
|
||||
// Causal window: keep first half, apply rising Hann (0.5→1.0)
|
||||
for (size_t i = 0; i < half; i++) {
|
||||
double win = 0.5 * (1.0 - std::cos(2.0 * M_PI * i / nfft));
|
||||
H[i] *= win;
|
||||
}
|
||||
for (size_t i = half; i < nfft; i++) {
|
||||
H[i] = std::complex<double>(0.0, 0.0);
|
||||
}
|
||||
|
||||
// FFT back to freq domain
|
||||
fft::execute(&plan_, H.data());
|
||||
|
||||
// Apply WIN_freq window
|
||||
if (!win_freq_.empty() && win_freq_.size() > half) {
|
||||
for (size_t i = 0; i <= half; i++) {
|
||||
H[i] *= static_cast<double>(win_freq_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Zero upper half again
|
||||
for (size_t i = half + 1; i < nfft; i++) {
|
||||
H[i] = std::complex<double>(0.0, 0.0);
|
||||
}
|
||||
|
||||
// Normalize: FIR[0]=1, FIR[1]=0
|
||||
double scale = 1.0;
|
||||
if (std::abs(H[0].real()) > 1e-12) {
|
||||
scale = 1.0 / H[0].real();
|
||||
}
|
||||
for (size_t i = 0; i < nfft; i++) {
|
||||
fir[i] = H[i] * scale;
|
||||
}
|
||||
fir[0] = std::complex<double>(1.0, 0.0);
|
||||
if (half >= 1) {
|
||||
fir[1] = std::complex<double>(0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
void SpectralProcessor::processBlock(float* in, float* out, size_t num_samples, size_t num_channels) {
|
||||
memset(out, 0, num_samples * sizeof(float));
|
||||
if (num_samples == 0 || num_samples < nfft_) {
|
||||
return;
|
||||
}
|
||||
|
||||
static const int firconv = []() {
|
||||
const char* e = getenv("RT_FIRCONV");
|
||||
return e ? atoi(e) : 0;
|
||||
}();
|
||||
|
||||
size_t nframes = (num_samples - nfft_) / hop_ + 1;
|
||||
|
||||
for (size_t f = 0; f < nframes; f++) {
|
||||
@@ -80,9 +241,39 @@ void SpectralProcessor::processBlock(float* in, float* out, size_t num_samples,
|
||||
|
||||
detector_.processFrame(buf_, mask_.data());
|
||||
|
||||
if (firconv == 3) {
|
||||
// RT_FIRCONV=3 (NOTES 24k): plugin application law decoded live:
|
||||
// applied_gain = 1.019 * V^1.8345 per bin (rms 0.0025 dB over
|
||||
// 8 drive levels). V = band curve (detector output); here M.
|
||||
for (size_t i = 0; i < nfft_; i++) {
|
||||
double m = std::max(static_cast<double>(mask_[i]), 1e-12);
|
||||
double a = 1.019 * std::pow(m, 1.8345);
|
||||
buf_[i] *= a;
|
||||
}
|
||||
} else if (firconv) {
|
||||
// RT_FIRCONV=2: Full FIR construction pipeline (52b550-52b8bb).
|
||||
// mask → reciprocal (1/mask) → window → normalize → complex multiply.
|
||||
// This replicates the plugin's FFT-conv FIR design path.
|
||||
buildFirFromMask(mask_.data(), fir_freq_, nfft_);
|
||||
// Complex multiply FIR × audio spectrum
|
||||
for (size_t i = 0; i < nfft_; i++) {
|
||||
buf_[i] *= fir_freq_[i];
|
||||
}
|
||||
} else if (firconv == 1) {
|
||||
// RT_FIRCONV=1: Simple frequency-domain mask multiply (legacy).
|
||||
for (size_t i = 0; i < nfft_; i++) {
|
||||
fir_freq_[i] = std::complex<double>(
|
||||
static_cast<double>(mask_[i % (nfft_/2+1)]), 0.0);
|
||||
}
|
||||
for (size_t i = 0; i < nfft_; i++) {
|
||||
buf_[i] *= fir_freq_[i];
|
||||
}
|
||||
} else {
|
||||
// Default path: simple frequency-domain mask multiply.
|
||||
for (size_t i = 0; i < nfft_; i++) {
|
||||
buf_[i] *= mask_[i];
|
||||
}
|
||||
}
|
||||
|
||||
istftFrame(buf_, out + offset, overlap_.data());
|
||||
}
|
||||
|
||||
@@ -25,6 +25,9 @@ private:
|
||||
FFTPlan plan_;
|
||||
std::complex<double>* buf_;
|
||||
std::complex<double>* tmp_buf_;
|
||||
std::complex<double>* fir_buf_;
|
||||
std::complex<double>* fir_freq_;
|
||||
std::vector<double> fir_window_;
|
||||
std::vector<float> overlap_;
|
||||
std::vector<float> mask_;
|
||||
FramedDetector detector_;
|
||||
@@ -34,4 +37,14 @@ private:
|
||||
void computeWindow();
|
||||
void stftFrame(const float* in, std::complex<double>* out);
|
||||
void istftFrame(std::complex<double>* in, float* out, float* overlap);
|
||||
|
||||
// FIR construction from detector mask (52b550-52b8bb pipeline):
|
||||
// mask → log → sign-invert → EXP → twiddle ops → window → normalize
|
||||
// Produces frequency-domain FIR kernel for complex multiply application.
|
||||
void buildFirFromMask(const float* mask, std::complex<double>* fir, size_t nbin);
|
||||
|
||||
// WIN_freq: live-captured freq-path window (0x540658), 0.5→1.0
|
||||
std::vector<float> win_freq_;
|
||||
bool win_freq_loaded_ = false;
|
||||
void loadWinFreq();
|
||||
};
|
||||
|
||||
@@ -153,3 +153,640 @@ for i in 1..n-1:
|
||||
Незакоммичено: f529fe0_full.dis, BLOCKMAP_529fe0.md, thunk-резолвер,
|
||||
правки NOTES_LEVEL (22v будет добавлена при транскрипции). Следующий шаг —
|
||||
транскрипция process_frame_faithful по этой карте.
|
||||
|
||||
## ДОПОЛНЕНИЕ 23b: резолв ILT + декод FIR-цикла (52b550–52b8bb)
|
||||
|
||||
### Резолвер
|
||||
`scripts/ilt_resolve.py`: стаб = `mov eax,[rip+idx]; lea r10,[rip+tbl]; jmp [r10+rax*8]`;
|
||||
live idx=4 у всех; таблицы @0x1826xxxx. Полная таблица «стаб→impl»:
|
||||
| стаб | impl | роль (уточн.) |
|
||||
|---|---|---|
|
||||
| 0x180002210 | 0x136e0 | copy scratch→FIR? (валидатор → 39de0/3a040/3a220) |
|
||||
| 0x180002180 | 0x125e0 | complex-op A/C float (воркер 3a4a0; r9 НЕ передаётся ⇒ длина из объекта) |
|
||||
| 0x180001bb0 | 0x6a40 | complex-op A/C double |
|
||||
| 0x180001a90 | 0x5560 | complex-op B/D float — ЧИСТЫЙ FMA (fma=28, mul/add=0!) |
|
||||
| 0x1800019d0 | 0x4340 | complex-op B/D double |
|
||||
| 0x180001880 | 0x2c60 | paired-scalar op 1 (флаг-ветка) |
|
||||
| 0x180001ca0 | 0x9380 | paired-scalar op 2 |
|
||||
| 0x180001df0 | 0xb3c0 | final op float |
|
||||
| 0x180001f70 | 0xe360 | final op double |
|
||||
| 0x180140a10 | 0x141400→[1826181d8]=**0x1802a24c0** | дизайн float |
|
||||
| 0x180140a70 | 0x141580→[1826183c8]=**0x1802fa420** | дизайн double |
|
||||
| 2030/1d30 | ffe0 / 9be0 | scalar-transform |
|
||||
| 2270/22a0 | 14c40 / 15060 | scalar-transform-2 |
|
||||
| 2000/1c40 | fb60 / 8700 | axpy-класс |
|
||||
| остальное | dc40,8d60,5a20,4720,4200,3f40,5160,25e0,ee20,3c40 | как в BLOCKMAP ✓ |
|
||||
|
||||
### Дизайн-тело 0x1802a24c0 (float, вход=rcx bands[i], выход=rdx scratch@0x540628)
|
||||
Функция входа 0..0x675 (~1.6КБ), далее сиблинги. Алгоритм = **ВЕКТОРНЫЙ LOG2**
|
||||
(range reduction бит-трюком с 0.6666667, полином Хорнера на YMM-константах
|
||||
−0.5, 0.3333656, −0.2500466, 0.198225, −0.1646246, 0.1696488, −0.1517721,
|
||||
реконструкция ×ln2=0.6931472; константы @FN+0x1cdfac0..d20). Маскированный
|
||||
хвост через vmaskmovps/popcnt-таблицы (@0x181F8xxxx). ИТОГ: **scratch = log(bands[i])**.
|
||||
Диспетчер 535a70 делает swap аргументов (rcx↔rdx) перед прыжком!
|
||||
|
||||
### Структура FIR-цикла (полностью залочена)
|
||||
На полосу: 2×scalar-transform(bands[i], xmm8·[540888] при флаге 540890==0, иначе
|
||||
xmm8; затем xmm12−xmm8) [ср. decomp 184-185: A=[0x540874]−expf(K), wet=[0x540888]]
|
||||
→ DESIGN=log(bands[i])→scratch → copy(scratch→FIR@0x540668) [2210]
|
||||
→ opA(FIR,buf548,buf598) [2180/1bb0] → FIR[n]=0 (n=0x540534=4096!)
|
||||
→ 52d920(&FIR[1], xmm13, n/2−1) деление; 52db50(&FIR[2049], xmm9, n/2−1)
|
||||
→ opB [1a90/19d0] → bigkernel in-place 140b30/140aa0 (n/2+1)
|
||||
→ opC [2180/1bb0] → FIR[n]=0 → 52d990(FIR, WIN_freq+n/2, n/2) УМНОЖЕНИЕ на
|
||||
**падающую половину Hann** (WIN_freq=wperiodicHann4096: w[1024]=0.5,w[2048]=1.0!)
|
||||
→ 52db50(&FIR[2048], xmm9, n/2) → opD [1a90/19d0] → FIR[0]=1.0, FIR[1]=0
|
||||
→ флаг-ветка: парно-скалярные 1880/ca0 → dry/wet scale ×[0x540888] над **2n флоатов**
|
||||
→ final(df0/f70) с сохранённым track_i ([rsp+0x138][i]).
|
||||
|
||||
### Живые буферы (firtrace.py по s1/s2 + свежие захваты dual_b1q_0.5)
|
||||
- 0x540658 WIN_freq = периодический Hann(4096), пик 1.0 @bin2048 (НЕ рамп 0.5→0.8!)
|
||||
- 0x540758 freqaxis = линейный, шаг ≈11.713 Гц (≈48000/4096=11.71875, лёгкое
|
||||
занижение — похоже на накопительную ошибку f32 при построении суммой)
|
||||
- 0x540598 = SIMD-маски: 8×1.0 / 8×0.0 периодом 16 флоатов, ровно 1024 шт
|
||||
(YMM lane-select для комплексных кернелов)
|
||||
- 0x540550 NULL (float-путь активен, флаг 0x5408b8=0); 0x540628 scratch нулевой
|
||||
между колбеками; 0x540668 FIR = комплексная единица (1,0)×2049 бинов МЕЖДУ
|
||||
колбеками — кернел потребляется и сбрасывается внутри колбека
|
||||
- 0x5406f8 хранит аудио-масштабный сигнал (~±0.1) между колбеками — overlap/STFT
|
||||
буфер conv-движка (не «нулевой acc»!)
|
||||
- 0x540788 vs 0x5407f8 различаются (max 1.108; @171: 1.751 vs 1.409) — две РАЗНЫЕ
|
||||
кривые; ни одна не достигает нужных 3.89×@171 (11.82 дБ) ⇒ применённый фильтр
|
||||
≠ поточечная копия любой из живых кривых (подтверждение разрыва 22y)
|
||||
|
||||
## ДОПОЛНЕНИЕ 24l: точный декод FIR-цикла по дизасму (52b550–52b8bb) + константы
|
||||
|
||||
Инструмент: scripts/disasm.py (capstone, base 0x180000000 над soothe_mem.bin).
|
||||
ILT-резолв bigkernel-стабов даёт impl в 141100..141940 — все они IAT-thunk
|
||||
массивы (`mov rax,[rip+..]; jmp rax`) вне дампа ⇒ тела за импортами; НО
|
||||
последовательность и КОНСТАНТЫ цикла видны полностью:
|
||||
|
||||
### Пошагово (float-ветка, флаг 0x540890==0):
|
||||
```
|
||||
52b5a3: xmm6 = xmm8 · [ctx+0x540888]
|
||||
52b5bf: th2030(bands[i], xmm6, n) ; bands *= 1.0·s888 (xmm8=double 1.0!)
|
||||
52b5f6: th2270(bands[i], xmm7, n) ; scalar-transform-2
|
||||
52b62f: 535a70(scratch@540628, bands[i], n/2+1) ; DESIGN: swap→scratch=log(bands)
|
||||
52b644: th2210(rcx=scratch, rdx=0, r8=FIR, r9=n/2+1) ; копия (+упаковка?)
|
||||
52b696: FIR[n]=0 ; float-индекс n=4096
|
||||
52b69e: 52d920(&FIR[1], xmm13=-1.0, n/2-1) ; РАЗДЕЛЕНИЕ НА −1 ⇒ ИНВЕРСИЯ ЗНАКА бинов 1..n/2!
|
||||
52b6ab: 52db50(&FIR[n/2+1], xmm9=0, n/2-1) ; ОБНУЛЕНИЕ верхней половины до exp!
|
||||
52b6e1: opB = th1a90(FIR, buf548, mask598, n/2-1) ; FMA-complex (twiddle!)
|
||||
52b716: BIGKERNEL 140b30(FIR, FIR, n/2+1) ; EXP in-place (тело за IAT)
|
||||
52b74b: opC = th2180(FIR, buf548, mask598, n/2-1)
|
||||
52b76d: FIR[n]=0
|
||||
52b77c: 52d990(FIR, WINfreq+n/2, n/2) ; окно: th2000-класс (FMA axpy!)
|
||||
52b78c: 52db50(&FIR[n/2], xmm9=0, n/2) ; верхняя половина ×0 снова
|
||||
52b7ba: opD = th1a90(...)
|
||||
52b7d4: FIR[0]=1.0f; FIR[1]=0
|
||||
если флаг f890!=0:
|
||||
52b803: th1880(FIR, {xmm10,xmm9}, n) ; парно-скалярный с (−1|0.8, 0)
|
||||
52b81f: th1ca0(FIR, {xmm12,xmm9}, n) ; парно-скалярный с (1.0, 0)
|
||||
52b857: th2030(FIR, s888, 2n) ; ×wet (=1 live)
|
||||
52b893: final df0(FIR, track_i, n)
|
||||
```
|
||||
|
||||
### Константы (статические значения из дампа):
|
||||
| reg | адрес | значение | роль |
|
||||
|-----|-------|----------|------|
|
||||
| xmm8 | 1824c4140 (double) | 1.0 | множитель шага 1 = NO-OP при s888=1 |
|
||||
| xmm13 | 1824c46a0 (double) | −1.0 | делитель бинов 1..n/2 (ИНВЕРСИЯ!) |
|
||||
| xmm9 | xorps | 0.0 | обнуление верхних половин |
|
||||
| xmm10 | 1824c4680 / 1824c3e28 | −1.0 / **0.8** | парный скаляр (0.8 активен в цикле) |
|
||||
| xmm12 | 1824c3ea4 | 1.0 | парный скаляр 2 |
|
||||
| xmm14 | 1824c4674 | −0.7 | (использование вне FIR) |
|
||||
| xmm15 | 1824c4670 | −0.5 | (использование вне FIR) |
|
||||
| xmm7 | вычисл. | sens·[540870]-цепочка | аргумент th2270 |
|
||||
|
||||
### СЛЕДСТВИЯ (меняют понимание построения кернела):
|
||||
1. Перед EXP: бины 1..n/2 = −log(bands) ⇒ после exp = **1/bands** (обратная
|
||||
величина!), бины выше = exp(0)=1. Экспонента применяется НЕ к спектру маски
|
||||
напрямую — вокруг неё twiddle-FMA стадии (ops B/C/D = радиальные проходы
|
||||
FFT-класса над упакованным вещественным спектром; buf548 = cos/sin таблица,
|
||||
mask598 = lane-select).
|
||||
2. «×0.984» из 23d НЕ найден как константа цикла — либо внутри exp-IAT-обёртки,
|
||||
либо следствие нормировки twiddle-стадий. Требуется численная репликация
|
||||
пайплайна против живых захватов (rendersnap2 ph*.npz содержат готовые пары).
|
||||
3. Шаг 1 и шаг ×s888 — no-op при дефолтных параметрах (s888=1, live 24j).
|
||||
4. 52d920/52d990/52db50 = тонкие обёртки: 920→th2030/1d30 (scalar-op),
|
||||
990→th2000/1c40 (axpy!), db50→то же. «УМНОЖЕНИЕ на окно» реализовано
|
||||
axpy-кернелом, «деление» — scalar-op.
|
||||
5. Ops A–D работают над дескрипторными векторами (проверка тега [obj]==6 в
|
||||
4ca80; ошибка 0xfffffff3 при несоответствии).
|
||||
|
||||
### Динамика (попытки перехвата; окружение)
|
||||
- realtime-playback НЕ тикает DSP (нет аудио-девайса; треды спят в futex);
|
||||
кривые 22y = результат инициализации при загрузке проекта
|
||||
- `-renderproject`: полный цикл init+render+exit хоста занимает ~0.8 c
|
||||
(host@1.2s, workers@1.4s, wav@1.6s, exit@2.0s); обработка идёт в окне ~0.5 c
|
||||
- INT3-ptrace: SEIZE+TRACECLONE обязательны до CONT (иначе untraced thread
|
||||
ловит SIGTRAP и убивает процесс — подтверждено); DR-брейкпоинты: DR0@user+0x380,
|
||||
но POKEUSER DR7 даёт EIO. Скрипты: fntrace*.py, fnhw.py, fnall.py, firstop.py,
|
||||
firtrace.py, hotips.py (см. scripts/)
|
||||
- Вывод: FUN_180529fe0 и 52d650/536300/52e260 НЕ ловятся в рендер-окне —
|
||||
маск-цепь выполняется при ЗАГРУЗКЕ/изменении параметров, стационарный рендер
|
||||
использует закэшированный кернел; либо трассировать надо момент инициализации
|
||||
- Выход плагина НЕдетерминирован: md5 двух свободных рендеров различен при
|
||||
одинаковом rms (PRNG-дизеринг из LCG-прологов) — метрика только спектральная!
|
||||
|
||||
## ДОПОЛНЕНИЕ 24t: ТОЧНЫЕ СЕМАНТИКИ СКАЛЯР-ОПОВ + опознание 563a60
|
||||
|
||||
Инструмент: scripts/disasm_func.py (полный дизасм функции с резолвом
|
||||
RIP-констант инлайн).
|
||||
|
||||
### Тела скаляр-трансформов (float-ветки):
|
||||
| стаб/impl | семантика | спец-случаи |
|
||||
|---|---|---|
|
||||
| th2030→ffe0 | dst[i] *= scalar | scalar==1 → скип; ==0 → zero-fill |
|
||||
| th2270→14c40 | dst[i] += scalar | scalar==0 → скип |
|
||||
Оба: скалярный хвост + AVX2 основной цикл (vmulps/vaddps ymm). Двойные
|
||||
ветки (1d30/22a0) аналогичны на sd/pd.
|
||||
|
||||
### FUN_180563a60 = init-time ПОСТРОИТЕЛЬ таблицы (не per-bin!)
|
||||
- Один caller: 1805636c2 (init-семейство).
|
||||
- Константы пролога: xmm11=8.68589 (20/ln10 — ln⇒дБ!), xmm12=1/1024,
|
||||
xmm14=0.5, xmm10=2, xmm9=−1, xmm6=1; вызов IAT 181a14cd0 (log-класс)
|
||||
над double из [obj+0x4198], ×8.68589 → дБ, запись пар во вектор
|
||||
([obj+0xe0], рост через realloc 56c640).
|
||||
- Вывод: строит дБ-доменную таблицу парами при param-rebuild — согласуется
|
||||
с «LUT» ролью. Хвост с вирт. вызовом [rax+0x10] не декодирован.
|
||||
|
||||
### Алгебра T1: обе формы фитуют серию драйва (8 точек недоопределены)
|
||||
- softplus α·ln1p(L/β)+c: rms 0.016 (α=3.2193 β=0.4927 c=0.542)
|
||||
- LUT-форма t=((dB−A)/(B−A))^γ·M: rms 0.029 (A=−36.2 B=20.0 γ=2.097 M=10.49)
|
||||
Различить только декомпом тракта am/res→scratch или бОльшим числом точек.
|
||||
|
||||
### Открытые микровопросы
|
||||
1. Значение xmm7 на входе th2270 в FIR-цикле (52b5f6): трассировка от
|
||||
52a583; если mix^p=1 → «bands+=1» противоречит провалам ⇒ xmm7 иной
|
||||
либо порядок аргументов иной.
|
||||
2. Раскладка объекта-вектора (тег 6) для ops A–D.
|
||||
|
||||
## ДОПОЛНЕНИЕ 24u: WIN_WINDOW движка — кусочное окно аудио-пути
|
||||
|
||||
Таблица WIN_WINDOW[8193] (dsp/tables_data.hpp, live-захват):
|
||||
- [0]=0.500000, плавный подъём до [2048]=0.800000, затем СКАЧОК до 1.0
|
||||
и единица до конца ([2049..8192]).
|
||||
- Длина перехода = РОВНО 2049 сэмплов = число бинов кернела (4096-сетка)!
|
||||
- Формула перехода не каноническая (ханн/синус/степенные не сошлись,
|
||||
maxdiff ≥0.09); для репликации достаточно встраивания таблицы как есть.
|
||||
- Структура намекает: блок аудио 8192 сэмплов ({16384,8192} из cfg движка),
|
||||
первые 2049 позиций получают взвешивание 0.5..0.8 (область «кернельного
|
||||
взаимодействия»?), остальное прозрачно; 0.8 подозрительно = blend.
|
||||
Проверка употребления — в resize fe00 / audio-клее (следующий раунд).
|
||||
|
||||
### Движок dc30: карта инициализаторов (24u)
|
||||
ctor 18052dc30 вызывает: 5335c0 (×2 — до/после валидатора), 534550 (×5 —
|
||||
регистрация конфиг-итемов, аргументы edx из стека [rsp+0x30..0x4c] =
|
||||
цепочка {2,4096},{16384,8192},{2,257}), затем ILT-стабы 2240/1c10.
|
||||
Следующий шаг декода: тела 534550/5335c0 + употребление WIN_WINDOW
|
||||
(по xref на таблицу или указатель из объекта).
|
||||
|
||||
## ДОПОЛНЕНИЕ 24w-3: ЖИВЫЕ КОНСТАНТЫ ГЕНЕРАТОРА 533340 (параметры частотных IIR)
|
||||
|
||||
Из scalar-bank (rendersnap2 v4+) на дефолтных параметрах multi:
|
||||
```
|
||||
p (экспонента) = [ctx+0x54087c] = 1.000000
|
||||
tau1 = [ctx+0x540894] = 1200.000122
|
||||
tau2 = [ctx+0x540898] = 180.000015
|
||||
mult (стадия-3) = DAT_1824c4564 = 360
|
||||
C_hz = DAT_1824c459c = 1000
|
||||
константы 530b60 : 0.7, 2, 800→(×2)=1600, 1200, 15, 9, 180, 0.01,
|
||||
[540898]=180*p+xmm6 (формула видна в дизасме)
|
||||
```
|
||||
Формула тела подтверждена дизасмом: g=min(fc_norm/i,(fc_norm/i)^p);
|
||||
c=1/(1+g*tau/mult); up=exp(...); down=1-up.
|
||||
Эксперимент: одноразовый bidir с этими коэф. НЕ двигает центр кривой
|
||||
⇒ q-зависимость катов не через эти IIR напрямую; тракт между main-loop
|
||||
и scratch содержит ещё этапы (ops A–D / steps 9–19 BLOCKMAP).
|
||||
|
||||
## ДОПОЛНЕНИЕ 24z: FUN_180563a60 ДЕКОДИРОВАН ПОЛНОСТЬЮ — ЭТО ДЕТЕКТОРНАЯ LUT-ФОРМА!
|
||||
|
||||
Постройка (на каждый банд, 1024 точки, вход double[+0x4198+i·8],
|
||||
выход пары-floats в вектор [+0xe0], stride вектора 0x18):
|
||||
```
|
||||
dB = log(input) · 8.68589
|
||||
idx = i / 1024 → store[2j]
|
||||
t = (dB − A) / (B − A) ; A=[sub+0], B=[sub+4] (sub=obj@[rcx+0x180])
|
||||
t = clamp(t, 0, 1)
|
||||
если γ(=[sub+0xc]) ≠ 1:
|
||||
если [sub+0x10]==0: out = t^γ (классика)
|
||||
иначе : out = sign(2t−1)·|2t−1|^γ + 1 (симметричный режим!)
|
||||
else: out = t
|
||||
out *= 0.5 → store[2j+1]
|
||||
```
|
||||
Виртуальная альтернатива: [sub+0x90]!=0 → вызов [sub vtbl+0x10](A,B,dB)
|
||||
с клампом [0,1].
|
||||
⇒ ЭТО ТА САМАЯ ФОРМА, ЧТО ДАЛА ФИТ cut=LUT(A,B,γ,M)! Стадия компрессии
|
||||
уровня найдена материально: A/B/γ живут в объекте [band+0x180],
|
||||
заполняются сеттерами. Осталось: снять их live-значения для наших конфигов
|
||||
(расширить scalar-dump на [ctx+0x180]-объект) и найти потребителя таблицы
|
||||
(интерполятор dB→out) в аудио-тракте.
|
||||
|
||||
## ДОПОЛНЕНИЕ 24cc: точная формула коэф. 533340 (дизасм+live)
|
||||
[state+8] = n = 2049 (∀ трёх состояний; live probe_states.py).
|
||||
```
|
||||
fc_norm = (X/(sr·0.5))·n ; X=xmm2 (C_hz=1000 или tau — уточнить)
|
||||
g(i) = min(fc_norm/i, (fc_norm/i)^p) ; p=[ctx+0x54087c]=1 @defaults
|
||||
c = 1/(1 + g/mult) ; mult=360 (стадия-3)
|
||||
arg = |c| · g / n ← НАСЫЩАЮЩАЯ форма (пол g→mult/n)
|
||||
up[i] = exp(arg · (−2π)) ; down[i]=1−up[i]
|
||||
```
|
||||
При дефолтах down ∈ [0.003..0.19] — очень мягкие сглаживатели; эффект
|
||||
только каскадом в полной цепочке шагов 9–19.
|
||||
Осталось уточнить: роль xmm13 (множитель перед c), знак/конст экспоненты,
|
||||
соответствие X=C_hz-vs-tau.
|
||||
|
||||
## ДОПОЛНЕНИЕ 24ff: семантика шага 11 (fma att/rel) — тройки (re,im,coef)
|
||||
|
||||
Цепочка вызова: ee20 → 487a0 → 1065c0; воркер получает r10=n/2·12 байт
|
||||
⇒ элементы по 12 байт = (dst_re f32, dst_im f32, coef f32).
|
||||
Call-site (52ac70–52acd4):
|
||||
```
|
||||
шаг 11a: fma(rcx=f6f8_upper, rdx=ATT@[5406c8], r8=ACC_i, r9=n/2)
|
||||
шаг 11b: fma(rcx=f6f8_lower, rdx=REL@[5406e8], r8=ACC_i, r9=n/2)
|
||||
```
|
||||
⇒ семантика: f6f8[k] += coef[k]·ACC_i[k] (комплексный axpy с пер-биновым
|
||||
скаляром), верхняя половина спектра — с ATTACK коэф., нижняя — с RELEASE.
|
||||
ACC_i персистентен между кадрами ⇒ утечный интегратор: стационар
|
||||
ACC = input/(1−coef); усиление 1/(1−att): @43=2.57 @85=2.93 @171=3.42.
|
||||
Коэф. массивы СТАТИЧНЫ (∀ конфигов бит-в-бит — проверено dual/qmap/sens18).
|
||||
Гипотеза: резонансное усиление ACC объясняет k>1 аномалии уровней
|
||||
(q2: impl/ours=2.48 ≈ A(85)); точная алгебра подачи ACC в кривую — в
|
||||
остатке шагов 13–19.
|
||||
|
||||
## ДОПОЛНЕНИЕ 24gg: шаг 12 — ЭТО КОПИЯ (исправление BLOCKMAP)
|
||||
|
||||
th1b80→6840→1a5a0→181a646c0 = ЧИСТЫЙ MEMCPY (vmovdqu без арифметики).
|
||||
«acc_i += bands[i]» из старого BLOCKMAP — НЕВЕРНО; реально копия
|
||||
(направление/роли rbx/rbp уточнить трассировкой регистров через цикл —
|
||||
аргументы на 52acf8: rcx=rbx, rdx=rbp, r8=n; значения rbx/rbp меняются
|
||||
через 52ac98 [0x5406e8] и др. — нужен полный dataflow-проход шагов 9–19).
|
||||
|
||||
Следствие: если acc_i не накапливается сложением, «резонансная» гипотеза
|
||||
24ff требует пересмотра — возможно ACC обновляется через fma шага 11
|
||||
(ACC входит как источник), а шаг 12 синхронизирует массивы.
|
||||
|
||||
### Статус декода шагов 9–19 (24ff+24gg)
|
||||
- шаг 11: f6f8[k] += att/rel_coef[k]·ACC_i[k] ✓ (тройки re,im,coef)
|
||||
- шаг 12: COPY (не add!) ✓ исправлено
|
||||
- шаги 13–16: th2270-add ветка с xmm6=xmm12−[54087c]; bigkernel 140950;
|
||||
axpy 2000/1c40 с vec@540778 — тела не декодированы
|
||||
- полный dataflow-проход = задача следующего раунда (связная, ~сессия)
|
||||
|
||||
## ДОПОЛНЕНИЕ 24hh: DATAFLOW шагов 9–12 (точный, из дизасма)
|
||||
|
||||
```
|
||||
шаг 9a: vec698 *= (xmm12 − [54087c]) ; th1a00=MUL; при 1−1=0 → ZERO
|
||||
шаг 9b: vec6f8 += 0.8 ; xmm10=0.8 ([1824c3e28]); th2270=ADD
|
||||
шаг 9c: bigkernel 140b60(vec6f8, bands_curve_i, vec6f8)
|
||||
шаг 10: vec6f8 = bands_curve_i − ACC_i ; dc40: out[r8]=rdx−r10 ✓COMBINE
|
||||
шаг 11: f6f8_upper += ATT[k]·ACC_i[k] ; тройки re/im/coef
|
||||
f6f8_lower += REL[k]·ACC_i[k]
|
||||
шаг 12: COPY(...) ; направление уточнить
|
||||
```
|
||||
Регистры: rbx↔vec698/6f8/acc_i, rbp↔bands_curve/[5406e8], r14=vec6f8.
|
||||
Картина: строится КОРРЕКЦИОННАЯ кривая (bands−ACC), модулированная
|
||||
att/rel-огибающими ACC — адаптивная петля редукции.
|
||||
Остаток прохода: шаги 13–19 + эпилог + связь с FIR-секцией (52b3cd+).
|
||||
|
||||
## ДОПОЛНЕНИЕ 24ii: семантики шагов 13–16 + ИСПРАВЛЕНИЕ th2000
|
||||
|
||||
th2000/fb60 (и 1c40/8700) = ПОЭЛЕМЕНТНОЕ УМНОЖЕНИЕ МАССИВОВ
|
||||
(dst[k] *= src[k]) — НЕ axpy! Исправляет интерпретации:
|
||||
|
||||
```
|
||||
шаг 13 (флаг≠0): зеркало шага 9 (vec698*=..., vec6f8+=0.8·..., bigkernel)
|
||||
шаг 14: bands_curve += (−1.0) ; константа [1824c4680]=−1 через th2270!
|
||||
затем bigkernel 1409e0/140ad0 IN-PLACE на bands_curve
|
||||
шаг 15: bands_curve *= track_i ; th2000 array-multiply
|
||||
шаг 16: bands_curve *= kWarp@[5406a8] ; th2000 array-multiply
|
||||
шаг 17(флаг): bigkernel in-place ещё раз
|
||||
```
|
||||
Картинка: кривая центрируется (−1), проходит нелинейность (bigkernel,
|
||||
вероятно exp/abs — тела за IAT), модулируется track и warp.
|
||||
Против log-входа design'а значение после этих шагов должно быть >0.
|
||||
|
||||
### Bigkernel-тела за ВЛОЖЕННЫМ диспатчем
|
||||
Таблицы стабов содержат смесь IAT-слотов и внутренних адресов (напр.
|
||||
table[7]=140a00), но внутренние ведут к call runtime-helper + НОВЫЙ
|
||||
ILT-стаб с собственной idx-ячейкой (паковка/протектор). Статическое
|
||||
разворачивание обрывается. Тела bigkernel'ов (exp/abs-нелинейность шага
|
||||
14/17) остаются за пакером — при необходимости снимаются дампом памяти
|
||||
ВОКРУГ вызова в рантайме (STOP + чтение таблиц после инициализации).
|
||||
|
||||
## ДОПОЛНЕНИЕ 24jj: ТЕЛА BIGKERNEL'ОВ НАЙДЕНЫ (рантайм-резолв IAT)
|
||||
|
||||
iat_name.py v2 (SIGSTOP + двойной deref + PE-экспорты) резолвит:
|
||||
```
|
||||
стаб 140b30/140b60 → runtime 1803a06a0 (общий для float/double!)
|
||||
стаб 1409e0 → runtime 180296c80
|
||||
стаб 140ad0 → runtime 180323f20
|
||||
стаб 140a40 → runtime 1802dc0e0
|
||||
```
|
||||
Все — НАСТОЯЩИЕ функции внутри дампа (не импорты!): большие стек-фреймы,
|
||||
x87 FNU-контроль, AVX2 полиномы, ДВЕ x87-трансцендентные инструкции
|
||||
(fyl2x/f2xm1 класс = 2^x/exp семейство). Полный декод математики каждого —
|
||||
отдельная сессия; вход/выход уже известны из контекста вызовов
|
||||
(in-place над n/2+1 элементами FIR-буфера).
|
||||
|
||||
## ДОПОЛНЕНИЕ 24jj2: R@540788 — БАНДПАС-ФОРМА, НЕ совпадающая с нашим twin!
|
||||
|
||||
Сравнение (multi6, band1=500/q0.5/s12):
|
||||
```
|
||||
бин R@540788 наш_res R/наш
|
||||
43 0.802 0.117 6.84
|
||||
85 1.086 0.374 2.91
|
||||
171 1.517 0.839 1.81
|
||||
342 3.521 1.401 2.51 ← ПИК ~3.5-4 кГц!
|
||||
512 2.910 1.673 1.74
|
||||
684 1.829 1.811 1.01
|
||||
1024 1.146 1.931 0.59
|
||||
1536 0.689 1.988 0.35
|
||||
```
|
||||
Наш twin res растёт монотонно от fc; R@788 — БАНДПАС с пиком ~bin300-342
|
||||
(~3.5-4 кГц) и СПАДОМ к Найквисту. Форма напоминает кривую равной
|
||||
громкости / слухового взвешивания!
|
||||
R@5407f8 = единичная нормировка (все 1.0000 в этом прогоне).
|
||||
|
||||
### ГИПОТЕЗА (проверяемая):
|
||||
Детекторный уровень = am · ВЕС(f) / res(f), где ВЕС — кривая типа
|
||||
равной громкости (R@788?). Тест: X=am·R/res против катов multi6 —
|
||||
НЕ сошлось лобово (X@43=1.44 макс при мин кате) ⇒ взвешивание входит
|
||||
иначе (до/после res-деления, или в log-домене).
|
||||
### Ценность
|
||||
Объясняет ВСЕ аномалии дальних бинов разом: наши дальние res слишком
|
||||
велики (нет спада), их lvl занижен, каты недобираются. Формула ВЕСА —
|
||||
ключ к кросс-конфиг параметризации.
|
||||
|
||||
## ДОПОЛНЕНИЕ 24kk3: слот [ctx+0x540668] ПОЛИМОРФНЫЙ!
|
||||
|
||||
Прямой проб во время рендера: [ctx+0x540668] содержит
|
||||
`3fdbcd8940000000` = ДВА FLOAT (~0.434, 2.0), НЕ указатель!
|
||||
(пробник probe_668.py; EIO на части чтений — слот мигрирует).
|
||||
|
||||
### Следствия:
|
||||
1. rendersnap2 пропускает слот 668 (ptr<0x10000 или мусорный ptr) ⇒
|
||||
во ВСЕХ новых захватах (sc_multi4b, sc_tt*, sc_q*, ...) НЕТ FIR-массивов.
|
||||
2. Старые захваты rendersnap.py v1 ИМЕЛИ валидный FIR-указатель в эти
|
||||
моменты (ловили фазу обработки). Данные старых phase*.npz про FIR —
|
||||
валидны для своих моментов, но смешивать с новыми нельзя.
|
||||
3. Все «FIR mag» анализы через этот слот зависят от ТОГО, в какой фазе
|
||||
слот был пойман: указатель-на-буфер vs скаляры vs сброс.
|
||||
4. Значения скаляров (~0.43, 2.0) — кандидаты: att/rel? dry/wet? g-компоненты?
|
||||
### Статус
|
||||
Канонический путь чтения ПРИМЕНЁННОЙ маски: слот [ctx+0x540678] (кривая
|
||||
банды) — он стабилен и МАТЧИТ АУДИО в deep-фазах (±5%).
|
||||
|
||||
## ДОПОЛНЕНИЕ 24mm2: ПОЛНАЯ РЕЗОЛЮВСЯ ВСЕХ 10 ЯДЕР + ИСПРАВЛЕНИЯ DATAFLOW
|
||||
|
||||
Инструмент: статический резолв цепочки стаб→таблица→L2→IAT-слот по
|
||||
soothe_mem.bin (без live). Стаб = `movsxd rax,[idx@1826159a0]; lea r10,[tbl];
|
||||
jmp [r10+rax*8]`, idx=4, L2=`mov rax,[slot]; jmp rax`.
|
||||
|
||||
### Таблица резолва (исправляет 24jj!)
|
||||
| стаб | таблица | runtime | опознание по константам |
|
||||
|------|---------|---------|------------------------|
|
||||
| 140950 | 182617448 | **18026b820** | exp2/exp DOUBLE (ln2, log2e, 1021.5, 2^27) |
|
||||
| 140980 | 182617488 | **18027c120** | **logf** FLOAT (ряд −½,+⅓,−¼,+⅕,−⅙; ln2 hi/lo; 2^32) |
|
||||
| 1409b0 | 1826174c8 | **18028d1e0** | **powf/log+exp** DOUBLE (ряд log + магия expf вместе) |
|
||||
| 1409e0 | 182617508 | 180296c80 ✓ | **expf** FLOAT — ДЕКОДИРОВАН ПОЛНОСТЬЮ (ниже) |
|
||||
| 140a40 | 182617588 | 1802dc0e0 ✓ | exp-вариант FLOAT c hi/lo сплитами |
|
||||
| 140aa0 | 182617608 | **18030fee0** | **sincos** DOUBLE (1/6,1/120,1/5040; π hi/lo) |
|
||||
| 140ad0 | 182617648 | 180323f20 ✓ | кусочно-табличная DOUBLE (сетка Δ=0.00541521) |
|
||||
| 140b00 | 182617688 | **180367980** | pow/exp DOUBLE (1023/1022, магия 1.5·2^20) |
|
||||
| 140b30 | 1826176c8 | **1803831c0** | кусочно-табличная FLOAT (π/2, π/4, сетка 184.665!) |
|
||||
| 140b60 | 182617708 | 1803a06a0 ✓ | **DIVIDE** FLOAT B/A (rcp+квантование+vpermps-таблицы+полином невязки) |
|
||||
|
||||
**ИСПРАВЛЕНИЕ 24jj**: «140b30/140b60 → общий 1803a06a0» — НЕВЕРНО.
|
||||
FIR-секция вызывает 140b30 = 1803831c0 (табличная кривая), divide только в шаге 9c.
|
||||
|
||||
### ДИСПЕТЧЕР float/double
|
||||
Каждый call-site имеет ПАРУ стабов через `call [181bab008]; test eax,eax; jne`:
|
||||
float-стаб (eax==0) / double-стаб. Дескрипторы type_info СТАТИЧЕСКИ идентичны
|
||||
(оба →182650db8) ⇒ eax=0 ⇒ **double-ядра мертвы на нашем пути**; рендеры
|
||||
идут по float. Double-тела не транскрибируем (отмечено на будущее M8).
|
||||
|
||||
### expf 180296c80 — полная формула (горячий цикл, FMA-точно)
|
||||
```
|
||||
n = fma(log2e_hi=1.4427, x, MAGIC=12582912.0) ; округление до int
|
||||
k = n − MAGIC
|
||||
r = (x − 0.693146·k) − 1.42861e-06·k ; ln2 hi/lo
|
||||
p = (((0.00829172·r + 0.0418735)·r + 0.166674)·r + 0.499994)·r + 1)·r + 1
|
||||
out = bits( (k<<23) + bits(p) ) ; vpaddd сборка
|
||||
guard: |x|>87.3365 → slow-path; head/tail через vmaskmovps+popcnt-маски
|
||||
```
|
||||
Коэф. минимаксные — транскрибировать КАК ЕСТЬ.
|
||||
|
||||
### DIVIDE 1803a06a0 — структура (90%)
|
||||
```
|
||||
A=[rcx], B=[rdx], dst=[r8]; r9d=n
|
||||
q0 = rcp(A); q0 += 2^23-magic (округление); q = q0 & 0xfff00000 ; 12 бит
|
||||
e = (q>>23); idx = q>>20 → vpermps tbl@1821269c0 (127±ε) и @182126a00
|
||||
err = 1 − q·A
|
||||
полином невязки {0.207515, −0.241687, 0.288535, −0.360671, ..., 0.240264, 0.0555119}
|
||||
сборка через магию 1.5·2^20 + vpslld 20
|
||||
результат ≈ B/A с точностью ~0.5 ulp
|
||||
```
|
||||
Таблицы коррекций сдамплены (per-mantissa-top-bits).
|
||||
|
||||
### ИСПРАВЛЕНИЯ DATAFLOW (по fn529fe0.dis, адреса call-sites)
|
||||
1. **Шаг 14 порядок ОБРАТЕН к BLOCKMAP 24ii**: сначала `bigkernel exp IN-PLACE
|
||||
на bands_curve` (52ae0e), ПОТОМ `bands_curve += (−1.0)` (52ae40, конст.
|
||||
1824c4680 через th2270).
|
||||
2. Шаг 9b точно: `vec6f8 += [ctx+54087c] · 0.8` (xmm10=0.8@1824c3e28,
|
||||
множитель виден в asm: mulss xmm6,xmm10 после movss xmm6,[54087c]).
|
||||
3. Шаг 9a: `vec698 *= (xmm12=1.0 − [54087c])` ⇒ zero-fill при дефолтах ✓.
|
||||
4. Шаг 10 combine dc40: аргументы rcx=ACC_i(**таблица указателей @0x5407c8**,
|
||||
НЕ дампилась rendersnap2!), rdx=bands_curve_i(@678+i), r8=vec6f8(@6f8),
|
||||
семантика dst=r8: vec6f8 = bands_curve_i − ACC_i. ACC-слот надо ДОБАВИТЬ
|
||||
в SLOTS rendersnap2 (0x5407c8).
|
||||
5. Шаги 15/16 подтверждены: th2000/th1c40 array-mul; затем rbx=[5406a8]
|
||||
(kWarp) — array-mul на bands_curve.
|
||||
6. Эпилог: скалярная часть из decomp (consumers_out 100-143): mix-веса,
|
||||
`fVar17 = [540874] − expf(DAT_1824c4704=-ln1000)` → bands += f17·[540888].
|
||||
|
||||
### Call-site карта больших ядер (fn529fe0)
|
||||
```
|
||||
52a63a/52a641: 140980(logf-float)/1409b0 — pre-combine #1
|
||||
52ab84/52ab8b: 140b60(divide)/140950 — шаг 9c
|
||||
52acd? : (шаги 10–12 мелкие ILT)
|
||||
52ae0e/52ae15: 1409e0(expf)/140ad0 — шаг 14 нелинейность
|
||||
52b32c/52b336: 1409e0(expf)/140ad0 — шаг 17 (повтор)
|
||||
52b3a0/52b3aa: 140a40(exp-var)/140b00 — пост-17
|
||||
52b716/52b71d: 140b30(кривая-float)/140aa0 — FIR-секция
|
||||
```
|
||||
|
||||
## ДОПОЛНЕНИЕ 24mm5: ПОЛНАЯ КАРТА ТРАКТА — буферы каждого шага; design = conv-тело 22z
|
||||
|
||||
### Полоса-цикл (float-путь), трасса регистров 52a580–52b3cd
|
||||
```
|
||||
пре: [678i] *= скаляры (s888-цепь, xmm7·[540870]·[54088c])
|
||||
LOG#1 (140980!) на [678i] ; 52a63a — В ЛОГ-ДОМЕН заранее
|
||||
combine 52d650([678i],[6f8])
|
||||
шаг 9a: vec698@698 *= (1−[54087c]) ; zero
|
||||
шаг 9b: vec6f8@6f8 += [54087c]·0.8
|
||||
шаг 9c: DIVIDE dst=[678i]: A=arg(rcx)=[678i], B=arg(rdx)=[6f8]
|
||||
⇒ [678i] = vec6f8 / bands_curve ; in-place
|
||||
шаг 10: dc40: rcx=ACC_i(@7c8+i!), rdx=[678i], r8=[6f8]
|
||||
⇒ vec6f8 = bands_curve − ACC_i ; ACC — таблица указателей 7c8
|
||||
шаг 11: fma ATT(@6c8)/REL(@6e8) — пары вызовов 1fa0/1940
|
||||
шаг 12: COPY 1b80/1d60 c [678i]
|
||||
шаг 13: зеркало 9a/9b + оп 1eb0(cbe0)([678i],[6f8])
|
||||
шаг 14: EXP#1 (1409e0=expf) на [678i]; затем += (−1)
|
||||
шаг 15: array-mul: X[rsp+0x40] *= [678i] ; НЕ bands*=track!
|
||||
шаг 16: [678i] *= kWarp@[5406a8]
|
||||
LOG#2 (140980) на [678i] ; 52aefd — возврат в лог!
|
||||
IIR4 ×2 бидир ; ~52af09–52b2b6, СПЕКТРАЛЬНОЕ
|
||||
; СМЕШЕНИЕ В ЛОГ-ДОМЕНЕ
|
||||
скаляры xmm14(−0.7)/xmm15(−0.5)-класс
|
||||
шаг 17: EXP#2 (1409e0) на [678i]; += scalar; exp-var 140a40 финал
|
||||
→ bands_final @678i
|
||||
```
|
||||
|
||||
### FIR-секция (52b3cd–52b94a)
|
||||
```
|
||||
bands_final *= s888, *= [540888]; += xmm7 (скаляр с expf(−ln1000)=0.001)
|
||||
DESIGN: call 535a70(rcx=scratch@628, rdx=bands)
|
||||
535a70 = диспетчер СО СВОПОМ аргументов → ILT 140a10/140a70 →
|
||||
→ РЕЗОЛВ: float=1802a24c0 (!!!), double=1802fa420
|
||||
⚡ ЭТО ТЕЛО FFT-CONV ИЗ ОТКРЫТОГО ВОПРОСА 22z («conv_float_a24c0.dis»,
|
||||
184K AVX2). Дизайн детектора == недекодированный conv. Пазл склеен.
|
||||
дальше: copy th2210; complex-op th2180/th1bb0 с твидл-буферами
|
||||
548/550/598; знак −1 (52d920); EXP 140b30(=1803831c0);
|
||||
окно 52d990(WINfreq); pair-scalar 1880/1ca0; *= wet[540888];
|
||||
финал df0(FIR, track_i)
|
||||
```
|
||||
|
||||
### Где γ=1.760561
|
||||
mask = bands_final^γ точно ⇒ γ возникает между scratch=log(bands_final)
|
||||
и финальной маской: либо ВНУТРИ design 1802a24c0 (масштаб на выходе),
|
||||
либо в комплекс-op цепочке 52b644–52b716 перед EXP 140b30. Обе точки
|
||||
локализованы до ~десятка инструкций — декод следующего раунда.
|
||||
|
||||
### Исправление понимания слотов
|
||||
- 688 = exp(628) тривиально: 628 — копия лога bands_final (design),
|
||||
688 — сами bands_final (или их exp-копия). «track» — имя рендерснапа.
|
||||
- 678 ПОСЛЕ цикла = bands_final; применённая маска перезаписывает
|
||||
поверх (финальный combine) — поэтому захваченный 678 матчит аудио.
|
||||
|
||||
## ДОПОЛНЕНИЕ 24mm6: ПЕРЕД EXP В FIR — УМНОЖЕНИЕ НА 2.0 (не −1!); гипотеза γ=2·k_design
|
||||
|
||||
### Точная последовательность 52b60c–52b720 (проверено, без пропусков)
|
||||
```
|
||||
rcx=[540628](scratch), rdx=[r15](источник design — уточнить r15!)
|
||||
call 535a70 → swap → 1802a24c0(scratch ← DESIGN(src))
|
||||
th2210: FIR(@540668) ← scratch (copy, edx=0)
|
||||
opB: th2180(FIR, buf548|550, buf598) ; complex pass
|
||||
FIR[n]=0
|
||||
FIR[1 .. n/2] *= xmm13 = 2.0 @1824c41e0 ; 52d920, БЫЛО «−1» в 24l — НЕВЕРНО
|
||||
FIR[n/2+1 .. n-1] *= xmm9 (=0) ; 52db50
|
||||
opC: th1a90(FIR, buf548|550, buf598) ; complex pass
|
||||
EXP in-place 140b30 (float) / 140aa0 (double)
|
||||
```
|
||||
xmm13/xmm9 не перезаписываются между 52b3d6 и использованием (проверено).
|
||||
|
||||
### Гипотеза источника γ
|
||||
Если opB/opC сохраняют пропорциональность (упаковка real-FFT), то
|
||||
mask = exp(2 · scratch) ⇒ γ = 2·k, где k — масштаб выхода design
|
||||
1802a24c0 относительно ln(bands): k = 1.760561/2 = 0.8802805.
|
||||
Альтернатива: k=1, а opB/opC суммарно дают множитель 0.88028.
|
||||
|
||||
### Открытые микровопросы (следующий раунд, всё локализовано)
|
||||
1. Что такое [r15] на входе design (bands_final@678 или иной буфер)?
|
||||
2. Семантика opB/opC (th2180/th1bb0/th1a90/th19d0 + твидлы 548/550/598)
|
||||
— вероятно упаковка/развёртка real-FFT.
|
||||
3. Масштаб выхода design: декод хвоста 1802a24c0 (файл уже есть:
|
||||
nls_dasm/conv_float_a24c0.dis, 184K).
|
||||
4. Согласование с identity-фазой захватов (гонка финального combine).
|
||||
|
||||
## ДОПОЛНЕНИЕ 24mm7: design выход = точный ln(bands_final); γ создаётся после design
|
||||
|
||||
### Численный тест (multi6/ph034, identity-фаза)
|
||||
```
|
||||
scr@628 − ln(cur@678): max|r| = 9.0e-08 (float32 eps) на 1013 бинах
|
||||
⇒ k_design = 1 (в момент захвата)
|
||||
```
|
||||
Оговорка: станционарность делает «свежий» и «сталый» scratch
|
||||
неразличимы; но факт (scr, cur)=(лог, значение) одной пары твёрд.
|
||||
|
||||
### Следствие для γ
|
||||
γ=1.760561 ≠ 2 ⇒ множитель НЕ только «×2 перед EXP». Источники:
|
||||
(a) opB/opC не взаимно сокращаются (не чистая упаковка real-FFT);
|
||||
(b) пост-exp шаги: окно 52d990 (варьируется по позиции — нарушил бы
|
||||
степенной закон, значит действует на верхнюю половину/после),
|
||||
pair-scalar th1880/th1ca0, финальный combine df0(FIR, track_i),
|
||||
где track=exp(scr)=bands_final.
|
||||
Комбинации дающие γ из {1,2}: 1+2x=1.760561 ⇒ x=0.3802805;
|
||||
либо лог-доменное смешение track^a·FIR^b c a+2b=1.760561.
|
||||
|
||||
### Статус декода design 1802a24c0
|
||||
AVX-512 (zmm, masked {k3}/{k4}), 3822 строки objdump — трансформ-класс.
|
||||
Для замыкания γ его полный декод МОЖНО НЕ НУЖЕН: достаточно семантики
|
||||
opB/opC + df0 (десятки инструкций в fn529fe0.dis).
|
||||
|
||||
## ДОПОЛНЕНИЕ 24mm8 (финал захода): opB/opC/df0 резолвлены
|
||||
```
|
||||
opB: 180002180→180004ca80(f)/18001d160(d) ; дескриптор-оп (тег [obj]==6)
|
||||
opC: 180001a90→18001a0c0(f)/180018400(d)
|
||||
df0: 18000df0→18000b3c0 ; f70→18000e360 ; финальный combine
|
||||
```
|
||||
Все четыре микровопроса 24mm6 закрыты или локализованы до тел-обёрток.
|
||||
Следующий раунд: семантика 4ca80/1a0c0 (кандидаты источника γ=2k−масштаба),
|
||||
затем полный numpy-конвейер.
|
||||
|
||||
## ДОПОЛНЕНИЕ 24mm9: opB/opC = RFFT-близнецы; df0 = complex-mul; цепь валидирована 0.0065 дБ
|
||||
|
||||
### Слой вызовов FIR-секции (уточнение поверх 24l/24mm6)
|
||||
```
|
||||
обёртки: th2180 impl=125e0, th1a90 impl=5560 — только перестановка аргументов:
|
||||
воркер получает (rcx=data, rdx=data, r8=ПЛАН, r9=WORK), ин-плейс.
|
||||
ПЛАН = [ctx+540548] (buf548!): tag=6 [+0], log2n=12 [+4], flag [+8]=0,
|
||||
scale_flag=1 [+0xc], scale=2^-12 [+0x10], workbytes=16384 [+0x18].
|
||||
WORK = [ctx+540598] — рабочая область FFT (заметение «lane-mask» из 23b).
|
||||
th2180 → воркер 4ca80(f)/1d160(d): INVERSE real-RFFT (голова: X[0]±X[Nyq]).
|
||||
th1a90 → воркер 1a0c0(f)/18400(d): FORWARD real-RFFT (хвост: пакинг Nyq).
|
||||
тела: импортные близнецы 181b853e0(inv)/181b81b80(fwd); константы только
|
||||
±0.707107; масштабов нет. ffe0 = ×scale pass (skip при scale∈{0,1}).
|
||||
copy th2210 → 136e0 → 4d900(src,dst,n): pack re=v, im=0 (vunpcklps+zero).
|
||||
df0 18000b3c0: ПОЭЛЕМЕНТНОЕ КОМПЛЕКСНОЕ УМНОЖЕНИЕ dst=[rdx]=arg2:
|
||||
track_i := track_i ⊗ FIR (vfmaddsub213ps; f70/b560 — double версия).
|
||||
EXP 140b30 → 1803831c0: полиномиальная комплексная exp (без таблиц значений):
|
||||
magic 12582912 (=2^23·1.5), guard 87.33654, редукция 184.665≈128/ln2,
|
||||
коэф. {−0.01604,−1.541667(=−37/24), 3.166e-05, 1.008329, −1.65777e-06,
|
||||
−0.01932, 0.00134, 0.00541687, 10000, 4.19179}; AVX-512+FMA.
|
||||
Численно = поточечный комплексный exp (flat-exp проигрывает 8 дБ).
|
||||
```
|
||||
|
||||
### Полная последовательность (52b60c–52b893, все шаги, без пропусков)
|
||||
```
|
||||
design 535a70(scratch@628 ← ln(bands_i)) ; 52b62f, своп аргументов
|
||||
copy 2210(scratch → FIR, 2049 пар (re,im=0)) ; 52b644
|
||||
FIR[4096]=0 ; 52b685 Найквост ДО фолда
|
||||
inv-RFFT opA ; 52b672 th2180
|
||||
fold: float[1..2047]*=2.0 (xmm13@1824c41e0) ; 52d920
|
||||
float[2049..4095]=0 ; 52db50
|
||||
fwd-RFFT opB ; 52b6e1 th1a90
|
||||
EXP in-place, аргумент×q (q≈0.80, источник ОТКРЫТ); 52b716
|
||||
inv-RFFT opC ; 52b74b th2180
|
||||
FIR[4096]=0 ; 52b76d
|
||||
float[0..2047]*=WINfreq[2048..4095] ; 52d990 (падающий Hann)
|
||||
float[2048..4095]=0 ; 52db50
|
||||
fwd-RFFT opD ; 52b7ba th1a90
|
||||
FIR[0]=1.0f; FIR[1]=0 ; 52b7cd
|
||||
(flag f890≠0: pair-scalars 1880/ca0 — live мертво)
|
||||
th2030(FIR, wet=s888, 2n float) ; 52b857, s888=1 no-op
|
||||
df0(FIR, track_i, n): track_i := track_i ⊗ FIR ; 52b893
|
||||
```
|
||||
Смысл: классическое минимально-фазовое ядро через кепстр
|
||||
(IDFT лога → фолдинг ×2 причинной части + усечение → exp → обратный ход).
|
||||
|
||||
### Валидация и γ
|
||||
mask_sim = trk·|F(q)|: 60 ультрачистых кадров, ВСЕ 2049 бина:
|
||||
rms мед 0.0065 дБ / p90 0.0075 / max 0.035 при q=0.80 (порог 0.05 ✓).
|
||||
γ = 1 + s_F(q), s_F = наклон log|F| по log trk в нотче: q=0.8 ⇒ γ_pred=1.7516
|
||||
(точный 1.760561). Открыто: место q в асме (внутренность 1803831c0);
|
||||
unicorn не эмулирует FMA ⇒ нужен статдекод ядра или live-захват входа EXP.
|
||||
Дизасмы: /tmp/opencode/cascade/{wrapA_125e0,wrapB_5560,opB_4ca80,opC_1a0c0,
|
||||
df0_b3c0,h_ffe0,h_136e0*,imp_b8*3e0_full,bk_1803831c0}.dis
|
||||
(*copy: python3 scripts/disasm_func.py 1800136e0 — ВАЖНО: полный VA,
|
||||
короткая форма «125e0» даёт пустой файл!).
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
# PROMPT FOR NEXT SESSION (2026-08-25, после 24kk2)
|
||||
|
||||
Продолжаем bit-exact реверс soothe2 в /home/m/re-tools (ветка main).
|
||||
ГЕЙТ СМЕНЫ КАНОНА = BIT EXACT (решение пользователя): все параметры
|
||||
прослежены до декомпа + корпус в шумовом пол. До тех пор канон не трогаем.
|
||||
|
||||
ПРОЧИТАТЬ ПЕРВЫМ: AGENTS.md (фаза-заголовок 24kk2 + env-флаги + инструменты)
|
||||
→ handoff/NOTES_LEVEL.md обновления 24j–24kk2 → BLOCKMAP_529fe0.md
|
||||
(дополнения 23b/24l/24hh/24ii).
|
||||
|
||||
## СОСТОЯНИЕ
|
||||
|
||||
ПРИМЕНЕНИЕ ДЕКОДИРОВАНО ДО ФОРМУЛ:
|
||||
```
|
||||
mask(b) = 10^(−cut_D(b)/20) вещественная, per-bin multiply кадра
|
||||
cut_D(b) = α·ln1p(lvl_raw(b)/β)+c [+Δ вторые пики]
|
||||
lvl_raw = am/res·scale наш фронтенд, float-parity ✓
|
||||
слой = STFT БЕЗ синтез-окна RT_SYN=1
|
||||
```
|
||||
Калибровки (rms ≤0.016 дБ):
|
||||
```
|
||||
dual fc500 q0.5 s12 ДВА тона : α=3.2193 β=0.4927 c=+0.54
|
||||
fc1000 q0.5 s12 ОДИН тон : α=1.6151 β=0.3645 c=+0.48
|
||||
fc500 q0.5 s12 ОДИН тон : α=1.1530 β=0.4038 c=+0.33
|
||||
```
|
||||
Корпус: dual **0.193 max 0.438** с флагами `RT_VLAW=1 RT_SYN=1 RT_NOWARP=1
|
||||
RT_NOIIR3=1 RT_IIR12=0`. Канон TOTAL 2.286 нетронут.
|
||||
|
||||
ОТЗЫВАНО И НЕ ВОЗВРАЩАТЬСЯ: ×1.805-свёртка [23e], OLA-нормировка [24i],
|
||||
двухстадийный γ₀ как множитель закона [24m — это артефакт двух тонов],
|
||||
клампы параметров [24dd], B∝am [24bb], axpy-семантика th2000 [24ii — это
|
||||
array-multiply], «acc_i += bands[i]» шага 12 [24gg — это COPY].
|
||||
|
||||
## ЗАДАЧА №1: каскадный симулятор шагов 9–19 (оп-за-опом)
|
||||
|
||||
Dataflow декодирован (BLOCKMAP 24hh/24ii):
|
||||
```
|
||||
vec698 *= (xmm12−[54087c]) ; обнуление при дефолтах
|
||||
vec6f8 += 0.8 ; базовая линия
|
||||
bigkernel(vec6f8, bands_i, vec6f8)
|
||||
vec6f8 = bands_curve − ACC_i ; COMBINE (dc40: out=rdx−r10)
|
||||
f6f8_верх += ATT[k]·ACC[k]; низ += REL[k]·ACC[k] ; тройки re/im/coef
|
||||
COPY(...) ; шаг 12 = memcpy!
|
||||
bands += (−1.0); bigkernel in-place ; центрирование+нелинейность
|
||||
bands *= track_i; bands *= kWarp ; th2000 = array-multiply
|
||||
IIR4 ×2; финальные scale/op
|
||||
→ bands[i] → design log → scratch → FIR → audio multiply exp(scratch)
|
||||
```
|
||||
Тела bigkernel'ов по рантайм-адресам: 1803a06a0/180296c80/180323f20/1802dc0e0
|
||||
(x87 exp-семейство). Коэффициенты IIR-генератора 533340 исправлены
|
||||
(насыщающая форма arg=|c|·g/n; p=[54087c]=1, mult=360, C=1000).
|
||||
|
||||
Метод проверки: собрать симулятор в Python (numpy), прогнать lvl_raw из
|
||||
tract_* через каскад, сравнить с deepest-scratch кривыми sc_* — rms < 0.05 дБ
|
||||
= замкнулось. Затем перенос в C++.
|
||||
|
||||
## ЗАДАЧА №2: параметризация α(контент)/fc
|
||||
|
||||
α удваивается с числом тонов (частотное смешение шаблонно-локальное —
|
||||
далёкий тон не влияет, 24ll). Инструмент: scripts/campaign.py (ячейка ≈8 мин).
|
||||
Двухтональная дистанционная серия уже снята (sc_d*, инверсия не сошлась —
|
||||
нужен каскад из Задачи №1 сначала!).
|
||||
|
||||
## СРЕДА (грабли, всё проверено болью)
|
||||
- rendersnap2.py: RENDER_FILE брать ИЗ rpp (клоны наследуют путь — однажды
|
||||
перезаписали реф); каталоги снапов задавать уникальные (argv[3]).
|
||||
- touch+mtime перед каждым замером (same-second cmake hazard).
|
||||
- tone1k.wav громче dual.wav в 2.28× — при сравнении серий учитывать.
|
||||
- Свип НЕ годится для Y/X-отношения; только мультитон/мультиуровень.
|
||||
- Динамика V(t)↔g(t) на рампе не сходится — пары только из стационара.
|
||||
- HW-ловушки под wine невозможны (wine держит слоты); INT3 требует
|
||||
дисциплины fnwatch4 и ГАРАНТИРОВАННО свежего рендера.
|
||||
- Метрика только честная: render_parity.load / Гёрцель последних 0.75 c.
|
||||
- Коммитить подшагами; факты → NOTES_LEVEL (очередной номер 24ll+).
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,383 @@
|
||||
; cons_52ec00 0x18052eb00-0x18052f100
|
||||
|
||||
/tmp/slice.bin: file format binary
|
||||
|
||||
|
||||
Disassembly of section .data:
|
||||
|
||||
000000018052eb00 <.data>:
|
||||
18052eb00: 0f af c8 imul %eax,%ecx
|
||||
18052eb03: 8b 05 f7 cb 0f 02 mov 0x20fcbf7(%rip),%eax # 0x18262b700
|
||||
18052eb09: 44 0f af e0 imul %eax,%r12d
|
||||
18052eb0d: 8b 86 e0 04 24 00 mov 0x2404e0(%rsi),%eax
|
||||
18052eb13: 05 e2 2c dc 06 add $0x6dc2ce2,%eax
|
||||
18052eb18: 44 2b e1 sub %ecx,%r12d
|
||||
18052eb1b: 25 7f 00 00 80 and $0x8000007f,%eax
|
||||
18052eb20: 7d 07 jge 0x18052eb29
|
||||
18052eb22: ff c8 dec %eax
|
||||
18052eb24: 83 c8 80 or $0xffffff80,%eax
|
||||
18052eb27: ff c0 inc %eax
|
||||
18052eb29: 89 86 e0 04 24 00 mov %eax,0x2404e0(%rsi)
|
||||
18052eb2f: 48 63 c8 movslq %eax,%rcx
|
||||
18052eb32: 48 8b 86 b0 08 54 00 mov 0x5408b0(%rsi),%rax
|
||||
18052eb39: f3 0f 10 04 88 movss (%rax,%rcx,4),%xmm0
|
||||
18052eb3e: 8b 05 c0 cb 0f 02 mov 0x20fcbc0(%rip),%eax # 0x18262b704
|
||||
18052eb44: 66 0f 6e d0 movd %eax,%xmm2
|
||||
18052eb48: 8b 86 e0 04 24 00 mov 0x2404e0(%rsi),%eax
|
||||
18052eb4e: ff c0 inc %eax
|
||||
18052eb50: 48 63 c8 movslq %eax,%rcx
|
||||
18052eb53: 48 8b 86 b0 08 54 00 mov 0x5408b0(%rsi),%rax
|
||||
18052eb5a: 0f 5b d2 cvtdq2ps %xmm2,%xmm2
|
||||
18052eb5d: f3 0f 59 d0 mulss %xmm0,%xmm2
|
||||
18052eb61: f3 0f 10 04 88 movss (%rax,%rcx,4),%xmm0
|
||||
18052eb66: 8b 05 5c ca 0f 02 mov 0x20fca5c(%rip),%eax # 0x18262b5c8
|
||||
18052eb6c: 66 0f 6e c8 movd %eax,%xmm1
|
||||
18052eb70: 8b 05 8a cb 0f 02 mov 0x20fcb8a(%rip),%eax # 0x18262b700
|
||||
18052eb76: 0f 5b c9 cvtdq2ps %xmm1,%xmm1
|
||||
18052eb79: f3 0f 59 c8 mulss %xmm0,%xmm1
|
||||
18052eb7d: f3 0f 59 ca mulss %xmm2,%xmm1
|
||||
18052eb81: f3 0f 58 cd addss %xmm5,%xmm1
|
||||
18052eb85: f3 0f 2c d9 cvttss2si %xmm1,%ebx
|
||||
18052eb89: 0f af d8 imul %eax,%ebx
|
||||
18052eb8c: 8b 86 e0 04 24 00 mov 0x2404e0(%rsi),%eax
|
||||
18052eb92: 05 9a f2 4b 00 add $0x4bf29a,%eax
|
||||
18052eb97: 89 9c 24 f8 00 00 00 mov %ebx,0xf8(%rsp)
|
||||
18052eb9e: 25 7f 00 00 80 and $0x8000007f,%eax
|
||||
18052eba3: 7d 07 jge 0x18052ebac
|
||||
18052eba5: ff c8 dec %eax
|
||||
18052eba7: 83 c8 80 or $0xffffff80,%eax
|
||||
18052ebaa: ff c0 inc %eax
|
||||
18052ebac: 89 86 e0 04 24 00 mov %eax,0x2404e0(%rsi)
|
||||
18052ebb2: 48 63 c8 movslq %eax,%rcx
|
||||
18052ebb5: 48 8b 86 b0 08 54 00 mov 0x5408b0(%rsi),%rax
|
||||
18052ebbc: f3 0f 10 04 88 movss (%rax,%rcx,4),%xmm0
|
||||
18052ebc1: 8b 05 3d cb 0f 02 mov 0x20fcb3d(%rip),%eax # 0x18262b704
|
||||
18052ebc7: 66 0f 6e d0 movd %eax,%xmm2
|
||||
18052ebcb: 8b 86 e0 04 24 00 mov 0x2404e0(%rsi),%eax
|
||||
18052ebd1: ff c0 inc %eax
|
||||
18052ebd3: 48 63 c8 movslq %eax,%rcx
|
||||
18052ebd6: 48 8b 86 b0 08 54 00 mov 0x5408b0(%rsi),%rax
|
||||
18052ebdd: 0f 5b d2 cvtdq2ps %xmm2,%xmm2
|
||||
18052ebe0: f3 0f 59 d0 mulss %xmm0,%xmm2
|
||||
18052ebe4: f3 0f 10 04 88 movss (%rax,%rcx,4),%xmm0
|
||||
18052ebe9: 8b 05 d9 c9 0f 02 mov 0x20fc9d9(%rip),%eax # 0x18262b5c8
|
||||
18052ebef: 66 0f 6e c8 movd %eax,%xmm1
|
||||
18052ebf3: 8b 05 07 cb 0f 02 mov 0x20fcb07(%rip),%eax # 0x18262b700
|
||||
18052ebf9: 0f 5b c9 cvtdq2ps %xmm1,%xmm1
|
||||
18052ebfc: f3 0f 59 c8 mulss %xmm0,%xmm1
|
||||
18052ec00: f3 0f 59 ca mulss %xmm2,%xmm1
|
||||
18052ec04: f3 0f 58 cd addss %xmm5,%xmm1
|
||||
18052ec08: f3 0f 2c c9 cvttss2si %xmm1,%ecx
|
||||
18052ec0c: 0f af c8 imul %eax,%ecx
|
||||
18052ec0f: 8b 86 e0 04 24 00 mov 0x2404e0(%rsi),%eax
|
||||
18052ec15: 05 94 62 cb 00 add $0xcb6294,%eax
|
||||
18052ec1a: 66 0f 6e f1 movd %ecx,%xmm6
|
||||
18052ec1e: 0f 5b f6 cvtdq2ps %xmm6,%xmm6
|
||||
18052ec21: 25 7f 00 00 80 and $0x8000007f,%eax
|
||||
18052ec26: 7d 07 jge 0x18052ec2f
|
||||
18052ec28: ff c8 dec %eax
|
||||
18052ec2a: 83 c8 80 or $0xffffff80,%eax
|
||||
18052ec2d: ff c0 inc %eax
|
||||
18052ec2f: 89 86 e0 04 24 00 mov %eax,0x2404e0(%rsi)
|
||||
18052ec35: 48 63 c8 movslq %eax,%rcx
|
||||
18052ec38: 48 8b 86 b0 08 54 00 mov 0x5408b0(%rsi),%rax
|
||||
18052ec3f: f3 0f 10 04 88 movss (%rax,%rcx,4),%xmm0
|
||||
18052ec44: 8b 05 ba ca 0f 02 mov 0x20fcaba(%rip),%eax # 0x18262b704
|
||||
18052ec4a: 66 0f 6e e0 movd %eax,%xmm4
|
||||
18052ec4e: 8b 86 e0 04 24 00 mov 0x2404e0(%rsi),%eax
|
||||
18052ec54: ff c0 inc %eax
|
||||
18052ec56: 48 63 c8 movslq %eax,%rcx
|
||||
18052ec59: 48 8b 86 b0 08 54 00 mov 0x5408b0(%rsi),%rax
|
||||
18052ec60: 0f 5b e4 cvtdq2ps %xmm4,%xmm4
|
||||
18052ec63: f3 0f 59 e0 mulss %xmm0,%xmm4
|
||||
18052ec67: f3 0f 10 04 88 movss (%rax,%rcx,4),%xmm0
|
||||
18052ec6c: 8b 05 56 c9 0f 02 mov 0x20fc956(%rip),%eax # 0x18262b5c8
|
||||
18052ec72: 66 0f 6e d8 movd %eax,%xmm3
|
||||
18052ec76: 8b 86 e0 04 24 00 mov 0x2404e0(%rsi),%eax
|
||||
18052ec7c: 0f 5b db cvtdq2ps %xmm3,%xmm3
|
||||
18052ec7f: 05 e0 b5 10 00 add $0x10b5e0,%eax
|
||||
18052ec84: f3 0f 59 d8 mulss %xmm0,%xmm3
|
||||
18052ec88: 25 7f 00 00 80 and $0x8000007f,%eax
|
||||
18052ec8d: 7d 07 jge 0x18052ec96
|
||||
18052ec8f: ff c8 dec %eax
|
||||
18052ec91: 83 c8 80 or $0xffffff80,%eax
|
||||
18052ec94: ff c0 inc %eax
|
||||
18052ec96: f3 0f 10 3d 06 52 f9 movss 0x1f95206(%rip),%xmm7 # 0x1824c3ea4
|
||||
18052ec9d: 01
|
||||
18052ec9e: 33 ff xor %edi,%edi
|
||||
18052eca0: 89 86 e0 04 24 00 mov %eax,0x2404e0(%rsi)
|
||||
18052eca6: 48 63 c8 movslq %eax,%rcx
|
||||
18052eca9: 48 8b 86 b0 08 54 00 mov 0x5408b0(%rsi),%rax
|
||||
18052ecb0: f3 0f 59 dc mulss %xmm4,%xmm3
|
||||
18052ecb4: f3 0f 10 04 88 movss (%rax,%rcx,4),%xmm0
|
||||
18052ecb9: 8b 05 45 ca 0f 02 mov 0x20fca45(%rip),%eax # 0x18262b704
|
||||
18052ecbf: f3 0f 58 dd addss %xmm5,%xmm3
|
||||
18052ecc3: 66 0f 6e d0 movd %eax,%xmm2
|
||||
18052ecc7: 8b 86 e0 04 24 00 mov 0x2404e0(%rsi),%eax
|
||||
18052eccd: ff c0 inc %eax
|
||||
18052eccf: 48 63 c8 movslq %eax,%rcx
|
||||
18052ecd2: 48 8b 86 b0 08 54 00 mov 0x5408b0(%rsi),%rax
|
||||
18052ecd9: 0f 5b d2 cvtdq2ps %xmm2,%xmm2
|
||||
18052ecdc: f3 44 0f 2c eb cvttss2si %xmm3,%r13d
|
||||
18052ece1: f3 0f 59 d0 mulss %xmm0,%xmm2
|
||||
18052ece5: f3 0f 10 04 88 movss (%rax,%rcx,4),%xmm0
|
||||
18052ecea: 8b 05 d8 c8 0f 02 mov 0x20fc8d8(%rip),%eax # 0x18262b5c8
|
||||
18052ecf0: 66 0f 6e c8 movd %eax,%xmm1
|
||||
18052ecf4: 8b 05 06 ca 0f 02 mov 0x20fca06(%rip),%eax # 0x18262b700
|
||||
18052ecfa: 0f 5b c9 cvtdq2ps %xmm1,%xmm1
|
||||
18052ecfd: f3 0f 59 c8 mulss %xmm0,%xmm1
|
||||
18052ed01: f3 0f 59 ca mulss %xmm2,%xmm1
|
||||
18052ed05: f3 0f 58 cd addss %xmm5,%xmm1
|
||||
18052ed09: f3 0f 2c c9 cvttss2si %xmm1,%ecx
|
||||
18052ed0d: 0f af c8 imul %eax,%ecx
|
||||
18052ed10: 8b 05 ea c9 0f 02 mov 0x20fc9ea(%rip),%eax # 0x18262b700
|
||||
18052ed16: 44 0f af e8 imul %eax,%r13d
|
||||
18052ed1a: 44 03 e9 add %ecx,%r13d
|
||||
18052ed1d: 84 d2 test %dl,%dl
|
||||
18052ed1f: 0f 85 95 03 00 00 jne 0x18052f0ba
|
||||
18052ed25: 48 8b ce mov %rsi,%rcx
|
||||
18052ed28: e8 d3 e0 ff ff call 0x18052ce00
|
||||
18052ed2d: 8b 86 a0 01 00 00 mov 0x1a0(%rsi),%eax
|
||||
18052ed33: 48 8d 8e 68 06 54 00 lea 0x540668(%rsi),%rcx
|
||||
18052ed3a: 0f af c3 imul %ebx,%eax
|
||||
18052ed3d: 0f 57 d2 xorps %xmm2,%xmm2
|
||||
18052ed40: c1 e0 03 shl $0x3,%eax
|
||||
18052ed43: 89 86 68 08 54 00 mov %eax,0x540868(%rsi)
|
||||
18052ed49: 99 cltd
|
||||
18052ed4a: 2b c2 sub %edx,%eax
|
||||
18052ed4c: d1 f8 sar $1,%eax
|
||||
18052ed4e: 8d 14 18 lea (%rax,%rbx,1),%edx
|
||||
18052ed51: 89 96 6c 08 54 00 mov %edx,0x54086c(%rsi)
|
||||
18052ed57: 03 d2 add %edx,%edx
|
||||
18052ed59: e8 32 f4 ff ff call 0x18052e190
|
||||
18052ed5e: 8b 96 6c 08 54 00 mov 0x54086c(%rsi),%edx
|
||||
18052ed64: 48 8d 8e 98 06 54 00 lea 0x540698(%rsi),%rcx
|
||||
18052ed6b: 0f 57 d2 xorps %xmm2,%xmm2
|
||||
18052ed6e: e8 1d f4 ff ff call 0x18052e190
|
||||
18052ed73: 8b d7 mov %edi,%edx
|
||||
18052ed75: 39 be a0 06 54 00 cmp %edi,0x5406a0(%rsi)
|
||||
18052ed7b: 7e 1e jle 0x18052ed9b
|
||||
18052ed7d: 8b cf mov %edi,%ecx
|
||||
18052ed7f: 90 nop
|
||||
18052ed80: 48 8b 86 98 06 54 00 mov 0x540698(%rsi),%rax
|
||||
18052ed87: 48 8d 49 04 lea 0x4(%rcx),%rcx
|
||||
18052ed8b: ff c2 inc %edx
|
||||
18052ed8d: f3 0f 11 74 01 fc movss %xmm6,-0x4(%rcx,%rax,1)
|
||||
18052ed93: 3b 96 a0 06 54 00 cmp 0x5406a0(%rsi),%edx
|
||||
18052ed99: 7c e5 jl 0x18052ed80
|
||||
18052ed9b: 8b 96 6c 08 54 00 mov 0x54086c(%rsi),%edx
|
||||
18052eda1: 48 8d 8e a8 06 54 00 lea 0x5406a8(%rsi),%rcx
|
||||
18052eda8: 0f 57 d2 xorps %xmm2,%xmm2
|
||||
18052edab: e8 e0 f3 ff ff call 0x18052e190
|
||||
18052edb0: 8b 96 6c 08 54 00 mov 0x54086c(%rsi),%edx
|
||||
18052edb6: 48 8d 8e b8 06 54 00 lea 0x5406b8(%rsi),%rcx
|
||||
18052edbd: 0f 57 d2 xorps %xmm2,%xmm2
|
||||
18052edc0: e8 cb f3 ff ff call 0x18052e190
|
||||
18052edc5: 8b 96 6c 08 54 00 mov 0x54086c(%rsi),%edx
|
||||
18052edcb: 48 8d 8e c8 06 54 00 lea 0x5406c8(%rsi),%rcx
|
||||
18052edd2: 0f 57 d2 xorps %xmm2,%xmm2
|
||||
18052edd5: e8 b6 f3 ff ff call 0x18052e190
|
||||
18052edda: 8b 96 6c 08 54 00 mov 0x54086c(%rsi),%edx
|
||||
18052ede0: 48 8d 8e d8 06 54 00 lea 0x5406d8(%rsi),%rcx
|
||||
18052ede7: 0f 57 d2 xorps %xmm2,%xmm2
|
||||
18052edea: e8 a1 f3 ff ff call 0x18052e190
|
||||
18052edef: 8b 96 6c 08 54 00 mov 0x54086c(%rsi),%edx
|
||||
18052edf5: 48 8d 8e e8 06 54 00 lea 0x5406e8(%rsi),%rcx
|
||||
18052edfc: 0f 57 d2 xorps %xmm2,%xmm2
|
||||
18052edff: e8 8c f3 ff ff call 0x18052e190
|
||||
18052ee04: 45 8b fc mov %r12d,%r15d
|
||||
18052ee07: 44 3b 66 30 cmp 0x30(%rsi),%r12d
|
||||
18052ee0b: 0f 8d ee 01 00 00 jge 0x18052efff
|
||||
18052ee11: 45 8b f5 mov %r13d,%r14d
|
||||
18052ee14: 49 63 dc movslq %r12d,%rbx
|
||||
18052ee17: 45 0f af f5 imul %r13d,%r14d
|
||||
18052ee1b: 48 81 c3 73 40 05 00 add $0x54073,%rbx
|
||||
18052ee22: 48 c1 e3 04 shl $0x4,%rbx
|
||||
18052ee26: 41 c1 e6 0e shl $0xe,%r14d
|
||||
18052ee2a: 48 03 de add %rsi,%rbx
|
||||
18052ee2d: 0f 1f 00 nopl (%rax)
|
||||
18052ee30: 8b ae 6c 08 54 00 mov 0x54086c(%rsi),%ebp
|
||||
18052ee36: 8b 83 50 ff ff ff mov -0xb0(%rbx),%eax
|
||||
18052ee3c: 3b c5 cmp %ebp,%eax
|
||||
18052ee3e: 74 3e je 0x18052ee7e
|
||||
18052ee40: 85 c0 test %eax,%eax
|
||||
18052ee42: 7e 11 jle 0x18052ee55
|
||||
18052ee44: 48 8b 8b 48 ff ff ff mov -0xb8(%rbx),%rcx
|
||||
18052ee4b: 48 85 c9 test %rcx,%rcx
|
||||
18052ee4e: 74 05 je 0x18052ee55
|
||||
18052ee50: e8 6b 22 ad ff call 0x1800010c0
|
||||
18052ee55: 85 ed test %ebp,%ebp
|
||||
18052ee57: 48 89 bb 48 ff ff ff mov %rdi,-0xb8(%rbx)
|
||||
18052ee5e: 0f 48 ef cmovs %edi,%ebp
|
||||
18052ee61: 89 ab 50 ff ff ff mov %ebp,-0xb0(%rbx)
|
||||
18052ee67: 85 ed test %ebp,%ebp
|
||||
18052ee69: 74 3e je 0x18052eea9
|
||||
18052ee6b: 8d 0c ad 00 00 00 00 lea 0x0(,%rbp,4),%ecx
|
||||
18052ee72: e8 09 22 ad ff call 0x180001080
|
||||
18052ee77: 48 89 83 48 ff ff ff mov %rax,-0xb8(%rbx)
|
||||
18052ee7e: 8b d7 mov %edi,%edx
|
||||
18052ee80: 39 bb 50 ff ff ff cmp %edi,-0xb0(%rbx)
|
||||
18052ee86: 7e 21 jle 0x18052eea9
|
||||
18052ee88: 48 8b cf mov %rdi,%rcx
|
||||
18052ee8b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
|
||||
18052ee90: 48 8b 83 48 ff ff ff mov -0xb8(%rbx),%rax
|
||||
18052ee97: 48 8d 49 04 lea 0x4(%rcx),%rcx
|
||||
18052ee9b: ff c2 inc %edx
|
||||
18052ee9d: 89 7c 01 fc mov %edi,-0x4(%rcx,%rax,1)
|
||||
18052eea1: 3b 93 50 ff ff ff cmp -0xb0(%rbx),%edx
|
||||
18052eea7: 7c e7 jl 0x18052ee90
|
||||
18052eea9: 8b 03 mov (%rbx),%eax
|
||||
18052eeab: 41 3b c6 cmp %r14d,%eax
|
||||
18052eeae: 74 35 je 0x18052eee5
|
||||
18052eeb0: 85 c0 test %eax,%eax
|
||||
18052eeb2: 7e 0e jle 0x18052eec2
|
||||
18052eeb4: 48 8b 4b f8 mov -0x8(%rbx),%rcx
|
||||
18052eeb8: 48 85 c9 test %rcx,%rcx
|
||||
18052eebb: 74 05 je 0x18052eec2
|
||||
18052eebd: e8 fe 21 ad ff call 0x1800010c0
|
||||
18052eec2: 45 85 f6 test %r14d,%r14d
|
||||
18052eec5: 48 89 7b f8 mov %rdi,-0x8(%rbx)
|
||||
18052eec9: 41 8b ce mov %r14d,%ecx
|
||||
18052eecc: 0f 48 cf cmovs %edi,%ecx
|
||||
18052eecf: 89 0b mov %ecx,(%rbx)
|
||||
18052eed1: 85 c9 test %ecx,%ecx
|
||||
18052eed3: 74 31 je 0x18052ef06
|
||||
18052eed5: 8d 0c 8d 00 00 00 00 lea 0x0(,%rcx,4),%ecx
|
||||
18052eedc: e8 9f 21 ad ff call 0x180001080
|
||||
18052eee1: 48 89 43 f8 mov %rax,-0x8(%rbx)
|
||||
18052eee5: 8b d7 mov %edi,%edx
|
||||
18052eee7: 39 3b cmp %edi,(%rbx)
|
||||
18052eee9: 7e 1b jle 0x18052ef06
|
||||
18052eeeb: 48 8b cf mov %rdi,%rcx
|
||||
18052eeee: 66 90 xchg %ax,%ax
|
||||
18052eef0: 48 8b 43 f8 mov -0x8(%rbx),%rax
|
||||
18052eef4: 48 8d 49 04 lea 0x4(%rcx),%rcx
|
||||
18052eef8: ff c2 inc %edx
|
||||
18052eefa: c7 44 01 fc 00 00 80 movl $0x3f800000,-0x4(%rcx,%rax,1)
|
||||
18052ef01: 3f
|
||||
18052ef02: 3b 13 cmp (%rbx),%edx
|
||||
18052ef04: 7c ea jl 0x18052eef0
|
||||
18052ef06: 8b ae 6c 08 54 00 mov 0x54086c(%rsi),%ebp
|
||||
18052ef0c: 8b 83 80 00 00 00 mov 0x80(%rbx),%eax
|
||||
18052ef12: 3b c5 cmp %ebp,%eax
|
||||
18052ef14: 74 35 je 0x18052ef4b
|
||||
18052ef16: 85 c0 test %eax,%eax
|
||||
18052ef18: 7e 0e jle 0x18052ef28
|
||||
18052ef1a: 48 8b 4b 78 mov 0x78(%rbx),%rcx
|
||||
18052ef1e: 48 85 c9 test %rcx,%rcx
|
||||
18052ef21: 74 05 je 0x18052ef28
|
||||
18052ef23: e8 98 21 ad ff call 0x1800010c0
|
||||
18052ef28: 85 ed test %ebp,%ebp
|
||||
18052ef2a: 48 89 7b 78 mov %rdi,0x78(%rbx)
|
||||
18052ef2e: 0f 48 ef cmovs %edi,%ebp
|
||||
18052ef31: 89 ab 80 00 00 00 mov %ebp,0x80(%rbx)
|
||||
18052ef37: 85 ed test %ebp,%ebp
|
||||
18052ef39: 74 3b je 0x18052ef76
|
||||
18052ef3b: 8d 0c ad 00 00 00 00 lea 0x0(,%rbp,4),%ecx
|
||||
18052ef42: e8 39 21 ad ff call 0x180001080
|
||||
18052ef47: 48 89 43 78 mov %rax,0x78(%rbx)
|
||||
18052ef4b: 8b d7 mov %edi,%edx
|
||||
18052ef4d: 39 bb 80 00 00 00 cmp %edi,0x80(%rbx)
|
||||
18052ef53: 7e 21 jle 0x18052ef76
|
||||
18052ef55: 48 8b cf mov %rdi,%rcx
|
||||
18052ef58: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
|
||||
18052ef5f: 00
|
||||
18052ef60: 48 8b 43 78 mov 0x78(%rbx),%rax
|
||||
18052ef64: 48 8d 49 04 lea 0x4(%rcx),%rcx
|
||||
18052ef68: ff c2 inc %edx
|
||||
18052ef6a: 89 7c 01 fc mov %edi,-0x4(%rcx,%rax,1)
|
||||
18052ef6e: 3b 93 80 00 00 00 cmp 0x80(%rbx),%edx
|
||||
18052ef74: 7c ea jl 0x18052ef60
|
||||
18052ef76: 8b ae 6c 08 54 00 mov 0x54086c(%rsi),%ebp
|
||||
18052ef7c: 8b 83 a0 00 00 00 mov 0xa0(%rbx),%eax
|
||||
18052ef82: 3b c5 cmp %ebp,%eax
|
||||
18052ef84: 74 3e je 0x18052efc4
|
||||
18052ef86: 85 c0 test %eax,%eax
|
||||
18052ef88: 7e 11 jle 0x18052ef9b
|
||||
18052ef8a: 48 8b 8b 98 00 00 00 mov 0x98(%rbx),%rcx
|
||||
18052ef91: 48 85 c9 test %rcx,%rcx
|
||||
18052ef94: 74 05 je 0x18052ef9b
|
||||
18052ef96: e8 25 21 ad ff call 0x1800010c0
|
||||
18052ef9b: 85 ed test %ebp,%ebp
|
||||
18052ef9d: 48 89 bb 98 00 00 00 mov %rdi,0x98(%rbx)
|
||||
18052efa4: 0f 48 ef cmovs %edi,%ebp
|
||||
18052efa7: 89 ab a0 00 00 00 mov %ebp,0xa0(%rbx)
|
||||
18052efad: 85 ed test %ebp,%ebp
|
||||
18052efaf: 74 3d je 0x18052efee
|
||||
18052efb1: 8d 0c ad 00 00 00 00 lea 0x0(,%rbp,4),%ecx
|
||||
18052efb8: e8 c3 20 ad ff call 0x180001080
|
||||
18052efbd: 48 89 83 98 00 00 00 mov %rax,0x98(%rbx)
|
||||
18052efc4: 8b d7 mov %edi,%edx
|
||||
18052efc6: 39 bb a0 00 00 00 cmp %edi,0xa0(%rbx)
|
||||
18052efcc: 7e 20 jle 0x18052efee
|
||||
18052efce: 48 8b cf mov %rdi,%rcx
|
||||
18052efd1: 48 8b 83 98 00 00 00 mov 0x98(%rbx),%rax
|
||||
18052efd8: 48 8d 49 04 lea 0x4(%rcx),%rcx
|
||||
18052efdc: ff c2 inc %edx
|
||||
18052efde: c7 44 01 fc 00 00 80 movl $0x3f800000,-0x4(%rcx,%rax,1)
|
||||
18052efe5: 3f
|
||||
18052efe6: 3b 93 a0 00 00 00 cmp 0xa0(%rbx),%edx
|
||||
18052efec: 7c e3 jl 0x18052efd1
|
||||
18052efee: 41 ff c7 inc %r15d
|
||||
18052eff1: 48 83 c3 10 add $0x10,%rbx
|
||||
18052eff5: 44 3b 7e 30 cmp 0x30(%rsi),%r15d
|
||||
18052eff9: 0f 8c 31 fe ff ff jl 0x18052ee30
|
||||
18052efff: 8b 96 68 08 54 00 mov 0x540868(%rsi),%edx
|
||||
18052f005: 48 8d 8e f8 06 54 00 lea 0x5406f8(%rsi),%rcx
|
||||
18052f00c: c1 e2 03 shl $0x3,%edx
|
||||
18052f00f: 0f 57 d2 xorps %xmm2,%xmm2
|
||||
18052f012: e8 79 f1 ff ff call 0x18052e190
|
||||
18052f017: 8b 96 68 08 54 00 mov 0x540868(%rsi),%edx
|
||||
18052f01d: 48 8d 8e 08 07 54 00 lea 0x540708(%rsi),%rcx
|
||||
18052f024: 41 0f af d5 imul %r13d,%edx
|
||||
18052f028: 0f 57 d2 xorps %xmm2,%xmm2
|
||||
18052f02b: e8 60 f1 ff ff call 0x18052e190
|
||||
18052f030: 8b 96 68 08 54 00 mov 0x540868(%rsi),%edx
|
||||
18052f036: 48 8d 8e 18 07 54 00 lea 0x540718(%rsi),%rcx
|
||||
18052f03d: 41 0f af d5 imul %r13d,%edx
|
||||
18052f041: 0f 57 d2 xorps %xmm2,%xmm2
|
||||
18052f044: e8 47 f1 ff ff call 0x18052e190
|
||||
18052f049: 8b 96 68 08 54 00 mov 0x540868(%rsi),%edx
|
||||
18052f04f: 48 8d 8e 98 07 54 00 lea 0x540798(%rsi),%rcx
|
||||
18052f056: 0f 57 d2 xorps %xmm2,%xmm2
|
||||
18052f059: e8 32 f1 ff ff call 0x18052e190
|
||||
18052f05e: 44 8b c7 mov %edi,%r8d
|
||||
18052f061: 39 be a0 07 54 00 cmp %edi,0x5407a0(%rsi)
|
||||
18052f067: 7e 26 jle 0x18052f08f
|
||||
18052f069: 48 8b cf mov %rdi,%rcx
|
||||
18052f06c: 0f 1f 40 00 nopl 0x0(%rax)
|
||||
18052f070: 48 8b 86 98 07 54 00 mov 0x540798(%rsi),%rax
|
||||
18052f077: 48 8d 49 04 lea 0x4(%rcx),%rcx
|
||||
18052f07b: 41 ff c0 inc %r8d
|
||||
18052f07e: c7 44 01 fc 00 00 80 movl $0x3f800000,-0x4(%rcx,%rax,1)
|
||||
18052f085: 3f
|
||||
18052f086: 44 3b 86 a0 07 54 00 cmp 0x5407a0(%rsi),%r8d
|
||||
18052f08d: 7c e1 jl 0x18052f070
|
||||
18052f08f: 44 8b 86 68 08 54 00 mov 0x540868(%rsi),%r8d
|
||||
18052f096: 48 8d 8e 30 05 54 00 lea 0x540530(%rsi),%rcx
|
||||
18052f09d: 8b 56 64 mov 0x64(%rsi),%edx
|
||||
18052f0a0: e8 8b eb ff ff call 0x18052dc30
|
||||
18052f0a5: 0f 28 df movaps %xmm7,%xmm3
|
||||
18052f0a8: 48 8d 8e 30 05 54 00 lea 0x540530(%rsi),%rcx
|
||||
18052f0af: 45 8b c5 mov %r13d,%r8d
|
||||
18052f0b2: 41 8b d5 mov %r13d,%edx
|
||||
18052f0b5: e8 46 0d 00 00 call 0x18052fe00
|
||||
18052f0ba: 45 8b cc mov %r12d,%r9d
|
||||
18052f0bd: 4c 8b ac 24 00 01 00 mov 0x100(%rsp),%r13
|
||||
18052f0c4: 00
|
||||
18052f0c5: 44 3b 66 30 cmp 0x30(%rsi),%r12d
|
||||
18052f0c9: 0f 8d a8 00 00 00 jge 0x18052f177
|
||||
18052f0cf: 49 63 cc movslq %r12d,%rcx
|
||||
18052f0d2: 48 81 c1 7b 40 05 00 add $0x5407b,%rcx
|
||||
18052f0d9: 48 c1 e1 04 shl $0x4,%rcx
|
||||
18052f0dd: 48 03 ce add %rsi,%rcx
|
||||
18052f0e0: 44 8b c7 mov %edi,%r8d
|
||||
18052f0e3: 39 79 80 cmp %edi,-0x80(%rcx)
|
||||
18052f0e6: 7e 22 jle 0x18052f10a
|
||||
18052f0e8: 48 8b d7 mov %rdi,%rdx
|
||||
18052f0eb: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
|
||||
18052f0f0: 48 8b 81 78 ff ff ff mov -0x88(%rcx),%rax
|
||||
18052f0f7: 48 8d 52 04 lea 0x4(%rdx),%rdx
|
||||
18052f0fb: 41 ff c0 inc %r8d
|
||||
18052f0fe: f3 repz
|
||||
18052f0ff: 0f .byte 0xf
|
||||
@@ -0,0 +1,275 @@
|
||||
; cons_536100 0x180536000-0x180536400
|
||||
|
||||
/tmp/slice.bin: file format binary
|
||||
|
||||
|
||||
Disassembly of section .data:
|
||||
|
||||
0000000180536000 <.data>:
|
||||
180536000: e8 bb b0 ac ff call 0x1800010c0
|
||||
180536005: 90 nop
|
||||
180536006: 48 89 bb 58 07 54 00 mov %rdi,0x540758(%rbx)
|
||||
18053600d: 89 bb 60 07 54 00 mov %edi,0x540760(%rbx)
|
||||
180536013: 39 bb 50 07 54 00 cmp %edi,0x540750(%rbx)
|
||||
180536019: 7e 12 jle 0x18053602d
|
||||
18053601b: 48 8b 8b 48 07 54 00 mov 0x540748(%rbx),%rcx
|
||||
180536022: 48 85 c9 test %rcx,%rcx
|
||||
180536025: 74 06 je 0x18053602d
|
||||
180536027: e8 94 b0 ac ff call 0x1800010c0
|
||||
18053602c: 90 nop
|
||||
18053602d: 48 89 bb 48 07 54 00 mov %rdi,0x540748(%rbx)
|
||||
180536034: 89 bb 50 07 54 00 mov %edi,0x540750(%rbx)
|
||||
18053603a: 48 8d 8b 28 07 54 00 lea 0x540728(%rbx),%rcx
|
||||
180536041: 4c 8d 0d d8 81 ff ff lea -0x7e28(%rip),%r9 # 0x18052e220
|
||||
180536048: ba 10 00 00 00 mov $0x10,%edx
|
||||
18053604d: 44 8d 42 f2 lea -0xe(%rdx),%r8d
|
||||
180536051: e8 c6 b6 bf 00 call 0x18113171c
|
||||
180536056: 90 nop
|
||||
180536057: 39 bb 20 07 54 00 cmp %edi,0x540720(%rbx)
|
||||
18053605d: 7e 12 jle 0x180536071
|
||||
18053605f: 48 8b 8b 18 07 54 00 mov 0x540718(%rbx),%rcx
|
||||
180536066: 48 85 c9 test %rcx,%rcx
|
||||
180536069: 74 06 je 0x180536071
|
||||
18053606b: e8 50 b0 ac ff call 0x1800010c0
|
||||
180536070: 90 nop
|
||||
180536071: 48 89 bb 18 07 54 00 mov %rdi,0x540718(%rbx)
|
||||
180536078: 89 bb 20 07 54 00 mov %edi,0x540720(%rbx)
|
||||
18053607e: 39 bb 10 07 54 00 cmp %edi,0x540710(%rbx)
|
||||
180536084: 7e 12 jle 0x180536098
|
||||
180536086: 48 8b 8b 08 07 54 00 mov 0x540708(%rbx),%rcx
|
||||
18053608d: 48 85 c9 test %rcx,%rcx
|
||||
180536090: 74 06 je 0x180536098
|
||||
180536092: e8 29 b0 ac ff call 0x1800010c0
|
||||
180536097: 90 nop
|
||||
180536098: 48 89 bb 08 07 54 00 mov %rdi,0x540708(%rbx)
|
||||
18053609f: 89 bb 10 07 54 00 mov %edi,0x540710(%rbx)
|
||||
1805360a5: 39 bb 00 07 54 00 cmp %edi,0x540700(%rbx)
|
||||
1805360ab: 7e 12 jle 0x1805360bf
|
||||
1805360ad: 48 8b 8b f8 06 54 00 mov 0x5406f8(%rbx),%rcx
|
||||
1805360b4: 48 85 c9 test %rcx,%rcx
|
||||
1805360b7: 74 06 je 0x1805360bf
|
||||
1805360b9: e8 02 b0 ac ff call 0x1800010c0
|
||||
1805360be: 90 nop
|
||||
1805360bf: 48 89 bb f8 06 54 00 mov %rdi,0x5406f8(%rbx)
|
||||
1805360c6: 89 bb 00 07 54 00 mov %edi,0x540700(%rbx)
|
||||
1805360cc: 39 bb f0 06 54 00 cmp %edi,0x5406f0(%rbx)
|
||||
1805360d2: 7e 12 jle 0x1805360e6
|
||||
1805360d4: 48 8b 8b e8 06 54 00 mov 0x5406e8(%rbx),%rcx
|
||||
1805360db: 48 85 c9 test %rcx,%rcx
|
||||
1805360de: 74 06 je 0x1805360e6
|
||||
1805360e0: e8 db af ac ff call 0x1800010c0
|
||||
1805360e5: 90 nop
|
||||
1805360e6: 48 89 bb e8 06 54 00 mov %rdi,0x5406e8(%rbx)
|
||||
1805360ed: 89 bb f0 06 54 00 mov %edi,0x5406f0(%rbx)
|
||||
1805360f3: 39 bb e0 06 54 00 cmp %edi,0x5406e0(%rbx)
|
||||
1805360f9: 7e 12 jle 0x18053610d
|
||||
1805360fb: 48 8b 8b d8 06 54 00 mov 0x5406d8(%rbx),%rcx
|
||||
180536102: 48 85 c9 test %rcx,%rcx
|
||||
180536105: 74 06 je 0x18053610d
|
||||
180536107: e8 b4 af ac ff call 0x1800010c0
|
||||
18053610c: 90 nop
|
||||
18053610d: 48 89 bb d8 06 54 00 mov %rdi,0x5406d8(%rbx)
|
||||
180536114: 89 bb e0 06 54 00 mov %edi,0x5406e0(%rbx)
|
||||
18053611a: 39 bb d0 06 54 00 cmp %edi,0x5406d0(%rbx)
|
||||
180536120: 7e 12 jle 0x180536134
|
||||
180536122: 48 8b 8b c8 06 54 00 mov 0x5406c8(%rbx),%rcx
|
||||
180536129: 48 85 c9 test %rcx,%rcx
|
||||
18053612c: 74 06 je 0x180536134
|
||||
18053612e: e8 8d af ac ff call 0x1800010c0
|
||||
180536133: 90 nop
|
||||
180536134: 48 89 bb c8 06 54 00 mov %rdi,0x5406c8(%rbx)
|
||||
18053613b: 89 bb d0 06 54 00 mov %edi,0x5406d0(%rbx)
|
||||
180536141: 39 bb c0 06 54 00 cmp %edi,0x5406c0(%rbx)
|
||||
180536147: 7e 12 jle 0x18053615b
|
||||
180536149: 48 8b 8b b8 06 54 00 mov 0x5406b8(%rbx),%rcx
|
||||
180536150: 48 85 c9 test %rcx,%rcx
|
||||
180536153: 74 06 je 0x18053615b
|
||||
180536155: e8 66 af ac ff call 0x1800010c0
|
||||
18053615a: 90 nop
|
||||
18053615b: 48 89 bb b8 06 54 00 mov %rdi,0x5406b8(%rbx)
|
||||
180536162: 89 bb c0 06 54 00 mov %edi,0x5406c0(%rbx)
|
||||
180536168: 39 bb b0 06 54 00 cmp %edi,0x5406b0(%rbx)
|
||||
18053616e: 7e 12 jle 0x180536182
|
||||
180536170: 48 8b 8b a8 06 54 00 mov 0x5406a8(%rbx),%rcx
|
||||
180536177: 48 85 c9 test %rcx,%rcx
|
||||
18053617a: 74 06 je 0x180536182
|
||||
18053617c: e8 3f af ac ff call 0x1800010c0
|
||||
180536181: 90 nop
|
||||
180536182: 48 89 bb a8 06 54 00 mov %rdi,0x5406a8(%rbx)
|
||||
180536189: 89 bb b0 06 54 00 mov %edi,0x5406b0(%rbx)
|
||||
18053618f: 39 bb a0 06 54 00 cmp %edi,0x5406a0(%rbx)
|
||||
180536195: 7e 12 jle 0x1805361a9
|
||||
180536197: 48 8b 8b 98 06 54 00 mov 0x540698(%rbx),%rcx
|
||||
18053619e: 48 85 c9 test %rcx,%rcx
|
||||
1805361a1: 74 06 je 0x1805361a9
|
||||
1805361a3: e8 18 af ac ff call 0x1800010c0
|
||||
1805361a8: 90 nop
|
||||
1805361a9: 48 89 bb 98 06 54 00 mov %rdi,0x540698(%rbx)
|
||||
1805361b0: 89 bb a0 06 54 00 mov %edi,0x5406a0(%rbx)
|
||||
1805361b6: 48 8d 8b 78 06 54 00 lea 0x540678(%rbx),%rcx
|
||||
1805361bd: 4c 8d 0d 5c 80 ff ff lea -0x7fa4(%rip),%r9 # 0x18052e220
|
||||
1805361c4: ba 10 00 00 00 mov $0x10,%edx
|
||||
1805361c9: 44 8d 42 f2 lea -0xe(%rdx),%r8d
|
||||
1805361cd: e8 4a b5 bf 00 call 0x18113171c
|
||||
1805361d2: 90 nop
|
||||
1805361d3: 39 bb 70 06 54 00 cmp %edi,0x540670(%rbx)
|
||||
1805361d9: 7e 12 jle 0x1805361ed
|
||||
1805361db: 48 8b 8b 68 06 54 00 mov 0x540668(%rbx),%rcx
|
||||
1805361e2: 48 85 c9 test %rcx,%rcx
|
||||
1805361e5: 74 06 je 0x1805361ed
|
||||
1805361e7: e8 d4 ae ac ff call 0x1800010c0
|
||||
1805361ec: 90 nop
|
||||
1805361ed: 48 89 bb 68 06 54 00 mov %rdi,0x540668(%rbx)
|
||||
1805361f4: 89 bb 70 06 54 00 mov %edi,0x540670(%rbx)
|
||||
1805361fa: 48 8d 8b 30 05 54 00 lea 0x540530(%rbx),%rcx
|
||||
180536201: e8 2a 7b ff ff call 0x18052dd30
|
||||
180536206: 90 nop
|
||||
180536207: 89 bb cc 04 24 00 mov %edi,0x2404cc(%rbx)
|
||||
18053620d: 48 8b 8b c0 04 24 00 mov 0x2404c0(%rbx),%rcx
|
||||
180536214: ff 15 8e 50 67 01 call *0x167508e(%rip) # 0x181bab2a8
|
||||
18053621a: 90 nop
|
||||
18053621b: 48 8d 8b d8 03 00 00 lea 0x3d8(%rbx),%rcx
|
||||
180536222: e8 59 70 ff ff call 0x18052d280
|
||||
180536227: 90 nop
|
||||
180536228: 48 8d 05 49 5e f7 01 lea 0x1f75e49(%rip),%rax # 0x1824ac078
|
||||
18053622f: 48 89 83 d0 03 00 00 mov %rax,0x3d0(%rbx)
|
||||
180536236: 48 8b cb mov %rbx,%rcx
|
||||
180536239: 48 8b 5c 24 40 mov 0x40(%rsp),%rbx
|
||||
18053623e: 48 83 c4 30 add $0x30,%rsp
|
||||
180536242: 5f pop %rdi
|
||||
180536243: e9 58 38 ff ff jmp 0x180529aa0
|
||||
180536248: cc int3
|
||||
180536249: cc int3
|
||||
18053624a: cc int3
|
||||
18053624b: cc int3
|
||||
18053624c: cc int3
|
||||
18053624d: cc int3
|
||||
18053624e: cc int3
|
||||
18053624f: cc int3
|
||||
180536250: f2 0f 10 0d e8 de f8 movsd 0x1f8dee8(%rip),%xmm1 # 0x1824c4140
|
||||
180536257: 01
|
||||
180536258: 48 8d 81 10 00 08 00 lea 0x80010(%rcx),%rax
|
||||
18053625f: f2 0f 11 4c 24 08 movsd %xmm1,0x8(%rsp)
|
||||
180536265: ba 00 80 00 00 mov $0x8000,%edx
|
||||
18053626a: f2 0f 10 44 24 08 movsd 0x8(%rsp),%xmm0
|
||||
180536270: 4c 8b c1 mov %rcx,%r8
|
||||
180536273: c6 41 04 00 movb $0x0,0x4(%rcx)
|
||||
180536277: 48 c7 81 10 00 10 00 movq $0x0,0x100010(%rcx)
|
||||
18053627e: 00 00 00 00
|
||||
180536282: 8b ca mov %edx,%ecx
|
||||
180536284: 66 0f c6 c0 00 shufpd $0x0,%xmm0,%xmm0
|
||||
180536289: a8 0f test $0xf,%al
|
||||
18053628b: 75 13 jne 0x1805362a0
|
||||
18053628d: 0f 1f 00 nopl (%rax)
|
||||
180536290: 0f 11 00 movups %xmm0,(%rax)
|
||||
180536293: 48 8d 40 10 lea 0x10(%rax),%rax
|
||||
180536297: 48 83 e9 01 sub $0x1,%rcx
|
||||
18053629b: 75 f3 jne 0x180536290
|
||||
18053629d: eb 0e jmp 0x1805362ad
|
||||
18053629f: 90 nop
|
||||
1805362a0: 0f 11 00 movups %xmm0,(%rax)
|
||||
1805362a3: 48 8d 40 10 lea 0x10(%rax),%rax
|
||||
1805362a7: 48 83 e9 01 sub $0x1,%rcx
|
||||
1805362ab: 75 f3 jne 0x1805362a0
|
||||
1805362ad: f2 0f 11 4c 24 08 movsd %xmm1,0x8(%rsp)
|
||||
1805362b3: 49 8d 40 10 lea 0x10(%r8),%rax
|
||||
1805362b7: f2 0f 10 44 24 08 movsd 0x8(%rsp),%xmm0
|
||||
1805362bd: 66 0f c6 c0 00 shufpd $0x0,%xmm0,%xmm0
|
||||
1805362c2: a8 0f test $0xf,%al
|
||||
1805362c4: 75 1b jne 0x1805362e1
|
||||
1805362c6: 66 66 0f 1f 84 00 00 data16 nopw 0x0(%rax,%rax,1)
|
||||
1805362cd: 00 00 00
|
||||
1805362d0: 0f 11 00 movups %xmm0,(%rax)
|
||||
1805362d3: 48 8d 40 10 lea 0x10(%rax),%rax
|
||||
1805362d7: 48 83 ea 01 sub $0x1,%rdx
|
||||
1805362db: 75 f3 jne 0x1805362d0
|
||||
1805362dd: 49 8b c0 mov %r8,%rax
|
||||
1805362e0: c3 ret
|
||||
1805362e1: 0f 11 00 movups %xmm0,(%rax)
|
||||
1805362e4: 48 8d 40 10 lea 0x10(%rax),%rax
|
||||
1805362e8: 48 83 ea 01 sub $0x1,%rdx
|
||||
1805362ec: 75 f3 jne 0x1805362e1
|
||||
1805362ee: 49 8b c0 mov %r8,%rax
|
||||
1805362f1: c3 ret
|
||||
1805362f2: cc int3
|
||||
1805362f3: cc int3
|
||||
1805362f4: cc int3
|
||||
1805362f5: cc int3
|
||||
1805362f6: cc int3
|
||||
1805362f7: cc int3
|
||||
1805362f8: cc int3
|
||||
1805362f9: cc int3
|
||||
1805362fa: cc int3
|
||||
1805362fb: cc int3
|
||||
1805362fc: cc int3
|
||||
1805362fd: cc int3
|
||||
1805362fe: cc int3
|
||||
1805362ff: cc int3
|
||||
180536300: 48 89 5c 24 08 mov %rbx,0x8(%rsp)
|
||||
180536305: 48 89 6c 24 18 mov %rbp,0x18(%rsp)
|
||||
18053630a: 48 89 74 24 20 mov %rsi,0x20(%rsp)
|
||||
18053630f: 48 89 54 24 10 mov %rdx,0x10(%rsp)
|
||||
180536314: 57 push %rdi
|
||||
180536315: 41 54 push %r12
|
||||
180536317: 41 55 push %r13
|
||||
180536319: 41 56 push %r14
|
||||
18053631b: 41 57 push %r15
|
||||
18053631d: 48 83 ec 50 sub $0x50,%rsp
|
||||
180536321: 48 63 bc 24 a0 00 00 movslq 0xa0(%rsp),%rdi
|
||||
180536328: 00
|
||||
180536329: 48 8d 15 88 aa 11 02 lea 0x211aa88(%rip),%rdx # 0x182650db8
|
||||
180536330: 4c 8b b4 24 b0 00 00 mov 0xb0(%rsp),%r14
|
||||
180536337: 00
|
||||
180536338: 49 8b e9 mov %r9,%rbp
|
||||
18053633b: 0f 29 74 24 40 movaps %xmm6,0x40(%rsp)
|
||||
180536340: 49 8b d8 mov %r8,%rbx
|
||||
180536343: 66 0f 6e b1 80 00 24 movd 0x240080(%rcx),%xmm6
|
||||
18053634a: 00
|
||||
18053634b: 8d 04 fd 00 00 00 00 lea 0x0(,%rdi,8),%eax
|
||||
180536352: 4c 63 d0 movslq %eax,%r10
|
||||
180536355: 8d 04 3f lea (%rdi,%rdi,1),%eax
|
||||
180536358: 0f 5b f6 cvtdq2ps %xmm6,%xmm6
|
||||
18053635b: 4f 8d 24 96 lea (%r14,%r10,4),%r12
|
||||
18053635f: 4c 63 d0 movslq %eax,%r10
|
||||
180536362: 4d 8d 3c bc lea (%r12,%rdi,4),%r15
|
||||
180536366: 4c 89 a4 24 b0 00 00 mov %r12,0xb0(%rsp)
|
||||
18053636d: 00
|
||||
18053636e: f3 0f 59 71 24 mulss 0x24(%rcx),%xmm6
|
||||
180536373: 48 8d 0d 3e aa 11 02 lea 0x211aa3e(%rip),%rcx # 0x182650db8
|
||||
18053637a: 4b 8d 34 97 lea (%r15,%r10,4),%rsi
|
||||
18053637e: 4e 8d 2c 96 lea (%rsi,%r10,4),%r13
|
||||
180536382: ff 15 80 4c 67 01 call *0x1674c80(%rip) # 0x181bab008
|
||||
180536388: f2 0f 10 0d b8 de f8 movsd 0x1f8deb8(%rip),%xmm1 # 0x1824c4248
|
||||
18053638f: 01
|
||||
180536390: 44 8b cf mov %edi,%r9d
|
||||
180536393: 0f 5a c6 cvtps2pd %xmm6,%xmm0
|
||||
180536396: 85 c0 test %eax,%eax
|
||||
180536398: 48 8b d3 mov %rbx,%rdx
|
||||
18053639b: 49 8b cc mov %r12,%rcx
|
||||
18053639e: 0f 94 84 24 a8 00 00 sete 0xa8(%rsp)
|
||||
1805363a5: 00
|
||||
1805363a6: f2 0f 5e c8 divsd %xmm0,%xmm1
|
||||
1805363aa: 66 0f 5a d1 cvtpd2ps %xmm1,%xmm2
|
||||
1805363ae: e8 4d 76 ff ff call 0x18052da00
|
||||
1805363b3: 80 bd 10 08 00 00 00 cmpb $0x0,0x810(%rbp)
|
||||
1805363ba: 44 8b c7 mov %edi,%r8d
|
||||
1805363bd: 74 1a je 0x1805363d9
|
||||
1805363bf: f3 0f 10 0d dd da f8 movss 0x1f8dadd(%rip),%xmm1 # 0x1824c3ea4
|
||||
1805363c6: 01
|
||||
1805363c7: 48 8b 8c 24 88 00 00 mov 0x88(%rsp),%rcx
|
||||
1805363ce: 00
|
||||
1805363cf: e8 7c 77 ff ff call 0x18052db50
|
||||
1805363d4: e9 88 01 00 00 jmp 0x180536561
|
||||
1805363d9: f3 0f 10 35 c3 da f8 movss 0x1f8dac3(%rip),%xmm6 # 0x1824c3ea4
|
||||
1805363e0: 01
|
||||
1805363e1: 48 8b ce mov %rsi,%rcx
|
||||
1805363e4: 0f 28 ce movaps %xmm6,%xmm1
|
||||
1805363e7: e8 64 77 ff ff call 0x18052db50
|
||||
1805363ec: 44 8b c7 mov %edi,%r8d
|
||||
1805363ef: 0f 57 c9 xorps %xmm1,%xmm1
|
||||
1805363f2: 49 8b cd mov %r13,%rcx
|
||||
1805363f5: e8 56 77 ff ff call 0x18052db50
|
||||
1805363fa: 33 db xor %ebx,%ebx
|
||||
1805363fc: 39 .byte 0x39
|
||||
1805363fd: 9d popf
|
||||
1805363fe: 14 08 adc $0x8,%al
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,69 @@
|
||||
; hot_52e1c0
|
||||
|
||||
/tmp/slice.bin: file format binary
|
||||
|
||||
|
||||
Disassembly of section .data:
|
||||
|
||||
000000018052e1c0 <.data>:
|
||||
18052e1c0: 05 e8 fa 2e ad add $0xad2efae8,%eax
|
||||
18052e1c5: ff 85 f6 48 89 1f incl 0x1f8948f6(%rbp)
|
||||
18052e1cb: 0f 48 f3 cmovs %ebx,%esi
|
||||
18052e1ce: 89 77 08 mov %esi,0x8(%rdi)
|
||||
18052e1d1: 85 f6 test %esi,%esi
|
||||
18052e1d3: 74 2f je 0x18052e204
|
||||
18052e1d5: 8d 0c b5 00 00 00 00 lea 0x0(,%rsi,4),%ecx
|
||||
18052e1dc: e8 9f 2e ad ff call 0x180001080
|
||||
18052e1e1: 48 89 07 mov %rax,(%rdi)
|
||||
18052e1e4: 39 5f 08 cmp %ebx,0x8(%rdi)
|
||||
18052e1e7: 7e 1b jle 0x18052e204
|
||||
18052e1e9: 48 8b cb mov %rbx,%rcx
|
||||
18052e1ec: 0f 1f 40 00 nopl 0x0(%rax)
|
||||
18052e1f0: 48 8b 07 mov (%rdi),%rax
|
||||
18052e1f3: 48 8d 49 04 lea 0x4(%rcx),%rcx
|
||||
18052e1f7: ff c3 inc %ebx
|
||||
18052e1f9: f3 0f 11 74 01 fc movss %xmm6,-0x4(%rcx,%rax,1)
|
||||
18052e1ff: 3b 5f 08 cmp 0x8(%rdi),%ebx
|
||||
18052e202: 7c ec jl 0x18052e1f0
|
||||
18052e204: 48 8b 5c 24 40 mov 0x40(%rsp),%rbx
|
||||
18052e209: 48 8b 74 24 48 mov 0x48(%rsp),%rsi
|
||||
18052e20e: 0f 28 74 24 20 movaps 0x20(%rsp),%xmm6
|
||||
18052e213: 48 83 c4 30 add $0x30,%rsp
|
||||
18052e217: 5f pop %rdi
|
||||
18052e218: c3 ret
|
||||
18052e219: cc int3
|
||||
18052e21a: cc int3
|
||||
18052e21b: cc int3
|
||||
18052e21c: cc int3
|
||||
18052e21d: cc int3
|
||||
18052e21e: cc int3
|
||||
18052e21f: cc int3
|
||||
18052e220: 40 53 rex push %rbx
|
||||
18052e222: 48 83 ec 20 sub $0x20,%rsp
|
||||
18052e226: 83 79 08 00 cmpl $0x0,0x8(%rcx)
|
||||
18052e22a: 48 8b d9 mov %rcx,%rbx
|
||||
18052e22d: 7e 1b jle 0x18052e24a
|
||||
18052e22f: 48 8b 09 mov (%rcx),%rcx
|
||||
18052e232: 48 85 c9 test %rcx,%rcx
|
||||
18052e235: 74 05 je 0x18052e23c
|
||||
18052e237: e8 84 2e ad ff call 0x1800010c0
|
||||
18052e23c: 33 c0 xor %eax,%eax
|
||||
18052e23e: 48 89 03 mov %rax,(%rbx)
|
||||
18052e241: 89 43 08 mov %eax,0x8(%rbx)
|
||||
18052e244: 48 83 c4 20 add $0x20,%rsp
|
||||
18052e248: 5b pop %rbx
|
||||
18052e249: c3 ret
|
||||
18052e24a: 33 c0 xor %eax,%eax
|
||||
18052e24c: 48 89 01 mov %rax,(%rcx)
|
||||
18052e24f: 89 41 08 mov %eax,0x8(%rcx)
|
||||
18052e252: 48 83 c4 20 add $0x20,%rsp
|
||||
18052e256: 5b pop %rbx
|
||||
18052e257: c3 ret
|
||||
18052e258: cc int3
|
||||
18052e259: cc int3
|
||||
18052e25a: cc int3
|
||||
18052e25b: cc int3
|
||||
18052e25c: cc int3
|
||||
18052e25d: cc int3
|
||||
18052e25e: cc int3
|
||||
18052e25f: cc int3
|
||||
@@ -0,0 +1,198 @@
|
||||
|
||||
/tmp/slice.bin: file format binary
|
||||
|
||||
|
||||
Disassembly of section .data:
|
||||
|
||||
0000000180534580 <.data>:
|
||||
180534580: 48 89 1f mov %rbx,(%rdi)
|
||||
180534583: 0f 48 f3 cmovs %ebx,%esi
|
||||
180534586: 89 77 08 mov %esi,0x8(%rdi)
|
||||
180534589: 85 f6 test %esi,%esi
|
||||
18053458b: 74 26 je 0x1805345b3
|
||||
18053458d: 8b ce mov %esi,%ecx
|
||||
18053458f: e8 ec ca ac ff call 0x180001080
|
||||
180534594: 48 89 07 mov %rax,(%rdi)
|
||||
180534597: 39 5f 08 cmp %ebx,0x8(%rdi)
|
||||
18053459a: 7e 17 jle 0x1805345b3
|
||||
18053459c: 48 8b cb mov %rbx,%rcx
|
||||
18053459f: 90 nop
|
||||
1805345a0: 48 8b 07 mov (%rdi),%rax
|
||||
1805345a3: 48 8d 49 01 lea 0x1(%rcx),%rcx
|
||||
1805345a7: ff c3 inc %ebx
|
||||
1805345a9: c6 44 01 ff 00 movb $0x0,-0x1(%rcx,%rax,1)
|
||||
1805345ae: 3b 5f 08 cmp 0x8(%rdi),%ebx
|
||||
1805345b1: 7c ed jl 0x1805345a0
|
||||
1805345b3: 48 8b 5c 24 30 mov 0x30(%rsp),%rbx
|
||||
1805345b8: 48 8b 74 24 38 mov 0x38(%rsp),%rsi
|
||||
1805345bd: 48 83 c4 20 add $0x20,%rsp
|
||||
1805345c1: 5f pop %rdi
|
||||
1805345c2: c3 ret
|
||||
1805345c3: cc int3
|
||||
1805345c4: cc int3
|
||||
1805345c5: cc int3
|
||||
1805345c6: cc int3
|
||||
1805345c7: cc int3
|
||||
1805345c8: cc int3
|
||||
1805345c9: cc int3
|
||||
1805345ca: cc int3
|
||||
1805345cb: cc int3
|
||||
1805345cc: cc int3
|
||||
1805345cd: cc int3
|
||||
1805345ce: cc int3
|
||||
1805345cf: cc int3
|
||||
1805345d0: 40 53 rex push %rbx
|
||||
1805345d2: 48 83 ec 40 sub $0x40,%rsp
|
||||
1805345d6: 48 c7 44 24 30 fe ff movq $0xfffffffffffffffe,0x30(%rsp)
|
||||
1805345dd: ff ff
|
||||
1805345df: 48 8b d9 mov %rcx,%rbx
|
||||
1805345e2: 48 8d 05 c7 ce f3 ff lea -0xc3139(%rip),%rax # 0x1804714b0
|
||||
1805345e9: 48 89 44 24 20 mov %rax,0x20(%rsp)
|
||||
1805345ee: 4c 8d 0d 8b 00 00 00 lea 0x8b(%rip),%r9 # 0x180534680
|
||||
1805345f5: ba 80 00 00 00 mov $0x80,%edx
|
||||
1805345fa: 44 8d 42 90 lea -0x70(%rdx),%r8d
|
||||
1805345fe: e8 01 d6 bf 00 call 0x181131c04
|
||||
180534603: 90 nop
|
||||
180534604: c7 83 00 08 00 00 08 movl $0x8,0x800(%rbx)
|
||||
18053460b: 00 00 00
|
||||
18053460e: 48 c7 83 04 08 00 00 movq $0x447a0000,0x804(%rbx)
|
||||
180534615: 00 00 7a 44
|
||||
180534619: c7 83 0c 08 00 00 f4 movl $0x3f34fdf4,0x80c(%rbx)
|
||||
180534620: fd 34 3f
|
||||
180534623: c6 83 10 08 00 00 00 movb $0x0,0x810(%rbx)
|
||||
18053462a: c7 83 14 08 00 00 01 movl $0x1,0x814(%rbx)
|
||||
180534631: 00 00 00
|
||||
180534634: 33 c0 xor %eax,%eax
|
||||
180534636: 48 89 83 18 08 00 00 mov %rax,0x818(%rbx)
|
||||
18053463d: 48 89 83 20 08 00 00 mov %rax,0x820(%rbx)
|
||||
180534644: 48 8b c3 mov %rbx,%rax
|
||||
180534647: 48 83 c4 40 add $0x40,%rsp
|
||||
18053464b: 5b pop %rbx
|
||||
18053464c: c3 ret
|
||||
18053464d: cc int3
|
||||
18053464e: cc int3
|
||||
18053464f: cc int3
|
||||
180534650: 48 83 ec 38 sub $0x38,%rsp
|
||||
180534654: 48 c7 44 24 20 fe ff movq $0xfffffffffffffffe,0x20(%rsp)
|
||||
18053465b: ff ff
|
||||
18053465d: 4c 8d 0d 4c ce f3 ff lea -0xc31b4(%rip),%r9 # 0x1804714b0
|
||||
180534664: ba 80 00 00 00 mov $0x80,%edx
|
||||
180534669: 44 8d 42 90 lea -0x70(%rdx),%r8d
|
||||
18053466d: e8 aa d0 bf 00 call 0x18113171c
|
||||
180534672: 90 nop
|
||||
180534673: 48 83 c4 38 add $0x38,%rsp
|
||||
180534677: c3 ret
|
||||
180534678: cc int3
|
||||
180534679: cc int3
|
||||
18053467a: cc int3
|
||||
18053467b: cc int3
|
||||
18053467c: cc int3
|
||||
18053467d: cc int3
|
||||
18053467e: cc int3
|
||||
18053467f: cc int3
|
||||
180534680: 48 83 ec 28 sub $0x28,%rsp
|
||||
180534684: e8 a7 00 00 00 call 0x180534730
|
||||
180534689: 4c 8b 19 mov (%rcx),%r11
|
||||
18053468c: 48 ba 00 00 00 00 00 movabs $0x3ff0000000000000,%rdx
|
||||
180534693: 00 f0 3f
|
||||
180534696: 49 89 13 mov %rdx,(%r11)
|
||||
180534699: 48 8b 41 08 mov 0x8(%rcx),%rax
|
||||
18053469d: 48 89 10 mov %rdx,(%rax)
|
||||
1805346a0: 48 8b c1 mov %rcx,%rax
|
||||
1805346a3: 48 83 c4 28 add $0x28,%rsp
|
||||
1805346a7: c3 ret
|
||||
1805346a8: cc int3
|
||||
1805346a9: cc int3
|
||||
1805346aa: cc int3
|
||||
1805346ab: cc int3
|
||||
1805346ac: cc int3
|
||||
1805346ad: cc int3
|
||||
1805346ae: cc int3
|
||||
1805346af: cc int3
|
||||
1805346b0: 48 89 5c 24 08 mov %rbx,0x8(%rsp)
|
||||
1805346b5: 48 89 74 24 10 mov %rsi,0x10(%rsp)
|
||||
1805346ba: 57 push %rdi
|
||||
1805346bb: 48 83 ec 20 sub $0x20,%rsp
|
||||
1805346bf: 48 8b d9 mov %rcx,%rbx
|
||||
1805346c2: 8b f2 mov %edx,%esi
|
||||
1805346c4: 48 83 c1 60 add $0x60,%rcx
|
||||
1805346c8: e8 a3 11 d7 00 call 0x1812a5870
|
||||
1805346cd: 48 8d 05 64 7f f7 01 lea 0x1f77f64(%rip),%rax # 0x1824ac638
|
||||
1805346d4: 48 89 03 mov %rax,(%rbx)
|
||||
1805346d7: 48 8b 4b 48 mov 0x48(%rbx),%rcx
|
||||
1805346db: c7 43 54 00 00 00 00 movl $0x0,0x54(%rbx)
|
||||
1805346e2: ff 15 c0 6b 67 01 call *0x1676bc0(%rip) # 0x181bab2a8
|
||||
1805346e8: 48 8b 7b 08 mov 0x8(%rbx),%rdi
|
||||
1805346ec: 48 85 ff test %rdi,%rdi
|
||||
1805346ef: 74 17 je 0x180534708
|
||||
1805346f1: 48 8b 4f 18 mov 0x18(%rdi),%rcx
|
||||
1805346f5: ff 15 ad 6b 67 01 call *0x1676bad(%rip) # 0x181bab2a8
|
||||
1805346fb: ba 28 01 00 00 mov $0x128,%edx
|
||||
180534700: 48 8b cf mov %rdi,%rcx
|
||||
180534703: e8 ec c9 bf 00 call 0x1811310f4
|
||||
180534708: 40 f6 c6 01 test $0x1,%sil
|
||||
18053470c: 74 0d je 0x18053471b
|
||||
18053470e: ba e0 00 00 00 mov $0xe0,%edx
|
||||
180534713: 48 8b cb mov %rbx,%rcx
|
||||
180534716: e8 d9 c9 bf 00 call 0x1811310f4
|
||||
18053471b: 48 8b 74 24 38 mov 0x38(%rsp),%rsi
|
||||
180534720: 48 8b c3 mov %rbx,%rax
|
||||
180534723: 48 8b 5c 24 30 mov 0x30(%rsp),%rbx
|
||||
180534728: 48 83 c4 20 add $0x20,%rsp
|
||||
18053472c: 5f pop %rdi
|
||||
18053472d: c3 ret
|
||||
18053472e: cc int3
|
||||
18053472f: cc int3
|
||||
180534730: 4c 8d 41 18 lea 0x18(%rcx),%r8
|
||||
180534734: c7 41 10 03 00 00 00 movl $0x3,0x10(%rcx)
|
||||
18053473b: 49 8b c0 mov %r8,%rax
|
||||
18053473e: 4c 89 01 mov %r8,(%rcx)
|
||||
180534741: 0f 57 c9 xorps %xmm1,%xmm1
|
||||
180534744: c6 41 78 01 movb $0x1,0x78(%rcx)
|
||||
180534748: 48 83 c0 10 add $0x10,%rax
|
||||
18053474c: f2 0f 11 4c 24 08 movsd %xmm1,0x8(%rsp)
|
||||
180534752: f2 0f 10 44 24 08 movsd 0x8(%rsp),%xmm0
|
||||
180534758: 48 8d 51 30 lea 0x30(%rcx),%rdx
|
||||
18053475c: 48 89 51 08 mov %rdx,0x8(%rcx)
|
||||
180534760: 66 0f c6 c0 00 shufpd $0x0,%xmm0,%xmm0
|
||||
180534765: 41 f6 c0 0f test $0xf,%r8b
|
||||
180534769: 75 06 jne 0x180534771
|
||||
18053476b: 41 0f 11 00 movups %xmm0,(%r8)
|
||||
18053476f: eb 0f jmp 0x180534780
|
||||
180534771: 41 0f 11 00 movups %xmm0,(%r8)
|
||||
180534775: 66 66 66 0f 1f 84 00 data16 data16 nopw 0x0(%rax,%rax,1)
|
||||
18053477c: 00 00 00 00
|
||||
180534780: 45 33 c9 xor %r9d,%r9d
|
||||
180534783: f2 0f 11 4c 24 08 movsd %xmm1,0x8(%rsp)
|
||||
180534789: f2 0f 10 44 24 08 movsd 0x8(%rsp),%xmm0
|
||||
18053478f: 4c 89 08 mov %r9,(%rax)
|
||||
180534792: 48 8b c2 mov %rdx,%rax
|
||||
180534795: 48 83 c0 10 add $0x10,%rax
|
||||
180534799: 66 0f c6 c0 00 shufpd $0x0,%xmm0,%xmm0
|
||||
18053479e: f6 c2 0f test $0xf,%dl
|
||||
1805347a1: 75 05 jne 0x1805347a8
|
||||
1805347a3: 0f 11 02 movups %xmm0,(%rdx)
|
||||
1805347a6: eb 08 jmp 0x1805347b0
|
||||
1805347a8: 0f 11 02 movups %xmm0,(%rdx)
|
||||
1805347ab: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
|
||||
1805347b0: 4c 89 08 mov %r9,(%rax)
|
||||
1805347b3: 49 ba 00 00 00 00 00 movabs $0x3ff0000000000000,%r10
|
||||
1805347ba: 00 f0 3f
|
||||
1805347bd: 4d 89 10 mov %r10,(%r8)
|
||||
1805347c0: 4c 8d 41 48 lea 0x48(%rcx),%r8
|
||||
1805347c4: 49 8b c0 mov %r8,%rax
|
||||
1805347c7: f2 0f 11 4c 24 08 movsd %xmm1,0x8(%rsp)
|
||||
1805347cd: f2 0f 10 44 24 08 movsd 0x8(%rsp),%xmm0
|
||||
1805347d3: 48 83 c0 10 add $0x10,%rax
|
||||
1805347d7: 4c 89 12 mov %r10,(%rdx)
|
||||
1805347da: 66 0f c6 c0 00 shufpd $0x0,%xmm0,%xmm0
|
||||
1805347df: 41 f6 c0 0f test $0xf,%r8b
|
||||
1805347e3: 75 06 jne 0x1805347eb
|
||||
1805347e5: 41 0f 11 00 movups %xmm0,(%r8)
|
||||
1805347e9: eb 05 jmp 0x1805347f0
|
||||
1805347eb: 41 0f 11 00 movups %xmm0,(%r8)
|
||||
1805347ef: 90 nop
|
||||
1805347f0: 48 8d 51 60 lea 0x60(%rcx),%rdx
|
||||
1805347f4: 4c 89 08 mov %r9,(%rax)
|
||||
1805347f7: 48 8b c2 mov %rdx,%rax
|
||||
1805347fa: f2 0f 11 4c 24 08 movsd %xmm1,0x8(%rsp)
|
||||
@@ -0,0 +1,235 @@
|
||||
|
||||
/tmp/slice.bin: file format binary
|
||||
|
||||
|
||||
Disassembly of section .data:
|
||||
|
||||
0000000180b0c3a0 <.data>:
|
||||
180b0c3a0: 00 80 7d 07 ff c9 add %al,-0x3600f883(%rax)
|
||||
180b0c3a6: 83 c9 fe or $0xfffffffe,%ecx
|
||||
180b0c3a9: ff c1 inc %ecx
|
||||
180b0c3ab: 85 c9 test %ecx,%ecx
|
||||
180b0c3ad: 75 b2 jne 0x180b0c361
|
||||
180b0c3af: ff 54 24 60 call *0x60(%rsp)
|
||||
180b0c3b3: 48 83 f8 01 cmp $0x1,%rax
|
||||
180b0c3b7: be 00 00 00 00 mov $0x0,%esi
|
||||
180b0c3bc: 76 2e jbe 0x180b0c3ec
|
||||
180b0c3be: 48 8d 84 24 c8 00 00 lea 0xc8(%rsp),%rax
|
||||
180b0c3c5: 00
|
||||
180b0c3c6: 48 b9 cc cc cc cc cc movabs $0xcccccccccccccccc,%rcx
|
||||
180b0c3cd: cc cc cc
|
||||
180b0c3d0: 48 39 08 cmp %rcx,(%rax)
|
||||
180b0c3d3: 74 17 je 0x180b0c3ec
|
||||
180b0c3d5: 66 66 66 0f 1f 84 00 data16 data16 nopw 0x0(%rax,%rax,1)
|
||||
180b0c3dc: 00 00 00 00
|
||||
180b0c3e0: 48 89 30 mov %rsi,(%rax)
|
||||
180b0c3e3: 48 8d 40 40 lea 0x40(%rax),%rax
|
||||
180b0c3e7: 48 39 08 cmp %rcx,(%rax)
|
||||
180b0c3ea: 75 f4 jne 0x180b0c3e0
|
||||
180b0c3ec: 48 8d b4 24 c8 00 00 lea 0xc8(%rsp),%rsi
|
||||
180b0c3f3: 00
|
||||
180b0c3f4: eb 03 jmp 0x180b0c3f9
|
||||
180b0c3f6: 4c 8b ca mov %rdx,%r9
|
||||
180b0c3f9: 41 53 push %r11
|
||||
180b0c3fb: 41 56 push %r14
|
||||
180b0c3fd: 4c 8d 1d 78 fa ff ff lea -0x588(%rip),%r11 # 0x180b0be7c
|
||||
180b0c404: 4d 8b f3 mov %r11,%r14
|
||||
180b0c407: 49 81 c6 ae 06 00 00 add $0x6ae,%r14
|
||||
180b0c40e: 48 8d 64 24 f0 lea -0x10(%rsp),%rsp
|
||||
180b0c413: 4d 03 cf add %r15,%r9
|
||||
180b0c416: 4d 85 e0 test %r12,%r8
|
||||
180b0c419: 49 3b d0 cmp %r8,%rdx
|
||||
180b0c41c: 4d 2b cf sub %r15,%r9
|
||||
180b0c41f: 4c 89 74 24 08 mov %r14,0x8(%rsp)
|
||||
180b0c424: 48 f7 d2 not %rdx
|
||||
180b0c427: 48 8d 52 01 lea 0x1(%rdx),%rdx
|
||||
180b0c42b: 4c 3b e8 cmp %rax,%r13
|
||||
180b0c42e: 4d 85 cf test %r9,%r15
|
||||
180b0c431: 48 f7 d2 not %rdx
|
||||
180b0c434: 48 8d 52 01 lea 0x1(%rdx),%rdx
|
||||
180b0c438: 48 83 ec f8 sub $0xfffffffffffffff8,%rsp
|
||||
180b0c43c: 49 c7 c6 83 1f 00 00 mov $0x1f83,%r14
|
||||
180b0c443: 4d 03 f3 add %r11,%r14
|
||||
180b0c446: 41 56 push %r14
|
||||
180b0c448: 49 c7 c6 3c 06 00 00 mov $0x63c,%r14
|
||||
180b0c44f: 4d 03 f3 add %r11,%r14
|
||||
180b0c452: 41 56 push %r14
|
||||
180b0c454: 49 c7 c6 49 cc 01 00 mov $0x1cc49,%r14
|
||||
180b0c45b: 4d 03 f3 add %r11,%r14
|
||||
180b0c45e: 48 83 c4 e8 add $0xffffffffffffffe8,%rsp
|
||||
180b0c462: 49 81 c4 8e ee 39 13 add $0x1339ee8e,%r12
|
||||
180b0c469: 48 a9 1d 6a 9f 2f test $0x2f9f6a1d,%rax
|
||||
180b0c46f: 49 f7 c2 89 fe 1a 73 test $0x731afe89,%r10
|
||||
180b0c476: 49 81 ec 8e ee 39 13 sub $0x1339ee8e,%r12
|
||||
180b0c47d: 4c 89 74 24 10 mov %r14,0x10(%rsp)
|
||||
180b0c482: 49 81 e9 b1 fe 6e 2c sub $0x2c6efeb1,%r9
|
||||
180b0c489: 49 3b c1 cmp %r9,%rax
|
||||
180b0c48c: 49 f7 c4 a6 46 72 79 test $0x797246a6,%r12
|
||||
180b0c493: 49 81 c1 b1 fe 6e 2c add $0x2c6efeb1,%r9
|
||||
180b0c49a: 48 83 ec f0 sub $0xfffffffffffffff0,%rsp
|
||||
180b0c49e: 4d 85 ea test %r13,%r10
|
||||
180b0c4a1: 49 c7 c6 3c 06 00 00 mov $0x63c,%r14
|
||||
180b0c4a8: 4d 03 f3 add %r11,%r14
|
||||
180b0c4ab: 48 8d 64 24 f8 lea -0x8(%rsp),%rsp
|
||||
180b0c4b0: 4d 2b cd sub %r13,%r9
|
||||
180b0c4b3: eb 04 jmp 0x180b0c4b9
|
||||
180b0c4b5: 32 04 24 xor (%rsp),%al
|
||||
180b0c4b8: c3 ret
|
||||
180b0c4b9: 4d 03 cd add %r13,%r9
|
||||
180b0c4bc: 4c 89 34 24 mov %r14,(%rsp)
|
||||
180b0c4c0: 4d 8b f3 mov %r11,%r14
|
||||
180b0c4c3: 49 81 c6 83 1f 00 00 add $0x1f83,%r14
|
||||
180b0c4ca: 48 83 c4 e8 add $0xffffffffffffffe8,%rsp
|
||||
180b0c4ce: 4c 89 74 24 10 mov %r14,0x10(%rsp)
|
||||
180b0c4d3: 4d 2b d0 sub %r8,%r10
|
||||
180b0c4d6: eb 08 jmp 0x180b0c4e0
|
||||
180b0c4d8: 2b 04 24 sub (%rsp),%eax
|
||||
180b0c4db: 03 44 24 f8 add -0x8(%rsp),%eax
|
||||
180b0c4df: c3 ret
|
||||
180b0c4e0: 4d 03 d0 add %r8,%r10
|
||||
180b0c4e3: 48 83 c4 10 add $0x10,%rsp
|
||||
180b0c4e7: 4d 8b f3 mov %r11,%r14
|
||||
180b0c4ea: 49 81 c6 33 d0 ff ff add $0xffffffffffffd033,%r14
|
||||
180b0c4f1: 41 56 push %r14
|
||||
180b0c4f3: 49 c7 c6 5f 1f 00 00 mov $0x1f5f,%r14
|
||||
180b0c4fa: 4d 03 f3 add %r11,%r14
|
||||
180b0c4fd: 41 56 push %r14
|
||||
180b0c4ff: 4d 8b f3 mov %r11,%r14
|
||||
180b0c502: 49 81 c6 3c 06 00 00 add $0x63c,%r14
|
||||
180b0c509: 41 ff e6 jmp *%r14
|
||||
180b0c50c: 7c 16 jl 0x180b0c524
|
||||
180b0c50e: 4c 2b fa sub %rdx,%r15
|
||||
180b0c511: 48 81 fa bd da 55 14 cmp $0x1455dabd,%rdx
|
||||
180b0c518: 48 f7 c2 bf a9 c1 1f test $0x1fc1a9bf,%rdx
|
||||
180b0c51f: 4c 03 fa add %rdx,%r15
|
||||
180b0c522: eb 06 jmp 0x180b0c52a
|
||||
180b0c524: eb 04 jmp 0x180b0c52a
|
||||
180b0c526: 02 24 24 add (%rsp),%ah
|
||||
180b0c529: c3 ret
|
||||
180b0c52a: 48 81 ea da 69 00 00 sub $0x69da,%rdx
|
||||
180b0c531: 41 5e pop %r14
|
||||
180b0c533: 41 5b pop %r11
|
||||
180b0c535: 8b 06 mov (%rsi),%eax
|
||||
180b0c537: 8d 48 01 lea 0x1(%rax),%ecx
|
||||
180b0c53a: 0f af c8 imul %eax,%ecx
|
||||
180b0c53d: 81 e1 01 00 00 80 and $0x80000001,%ecx
|
||||
180b0c543: 7d 07 jge 0x180b0c54c
|
||||
180b0c545: ff c9 dec %ecx
|
||||
180b0c547: 83 c9 fe or $0xfffffffe,%ecx
|
||||
180b0c54a: ff c1 inc %ecx
|
||||
180b0c54c: 85 c9 test %ecx,%ecx
|
||||
180b0c54e: 0f 85 a0 fe ff ff jne 0x180b0c3f4
|
||||
180b0c554: 4d 3b f7 cmp %r15,%r14
|
||||
180b0c557: 0f 84 a3 01 00 00 je 0x180b0c700
|
||||
180b0c55d: 4b 8d 34 34 lea (%r12,%r14,1),%rsi
|
||||
180b0c561: 4d 03 fc add %r12,%r15
|
||||
180b0c564: 49 f7 df neg %r15
|
||||
180b0c567: 48 8d 9c 24 c8 00 00 lea 0xc8(%rsp),%rbx
|
||||
180b0c56e: 00
|
||||
180b0c56f: 4c 8d 25 4a 5a b1 01 lea 0x1b15a4a(%rip),%r12 # 0x182621fc0
|
||||
180b0c576: 66 66 0f 1f 84 00 00 data16 nopw 0x0(%rax,%rax,1)
|
||||
180b0c57d: 00 00 00
|
||||
180b0c580: 4c 8b f6 mov %rsi,%r14
|
||||
180b0c583: 48 85 ff test %rdi,%rdi
|
||||
180b0c586: 0f 84 a4 00 00 00 je 0x180b0c630
|
||||
180b0c58c: 48 8b 17 mov (%rdi),%rdx
|
||||
180b0c58f: 48 85 d2 test %rdx,%rdx
|
||||
180b0c592: 0f 88 98 00 00 00 js 0x180b0c630
|
||||
180b0c598: 48 b8 c0 1f 62 02 00 movabs $0x2621fc0,%rax
|
||||
180b0c59f: 00 00 00
|
||||
180b0c5a2: 48 89 44 24 48 mov %rax,0x48(%rsp)
|
||||
180b0c5a7: 48 8b 44 24 48 mov 0x48(%rsp),%rax
|
||||
180b0c5ac: 4d 8b c4 mov %r12,%r8
|
||||
180b0c5af: 4c 2b c0 sub %rax,%r8
|
||||
180b0c5b2: 49 8d 40 08 lea 0x8(%r8),%rax
|
||||
180b0c5b6: 48 03 c2 add %rdx,%rax
|
||||
180b0c5b9: 48 3b c6 cmp %rsi,%rax
|
||||
180b0c5bc: 77 0e ja 0x180b0c5cc
|
||||
180b0c5be: 48 83 c7 08 add $0x8,%rdi
|
||||
180b0c5c2: 48 8b 17 mov (%rdi),%rdx
|
||||
180b0c5c5: 48 85 d2 test %rdx,%rdx
|
||||
180b0c5c8: 79 e8 jns 0x180b0c5b2
|
||||
180b0c5ca: eb 64 jmp 0x180b0c630
|
||||
180b0c5cc: 48 85 d2 test %rdx,%rdx
|
||||
180b0c5cf: 78 5f js 0x180b0c630
|
||||
180b0c5d1: 49 8d 0c 10 lea (%r8,%rdx,1),%rcx
|
||||
180b0c5d5: 4c 8d 5e 04 lea 0x4(%rsi),%r11
|
||||
180b0c5d9: 49 3b cb cmp %r11,%rcx
|
||||
180b0c5dc: 73 52 jae 0x180b0c630
|
||||
180b0c5de: 4c 8b cf mov %rdi,%r9
|
||||
180b0c5e1: 4c 8d b4 24 88 00 00 lea 0x88(%rsp),%r14
|
||||
180b0c5e8: 00
|
||||
180b0c5e9: 8b 06 mov (%rsi),%eax
|
||||
180b0c5eb: 89 84 24 88 00 00 00 mov %eax,0x88(%rsp)
|
||||
180b0c5f2: 4d 8b d0 mov %r8,%r10
|
||||
180b0c5f5: 4c 2b d6 sub %rsi,%r10
|
||||
180b0c5f8: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
|
||||
180b0c5ff: 00
|
||||
180b0c600: 48 8b 09 mov (%rcx),%rcx
|
||||
180b0c603: 49 2b c8 sub %r8,%rcx
|
||||
180b0c606: 49 8d 04 12 lea (%r10,%rdx,1),%rax
|
||||
180b0c60a: 48 89 8c 04 88 00 00 mov %rcx,0x88(%rsp,%rax,1)
|
||||
180b0c611: 00
|
||||
180b0c612: 4d 8d 49 08 lea 0x8(%r9),%r9
|
||||
180b0c616: 49 8b 11 mov (%r9),%rdx
|
||||
180b0c619: 48 85 d2 test %rdx,%rdx
|
||||
180b0c61c: 78 12 js 0x180b0c630
|
||||
180b0c61e: 49 8d 0c 10 lea (%r8,%rdx,1),%rcx
|
||||
180b0c622: 49 3b cb cmp %r11,%rcx
|
||||
180b0c625: 72 d9 jb 0x180b0c600
|
||||
180b0c627: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
|
||||
180b0c62e: 00 00
|
||||
180b0c630: 4c 8d 4c 24 50 lea 0x50(%rsp),%r9
|
||||
180b0c635: 45 33 c0 xor %r8d,%r8d
|
||||
180b0c638: 49 8b d6 mov %r14,%rdx
|
||||
180b0c63b: b9 14 72 00 00 mov $0x7214,%ecx
|
||||
180b0c640: 39 c8 cmp %ecx,%eax
|
||||
180b0c642: 48 85 c0 test %rax,%rax
|
||||
180b0c645: 48 83 c4 c8 add $0xffffffffffffffc8,%rsp
|
||||
180b0c649: 49 81 c1 b2 c6 45 2b add $0x2b45c6b2,%r9
|
||||
180b0c650: 48 85 d0 test %rdx,%rax
|
||||
180b0c653: 49 81 e9 b2 c6 45 2b sub $0x2b45c6b2,%r9
|
||||
180b0c65a: 48 89 74 24 30 mov %rsi,0x30(%rsp)
|
||||
180b0c65f: 49 81 f5 ce cd f1 1a xor $0x1af1cdce,%r13
|
||||
180b0c666: 4d 85 ec test %r13,%r12
|
||||
180b0c669: 48 81 fa ff 37 12 61 cmp $0x611237ff,%rdx
|
||||
180b0c670: 49 81 f5 ce cd f1 1a xor $0x1af1cdce,%r13
|
||||
180b0c677: 48 83 ec d0 sub $0xffffffffffffffd0,%rsp
|
||||
180b0c67b: 48 8b f2 mov %rdx,%rsi
|
||||
180b0c67e: eb 01 jmp 0x180b0c681
|
||||
180b0c680: 35 8b 06 eb 01 xor $0x1eb068b,%eax
|
||||
180b0c685: c3 ret
|
||||
180b0c686: 41 89 01 mov %eax,(%r9)
|
||||
180b0c689: 48 83 c4 d8 add $0xffffffffffffffd8,%rsp
|
||||
180b0c68d: 4d 85 e0 test %r12,%r8
|
||||
180b0c690: 48 3d 0c 68 55 6c cmp $0x6c55680c,%rax
|
||||
180b0c696: 49 f7 c2 cf c3 7a 65 test $0x657ac3cf,%r10
|
||||
180b0c69d: 48 8b 74 24 28 mov 0x28(%rsp),%rsi
|
||||
180b0c6a2: f6 c1 c1 test $0xc1,%cl
|
||||
180b0c6a5: 74 04 je 0x180b0c6ab
|
||||
180b0c6a7: 2c 02 sub $0x2,%al
|
||||
180b0c6a9: 24 f5 and $0xf5,%al
|
||||
180b0c6ab: 48 83 c4 30 add $0x30,%rsp
|
||||
180b0c6af: 8b 0b mov (%rbx),%ecx
|
||||
180b0c6b1: 8d 41 01 lea 0x1(%rcx),%eax
|
||||
180b0c6b4: 0f af c1 imul %ecx,%eax
|
||||
180b0c6b7: 25 01 00 00 80 and $0x80000001,%eax
|
||||
180b0c6bc: 7d 07 jge 0x180b0c6c5
|
||||
180b0c6be: ff c8 dec %eax
|
||||
180b0c6c0: 83 c8 fe or $0xfffffffe,%eax
|
||||
180b0c6c3: ff c0 inc %eax
|
||||
180b0c6c5: 85 c0 test %eax,%eax
|
||||
180b0c6c7: 0f 85 63 ff ff ff jne 0x180b0c630
|
||||
180b0c6cd: 03 6c 24 50 add 0x50(%rsp),%ebp
|
||||
180b0c6d1: 41 0f af ed imul %r13d,%ebp
|
||||
180b0c6d5: 8b c5 mov %ebp,%eax
|
||||
180b0c6d7: c1 e8 10 shr $0x10,%eax
|
||||
180b0c6da: 33 e8 xor %eax,%ebp
|
||||
180b0c6dc: 48 83 c6 04 add $0x4,%rsi
|
||||
180b0c6e0: 49 8d 04 37 lea (%r15,%rsi,1),%rax
|
||||
180b0c6e4: 48 85 c0 test %rax,%rax
|
||||
180b0c6e7: 0f 85 93 fe ff ff jne 0x180b0c580
|
||||
180b0c6ed: 48 8b 5c 24 68 mov 0x68(%rsp),%rbx
|
||||
180b0c6f2: 48 8d b4 24 c8 00 00 lea 0xc8(%rsp),%rsi
|
||||
180b0c6f9: 00
|
||||
180b0c6fa: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
|
||||
@@ -0,0 +1,15 @@
|
||||
; imp_141400: VA 0x180141400-0x180141420 (32 bytes)
|
||||
|
||||
/tmp/opencode/dis/imp_141400.bin: file format binary
|
||||
|
||||
|
||||
Disassembly of section .data:
|
||||
|
||||
0000000000000000 <.data>:
|
||||
0: 48 8b 05 d1 6d 4d 02 mov 0x24d6dd1(%rip),%rax # 0x24d6dd8
|
||||
7: ff e0 jmp *%rax
|
||||
9: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
|
||||
10: 00
|
||||
11: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
|
||||
18: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
|
||||
1f: 00
|
||||
@@ -0,0 +1,15 @@
|
||||
; imp_141580: VA 0x180141580-0x1801415a0 (32 bytes)
|
||||
|
||||
/tmp/opencode/dis/imp_141580.bin: file format binary
|
||||
|
||||
|
||||
Disassembly of section .data:
|
||||
|
||||
0000000000000000 <.data>:
|
||||
0: 48 8b 05 41 6e 4d 02 mov 0x24d6e41(%rip),%rax # 0x24d6e48
|
||||
7: ff e0 jmp *%rax
|
||||
9: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
|
||||
10: 00
|
||||
11: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
|
||||
18: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
|
||||
1f: 00
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,594 @@
|
||||
; vt_542100
|
||||
|
||||
/tmp/slice.bin: file format binary
|
||||
|
||||
|
||||
Disassembly of section .data:
|
||||
|
||||
0000000180542100 <.data>:
|
||||
180542100: 40 3d 57 41 56 45 rex cmp $0x45564157,%eax
|
||||
180542106: 0f 85 6b 14 00 00 jne 0x180543577
|
||||
18054210c: 41 80 bd 84 00 00 00 cmpb $0x0,0x84(%r13)
|
||||
180542113: 00
|
||||
180542114: 74 6e je 0x180542184
|
||||
180542116: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
18054211a: 48 8b 01 mov (%rcx),%rax
|
||||
18054211d: ff 50 40 call *0x40(%rax)
|
||||
180542120: 3d 64 73 36 34 cmp $0x34367364,%eax
|
||||
180542125: 75 5d jne 0x180542184
|
||||
180542127: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
18054212b: 48 8b 01 mov (%rcx),%rax
|
||||
18054212e: ff 50 40 call *0x40(%rax)
|
||||
180542131: 83 f8 1c cmp $0x1c,%eax
|
||||
180542134: 0f 82 89 14 00 00 jb 0x1805435c3
|
||||
18054213a: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
18054213e: 8b d8 mov %eax,%ebx
|
||||
180542140: 48 8b 01 mov (%rcx),%rax
|
||||
180542143: ff 90 a8 00 00 00 call *0xa8(%rax)
|
||||
180542149: 8b fb mov %ebx,%edi
|
||||
18054214b: 83 e7 01 and $0x1,%edi
|
||||
18054214e: 48 03 c3 add %rbx,%rax
|
||||
180542151: 48 03 f8 add %rax,%rdi
|
||||
180542154: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
180542158: 48 8b 01 mov (%rcx),%rax
|
||||
18054215b: ff 50 50 call *0x50(%rax)
|
||||
18054215e: 4c 8d 3c 06 lea (%rsi,%rax,1),%r15
|
||||
180542162: 4c 89 7d 88 mov %r15,-0x78(%rbp)
|
||||
180542166: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
18054216a: 48 8b 01 mov (%rcx),%rax
|
||||
18054216d: ff 50 50 call *0x50(%rax)
|
||||
180542170: 49 89 45 78 mov %rax,0x78(%r13)
|
||||
180542174: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
180542178: 48 8b 01 mov (%rcx),%rax
|
||||
18054217b: 48 8b d7 mov %rdi,%rdx
|
||||
18054217e: ff 90 b0 00 00 00 call *0xb0(%rax)
|
||||
180542184: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
180542188: 48 8b 01 mov (%rcx),%rax
|
||||
18054218b: ff 90 a8 00 00 00 call *0xa8(%rax)
|
||||
180542191: 49 3b c7 cmp %r15,%rax
|
||||
180542194: 0f 83 dd 13 00 00 jae 0x180543577
|
||||
18054219a: 4c 8d 3d ff aa f6 01 lea 0x1f6aaff(%rip),%r15 # 0x1824acca0
|
||||
1805421a1: 48 8d 35 f0 aa f6 01 lea 0x1f6aaf0(%rip),%rsi # 0x1824acc98
|
||||
1805421a8: 4c 8d 25 20 ab f6 01 lea 0x1f6ab20(%rip),%r12 # 0x1824acccf
|
||||
1805421af: 4c 8d 35 12 ab f6 01 lea 0x1f6ab12(%rip),%r14 # 0x1824accc8
|
||||
1805421b6: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
1805421ba: 48 8b 01 mov (%rcx),%rax
|
||||
1805421bd: ff 50 10 call *0x10(%rax)
|
||||
1805421c0: 84 c0 test %al,%al
|
||||
1805421c2: 0f 85 7b 11 00 00 jne 0x180543343
|
||||
1805421c8: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
1805421cc: 48 8b 01 mov (%rcx),%rax
|
||||
1805421cf: ff 50 40 call *0x40(%rax)
|
||||
1805421d2: 8b d8 mov %eax,%ebx
|
||||
1805421d4: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
1805421d8: 48 8b 01 mov (%rcx),%rax
|
||||
1805421db: ff 50 40 call *0x40(%rax)
|
||||
1805421de: 44 8b e8 mov %eax,%r13d
|
||||
1805421e1: 48 8b 4c 24 20 mov 0x20(%rsp),%rcx
|
||||
1805421e6: 48 8b 49 50 mov 0x50(%rcx),%rcx
|
||||
1805421ea: 8b f8 mov %eax,%edi
|
||||
1805421ec: 48 8b 01 mov (%rcx),%rax
|
||||
1805421ef: ff 90 a8 00 00 00 call *0xa8(%rax)
|
||||
1805421f5: 41 8b cd mov %r13d,%ecx
|
||||
1805421f8: 83 e1 01 and $0x1,%ecx
|
||||
1805421fb: 49 03 c5 add %r13,%rax
|
||||
1805421fe: 48 03 c8 add %rax,%rcx
|
||||
180542201: 48 89 4c 24 28 mov %rcx,0x28(%rsp)
|
||||
180542206: 81 fb 66 6d 74 20 cmp $0x20746d66,%ebx
|
||||
18054220c: 0f 85 65 03 00 00 jne 0x180542577
|
||||
180542212: 48 8b 7c 24 20 mov 0x20(%rsp),%rdi
|
||||
180542217: 48 8b 4f 50 mov 0x50(%rdi),%rcx
|
||||
18054221b: 48 8b 01 mov (%rcx),%rax
|
||||
18054221e: ff 50 30 call *0x30(%rax)
|
||||
180542221: 0f b7 d8 movzwl %ax,%ebx
|
||||
180542224: 48 8b 4f 50 mov 0x50(%rdi),%rcx
|
||||
180542228: 48 8b 01 mov (%rcx),%rax
|
||||
18054222b: ff 50 30 call *0x30(%rax)
|
||||
18054222e: 0f bf c8 movswl %ax,%ecx
|
||||
180542231: 89 4f 20 mov %ecx,0x20(%rdi)
|
||||
180542234: 48 8b 4f 50 mov 0x50(%rdi),%rcx
|
||||
180542238: 48 8b 01 mov (%rcx),%rax
|
||||
18054223b: ff 50 40 call *0x40(%rax)
|
||||
18054223e: 66 0f 6e c0 movd %eax,%xmm0
|
||||
180542242: f3 0f e6 c0 cvtdq2pd %xmm0,%xmm0
|
||||
180542246: f2 0f 11 47 08 movsd %xmm0,0x8(%rdi)
|
||||
18054224b: 48 8b 4f 50 mov 0x50(%rdi),%rcx
|
||||
18054224f: 48 8b 01 mov (%rcx),%rax
|
||||
180542252: ff 50 40 call *0x40(%rax)
|
||||
180542255: 8b f8 mov %eax,%edi
|
||||
180542257: 48 8b 4c 24 20 mov 0x20(%rsp),%rcx
|
||||
18054225c: 48 8b 49 50 mov 0x50(%rcx),%rcx
|
||||
180542260: 48 8b 01 mov (%rcx),%rax
|
||||
180542263: ba 02 00 00 00 mov $0x2,%edx
|
||||
180542268: ff 90 b8 00 00 00 call *0xb8(%rax)
|
||||
18054226e: 48 8b 44 24 20 mov 0x20(%rsp),%rax
|
||||
180542273: 48 8b 48 50 mov 0x50(%rax),%rcx
|
||||
180542277: 48 8b 01 mov (%rcx),%rax
|
||||
18054227a: ff 50 30 call *0x30(%rax)
|
||||
18054227d: 0f bf c8 movswl %ax,%ecx
|
||||
180542280: 48 8b 44 24 20 mov 0x20(%rsp),%rax
|
||||
180542285: 89 48 10 mov %ecx,0x10(%rax)
|
||||
180542288: 83 f9 40 cmp $0x40,%ecx
|
||||
18054228b: 76 26 jbe 0x1805422b3
|
||||
18054228d: f2 0f 2c 48 08 cvttsd2si 0x8(%rax),%ecx
|
||||
180542292: 8b c7 mov %edi,%eax
|
||||
180542294: 99 cltd
|
||||
180542295: f7 f9 idiv %ecx
|
||||
180542297: 48 8b 7c 24 20 mov 0x20(%rsp),%rdi
|
||||
18054229c: 89 87 80 00 00 00 mov %eax,0x80(%rdi)
|
||||
1805422a2: 8d 04 c5 00 00 00 00 lea 0x0(,%rax,8),%eax
|
||||
1805422a9: 33 d2 xor %edx,%edx
|
||||
1805422ab: f7 77 20 divl 0x20(%rdi)
|
||||
1805422ae: 89 47 10 mov %eax,0x10(%rdi)
|
||||
1805422b1: eb 14 jmp 0x1805422c7
|
||||
1805422b3: 48 8b 7c 24 20 mov 0x20(%rsp),%rdi
|
||||
1805422b8: 8b 47 20 mov 0x20(%rdi),%eax
|
||||
1805422bb: 0f af c1 imul %ecx,%eax
|
||||
1805422be: c1 e8 03 shr $0x3,%eax
|
||||
1805422c1: 89 87 80 00 00 00 mov %eax,0x80(%rdi)
|
||||
1805422c7: 66 83 fb 03 cmp $0x3,%bx
|
||||
1805422cb: 75 0f jne 0x1805422dc
|
||||
1805422cd: 4c 8b 6c 24 20 mov 0x20(%rsp),%r13
|
||||
1805422d2: 41 c6 45 24 01 movb $0x1,0x24(%r13)
|
||||
1805422d7: e9 a3 11 00 00 jmp 0x18054347f
|
||||
1805422dc: b8 fe ff 00 00 mov $0xfffe,%eax
|
||||
1805422e1: 66 3b d8 cmp %ax,%bx
|
||||
1805422e4: 0f 85 3f 02 00 00 jne 0x180542529
|
||||
1805422ea: 41 83 fd 28 cmp $0x28,%r13d
|
||||
1805422ee: 73 15 jae 0x180542305
|
||||
1805422f0: 4c 8b 6c 24 20 mov 0x20(%rsp),%r13
|
||||
1805422f5: 41 c7 85 80 00 00 00 movl $0x0,0x80(%r13)
|
||||
1805422fc: 00 00 00 00
|
||||
180542300: e9 7a 11 00 00 jmp 0x18054347f
|
||||
180542305: 48 8b 4f 50 mov 0x50(%rdi),%rcx
|
||||
180542309: 48 8b 01 mov (%rcx),%rax
|
||||
18054230c: ba 04 00 00 00 mov $0x4,%edx
|
||||
180542311: ff 90 b8 00 00 00 call *0xb8(%rax)
|
||||
180542317: 48 8b 4f 50 mov 0x50(%rdi),%rcx
|
||||
18054231b: 48 8b 01 mov (%rcx),%rax
|
||||
18054231e: ff 50 40 call *0x40(%rax)
|
||||
180542321: 8b d8 mov %eax,%ebx
|
||||
180542323: 48 8d 15 46 ac f6 01 lea 0x1f6ac46(%rip),%rdx # 0x1824acf70
|
||||
18054232a: 48 8d 4d 98 lea -0x68(%rbp),%rcx
|
||||
18054232e: e8 ad a1 f5 ff call 0x18049c4e0
|
||||
180542333: 90 nop
|
||||
180542334: 8b d3 mov %ebx,%edx
|
||||
180542336: 48 8d 8d 00 02 00 00 lea 0x200(%rbp),%rcx
|
||||
18054233d: e8 ce 1a cf 00 call 0x181233e10
|
||||
180542342: 4c 8d 85 ff 01 00 00 lea 0x1ff(%rbp),%r8
|
||||
180542349: 4c 2b c0 sub %rax,%r8
|
||||
18054234c: 48 8b d0 mov %rax,%rdx
|
||||
18054234f: 48 8d 4d 90 lea -0x70(%rbp),%rcx
|
||||
180542353: e8 f8 2d f5 ff call 0x180495150
|
||||
180542358: 4c 8d 45 90 lea -0x70(%rbp),%r8
|
||||
18054235c: 48 8d 55 98 lea -0x68(%rbp),%rdx
|
||||
180542360: 48 8d 4f 28 lea 0x28(%rdi),%rcx
|
||||
180542364: e8 17 a5 ce 00 call 0x18122c880
|
||||
180542369: 48 8b 4d 90 mov -0x70(%rbp),%rcx
|
||||
18054236d: 48 83 c1 f0 add $0xfffffffffffffff0,%rcx
|
||||
180542371: 8b 01 mov (%rcx),%eax
|
||||
180542373: a9 00 00 00 30 test $0x30000000,%eax
|
||||
180542378: 75 16 jne 0x180542390
|
||||
18054237a: b8 ff ff ff ff mov $0xffffffff,%eax
|
||||
18054237f: f0 0f c1 01 lock xadd %eax,(%rcx)
|
||||
180542383: ff c8 dec %eax
|
||||
180542385: 83 f8 ff cmp $0xffffffff,%eax
|
||||
180542388: 75 06 jne 0x180542390
|
||||
18054238a: e8 65 ed be 00 call 0x1811310f4
|
||||
18054238f: 90 nop
|
||||
180542390: 48 8b 4d 98 mov -0x68(%rbp),%rcx
|
||||
180542394: 48 83 c1 f0 add $0xfffffffffffffff0,%rcx
|
||||
180542398: 8b 01 mov (%rcx),%eax
|
||||
18054239a: a9 00 00 00 30 test $0x30000000,%eax
|
||||
18054239f: 75 15 jne 0x1805423b6
|
||||
1805423a1: b8 ff ff ff ff mov $0xffffffff,%eax
|
||||
1805423a6: f0 0f c1 01 lock xadd %eax,(%rcx)
|
||||
1805423aa: ff c8 dec %eax
|
||||
1805423ac: 83 f8 ff cmp $0xffffffff,%eax
|
||||
1805423af: 75 05 jne 0x1805423b6
|
||||
1805423b1: e8 3e ed be 00 call 0x1811310f4
|
||||
1805423b6: 44 8b 47 20 mov 0x20(%rdi),%r8d
|
||||
1805423ba: 8b d3 mov %ebx,%edx
|
||||
1805423bc: 48 8d 8d 98 01 00 00 lea 0x198(%rbp),%rcx
|
||||
1805423c3: e8 68 17 00 00 call 0x180543b30
|
||||
1805423c8: 48 8b d0 mov %rax,%rdx
|
||||
1805423cb: 48 8b 8f 88 00 00 00 mov 0x88(%rdi),%rcx
|
||||
1805423d2: 48 89 8d 70 01 00 00 mov %rcx,0x170(%rbp)
|
||||
1805423d9: 48 8b 00 mov (%rax),%rax
|
||||
1805423dc: 48 89 87 88 00 00 00 mov %rax,0x88(%rdi)
|
||||
1805423e3: 48 89 0a mov %rcx,(%rdx)
|
||||
1805423e6: 0f 10 42 08 movups 0x8(%rdx),%xmm0
|
||||
1805423ea: 0f 11 87 90 00 00 00 movups %xmm0,0x90(%rdi)
|
||||
1805423f1: 48 8b 42 18 mov 0x18(%rdx),%rax
|
||||
1805423f5: 48 89 87 a0 00 00 00 mov %rax,0xa0(%rdi)
|
||||
1805423fc: 8b 42 20 mov 0x20(%rdx),%eax
|
||||
1805423ff: 89 87 a8 00 00 00 mov %eax,0xa8(%rdi)
|
||||
180542405: 0f b6 42 24 movzbl 0x24(%rdx),%eax
|
||||
180542409: 88 87 ac 00 00 00 mov %al,0xac(%rdi)
|
||||
18054240f: 48 8b 8d 98 01 00 00 mov 0x198(%rbp),%rcx
|
||||
180542416: ff 15 8c 8e 66 01 call *0x1668e8c(%rip) # 0x181bab2a8
|
||||
18054241c: 48 8b 4f 50 mov 0x50(%rdi),%rcx
|
||||
180542420: 48 8b 01 mov (%rcx),%rax
|
||||
180542423: ff 50 40 call *0x40(%rax)
|
||||
180542426: 89 85 88 01 00 00 mov %eax,0x188(%rbp)
|
||||
18054242c: 48 8b 4f 50 mov 0x50(%rdi),%rcx
|
||||
180542430: 48 8b 01 mov (%rcx),%rax
|
||||
180542433: ff 50 30 call *0x30(%rax)
|
||||
180542436: 66 89 85 8c 01 00 00 mov %ax,0x18c(%rbp)
|
||||
18054243d: 48 8b 4f 50 mov 0x50(%rdi),%rcx
|
||||
180542441: 48 8b 01 mov (%rcx),%rax
|
||||
180542444: ff 50 30 call *0x30(%rax)
|
||||
180542447: 66 89 85 8e 01 00 00 mov %ax,0x18e(%rbp)
|
||||
18054244e: bb 08 00 00 00 mov $0x8,%ebx
|
||||
180542453: 48 89 9d 28 01 00 00 mov %rbx,0x128(%rbp)
|
||||
18054245a: 4c 8b 6f 50 mov 0x50(%rdi),%r13
|
||||
18054245e: 33 ff xor %edi,%edi
|
||||
180542460: 41 bc 00 00 00 70 mov $0x70000000,%r12d
|
||||
180542466: 44 8b c3 mov %ebx,%r8d
|
||||
180542469: 49 3b dc cmp %r12,%rbx
|
||||
18054246c: 45 0f 47 c4 cmova %r12d,%r8d
|
||||
180542470: 48 8d 95 90 01 00 00 lea 0x190(%rbp),%rdx
|
||||
180542477: 48 03 d7 add %rdi,%rdx
|
||||
18054247a: 49 8b 45 00 mov 0x0(%r13),%rax
|
||||
18054247e: 49 8b cd mov %r13,%rcx
|
||||
180542481: ff 50 18 call *0x18(%rax)
|
||||
180542484: 83 f8 01 cmp $0x1,%eax
|
||||
180542487: 7c 0a jl 0x180542493
|
||||
180542489: 48 98 cltq
|
||||
18054248b: 48 03 f8 add %rax,%rdi
|
||||
18054248e: 48 2b d8 sub %rax,%rbx
|
||||
180542491: 75 d3 jne 0x180542466
|
||||
180542493: 48 89 9d 28 01 00 00 mov %rbx,0x128(%rbp)
|
||||
18054249a: 48 8b 8d 88 01 00 00 mov 0x188(%rbp),%rcx
|
||||
1805424a1: 48 8b c1 mov %rcx,%rax
|
||||
1805424a4: 48 8b 95 90 01 00 00 mov 0x190(%rbp),%rdx
|
||||
1805424ab: 48 2b 05 d6 96 e1 01 sub 0x1e196d6(%rip),%rax # 0x18235bb88
|
||||
1805424b2: 4c 8d 25 16 a8 f6 01 lea 0x1f6a816(%rip),%r12 # 0x1824acccf
|
||||
1805424b9: 75 0a jne 0x1805424c5
|
||||
1805424bb: 48 8b c2 mov %rdx,%rax
|
||||
1805424be: 48 2b 05 cb 96 e1 01 sub 0x1e196cb(%rip),%rax # 0x18235bb90
|
||||
1805424c5: 48 85 c0 test %rax,%rax
|
||||
1805424c8: 0f 94 c0 sete %al
|
||||
1805424cb: 84 c0 test %al,%al
|
||||
1805424cd: 74 0f je 0x1805424de
|
||||
1805424cf: 4c 8b 6c 24 20 mov 0x20(%rsp),%r13
|
||||
1805424d4: 41 c6 45 24 01 movb $0x1,0x24(%r13)
|
||||
1805424d9: e9 a1 0f 00 00 jmp 0x18054347f
|
||||
1805424de: 48 8b c1 mov %rcx,%rax
|
||||
1805424e1: 48 2b 05 38 96 e1 01 sub 0x1e19638(%rip),%rax # 0x18235bb20
|
||||
1805424e8: 75 0a jne 0x1805424f4
|
||||
1805424ea: 48 8b c2 mov %rdx,%rax
|
||||
1805424ed: 48 2b 05 34 96 e1 01 sub 0x1e19634(%rip),%rax # 0x18235bb28
|
||||
1805424f4: 48 85 c0 test %rax,%rax
|
||||
1805424f7: 0f 94 c0 sete %al
|
||||
1805424fa: 84 c0 test %al,%al
|
||||
1805424fc: 0f 94 c0 sete %al
|
||||
1805424ff: 84 c0 test %al,%al
|
||||
180542501: 0f 84 73 0f 00 00 je 0x18054347a
|
||||
180542507: 48 2b 0d 5a 96 e1 01 sub 0x1e1965a(%rip),%rcx # 0x18235bb68
|
||||
18054250e: 75 0a jne 0x18054251a
|
||||
180542510: 48 8b ca mov %rdx,%rcx
|
||||
180542513: 48 2b 0d 56 96 e1 01 sub 0x1e19656(%rip),%rcx # 0x18235bb70
|
||||
18054251a: 48 85 c9 test %rcx,%rcx
|
||||
18054251d: 0f 94 c0 sete %al
|
||||
180542520: 84 c0 test %al,%al
|
||||
180542522: 0f 94 c0 sete %al
|
||||
180542525: 84 c0 test %al,%al
|
||||
180542527: eb 2e jmp 0x180542557
|
||||
180542529: 0f b7 c3 movzwl %bx,%eax
|
||||
18054252c: b9 4f 67 00 00 mov $0x674f,%ecx
|
||||
180542531: 66 2b c1 sub %cx,%ax
|
||||
180542534: 66 83 f8 02 cmp $0x2,%ax
|
||||
180542538: 0f 86 6f 0f 00 00 jbe 0x1805434ad
|
||||
18054253e: 0f b7 c3 movzwl %bx,%eax
|
||||
180542541: b9 6f 67 00 00 mov $0x676f,%ecx
|
||||
180542546: 66 2b c1 sub %cx,%ax
|
||||
180542549: 66 83 f8 02 cmp $0x2,%ax
|
||||
18054254d: 0f 86 5a 0f 00 00 jbe 0x1805434ad
|
||||
180542553: 66 83 fb 01 cmp $0x1,%bx
|
||||
180542557: 48 8b 54 24 28 mov 0x28(%rsp),%rdx
|
||||
18054255c: 4c 8b 6c 24 20 mov 0x20(%rsp),%r13
|
||||
180542561: 0f 84 1d 0f 00 00 je 0x180543484
|
||||
180542567: 41 c7 85 80 00 00 00 movl $0x0,0x80(%r13)
|
||||
18054256e: 00 00 00 00
|
||||
180542572: e9 0d 0f 00 00 jmp 0x180543484
|
||||
180542577: 81 fb 64 61 74 61 cmp $0x61746164,%ebx
|
||||
18054257d: 75 7a jne 0x1805425f9
|
||||
18054257f: 4c 8b 6c 24 20 mov 0x20(%rsp),%r13
|
||||
180542584: 41 80 bd 84 00 00 00 cmpb $0x0,0x84(%r13)
|
||||
18054258b: 00
|
||||
18054258c: 74 2b je 0x1805425b9
|
||||
18054258e: 49 83 7d 78 00 cmpq $0x0,0x78(%r13)
|
||||
180542593: 7e 28 jle 0x1805425bd
|
||||
180542595: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
180542599: 49 8b 5d 78 mov 0x78(%r13),%rbx
|
||||
18054259d: 48 8b 01 mov (%rcx),%rax
|
||||
1805425a0: ff 90 a8 00 00 00 call *0xa8(%rax)
|
||||
1805425a6: 48 8b cb mov %rbx,%rcx
|
||||
1805425a9: 83 e1 01 and $0x1,%ecx
|
||||
1805425ac: 48 03 c3 add %rbx,%rax
|
||||
1805425af: 48 03 c8 add %rax,%rcx
|
||||
1805425b2: 48 89 4c 24 28 mov %rcx,0x28(%rsp)
|
||||
1805425b7: eb 04 jmp 0x1805425bd
|
||||
1805425b9: 49 89 7d 78 mov %rdi,0x78(%r13)
|
||||
1805425bd: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
1805425c1: 48 8b 01 mov (%rcx),%rax
|
||||
1805425c4: ff 90 a8 00 00 00 call *0xa8(%rax)
|
||||
1805425ca: 49 89 45 70 mov %rax,0x70(%r13)
|
||||
1805425ce: 49 63 85 80 00 00 00 movslq 0x80(%r13),%rax
|
||||
1805425d5: 85 c0 test %eax,%eax
|
||||
1805425d7: 7e 15 jle 0x1805425ee
|
||||
1805425d9: 48 8b c8 mov %rax,%rcx
|
||||
1805425dc: 49 8b 45 78 mov 0x78(%r13),%rax
|
||||
1805425e0: 48 99 cqto
|
||||
1805425e2: 48 f7 f9 idiv %rcx
|
||||
1805425e5: 49 89 45 18 mov %rax,0x18(%r13)
|
||||
1805425e9: e9 91 0e 00 00 jmp 0x18054347f
|
||||
1805425ee: 33 c0 xor %eax,%eax
|
||||
1805425f0: 49 89 45 18 mov %rax,0x18(%r13)
|
||||
1805425f4: e9 86 0e 00 00 jmp 0x18054347f
|
||||
1805425f9: 81 fb 62 65 78 74 cmp $0x74786562,%ebx
|
||||
1805425ff: 75 75 jne 0x180542676
|
||||
180542601: 48 8b 5c 24 20 mov 0x20(%rsp),%rbx
|
||||
180542606: 48 8b 4b 50 mov 0x50(%rbx),%rcx
|
||||
18054260a: 48 8b 01 mov (%rcx),%rax
|
||||
18054260d: ff 90 a8 00 00 00 call *0xa8(%rax)
|
||||
180542613: 48 89 43 60 mov %rax,0x60(%rbx)
|
||||
180542617: 48 89 7b 68 mov %rdi,0x68(%rbx)
|
||||
18054261b: 49 8d 5d 01 lea 0x1(%r13),%rbx
|
||||
18054261f: 33 c9 xor %ecx,%ecx
|
||||
180542621: ff 15 81 8c 66 01 call *0x1668c81(%rip) # 0x181bab2a8
|
||||
180542627: bf 5b 02 00 00 mov $0x25b,%edi
|
||||
18054262c: 48 3b df cmp %rdi,%rbx
|
||||
18054262f: 48 0f 42 df cmovb %rdi,%rbx
|
||||
180542633: ba 01 00 00 00 mov $0x1,%edx
|
||||
180542638: 48 8b cb mov %rbx,%rcx
|
||||
18054263b: ff 15 5f 8c 66 01 call *0x1668c5f(%rip) # 0x181bab2a0
|
||||
180542641: 48 8b d8 mov %rax,%rbx
|
||||
180542644: 48 89 85 78 01 00 00 mov %rax,0x178(%rbp)
|
||||
18054264b: 48 8b 44 24 20 mov 0x20(%rsp),%rax
|
||||
180542650: 48 8b 48 50 mov 0x50(%rax),%rcx
|
||||
180542654: 48 8b 01 mov (%rcx),%rax
|
||||
180542657: 45 8b c5 mov %r13d,%r8d
|
||||
18054265a: 48 8b d3 mov %rbx,%rdx
|
||||
18054265d: ff 50 18 call *0x18(%rax)
|
||||
180542660: 45 8b c5 mov %r13d,%r8d
|
||||
180542663: 48 8b 54 24 60 mov 0x60(%rsp),%rdx
|
||||
180542668: 48 8b cb mov %rbx,%rcx
|
||||
18054266b: e8 20 c7 ff ff call 0x18053ed90
|
||||
180542670: 90 nop
|
||||
180542671: e9 fb 0d 00 00 jmp 0x180543471
|
||||
180542676: 81 fb 73 6d 70 6c cmp $0x6c706d73,%ebx
|
||||
18054267c: 75 5a jne 0x1805426d8
|
||||
18054267e: 49 8d 5d 01 lea 0x1(%r13),%rbx
|
||||
180542682: 33 c9 xor %ecx,%ecx
|
||||
180542684: ff 15 1e 8c 66 01 call *0x1668c1e(%rip) # 0x181bab2a8
|
||||
18054268a: 48 83 fb 3c cmp $0x3c,%rbx
|
||||
18054268e: b8 3c 00 00 00 mov $0x3c,%eax
|
||||
180542693: 48 0f 42 d8 cmovb %rax,%rbx
|
||||
180542697: 8d 50 c5 lea -0x3b(%rax),%edx
|
||||
18054269a: 48 8b cb mov %rbx,%rcx
|
||||
18054269d: ff 15 fd 8b 66 01 call *0x1668bfd(%rip) # 0x181bab2a0
|
||||
1805426a3: 48 8b d8 mov %rax,%rbx
|
||||
1805426a6: 48 89 85 80 01 00 00 mov %rax,0x180(%rbp)
|
||||
1805426ad: 48 8b 44 24 20 mov 0x20(%rsp),%rax
|
||||
1805426b2: 48 8b 48 50 mov 0x50(%rax),%rcx
|
||||
1805426b6: 48 8b 01 mov (%rcx),%rax
|
||||
1805426b9: 45 8b c5 mov %r13d,%r8d
|
||||
1805426bc: 48 8b d3 mov %rbx,%rdx
|
||||
1805426bf: ff 50 18 call *0x18(%rax)
|
||||
1805426c2: 45 8b c5 mov %r13d,%r8d
|
||||
1805426c5: 48 8b 54 24 60 mov 0x60(%rsp),%rdx
|
||||
1805426ca: 48 8b cb mov %rbx,%rcx
|
||||
1805426cd: e8 5e d0 ff ff call 0x18053f730
|
||||
1805426d2: 90 nop
|
||||
1805426d3: e9 99 0d 00 00 jmp 0x180543471
|
||||
1805426d8: 81 fb 69 6e 73 74 cmp $0x74736e69,%ebx
|
||||
1805426de: 0f 84 b8 0c 00 00 je 0x18054339c
|
||||
1805426e4: 81 fb 49 4e 53 54 cmp $0x54534e49,%ebx
|
||||
1805426ea: 0f 84 ac 0c 00 00 je 0x18054339c
|
||||
1805426f0: 81 fb 63 75 65 20 cmp $0x20657563,%ebx
|
||||
1805426f6: 75 5a jne 0x180542752
|
||||
1805426f8: 49 8d 5d 01 lea 0x1(%r13),%rbx
|
||||
1805426fc: 33 c9 xor %ecx,%ecx
|
||||
1805426fe: ff 15 a4 8b 66 01 call *0x1668ba4(%rip) # 0x181bab2a8
|
||||
180542704: 48 83 fb 1c cmp $0x1c,%rbx
|
||||
180542708: b8 1c 00 00 00 mov $0x1c,%eax
|
||||
18054270d: 48 0f 42 d8 cmovb %rax,%rbx
|
||||
180542711: 8d 50 e5 lea -0x1b(%rax),%edx
|
||||
180542714: 48 8b cb mov %rbx,%rcx
|
||||
180542717: ff 15 83 8b 66 01 call *0x1668b83(%rip) # 0x181bab2a0
|
||||
18054271d: 48 8b d8 mov %rax,%rbx
|
||||
180542720: 48 89 85 50 01 00 00 mov %rax,0x150(%rbp)
|
||||
180542727: 48 8b 44 24 20 mov 0x20(%rsp),%rax
|
||||
18054272c: 48 8b 48 50 mov 0x50(%rax),%rcx
|
||||
180542730: 48 8b 01 mov (%rcx),%rax
|
||||
180542733: 45 8b c5 mov %r13d,%r8d
|
||||
180542736: 48 8b d3 mov %rbx,%rdx
|
||||
180542739: ff 50 18 call *0x18(%rax)
|
||||
18054273c: 45 8b c5 mov %r13d,%r8d
|
||||
18054273f: 48 8b 54 24 60 mov 0x60(%rsp),%rdx
|
||||
180542744: 48 8b cb mov %rbx,%rcx
|
||||
180542747: e8 e4 e0 ff ff call 0x180540830
|
||||
18054274c: 90 nop
|
||||
18054274d: e9 1f 0d 00 00 jmp 0x180543471
|
||||
180542752: 81 fb 61 78 6d 6c cmp $0x6c6d7861,%ebx
|
||||
180542758: 0f 85 a6 00 00 00 jne 0x180542804
|
||||
18054275e: 33 db xor %ebx,%ebx
|
||||
180542760: 48 89 5d 60 mov %rbx,0x60(%rbp)
|
||||
180542764: 48 89 5d 68 mov %rbx,0x68(%rbp)
|
||||
180542768: 4c 8b 6c 24 20 mov 0x20(%rsp),%r13
|
||||
18054276d: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
180542771: 48 8b 01 mov (%rcx),%rax
|
||||
180542774: 4c 8b c7 mov %rdi,%r8
|
||||
180542777: 48 8d 55 60 lea 0x60(%rbp),%rdx
|
||||
18054277b: ff 90 a0 00 00 00 call *0xa0(%rax)
|
||||
180542781: 48 8b 55 60 mov 0x60(%rbp),%rdx
|
||||
180542785: 48 85 d2 test %rdx,%rdx
|
||||
180542788: 74 28 je 0x1805427b2
|
||||
18054278a: 48 8b 45 68 mov 0x68(%rbp),%rax
|
||||
18054278e: 85 c0 test %eax,%eax
|
||||
180542790: 79 0c jns 0x18054279e
|
||||
180542792: 48 8d 4c 24 78 lea 0x78(%rsp),%rcx
|
||||
180542797: e8 44 a2 f5 ff call 0x18049c9e0
|
||||
18054279c: eb 20 jmp 0x1805427be
|
||||
18054279e: 7e 12 jle 0x1805427b2
|
||||
1805427a0: 4c 63 c0 movslq %eax,%r8
|
||||
1805427a3: 4c 03 c2 add %rdx,%r8
|
||||
1805427a6: 48 8d 4c 24 78 lea 0x78(%rsp),%rcx
|
||||
1805427ab: e8 f0 80 d0 00 call 0x18124a8a0
|
||||
1805427b0: eb 0c jmp 0x1805427be
|
||||
1805427b2: 48 8d 05 df 97 c9 01 lea 0x1c997df(%rip),%rax # 0x1821dbf98
|
||||
1805427b9: 48 89 44 24 78 mov %rax,0x78(%rsp)
|
||||
1805427be: 48 8d 54 24 78 lea 0x78(%rsp),%rdx
|
||||
1805427c3: 49 8d 4d 28 lea 0x28(%r13),%rcx
|
||||
1805427c7: e8 e4 b2 e2 00 call 0x18136dab0
|
||||
1805427cc: 90 nop
|
||||
1805427cd: 48 8b 4c 24 78 mov 0x78(%rsp),%rcx
|
||||
1805427d2: 48 83 c1 f0 add $0xfffffffffffffff0,%rcx
|
||||
1805427d6: 8b 01 mov (%rcx),%eax
|
||||
1805427d8: a9 00 00 00 30 test $0x30000000,%eax
|
||||
1805427dd: 75 16 jne 0x1805427f5
|
||||
1805427df: b8 ff ff ff ff mov $0xffffffff,%eax
|
||||
1805427e4: f0 0f c1 01 lock xadd %eax,(%rcx)
|
||||
1805427e8: ff c8 dec %eax
|
||||
1805427ea: 83 f8 ff cmp $0xffffffff,%eax
|
||||
1805427ed: 75 06 jne 0x1805427f5
|
||||
1805427ef: e8 00 e9 be 00 call 0x1811310f4
|
||||
1805427f4: 90 nop
|
||||
1805427f5: 48 8b 4d 60 mov 0x60(%rbp),%rcx
|
||||
1805427f9: ff 15 a9 8a 66 01 call *0x1668aa9(%rip) # 0x181bab2a8
|
||||
1805427ff: e9 7b 0c 00 00 jmp 0x18054347f
|
||||
180542804: 81 fb 4c 49 53 54 cmp $0x5453494c,%ebx
|
||||
18054280a: 0f 85 2a 0a 00 00 jne 0x18054323a
|
||||
180542810: 4c 8b 6c 24 20 mov 0x20(%rsp),%r13
|
||||
180542815: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
180542819: 48 8b 01 mov (%rcx),%rax
|
||||
18054281c: ff 50 40 call *0x40(%rax)
|
||||
18054281f: 3d 69 6e 66 6f cmp $0x6f666e69,%eax
|
||||
180542824: 0f 84 f9 09 00 00 je 0x180543223
|
||||
18054282a: 3d 49 4e 46 4f cmp $0x4f464e49,%eax
|
||||
18054282f: 0f 84 ee 09 00 00 je 0x180543223
|
||||
180542835: 3d 61 64 74 6c cmp $0x6c746461,%eax
|
||||
18054283a: 0f 85 3f 0c 00 00 jne 0x18054347f
|
||||
180542840: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
180542844: 48 8b 01 mov (%rcx),%rax
|
||||
180542847: ff 90 a8 00 00 00 call *0xa8(%rax)
|
||||
18054284d: 48 8b 54 24 28 mov 0x28(%rsp),%rdx
|
||||
180542852: 48 3b c2 cmp %rdx,%rax
|
||||
180542855: 0f 8d 29 0c 00 00 jge 0x180543484
|
||||
18054285b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
|
||||
180542860: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
180542864: 48 8b 01 mov (%rcx),%rax
|
||||
180542867: ff 50 40 call *0x40(%rax)
|
||||
18054286a: 8b f8 mov %eax,%edi
|
||||
18054286c: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
180542870: 48 8b 01 mov (%rcx),%rax
|
||||
180542873: ff 50 40 call *0x40(%rax)
|
||||
180542876: 8b d8 mov %eax,%ebx
|
||||
180542878: 89 44 24 68 mov %eax,0x68(%rsp)
|
||||
18054287c: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
180542880: 48 8b 01 mov (%rcx),%rax
|
||||
180542883: ff 90 a8 00 00 00 call *0xa8(%rax)
|
||||
180542889: 48 8b c8 mov %rax,%rcx
|
||||
18054288c: 8b c3 mov %ebx,%eax
|
||||
18054288e: 83 e0 01 and $0x1,%eax
|
||||
180542891: 03 c3 add %ebx,%eax
|
||||
180542893: 48 03 c8 add %rax,%rcx
|
||||
180542896: 48 89 8d f8 00 00 00 mov %rcx,0xf8(%rbp)
|
||||
18054289d: 81 ff 6c 61 62 6c cmp $0x6c62616c,%edi
|
||||
1805428a3: 0f 84 89 05 00 00 je 0x180542e32
|
||||
1805428a9: 81 ff 6e 6f 74 65 cmp $0x65746f6e,%edi
|
||||
1805428af: 0f 84 7d 05 00 00 je 0x180542e32
|
||||
1805428b5: 81 ff 6c 74 78 74 cmp $0x7478746c,%edi
|
||||
1805428bb: 0f 85 31 09 00 00 jne 0x1805431f2
|
||||
1805428c1: 8b 5c 24 58 mov 0x58(%rsp),%ebx
|
||||
1805428c5: 8b d3 mov %ebx,%edx
|
||||
1805428c7: 48 8d 8d 30 01 00 00 lea 0x130(%rbp),%rcx
|
||||
1805428ce: e8 8d 80 d0 00 call 0x18124a960
|
||||
1805428d3: 90 nop
|
||||
1805428d4: 4c 8b c0 mov %rax,%r8
|
||||
1805428d7: 48 8d 15 a2 a6 f6 01 lea 0x1f6a6a2(%rip),%rdx # 0x1824acf80
|
||||
1805428de: 48 8d 4c 24 38 lea 0x38(%rsp),%rcx
|
||||
1805428e3: e8 68 3c d0 00 call 0x181246550
|
||||
1805428e8: 90 nop
|
||||
1805428e9: ff c3 inc %ebx
|
||||
1805428eb: 89 5c 24 58 mov %ebx,0x58(%rsp)
|
||||
1805428ef: 48 8b 8d 30 01 00 00 mov 0x130(%rbp),%rcx
|
||||
1805428f6: 48 83 c1 f0 add $0xfffffffffffffff0,%rcx
|
||||
1805428fa: 8b 01 mov (%rcx),%eax
|
||||
1805428fc: a9 00 00 00 30 test $0x30000000,%eax
|
||||
180542901: 75 15 jne 0x180542918
|
||||
180542903: b8 ff ff ff ff mov $0xffffffff,%eax
|
||||
180542908: f0 0f c1 01 lock xadd %eax,(%rcx)
|
||||
18054290c: ff c8 dec %eax
|
||||
18054290e: 83 f8 ff cmp $0xffffffff,%eax
|
||||
180542911: 75 05 jne 0x180542918
|
||||
180542913: e8 dc e7 be 00 call 0x1811310f4
|
||||
180542918: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
18054291c: 48 8b 01 mov (%rcx),%rax
|
||||
18054291f: ff 50 40 call *0x40(%rax)
|
||||
180542922: 8b d8 mov %eax,%ebx
|
||||
180542924: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
180542928: 48 8b 01 mov (%rcx),%rax
|
||||
18054292b: ff 50 40 call *0x40(%rax)
|
||||
18054292e: 8b f8 mov %eax,%edi
|
||||
180542930: 49 8b 4d 50 mov 0x50(%r13),%rcx
|
||||
180542934: 48 8b 01 mov (%rcx),%rax
|
||||
180542937: ff 50 40 call *0x40(%rax)
|
||||
18054293a: 44 8b e8 mov %eax,%r13d
|
||||
18054293d: 48 8b 44 24 20 mov 0x20(%rsp),%rax
|
||||
180542942: 48 8b 48 50 mov 0x50(%rax),%rcx
|
||||
180542946: 48 8b 01 mov (%rcx),%rax
|
||||
180542949: ff 50 30 call *0x30(%rax)
|
||||
18054294c: 66 89 44 24 5c mov %ax,0x5c(%rsp)
|
||||
180542951: 48 8b 44 24 20 mov 0x20(%rsp),%rax
|
||||
180542956: 48 8b 48 50 mov 0x50(%rax),%rcx
|
||||
18054295a: 48 8b 01 mov (%rcx),%rax
|
||||
18054295d: ff 50 30 call *0x30(%rax)
|
||||
180542960: 66 89 44 24 50 mov %ax,0x50(%rsp)
|
||||
180542965: 48 8b 44 24 20 mov 0x20(%rsp),%rax
|
||||
18054296a: 48 8b 48 50 mov 0x50(%rax),%rcx
|
||||
18054296e: 48 8b 01 mov (%rcx),%rax
|
||||
180542971: ff 50 30 call *0x30(%rax)
|
||||
180542974: 66 89 44 24 52 mov %ax,0x52(%rsp)
|
||||
180542979: 48 8b 44 24 20 mov 0x20(%rsp),%rax
|
||||
18054297e: 48 8b 48 50 mov 0x50(%rax),%rcx
|
||||
180542982: 48 8b 01 mov (%rcx),%rax
|
||||
180542985: ff 50 30 call *0x30(%rax)
|
||||
180542988: 66 89 44 24 54 mov %ax,0x54(%rsp)
|
||||
18054298d: 8b 54 24 68 mov 0x68(%rsp),%edx
|
||||
180542991: 83 c2 ec add $0xffffffec,%edx
|
||||
180542994: 33 c0 xor %eax,%eax
|
||||
180542996: 48 89 85 80 00 00 00 mov %rax,0x80(%rbp)
|
||||
18054299d: 48 89 85 88 00 00 00 mov %rax,0x88(%rbp)
|
||||
1805429a4: 48 8b 44 24 20 mov 0x20(%rsp),%rax
|
||||
1805429a9: 48 8b 48 50 mov 0x50(%rax),%rcx
|
||||
1805429ad: 48 8b 01 mov (%rcx),%rax
|
||||
1805429b0: 4c 63 c2 movslq %edx,%r8
|
||||
1805429b3: 48 8d 95 80 00 00 00 lea 0x80(%rbp),%rdx
|
||||
1805429ba: ff 90 a0 00 00 00 call *0xa0(%rax)
|
||||
1805429c0: 8b d3 mov %ebx,%edx
|
||||
1805429c2: 48 8d 4d a8 lea -0x58(%rbp),%rcx
|
||||
1805429c6: e8 05 f6 cc 00 call 0x181211fd0
|
||||
1805429cb: 90 nop
|
||||
1805429cc: 48 8b 5c 24 38 mov 0x38(%rsp),%rbx
|
||||
1805429d1: 48 89 5d a0 mov %rbx,-0x60(%rbp)
|
||||
1805429d5: 8b 43 f0 mov -0x10(%rbx),%eax
|
||||
1805429d8: a9 00 00 00 30 test $0x30000000,%eax
|
||||
1805429dd: 75 0a jne 0x1805429e9
|
||||
1805429df: b8 01 00 00 00 mov $0x1,%eax
|
||||
1805429e4: f0 0f c1 43 f0 lock xadd %eax,-0x10(%rbx)
|
||||
1805429e9: 4c 8d 05 68 a2 f6 01 lea 0x1f6a268(%rip),%r8 # 0x1824acc58
|
||||
1805429f0: 48 8d 55 a0 lea -0x60(%rbp),%rdx
|
||||
1805429f4: 48 8d 8d a0 00 00 00 lea 0xa0(%rbp),%rcx
|
||||
1805429fb: e8 e0 3b d0 00 call 0x1812465e0
|
||||
180542a00: 4c 8d 45 a8 lea -0x58(%rbp),%r8
|
||||
180542a04: 48 8b d0 mov %rax,%rdx
|
||||
180542a07: 48 8b 4c 24 60 mov 0x60(%rsp),%rcx
|
||||
180542a0c: e8 6f 9e ce 00 call 0x18122c880
|
||||
180542a11: 48 8b 8d a0 00 00 00 mov 0xa0(%rbp),%rcx
|
||||
180542a18: 48 83 c1 f0 add $0xfffffffffffffff0,%rcx
|
||||
180542a1c: 8b 01 mov (%rcx),%eax
|
||||
180542a1e: a9 .byte 0xa9
|
||||
...
|
||||
@@ -0,0 +1,247 @@
|
||||
; vt_54b600
|
||||
|
||||
/tmp/slice.bin: file format binary
|
||||
|
||||
|
||||
Disassembly of section .data:
|
||||
|
||||
000000018054b600 <.data>:
|
||||
18054b600: 8b f8 mov %eax,%edi
|
||||
18054b602: 00 00 add %al,(%rax)
|
||||
18054b604: 00 48 85 add %cl,-0x7b(%rax)
|
||||
18054b607: c9 leave
|
||||
18054b608: 74 07 je 0x18054b611
|
||||
18054b60a: 48 8b 01 mov (%rcx),%rax
|
||||
18054b60d: ff 50 10 call *0x10(%rax)
|
||||
18054b610: 90 nop
|
||||
18054b611: 48 8b cb mov %rbx,%rcx
|
||||
18054b614: e8 07 f0 ff ff call 0x18054a620
|
||||
18054b619: 90 nop
|
||||
18054b61a: 40 f6 c7 01 test $0x1,%dil
|
||||
18054b61e: 74 0e je 0x18054b62e
|
||||
18054b620: ba 30 01 00 00 mov $0x130,%edx
|
||||
18054b625: 48 8b cb mov %rbx,%rcx
|
||||
18054b628: e8 c7 5a be 00 call 0x1811310f4
|
||||
18054b62d: 90 nop
|
||||
18054b62e: 48 8b c3 mov %rbx,%rax
|
||||
18054b631: 48 8b 5c 24 40 mov 0x40(%rsp),%rbx
|
||||
18054b636: 48 83 c4 30 add $0x30,%rsp
|
||||
18054b63a: 5f pop %rdi
|
||||
18054b63b: c3 ret
|
||||
18054b63c: cc int3
|
||||
18054b63d: cc int3
|
||||
18054b63e: cc int3
|
||||
18054b63f: cc int3
|
||||
18054b640: 40 53 rex push %rbx
|
||||
18054b642: 48 83 ec 20 sub $0x20,%rsp
|
||||
18054b646: 48 8b d9 mov %rcx,%rbx
|
||||
18054b649: 84 d2 test %dl,%dl
|
||||
18054b64b: 74 1e je 0x18054b66b
|
||||
18054b64d: b9 10 00 00 00 mov $0x10,%ecx
|
||||
18054b652: e8 89 60 be 00 call 0x1811316e0
|
||||
18054b657: 44 8b 43 2c mov 0x2c(%rbx),%r8d
|
||||
18054b65b: 48 8d 0d 56 27 f6 01 lea 0x1f62756(%rip),%rcx # 0x1824addb8
|
||||
18054b662: 48 89 08 mov %rcx,(%rax)
|
||||
18054b665: 44 89 40 0c mov %r8d,0xc(%rax)
|
||||
18054b669: eb 46 jmp 0x18054b6b1
|
||||
18054b66b: 8b 81 9c 00 00 00 mov 0x9c(%rcx),%eax
|
||||
18054b671: b9 10 00 00 00 mov $0x10,%ecx
|
||||
18054b676: 83 f8 04 cmp $0x4,%eax
|
||||
18054b679: 75 0e jne 0x18054b689
|
||||
18054b67b: e8 60 60 be 00 call 0x1811316e0
|
||||
18054b680: 48 8d 15 39 24 f6 01 lea 0x1f62439(%rip),%rdx # 0x1824adac0
|
||||
18054b687: eb 1f jmp 0x18054b6a8
|
||||
18054b689: 83 f8 03 cmp $0x3,%eax
|
||||
18054b68c: 75 0e jne 0x18054b69c
|
||||
18054b68e: e8 4d 60 be 00 call 0x1811316e0
|
||||
18054b693: 48 8d 15 0e 1f f6 01 lea 0x1f61f0e(%rip),%rdx # 0x1824ad5a8
|
||||
18054b69a: eb 0c jmp 0x18054b6a8
|
||||
18054b69c: e8 3f 60 be 00 call 0x1811316e0
|
||||
18054b6a1: 48 8d 15 30 1f f6 01 lea 0x1f61f30(%rip),%rdx # 0x1824ad5d8
|
||||
18054b6a8: 8b 4b 2c mov 0x2c(%rbx),%ecx
|
||||
18054b6ab: 89 48 0c mov %ecx,0xc(%rax)
|
||||
18054b6ae: 48 89 10 mov %rdx,(%rax)
|
||||
18054b6b1: c7 40 08 01 00 00 00 movl $0x1,0x8(%rax)
|
||||
18054b6b8: 48 8b 8b 00 01 00 00 mov 0x100(%rbx),%rcx
|
||||
18054b6bf: 48 89 83 00 01 00 00 mov %rax,0x100(%rbx)
|
||||
18054b6c6: 48 89 44 24 40 mov %rax,0x40(%rsp)
|
||||
18054b6cb: 48 85 c9 test %rcx,%rcx
|
||||
18054b6ce: 74 10 je 0x18054b6e0
|
||||
18054b6d0: 48 8b 01 mov (%rcx),%rax
|
||||
18054b6d3: ba 01 00 00 00 mov $0x1,%edx
|
||||
18054b6d8: 48 83 c4 20 add $0x20,%rsp
|
||||
18054b6dc: 5b pop %rbx
|
||||
18054b6dd: 48 ff 20 rex.W jmp *(%rax)
|
||||
18054b6e0: 48 83 c4 20 add $0x20,%rsp
|
||||
18054b6e4: 5b pop %rbx
|
||||
18054b6e5: c3 ret
|
||||
18054b6e6: cc int3
|
||||
18054b6e7: cc int3
|
||||
18054b6e8: cc int3
|
||||
18054b6e9: cc int3
|
||||
18054b6ea: cc int3
|
||||
18054b6eb: cc int3
|
||||
18054b6ec: cc int3
|
||||
18054b6ed: cc int3
|
||||
18054b6ee: cc int3
|
||||
18054b6ef: cc int3
|
||||
18054b6f0: 40 53 rex push %rbx
|
||||
18054b6f2: 48 83 ec 20 sub $0x20,%rsp
|
||||
18054b6f6: 83 79 28 00 cmpl $0x0,0x28(%rcx)
|
||||
18054b6fa: 48 8b d9 mov %rcx,%rbx
|
||||
18054b6fd: 7f 08 jg 0x18054b707
|
||||
18054b6ff: 33 c0 xor %eax,%eax
|
||||
18054b701: 48 83 c4 20 add $0x20,%rsp
|
||||
18054b705: 5b pop %rbx
|
||||
18054b706: c3 ret
|
||||
18054b707: 80 79 40 00 cmpb $0x0,0x40(%rcx)
|
||||
18054b70b: 75 2b jne 0x18054b738
|
||||
18054b70d: 48 8b 49 10 mov 0x10(%rcx),%rcx
|
||||
18054b711: 48 8d 54 24 30 lea 0x30(%rsp),%rdx
|
||||
18054b716: c7 44 24 30 00 00 00 movl $0x0,0x30(%rsp)
|
||||
18054b71d: 00
|
||||
18054b71e: 48 8b 01 mov (%rcx),%rax
|
||||
18054b721: ff 50 30 call *0x30(%rax)
|
||||
18054b724: 85 c0 test %eax,%eax
|
||||
18054b726: 78 10 js 0x18054b738
|
||||
18054b728: 8b 83 98 00 00 00 mov 0x98(%rbx),%eax
|
||||
18054b72e: 2b 44 24 30 sub 0x30(%rsp),%eax
|
||||
18054b732: 48 83 c4 20 add $0x20,%rsp
|
||||
18054b736: 5b pop %rbx
|
||||
18054b737: c3 ret
|
||||
18054b738: 8b 83 98 00 00 00 mov 0x98(%rbx),%eax
|
||||
18054b73e: 48 83 c4 20 add $0x20,%rsp
|
||||
18054b742: 5b pop %rbx
|
||||
18054b743: c3 ret
|
||||
18054b744: cc int3
|
||||
18054b745: cc int3
|
||||
18054b746: cc int3
|
||||
18054b747: cc int3
|
||||
18054b748: cc int3
|
||||
18054b749: cc int3
|
||||
18054b74a: cc int3
|
||||
18054b74b: cc int3
|
||||
18054b74c: cc int3
|
||||
18054b74d: cc int3
|
||||
18054b74e: cc int3
|
||||
18054b74f: cc int3
|
||||
18054b750: 48 8b c4 mov %rsp,%rax
|
||||
18054b753: 48 89 50 10 mov %rdx,0x10(%rax)
|
||||
18054b757: 55 push %rbp
|
||||
18054b758: 57 push %rdi
|
||||
18054b759: 48 83 ec 68 sub $0x68,%rsp
|
||||
18054b75d: 83 79 28 00 cmpl $0x0,0x28(%rcx)
|
||||
18054b761: 41 8b e9 mov %r9d,%ebp
|
||||
18054b764: 48 8b f9 mov %rcx,%rdi
|
||||
18054b767: 0f 8e b6 01 00 00 jle 0x18054b923
|
||||
18054b76d: 48 89 70 e8 mov %rsi,-0x18(%rax)
|
||||
18054b771: 33 f6 xor %esi,%esi
|
||||
18054b773: 4c 89 60 e0 mov %r12,-0x20(%rax)
|
||||
18054b777: 44 8b e6 mov %esi,%r12d
|
||||
18054b77a: 4c 89 68 d8 mov %r13,-0x28(%rax)
|
||||
18054b77e: 4d 63 e8 movslq %r8d,%r13
|
||||
18054b781: 45 85 c9 test %r9d,%r9d
|
||||
18054b784: 0f 8e 8a 01 00 00 jle 0x18054b914
|
||||
18054b78a: 48 89 58 18 mov %rbx,0x18(%rax)
|
||||
18054b78e: 4c 89 70 d0 mov %r14,-0x30(%rax)
|
||||
18054b792: 4c 89 78 c8 mov %r15,-0x38(%rax)
|
||||
18054b796: 4c 8b bc 24 a0 00 00 mov 0xa0(%rsp),%r15
|
||||
18054b79d: 00
|
||||
18054b79e: 66 90 xchg %ax,%ax
|
||||
18054b7a0: 80 7f 40 00 cmpb $0x0,0x40(%rdi)
|
||||
18054b7a4: 75 1d jne 0x18054b7c3
|
||||
18054b7a6: 4d 85 ff test %r15,%r15
|
||||
18054b7a9: 74 18 je 0x18054b7c3
|
||||
18054b7ab: 49 8b 4f 58 mov 0x58(%r15),%rcx
|
||||
18054b7af: 33 d2 xor %edx,%edx
|
||||
18054b7b1: ff 15 69 ed 65 01 call *0x165ed69(%rip) # 0x181baa520
|
||||
18054b7b7: 85 c0 test %eax,%eax
|
||||
18054b7b9: 75 08 jne 0x18054b7c3
|
||||
18054b7bb: 49 8b cf mov %r15,%rcx
|
||||
18054b7be: e8 7d fc ff ff call 0x18054b440
|
||||
18054b7c3: 83 7f 28 00 cmpl $0x0,0x28(%rdi)
|
||||
18054b7c7: 7f 04 jg 0x18054b7cd
|
||||
18054b7c9: 8b de mov %esi,%ebx
|
||||
18054b7cb: eb 38 jmp 0x18054b805
|
||||
18054b7cd: 80 7f 40 00 cmpb $0x0,0x40(%rdi)
|
||||
18054b7d1: 75 2c jne 0x18054b7ff
|
||||
18054b7d3: 48 8b 4f 10 mov 0x10(%rdi),%rcx
|
||||
18054b7d7: 48 8d 94 24 80 00 00 lea 0x80(%rsp),%rdx
|
||||
18054b7de: 00
|
||||
18054b7df: 89 b4 24 80 00 00 00 mov %esi,0x80(%rsp)
|
||||
18054b7e6: 48 8b 01 mov (%rcx),%rax
|
||||
18054b7e9: ff 50 30 call *0x30(%rax)
|
||||
18054b7ec: 85 c0 test %eax,%eax
|
||||
18054b7ee: 78 0f js 0x18054b7ff
|
||||
18054b7f0: 8b 9f 98 00 00 00 mov 0x98(%rdi),%ebx
|
||||
18054b7f6: 2b 9c 24 80 00 00 00 sub 0x80(%rsp),%ebx
|
||||
18054b7fd: eb 06 jmp 0x18054b805
|
||||
18054b7ff: 8b 9f 98 00 00 00 mov 0x98(%rdi),%ebx
|
||||
18054b805: 3b eb cmp %ebx,%ebp
|
||||
18054b807: 0f 4c dd cmovl %ebp,%ebx
|
||||
18054b80a: 85 db test %ebx,%ebx
|
||||
18054b80c: 75 32 jne 0x18054b840
|
||||
18054b80e: 48 8b 84 24 a8 00 00 mov 0xa8(%rsp),%rax
|
||||
18054b815: 00
|
||||
18054b816: 8b 80 b8 01 00 00 mov 0x1b8(%rax),%eax
|
||||
18054b81c: 85 c0 test %eax,%eax
|
||||
18054b81e: 0f 85 de 00 00 00 jne 0x18054b902
|
||||
18054b824: 48 8b 4f 58 mov 0x58(%rdi),%rcx
|
||||
18054b828: ba e8 03 00 00 mov $0x3e8,%edx
|
||||
18054b82d: ff 15 ed ec 65 01 call *0x165eced(%rip) # 0x181baa520
|
||||
18054b833: 85 c0 test %eax,%eax
|
||||
18054b835: 0f 85 c7 00 00 00 jne 0x18054b902
|
||||
18054b83b: e9 ba 00 00 00 jmp 0x18054b8fa
|
||||
18054b840: 80 7f 40 00 cmpb $0x0,0x40(%rdi)
|
||||
18054b844: 74 1a je 0x18054b860
|
||||
18054b846: 48 8b 4f 58 mov 0x58(%rdi),%rcx
|
||||
18054b84a: ba e8 03 00 00 mov $0x3e8,%edx
|
||||
18054b84f: ff 15 cb ec 65 01 call *0x165eccb(%rip) # 0x181baa520
|
||||
18054b855: 3d 02 01 00 00 cmp $0x102,%eax
|
||||
18054b85a: 0f 84 a2 00 00 00 je 0x18054b902
|
||||
18054b860: 48 8b 8f f8 00 00 00 mov 0xf8(%rdi),%rcx
|
||||
18054b867: 4c 8d 44 24 30 lea 0x30(%rsp),%r8
|
||||
18054b86c: 48 89 74 24 30 mov %rsi,0x30(%rsp)
|
||||
18054b871: 8b d3 mov %ebx,%edx
|
||||
18054b873: 48 8b 01 mov (%rcx),%rax
|
||||
18054b876: ff 50 18 call *0x18(%rax)
|
||||
18054b879: 85 c0 test %eax,%eax
|
||||
18054b87b: 78 78 js 0x18054b8f5
|
||||
18054b87d: 4d 85 ed test %r13,%r13
|
||||
18054b880: 7e 5f jle 0x18054b8e1
|
||||
18054b882: 4c 8b bc 24 88 00 00 mov 0x88(%rsp),%r15
|
||||
18054b889: 00
|
||||
18054b88a: 49 63 c4 movslq %r12d,%rax
|
||||
18054b88d: 4c 8d 34 85 00 00 00 lea 0x0(,%rax,4),%r14
|
||||
18054b894: 00
|
||||
18054b895: 66 66 66 0f 1f 84 00 data16 data16 nopw 0x0(%rax,%rax,1)
|
||||
18054b89c: 00 00 00 00
|
||||
18054b8a0: 48 8b 8f 00 01 00 00 mov 0x100(%rdi),%rcx
|
||||
18054b8a7: 48 8b 87 88 00 00 00 mov 0x88(%rdi),%rax
|
||||
18054b8ae: 4d 8b 0c f7 mov (%r15,%rsi,8),%r9
|
||||
18054b8b2: 48 8b 54 24 30 mov 0x30(%rsp),%rdx
|
||||
18054b8b7: 4d 03 ce add %r14,%r9
|
||||
18054b8ba: 4c 8b 11 mov (%rcx),%r10
|
||||
18054b8bd: 44 8b 04 b0 mov (%rax,%rsi,4),%r8d
|
||||
18054b8c1: 89 5c 24 28 mov %ebx,0x28(%rsp)
|
||||
18054b8c5: c7 44 24 20 00 00 00 movl $0x0,0x20(%rsp)
|
||||
18054b8cc: 00
|
||||
18054b8cd: 41 ff 52 08 call *0x8(%r10)
|
||||
18054b8d1: 48 ff c6 inc %rsi
|
||||
18054b8d4: 49 3b f5 cmp %r13,%rsi
|
||||
18054b8d7: 7c c7 jl 0x18054b8a0
|
||||
18054b8d9: 4c 8b bc 24 a0 00 00 mov 0xa0(%rsp),%r15
|
||||
18054b8e0: 00
|
||||
18054b8e1: 48 8b 8f f8 00 00 00 mov 0xf8(%rdi),%rcx
|
||||
18054b8e8: 45 33 c0 xor %r8d,%r8d
|
||||
18054b8eb: 8b d3 mov %ebx,%edx
|
||||
18054b8ed: 48 8b 01 mov (%rcx),%rax
|
||||
18054b8f0: ff 50 20 call *0x20(%rax)
|
||||
18054b8f3: 33 f6 xor %esi,%esi
|
||||
18054b8f5: 2b eb sub %ebx,%ebp
|
||||
18054b8f7: 44 03 e3 add %ebx,%r12d
|
||||
18054b8fa: 85 ed test %ebp,%ebp
|
||||
18054b8fc: 0f .byte 0xf
|
||||
18054b8fd: 8f (bad)
|
||||
18054b8fe: 9e sahf
|
||||
18054b8ff: fe .byte 0xfe
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -27,6 +27,11 @@
|
||||
> одновременно (res-тенция) → канон не меняем; следующий рычаг — контент-зависимость
|
||||
> (att/rel на флюктуациях, combine-консюмер). Инструментарий RT_DUMP_BIN/RT_DUMP_ALL.
|
||||
|
||||
> **2026-08-25 (24j–24kk2): ПРИМЕНЕНИЕ ДЕКОДИРОВАНО ДО ФОРМУЛ.**
|
||||
> mask=10^(−cut_D/20); cut_D=α·ln1p(lvl/β)+c (пер-контент константы, rms≤0.016);
|
||||
> слой STFT без синтез-окна; dual-корпус 0.193 (канон 3.264). ГЕЙТ = BIT EXACT.
|
||||
> Детали: NOTES_LEVEL 24j–24kk2, BLOCKMAP_529fe0 23b–24jj, NEXT_PROMPT.md.
|
||||
|
||||
- **Статический декомп DSP-ядра — закрыт (~95%)**: twin-резонатор, генератор case8,
|
||||
level-path (0x529fe0/0x563440/0x563a60), mask-apply (FUN_180529fe0 mono-path), IIR-трекеры,
|
||||
FFT-conv (0x535a70), main render-loop (FUN_18052e260) декодированы; `.dis` в `handoff/nls_dasm/`.
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env python3
|
||||
"""amseries.py — amplitude sweep via rendersnap: scratch vs input level.
|
||||
Gives ka = d(scr)/d(ln am) of the log-domain law."""
|
||||
import glob
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
CASES = [('t_-24', -24.0), ('t_-12', -12.0), ('t_0', 0.0), ('t_24', 24.0)]
|
||||
|
||||
|
||||
def steady(tag):
|
||||
fs = sorted(glob.glob('/tmp/opencode/rendersnap/phase*.npz'))
|
||||
for f in fs[::-1]:
|
||||
z = np.load(f)
|
||||
sc = z['0x540628']
|
||||
if sc[85] < -1e-4:
|
||||
return float(sc[85]), float(sc[85])
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
out = []
|
||||
for tag, db in CASES:
|
||||
rpp = f'/tmp/opencode/{tag}.rpp'
|
||||
subprocess.run(['timeout', '100', 'python3',
|
||||
'/home/m/re-tools/scripts/rendersnap.py', rpp],
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
st = steady(tag)
|
||||
if st:
|
||||
out.append((db, st))
|
||||
print(tag, db, 'scr43=%.4f scr171=%.4f' % st, flush=True)
|
||||
else:
|
||||
print(tag, 'NO STEADY', flush=True)
|
||||
if len(out) >= 2:
|
||||
(d1, s1), (d2, s2) = out[0], out[-1]
|
||||
ka = (s2[0] - s1[0]) / ((d2 - d1) * np.log(10) / 20)
|
||||
ka171 = (s2[1] - s1[1]) / ((d2 - d1) * np.log(10) / 20)
|
||||
print('ka(d scr/d ln am) @85: %.4f' % ka)
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python3
|
||||
"""campaign.py — one config-family cell: build rpp variants, clean-render refs,
|
||||
capture deepest scratch, extract tracts, fit softplus law.
|
||||
Usage: campaign.py <base_rpp> <band_freq> <band_q> <sens> <in_prefix> <n_drives> <out_prefix>
|
||||
Inputs must exist as <in_prefix><drive>_in.wav for drive in list.
|
||||
"""
|
||||
import subprocess, os, re, sys, time, glob
|
||||
import numpy as np
|
||||
|
||||
sys.path.insert(0,'/home/m/re-tools/scripts')
|
||||
|
||||
def sh(cmd):
|
||||
return subprocess.run(cmd,shell=True,capture_output=True,text=True).stdout
|
||||
|
||||
def find_host():
|
||||
import glob as g
|
||||
for p in g.glob('/proc/[0-9]*'):
|
||||
pid=int(os.path.basename(p))
|
||||
try:
|
||||
cmd=open('/proc/%d/cmdline'%pid,'rb').read().replace(b'\0',b' ').decode('utf8','replace')
|
||||
maps=open('/proc/%d/maps'%pid).read()
|
||||
except Exception: continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd: return pid
|
||||
return None
|
||||
|
||||
def main():
|
||||
base,freq,q,sens,pref,drives,outp=sys.argv[1],sys.argv[2],sys.argv[3],sys.argv[4],sys.argv[5],sys.argv[6].split(','),sys.argv[7]
|
||||
# build rpps
|
||||
for a in drives:
|
||||
src=open(base).read()
|
||||
src=src.replace('FILE "/home/m/soothe-bt/tone1k.wav"',f'FILE "{pref}{a}_in.wav"')
|
||||
src=re.sub(r'RENDER_FILE "[^"]*"',f'RENDER_FILE "{outp}/{a}_ref.wav"',src)
|
||||
tmp=f'{outp}/{a}_tmp.rpp'
|
||||
open(tmp,'w').write(src)
|
||||
out=sh(f'cd /home/m/re-tools && python3 patchparam.py {tmp} {outp}/{a}.rpp '
|
||||
f'"band1 freq"={freq} "band1 q"={q}')
|
||||
if 'patched' not in out and 'warning' not in out:
|
||||
print(f'drive {a}: patch issue: {out[:100]}')
|
||||
sh("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; "
|
||||
"rm -rf /run/user/1000/yabridge-soothe2_x64-*; sleep 1")
|
||||
# render refs cleanly
|
||||
for a in drives:
|
||||
wav=f'{outp}/{a}_ref.wav'
|
||||
if os.path.exists(wav): os.remove(wav)
|
||||
pr=subprocess.Popen(['/usr/bin/reaper','-nosplash','-ignoreerrors','-renderproject',f'{outp}/{a}.rpp'],
|
||||
stdout=subprocess.DEVNULL,stderr=subprocess.STDOUT)
|
||||
t0=time.time()
|
||||
while time.time()-t0<30 and pr.poll() is None:
|
||||
time.sleep(0.2)
|
||||
for _ in range(60):
|
||||
if pr.poll() is not None: break
|
||||
time.sleep(0.1)
|
||||
print(f'drive {a}: ref rc={pr.poll()} size={os.path.getsize(wav) if os.path.exists(wav) else 0}',flush=True)
|
||||
|
||||
if __name__=='__main__':
|
||||
main()
|
||||
@@ -0,0 +1,237 @@
|
||||
#!/usr/bin/env python3
|
||||
"""cascade_sim.py — структурный симулятор тракта маски soothe2 (float-путь).
|
||||
|
||||
Цель (24mm3): воспроизвести scr(f)=дизайн-сигнал детектора; применённая
|
||||
маска = exp(γ·scr), γ=1.760561 (точно), trk@688=exp(scr@628) бит-в-бит.
|
||||
|
||||
Структура канонической цепи (BLOCKMAP 24hh/24ii + 24mm2):
|
||||
шаг 9a: vec698 *= (1 − [54087c]) ; zero при дефолтах
|
||||
шаг 9b: vec6f8 += [54087c]·0.8 ; xmm10=0.8 @1824c3e28
|
||||
шаг 9c: bands_curve_i /= ... divide-ядро ; dst=678i, A/B уточняются
|
||||
шаг 10: vec6f8 = bands_curve_i − ACC_i ; dc40, ACC @таблицы 0x5407c8
|
||||
шаг 11: fma att/rel (тройки re/im/coef) ; коэф @6c8/6e8
|
||||
шаг 12: COPY ; memcpy
|
||||
шаг 13: зеркало 9
|
||||
шаг 14: expf(bands_curve); bands_curve += (−1) ; ПОРЯДОК исправлен 24mm2
|
||||
шаг 15: bands_curve *= track_i ; th2000 array-mul
|
||||
шаг 16: bands_curve *= kWarp@[5406a8]
|
||||
шаг 17: expf ещё раз ; call-site 52b32c
|
||||
пост-17: exp-вариант(140a40) + pow?(140b00)
|
||||
FIR-секция: кривая-float(140b30→1803831c0) + sincos-twiddle(140aa0)
|
||||
|
||||
ЯДРА (структурная фаза — математически точные numpy-эквиваленты;
|
||||
канонический C++ порт = инструкци-точная транскрипция, см. BLOCKMAP 24mm2):
|
||||
"""
|
||||
import numpy as np
|
||||
import glob
|
||||
import os
|
||||
|
||||
GAMMA = 1.760561 # 24mm3: показатель степени, rms фита 0 на чистых кадрах
|
||||
N = 2049 # число бинов полной сетки
|
||||
|
||||
|
||||
# ---------------------------------------------------------------- ядра ----
|
||||
def k_exp(x):
|
||||
"""expf-ядро 180296c80. Структурная фаза: np.exp.
|
||||
Каноническая формула (для C++ порта, FMA-точно):
|
||||
n = fma(log2e_hi=1.4427f, x, 12582912.0f); k = n - MAGIC
|
||||
r = (x - 0.693146f*k) - 1.42861e-06f*k
|
||||
p = (((0.00829172f*r+0.0418735f)*r+0.166674f)*r+0.499994f)*r+1)*r+1
|
||||
out = bits((k<<23) + bits(p)); guard |x|>87.3365 -> slow path
|
||||
"""
|
||||
return np.exp(x)
|
||||
|
||||
|
||||
def k_div(a, b):
|
||||
"""divide-ядро 1803a06a0: dst = B/A (~0.5 ulp, rcp+таблицы+полином).
|
||||
Структурная фаза: точное деление."""
|
||||
return b / a
|
||||
|
||||
|
||||
# ------------------------------------------------------------ данные -----
|
||||
def load_tract(path):
|
||||
"""tract_*.txt: k am res lvl_raw band_level prewarp w"""
|
||||
t = np.loadtxt(path)
|
||||
return {'am': t[:, 1], 'res': t[:, 2], 'lvl': t[:, 3]}
|
||||
|
||||
|
||||
def load_frame(npz):
|
||||
"""Слоты кадра rendersnap2 → dict[int, np.ndarray]."""
|
||||
d = np.load(npz)
|
||||
out = {}
|
||||
for k in d.keys():
|
||||
if k.startswith('0x'):
|
||||
out[int(k[2:], 16)] = d[k]
|
||||
return out, d['t_snap']
|
||||
|
||||
|
||||
def pick_clean_frame(ds_dir, min_bins=8):
|
||||
"""Отбор чистых стационарных кадров по фазам (24mm3):
|
||||
возвращает лучший на фазе γ* (~1.7606, маска применена)
|
||||
и лучший на фазе γ=1 (степень ещё не применена)."""
|
||||
classes = {'gamma': None, 'identity': None}
|
||||
for f in sorted(glob.glob(os.path.join(ds_dir, 'ph*.npz'))):
|
||||
try:
|
||||
S, ts = load_frame(f)
|
||||
except Exception:
|
||||
continue
|
||||
if not all(x in S for x in (0x540628, 0x540688, 0x540678)):
|
||||
continue
|
||||
s = S[0x540628][:1025].astype(np.float64)
|
||||
t = S[0x540688][:1025].astype(np.float64)
|
||||
c = S[0x540678][:1025].astype(np.float64)
|
||||
ok = (t > 1e-30) & (c > 1e-30) & np.isfinite(s)
|
||||
if ok.sum() < 50:
|
||||
continue
|
||||
lt = np.log(t[ok])
|
||||
lc = np.log(c[ok])
|
||||
sel = np.abs(lt) > 0.05
|
||||
if sel.sum() < min_bins:
|
||||
continue
|
||||
g = float(np.sum(lt[sel] * lc[sel]) / np.sum(lt[sel] ** 2))
|
||||
rms = float(np.sqrt(np.mean((lc[sel] - g * lt[sel]) ** 2)))
|
||||
depth = float(-lc.min())
|
||||
key = 'gamma' if abs(g - GAMMA) < 0.01 else \
|
||||
('identity' if abs(g - 1.0) < 1e-4 else None)
|
||||
if key is None or rms > 1e-4:
|
||||
continue
|
||||
cand = (depth, f, s, t, c, g, rms)
|
||||
if classes[key] is None or depth > classes[key][0]:
|
||||
classes[key] = cand
|
||||
return classes
|
||||
|
||||
|
||||
# ------------------------------------------------------- валидация -------
|
||||
def validate_scr(sim_scr, cap_scr, tol_db=0.05):
|
||||
"""rms в дБ между симулированным и захваченным scr."""
|
||||
m = np.abs(cap_scr) > 0.02
|
||||
err = (sim_scr[m] - cap_scr[m]) * (20 / np.log(10))
|
||||
return float(np.sqrt(np.mean(err ** 2))), int(m.sum())
|
||||
|
||||
|
||||
def win_periodic_hann(N):
|
||||
return 0.5 * (1.0 - np.cos(2.0 * np.pi * np.arange(N) / N))
|
||||
|
||||
|
||||
# ------------------------------------------------ FIR-цепь (24mm9) --------
|
||||
NFRAME = 4096 # n=[ctx+0x540534]
|
||||
NBINS_FIR = NFRAME // 2 + 1
|
||||
Q_EXP = 0.80 # скаляр аргумента EXP; источник в 1803831c0 (ОТКРЫТО)
|
||||
|
||||
|
||||
def winfreq_fall():
|
||||
"""WINfreq@[ctx+0x540658]: периодический Hann(4096), падающая половина."""
|
||||
return win_periodic_hann(NFRAME)[NFRAME // 2:]
|
||||
|
||||
|
||||
def fir_kernel(scr, q=Q_EXP):
|
||||
"""Полная FIR-цепь (BLOCKMAP 24mm9): min-phase кепстральный сэндвич.
|
||||
|
||||
scr(2049) → pack(re=scr,im=0) → FIR[n]=0 (Найквост)
|
||||
→ inv-RFFT → fold(y[1..2047]*=2.0 @1824c41e0; y[2049..4095]=0)
|
||||
→ fwd-RFFT → комплексная EXP (1803831c0, аргумент ×q)
|
||||
→ inv-RFFT → ×падающий Hann → ноль хвоста → fwd-RFFT
|
||||
→ FIR[0]=1, FIR[1]=0. Возвращает |F| (2049).
|
||||
"""
|
||||
h = np.asarray(scr, dtype=np.complex128).copy()
|
||||
h[-1] = 0.0
|
||||
y = np.fft.irfft(h, n=NFRAME)
|
||||
y[1:NFRAME // 2] *= 2.0
|
||||
y[NFRAME // 2 + 1:] = 0.0
|
||||
w = np.fft.irfft(np.exp(q * np.fft.rfft(y, n=NFRAME)), n=NFRAME)
|
||||
w[:NFRAME // 2] *= winfreq_fall()
|
||||
w[NFRAME // 2:] = 0.0
|
||||
F = np.abs(np.fft.rfft(w, n=NFRAME))
|
||||
F[0] = 1.0
|
||||
return F
|
||||
|
||||
|
||||
def mask_from_frame(S, q=Q_EXP):
|
||||
"""mask_sim из слотов кадра: cur ≈ trk · |F(scr)| (df0 complex-mul)."""
|
||||
scr = S[0x540628][:NBINS_FIR].astype(np.float64)
|
||||
trk = S[0x540688][:NBINS_FIR].astype(np.float64)
|
||||
return trk * fir_kernel(scr, q)
|
||||
|
||||
|
||||
def validate_mask_stage(ds, q=Q_EXP, cap=60):
|
||||
"""Валидация масочной ветви на чистых γ-кадрах (24mm9-протокол).
|
||||
|
||||
Отбор: |γ_fit−1.760561|<5e-4 и fit-rms<1e-5 (жёстче pick_clean_frame).
|
||||
Критерий: rms по ВСЕМ 2049 бинам < 0.05 дБ (структурная фаза).
|
||||
"""
|
||||
import glob
|
||||
rmss, gpred = [], []
|
||||
for f in sorted(glob.glob(os.path.join(ds, 'ph*.npz'))):
|
||||
try:
|
||||
d = np.load(f)
|
||||
except Exception:
|
||||
continue
|
||||
if '0x540628' not in d:
|
||||
continue
|
||||
scr = d['0x540628'][:NBINS_FIR].astype(np.float64)
|
||||
trk = d['0x540688'][:NBINS_FIR].astype(np.float64)
|
||||
cur = d['0x540678'][:NBINS_FIR].astype(np.float64)
|
||||
ok = (trk > 1e-30) & (cur > 1e-30) & np.isfinite(scr)
|
||||
if ok.sum() < 50:
|
||||
continue
|
||||
lt, lc = np.log(trk[ok]), np.log(cur[ok])
|
||||
sel = np.abs(lt) > 0.05
|
||||
if sel.sum() < 8:
|
||||
continue
|
||||
g = float(np.sum(lt[sel] * lc[sel]) / np.sum(lt[sel] ** 2))
|
||||
frms = float(np.sqrt(np.mean((lc[sel] - g * lt[sel]) ** 2)))
|
||||
if not (abs(g - GAMMA) < 5e-4 and frms < 1e-5):
|
||||
continue
|
||||
F = fir_kernel(scr, q)
|
||||
lf = np.log(F[sel])
|
||||
lt_s = np.log(trk[sel])
|
||||
sF = float(np.sum(lf * lt_s) / np.sum(lt_s ** 2))
|
||||
gpred.append(1.0 + sF)
|
||||
m = trk * F
|
||||
mm = (cur > 1e-12) & (m > 1e-12)
|
||||
e = (np.log(m[mm]) - np.log(cur[mm])) * 20 / np.log(10)
|
||||
rmss.append(float(np.sqrt(np.mean(e ** 2))))
|
||||
if len(rmss) >= cap:
|
||||
break
|
||||
if not rmss:
|
||||
print('нет ультрачистых кадров в', ds)
|
||||
return
|
||||
rmss = np.array(rmss)
|
||||
print('кадров=%d | rms медиана=%.4f дБ p90=%.4f max=%.4f | '
|
||||
'gamma_pred(1+s_F)=%.6f' %
|
||||
(len(rmss), np.median(rmss), np.percentile(rmss, 90), rmss.max(),
|
||||
float(np.median(gpred))))
|
||||
|
||||
|
||||
def main():
|
||||
import sys
|
||||
if len(sys.argv) > 1 and sys.argv[1] == '--mask':
|
||||
validate_mask_stage(sys.argv[2] if len(sys.argv) > 2
|
||||
else '/tmp/opencode/sc_multi4b')
|
||||
return
|
||||
ds = sys.argv[1] if len(sys.argv) > 1 else '/tmp/opencode/sc_multi6'
|
||||
tract = sys.argv[2] if len(sys.argv) > 2 else '/tmp/opencode/tract_multi6.txt'
|
||||
|
||||
classes = pick_clean_frame(ds)
|
||||
ph_g = classes['gamma']
|
||||
ph_i = classes['identity']
|
||||
if not ph_g and not ph_i:
|
||||
print('нет чистых кадров в', ds)
|
||||
return
|
||||
for lbl, best in (('γ-фаза', ph_g), ('identity', ph_i)):
|
||||
if not best:
|
||||
continue
|
||||
_, f, scr, trk, cur, gamma_fit, grms = best
|
||||
n = len(scr)
|
||||
cut_meas = -20 / np.log(10) * np.log(np.maximum(cur, 1e-30))
|
||||
g_use = gamma_fit
|
||||
cut_sim = g_use * (-scr) * 20 / np.log(10)
|
||||
e = cut_sim - cut_meas
|
||||
sel = np.abs(cut_meas) > 0.1
|
||||
rms_db = float(np.sqrt(np.mean(e[sel] ** 2))) if sel.any() else 0.0
|
||||
print(f'{lbl}: {os.path.basename(f)} γ={gamma_fit:.6f} (rms {grms:.1e}) '
|
||||
f'закон: rms={rms_db:.4f} дБ / {int(sel.sum())} бинов')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -32,6 +32,9 @@ def load_mono(p):
|
||||
ch = w.getnchannels(); b = w.getsampwidth()
|
||||
if b == 2:
|
||||
return np.frombuffer(d, dtype=np.int16).astype(np.float64).reshape(-1, ch).mean(1) / 32768
|
||||
# 24-bit: handle misaligned data (extra bytes from bext/junk chunks)
|
||||
n_samples = len(d) // (ch * 3)
|
||||
d = d[:n_samples * ch * 3]
|
||||
raw = np.frombuffer(d, dtype=np.uint8).reshape(-1, ch, 3)
|
||||
s = raw[:, :, 0].astype(np.int64) | (raw[:, :, 1].astype(np.int64) << 8) | (raw[:, :, 2].astype(np.int64) << 16)
|
||||
return np.where(s >= 0x800000, s - 0x1000000, s).mean(1).astype(np.float64) / 8388608.0
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
#!/usr/bin/env python3
|
||||
"""detector_cascade.py — validated simulator of the soothe2 detector cascade (529c60).
|
||||
|
||||
Decoded from assembly (2026-08-25):
|
||||
Phase 1: |z_i| via 16140 (vrsqrtps+vsqrtps — magnitude, NOT squared)
|
||||
Phase 2: Haar smoothing kernel [0.25, 0.5, 0.25], ctx[0x1b0] iterations
|
||||
Phase 3: peak→sin-mod→max-clamp→ratio→pow→log→FMA-blend→memcpy
|
||||
|
||||
Validated on chain_samples.pkl (2-frame ptrace capture):
|
||||
- op A output matches |z| (max diff 5.4e-6)
|
||||
- 2 Haar iterations + scalar blend: rms=0.30, corr=0.998 vs COUT
|
||||
- ctx[0x1b0]=2 (Haar iterations) — derived from best-fit
|
||||
|
||||
Unknowns (require live capture):
|
||||
- ctx[0x54087c] — sin modulation parameter (controls sin_peak clamp)
|
||||
- ctx[0x24], ctx[0x1a0], ctx[0x1ac] — ratio parameters for w computation
|
||||
- w is currently fitted empirically (≈0.015 for this test signal)
|
||||
"""
|
||||
import numpy as np
|
||||
|
||||
N = 2049 # FFT bins (NFRAME/2 + 1)
|
||||
|
||||
|
||||
def haar_one_pass(b):
|
||||
"""One Haar smoothing pass (kernel [0.25, 0.5, 0.25]).
|
||||
|
||||
Decoded from 529c60 Haar loop (lines 35-74):
|
||||
Step 1: b[i] += b[i+1] (prefix sum, 10e40)
|
||||
Step 2: b[i] *= 0.5 (scalar mul, ffe0)
|
||||
Step 3: scratch[i] = b[i+1] + b[i] (3-op add, 11580)
|
||||
Step 4: b[i+1] = 0.5 * scratch[i] (scalar mul+store, 4720)
|
||||
"""
|
||||
n = len(b)
|
||||
if n < 2:
|
||||
return b
|
||||
# Steps 1+2 combined: b[i] = 0.5 * (b[i] + b[i+1]) for i < n-1
|
||||
# Note: b[n-1] is unchanged by steps 1+2
|
||||
b[:-1] = 0.5 * (b[:-1] + b[1:])
|
||||
# Steps 3+4: b[i+1] = 0.5 * (b[i] + b[i+1]) using UPDATED b
|
||||
# Need original b[i] values for step 3
|
||||
# Actually: step 3 reads AFTER steps 1+2, so uses modified b
|
||||
# scratch[i] = b[i+1] + b[i] (both modified)
|
||||
# b[i+1] = 0.5 * scratch[i]
|
||||
# This means: b_new[i+1] = 0.5 * (b_modified[i+1] + b_modified[i])
|
||||
b6f8 = b[1:] + b[:-1]
|
||||
b[1:] = 0.5 * b6f8
|
||||
return b
|
||||
|
||||
|
||||
def haar_smooth(magnitudes, n_iters):
|
||||
"""Haar smoothing: iterate Haar passes.
|
||||
|
||||
Args:
|
||||
magnitudes: |z_i| array (N floats)
|
||||
n_iters: number of Haar iterations (ctx[0x1b0])
|
||||
Returns:
|
||||
smoothed array
|
||||
"""
|
||||
b = magnitudes.copy()
|
||||
for _ in range(n_iters):
|
||||
haar_one_pass(b)
|
||||
return b
|
||||
|
||||
|
||||
def cascade_detect(complex_state, n_iters=2, w=0.015, sin_peak_floor=0.0):
|
||||
"""Full detector cascade (529c60) simulation.
|
||||
|
||||
Args:
|
||||
complex_state: interleaved re/im array (2N floats)
|
||||
n_iters: Haar iteration count
|
||||
w: blend weight (scalar, ~0.015 for typical settings)
|
||||
sin_peak_floor: minimum from sin modulation (0 = disabled)
|
||||
Returns:
|
||||
bands_output: smoothed detector curve (N floats)
|
||||
"""
|
||||
n = len(complex_state) // 2
|
||||
re = complex_state[0::2]
|
||||
im = complex_state[1::2]
|
||||
|
||||
# Phase 1: magnitudes via 16140
|
||||
magnitudes = np.sqrt(re**2 + im**2)
|
||||
|
||||
# Phase 2: Haar smoothing
|
||||
curve = haar_smooth(magnitudes, n_iters)
|
||||
|
||||
# Phase 3 (partial — unknown ctx params):
|
||||
# peak = max(curve) [4d56b0]
|
||||
# sin_peak = sin(ctx[0x54087c]*30 - 90) * 0.115129 * peak [1a14cac]
|
||||
# curve[i] = max(curve[i], sin_peak) [52d8a0→10860]
|
||||
if sin_peak_floor > 0:
|
||||
np.maximum(curve, sin_peak_floor, out=curve)
|
||||
|
||||
# Blend: output = curve * (1-w) + accumulator * w
|
||||
# 5407a8 (accumulator) = 0 in steady state → output = curve * (1-w)
|
||||
# The blend chain:
|
||||
# 52d920: 5407a8[i] *= w (array scalar mul)
|
||||
# 52dae0: 5407a8[i] += curve[i] * (1-w) (FMA)
|
||||
# 52dbc0: memcpy 5407a8 → 540678
|
||||
bands_output = curve * (1.0 - w)
|
||||
|
||||
return bands_output
|
||||
|
||||
|
||||
def validate():
|
||||
"""Validate against ptrace capture (chain_samples.pkl)."""
|
||||
import pickle
|
||||
path = '/tmp/opencode/winetrace_casc/chain_samples.pkl'
|
||||
with open(path, 'rb') as f:
|
||||
data = pickle.load(f)
|
||||
|
||||
s = data['samples']
|
||||
cin = s[0]
|
||||
cout = s[3]
|
||||
|
||||
trk = np.array(cin['trk'], dtype=np.float64)
|
||||
b0_cout = np.array(cout['bands0'], dtype=np.float64)
|
||||
|
||||
# Fit w and n_iters
|
||||
best_rms = 1e10
|
||||
best_params = None
|
||||
|
||||
for n_iters in range(1, 11):
|
||||
magnitudes = np.zeros(len(trk) // 2)
|
||||
re = trk[0::2]; im = trk[1::2]
|
||||
magnitudes = np.sqrt(re**2 + im**2)
|
||||
|
||||
curve = haar_smooth(magnitudes, n_iters)
|
||||
|
||||
sig = (curve > 0.5) & (b0_cout > 0.5)
|
||||
if sig.sum() < 10:
|
||||
continue
|
||||
|
||||
w_vals = 1.0 - b0_cout[sig] / curve[sig]
|
||||
w = float(np.median(w_vals))
|
||||
|
||||
predicted = curve * (1.0 - w)
|
||||
rms = float(np.sqrt(np.mean((predicted - b0_cout) ** 2)))
|
||||
corr = float(np.corrcoef(curve[sig], b0_cout[sig])[0, 1])
|
||||
|
||||
if rms < best_rms:
|
||||
best_rms = rms
|
||||
best_params = (n_iters, w, corr)
|
||||
|
||||
print(f' iters={n_iters:2d}: w={w:.6f}, rms={rms:.4f}, corr={corr:.6f}')
|
||||
|
||||
n_iters, w, corr = best_params
|
||||
print(f'\nBest: iters={n_iters}, w={w:.6f}, rms={best_rms:.4f}, corr={corr:.6f}')
|
||||
return n_iters, w
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
if '--validate' in sys.argv:
|
||||
validate()
|
||||
else:
|
||||
print('Usage: detector_cascade.py --validate')
|
||||
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env python3
|
||||
"""dis.py — quick capstone disassembler for soothe_mem.bin (base 0x180000000).
|
||||
Usage: dis.py <VA> [len] [va2 len2 ...]
|
||||
"""
|
||||
import sys
|
||||
from capstone import Cs, CS_ARCH_X86, CS_MODE_64
|
||||
|
||||
BASE = 0x180000000
|
||||
_data = open('/home/m/re-tools/soothe_mem.bin', 'rb').read()
|
||||
|
||||
def dis(va, n=256):
|
||||
off = va - BASE
|
||||
code = _data[off:off + n]
|
||||
md = Cs(CS_ARCH_X86, CS_MODE_64)
|
||||
md.detail = False
|
||||
out = []
|
||||
for ins in md.disasm(code, va):
|
||||
s = '%08x %-24s %s %s' % (ins.address, ins.bytes.hex(),
|
||||
ins.mnemonic, ins.op_str)
|
||||
out.append(s)
|
||||
if ins.mnemonic == 'ret':
|
||||
break
|
||||
return '\n'.join(out)
|
||||
|
||||
if __name__ == '__main__':
|
||||
a = sys.argv[1:]
|
||||
for i in range(0, len(a), 2):
|
||||
va = int(a[i], 16)
|
||||
n = int(a[i + 1], 16) if i + 1 < len(a) else 256
|
||||
print('==== %x (len %x) ====' % (va, n))
|
||||
print(dis(va, n))
|
||||
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python3
|
||||
"""disasm_func.py — full-function disassembler with resolved RIP constants.
|
||||
Usage: disasm_func.py <VA> [max_bytes]
|
||||
Stops on int3-run after a ret. Prints resolved [rip+X] targets inline.
|
||||
"""
|
||||
import sys
|
||||
import struct
|
||||
from capstone import Cs, CS_ARCH_X86, CS_MODE_64
|
||||
from capstone.x86 import X86_OP_MEM, X86_REG_RIP
|
||||
|
||||
BASE = 0x180000000
|
||||
_data = open('/home/m/re-tools/soothe_mem.bin', 'rb').read()
|
||||
|
||||
def rd(va, n):
|
||||
return _data[va - BASE: va - BASE + n]
|
||||
|
||||
def main():
|
||||
va = int(sys.argv[1], 16)
|
||||
maxb = int(sys.argv[2], 16) if len(sys.argv) > 2 else 0x4000
|
||||
code = rd(va, maxb)
|
||||
md = Cs(CS_ARCH_X86, CS_MODE_64)
|
||||
md.detail = True
|
||||
out = []
|
||||
run_int3 = 0
|
||||
seen_ret = False
|
||||
for ins in md.disasm(code, va):
|
||||
line = '%08x %-22s %s %s' % (ins.address, ins.bytes.hex(), ins.mnemonic, ins.op_str)
|
||||
note = ''
|
||||
for op in ins.operands:
|
||||
if op.type == X86_OP_MEM and op.mem.base == X86_REG_RIP:
|
||||
tgt = ins.address + ins.size + op.mem.disp
|
||||
note += ' ; ->%x' % tgt
|
||||
b4 = rd(tgt, 8)
|
||||
f32v = struct.unpack('<f', b4[:4])[0]
|
||||
f64v = struct.unpack('<d', b4[:8])[0]
|
||||
u64v = struct.unpack('<Q', b4[:8])[0]
|
||||
if abs(f32v) > 1e-6 and abs(f32v) < 1e8:
|
||||
note += ' f32=%.6g' % f32v
|
||||
elif abs(f64v) > 1e-6 and abs(f64v) < 1e12:
|
||||
note += ' f64=%.6g' % f64v
|
||||
else:
|
||||
note += ' u64=%x' % u64v
|
||||
line += note
|
||||
out.append(line)
|
||||
if ins.mnemonic == 'ret':
|
||||
seen_ret = True
|
||||
run_int3 = 0
|
||||
elif ins.mnemonic == 'int3':
|
||||
if seen_ret:
|
||||
run_int3 += 1
|
||||
if run_int3 >= 4:
|
||||
break
|
||||
else:
|
||||
run_int3 = 0
|
||||
print('\n'.join(out))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env python3
|
||||
"""dump_dispatch.py — dump dispatch tables of bigkernel stubs at runtime.
|
||||
Stubs of interest (from FIR loop / steps 14,17):
|
||||
1409e0 -> table@182617508 ; 140ad0 -> ? ; 140b30 -> table@1826176c8
|
||||
Nested stub inside 140a00: idx cell/table computed below.
|
||||
Dumps tables pre-render (static) and during render (runtime-patched).
|
||||
"""
|
||||
import struct, subprocess, sys, time
|
||||
import glob, os
|
||||
|
||||
BASE = 0x180000000
|
||||
data = open('/home/m/re-tools/soothe_mem.bin','rb').read()
|
||||
|
||||
def find_host():
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid=int(os.path.basename(p))
|
||||
try:
|
||||
cmd=open(f'/proc/{pid}/cmdline','rb').read().replace(b'\0',b' ').decode('utf8','replace')
|
||||
maps=open(f'/proc/{pid}/maps').read()
|
||||
except Exception: continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd: return pid
|
||||
return None
|
||||
|
||||
def rd(a,n):
|
||||
try: return os.pread(fd,n,a)
|
||||
except OSError: return None
|
||||
|
||||
subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; "
|
||||
"rm -rf /run/user/1000/yabridge-soothe2_x64-*; sleep 1", shell=True)
|
||||
rpp=sys.argv[1] if len(sys.argv)>1 else '/tmp/opencode/multi.rpp'
|
||||
proc=subprocess.Popen(['/usr/bin/reaper','-nosplash','-ignoreerrors','-renderproject',rpp],
|
||||
stdout=subprocess.DEVNULL,stderr=subprocess.STDOUT)
|
||||
t0=time.time(); host=None
|
||||
while time.time()-t0<30 and not host:
|
||||
host=find_host(); time.sleep(0.002)
|
||||
print('host',host,flush=True)
|
||||
if not host: sys.exit(1)
|
||||
fd=os.open(f'/proc/{host}/mem',os.O_RDONLY)
|
||||
|
||||
TABLES={'bk140b30':0x1826176c8,'bk140b60':0x182617708,'bk1409e0':0x182617508,
|
||||
'bk140ad0':None,'bk140a40':0x182617588}
|
||||
# find bk140ad0 table: stub 140ad0 pattern movsxd rax,[rip+X]; lea r10,[rip+Y]
|
||||
off=0x180140ad0-BASE
|
||||
b=data[off:off+16]
|
||||
rel1=struct.unpack('<i',b[3:7])[0]
|
||||
rel2=struct.unpack('<i',b[10:14])[0]
|
||||
idx_a=0x180140ad0+7+rel1
|
||||
tbl_a=0x180140ad0+14+rel2
|
||||
TABLES['bk140ad0']=tbl_a
|
||||
print('bk140ad0 idx@%x tbl@%x' % (idx_a,tbl_a),flush=True)
|
||||
|
||||
def dump_tables(tag):
|
||||
print(tag,'fd=',fd,flush=True)
|
||||
for nm,t in TABLES.items():
|
||||
b=rd(t,64)
|
||||
if b is None:
|
||||
import errno
|
||||
print('%s %s unreadable err=%s'%(tag,nm,os.strerror(errno.EIO))); continue
|
||||
vals=struct.unpack('<%dQ'%(len(b)//8),b[:len(b)//8*8])
|
||||
nz=[(i,hex(v)) for i,v in enumerate(vals) if v]
|
||||
print('%s %-9s: %s' % (tag,nm,nz), flush=True)
|
||||
|
||||
# also nested stub inside 140a00 (static parse):
|
||||
off=0x140a10-BASE
|
||||
b1=data[off:off+7]
|
||||
if b1[:3]==b'\x48\x63\x05':
|
||||
rel=struct.unpack('<i',b1[3:7])[0]
|
||||
icell=0x180140a10+7+rel
|
||||
b2=data[icell-BASE:4]
|
||||
print('nested idx cell @%x static=%d' % (icell, struct.unpack('<i',b2)[0]),flush=True)
|
||||
|
||||
for k in range(30):
|
||||
dump_tables('R%d'%k)
|
||||
time.sleep(0.15)
|
||||
try:
|
||||
os.kill(proc.pid,0)
|
||||
except ProcessLookupError:
|
||||
break
|
||||
os.close(fd)
|
||||
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python3
|
||||
"""finish_f.py — patch band freq=500, render refs, capture scratches, build tracts."""
|
||||
import subprocess, os, re, sys, time, wave, glob
|
||||
import numpy as np
|
||||
|
||||
sys.path.insert(0,'/home/m/re-tools/scripts')
|
||||
|
||||
def sh(cmd):
|
||||
r=subprocess.run(cmd,shell=True,capture_output=True,text=True)
|
||||
return r.stdout+r.stderr
|
||||
|
||||
# 1. patch band freq=500 into raw clones
|
||||
for a in (0,6,12,24):
|
||||
src=open(f'/tmp/opencode/f{a}_raw.rpp').read()
|
||||
open(f'/tmp/opencode/f{a}.rpp','w').write(src)
|
||||
print('freq left as base1k default (band1 freq=1000?) — CHECK')
|
||||
# base1k was cloned from multi.rpp which had band1 freq=500 already!
|
||||
# t1k_base.rpp got 'band1 freq'=1000 patched; f*_raw cloned from base1k -> 1000.
|
||||
# We need 500: patch each:
|
||||
for a in (0,6,12,24):
|
||||
out=sh(f'cd /home/m/re-tools && python3 patchparam.py /tmp/opencode/f{a}_raw.rpp /tmp/opencode/f{a}.rpp "band1 freq"=500.0')
|
||||
if 'patched 1' not in out: print(f'f{a} patch issue:',out.strip()[:80])
|
||||
print('patched to 500')
|
||||
|
||||
def find_host():
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid=int(os.path.basename(p))
|
||||
try:
|
||||
cmd=open(f'/proc/{pid}/cmdline','rb').read().replace(b'\0',b' ').decode('utf8','replace')
|
||||
maps=open(f'/proc/{pid}/maps').read()
|
||||
except Exception: continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd: return pid
|
||||
return None
|
||||
|
||||
sh("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; "
|
||||
"rm -rf /run/user/1000/yabridge-soothe2_x64-*; sleep 1")
|
||||
|
||||
for a in (0,6,12,24):
|
||||
wav=f'/tmp/opencode/f{a}_ref.wav'
|
||||
if os.path.exists(wav): os.remove(wav)
|
||||
pr=subprocess.Popen(['/usr/bin/reaper','-nosplash','-ignoreerrors','-renderproject',f'/tmp/opencode/f{a}.rpp'],
|
||||
stdout=subprocess.DEVNULL,stderr=subprocess.STDOUT)
|
||||
t0=time.time(); host=None
|
||||
while time.time()-t0<30 and not host: host=find_host(); time.sleep(0.002)
|
||||
# wait for natural finish
|
||||
for _ in range(200):
|
||||
if pr.poll() is not None: break
|
||||
try:
|
||||
if not os.path.exists('/proc/%d'%host) if host else True: break
|
||||
except Exception: break
|
||||
time.sleep(0.05)
|
||||
for _ in range(60):
|
||||
if pr.poll() is not None: break
|
||||
time.sleep(0.1)
|
||||
print(f'f{a} rendered rc={pr.poll()} wav={os.path.getsize(wav) if os.path.exists(wav) else "NONE"}')
|
||||
|
||||
# tracts
|
||||
env=dict(os.environ)
|
||||
for a in (0,6,12,24):
|
||||
tf=f'/tmp/opencode/tract_f{a}.txt'
|
||||
if os.path.exists(tf): os.remove(tf)
|
||||
e=dict(env); e['RT_DUMP_BIN']=tf
|
||||
subprocess.run(['/home/m/re-tools/dsp/build/render48k',f'/tmp/opencode/{a}_in.wav' if False else f'/tmp/opencode/f{a}_in.wav',
|
||||
'/tmp/o48_f.wav','500,0.5,12'],capture_output=True,env=e)
|
||||
print('tracts done')
|
||||
@@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env python3
|
||||
"""fir_probe.py — численная реплика FIR-цепи (Этап A3) против захватов.
|
||||
|
||||
Структура по дизасму (BLOCKMAP 24mm6/24mm8 + wrap/worker декод этого раунда):
|
||||
copy: FIR[2j]=scr[j], FIR[2j+1]=0 (18004d900, 2049 пар)
|
||||
opA: th2180 = INVERSE real-FFT (план buf548, N=4096, scale 1/4096)
|
||||
scale: float[1..2047] *= 2.0 ; float[2049..4095] = 0 (52d920/52db50)
|
||||
opB: th1a90 = FORWARD real-FFT
|
||||
EXP: expf in-place по первым 2049 ФЛОАТАМ (140b30, 52b708-716)
|
||||
opC: th2180 = INVERSE
|
||||
window: float[0..2047] *= WINfreq[2048..4095] (52d990, падающий Hann)
|
||||
float[2048..4095] = 0 (52db50)
|
||||
opD: th1a90 = FORWARD
|
||||
fix: FIR[0]=1.0, FIR[1]=0 (52b7cd-e1)
|
||||
df0: track_i := track_i ⊗ FIR (комплексное умножение, 18000b3c0)
|
||||
Цель: воспроизвести cur@678 из trk@688 без свободных параметров.
|
||||
"""
|
||||
import numpy as np
|
||||
import glob
|
||||
import os
|
||||
import sys
|
||||
|
||||
NFLOAT = 4098 # 2049 пар
|
||||
NBINS = 2049 # n/2+1, n=[ctx+0x540534]=4096
|
||||
|
||||
|
||||
def load_frame(npz):
|
||||
d = np.load(npz)
|
||||
S = {}
|
||||
for k in d.keys():
|
||||
if k.startswith('0x'):
|
||||
S[int(k[2:], 16)] = d[k]
|
||||
return S
|
||||
|
||||
|
||||
def win_periodic_hann(N):
|
||||
return 0.5 * (1.0 - np.cos(2.0 * np.pi * np.arange(N) / N)).astype(np.float64)
|
||||
|
||||
|
||||
def fir_chain(scr, winfall, variant='flat'):
|
||||
"""scr: 2049 float (log-домен). Возвращает halfcomplex-спектр ядра F[2049]."""
|
||||
# copy/pack: пары (re=scr, im=0) -> inverse rfft вход (numpy: complex[2049])
|
||||
H = scr.astype(np.float64).astype(np.complex128)
|
||||
# opA: inverse real FFT, нормировка 1/N (план scale=2^-12 при активном флаге)
|
||||
y = np.fft.irfft(H, n=4096) # уже содержит деление на 4096
|
||||
# scale/zero по asm: float[1..2047]*=2, float[2049..]=0 (f[2048] не трогаем)
|
||||
y[1:2048] *= 2.0
|
||||
y[2049:] = 0.0
|
||||
# opB: forward
|
||||
Y = np.fft.rfft(y, n=4096) # complex[2049]
|
||||
# EXP по первым 2049 флоатам плоского массива
|
||||
flat = np.empty(NFLOAT)
|
||||
flat[0::2] = Y.real
|
||||
flat[1::2] = Y.imag
|
||||
if variant == 'flat':
|
||||
flat[:2049] = np.exp(flat[:2049])
|
||||
elif variant == 'cplx':
|
||||
Y = np.exp(Y.astype(np.complex128))
|
||||
flat[0::2] = Y.real
|
||||
flat[1::2] = Y.imag
|
||||
Y2 = flat[0::2] + 1j * flat[1::2]
|
||||
# opC: inverse
|
||||
w = np.fft.irfft(Y2, n=4096)
|
||||
# window: float[0..2047] *= падающая половина; хвост = 0
|
||||
w[:2048] *= winfall
|
||||
w[2048:] = 0.0
|
||||
# opD: forward
|
||||
F = np.fft.rfft(w, n=4096)
|
||||
# fix: FIR[0]=1.0, FIR[1]=0
|
||||
F[0] = 1.0 + 0.0j
|
||||
return F
|
||||
|
||||
|
||||
def evaluate(ds, ph_file, verbose=True):
|
||||
S = load_frame(os.path.join(ds, ph_file))
|
||||
scr = S[0x540628][:NBINS].astype(np.float64)
|
||||
trk = S[0x540688][:NBINS].astype(np.float64)
|
||||
cur = S[0x540678][:NBINS].astype(np.float64)
|
||||
# проверка trk == exp(scr)
|
||||
m_ok = trk > 1e-30
|
||||
err_trk = np.abs(np.log(trk[m_ok]) - scr[m_ok]).max()
|
||||
# фит gamma
|
||||
sel = np.abs(scr) > 0.05
|
||||
g = float(np.sum(scr[sel] * np.log(cur[sel])) / np.sum(scr[sel] ** 2))
|
||||
rms_fit = float(np.sqrt(np.mean((np.log(cur[sel]) - g * scr[sel]) ** 2)))
|
||||
winfall = win_periodic_hann(4096)[2048:]
|
||||
out = []
|
||||
for variant in ('flat', 'cplx'):
|
||||
F = fir_chain(scr, winfall, variant)
|
||||
# маска = track ⊗ F (df0), берём реальную часть как применённую маску
|
||||
mask_sim = np.abs(trk * F) if variant == 'cplx' else trk * F.real
|
||||
mm = (cur > 1e-6) & np.isfinite(mask_sim)
|
||||
e_db = 20.0 / np.log(10) * np.log(np.abs(mask_sim[mm])) - \
|
||||
20.0 / np.log(10) * np.log(cur[mm])
|
||||
rms_db = float(np.sqrt(np.mean(e_db ** 2)))
|
||||
out.append((variant, rms_db, int(mm.sum())))
|
||||
if verbose:
|
||||
print(f'{ph_file} [{variant}] gamma_fit={g:.6f} (rms {rms_fit:.1e}) '
|
||||
f'trk_err={err_trk:.2e} MASK rms={rms_db:.4f} дБ / {mm.sum()} бинов')
|
||||
return out
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
jobs = [
|
||||
('/tmp/opencode/sc_multi4b', 'ph073.npz'),
|
||||
('/tmp/opencode/sc_multi6', 'ph037.npz'),
|
||||
('/tmp/opencode/sc_multi6', 'ph034.npz'),
|
||||
]
|
||||
if len(sys.argv) > 1:
|
||||
jobs = [(os.path.dirname(sys.argv[1]), os.path.basename(sys.argv[1]))]
|
||||
for ds, ph in jobs:
|
||||
evaluate(ds, ph)
|
||||
@@ -0,0 +1,136 @@
|
||||
#!/usr/bin/env python3
|
||||
"""firstop.py — catch the plugin INSIDE its audio callback by repeatedly
|
||||
SIGSTOP-ing the yabridge host and reading only the ctx-referenced arrays.
|
||||
|
||||
Between callbacks the FIR work buffer (ctx+0x540668) is reset to the complex
|
||||
identity (1,0)x2049. A snapshot where FIR != identity means we stopped after
|
||||
the mask->FIR build stage; those snapshots are saved with the full pipeline
|
||||
state (bands/scratch/f6f8/track/R curves).
|
||||
|
||||
Usage: python3 scripts/firstop.py [rpp] [nattempts]
|
||||
"""
|
||||
import os
|
||||
import signal
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
|
||||
SNAPDIR = '/tmp/opencode/firstop'
|
||||
SLOTS = [0x540548, 0x540550, 0x540598, 0x540628, 0x540668, 0x540678, 0x540688,
|
||||
0x540698, 0x5406a8, 0x5406b8, 0x5406c8, 0x5406d8, 0x5406e8, 0x5406f8,
|
||||
0x540708, 0x540718, 0x540728, 0x540738, 0x540748, 0x540758,
|
||||
0x540768, 0x540778, 0x540788, 0x540798, 0x5407a8, 0x5407b8,
|
||||
0x5407c8, 0x5407d8, 0x5407e8, 0x5407f8, 0x540808, 0x540818,
|
||||
0x540828, 0x540838, 0x540848]
|
||||
NARR = 8194
|
||||
|
||||
|
||||
def find_host():
|
||||
import glob
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
cmd = open(f'/proc/{pid}/cmdline', 'rb').read().replace(b'\0', b' ').decode('utf8', 'replace')
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd:
|
||||
return pid
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
rpp = sys.argv[1] if len(sys.argv) > 1 else '/home/m/soothe-bt/dual_b1q_0.5.rpp'
|
||||
nattempts = int(sys.argv[2]) if len(sys.argv) > 2 else 120
|
||||
os.makedirs(SNAPDIR, exist_ok=True)
|
||||
subprocess.run('pkill -9 -x reaser 2>/dev/null; pkill -9 -x reaper 2>/dev/null; '
|
||||
"pkill -9 -f '[y]abridge' 2>/dev/null; sleep 1", shell=True)
|
||||
proc = subprocess.Popen(
|
||||
['/usr/bin/reaper', '-nosplash', '-ignoreerrors', rpp,
|
||||
'/home/m/re-tools/play_loop.lua'],
|
||||
stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
t0 = time.time()
|
||||
host = None
|
||||
while time.time() - t0 < 60 and not host:
|
||||
host = find_host()
|
||||
time.sleep(0.2)
|
||||
if not host:
|
||||
print('NO HOST')
|
||||
return 1
|
||||
print('host', host, flush=True)
|
||||
time.sleep(12)
|
||||
|
||||
fd = os.open(f'/proc/{host}/mem', os.O_RDONLY)
|
||||
|
||||
def rd(addr, n):
|
||||
try:
|
||||
return os.pread(fd, n, addr)
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
def get_ctx():
|
||||
# cheap probe: sens scalar must be >100 at known offset
|
||||
for base in (CTX.get('base'),):
|
||||
pass
|
||||
return CTX.get('base')
|
||||
|
||||
# locate ctx once (while running): marker scan over heap only is heavy;
|
||||
# reuse known-good address from prior sessions, validate via sens scalar.
|
||||
CTX = {}
|
||||
ctx = None
|
||||
b = rd(0x2370040 + 0x540870, 4)
|
||||
if b and struct.unpack('<f', b)[0] > 100:
|
||||
ctx = 0x2370040
|
||||
else:
|
||||
print('known ctx invalid; full scan needed')
|
||||
return 1
|
||||
print('ctx', hex(ctx), flush=True)
|
||||
|
||||
hits = 0
|
||||
saved = []
|
||||
rng = np.random.default_rng(7)
|
||||
for k in range(nattempts):
|
||||
os.kill(host, signal.SIGSTOP)
|
||||
try:
|
||||
fir_p = struct.unpack('<Q', rd(ctx + 0x540668, 8))[0]
|
||||
fb = rd(fir_p, 64 * 4)
|
||||
ident = False
|
||||
if fb:
|
||||
arr = np.frombuffer(fb[:256], dtype='<f4')
|
||||
ident = bool(np.all(np.abs(arr[0::2] - 1.0) < 1e-6))
|
||||
ident = ident and bool(np.all(arr[1::2] == 0))
|
||||
if not ident:
|
||||
hits += 1
|
||||
store = {}
|
||||
for off in SLOTS:
|
||||
pb = rd(ctx + off, 8)
|
||||
if not pb:
|
||||
continue
|
||||
p = struct.unpack('<Q', pb)[0]
|
||||
if p < 0x10000:
|
||||
continue
|
||||
ab = rd(p, NARR * 4)
|
||||
if not ab:
|
||||
continue
|
||||
store[hex(off)] = np.frombuffer(ab, dtype='<f4').astype(np.float32)
|
||||
fn = f'{SNAPDIR}/hit{k:03d}.npz'
|
||||
np.savez_compressed(fn, **store)
|
||||
saved.append(fn)
|
||||
sc = rd(ctx + 0x2404dc, 4)
|
||||
print(f'[{k}] HIT fir!=identity -> {fn} '
|
||||
f'(fir[0..5]={np.round(store["0x540668"][:6],4)})', flush=True)
|
||||
finally:
|
||||
os.kill(host, signal.SIGCONT)
|
||||
time.sleep(float(rng.uniform(0.02, 0.09)))
|
||||
os.close(fd)
|
||||
if proc.poll() is None:
|
||||
proc.kill()
|
||||
print(f'done: {hits} hits / {nattempts} attempts -> {SNAPDIR}')
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,206 @@
|
||||
#!/usr/bin/env python3
|
||||
"""firtrace.py — live capture of mask->FIR pipeline buffers during realtime
|
||||
playback, with GUI-publish flag forced ON so bands[i] curves are copied into
|
||||
the 0x540728+ slots inside the audio callback (decomp 529fe0:144-183).
|
||||
|
||||
Dumps full vector-object arrays for every ctx slot in [0x540500,0x540900):
|
||||
reads {data_ptr, end_ptr, cap_ptr} (std::vector layout) when available,
|
||||
falls back to fixed-length float view.
|
||||
|
||||
Usage: python3 scripts/firtrace.py [rpp] [nsnap]
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
|
||||
SNAPDIR = '/tmp/opencode/firtrace'
|
||||
|
||||
|
||||
def find_host():
|
||||
import glob
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
cmd = open(f'/proc/{pid}/cmdline', 'rb').read().replace(b'\0', b' ').decode('utf8', 'replace')
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd:
|
||||
return pid
|
||||
return None
|
||||
|
||||
|
||||
def mem_read(fd, addr, n):
|
||||
try:
|
||||
return os.pread(fd, n, addr)
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
|
||||
def mem_write(fd, addr, data):
|
||||
try:
|
||||
os.pwrite(fd, data, addr)
|
||||
return True
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
|
||||
def parse_snap(path):
|
||||
data = open(path, 'rb').read()
|
||||
regs = []
|
||||
i = 0
|
||||
while i + 16 <= len(data):
|
||||
lo, sz = struct.unpack_from('<QQ', data, i)
|
||||
regs.append((lo, data[i + 16:i + 16 + sz]))
|
||||
i += 16 + sz
|
||||
return regs
|
||||
|
||||
|
||||
def readabs(regs, addr, n):
|
||||
for lo, body in regs:
|
||||
if lo <= addr < lo + len(body) and addr - lo + n <= len(body):
|
||||
return body[addr - lo:addr - lo + n]
|
||||
return None
|
||||
|
||||
|
||||
def find_ctx(regs):
|
||||
sig = struct.pack('<I', 0x473b8000)
|
||||
cands = []
|
||||
for lo, body in regs:
|
||||
j = body.find(sig)
|
||||
while j >= 0:
|
||||
base = lo + j - 0x24
|
||||
b = readabs(regs, base + 0x540870, 4)
|
||||
if b and struct.unpack('<f', b)[0] > 100:
|
||||
cands.append(base)
|
||||
j = body.find(sig, j + 1)
|
||||
return sorted(set(cands))
|
||||
|
||||
|
||||
SLOTS = list(range(0x540600, 0x540900, 8))
|
||||
EXTRA = [0x540548, 0x540550, 0x540558, 0x540560, 0x540568, 0x540570,
|
||||
0x540578, 0x540580, 0x540588, 0x540590, 0x540598, 0x5405a0,
|
||||
0x5405a8, 0x5405b0, 0x5405b8, 0x5405c0, 0x5405c8, 0x5405d0,
|
||||
0x5405d8, 0x5405e0, 0x5405e8, 0x5405f0, 0x5405f8]
|
||||
|
||||
|
||||
def dump_slot(regs, ctx, off, maxf=65536):
|
||||
"""Read qword at ctx+off; if it looks like a heap array, dump floats."""
|
||||
b = readabs(regs, ctx + off, 8)
|
||||
if not b:
|
||||
return None
|
||||
ptr = struct.unpack('<Q', b)[0]
|
||||
if ptr < 0x10000 or ptr > 0x7fffffffffff:
|
||||
return None
|
||||
body = readabs(regs, ptr, min(maxf, 262144) * 4)
|
||||
if body is None or len(body) < 64:
|
||||
return None
|
||||
a = np.frombuffer(body, dtype='<f4').astype(np.float64)
|
||||
# trim trailing zeros beyond a floor of 2049 samples
|
||||
nz = np.nonzero(a != 0)[0]
|
||||
keep = max(2049, (nz[-1] + 1) if len(nz) else 0)
|
||||
return a[:min(len(a), ((keep + 63) // 64) * 64)]
|
||||
|
||||
|
||||
def main():
|
||||
rpp = sys.argv[1] if len(sys.argv) > 1 else '/home/m/soothe-bt/dual_b1q_0.5.rpp'
|
||||
nsnap = int(sys.argv[2]) if len(sys.argv) > 2 else 4
|
||||
os.makedirs(SNAPDIR, exist_ok=True)
|
||||
subprocess.run('pkill -9 -x reaser 2>/dev/null; pkill -9 -x reaper 2>/dev/null; '
|
||||
"pkill -9 -f '[y]abridge' 2>/dev/null; sleep 1", shell=True)
|
||||
proc = subprocess.Popen(
|
||||
['/usr/bin/reaper', '-nosplash', '-ignoreerrors', rpp,
|
||||
'/home/m/re-tools/play_loop.lua'],
|
||||
stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
t0 = time.time()
|
||||
host = None
|
||||
while time.time() - t0 < 60 and not host:
|
||||
host = find_host()
|
||||
time.sleep(0.2)
|
||||
if not host:
|
||||
print('NO HOST')
|
||||
return 1
|
||||
print('host', host, flush=True)
|
||||
time.sleep(12)
|
||||
|
||||
fd = os.open(f'/proc/{host}/mem', os.O_RDONLY)
|
||||
# locate ctx via one full snapshot
|
||||
snap0 = f'{SNAPDIR}/probe.bin'
|
||||
snapshot(fd, host, snap0)
|
||||
regs = parse_snap(snap0)
|
||||
cands = find_ctx(regs)
|
||||
print('ctx candidates:', ['0x%x' % c for c in cands][:5], flush=True)
|
||||
if not cands:
|
||||
return 1
|
||||
ctx = cands[0]
|
||||
|
||||
# force GUI publish flag (byte at ctx+0x2404bc)
|
||||
ok = mem_write(fd, ctx + 0x2404bc, b'\x01')
|
||||
print('GUI flag write:', ok, flush=True)
|
||||
|
||||
store = {}
|
||||
meta = {}
|
||||
for k in range(nsnap):
|
||||
time.sleep(1.5)
|
||||
# re-arm flag (callback consumes it)
|
||||
mem_write(fd, ctx + 0x2404bc, b'\x01')
|
||||
time.sleep(0.05)
|
||||
p = f'{SNAPDIR}/s{k}.bin'
|
||||
snapshot(fd, host, p)
|
||||
rg = parse_snap(p)
|
||||
cs = find_ctx(rg)
|
||||
if not cs:
|
||||
continue
|
||||
c = cs[0]
|
||||
tag = f's{k}'
|
||||
scal = {}
|
||||
for a in range(0x540860, 0x5408a8, 4):
|
||||
bb = readabs(rg, c + a, 4)
|
||||
scal[hex(a)] = struct.unpack('<f', bb)[0] if bb else None
|
||||
store[f'{tag}_scalars'] = json.dumps(scal)
|
||||
for off in SLOTS + EXTRA:
|
||||
arr = dump_slot(rg, c, off)
|
||||
if arr is not None:
|
||||
store[f'{tag}_{hex(off)}'] = arr
|
||||
meta.setdefault(hex(off), []).append(len(arr))
|
||||
print(f'snap {k}: dumped {sum(1 for x in store if x.startswith(tag+"_") and x!=tag+"_scalars")} arrays',
|
||||
flush=True)
|
||||
os.close(fd)
|
||||
if proc.poll() is None:
|
||||
proc.kill()
|
||||
|
||||
json.dump(meta, open(f'{SNAPDIR}/meta.json', 'w'), indent=1)
|
||||
np.savez_compressed(f'{SNAPDIR}/firtrace.npz', **store)
|
||||
print('saved', f'{SNAPDIR}/firtrace.npz')
|
||||
return 0
|
||||
|
||||
|
||||
def snapshot(fd, host, path):
|
||||
out = open(path, 'wb')
|
||||
nreg = nbytes = 0
|
||||
for line in open(f'/proc/{host}/maps').read().splitlines():
|
||||
p = line.split()
|
||||
if len(p) < 2 or 'r' not in p[1]:
|
||||
continue
|
||||
lo, hi = (int(x, 16) for x in p[0].split('-'))
|
||||
a = lo
|
||||
while a < hi:
|
||||
n = min(hi - a, 8 * 1024 * 1024)
|
||||
d = mem_read(fd, a, n)
|
||||
if d:
|
||||
out.write(struct.pack('<QQ', a, len(d)))
|
||||
out.write(d)
|
||||
nreg += 1
|
||||
nbytes += len(d)
|
||||
a += n
|
||||
out.close()
|
||||
return nreg, nbytes
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,210 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
fit_vlaw_by_group.py — Fit VLAW parameters (α, β, c, Δ) per configuration group.
|
||||
|
||||
VLAW model (framed_model.cpp:205-208):
|
||||
cs = α * log1p(lvl / β) + c + (delta ? Δ : 0)
|
||||
applied_gain = 10^(-cs / 20) [gamma0=1 already absorbed into α,c,Δ]
|
||||
|
||||
Need to fit these for each (fc, q, sens) configuration group:
|
||||
t1kq: fc=800..1200, q=1.0, sens=12 (input tone1kq)
|
||||
t1k: fc=500..2000, q=1.0, sens=12 (input tone1k)
|
||||
al: fc=1000, q=1.0, sens=3..24 (input lvl_tone_lvX)
|
||||
res: fc=300..700, q=1.0, sens=12 (input resonant)
|
||||
dual: fc=500, q=0.1..10.0, sens=12 (input dual)
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import json
|
||||
|
||||
sys.path.insert(0, '/home/m/re-tools/scripts')
|
||||
import corpus
|
||||
|
||||
corpus.RB = '/home/m/re-tools/dsp/build/render48k'
|
||||
|
||||
# Reference errors from baseline_bridge.json (target)
|
||||
with open('scripts/baseline_bridge.json') as f:
|
||||
REF_ERRORS = json.load(f)
|
||||
|
||||
def structural_cases():
|
||||
out = []
|
||||
for name, inp, args, ref, f in corpus.build_cases():
|
||||
joined = [','.join(args)] if len(args) == 3 else args
|
||||
out.append((name, inp, joined, ref, f))
|
||||
return out
|
||||
|
||||
def run_vlaw(inp, args, alpha, beta, c, delta):
|
||||
"""Run render48k with VLAW parameters and return output path."""
|
||||
out = f'/tmp/vlaw_fit_{alpha}_{beta}_{c}_{delta}_{os.path.basename(inp)}.wav'
|
||||
env = {
|
||||
**os.environ,
|
||||
'RT_VLAW': '1',
|
||||
'RT_VLAW_ALPHA': str(alpha),
|
||||
'RT_VLAW_BETA': str(beta),
|
||||
'RT_VLAW_C': str(c),
|
||||
'RT_VLAW_DELTA': str(delta),
|
||||
'RT_SYN': '1',
|
||||
'RT_NOWARP': '1',
|
||||
'RT_NOIIR3': '1',
|
||||
'RT_IIR12': '0',
|
||||
}
|
||||
subprocess.run(
|
||||
[corpus.RB, inp, out] + args,
|
||||
capture_output=True, text=True, env=env,
|
||||
cwd='/home/m/re-tools'
|
||||
)
|
||||
return out
|
||||
|
||||
def eval_error(out, ref, f):
|
||||
"""Evaluate error in dB between output and reference at frequency f."""
|
||||
if not os.path.exists(out) or os.path.getsize(out) == 0:
|
||||
return None
|
||||
ref_sig = corpus.load_mono(ref)
|
||||
out_sig = corpus.load_mono(out)
|
||||
min_len = min(len(ref_sig), len(out_sig))
|
||||
ref_sig = ref_sig[-min_len:]
|
||||
out_sig = out_sig[-min_len:]
|
||||
ref_ta = corpus.ta(ref_sig, f)
|
||||
out_ta = corpus.ta(out_sig, f)
|
||||
return corpus.db(out_ta / ref_ta)
|
||||
|
||||
def group_key(name):
|
||||
return name.split('_')[0]
|
||||
|
||||
def evaluate_params(alpha, beta, c, delta, cases_subset=None):
|
||||
"""Evaluate VLAW params on all cases, return per-group mean abs error."""
|
||||
all_cases = structural_cases()
|
||||
if cases_subset:
|
||||
all_cases = [c for c in all_cases if group_key(c[0]) in cases_subset]
|
||||
|
||||
errs = {}
|
||||
|
||||
for name, inp, args, ref, f in all_cases:
|
||||
out = run_vlaw(inp, args, alpha, beta, c, delta)
|
||||
err = eval_error(out, ref, f)
|
||||
if err is not None:
|
||||
errs[name] = err
|
||||
|
||||
# Group stats
|
||||
groups = {}
|
||||
for k, v in errs.items():
|
||||
g = group_key(k)
|
||||
groups.setdefault(g, []).append(v)
|
||||
|
||||
out_stats = {g: float(np.mean(np.abs(v))) for g, v in groups.items()}
|
||||
out_stats['TOTAL'] = float(np.mean(np.abs(list(errs.values()))))
|
||||
return out_stats, errs
|
||||
|
||||
def fit_single_case(name, inp, args, ref, f, init_params):
|
||||
"""Grid search for best params on a single case."""
|
||||
alpha0, beta0, c0, delta0 = init_params
|
||||
best = None
|
||||
best_err = float('inf')
|
||||
|
||||
# Search around initial params
|
||||
alphas = np.linspace(max(0.5, alpha0-1), alpha0+1, 9)
|
||||
betas = np.linspace(max(0.1, beta0-0.2), beta0+0.2, 9)
|
||||
cs = np.linspace(max(0.0, c0-0.5), c0+0.5, 9)
|
||||
deltas = np.linspace(max(0.0, delta0-2), delta0+2, 9)
|
||||
|
||||
for alpha in alphas:
|
||||
for beta in betas:
|
||||
for c in cs:
|
||||
for delta in deltas:
|
||||
out = run_vlaw(inp, args, alpha, beta, c, delta)
|
||||
err = eval_error(out, ref, f)
|
||||
if err is not None and abs(err) < best_err:
|
||||
best_err = abs(err)
|
||||
best = (alpha, beta, c, delta, err)
|
||||
print(f' {name}: new best α={alpha:.3f}, β={beta:.3f}, c={c:.3f}, Δ={delta:.3f} => err={err:.3f} dB')
|
||||
|
||||
return best
|
||||
|
||||
def main():
|
||||
# Build case map by group
|
||||
all_cases = structural_cases()
|
||||
groups = {}
|
||||
for name, inp, args, ref, f in all_cases:
|
||||
g = group_key(name)
|
||||
groups.setdefault(g, []).append((name, inp, args, ref, f))
|
||||
|
||||
print("Available groups:", list(groups.keys()))
|
||||
for g, cases in groups.items():
|
||||
print(f" {g}: {len(cases)} cases")
|
||||
|
||||
# Current calibrated params for dual(q=0.5)
|
||||
dual_params = (3.2193, 0.4927, 0.5423, 6.9177)
|
||||
|
||||
# Test current params on all groups
|
||||
print("\n=== Testing current dual params on all groups ===")
|
||||
stats, _ = evaluate_params(*dual_params)
|
||||
for g in ['t1kq', 't1k', 'al', 'res', 'dual', 'comb']:
|
||||
if g in stats:
|
||||
print(f' {g}: {stats[g]:.3f} dB')
|
||||
|
||||
# For each group, pick a representative case and fit
|
||||
print("\n=== Fitting per group (representative case) ===")
|
||||
results = {}
|
||||
|
||||
# For dual, use q=0.5 as reference (already calibrated)
|
||||
if 'dual' in groups:
|
||||
# Find q=0.5 case
|
||||
for name, inp, args, ref, f in groups['dual']:
|
||||
if '0.5' in name:
|
||||
best = fit_single_case(name, inp, args, ref, f, dual_params)
|
||||
if best:
|
||||
results['dual'] = best[:4]
|
||||
break
|
||||
|
||||
# For t1kq, use fc=1000
|
||||
if 't1kq' in groups:
|
||||
for name, inp, args, ref, f in groups['t1kq']:
|
||||
if '1000' in name:
|
||||
best = fit_single_case(name, inp, args, ref, f, dual_params)
|
||||
if best:
|
||||
results['t1kq'] = best[:4]
|
||||
break
|
||||
|
||||
# For t1k, use fc=1000
|
||||
if 't1k' in groups:
|
||||
for name, inp, args, ref, f in groups['t1k']:
|
||||
if '1000' in name:
|
||||
best = fit_single_case(name, inp, args, ref, f, dual_params)
|
||||
if best:
|
||||
results['t1k'] = best[:4]
|
||||
break
|
||||
|
||||
# For al, use sens=12
|
||||
if 'al' in groups:
|
||||
for name, inp, args, ref, f in groups['al']:
|
||||
if '12' in name:
|
||||
best = fit_single_case(name, inp, args, ref, f, dual_params)
|
||||
if best:
|
||||
results['al'] = best[:4]
|
||||
break
|
||||
|
||||
# For res, use fc=500
|
||||
if 'res' in groups:
|
||||
for name, inp, args, ref, f in groups['res']:
|
||||
if '500' in name:
|
||||
best = fit_single_case(name, inp, args, ref, f, dual_params)
|
||||
if best:
|
||||
results['res'] = best[:4]
|
||||
break
|
||||
|
||||
# Print results
|
||||
print("\n=== FITTED VLAW PARAMETERS BY GROUP ===")
|
||||
for g, (alpha, beta, c, delta) in results.items():
|
||||
print(f'{g}: α={alpha:.4f}, β={beta:.4f}, c={c:.4f}, Δ={delta:.4f}')
|
||||
|
||||
# Save to JSON
|
||||
with open('/tmp/opencode/vlaw_params.json', 'w') as f:
|
||||
json.dump({g: {'alpha': a, 'beta': b, 'c': c, 'delta': d}
|
||||
for g, (a, b, c, d) in results.items()}, f, indent=2)
|
||||
print('\nSaved to /tmp/opencode/vlaw_params.json')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,158 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
fit_vlaw_params.py — Fit VLAW parameters (α, β, c, Δ, γ₀) per configuration group.
|
||||
|
||||
VLAW model (framed_model.cpp:198-200):
|
||||
cs = α * log1p(lvl / β) + c + (delta ? Δ : 0)
|
||||
applied_gain = 10^(-γ₀ * cs / 20)
|
||||
|
||||
Currently hardcoded for dual(q=0.5): α=3.2193, β=0.4927, c=0.5423, Δ=7.46-0.5423, γ₀=1.79
|
||||
|
||||
Need to fit these for each (fc, q, sens) configuration group:
|
||||
t1kq: fc=800..1200, q=1.0, sens=12
|
||||
t1k: fc=500..2000, q=1.0, sens=12
|
||||
al: fc=1000, q=1.0, sens=3..24
|
||||
res: fc=300..700, q=1.0, sens=12
|
||||
dual: fc=500, q=0.1..10.0, sens=12
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
sys.path.insert(0, '/home/m/re-tools/scripts')
|
||||
import corpus
|
||||
|
||||
corpus.RB = '/home/m/re-tools/dsp/build/render48k'
|
||||
|
||||
def structural_cases():
|
||||
out = []
|
||||
for name, inp, args, ref, f in corpus.build_cases():
|
||||
joined = [','.join(args)] if len(args) == 3 else args
|
||||
out.append((name, inp, joined, ref, f))
|
||||
return out
|
||||
|
||||
def group_key(name):
|
||||
return name.split('_')[0]
|
||||
|
||||
def load_ref_errors():
|
||||
"""Load baseline_bridge.json for target errors."""
|
||||
with open('scripts/baseline_bridge.json') as f:
|
||||
return json.load(f)
|
||||
|
||||
def render_vlaw(inp, out, args, alpha, beta, c, delta, gamma0, extra_env=None):
|
||||
"""Run render48k with VLAW parameters."""
|
||||
env = {
|
||||
**os.environ,
|
||||
'RT_VLAW': '1',
|
||||
'RT_VLAW_ALPHA': str(alpha),
|
||||
'RT_VLAW_BETA': str(beta),
|
||||
'RT_VLAW_C': str(c),
|
||||
'RT_VLAW_DELTA': str(delta),
|
||||
'RT_VLAW_GAMMA0': str(gamma0),
|
||||
'RT_SYN': '1',
|
||||
'RT_NOWARP': '1',
|
||||
'RT_NOIIR3': '1',
|
||||
'RT_IIR12': '0',
|
||||
}
|
||||
if extra_env:
|
||||
env.update(extra_env)
|
||||
subprocess.run(
|
||||
[corpus.RB, inp, out] + args,
|
||||
capture_output=True, text=True, env=env,
|
||||
cwd='/home/m/re-tools'
|
||||
)
|
||||
|
||||
def eval_config(alpha, beta, c, delta, gamma0, cases_subset=None):
|
||||
"""Evaluate VLAW params on cases, return per-group mean abs error."""
|
||||
all_cases = structural_cases()
|
||||
if cases_subset:
|
||||
all_cases = [c for c in all_cases if group_key(c[0]) in cases_subset]
|
||||
|
||||
refs = load_ref_errors()
|
||||
errs = {}
|
||||
|
||||
for name, inp, args, ref, f in all_cases:
|
||||
out = f'/tmp/vlaw_fit_{name}.wav'
|
||||
render_vlaw(inp, out, args, alpha, beta, c, delta, gamma0)
|
||||
|
||||
if not os.path.exists(out) or os.path.getsize(out) == 0:
|
||||
errs[name] = 999.0
|
||||
continue
|
||||
|
||||
try:
|
||||
ref_sig = corpus.load_mono(ref)
|
||||
out_sig = corpus.load_mono(out)
|
||||
min_len = min(len(ref_sig), len(out_sig))
|
||||
ref_sig = ref_sig[-min_len:]
|
||||
out_sig = out_sig[-min_len:]
|
||||
|
||||
ref_ta = corpus.ta(ref_sig, f)
|
||||
out_ta = corpus.ta(out_sig, f)
|
||||
err_db = corpus.db(out_ta / ref_ta)
|
||||
errs[name] = err_db
|
||||
except Exception as e:
|
||||
print(f"Error on {name}: {e}")
|
||||
errs[name] = 999.0
|
||||
|
||||
# Group stats
|
||||
groups = {}
|
||||
for k, v in errs.items():
|
||||
g = group_key(k)
|
||||
groups.setdefault(g, []).append(v)
|
||||
|
||||
out = {g: float(np.mean(np.abs(v))) for g, v in groups.items()}
|
||||
out['TOTAL'] = float(np.mean(np.abs(list(errs.values()))))
|
||||
return out, errs
|
||||
|
||||
def fit_alpha_beta_c(cases_to_fit):
|
||||
"""Coordinate descent on (α, β, c) for a specific case group."""
|
||||
# For now, grid search
|
||||
best = None
|
||||
best_err = float('inf')
|
||||
|
||||
# Search ranges around current dual(q=0.5) values
|
||||
for alpha in np.linspace(2.5, 4.0, 8):
|
||||
for beta in np.linspace(0.3, 0.7, 8):
|
||||
for c in np.linspace(0.2, 1.0, 8):
|
||||
stats, _ = eval_config(alpha, beta, c, 6.9, 1.79, cases_to_fit)
|
||||
total = stats['TOTAL']
|
||||
if total < best_err:
|
||||
best_err = total
|
||||
best = (alpha, beta, c, stats)
|
||||
print(f" New best: α={alpha:.4f}, β={beta:.4f}, c={c:.4f}, TOTAL={total:.4f}")
|
||||
|
||||
return best
|
||||
|
||||
def main():
|
||||
# Build case map by group
|
||||
all_cases = structural_cases()
|
||||
groups = {}
|
||||
for name, inp, args, ref, f in all_cases:
|
||||
g = group_key(name)
|
||||
groups.setdefault(g, []).append(name)
|
||||
|
||||
print("Available groups:", list(groups.keys()))
|
||||
for g, names in groups.items():
|
||||
print(f" {g}: {len(names)} cases")
|
||||
|
||||
# Start with dual group (already calibrated)
|
||||
print("\n=== Testing dual(q=0.5) baseline ===")
|
||||
stats, errs = eval_config(3.2193, 0.4927, 0.5423, 6.9177, 1.79, ['dual'])
|
||||
print(f"Dual stats: {stats}")
|
||||
|
||||
# Now fit for each group
|
||||
for g in ['t1kq', 't1k', 'al', 'res', 'dual']:
|
||||
if g not in groups:
|
||||
continue
|
||||
print(f"\n=== Fitting {g} ===")
|
||||
best = fit_alpha_beta_c([g])
|
||||
if best:
|
||||
alpha, beta, c, stats = best
|
||||
print(f" {g} best: α={alpha:.4f}, β={beta:.4f}, c={c:.4f}")
|
||||
print(f" Stats: {stats}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,233 @@
|
||||
#!/usr/bin/env python3
|
||||
"""fnall.py — safe full-thread INT3 tracer.
|
||||
|
||||
Invariant: every thread is SEIZE+INTERRUPT-stopped BEFORE the breakpoint is
|
||||
armed, so any later clone descends from a traced thread and its SIGTRAPs come
|
||||
to us instead of killing the host.
|
||||
|
||||
Env: FN_ADDR, FN_DUR, FN_MAXHITS
|
||||
"""
|
||||
import ctypes
|
||||
import glob
|
||||
import json
|
||||
import os
|
||||
import signal
|
||||
import struct
|
||||
import numpy as np
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
FN = int(os.environ.get('FN_ADDR', '0x180529FE0'), 16)
|
||||
DUR = float(os.environ.get('FN_DUR', '15'))
|
||||
MAXHITS = int(os.environ.get('FN_MAXHITS', '50'))
|
||||
|
||||
PTRACE_CONT = 7
|
||||
PTRACE_GETREGS = 12
|
||||
PTRACE_SETREGS = 13
|
||||
PTRACE_PEEKDATA = 2
|
||||
PTRACE_POKETEXT = 4
|
||||
PTRACE_SINGLESTEP = 9
|
||||
PTRACE_SEIZE = 0x4206
|
||||
PTRACE_INTERRUPT = 0x4207
|
||||
PTRACE_O_TRACECLONE = 0x00000002
|
||||
|
||||
libc = ctypes.CDLL('libc.so.6', use_errno=True)
|
||||
|
||||
|
||||
class UserRegs(ctypes.Structure):
|
||||
_fields_ = [(n, ctypes.c_ulonglong) for n in (
|
||||
'r15', 'r14', 'r13', 'r12', 'rbp', 'rbx', 'r11', 'r10',
|
||||
'r9', 'r8', 'rax', 'rcx', 'rdx', 'rsi', 'rdi', 'orig_rax',
|
||||
'rip', 'cs', 'eflags', 'rsp', 'ss', 'fs_base', 'gs_base',
|
||||
'ds', 'es', 'fs', 'gs')]
|
||||
|
||||
|
||||
def pt(req, pid, addr=0, data=0):
|
||||
libc.ptrace.restype = ctypes.c_long
|
||||
r = libc.ptrace(req, pid, ctypes.c_void_p(addr), ctypes.c_void_p(data))
|
||||
if r == -1:
|
||||
return None, ctypes.get_errno()
|
||||
return r, 0
|
||||
|
||||
|
||||
def find_host():
|
||||
# proven maps-based finder (same as rendersnap.py)
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
cmd = open(f'/proc/{pid}/cmdline', 'rb').read().replace(b'\0', b' ').decode('utf8', 'replace')
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd:
|
||||
return pid
|
||||
return None
|
||||
def drain_waits():
|
||||
out = []
|
||||
while True:
|
||||
try:
|
||||
pid, status = os.waitpid(-1, os.WSTOPPED | os.WUNTRACED | os.WNOHANG)
|
||||
except ChildProcessError:
|
||||
break
|
||||
if pid == 0:
|
||||
break
|
||||
out.append((pid, status))
|
||||
return out
|
||||
|
||||
|
||||
def main():
|
||||
subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; sleep 1", shell=True)
|
||||
proc = subprocess.Popen(['/usr/bin/reaper', '-nosplash', '-ignoreerrors',
|
||||
'-renderproject', '/home/m/soothe-bt/dual_b1q_0.5.rpp'],
|
||||
stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
host = None
|
||||
t0 = time.time()
|
||||
while time.time() - t0 < 30 and not host:
|
||||
host = find_host()
|
||||
if host is None and time.time() - t0 > 2:
|
||||
# fallback: maps-based
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
cmd = open(f'/proc/{pid}/cmdline', 'rb').read().replace(b'\0', b' ').decode('utf8', 'replace')
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd:
|
||||
host = pid
|
||||
break
|
||||
time.sleep(0.002)
|
||||
if not host:
|
||||
print('NO HOST')
|
||||
return 1
|
||||
print('host %d at %.3fs' % (host, time.time() - t0), flush=True)
|
||||
|
||||
# phase 1: seize main, interrupt, wait stop
|
||||
seized = []
|
||||
r, e = pt(PTRACE_SEIZE, host, 0, PTRACE_O_TRACECLONE)
|
||||
if r is None:
|
||||
print('seize fail', e)
|
||||
return 1
|
||||
seized.append(host)
|
||||
pt(PTRACE_INTERRUPT, host)
|
||||
|
||||
# phase 2: pump events, seize newcomers until set stabilizes
|
||||
stable_until = time.time() + float(os.environ.get('FN_STAB','0.05'))
|
||||
deadline = time.time() + 3.0
|
||||
while time.time() < deadline:
|
||||
for pid, st in drain_waits():
|
||||
pass # they stay stopped; we hold them
|
||||
grew = False
|
||||
for tid_s in glob.glob(f'/proc/{host}/task/*'):
|
||||
tid = int(os.path.basename(tid_s))
|
||||
if tid not in seized:
|
||||
r, e = pt(PTRACE_SEIZE, tid, 0, PTRACE_O_TRACECLONE)
|
||||
if r is not None or e != 3:
|
||||
seized.append(tid)
|
||||
pt(PTRACE_INTERRUPT, tid)
|
||||
grew = True
|
||||
if grew:
|
||||
stable_until = time.time() + 0.5
|
||||
elif time.time() > stable_until:
|
||||
break
|
||||
time.sleep(0.002)
|
||||
print('stopped %d threads' % len(seized), flush=True)
|
||||
|
||||
orig, _ = pt(PTRACE_PEEKDATA, host, FN)
|
||||
cc = (orig & ~0xFF) | 0xCC
|
||||
r, e = pt(PTRACE_POKETEXT, host, FN, cc)
|
||||
if r is None:
|
||||
print('arm fail', e)
|
||||
return 1
|
||||
print('armed %#x' % FN, flush=True)
|
||||
|
||||
log = []
|
||||
hits = 0
|
||||
EVENTS = []
|
||||
for tid in seized:
|
||||
pt(PTRACE_CONT, tid, 0, 0)
|
||||
|
||||
t_end = time.time() + DUR
|
||||
last_resweep = time.time()
|
||||
while hits < MAXHITS and time.time() < t_end:
|
||||
try:
|
||||
pid, status = os.waitpid(-1, os.WSTOPPED | os.WUNTRACED | os.WNOHANG)
|
||||
except ChildProcessError:
|
||||
break
|
||||
EVENTS.append((time.time()-t0, pid, hex(status), status >> 16))
|
||||
if pid == 0:
|
||||
if time.time() - last_resweep > 0.05:
|
||||
last_resweep = time.time()
|
||||
for tid_s in glob.glob(f'/proc/{host}/task/*'):
|
||||
tid = int(os.path.basename(tid_s))
|
||||
if tid not in seized:
|
||||
r, e = pt(PTRACE_SEIZE, tid, 0, PTRACE_O_TRACECLONE)
|
||||
if r is not None or e != 3:
|
||||
seized.append(tid)
|
||||
pt(PTRACE_INTERRUPT, tid)
|
||||
drain_waits()
|
||||
pt(PTRACE_CONT, tid, 0, 0)
|
||||
time.sleep(0.0005)
|
||||
continue
|
||||
sig = status >> 8
|
||||
ev = status >> 16
|
||||
if os.WIFEXITED(status) or os.WIFSIGNALED(status):
|
||||
EVENTS.append((time.time()-t0, pid, hex(status), ev))
|
||||
continue
|
||||
if ev == 3 or ev == 1:
|
||||
pt(PTRACE_CONT, pid, 0, 0)
|
||||
continue
|
||||
if os.WIFSTOPPED(pid) and sig == signal.SIGTRAP and ev == 0:
|
||||
regs = UserRegs()
|
||||
r, _ = pt(PTRACE_GETREGS, pid, 0, ctypes.addressof(regs))
|
||||
if r is None:
|
||||
continue
|
||||
if regs.rip - 1 == FN:
|
||||
ret, _ = pt(PTRACE_PEEKDATA, pid, regs.rsp)
|
||||
rec = dict(ctx=regs.rcx, a2=regs.rdx, cnt=regs.r8 & 0xffffffff,
|
||||
r9=regs.r9 & 0xffffffff, ret=ret,
|
||||
rbx=regs.rbx, r12=regs.r12, r13=regs.r13,
|
||||
r14=regs.r14, r15=regs.r15, rsp=regs.rsp, tid=pid,
|
||||
dump_in=[], dump_out=[], dump_r14=[], dump_rbx=[])
|
||||
# dump arrays referenced by registers (process is stopped)
|
||||
fdm = os.open(f'/proc/{host}/mem', os.O_RDONLY)
|
||||
|
||||
def rdarr(ptr, n=2049):
|
||||
try:
|
||||
b = os.pread(fdm, n * 4, ptr)
|
||||
return np.frombuffer(b, dtype='<f4').astype(np.float32).tolist()
|
||||
except OSError:
|
||||
return []
|
||||
rec['dump_in'] = rdarr(regs.rcx)
|
||||
rec['dump_out'] = rdarr(regs.rdx)
|
||||
if FN != 0x18052dbc0:
|
||||
rec['dump_r14'] = rdarr(regs.r14)
|
||||
os.close(fdm)
|
||||
log.append(rec)
|
||||
hits += 1
|
||||
if hits <= 20:
|
||||
print('HIT ctx=%#x a2=%#x cnt=%#x ret=%#x'
|
||||
% (rec['ctx'], rec['a2'], rec['cnt'], rec['ret']), flush=True)
|
||||
pt(PTRACE_POKETEXT, pid, FN, orig)
|
||||
regs.rip = FN
|
||||
pt(PTRACE_SETREGS, pid, 0, ctypes.addressof(regs))
|
||||
pt(PTRACE_SINGLESTEP, pid, 0, 0)
|
||||
os.waitpid(pid, os.WUNTRACED)
|
||||
pt(PTRACE_POKETEXT, pid, FN, cc)
|
||||
pt(PTRACE_CONT, pid, 0, 0)
|
||||
else:
|
||||
pt(PTRACE_CONT, pid, 0, 0)
|
||||
elif os.WIFSTOPPED(pid):
|
||||
pt(PTRACE_CONT, pid, 0, sig if 0 < sig < 32 else 0)
|
||||
|
||||
pt(PTRACE_POKETEXT, host, FN, orig)
|
||||
print('total hits:', hits)
|
||||
json.dump(dict(log=log, events=EVENTS[:8000], nseized=len(seized)),
|
||||
open('/tmp/opencode/fntrace/allhits.json', 'w'), indent=1)
|
||||
proc.kill()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,257 @@
|
||||
#!/usr/bin/env python3
|
||||
"""fnexec.py — hardware EXEC breakpoints on 529fe0 entry and FIR-loop head.
|
||||
Answers definitively whether the decoded mask chain executes during render."""
|
||||
import ctypes
|
||||
import glob
|
||||
import os
|
||||
import signal
|
||||
import struct
|
||||
import numpy as np
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
DUR = float(os.environ.get('EXEC_DUR', '20'))
|
||||
PTRACE_CONT = 7
|
||||
PTRACE_GETREGS = 12
|
||||
PTRACE_SETREGS = 13
|
||||
PTRACE_PEEKUSER = 3
|
||||
PTRACE_POKEUSER = 6
|
||||
PTRACE_SINGLESTEP = 9
|
||||
PTRACE_SEIZE = 0x4206
|
||||
PTRACE_INTERRUPT = 0x4207
|
||||
PTRACE_O_TRACECLONE = 2
|
||||
|
||||
DR_BASE = 0x350
|
||||
DR7_OFF = DR_BASE + 56
|
||||
# DR0=exec 529fe0, DR1=exec 52b550; RW=00 LEN=00 both; L0,L1 enabled
|
||||
DR7_VAL = 0x00000003
|
||||
|
||||
libc = ctypes.CDLL('libc.so.6', use_errno=True)
|
||||
|
||||
|
||||
class UserRegs(ctypes.Structure):
|
||||
_fields_ = [(n, ctypes.c_ulonglong) for n in (
|
||||
'r15', 'r14', 'r13', 'r12', 'rbp', 'rbx', 'r11', 'r10',
|
||||
'r9', 'r8', 'rax', 'rcx', 'rdx', 'rsi', 'rdi', 'orig_rax',
|
||||
'rip', 'cs', 'eflags', 'rsp', 'ss', 'fs_base', 'gs_base',
|
||||
'ds', 'es', 'fs', 'gs')]
|
||||
|
||||
|
||||
def pt(req, pid, addr=0, data=0):
|
||||
libc.ptrace.restype = ctypes.c_long
|
||||
r = libc.ptrace(req, pid, ctypes.c_void_p(addr), ctypes.c_void_p(data))
|
||||
return None if r == -1 else r
|
||||
|
||||
|
||||
def find_host():
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
cmd = open(f'/proc/{pid}/cmdline', 'rb').read().replace(b'\0', b' ').decode('utf8', 'replace')
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd:
|
||||
return pid
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; "
|
||||
"rm -rf /run/user/1000/yabridge-soothe2_x64-*; sleep 1", shell=True)
|
||||
wav = '/home/m/soothe-bt/dual_b1q_0.5.wav'
|
||||
wt0 = os.path.getmtime(wav) if os.path.exists(wav) else 0
|
||||
proc = subprocess.Popen(['/usr/bin/reaper', '-nosplash', '-ignoreerrors',
|
||||
'-renderproject', '/home/m/soothe-bt/dual_b1q_0.5.rpp'],
|
||||
stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
host = None
|
||||
t0 = time.time()
|
||||
while time.time() - t0 < 30 and not host:
|
||||
host = find_host()
|
||||
time.sleep(0.002)
|
||||
if not host:
|
||||
print('NO HOST')
|
||||
return 1
|
||||
print('host %d at %.2fs' % (host, time.time() - t0), flush=True)
|
||||
fd = os.open(f'/proc/{host}/mem', os.O_RDONLY)
|
||||
|
||||
# EARLY arm: exec watch on DESIGN bodies (inherited by future clones)
|
||||
fd0 = os.open(f'/proc/{host}/mem', os.O_RDONLY)
|
||||
pt(PTRACE_SEIZE, host, 0, PTRACE_O_TRACECLONE)
|
||||
pt(PTRACE_INTERRUPT, host)
|
||||
for _ in range(60):
|
||||
try:
|
||||
wpid, _st = os.waitpid(host, os.WUNTRACED | os.WNOHANG)
|
||||
except ChildProcessError:
|
||||
break
|
||||
if wpid == host:
|
||||
break
|
||||
time.sleep(0.001)
|
||||
pt(PTRACE_POKEUSER, host, DR_BASE + 0, 0x1802A24C0)
|
||||
pt(PTRACE_POKEUSER, host, DR_BASE + 8, 0x1802FA420)
|
||||
pt(PTRACE_POKEUSER, host, DR_BASE + 16, 0x180535A70)
|
||||
pt(PTRACE_POKEUSER, host, DR_BASE + 24, 0x18052D650)
|
||||
pt(PTRACE_POKEUSER, host, DR7_OFF, 0xF)
|
||||
ok0 = pt(PTRACE_PEEKUSER, host, DR7_OFF)
|
||||
print('early arm dr7=%#x' % (ok0 or 0), flush=True)
|
||||
pt(PTRACE_CONT, host, 0, 0)
|
||||
|
||||
# phase B: seize ALL tids NOW and arm exec watches
|
||||
def arm(tid):
|
||||
pt(PTRACE_POKEUSER, tid, DR_BASE + 0, 0x180529FE0)
|
||||
pt(PTRACE_POKEUSER, tid, DR_BASE + 8, 0x18052B550)
|
||||
pt(PTRACE_POKEUSER, tid, DR7_OFF, DR7_VAL)
|
||||
v = pt(PTRACE_PEEKUSER, tid, DR7_OFF)
|
||||
return v is not None and (v & ~0x400) == DR7_VAL
|
||||
|
||||
seized = {host}
|
||||
armed = set()
|
||||
for tid_s in glob.glob(f'/proc/{host}/task/*') or [host]:
|
||||
tid = int(os.path.basename(tid_s))
|
||||
pt(PTRACE_SEIZE, tid, 0, PTRACE_O_TRACECLONE)
|
||||
pt(PTRACE_INTERRUPT, tid)
|
||||
for _ in range(40):
|
||||
try:
|
||||
wpid, _st = os.waitpid(tid, os.WUNTRACED | os.WNOHANG)
|
||||
except ChildProcessError:
|
||||
break
|
||||
if wpid == tid:
|
||||
break
|
||||
time.sleep(0.001)
|
||||
if arm(tid):
|
||||
armed.add(tid)
|
||||
try:
|
||||
pt(PTRACE_CONT, tid, 0, 0)
|
||||
except OSError:
|
||||
pass
|
||||
print('armed %d/%d tids' % (len(armed), len(seized)), flush=True)
|
||||
|
||||
n0 = n1 = 0
|
||||
STOPLOG=[]
|
||||
samples = []
|
||||
t_end = time.time() + DUR
|
||||
last_sweep = 0.0
|
||||
fresh_t = None
|
||||
while time.time() < t_end:
|
||||
now = time.time()
|
||||
if now - last_sweep > 0.03:
|
||||
last_sweep = now
|
||||
for tid_s in glob.glob(f'/proc/{host}/task/*'):
|
||||
tid = int(os.path.basename(tid_s))
|
||||
if tid not in seized:
|
||||
if pt(PTRACE_SEIZE, tid, 0, PTRACE_O_TRACECLONE) is not None:
|
||||
seized.add(tid)
|
||||
pt(PTRACE_INTERRUPT, tid)
|
||||
for _ in range(40):
|
||||
try:
|
||||
wpid, _st = os.waitpid(tid, os.WUNTRACED | os.WNOHANG)
|
||||
except ChildProcessError:
|
||||
break
|
||||
if wpid == tid:
|
||||
break
|
||||
time.sleep(0.001)
|
||||
if arm(tid):
|
||||
armed.add(tid)
|
||||
d0=pt(PTRACE_PEEKUSER,tid,DR_BASE)
|
||||
d7=pt(PTRACE_PEEKUSER,tid,DR7_OFF)
|
||||
print(' tid %d dr0=%#x dr7=%#x'%(tid,d0 or 0,d7 or 0),flush=True)
|
||||
try:
|
||||
pt(PTRACE_CONT, tid, 0, 0)
|
||||
except OSError:
|
||||
pass
|
||||
try:
|
||||
pid, status = os.waitpid(-1, os.WSTOPPED | os.WNOHANG)
|
||||
except ChildProcessError:
|
||||
break
|
||||
if pid == 0:
|
||||
time.sleep(0.0004)
|
||||
continue
|
||||
ent=[round(time.time()-t0,3), pid, hex(status)]
|
||||
if os.WIFSTOPPED(pid) and (status>>8)==5:
|
||||
rg=UserRegs()
|
||||
if pt(PTRACE_GETREGS,pid,0,ctypes.addressof(rg)) is not None:
|
||||
ent+= [rg.rip, pt(PTRACE_PEEKUSER,pid,DR_BASE+48)]
|
||||
# auto-dump arrays on design hits
|
||||
if rg.rip in (0x1802A24C0,0x1802FA420):
|
||||
def dmp(ptr):
|
||||
try:
|
||||
b=os.pread(fd,2049*4,ptr)
|
||||
return np.frombuffer(b,dtype='<f4').astype(np.float32).tolist()
|
||||
except OSError: return []
|
||||
ent.append({'rcx':rg.rcx,'rdx':rg.rdx,
|
||||
'in':dmp(rg.rcx),'out':dmp(rg.rdx)})
|
||||
STOPLOG.append(ent)
|
||||
sig = status >> 8
|
||||
if os.WIFEXITED(status) or os.WIFSIGNALED(status):
|
||||
continue
|
||||
if os.WIFSTOPPED(pid) and sig == signal.SIGTRAP:
|
||||
regs = UserRegs()
|
||||
if pt(PTRACE_GETREGS, pid, 0, ctypes.addressof(regs)) is None:
|
||||
continue
|
||||
rip = regs.rip - (1 if False else 0)
|
||||
if pid not in armed:
|
||||
seized.add(pid)
|
||||
if arm(pid):
|
||||
armed.add(pid)
|
||||
# re-read regs after arming? DR change does not touch GPRs
|
||||
if rip not in (0x180529FE0, 0x18052B550, 0x1802A24C0, 0x1802FA420, 0x180535A70, 0x18052D650):
|
||||
pt(PTRACE_CONT, pid, 0, 0)
|
||||
continue
|
||||
if rip == 0x180529FE0:
|
||||
n0 += 1
|
||||
elif rip == 0x18052B550:
|
||||
n1 += 1
|
||||
rec = dict(which='design' if rip in (0x1802A24C0, 0x1802FA420)
|
||||
else ('529fe0' if rip == 0x180529FE0 else 'loop'),
|
||||
rip=rip, rcx=regs.rcx, rdx=regs.rdx,
|
||||
cnt=regs.r8 & 0xffffffff,
|
||||
t=round(time.time() - t0, 3), tid=pid)
|
||||
# dump band curve (rcx) and scratch (rdx) for design hits
|
||||
if rec['which'] == 'design':
|
||||
def rdarr(ptr, n=2049):
|
||||
try:
|
||||
b = os.pread(fd, n * 4, ptr)
|
||||
return np.frombuffer(b, dtype='<f4').astype(np.float32).tolist()
|
||||
except OSError:
|
||||
return []
|
||||
rec['in'] = rdarr(regs.rcx)
|
||||
rec['out'] = rdarr(regs.rdx)
|
||||
print('DESIGN hit tid=%d rcx=%#x rdx=%#x cnt=%#x in[85]=%g'
|
||||
% (pid, regs.rcx, regs.rdx, rec['cnt'],
|
||||
rec['in'][85] if rec['in'] else -1), flush=True)
|
||||
samples.append(rec)
|
||||
if len(samples) > 400:
|
||||
break
|
||||
# pass exec trap: RF flag suppresses next report
|
||||
pt(PTRACE_POKEUSER, pid, DR_BASE + 48, 0xFFFF0FF0)
|
||||
regs.eflags |= 0x10000
|
||||
pt(PTRACE_SETREGS, pid, 0, ctypes.addressof(regs))
|
||||
pt(PTRACE_CONT, pid, 0, 0)
|
||||
elif os.WIFSTOPPED(pid):
|
||||
if pid not in armed and sig == signal.SIGTRAP:
|
||||
seized.add(pid)
|
||||
if arm(pid):
|
||||
armed.add(pid)
|
||||
pt(PTRACE_CONT, pid, 0, sig if 0 < sig < 32 else 0)
|
||||
if fresh_t is None and os.path.exists(wav) and os.path.getmtime(wav) > wt0:
|
||||
fresh_t = time.time() - t0
|
||||
print('wav fresh at %.2fs' % fresh_t, flush=True)
|
||||
|
||||
fresh = fresh_t is not None
|
||||
print('hits: 529fe0=%d loop=%d render_fresh=%s armed=%d/%d'
|
||||
% (n0, n1, fresh, len(armed), len(seized)))
|
||||
import json
|
||||
json.dump(dict(samples=samples[:300], stops=STOPLOG[:4000]),
|
||||
open('/tmp/opencode/fnexec/hits.json', 'w'), indent=1, default=str)
|
||||
proc.kill()
|
||||
return 0
|
||||
|
||||
|
||||
def rdsp(sp, pid):
|
||||
return None
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
os.makedirs('/tmp/opencode/fnexec', exist_ok=True)
|
||||
sys.exit(main())
|
||||
+224
@@ -0,0 +1,224 @@
|
||||
#!/usr/bin/env python3
|
||||
"""fnhw.py — hardware-breakpoint tracer (DR0) for the yabridge host.
|
||||
Safe for un-traced threads (code is never patched). Auto-arms new threads.
|
||||
|
||||
Env: FN_ADDR (target VA), FN_DUR (seconds), FN_SKIP (skip first N hits)
|
||||
"""
|
||||
import ctypes
|
||||
import glob
|
||||
import json
|
||||
import os
|
||||
import signal
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
FN = int(os.environ.get('FN_ADDR', '0x180529FE0'), 16)
|
||||
DUR = float(os.environ.get('FN_DUR', '15'))
|
||||
|
||||
PTRACE_CONT = 7
|
||||
PTRACE_GETREGS = 12
|
||||
PTRACE_SETREGS = 13
|
||||
PTRACE_PEEKUSER = 3
|
||||
PTRACE_POKEUSER = 6
|
||||
PTRACE_SINGLESTEP = 9
|
||||
PTRACE_SEIZE = 0x4206
|
||||
PTRACE_INTERRUPT = 0x4207
|
||||
|
||||
libc = ctypes.CDLL('libc.so.6', use_errno=True)
|
||||
|
||||
|
||||
class UserRegs(ctypes.Structure):
|
||||
_fields_ = [(n, ctypes.c_ulonglong) for n in (
|
||||
'r15', 'r14', 'r13', 'r12', 'rbp', 'rbx', 'r11', 'r10',
|
||||
'r9', 'r8', 'rax', 'rcx', 'rdx', 'rsi', 'rdi', 'orig_rax',
|
||||
'rip', 'cs', 'eflags', 'rsp', 'ss', 'fs_base', 'gs_base',
|
||||
'ds', 'es', 'fs', 'gs')]
|
||||
|
||||
|
||||
def pt(req, pid, addr=0, data=0):
|
||||
libc.ptrace.restype = ctypes.c_long
|
||||
r = libc.ptrace(req, pid, ctypes.c_void_p(addr), ctypes.c_void_p(data))
|
||||
if r == -1:
|
||||
return None, ctypes.get_errno()
|
||||
return r, 0
|
||||
|
||||
|
||||
def find_host():
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
cmd = open(f'/proc/{pid}/cmdline', 'rb').read().replace(b'\0', b' ').decode('utf8', 'replace')
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd:
|
||||
return pid
|
||||
return None
|
||||
|
||||
|
||||
def find_dr0_off(pid):
|
||||
"""Locate DR0 slot inside the USER area by probing."""
|
||||
probe = 0x1234567890abcdef
|
||||
for off in range(0x200, 0x400, 8):
|
||||
r, e = pt(PTRACE_POKEUSER, pid, off, probe)
|
||||
if r is None:
|
||||
continue
|
||||
v, _ = pt(PTRACE_PEEKUSER, pid, off)
|
||||
if v == (probe & 0xFFFFFFFFFFFFFFFF):
|
||||
# restore zero & sanity-check neighbours exist
|
||||
pt(PTRACE_POKEUSER, pid, off, 0)
|
||||
return off
|
||||
return None
|
||||
|
||||
|
||||
def arm(tid, dr0_off):
|
||||
"""Arm DR0/DR7 - requires tid to be STOPPED; caller handles stop/cont."""
|
||||
pt(PTRACE_POKEUSER, tid, dr0_off, FN)
|
||||
# DR7 (index 7): L0=1, RW0=00 (exec), LEN0=00
|
||||
pt(PTRACE_POKEUSER, tid, dr0_off + 7 * 8, 0x1)
|
||||
v, _ = pt(PTRACE_PEEKUSER, tid, dr0_off + 7 * 8)
|
||||
return v == 1
|
||||
|
||||
|
||||
def disarm(tid, dr0_off):
|
||||
pt(PTRACE_POKEUSER, tid, dr0_off + 7 * 8, 0)
|
||||
pt(PTRACE_POKEUSER, tid, dr0_off, 0)
|
||||
|
||||
|
||||
def arm_stopped(tid, dr0_off):
|
||||
"""INTERRUPT -> (bounded) wait -> arm -> CONT. True if DR7 verified."""
|
||||
pt(PTRACE_INTERRUPT, tid)
|
||||
for _ in range(30):
|
||||
try:
|
||||
pid, st = os.waitpid(tid, os.WUNTRACED | os.WNOHANG)
|
||||
except ChildProcessError:
|
||||
return False
|
||||
if pid == tid:
|
||||
break
|
||||
time.sleep(0.002)
|
||||
r0, e0 = pt(PTRACE_POKEUSER, tid, dr0_off, FN)
|
||||
r7, e7 = pt(PTRACE_POKEUSER, tid, dr0_off + 7 * 8, 0x1)
|
||||
v, _ = pt(PTRACE_PEEKUSER, tid, dr0_off + 7 * 8)
|
||||
print(' arm tid=%d poke_dr0=%s(e%s) poke_dr7=%s(e%s) dr7_read=%s'
|
||||
% (tid, 'ok' if r0 is not None else 'FAIL', e0,
|
||||
'ok' if r7 is not None else 'FAIL', e7, hex(v or 0)), flush=True)
|
||||
pt(PTRACE_CONT, tid, 0, 0)
|
||||
return v == 1
|
||||
|
||||
|
||||
def main():
|
||||
subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; sleep 1", shell=True)
|
||||
proc = subprocess.Popen(['/usr/bin/reaper', '-nosplash', '-ignoreerrors',
|
||||
'-renderproject', '/home/m/soothe-bt/dual_b1q_0.5.rpp'],
|
||||
stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
host = None
|
||||
t0 = time.time()
|
||||
while time.time() - t0 < 30 and not host:
|
||||
host = find_host()
|
||||
time.sleep(0.002)
|
||||
if not host:
|
||||
print('NO HOST')
|
||||
return 1
|
||||
print('host %d at %.3fs' % (host, time.time() - t0), flush=True)
|
||||
|
||||
seized = []
|
||||
for tid in [int(os.path.basename(p)) for p in glob.glob(f'/proc/{host}/task/*')] or [host]:
|
||||
if tid not in seized:
|
||||
r, e = pt(PTRACE_SEIZE, tid, 0, 0)
|
||||
if r is not None or e != 3:
|
||||
seized.append(tid)
|
||||
|
||||
# stop one thread briefly to locate DR0 offset
|
||||
tgt = seized[0]
|
||||
pt(PTRACE_INTERRUPT, tgt)
|
||||
os.waitpid(tgt, os.WUNTRACED)
|
||||
dr0_off = find_dr0_off(tgt)
|
||||
print('DR0 user-offset:', hex(dr0_off) if dr0_off else 'NOT FOUND', flush=True)
|
||||
if not dr0_off:
|
||||
return 1
|
||||
pt(PTRACE_CONT, tgt, 0, 0)
|
||||
n_ok = 0
|
||||
for tid in seized:
|
||||
if arm_stopped(tid, dr0_off):
|
||||
n_ok += 1
|
||||
print('armed %#x on %d/%d tids (DR7 verified)' % (FN, n_ok, len(seized)), flush=True)
|
||||
|
||||
log = []
|
||||
hits = 0
|
||||
skip = int(os.environ.get('FN_SKIP', '0'))
|
||||
t_end = time.time() + DUR
|
||||
last_resweep = 0.0
|
||||
while time.time() < t_end:
|
||||
now = time.time()
|
||||
if now - last_resweep > 0.03:
|
||||
last_resweep = now
|
||||
for tid_s in glob.glob(f'/proc/{host}/task/*'):
|
||||
tid = int(os.path.basename(tid_s))
|
||||
if tid not in seized:
|
||||
r, e = pt(PTRACE_SEIZE, tid, 0, 0)
|
||||
if r is not None or e != 3:
|
||||
seized.append(tid)
|
||||
if arm_stopped(tid, dr0_off):
|
||||
print('+tid', tid, flush=True)
|
||||
try:
|
||||
pid, status = os.waitpid(-1, os.WSTOPPED | os.WUNTRACED | os.WNOHANG)
|
||||
except ChildProcessError:
|
||||
break
|
||||
if pid == 0:
|
||||
time.sleep(0.0005)
|
||||
continue
|
||||
sig = status >> 8
|
||||
ev = status >> 16
|
||||
if os.WIFEXITED(status) or os.WIFSIGNALED(status):
|
||||
continue
|
||||
if ev == 3 or ev == 1:
|
||||
pt(PTRACE_CONT, pid, 0, 0)
|
||||
continue
|
||||
if os.WIFSTOPPED(pid) and sig == signal.SIGTRAP:
|
||||
regs = UserRegs()
|
||||
r, _ = pt(PTRACE_GETREGS, pid, 0, ctypes.addressof(regs))
|
||||
if r is None:
|
||||
continue
|
||||
if regs.rip == FN or regs.rip == FN + 1:
|
||||
rip = FN
|
||||
ret, _ = pt(PTRACE_PEEKDATA, pid, regs.rsp)
|
||||
rec = dict(ctx=regs.rcx, a2=regs.rdx, cnt=regs.r8 & 0xffffffff,
|
||||
r9=regs.r9 & 0xffffffff, ret=ret,
|
||||
rbx=regs.rbx, r12=regs.r12, r13=regs.r13,
|
||||
r14=regs.r14, r15=regs.r15, rsp=regs.rsp, tid=pid)
|
||||
if hits >= skip:
|
||||
log.append(rec)
|
||||
print('HIT ctx=%#x a2=%#x cnt=%#x r9d=%#x ret=%#x'
|
||||
% (rec['ctx'], rec['a2'], rec['cnt'], rec['r9'], rec['ret']),
|
||||
flush=True)
|
||||
hits += 1
|
||||
# pass bp: clear DR0 temporarily, single-step, re-arm
|
||||
pt(PTRACE_POKEUSER, pid, dr0_off + 7 * 8, 0)
|
||||
regs.eflags |= 0x100 # TF
|
||||
pt(PTRACE_SETREGS, pid, 0, ctypes.addressof(regs))
|
||||
pt(PTRACE_SINGLESTEP, pid, 0, 0)
|
||||
os.waitpid(pid, os.WUNTRACED)
|
||||
regs2 = UserRegs()
|
||||
pt(PTRACE_GETREGS, pid, 0, ctypes.addressof(regs2))
|
||||
regs2.eflags &= ~0x100
|
||||
pt(PTRACE_SETREGS, pid, 0, ctypes.addressof(regs2))
|
||||
arm(pid, dr0_off)
|
||||
pt(PTRACE_CONT, pid, 0, 0)
|
||||
else:
|
||||
# stray SIGTRAP (wine internal): forward
|
||||
pt(PTRACE_CONT, pid, 0, signal.SIGTRAP)
|
||||
elif os.WIFSTOPPED(pid):
|
||||
pt(PTRACE_CONT, pid, 0, sig if 0 < sig < 32 else 0)
|
||||
|
||||
print('total hits:', hits, 'logged:', len(log))
|
||||
json.dump(log, open('/tmp/opencode/fntrace/hwhits.json', 'w'), indent=1)
|
||||
for tid in seized:
|
||||
disarm(tid, dr0_off)
|
||||
proc.kill()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env python3
|
||||
"""fnsample.py — active RIP sampling of all threads via PTRACE_INTERRUPT
|
||||
during the offline-render burst. Finds which code ACTUALLY executes."""
|
||||
import ctypes
|
||||
import glob
|
||||
import os
|
||||
import signal
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
MOD_LO, MOD_HI = 0x180001000, 0x181baa000
|
||||
DUR = float(os.environ.get('SAMP_DUR', '2.5'))
|
||||
|
||||
PTRACE_CONT = 7
|
||||
PTRACE_GETREGS = 12
|
||||
PTRACE_INTERRUPT = 0x4207
|
||||
PTRACE_SEIZE = 0x4206
|
||||
PTRACE_O_TRACECLONE = 2
|
||||
|
||||
libc = ctypes.CDLL('libc.so.6', use_errno=True)
|
||||
|
||||
|
||||
class UserRegs(ctypes.Structure):
|
||||
_fields_ = [(n, ctypes.c_ulonglong) for n in (
|
||||
'r15', 'r14', 'r13', 'r12', 'rbp', 'rbx', 'r11', 'r10',
|
||||
'r9', 'r8', 'rax', 'rcx', 'rdx', 'rsi', 'rdi', 'orig_rax',
|
||||
'rip', 'cs', 'eflags', 'rsp', 'ss', 'fs_base', 'gs_base',
|
||||
'ds', 'es', 'fs', 'gs')]
|
||||
|
||||
|
||||
def pt(req, pid, addr=0, data=0):
|
||||
libc.ptrace.restype = ctypes.c_long
|
||||
r = libc.ptrace(req, pid, ctypes.c_void_p(addr), ctypes.c_void_p(data))
|
||||
return None if r == -1 else r
|
||||
|
||||
|
||||
def find_host():
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
cmd = open(f'/proc/{pid}/cmdline', 'rb').read().replace(b'\0', b' ').decode('utf8', 'replace')
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd:
|
||||
return pid
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; sleep 1", shell=True)
|
||||
proc = subprocess.Popen(['/usr/bin/reaper', '-nosplash', '-ignoreerrors',
|
||||
'-renderproject', '/home/m/soothe-bt/dual_b1q_0.5.rpp'],
|
||||
stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
host = None
|
||||
t0 = time.time()
|
||||
while time.time() - t0 < 30 and not host:
|
||||
host = find_host()
|
||||
time.sleep(0.002)
|
||||
if not host:
|
||||
print('NO HOST')
|
||||
return 1
|
||||
print('host %d at %.3fs' % (host, time.time() - t0), flush=True)
|
||||
|
||||
seized = {host}
|
||||
pt(PTRACE_SEIZE, host, 0, PTRACE_O_TRACECLONE)
|
||||
pt(PTRACE_CONT, host, 0, 0)
|
||||
|
||||
ips = {}
|
||||
t_end = time.time() + DUR
|
||||
t_start = None
|
||||
nsamp = 0
|
||||
while time.time() < t_end:
|
||||
# resweep tids occasionally
|
||||
for tid_s in glob.glob(f'/proc/{host}/task/*'):
|
||||
tid = int(os.path.basename(tid_s))
|
||||
if tid not in seized:
|
||||
if pt(PTRACE_SEIZE, tid, 0, PTRACE_O_TRACECLONE) is not None:
|
||||
seized.add(tid)
|
||||
for tid in list(seized):
|
||||
if pt(PTRACE_INTERRUPT, tid) is None:
|
||||
continue
|
||||
got = False
|
||||
for _ in range(20):
|
||||
try:
|
||||
pid, status = os.waitpid(tid, os.WUNTRACED | os.WNOHANG)
|
||||
except ChildProcessError:
|
||||
break
|
||||
if pid == tid:
|
||||
got = True
|
||||
break
|
||||
time.sleep(0.0002)
|
||||
if got:
|
||||
regs = UserRegs()
|
||||
if pt(PTRACE_GETREGS, tid, 0, ctypes.addressof(regs)) is not None:
|
||||
nsamp += 1
|
||||
if t_start is None:
|
||||
t_start = time.time()
|
||||
if MOD_LO <= regs.rip < MOD_HI:
|
||||
b = regs.rip >> 4 << 4
|
||||
ips[b] = ips.get(b, 0) + 1
|
||||
pt(PTRACE_CONT, tid, 0, 0)
|
||||
print('samples=%d in-module=%d unique64=%d window=%.2fs..%.2fs'
|
||||
% (nsamp, sum(ips.values()), len(ips),
|
||||
(t_start or t0) - t0, time.time() - t0))
|
||||
core = {a: c for a, c in ips.items() if 0x180520000 <= a < 0x180560000}
|
||||
for a, c in sorted(core.items(), key=lambda x: -x[1])[:18]:
|
||||
print('CORE %#x %d' % (a, c))
|
||||
for b, c in sorted(ips.items(), key=lambda x: -x[1])[:6]:
|
||||
print('%#x %d' % (b, c))
|
||||
proc.kill()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,225 @@
|
||||
#!/usr/bin/env python3
|
||||
"""fntrace.py — ptrace INT3 tracer for FUN_180529fe0 (mask chain vtbl slot 6)
|
||||
in the live yabridge host. The wine module is mapped at its preferred base,
|
||||
so dump VAs == runtime addresses (verified: exec map 0x180001000-0x181baa000).
|
||||
|
||||
On each hit logs: RIP, RCX (ctx), RDX, R8D (count), R9D, [RSP] (return addr),
|
||||
plus xmm0/xmm1 low scalars if available via GETFPREGS (skipped: not portable).
|
||||
|
||||
Usage: python3 scripts/fntrace.py [rpp] [nhits]
|
||||
"""
|
||||
import ctypes
|
||||
import glob
|
||||
import os
|
||||
import signal
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
FN = int(os.environ.get('FN_ADDR', '0x180529FE0'), 16)
|
||||
SNAPDIR = '/tmp/opencode/fntrace'
|
||||
|
||||
PTRACE_TRACEME = 0
|
||||
PTRACE_PEEKTEXT = 1
|
||||
PTRACE_PEEKDATA = 2
|
||||
PTRACE_POKETEXT = 4
|
||||
PTRACE_CONT = 7
|
||||
PTRACE_SINGLESTEP = 9
|
||||
PTRACE_GETREGS = 12
|
||||
PTRACE_SETREGS = 13
|
||||
PTRACE_ATTACH = 16
|
||||
PTRACE_DETACH = 17
|
||||
PTRACE_SEIZE = 0x4206
|
||||
PTRACE_INTERRUPT = 0x4207
|
||||
PTRACE_O_TRACECLONE = 0x00000002
|
||||
PTRACE_EVENT_CLONE = 3 # status >> 16 == 4 (event+1)? actually event = status>>16, CLONE==3 -> 4? use raw compare below
|
||||
PTRACE_EVENT_FORK = 1
|
||||
|
||||
|
||||
class UserRegs(ctypes.Structure):
|
||||
_fields_ = [(n, ctypes.c_ulonglong) for n in (
|
||||
'r15', 'r14', 'r13', 'r12', 'rbp', 'rbx', 'r11', 'r10',
|
||||
'r9', 'r8', 'rax', 'rcx', 'rdx', 'rsi', 'rdi', 'orig_rax',
|
||||
'rip', 'cs', 'eflags', 'rsp', 'ss', 'fs_base', 'gs_base',
|
||||
'ds', 'es', 'fs', 'gs')]
|
||||
|
||||
|
||||
libc = ctypes.CDLL('libc.so.6', use_errno=True)
|
||||
|
||||
|
||||
def ptrace(req, pid, addr=0, data=0):
|
||||
libc.ptrace.restype = ctypes.c_long
|
||||
r = libc.ptrace(req, pid, ctypes.c_void_p(addr), ctypes.c_void_p(data))
|
||||
if r == -1:
|
||||
e = ctypes.get_errno()
|
||||
if req not in (PTRACE_PEEKTEXT, PTRACE_PEEKDATA):
|
||||
raise OSError(e, f'ptrace({req:#x},{pid}) failed')
|
||||
return None
|
||||
return r
|
||||
|
||||
|
||||
def find_host():
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
cmd = open(f'/proc/{pid}/cmdline', 'rb').read().replace(b'\0', b' ').decode('utf8', 'replace')
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd:
|
||||
return pid
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
rpp = sys.argv[1] if len(sys.argv) > 1 else '/home/m/soothe-bt/dual_b1q_0.5.rpp'
|
||||
nhits = int(sys.argv[2]) if len(sys.argv) > 2 else 24
|
||||
render = '--render' in sys.argv
|
||||
os.makedirs(SNAPDIR, exist_ok=True)
|
||||
subprocess.run('pkill -9 -x reaser 2>/dev/null; pkill -9 -x reaper 2>/dev/null; '
|
||||
"pkill -9 -f '[y]abridge' 2>/dev/null; sleep 1", shell=True)
|
||||
if render:
|
||||
proc = subprocess.Popen(
|
||||
['/usr/bin/reaper', '-nosplash', '-ignoreerrors',
|
||||
'-renderproject', rpp],
|
||||
stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
else:
|
||||
proc = subprocess.Popen(
|
||||
['/usr/bin/reaper', '-nosplash', '-ignoreerrors', rpp,
|
||||
'/home/m/re-tools/play_loop.lua'],
|
||||
stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
t0 = time.time()
|
||||
host = None
|
||||
while time.time() - t0 < 60 and not host:
|
||||
host = find_host()
|
||||
time.sleep(0.05)
|
||||
if not host:
|
||||
print('NO HOST')
|
||||
return 1
|
||||
print('host', host, 'at %.1fs' % (time.time() - t0), flush=True)
|
||||
|
||||
tids = [int(os.path.basename(p)) for p in glob.glob(f'/proc/{host}/task/*')]
|
||||
print('tids:', tids, flush=True)
|
||||
|
||||
seized = []
|
||||
for tid in tids:
|
||||
try:
|
||||
ptrace(PTRACE_SEIZE, tid, 0, PTRACE_O_TRACECLONE)
|
||||
seized.append(tid)
|
||||
except OSError as e:
|
||||
print('seize fail', tid, e)
|
||||
if not seized:
|
||||
return 1
|
||||
# stop everyone
|
||||
stopped = []
|
||||
for tid in seized:
|
||||
try:
|
||||
ptrace(PTRACE_INTERRUPT, tid)
|
||||
os.waitpid(tid, os.WUNTRACED)
|
||||
stopped.append(tid)
|
||||
except (OSError, ChildProcessError):
|
||||
pass
|
||||
|
||||
orig = ptrace(PTRACE_PEEKTEXT, stopped[0], FN)
|
||||
cc = (orig & ~0xFF) | 0xCC
|
||||
ptrace(PTRACE_POKETEXT, stopped[0], FN, cc)
|
||||
print('breakpoint armed at %#x (orig=%#x)' % (FN, orig), flush=True)
|
||||
|
||||
for tid in stopped:
|
||||
try:
|
||||
ptrace(PTRACE_CONT, tid, 0, 0)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
hits = 0
|
||||
log = []
|
||||
import select
|
||||
import time as _t
|
||||
t_last = _t.time()
|
||||
idle_deadline = float(os.environ.get('FNTRACE_IDLE', '20'))
|
||||
while hits < nhits and _t.time() - t_last < idle_deadline:
|
||||
try:
|
||||
pid, status = os.waitpid(-1, os.WUNTRACED | os.WSTOPPED | os.WNOHANG)
|
||||
except ChildProcessError:
|
||||
break
|
||||
if pid == 0:
|
||||
_t.sleep(0.005)
|
||||
continue
|
||||
sig = status >> 8
|
||||
if os.WIFEXITED(pid and status or status) or os.WIFSIGNALED(status):
|
||||
# thread/process exited (normal in wine): forget it
|
||||
if pid in seized:
|
||||
seized.remove(pid)
|
||||
if pid in stopped:
|
||||
stopped.remove(pid)
|
||||
continue
|
||||
if not os.WIFSTOPPED(pid):
|
||||
continue
|
||||
t_last = _t.time()
|
||||
ev = status >> 16
|
||||
if ev == PTRACE_EVENT_CLONE or ev == PTRACE_EVENT_FORK:
|
||||
if pid not in seized:
|
||||
seized.append(pid)
|
||||
ptrace(PTRACE_CONT, pid, 0, 0)
|
||||
continue
|
||||
if sig == signal.SIGTRAP:
|
||||
regs = UserRegs()
|
||||
try:
|
||||
ptrace(PTRACE_GETREGS, pid, 0, ctypes.addressof(regs))
|
||||
except OSError:
|
||||
ptrace(PTRACE_CONT, pid, 0, 0)
|
||||
continue
|
||||
if regs.rip - 1 == FN:
|
||||
ret = ptrace(PTRACE_PEEKDATA, pid, regs.rsp)
|
||||
rec = dict(rip=regs.rip - 1, ctx=regs.rcx, a2=regs.rdx,
|
||||
cnt=regs.r8 & 0xffffffff, r9=regs.r9 & 0xffffffff,
|
||||
ret=ret, tid=pid,
|
||||
rbx=regs.rbx, rbp_=regs.rbp, rsi=regs.rsi, rdi=regs.rdi)
|
||||
log.append(rec)
|
||||
hits += 1
|
||||
print(f'hit {hits}: tid={pid} ctx={regs.rcx:#x} '
|
||||
f'a2={regs.rdx:#x} cnt={regs.r8:#x} r9d={regs.r9:#x} '
|
||||
f'ret={ret:#x}', flush=True)
|
||||
# step over int3
|
||||
lo = struct.unpack('<Q', struct.pack('<Q', orig ^ ((orig ^ cc) & 0xFF)))[0]
|
||||
ptrace(PTRACE_POKETEXT, pid, FN, orig)
|
||||
regs.rip = FN
|
||||
ptrace(PTRACE_SETREGS, pid, 0, ctypes.addressof(regs))
|
||||
ptrace(PTRACE_SINGLESTEP, pid, 0, 0)
|
||||
os.waitpid(pid, os.WUNTRACED)
|
||||
ptrace(PTRACE_POKETEXT, pid, FN, cc)
|
||||
ptrace(PTRACE_CONT, pid, 0, 0)
|
||||
else:
|
||||
ptrace(PTRACE_CONT, pid, 0, 0)
|
||||
else:
|
||||
# other stop signals: deliver and continue
|
||||
ptrace(PTRACE_CONT, pid, 0, sig if 0 < sig < 0x20 else 0)
|
||||
|
||||
# cleanup: remove breakpoint, detach
|
||||
print('done hits=', hits, 'cleaning up...', flush=True)
|
||||
for tid in seized:
|
||||
try:
|
||||
ptrace(PTRACE_INTERRUPT, tid)
|
||||
os.waitpid(tid, os.WUNTRACED)
|
||||
except (OSError, ChildProcessError):
|
||||
continue
|
||||
try:
|
||||
ptrace(PTRACE_POKETEXT, stopped[0], FN, orig)
|
||||
except Exception as e:
|
||||
print('restore fail', e)
|
||||
for tid in seized:
|
||||
try:
|
||||
ptrace(PTRACE_DETACH, tid, 0, 0)
|
||||
except OSError:
|
||||
pass
|
||||
import json
|
||||
json.dump(log, open(f'{SNAPDIR}/hits.json', 'w'), indent=1)
|
||||
print('saved', f'{SNAPDIR}/hits.json')
|
||||
if proc.poll() is None:
|
||||
proc.kill()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,195 @@
|
||||
#!/usr/bin/env python3
|
||||
"""fntrace2.py — fast single-point INT3 tracer for the live yabridge host.
|
||||
|
||||
Flow: poll for host spawn (5ms), immediately PTRACE_SEIZE the main thread,
|
||||
poke INT3 at FN (no stop required - word write is atomic), then serve
|
||||
waitpid events (clone children are auto-traced and continued). Logs args at
|
||||
each hit. Works best against `reaper -renderproject` where all DSP work
|
||||
happens in a burst right after host spawn.
|
||||
|
||||
Usage: python3 scripts/fntrace2.py [rpp] [nhits] [--render]
|
||||
Env: FN_ADDR (default 0x180529fe0)
|
||||
"""
|
||||
import ctypes
|
||||
import glob
|
||||
import json
|
||||
import os
|
||||
import signal
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
FN = int(os.environ.get('FN_ADDR', '0x180529FE0'), 16)
|
||||
SNAPDIR = '/tmp/opencode/fntrace'
|
||||
|
||||
PTRACE_CONT = 7
|
||||
PTRACE_GETREGS = 12
|
||||
PTRACE_SETREGS = 13
|
||||
PTRACE_PEEKDATA = 2
|
||||
PTRACE_POKETEXT = 4
|
||||
PTRACE_SINGLESTEP = 9
|
||||
PTRACE_DETACH = 17
|
||||
PTRACE_SEIZE = 0x4206
|
||||
PTRACE_INTERRUPT = 0x4207
|
||||
PTRACE_O_TRACECLONE = 0x00000002
|
||||
|
||||
|
||||
class UserRegs(ctypes.Structure):
|
||||
_fields_ = [(n, ctypes.c_ulonglong) for n in (
|
||||
'r15', 'r14', 'r13', 'r12', 'rbp', 'rbx', 'r11', 'r10',
|
||||
'r9', 'r8', 'rax', 'rcx', 'rdx', 'rsi', 'rdi', 'orig_rax',
|
||||
'rip', 'cs', 'eflags', 'rsp', 'ss', 'fs_base', 'gs_base',
|
||||
'ds', 'es', 'fs', 'gs')]
|
||||
|
||||
|
||||
libc = ctypes.CDLL('libc.so.6', use_errno=True)
|
||||
|
||||
|
||||
def ptrace(req, pid, addr=0, data=0):
|
||||
libc.ptrace.restype = ctypes.c_long
|
||||
r = libc.ptrace(req, pid, ctypes.c_void_p(addr), ctypes.c_void_p(data))
|
||||
if r == -1:
|
||||
e = ctypes.get_errno()
|
||||
if req not in (PTRACE_PEEKDATA,):
|
||||
raise OSError(e, f'ptrace({req:#x},{pid}) failed')
|
||||
return None
|
||||
return r
|
||||
|
||||
|
||||
def find_host():
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
cmd = open(f'/proc/{pid}/cmdline', 'rb').read().replace(b'\0', b' ').decode('utf8', 'replace')
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd:
|
||||
return pid
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
rpp = sys.argv[1] if len(sys.argv) > 1 else '/home/m/soothe-bt/dual_b1q_0.5.rpp'
|
||||
nhits = int(sys.argv[2]) if len(sys.argv) > 2 else 12
|
||||
render = '--render' in sys.argv
|
||||
os.makedirs(SNAPDIR, exist_ok=True)
|
||||
subprocess.run('pkill -9 -x reaser 2>/dev/null; pkill -9 -x reaper 2>/dev/null; '
|
||||
"pkill -9 -f '[y]abridge' 2>/dev/null; sleep 1", shell=True)
|
||||
if render:
|
||||
proc = subprocess.Popen(
|
||||
['/usr/bin/reaper', '-nosplash', '-ignoreerrors',
|
||||
'-renderproject', rpp],
|
||||
stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
else:
|
||||
proc = subprocess.Popen(
|
||||
['/usr/bin/reaper', '-nosplash', '-ignoreerrors', rpp,
|
||||
'/home/m/re-tools/play_loop.lua'],
|
||||
stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
|
||||
host = None
|
||||
t0 = time.time()
|
||||
while time.time() - t0 < 60 and not host:
|
||||
host = find_host()
|
||||
time.sleep(0.005)
|
||||
if not host:
|
||||
print('NO HOST')
|
||||
return 1
|
||||
print('host %d at %.2fs' % (host, time.time() - t0), flush=True)
|
||||
|
||||
ptrace(PTRACE_SEIZE, host, 0, PTRACE_O_TRACECLONE)
|
||||
try:
|
||||
ptrace(PTRACE_INTERRUPT, host)
|
||||
os.waitpid(host, os.WUNTRACED)
|
||||
except (OSError, ChildProcessError) as e:
|
||||
print('interrupt fail', e)
|
||||
orig = ptrace(PTRACE_PEEKDATA, host, FN)
|
||||
cc = (orig & ~0xFF) | 0xCC
|
||||
ptrace(PTRACE_POKETEXT, host, FN, cc)
|
||||
print('armed %#x orig=%#x' % (FN, orig), flush=True)
|
||||
try:
|
||||
ptrace(PTRACE_CONT, host, 0, 0)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
known = {host}
|
||||
log = []
|
||||
hits = 0
|
||||
t_last = time.time()
|
||||
deadline_idle = float(os.environ.get('FNTRACE_IDLE', '25'))
|
||||
while hits < nhits and time.time() - t_last < deadline_idle:
|
||||
try:
|
||||
pid, status = os.waitpid(-1, os.WSTOPPED | os.WUNTRACED)
|
||||
except ChildProcessError:
|
||||
break
|
||||
sig = status >> 8
|
||||
ev = status >> 16
|
||||
known.add(pid)
|
||||
t_last = time.time()
|
||||
if ev == 3 or ev == 1: # CLONE/FORK event stop
|
||||
try:
|
||||
ptrace(PTRACE_CONT, pid, 0, 0)
|
||||
except OSError:
|
||||
pass
|
||||
continue
|
||||
if not os.WIFSTOPPED(pid):
|
||||
continue
|
||||
if sig == signal.SIGTRAP:
|
||||
regs = UserRegs()
|
||||
try:
|
||||
ptrace(PTRACE_GETREGS, pid, 0, ctypes.addressof(regs))
|
||||
except OSError:
|
||||
continue
|
||||
if regs.rip - 1 == FN:
|
||||
ret = ptrace(PTRACE_PEEKDATA, pid, regs.rsp)
|
||||
rec = dict(ctx=regs.rcx, a2=regs.rdx, cnt=regs.r8 & 0xffffffff,
|
||||
r9=regs.r9 & 0xffffffff, ret=ret, rsp=regs.rsp,
|
||||
rbx=regs.rbx, r12=regs.r12, r13=regs.r13,
|
||||
r14=regs.r14, r15=regs.r15, rsi=regs.rsi, rdi=regs.rdi,
|
||||
rip=regs.rip - 1, tid=pid)
|
||||
log.append(rec)
|
||||
hits += 1
|
||||
print('hit %d tid=%d ctx=%#x a2=%#x cnt=%#x r9d=%#x ret=%#x'
|
||||
% (hits, pid, regs.rcx, regs.rdx,
|
||||
regs.r8 & 0xffffffff, regs.r9 & 0xffffffff, ret),
|
||||
flush=True)
|
||||
# step over
|
||||
ptrace(PTRACE_POKETEXT, pid, FN, orig)
|
||||
regs.rip = FN
|
||||
ptrace(PTRACE_SETREGS, pid, 0, ctypes.addressof(regs))
|
||||
ptrace(PTRACE_SINGLESTEP, pid, 0, 0)
|
||||
try:
|
||||
os.waitpid(pid, os.WUNTRACED)
|
||||
except ChildProcessError:
|
||||
pass
|
||||
ptrace(PTRACE_POKETEXT, pid, FN, cc)
|
||||
try:
|
||||
ptrace(PTRACE_CONT, pid, 0, 0)
|
||||
except OSError:
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
ptrace(PTRACE_CONT, pid, 0, 0)
|
||||
except OSError:
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
ptrace(PTRACE_CONT, pid, 0, sig if 0 < sig < 0x20 else 0)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
print('hits:', hits, flush=True)
|
||||
json.dump(log, open(f'{SNAPDIR}/hits.json', 'w'), indent=1)
|
||||
for pid in list(known):
|
||||
try:
|
||||
os.kill(pid, signal.SIGKILL)
|
||||
except OSError:
|
||||
pass
|
||||
proc.kill()
|
||||
print('saved', f'{SNAPDIR}/hits.json')
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,173 @@
|
||||
#!/usr/bin/env python3
|
||||
"""fntrace3.py — decisive INT3 experiment: seize ALL tids within milliseconds
|
||||
of host spawn, arm breakpoint, log EVERY waitpid event for N seconds."""
|
||||
import ctypes
|
||||
import glob
|
||||
import json
|
||||
import os
|
||||
import signal
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
FN = int(os.environ.get('FN_ADDR', '0x180529FE0'), 16)
|
||||
DUR = float(os.environ.get('FN_DUR', '25'))
|
||||
|
||||
PTRACE_CONT = 7
|
||||
PTRACE_GETREGS = 12
|
||||
PTRACE_SETREGS = 13
|
||||
PTRACE_PEEKDATA = 2
|
||||
PTRACE_POKETEXT = 4
|
||||
PTRACE_SINGLESTEP = 9
|
||||
PTRACE_SEIZE = 0x4206
|
||||
PTRACE_INTERRUPT = 0x4207
|
||||
PTRACE_LISTEN = 0x4208
|
||||
PTRACE_O_TRACECLONE = 2
|
||||
|
||||
libc = ctypes.CDLL('libc.so.6', use_errno=True)
|
||||
|
||||
|
||||
class UserRegs(ctypes.Structure):
|
||||
_fields_ = [(n, ctypes.c_ulonglong) for n in (
|
||||
'r15', 'r14', 'r13', 'r12', 'rbp', 'rbx', 'r11', 'r10',
|
||||
'r9', 'r8', 'rax', 'rcx', 'rdx', 'rsi', 'rdi', 'orig_rax',
|
||||
'rip', 'cs', 'eflags', 'rsp', 'ss', 'fs_base', 'gs_base',
|
||||
'ds', 'es', 'fs', 'gs')]
|
||||
|
||||
|
||||
def pt(req, pid, addr=0, data=0):
|
||||
libc.ptrace.restype = ctypes.c_long
|
||||
r = libc.ptrace(req, pid, ctypes.c_void_p(addr), ctypes.c_void_p(data))
|
||||
if r == -1:
|
||||
return None, ctypes.get_errno()
|
||||
return r, 0
|
||||
|
||||
|
||||
def find_host():
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
cmd = open(f'/proc/{pid}/cmdline', 'rb').read().replace(b'\0', b' ').decode('utf8', 'replace')
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd:
|
||||
return pid
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
rpp = '/home/m/soothe-bt/dual_b1q_0.5.rpp'
|
||||
subprocess.run('pkill -9 -x reaper; pkill -9 -f \'[y]abridge\'; sleep 1', shell=True)
|
||||
proc = subprocess.Popen(['/usr/bin/reaper', '-nosplash', '-ignoreerrors',
|
||||
'-renderproject', rpp],
|
||||
stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
host = None
|
||||
t0 = time.time()
|
||||
while time.time() - t0 < 30 and not host:
|
||||
host = find_host()
|
||||
time.sleep(0.002)
|
||||
if not host:
|
||||
print('NO HOST')
|
||||
return 1
|
||||
print('host %d at %.3fs' % (host, time.time() - t0), flush=True)
|
||||
|
||||
seized = []
|
||||
for tid in [host] + [int(os.path.basename(p)) for p in glob.glob(f'/proc/{host}/task/*')]:
|
||||
if tid in seized:
|
||||
continue
|
||||
r, e = pt(PTRACE_SEIZE, tid, 0, PTRACE_O_TRACECLONE)
|
||||
if r is None and e == 3: # ESRCH - gone
|
||||
continue
|
||||
seized.append(tid)
|
||||
# interrupt to allow poke below (poke needs SOME stopped thread)
|
||||
print('seized:', seized, flush=True)
|
||||
# stop one thread to enable POKETEXT
|
||||
tgt = seized[0]
|
||||
pt(PTRACE_INTERRUPT, tgt)
|
||||
os.waitpid(tgt, os.WUNTRACED)
|
||||
orig, _ = pt(PTRACE_PEEKDATA, tgt, FN)
|
||||
cc = (orig & ~0xFF) | 0xCC
|
||||
pt(PTRACE_POKETEXT, tgt, FN, cc)
|
||||
print('armed orig=%#x' % orig, flush=True)
|
||||
# seize any tids spawned meanwhile
|
||||
for tid in [int(os.path.basename(p)) for p in glob.glob(f'/proc/{host}/task/*')]:
|
||||
if tid not in seized:
|
||||
r, e = pt(PTRACE_SEIZE, tid, 0, PTRACE_O_TRACECLONE)
|
||||
if r is not None or e != 3:
|
||||
seized.append(tid)
|
||||
for tid in seized:
|
||||
try:
|
||||
pt(PTRACE_CONT, tid, 0, 0)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
log = []
|
||||
events = []
|
||||
hits = 0
|
||||
t_end = time.time() + DUR
|
||||
last_resweep = 0.0
|
||||
while time.time() < t_end:
|
||||
now = time.time()
|
||||
if now - last_resweep > 0.05:
|
||||
last_resweep = now
|
||||
for tid_s in glob.glob(f'/proc/{host}/task/*'):
|
||||
tid = int(os.path.basename(tid_s))
|
||||
if tid not in seized:
|
||||
r, e = pt(PTRACE_SEIZE, tid, 0, PTRACE_O_TRACECLONE)
|
||||
if r is not None or e != 3:
|
||||
seized.append(tid)
|
||||
print('+tid', tid, flush=True)
|
||||
pid, status = os.waitpid(-1, os.WSTOPPED | os.WUNTRACED | os.WNOHANG)
|
||||
if pid == 0:
|
||||
time.sleep(0.001)
|
||||
continue
|
||||
sig = status >> 8
|
||||
ev = status >> 16
|
||||
events.append((time.time() - t0, pid, hex(status), ev))
|
||||
if pid not in seized:
|
||||
r, e = pt(PTRACE_SEIZE, pid, 0, PTRACE_O_TRACECLONE)
|
||||
if r is not None or e != 3:
|
||||
seized.append(pid)
|
||||
if ev == 3 or ev == 1:
|
||||
pt(PTRACE_CONT, pid, 0, 0)
|
||||
continue
|
||||
if os.WIFSTOPPED(pid) and sig == signal.SIGTRAP:
|
||||
regs = UserRegs()
|
||||
r, _ = pt(PTRACE_GETREGS, pid, 0, ctypes.addressof(regs))
|
||||
if r is None:
|
||||
continue
|
||||
if regs.rip - 1 == FN:
|
||||
ret, _ = pt(PTRACE_PEEKDATA, pid, regs.rsp)
|
||||
rec = dict(ctx=regs.rcx, a2=regs.rdx, cnt=regs.r8 & 0xffffffff,
|
||||
r9=regs.r9 & 0xffffffff, ret=ret, rbx=regs.rbx,
|
||||
r12=regs.r12, r13=regs.r13, r14=regs.r14,
|
||||
r15=regs.r15, rsp=regs.rsp, tid=pid)
|
||||
log.append(rec)
|
||||
hits += 1
|
||||
print('HIT ctx=%#x a2=%#x cnt=%#x ret=%#x'
|
||||
% (regs.rcx, regs.rdx, regs.r8 & 0xffffffff, ret), flush=True)
|
||||
pt(PTRACE_POKETEXT, pid, FN, orig)
|
||||
regs.rip = FN
|
||||
pt(PTRACE_SETREGS, pid, 0, ctypes.addressof(regs))
|
||||
pt(PTRACE_SINGLESTEP, pid, 0, 0)
|
||||
os.waitpid(pid, os.WUNTRACED)
|
||||
pt(PTRACE_POKETEXT, pid, FN, cc)
|
||||
pt(PTRACE_CONT, pid, 0, 0)
|
||||
else:
|
||||
pt(PTRACE_CONT, pid, 0, 0)
|
||||
elif os.WIFEXITED(status) or os.WIFSIGNALED(status):
|
||||
continue
|
||||
else:
|
||||
pt(PTRACE_CONT, pid, 0, sig if 0 < sig < 32 else 0)
|
||||
|
||||
print('total hits:', hits, 'events:', len(events))
|
||||
json.dump(dict(log=log, events=events[:400]),
|
||||
open('/tmp/opencode/fntrace/hits3.json', 'w'), indent=1)
|
||||
proc.kill()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,234 @@
|
||||
#!/usr/bin/env python3
|
||||
"""fnwatch.py — hardware data-watchpoint (DR0 RW) on the live FIR kernel word.
|
||||
Catches whoever READS the built kernel during offline render -> consumer RIP."""
|
||||
import ctypes
|
||||
import glob
|
||||
import os
|
||||
import signal
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
DUR = float(os.environ.get('WATCH_DUR', '20'))
|
||||
BIN = '/home/m/re-tools/soothe_mem.bin'
|
||||
BASE = 0x180000000
|
||||
|
||||
PTRACE_CONT = 7
|
||||
PTRACE_GETREGS = 12
|
||||
PTRACE_SETREGS = 13
|
||||
PTRACE_PEEKUSER = 3
|
||||
PTRACE_POKEUSER = 6
|
||||
PTRACE_SINGLESTEP = 9
|
||||
PTRACE_SEIZE = 0x4206
|
||||
PTRACE_INTERRUPT = 0x4207
|
||||
PTRACE_O_TRACECLONE = 2
|
||||
|
||||
DR0_OFF = 0x350 # empirically verified debugreg base
|
||||
DR7_OFF = DR0_OFF + 56 # 0x388
|
||||
DR7_VAL = 0x000F0001 # L0=1, R/W0=11 (rd/wr), LEN0=11 (4 bytes)
|
||||
|
||||
libc = ctypes.CDLL('libc.so.6', use_errno=True)
|
||||
_mod = open(BIN, 'rb').read()
|
||||
|
||||
|
||||
class UserRegs(ctypes.Structure):
|
||||
_fields_ = [(n, ctypes.c_ulonglong) for n in (
|
||||
'r15', 'r14', 'r13', 'r12', 'rbp', 'rbx', 'r11', 'r10',
|
||||
'r9', 'r8', 'rax', 'rcx', 'rdx', 'rsi', 'rdi', 'orig_rax',
|
||||
'rip', 'cs', 'eflags', 'rsp', 'ss', 'fs_base', 'gs_base',
|
||||
'ds', 'es', 'fs', 'gs')]
|
||||
|
||||
|
||||
def pt(req, pid, addr=0, data=0):
|
||||
libc.ptrace.restype = ctypes.c_long
|
||||
r = libc.ptrace(req, pid, ctypes.c_void_p(addr), ctypes.c_void_p(data))
|
||||
return None if r == -1 else r
|
||||
|
||||
|
||||
def find_host():
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
cmd = open(f'/proc/{pid}/cmdline', 'rb').read().replace(b'\0', b' ').decode('utf8', 'replace')
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd:
|
||||
return pid
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; "
|
||||
"rm -rf /run/user/1000/yabridge-soothe2_x64-*; sleep 1", shell=True)
|
||||
proc = subprocess.Popen(['/usr/bin/reaper', '-nosplash', '-ignoreerrors',
|
||||
'-renderproject', '/home/m/soothe-bt/dual_b1q_0.5.rpp'],
|
||||
stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
host = None
|
||||
t0 = time.time()
|
||||
while time.time() - t0 < 30 and not host:
|
||||
host = find_host()
|
||||
time.sleep(0.002)
|
||||
if not host:
|
||||
print('NO HOST')
|
||||
return 1
|
||||
|
||||
fd = os.open(f'/proc/{host}/mem', os.O_RDONLY)
|
||||
|
||||
def rd(a, n):
|
||||
try:
|
||||
return os.pread(fd, n, a)
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
# find ctx & FIR ptr while running (poll till instance exists)
|
||||
ctx = firptr = None
|
||||
vt = struct.pack('<Q', 0x1824AC210)
|
||||
while time.time() - t0 < 25 and firptr is None:
|
||||
for line in open(f'/proc/{host}/maps'):
|
||||
parts = line.split()
|
||||
if 'rw' not in parts[1]:
|
||||
continue
|
||||
lo, hi = (int(x, 16) for x in parts[0].split('-'))
|
||||
CH = 16 * 1024 * 1024
|
||||
a = lo
|
||||
while a < hi and firptr is None:
|
||||
d = rd(a, min(CH + 4096, hi - a))
|
||||
if not d:
|
||||
break
|
||||
j = d.find(vt)
|
||||
while j >= 0:
|
||||
cand = a + j
|
||||
sb = rd(cand + 0x540870, 4)
|
||||
if sb and struct.unpack('<f', sb)[0] > 100:
|
||||
ctx = cand
|
||||
qb = rd(cand + 0x540668, 8)
|
||||
firptr = struct.unpack('<Q', qb)[0]
|
||||
break
|
||||
j = d.find(vt, j + 1)
|
||||
a += CH
|
||||
if firptr is None:
|
||||
print('NO CTX/FIR')
|
||||
return 1
|
||||
print('host %d ctx %#x fir %#x at %.2fs' % (host, ctx, firptr, time.time() - t0), flush=True)
|
||||
|
||||
seized = {host}
|
||||
armed = set()
|
||||
pt(PTRACE_SEIZE, host, 0, PTRACE_O_TRACECLONE)
|
||||
pt(PTRACE_INTERRUPT, host)
|
||||
for _ in range(60):
|
||||
try:
|
||||
pid, st = os.waitpid(host, os.WUNTRACED | os.WNOHANG)
|
||||
except ChildProcessError:
|
||||
break
|
||||
if pid == host:
|
||||
break
|
||||
time.sleep(0.001)
|
||||
pt(PTRACE_POKEUSER, host, DR0_OFF, 0x18052b8bb)
|
||||
pt(PTRACE_POKEUSER, host, DR7_OFF, DR7_VAL)
|
||||
armed.add(host)
|
||||
print('placeholder armed', flush=True)
|
||||
|
||||
def arm_dbg(tid):
|
||||
pass_off=(0x350,)
|
||||
for off in pass_off:
|
||||
r = pt(PTRACE_POKEUSER, tid, off, 0xdeadbeef if off == DR0_OFF else DR7_VAL)
|
||||
v = pt(PTRACE_PEEKUSER, tid, off)
|
||||
print(' dbg poke %#x -> r=%s read=%#x' % (off, 'ok' if r is not None else 'EIO', v or 0), flush=True)
|
||||
|
||||
def arm(tid):
|
||||
pt(PTRACE_POKEUSER, tid, DR0_OFF, firptr + 43 * 8) # bin43 re (hot word)
|
||||
pt(PTRACE_POKEUSER, tid, DR7_OFF, DR7_VAL)
|
||||
v = pt(PTRACE_PEEKUSER, tid, DR7_OFF)
|
||||
# bit10 of DR7 reads as always-1 (RA1)
|
||||
return v is not None and (v & ~0x400) == (DR7_VAL & ~0x400)
|
||||
|
||||
# stop host briefly to verify arming works at all
|
||||
pt(PTRACE_INTERRUPT, host)
|
||||
for _ in range(50):
|
||||
try:
|
||||
pid, st = os.waitpid(host, os.WUNTRACED | os.WNOHANG)
|
||||
except ChildProcessError:
|
||||
break
|
||||
if pid == host:
|
||||
break
|
||||
time.sleep(0.002)
|
||||
arm_dbg(host)
|
||||
ok = arm(host)
|
||||
print('arm check (stopped):', ok, flush=True)
|
||||
pt(PTRACE_CONT, host, 0, 0)
|
||||
|
||||
if ok:
|
||||
armed.add(host)
|
||||
|
||||
hits = []
|
||||
t_end = time.time() + DUR
|
||||
last_sweep = 0.0
|
||||
while time.time() < t_end:
|
||||
now = time.time()
|
||||
if now - last_sweep > 0.03:
|
||||
last_sweep = now
|
||||
for tid_s in glob.glob(f'/proc/{host}/task/*'):
|
||||
tid = int(os.path.basename(tid_s))
|
||||
if tid not in seized:
|
||||
if pt(PTRACE_SEIZE, tid, 0, 0) is not None:
|
||||
seized.add(tid)
|
||||
if tid not in armed:
|
||||
pt(PTRACE_INTERRUPT, tid)
|
||||
for _ in range(40):
|
||||
try:
|
||||
pid, st = os.waitpid(tid, os.WUNTRACED | os.WNOHANG)
|
||||
except ChildProcessError:
|
||||
break
|
||||
if pid == tid:
|
||||
break
|
||||
time.sleep(0.001)
|
||||
if arm(tid):
|
||||
armed.add(tid)
|
||||
try:
|
||||
pt(PTRACE_CONT, tid, 0, 0)
|
||||
except OSError:
|
||||
pass
|
||||
try:
|
||||
pid, status = os.waitpid(-1, os.WSTOPPED | os.WNOHANG)
|
||||
except ChildProcessError:
|
||||
break
|
||||
if pid == 0:
|
||||
time.sleep(0.0005)
|
||||
continue
|
||||
sig = status >> 8
|
||||
if os.WIFEXITED(status) or os.WIFSIGNALED(status):
|
||||
continue
|
||||
if os.WIFSTOPPED(pid) and sig == signal.SIGTRAP:
|
||||
regs = UserRegs()
|
||||
if pt(PTRACE_GETREGS, pid, 0, ctypes.addressof(regs)) is None:
|
||||
continue
|
||||
rec = dict(rip=regs.rip, rsp=regs.rsp, tid=pid,
|
||||
ret=struct.unpack('<Q', rd(regs.rsp, 8) or b'\0' * 8)[0])
|
||||
hits.append(rec)
|
||||
if len(hits) <= 15:
|
||||
print('WATCH HIT rip=%#x ret=%#x' % (rec['rip'], rec['ret']), flush=True)
|
||||
# pass trap: clear DR6 (poke 0xffff0ff0), single-step, continue
|
||||
pt(PTRACE_POKEUSER, pid, DR0_OFF + 48, 0xFFFF0FF0) # reset DR6
|
||||
regs.eflags |= 0x100
|
||||
pt(PTRACE_SETREGS, pid, 0, ctypes.addressof(regs))
|
||||
pt(PTRACE_SINGLESTEP, pid, 0, 0)
|
||||
try:
|
||||
os.waitpid(pid, os.WUNTRACED)
|
||||
except ChildProcessError:
|
||||
pass
|
||||
pt(PTRACE_CONT, pid, 0, 0)
|
||||
elif os.WIFSTOPPED(pid):
|
||||
pt(PTRACE_CONT, pid, 0, sig if 0 < sig < 32 else 0)
|
||||
|
||||
print('total watch hits:', len(hits))
|
||||
import json
|
||||
json.dump(hits, open('/tmp/opencode/fnwatch/hits.json', 'w'), indent=1, default=str)
|
||||
proc.kill()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
os.makedirs('/tmp/opencode/fnwatch', exist_ok=True)
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,235 @@
|
||||
#!/usr/bin/env python3
|
||||
"""fnwatch4.py — 4 hardware watchpoints simultaneously:
|
||||
DR0/DR1: dwords of the FIR pointer slot ctx+0x540668 (catches loader of ptr)
|
||||
DR2 : kernel word bin43.re
|
||||
DR3 : scratch word bin43
|
||||
RW=read/write (traps readers AND writers), LEN=4B."""
|
||||
import ctypes
|
||||
import glob
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import signal
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
DUR = float(os.environ.get('WATCH_DUR', '20'))
|
||||
PTRACE_CONT = 7
|
||||
PTRACE_GETREGS = 12
|
||||
PTRACE_SETREGS = 13
|
||||
PTRACE_PEEKUSER = 3
|
||||
PTRACE_POKEUSER = 6
|
||||
PTRACE_SEIZE = 0x4206
|
||||
PTRACE_INTERRUPT = 0x4207
|
||||
PTRACE_O_TRACECLONE = 2
|
||||
|
||||
DR_BASE = 0x350 # u_debugreg[0]
|
||||
DR6_OFF = DR_BASE + 48 # 0x388 - wait: idx6=+48 -> that IS DR6 slot? no:
|
||||
# u_debugreg[0..7]: DR0@+0, DR1@+8, DR2@+16, DR3@+24, DR4@+32, DR5@+40,
|
||||
# DR6@+48, DR7@+56
|
||||
DR7_OFF = DR_BASE + 56
|
||||
DR7_VAL = 0xFFFF000F # L0-3 enabled, all RW=11, all LEN=11 (4B)
|
||||
|
||||
libc = ctypes.CDLL('libc.so.6', use_errno=True)
|
||||
|
||||
|
||||
class UserRegs(ctypes.Structure):
|
||||
_fields_ = [(n, ctypes.c_ulonglong) for n in (
|
||||
'r15', 'r14', 'r13', 'r12', 'rbp', 'rbx', 'r11', 'r10',
|
||||
'r9', 'r8', 'rax', 'rcx', 'rdx', 'rsi', 'rdi', 'orig_rax',
|
||||
'rip', 'cs', 'eflags', 'rsp', 'ss', 'fs_base', 'gs_base',
|
||||
'ds', 'es', 'fs', 'gs')]
|
||||
|
||||
|
||||
def pt(req, pid, addr=0, data=0):
|
||||
libc.ptrace.restype = ctypes.c_long
|
||||
r = libc.ptrace(req, pid, ctypes.c_void_p(addr), ctypes.c_void_p(data))
|
||||
return None if r == -1 else r
|
||||
|
||||
|
||||
def find_host():
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
cmd = open(f'/proc/{pid}/cmdline', 'rb').read().replace(b'\0', b' ').decode('utf8', 'replace')
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd:
|
||||
return pid
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; "
|
||||
"rm -rf /run/user/1000/yabridge-soothe2_x64-*; sleep 1", shell=True)
|
||||
rpp = '/home/m/soothe-bt/dual_b1q_0.5.rpp'
|
||||
wav = rpp.replace('.rpp', '.wav')
|
||||
wt0 = os.path.getmtime(wav) if os.path.exists(wav) else 0
|
||||
proc = subprocess.Popen(['/usr/bin/reaper', '-nosplash', '-ignoreerrors',
|
||||
'-renderproject', rpp],
|
||||
stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
host = None
|
||||
t0 = time.time()
|
||||
while time.time() - t0 < 30 and not host:
|
||||
host = find_host()
|
||||
time.sleep(0.002)
|
||||
if not host:
|
||||
print('NO HOST')
|
||||
return 1
|
||||
|
||||
fd = os.open(f'/proc/{host}/mem', os.O_RDONLY)
|
||||
|
||||
def rd(a, n):
|
||||
try:
|
||||
return os.pread(fd, n, a)
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
ctx = firptr = scrptr = None
|
||||
vt = struct.pack('<Q', 0x1824AC210)
|
||||
while time.time() - t0 < 25 and firptr is None:
|
||||
for line in open(f'/proc/{host}/maps'):
|
||||
parts = line.split()
|
||||
if 'rw' not in parts[1]:
|
||||
continue
|
||||
lo, hi = (int(x, 16) for x in parts[0].split('-'))
|
||||
CH = 16 * 1024 * 1024
|
||||
a = lo
|
||||
while a < hi and firptr is None:
|
||||
d = rd(a, min(CH + 4096, hi - a))
|
||||
if not d:
|
||||
break
|
||||
j = d.find(vt)
|
||||
while j >= 0:
|
||||
cand = a + j
|
||||
sb = rd(cand + 0x540870, 4)
|
||||
if sb and struct.unpack('<f', sb)[0] > 100:
|
||||
ctx = cand
|
||||
firptr = struct.unpack('<Q', rd(cand + 0x540668, 8))[0]
|
||||
scrptr = struct.unpack('<Q', rd(cand + 0x540628, 8))[0] or firptr
|
||||
break
|
||||
j = d.find(vt, j + 1)
|
||||
a += CH
|
||||
if firptr is None:
|
||||
print('NO CTX')
|
||||
return 1
|
||||
print('host %d ctx %#x fir %#x scr %#x at %.2fs' %
|
||||
(host, ctx, firptr, scrptr, time.time() - t0), flush=True)
|
||||
|
||||
seized = {host}
|
||||
armed = set()
|
||||
pt(PTRACE_SEIZE, host, 0, PTRACE_O_TRACECLONE)
|
||||
|
||||
def arm(tid):
|
||||
okall = True
|
||||
ovf = struct.unpack('<Q', rd(ctx + 0x5406f8, 8))[0]
|
||||
trk = struct.unpack('<Q', rd(ctx + 0x540768, 8))[0]
|
||||
rax = struct.unpack('<Q', rd(ctx + 0x5407f8, 8))[0]
|
||||
targets = [(DR_BASE + 0, ovf + 8192),
|
||||
(DR_BASE + 8, trk + 43 * 4),
|
||||
(DR_BASE + 16, rax + 43 * 4),
|
||||
(DR_BASE + 24, ctx + 0x2404dc)]
|
||||
for off, addr in targets:
|
||||
pt(PTRACE_POKEUSER, tid, off, addr)
|
||||
v = pt(PTRACE_PEEKUSER, tid, off)
|
||||
if v != addr:
|
||||
okall = False
|
||||
pt(PTRACE_POKEUSER, tid, DR7_OFF, DR7_VAL)
|
||||
return okall
|
||||
|
||||
pt(PTRACE_INTERRUPT, host)
|
||||
for _ in range(60):
|
||||
try:
|
||||
pid, st = os.waitpid(host, os.WUNTRACED | os.WNOHANG)
|
||||
except ChildProcessError:
|
||||
break
|
||||
if pid == host:
|
||||
break
|
||||
time.sleep(0.001)
|
||||
ok = arm(host)
|
||||
print('arm(host)=%s' % ok, flush=True)
|
||||
pt(PTRACE_CONT, host, 0, 0)
|
||||
if ok:
|
||||
armed.add(host)
|
||||
|
||||
hits = []
|
||||
t_end = time.time() + DUR
|
||||
last_sweep = 0.0
|
||||
while time.time() < t_end:
|
||||
now = time.time()
|
||||
if now - last_sweep > 0.03:
|
||||
last_sweep = now
|
||||
for tid_s in glob.glob(f'/proc/{host}/task/*'):
|
||||
tid = int(os.path.basename(tid_s))
|
||||
if tid not in seized:
|
||||
if pt(PTRACE_SEIZE, tid, 0, PTRACE_O_TRACECLONE) is not None:
|
||||
seized.add(tid)
|
||||
pt(PTRACE_INTERRUPT, tid)
|
||||
for _ in range(40):
|
||||
try:
|
||||
wpid, _st = os.waitpid(tid, os.WUNTRACED | os.WNOHANG)
|
||||
except ChildProcessError:
|
||||
break
|
||||
if wpid == tid:
|
||||
break
|
||||
time.sleep(0.001)
|
||||
if arm(tid):
|
||||
armed.add(tid)
|
||||
try:
|
||||
pt(PTRACE_CONT, tid, 0, 0)
|
||||
except OSError:
|
||||
pass
|
||||
try:
|
||||
pid, status = os.waitpid(-1, os.WSTOPPED | os.WNOHANG)
|
||||
except ChildProcessError:
|
||||
break
|
||||
if pid == 0:
|
||||
time.sleep(0.0005)
|
||||
continue
|
||||
sig = status >> 8
|
||||
if os.WIFEXITED(status) or os.WIFSIGNALED(status):
|
||||
continue
|
||||
if os.WIFSTOPPED(pid) and sig == signal.SIGTRAP:
|
||||
regs = UserRegs()
|
||||
if pt(PTRACE_GETREGS, pid, 0, ctypes.addressof(regs)) is None:
|
||||
continue
|
||||
dr6v = pt(PTRACE_PEEKUSER, pid, DR_BASE + 48)
|
||||
rec = dict(rip=regs.rip, rsp=regs.rsp, tid=pid,
|
||||
dr6=dr6v,
|
||||
ret=struct.unpack('<Q', rd(regs.rsp, 8) or b'\0' * 8)[0])
|
||||
hits.append(rec)
|
||||
if len(hits) <= 20:
|
||||
print('HIT rip=%#x ret=%#x dr6=%#x'
|
||||
% (rec['rip'], rec['ret'], dr6v or 0), flush=True)
|
||||
# clear DR6 and single-step past
|
||||
pt(PTRACE_POKEUSER, pid, DR_BASE + 48, 0xFFFF0FF0)
|
||||
regs.eflags |= 0x100
|
||||
pt(PTRACE_SETREGS, pid, 0, ctypes.addressof(regs))
|
||||
pt(PTRACE_SINGLESTEP, pid, 0, 0)
|
||||
try:
|
||||
os.waitpid(pid, os.WUNTRACED)
|
||||
except ChildProcessError:
|
||||
pass
|
||||
pt(PTRACE_CONT, pid, 0, 0)
|
||||
elif os.WIFSTOPPED(pid):
|
||||
pt(PTRACE_CONT, pid, 0, sig if 0 < sig < 32 else 0)
|
||||
|
||||
if not hasattr(main, '_wv') and os.path.exists(wav) and os.path.getmtime(wav) > wt0:
|
||||
main._wv = True
|
||||
print('wav fresh at %.2fs' % (time.time() - t0), flush=True)
|
||||
if not hasattr(main, '_wv'):
|
||||
main._wv = False
|
||||
fresh = main._wv
|
||||
print('hits=%d render_fresh=%s armed=%d/%d' % (len(hits), fresh, len(armed), len(seized)))
|
||||
json.dump(hits[:200], open('/tmp/opencode/fnwatch/hits4.json', 'w'),
|
||||
indent=1, default=str)
|
||||
proc.kill()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
os.makedirs('/tmp/opencode/fnwatch', exist_ok=True)
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env python3
|
||||
"""g_s12 pipeline: clean render ref + deepest scratch capture + render48k tract.
|
||||
Then compute implied-res vs our-res for the frontend clamp analysis."""
|
||||
import subprocess, os, sys, time, glob
|
||||
import numpy as np
|
||||
|
||||
def find_host():
|
||||
import glob as g
|
||||
for p in g.glob('/proc/[0-9]*'):
|
||||
pid=int(os.path.basename(p))
|
||||
try:
|
||||
cmd=open(f'/proc/{pid}/cmdline','rb').read().replace(b'\0',b' ').decode('utf8','replace')
|
||||
maps=open(f'/proc/{pid}/maps').read()
|
||||
except Exception: continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd: return pid
|
||||
return None
|
||||
|
||||
def sh(cmd):
|
||||
return subprocess.run(cmd,shell=True,capture_output=True,text=True).stdout
|
||||
|
||||
sh("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; "
|
||||
"rm -rf /run/user/1000/yabridge-soothe2_x64-*; sleep 1")
|
||||
|
||||
# 1. clean ref render
|
||||
wav='/tmp/opencode/g_s12_ref.wav'
|
||||
if os.path.exists(wav): os.remove(wav)
|
||||
pr=subprocess.Popen(['/usr/bin/reaper','-nosplash','-ignoreerrors','-renderproject','/tmp/opencode/g_s12.rpp'],
|
||||
stdout=subprocess.DEVNULL,stderr=subprocess.STDOUT)
|
||||
t0=time.time(); host=None
|
||||
while time.time()-t0<30 and not host: host=find_host(); time.sleep(0.002)
|
||||
print('host',host)
|
||||
for _ in range(300):
|
||||
if pr.poll() is not None: break
|
||||
time.sleep(0.1)
|
||||
for _ in range(50):
|
||||
if pr.poll() is not None: break
|
||||
time.sleep(0.1)
|
||||
print('ref done rc=',pr.poll())
|
||||
|
||||
# 2. deepest scratch capture
|
||||
sh("pkill -9 -x reaper; sleep 1; rm -rf /tmp/opencode/sc_g_s12")
|
||||
r=sh('cd /home/m/re-tools && timeout 60 python3 scripts/rendersnap2.py /tmp/opencode/g_s12.rpp 400 /tmp/opencode/sc_g_s12')
|
||||
print('capture tail:',r.strip().splitlines()[-1] if r.strip() else 'empty')
|
||||
|
||||
# 3. render48k tract (same input tone1k, band fc1000 q1 s12)
|
||||
tf='/tmp/opencode/tract_g_s12.txt'
|
||||
if os.path.exists(tf): os.remove(tf)
|
||||
env=dict(os.environ); env['RT_DUMP_BIN']=tf
|
||||
subprocess.run(['/home/m/re-tools/dsp/build/render48k','/home/m/soothe-bt/tone1k.wav',
|
||||
'/tmp/o48_g.wav','1000,1.0,12'],capture_output=True,env=e if False else env)
|
||||
print('tract done')
|
||||
|
||||
# 4. analysis
|
||||
import wave
|
||||
def loadwav(p):
|
||||
w=wave.open(p,'rb'); n=w.getnframes(); ch=w.getnchannels(); sw=w.getsampwidth()
|
||||
d=w.readframes(n); w.close()
|
||||
if sw==2: return np.frombuffer(d,dtype=np.int16).astype(np.float64).reshape(-1,ch).mean(1)/32768
|
||||
raw=np.frombuffer(d,dtype=np.uint8).reshape(-1,ch,3)
|
||||
s=raw[:,:,0].astype(np.int64)|(raw[:,:,1].astype(np.int64)<<8)|(raw[:,:,2].astype(np.int64)<<16)
|
||||
return np.where(s>=0x800000,s-0x1000000,s).astype(np.float64).reshape(-1,ch).mean(1)/8388608
|
||||
def ta(x,f,sr=44100):
|
||||
x=x[-int(0.75*sr):]; t=np.arange(len(x))/sr; w=2*np.pi*f
|
||||
return np.hypot(2*np.sum(x*np.cos(w*t))/len(x), 2*np.sum(x*np.sin(w*t))/len(x))
|
||||
def db(a): return 20*np.log10(max(a,1e-12))
|
||||
|
||||
inp=loadwav('/home/m/soothe-bt/tone1k.wav')
|
||||
ref=loadwav(wav)
|
||||
rcut=-db(ta(ref,1000)/ta(inp,1000))
|
||||
|
||||
best=None
|
||||
for fn in sorted(glob.glob('/tmp/opencode/sc_g_s12/ph*.npz')):
|
||||
d=np.load(fn)
|
||||
if '0x540628' not in d.files: continue
|
||||
s=d['0x540628'].astype(np.float64)
|
||||
if best is None or s[85]<best[0]: best=(s[85],s)
|
||||
cutD=-best[0]*8.685889638 if best else float('nan')
|
||||
|
||||
lv=res85=None
|
||||
for ln in open(tf):
|
||||
if ln.startswith('#'): continue
|
||||
p=ln.split()
|
||||
if int(p[0])==85: lv=float(p[3]); res85=float(p[2])
|
||||
|
||||
alpha,beta,c=3.2193,0.4927,0.5423 # dual constants
|
||||
li=beta*np.expm1((cutD-c)/alpha)
|
||||
print('\n=== fc1000 q1 SENS12 (недостающая точка) ===')
|
||||
print('our lvl@85=%.3f res@85=%.5f' % (lv,res85))
|
||||
print('scratch cut_D=%.2f dB' % cutD)
|
||||
print('law-inverse impl lvl=%.3f -> implied res=%.5f' % (li, 0.7307*3.2309/max(li,1e-9)))
|
||||
print('REF goertzel cut@1000=%.2f dB' % rcut)
|
||||
print('\ncontext: sens18 impl res=0.15244 (плато); ours@s18=0.0284')
|
||||
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env python3
|
||||
"""hotips.py — sample thread RIPs aggressively during the render burst to find
|
||||
which module code actually executes (the real DSP path)."""
|
||||
import collections
|
||||
import glob
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
MOD_LO, MOD_HI = 0x180001000, 0x181baa000
|
||||
|
||||
|
||||
def find_host():
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
cmd = open(f'/proc/{pid}/cmdline', 'rb').read().replace(b'\0', b' ').decode('utf8', 'replace')
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd:
|
||||
return pid
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; sleep 1", shell=True)
|
||||
proc = subprocess.Popen(['/usr/bin/reaper', '-nosplash', '-ignoreerrors',
|
||||
'-renderproject', '/home/m/soothe-bt/dual_b1q_0.5.rpp'],
|
||||
stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
host = None
|
||||
t0 = time.time()
|
||||
while time.time() - t0 < 30 and not host:
|
||||
host = find_host()
|
||||
time.sleep(0.002)
|
||||
print('host', host, 'at %.3fs' % (time.time() - t0))
|
||||
ips = collections.Counter()
|
||||
t_end = time.time() + float(os.environ.get('HOT_DUR', '6'))
|
||||
n_ok = n_fail = 0
|
||||
while time.time() < t_end:
|
||||
for tid_s in glob.glob(f'/proc/{host}/task/*'):
|
||||
try:
|
||||
parts = open(f'{tid_s}/syscall').read().split()
|
||||
ip = int(parts[-1], 16)
|
||||
n_ok += 1
|
||||
if MOD_LO <= ip < MOD_HI:
|
||||
ips[ip] += 1
|
||||
except Exception:
|
||||
n_fail += 1
|
||||
proc.kill()
|
||||
print('samples ok=%d fail=%d, in-module=%d' % (n_ok, n_fail, sum(ips.values())))
|
||||
# bucket to 64-byte lines, aggregate by function-ish regions
|
||||
agg = collections.Counter()
|
||||
for ip, c in ips.items():
|
||||
agg[(ip >> 6) << 6] += c
|
||||
for addr, c in agg.most_common(40):
|
||||
print('%#x %d' % (addr, c))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,136 @@
|
||||
#!/usr/bin/env python3
|
||||
"""hunt2.py — enumerate ALL soothe2 module instances during offline render.
|
||||
|
||||
Chunk-correct full-heap scan (rendersnap-style) collecting EVERY ctx candidate
|
||||
(vtable 0x1824AC210 or m48 marker), not just the first. Per candidate: sens,
|
||||
fir43/fir171 (via ctx+0x540668 ptr), scalar bank snapshot. Goal: find the
|
||||
GUI/DSP pair (24c/24j): visible instance holds shallow kernel while audio is
|
||||
processed by another instance with the deep one.
|
||||
"""
|
||||
import hashlib
|
||||
import os
|
||||
import signal
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
|
||||
VT = struct.pack('<Q', 0x1824AC210)
|
||||
M48 = struct.pack('<I', 0x473b8000)
|
||||
|
||||
|
||||
def find_host():
|
||||
import glob
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
cmd = open(f'/proc/{pid}/cmdline', 'rb').read().replace(b'\0', b' ').decode('utf8', 'replace')
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd:
|
||||
return pid
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
rpp = sys.argv[1] if len(sys.argv) > 1 else '/tmp/opencode/multi.rpp'
|
||||
subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; "
|
||||
"rm -rf /run/user/1000/yabridge-soothe2_x64-*; sleep 1", shell=True)
|
||||
proc = subprocess.Popen(['/usr/bin/reaper', '-nosplash', '-ignoreerrors',
|
||||
'-renderproject', rpp],
|
||||
stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
t0 = time.time()
|
||||
host = None
|
||||
while time.time() - t0 < 30 and not host:
|
||||
host = find_host()
|
||||
time.sleep(0.001)
|
||||
if not host:
|
||||
print('NO HOST')
|
||||
return 1
|
||||
fd = os.open(f'/proc/{host}/mem', os.O_RDONLY)
|
||||
|
||||
def rd(a, n):
|
||||
try:
|
||||
return os.pread(fd, n, a)
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
def scan_all():
|
||||
found = {}
|
||||
for line in open(f'/proc/{host}/maps'):
|
||||
parts = line.split()
|
||||
if 'rw' not in parts[1]:
|
||||
continue
|
||||
lo, hi = (int(x, 16) for x in parts[0].split('-'))
|
||||
CH = 16 * 1024 * 1024
|
||||
a = lo
|
||||
while a < hi:
|
||||
d = rd(a, min(CH + 4096, hi - a))
|
||||
if not d:
|
||||
break
|
||||
for pat, off in ((VT, 0), (M48, -0x24)):
|
||||
j = d.find(pat)
|
||||
while j >= 0:
|
||||
cand = a + j + off
|
||||
if cand not in found:
|
||||
sb = rd(cand + 0x540870, 4)
|
||||
if sb and struct.unpack('<f', sb)[0] > 100:
|
||||
found[cand] = True
|
||||
j = d.find(pat, j + 1)
|
||||
a += CH
|
||||
return list(found)
|
||||
|
||||
known = {}
|
||||
rounds = 0
|
||||
while time.time() - t0 < 25:
|
||||
rounds += 1
|
||||
try:
|
||||
os.kill(host, signal.SIGSTOP)
|
||||
except ProcessLookupError:
|
||||
break
|
||||
try:
|
||||
cands = scan_all()
|
||||
new = [c for c in cands if c not in known]
|
||||
for c in new:
|
||||
known[c] = rounds
|
||||
pb = rd(c + 0x540668, 8)
|
||||
m43 = m171 = -1
|
||||
if pb:
|
||||
p = struct.unpack('<Q', pb)[0]
|
||||
if p > 0x10000:
|
||||
fb = rd(p, 2049 * 8)
|
||||
if fb:
|
||||
arr = np.frombuffer(fb[:2049 * 8], dtype='<f4')
|
||||
mag = np.hypot(arr[0::2], arr[1::2])
|
||||
m43, m171 = float(mag[43]), float(mag[171])
|
||||
sb = rd(c + 0x540888, 4)
|
||||
s888 = struct.unpack('<f', sb)[0] if sb else -1
|
||||
print('NEW ctx %#x @r%d t=%.2f fir43=%.4f fir171=%.4f s888=%.4f'
|
||||
% (c, rounds, time.time() - t0, m43, m171, s888), flush=True)
|
||||
# status of known ones every round
|
||||
for c in known:
|
||||
pb = rd(c + 0x540668, 8)
|
||||
if pb:
|
||||
p = struct.unpack('<Q', pb)[0]
|
||||
if p > 0x10000:
|
||||
fb = rd(p, 2049 * 8)
|
||||
if fb:
|
||||
arr = np.frombuffer(fb[:2049 * 8], dtype='<f4')
|
||||
mag = np.hypot(arr[0::2], arr[1::2])
|
||||
print(' st ctx %#x t=%.2f fir43=%.4f' % (c, time.time() - t0, mag[43]), flush=True)
|
||||
finally:
|
||||
try:
|
||||
os.kill(host, signal.SIGCONT)
|
||||
except ProcessLookupError:
|
||||
pass
|
||||
time.sleep(0.05)
|
||||
print('total instances: %d' % len(known))
|
||||
proc.kill()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,133 @@
|
||||
#!/usr/bin/env python3
|
||||
"""iat_name.py — resolve imported-function names for bigkernel dispatch targets.
|
||||
Reads runtime IAT values, finds owning module, parses PE exports."""
|
||||
import struct, subprocess, sys, time
|
||||
import glob, os
|
||||
|
||||
BASE=0x180000000
|
||||
data=open('/home/m/re-tools/soothe_mem.bin','rb').read()
|
||||
|
||||
def rd(fd,a,n):
|
||||
try: return os.pread(fd,n,a)
|
||||
except OSError: return None
|
||||
|
||||
def find_host():
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid=int(os.path.basename(p))
|
||||
try:
|
||||
cmd=open('/proc/%d/cmdline'%pid,'rb').read().replace(b'\0',b' ').decode('utf8','replace')
|
||||
maps=open('/proc/%d/maps'%pid).read()
|
||||
except Exception: continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd: return pid
|
||||
return None
|
||||
|
||||
def iat_slot(stub):
|
||||
# pattern: mov rax,[rip+rel] (48 8b 05 rel32)
|
||||
off=stub-BASE
|
||||
b=data[off:off+7]
|
||||
if b[:2]!=b'\x48\x8b': return None
|
||||
rel=struct.unpack('<i',b[2:6])[0]
|
||||
return stub+6+rel
|
||||
|
||||
def pe_exports(path):
|
||||
"""Parse PE export table -> {name: rva}"""
|
||||
try:
|
||||
f=open(path,'rb').read()
|
||||
except Exception:
|
||||
return {}
|
||||
if f[:2]!=b'MZ': return {}
|
||||
pe=struct.unpack('<I',f[0x3c:0x40])[0]
|
||||
if f[pe:pe+4]!=b'PE\0\0': return {}
|
||||
nsec=struct.unpack('<H',f[pe+6:pe+8])[0]
|
||||
optsz=struct.unpack('<H',f[pe+20:pe+22])[0]
|
||||
magic=struct.unpack('<H',f[pe+24:pe+26])[0]
|
||||
ddir=pe+24+(0x70 if magic==0x20b else 0x60)+0*8 # data dir[0]=export
|
||||
exp_rva,exp_sz=struct.unpack('<II',f[ddir:ddir+8])
|
||||
if not exp_rva: return {}
|
||||
# sections
|
||||
secs=[]
|
||||
so=pe+24+optsz
|
||||
for i in range(nsec):
|
||||
s=f[so+i*40:so+i*40+40]
|
||||
va,sz=struct.unpack('<II',s[12:20])
|
||||
raw,rsz=struct.unpack('<II',s[20:28])
|
||||
secs.append((va,sz,raw,rsz))
|
||||
def r2o(rva):
|
||||
for va,sz,raw,rsz in secs:
|
||||
if va<=rva<va+max(sz,rsz): return raw+(rva-va)
|
||||
return None
|
||||
eo=r2o(exp_rva)
|
||||
if eo is None: return {}
|
||||
nnames=struct.unpack('<I',f[eo+24:eo+28])[0]
|
||||
nrva=struct.unpack('<I',f[eo+32:eo+36])[0]
|
||||
names_rva=struct.unpack('<I',f[eo+32+4:eo+32+8])[0]
|
||||
funcs_rva=struct.unpack('<I',f[eo+28:eo+32])[0]
|
||||
no=r2o(names_rva); fo=r2o(funcs_rva)
|
||||
out={}
|
||||
if no is None or fo is None: return {}
|
||||
for i in range(nnames):
|
||||
nrva_i=struct.unpack('<I',f[no+i*4:no+i*4+4])[0]
|
||||
noff=r2o(nrva_i)
|
||||
if noff is None: continue
|
||||
end=f.find(b'\0',noff)
|
||||
nm=f[noff:end].decode('ascii','replace')
|
||||
frva=struct.unpack('<I',f[fo+i*4:fo+i*4+4])[0]
|
||||
out[nm]=frva
|
||||
return out
|
||||
|
||||
subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; "
|
||||
"rm -rf /run/user/1000/yabridge-soothe2_x64-*; sleep 1", shell=True)
|
||||
proc=subprocess.Popen(['/usr/bin/reaper','-nosplash','-ignoreerrors','-renderproject','/tmp/opencode/multi.rpp'],
|
||||
stdout=subprocess.DEVNULL,stderr=subprocess.STDOUT)
|
||||
t0=time.time(); host=None
|
||||
while time.time()-t0<30 and not host:
|
||||
host=find_host(); time.sleep(0.002)
|
||||
print('host',host,flush=True)
|
||||
import signal as sg
|
||||
os.kill(host,sg.SIGSTOP)
|
||||
fd=os.open('/proc/%d/mem'%host,os.O_RDONLY)
|
||||
|
||||
# build module map
|
||||
mods=[]
|
||||
for line in open('/proc/%d/maps'%host):
|
||||
parts=line.split()
|
||||
if len(parts)<6 or 'x' not in parts[1]: continue
|
||||
lo,hi=(int(x,16) for x in parts[0].split('-'))
|
||||
mods.append((lo,hi,parts[5]))
|
||||
print('modules:',len(mods))
|
||||
|
||||
def owner(addr):
|
||||
for lo,hi,path in mods:
|
||||
if lo<=addr<hi: return (lo,addr-lo,path)
|
||||
return None
|
||||
|
||||
targets={}
|
||||
TBL={0x180140b30:0x1826176c8,0x180140b60:0x182617708,0x1801409e0:0x182617508,
|
||||
0x180140ad0:0x182617648,0x180140a40:0x182617588}
|
||||
for stub,tbl in TBL.items():
|
||||
v=rd(fd,tbl+32,8)
|
||||
tgt=struct.unpack('<Q',v)[0] if v else 0
|
||||
# second level: tgt code = mov rax,[rip+rel]; jmp rax -> IAT slot
|
||||
print(' L2: tgt=%x' % tgt, flush=True)
|
||||
if 0x180000000 <= tgt < 0x187000000:
|
||||
off2=tgt-BASE
|
||||
b2=data[off2:off2+7] if 0<=off2<len(data)-7 else rd(tgt,7)
|
||||
if b2[:2]==b'\x48\x8b':
|
||||
rel2=struct.unpack('<i',b2[3:7])[0]
|
||||
slot=tgt+7+rel2
|
||||
print(' L2: b2=%s rel2=%x slot=%x' % (b2.hex(),rel2&0xffffffff,slot), flush=True)
|
||||
fv=rd(fd,slot,8)
|
||||
if fv:
|
||||
tgt=struct.unpack('<Q',fv)[0]
|
||||
else:
|
||||
print(' slot read FAIL',slot,flush=True)
|
||||
else:
|
||||
print(' no mov-rax pattern at %x: %s'%(tgt,b2[:3].hex() if b2 else '-'),flush=True)
|
||||
ow=owner(tgt)
|
||||
print('%x idx4->%x runtime=%x owner=%s' % (stub,tbl,tgt,ow[2] if ow else '?'),flush=True)
|
||||
if ow:
|
||||
lo,rva,path=ow
|
||||
exps=pe_exports(path)
|
||||
best=[nm for nm,r in exps.items() if r==rva]
|
||||
print(' export:',best,flush=True)
|
||||
os.close(fd)
|
||||
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python3
|
||||
"""ilt_resolve.py — resolve ILT dispatch stubs of soothe_mem.bin (raw dump, base 0x180000000).
|
||||
|
||||
Stub pattern (7+7+4 bytes):
|
||||
48 63 05 rel32 mov eax, [rip+rel32] ; slot index (runtime-fixed after reloc)
|
||||
4c 8d 15 rel32 lea r10, [rip+rel32] ; pointer table base
|
||||
41 ff 24 d2 jmp qword ptr [r10+rax*8]
|
||||
|
||||
Resolution (all offline from the dump, post-relocation values):
|
||||
idx_addr = stub + 7 + rel32_a
|
||||
tbl_addr = stub + 14 + rel32_b
|
||||
impl = u64[tbl_addr + idx * 8]
|
||||
|
||||
Usage: ilt_resolve.py [VA ...] (default: FIR-loop + main-loop stub set)
|
||||
"""
|
||||
import struct
|
||||
import sys
|
||||
|
||||
BASE = 0x180000000
|
||||
BIN = '/home/m/re-tools/soothe_mem.bin'
|
||||
_data = open(BIN, 'rb').read()
|
||||
|
||||
|
||||
def rd(va, n):
|
||||
off = va - BASE
|
||||
return _data[off:off + n]
|
||||
|
||||
|
||||
def u32(va):
|
||||
return struct.unpack('<I', rd(va, 4))[0]
|
||||
|
||||
|
||||
def u64(va):
|
||||
return struct.unpack('<Q', rd(va, 8))[0]
|
||||
|
||||
|
||||
def resolve_stub(va):
|
||||
"""Return dict describing the ILT stub at va, or None if pattern mismatch."""
|
||||
b = rd(va, 18)
|
||||
if len(b) < 18 or b[0] != 0x48 or b[1] != 0x63 or b[2] != 0x05:
|
||||
return None
|
||||
rel_a = struct.unpack_from('<i', b, 3)[0]
|
||||
if b[7] != 0x4C or b[8] != 0x8D or b[9] != 0x15:
|
||||
return None
|
||||
rel_b = struct.unpack_from('<i', b, 10)[0]
|
||||
idx_addr = va + 7 + rel_a
|
||||
tbl_addr = va + 14 + rel_b
|
||||
idx = u32(idx_addr)
|
||||
impl = u64(tbl_addr + idx * 8)
|
||||
return dict(stub=va, idx_addr=idx_addr, idx=idx,
|
||||
tbl_addr=tbl_addr, impl=impl)
|
||||
|
||||
|
||||
DEFAULT_STUBS = [
|
||||
# FIR-build loop 52b550..52b8bb
|
||||
0x180002210, # copy scratch->FIR ?
|
||||
0x180002180, # complex-op A/C (float)
|
||||
0x180001bb0, # complex-op A/C (double)
|
||||
0x180001a90, # complex-op B/D (float)
|
||||
0x1800019d0, # complex-op B/D (double)
|
||||
0x180001880, # paired-scalar op 1 (flag branch)
|
||||
0x180001ca0, # paired-scalar op 2 (flag branch)
|
||||
0x180001df0, # final op (float)
|
||||
0x180001f70, # final op (double)
|
||||
# import thunks of 535a70 dispatcher
|
||||
0x180140a10,
|
||||
0x180140a70,
|
||||
# main-loop transforms referenced by BLOCKMAP
|
||||
0x180002030, 0x180001d30, 0x180002270, 0x1800022a0,
|
||||
0x180001970, 0x180001a60, 0x180001850, 0x180002000,
|
||||
0x180001c40, 0x180001fa0, 0x180001940, 0x180001f10,
|
||||
0x180001c70, 0x180001d60, 0x1800019a0, 0x180001a00,
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
args = [int(a, 16) if not a.startswith('0x') else int(a, 0)
|
||||
for a in sys.argv[1:]] or DEFAULT_STUBS
|
||||
print(f'{"stub":>12} {"idx@":>12} {"idx":>4} {"table":>12} {"impl":>12}')
|
||||
rows = []
|
||||
for va in args:
|
||||
r = resolve_stub(va)
|
||||
if r is None:
|
||||
print(f'{va:#12x} PATTERN MISMATCH')
|
||||
continue
|
||||
rows.append(r)
|
||||
print(f'{r["stub"]:#12x} {r["idx_addr"]:#12x} {r["idx"]:4d} '
|
||||
f'{r["tbl_addr"]:#12x} {r["impl"]:#12x}')
|
||||
return rows
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env python3
|
||||
"""mk_dist.py — two-tone spacing series: 500Hz + (500+d)Hz, equal amps."""
|
||||
import wave, numpy as np
|
||||
sr=44100; T=4.0; n=int(sr*T); t=np.arange(n)/sr
|
||||
ph=np.random.default_rng(31).uniform(0,2*np.pi,4)
|
||||
for d_hz in (200,400,750,1500):
|
||||
nm='d%d'%d_hz
|
||||
A=0.4248
|
||||
y=A*np.sin(2*np.pi*500*t+ph[0])+A*np.sin(2*np.pi*(500+d_hz)*t+ph[1])
|
||||
y=np.clip(y,-0.999,0.999)
|
||||
w=wave.open('/tmp/opencode/%s_in.wav'%nm,'wb'); w.setnchannels(1); w.setsampwidth(2); w.setframerate(sr)
|
||||
w.writeframes((y*32767).astype(np.int16).tobytes()); w.close()
|
||||
import re
|
||||
src=open('/tmp/opencode/f0.rpp').read()
|
||||
src=re.sub(r'RENDER_FILE "[^"]*"','RENDER_FILE "/tmp/opencode/%s_ref.wav"'%nm,src)
|
||||
src=src.replace('FILE "/tmp/opencode/f0_in.wav"','FILE "/tmp/opencode/%s_in.wav"'%nm)
|
||||
open('/tmp/opencode/%s.rpp'%nm,'w').write(src)
|
||||
print('distance series ready')
|
||||
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env python3
|
||||
import wave, numpy as np
|
||||
sr=44100; T=4.0; n=int(sr*T); t=np.arange(n)/sr
|
||||
ph=np.random.default_rng(21).uniform(0,2*np.pi,7)
|
||||
for att,nm,f2 in ((0,'far0',4000.),(12,'far12',4000.)):
|
||||
A=0.4248*10**(-att/20)
|
||||
y=A*np.sin(2*np.pi*500*t+ph[0])+A*np.sin(2*np.pi*f2*t+ph[1])
|
||||
for i,f in enumerate((300.,700.,1400.,2800.)):
|
||||
y+=A*10**(-30/20)*np.sin(2*np.pi*f*t+ph[i+2])
|
||||
y=np.clip(y,-0.999,0.999)
|
||||
w=wave.open('/tmp/opencode/%s_in.wav'%nm,'wb'); w.setnchannels(1); w.setsampwidth(2); w.setframerate(sr)
|
||||
w.writeframes((y*32767).astype(np.int16).tobytes()); w.close()
|
||||
import re
|
||||
src=open('/tmp/opencode/f0.rpp').read()
|
||||
src=re.sub(r'RENDER_FILE "[^"]*"','RENDER_FILE "/tmp/opencode/%s_ref.wav"'%nm,src)
|
||||
src=src.replace('FILE "/tmp/opencode/f0_in.wav"','FILE "/tmp/opencode/%s_in.wav"'%nm)
|
||||
open('/tmp/opencode/%s.rpp'%nm,'w').write(src)
|
||||
print('far-pair inputs+rpps ready')
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
"""mk_multi6.py — 6-tone multitone input + rpp clone."""
|
||||
import wave, numpy as np, re
|
||||
sr=44100; T=4.0; n=int(sr*T); t=np.arange(n)/sr
|
||||
tones=(200.,500.,1000.,2000.,4000.,8000.)
|
||||
ph=np.random.default_rng(51).uniform(0,2*np.pi,len(tones))
|
||||
A=0.30 # per-tone amplitude (avoid clip: sum ~0.9 worst case)
|
||||
y=sum(A*np.sin(2*np.pi*f*t+p) for f,p in zip(tones,ph))
|
||||
y=np.clip(y,-0.999,0.999)
|
||||
w=wave.open('/tmp/opencode/multi6_in.wav','wb'); w.setnchannels(1); w.setsampwidth(2); w.setframerate(sr)
|
||||
w.writeframes((y*32767).astype(np.int16).tobytes()); w.close()
|
||||
src=open('/tmp/opencode/t1k_base.rpp').read() # band1 freq will be patched to 500
|
||||
src=re.sub(r'RENDER_FILE "[^"]*"','RENDER_FILE "/tmp/opencode/multi6_ref.wav"',src)
|
||||
src=src.replace('FILE "/home/m/soothe-bt/tone1k.wav"','FILE "/tmp/opencode/multi6_in.wav"')
|
||||
open('/tmp/opencode/multi6.rpp','w').write(src)
|
||||
print('multi6 ready: tones',tones,'amp',A)
|
||||
@@ -0,0 +1,217 @@
|
||||
#!/usr/bin/env python3
|
||||
"""perfbp.py — hardware data-breakpoint via perf_event_open (no ptrace).
|
||||
Watches READS of the live FIR kernel word across all host threads during
|
||||
offline render; collects sampler IPs -> the consumer."""
|
||||
import ctypes
|
||||
import glob
|
||||
import mmap
|
||||
import os
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
PERF_TYPE_BREAKPOINT = 5
|
||||
PERF_SAMPLE_IP = 1 << 0
|
||||
HW_BREAKPOINT_R = 2
|
||||
PERF_RECORD_SAMPLE = 9
|
||||
SYS_perf_event_open = 298
|
||||
IOCTL_ENABLE = 0x2400 # PERF_EVENT_IOC_ENABLE
|
||||
IOC_FLAG_GROUP = 0
|
||||
|
||||
|
||||
class PerfAttr(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('type', ctypes.c_uint32),
|
||||
('size', ctypes.c_uint32),
|
||||
('config', ctypes.uint64 if hasattr(ctypes, 'uint64') else ctypes.c_uint64),
|
||||
('sample_period', ctypes.c_uint64),
|
||||
('sample_type', ctypes.c_uint64),
|
||||
('read_format', ctypes.c_uint64),
|
||||
('flags', ctypes.c_uint64), # bitfield packed: disabled=bit0 ...
|
||||
('wakeup_events', ctypes.c_uint32),
|
||||
('bp_type', ctypes.c_uint32),
|
||||
('bp_addr', ctypes.c_uint64),
|
||||
('bp_len', ctypes.c_uint64),
|
||||
]
|
||||
|
||||
|
||||
libc = ctypes.CDLL('libc.so.6', use_errno=True)
|
||||
|
||||
|
||||
def find_host():
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
cmd = open(f'/proc/{pid}/cmdline', 'rb').read().replace(b'\0', b' ').decode('utf8', 'replace')
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd:
|
||||
return pid
|
||||
return None
|
||||
|
||||
|
||||
def perf_open(tid, addr):
|
||||
a = PerfAttr()
|
||||
a.type = PERF_TYPE_BREAKPOINT
|
||||
a.size = ctypes.sizeof(a)
|
||||
a.config = 0
|
||||
a.sample_period = 1
|
||||
a.sample_type = PERF_SAMPLE_IP
|
||||
a.read_format = 0
|
||||
a.flags = 1 | (1 << 5) # disabled=1, exclude_kernel=1
|
||||
a.wakeup_events = 1
|
||||
a.bp_type = HW_BREAKPOINT_R
|
||||
a.bp_addr = addr
|
||||
a.bp_len = 4
|
||||
libc.syscall.restype = ctypes.c_long
|
||||
r = libc.syscall(ctypes.c_long(SYS_perf_event_open), ctypes.byref(a),
|
||||
ctypes.c_int(tid), ctypes.c_int(-1), ctypes.c_uint(-1),
|
||||
ctypes.c_void_p(0))
|
||||
if r == -1:
|
||||
e = ctypes.get_errno()
|
||||
return None, e
|
||||
return r, 0
|
||||
|
||||
|
||||
def main():
|
||||
subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; "
|
||||
"rm -rf /run/user/1000/yabridge-soothe2_x64-*; sleep 1", shell=True)
|
||||
wav = '/home/m/soothe-bt/dual_b1q_0.5.wav'
|
||||
wt0 = os.path.getmtime(wav) if os.path.exists(wav) else 0
|
||||
proc = subprocess.Popen(['/usr/bin/reaper', '-nosplash', '-ignoreerrors',
|
||||
'-renderproject', '/home/m/soothe-bt/dual_b1q_0.5.rpp'],
|
||||
stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
host = None
|
||||
t0 = time.time()
|
||||
while time.time() - t0 < 30 and not host:
|
||||
host = find_host()
|
||||
time.sleep(0.002)
|
||||
if not host:
|
||||
print('NO HOST')
|
||||
return 1
|
||||
|
||||
fd = os.open(f'/proc/{host}/mem', os.O_RDONLY)
|
||||
|
||||
def rd(a, n):
|
||||
try:
|
||||
return os.pread(fd, n, a)
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
# wait for instance
|
||||
ctx = firptr = None
|
||||
vt = struct.pack('<Q', 0x1824AC210)
|
||||
while time.time() - t0 < 25 and firptr is None:
|
||||
for line in open(f'/proc/{host}/maps'):
|
||||
parts = line.split()
|
||||
if 'rw' not in parts[1]:
|
||||
continue
|
||||
lo, hi = (int(x, 16) for x in parts[0].split('-'))
|
||||
CH = 16 * 1024 * 1024
|
||||
a = lo
|
||||
while a < hi and firptr is None:
|
||||
d = rd(a, min(CH + 4096, hi - a))
|
||||
if not d:
|
||||
break
|
||||
j = d.find(vt)
|
||||
while j >= 0:
|
||||
cand = a + j
|
||||
sb = rd(cand + 0x540870, 4)
|
||||
if sb and struct.unpack('<f', sb)[0] > 100:
|
||||
ctx = cand
|
||||
firptr = struct.unpack('<Q', rd(cand + 0x540668, 8))[0]
|
||||
break
|
||||
j = d.find(vt, j + 1)
|
||||
a += CH
|
||||
if firptr:
|
||||
break
|
||||
print('host %d ctx %#x fir %#x at %.2fs'
|
||||
% (host, ctx or 0, firptr or 0, time.time() - t0), flush=True)
|
||||
if not firptr:
|
||||
return 1
|
||||
watch = firptr + 43 * 8 # bin43 re word
|
||||
|
||||
# attach to all current threads; remember to attach newborns too
|
||||
events = {}
|
||||
errs = {}
|
||||
|
||||
def attach(tid):
|
||||
fde, e = perf_open(tid, watch)
|
||||
if fde is None or fde < 0:
|
||||
errs[e] = errs.get(e, 0) + 1
|
||||
return None
|
||||
events[fde] = tid
|
||||
libc.mmap.restype = ctypes.c_void_p
|
||||
m = libc.mmap(None, 2 * 4096, 1 | 2, 2, fde, 0) # PROT_R|W, MAP_PRIVATE
|
||||
if m in (None, ctypes.c_void_p(-1).value):
|
||||
return None
|
||||
bufs[fde] = (m, (ctypes.c_char * (2 * 4096)).from_address(m))
|
||||
libc.ioctl.argtypes = [ctypes.c_int] * 3 + [ctypes.c_void_p]
|
||||
libc.ioctl(fde, IOCTL_ENABLE, 0)
|
||||
return fde
|
||||
|
||||
bufs = {}
|
||||
# pick top-CPU thread only (minimise BP resource demand)
|
||||
import time as _t
|
||||
def tcpu(tid):
|
||||
try:
|
||||
f = open(f'/proc/{host}/task/{tid}/stat').read().split()
|
||||
return int(f[13]) + int(f[14])
|
||||
except Exception:
|
||||
return -1
|
||||
tids = [int(os.path.basename(p)) for p in glob.glob(f'/proc/{host}/task/*')]
|
||||
c0 = {t: tcpu(t) for t in tids}
|
||||
_t.sleep(0.4)
|
||||
deltas = sorted(((tcpu(t) - c0.get(t, 0), t) for t in tids), reverse=True)
|
||||
target = deltas[0][1] if deltas else host
|
||||
print('target tid=%d cpuΔ=%s all=%s' % (target, deltas[0], deltas[:6]), flush=True)
|
||||
fde = attach(target)
|
||||
n_ok = 1 if fde is not None else 0
|
||||
print('attached %d fds; errno hist=%s' % (n_ok, errs), flush=True)
|
||||
|
||||
# let render run; drain buffers periodically
|
||||
ips = {}
|
||||
DUR = float(os.environ.get('BP_DUR', '12'))
|
||||
t_end = time.time() + DUR
|
||||
fresh_t = None
|
||||
DATA = 4096
|
||||
while time.time() < t_end:
|
||||
time.sleep(0.05)
|
||||
if fresh_t is None and os.path.exists(wav) and os.path.getmtime(wav) > wt0:
|
||||
fresh_t = time.time() - t0
|
||||
print('wav fresh at %.2fs' % fresh_t, flush=True)
|
||||
for fde, (m, arr) in list(bufs.items()):
|
||||
head, tail = struct.unpack_from('<QQ', bytes(arr[:16]), 0)
|
||||
n = head - tail
|
||||
if n == 0:
|
||||
continue
|
||||
blob = bytes(arr[4096:8192])
|
||||
p = tail % DATA
|
||||
consumed = 0
|
||||
while consumed < n:
|
||||
if p + 8 > DATA:
|
||||
p = 0
|
||||
typ, misc, recsz = struct.unpack_from('<IHH', blob, p)
|
||||
if recsz < 8:
|
||||
break
|
||||
rec = blob[p:p + recsz]
|
||||
if typ == PERF_RECORD_SAMPLE and recsz >= 16:
|
||||
ip = struct.unpack_from('<Q', rec, 8)[0]
|
||||
if 0x180001000 <= ip < 0x181baa000:
|
||||
key = ip >> 4 << 4
|
||||
ips[key] = ips.get(key, 0) + 1
|
||||
adv = max(recsz, 8)
|
||||
consumed += adv
|
||||
p = (p + adv) % DATA
|
||||
struct.pack_into('<Q', arr, 8, head)
|
||||
print('distinct ips:', len(ips), 'total:', sum(ips.values()))
|
||||
for a_, c in sorted(ips.items(), key=lambda x: -x[1])[:20]:
|
||||
print('%#x %d' % (a_, c))
|
||||
proc.kill()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
import struct, subprocess, time, os, glob
|
||||
def find_host():
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid=int(os.path.basename(p))
|
||||
try:
|
||||
cmd=open('/proc/%d/cmdline'%pid,'rb').read().replace(b'\0',b' ').decode('utf8','replace')
|
||||
maps=open('/proc/%d/maps'%pid).read()
|
||||
except Exception: continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd: return pid
|
||||
return None
|
||||
subprocess.run("pkill -9 -x reaper; sleep 1; rm -rf /run/user/1000/yabridge-soothe2_x64-*",shell=True)
|
||||
proc=subprocess.Popen(['/usr/bin/reaper','-nosplash','-ignoreerrors','-renderproject','/tmp/opencode/multi.rpp'],
|
||||
stdout=subprocess.DEVNULL,stderr=subprocess.STDOUT)
|
||||
t0=time.time();host=None
|
||||
while time.time()-t0<30 and not host: host=find_host();time.sleep(0.002)
|
||||
print('host',host,flush=True)
|
||||
fd=os.open('/proc/%d/mem'%host,os.O_RDONLY)
|
||||
ctx=0x2370040
|
||||
for k in range(40):
|
||||
try:
|
||||
b=os.pread(fd,8,ctx+0x540668)
|
||||
v=struct.unpack('<Q',b)[0]
|
||||
print('t=%.1f [ctx+540668]=%x' % (time.time()-t0,v), flush=True)
|
||||
except OSError as e:
|
||||
print('read fail',e)
|
||||
time.sleep(0.3)
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
"""probe_lut.py — one-shot probe of [ctx+0x180] LUT params during render."""
|
||||
import struct, subprocess, sys, time
|
||||
import glob, os
|
||||
|
||||
def find_host():
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
cmd = open(f'/proc/{pid}/cmdline','rb').read().replace(b'\0',b' ').decode('utf8','replace')
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd:
|
||||
return pid
|
||||
return None
|
||||
|
||||
subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; "
|
||||
"rm -rf /run/user/1000/yabridge-soothe2_x64-*; sleep 1", shell=True)
|
||||
rpp = sys.argv[1] if len(sys.argv) > 1 else '/home/m/soothe-bt/dual_b1q_0.5.rpp'
|
||||
proc = subprocess.Popen(['/usr/bin/reaper','-nosplash','-ignoreerrors','-renderproject', rpp],
|
||||
stdout=open('/dev/null','w'), stderr=subprocess.STDOUT)
|
||||
t0=time.time(); host=None
|
||||
while time.time()-t0<30 and not host:
|
||||
host=find_host(); time.sleep(0.001)
|
||||
print('host',host, flush=True)
|
||||
if not host:
|
||||
sys.exit(1)
|
||||
fd=os.open(f'/proc/{host}/mem',os.O_RDONLY)
|
||||
def rd(a,n):
|
||||
try: return os.pread(fd,n,a)
|
||||
except OSError: return None
|
||||
ctx=0x2370040
|
||||
best=None
|
||||
while time.time()-t0 < 12:
|
||||
b=rd(ctx+0x180,8)
|
||||
v=struct.unpack('<Q',b)[0] if b else 0
|
||||
if 0x10000 < v < 0x7ffff0000000:
|
||||
s=rd(v,0x18)
|
||||
if s:
|
||||
A,B=struct.unpack('<ff',s[0:8]); G=struct.unpack('<f',s[12:16])[0]
|
||||
m=s[16]
|
||||
q90=rd(v+0x90,8)
|
||||
p90=struct.unpack('<Q',q90)[0] if q90 else 0
|
||||
rec=(A,B,G,m,p90)
|
||||
if best is None or rec!=best:
|
||||
best=rec
|
||||
print('t=%.2f [ctx+180]=%x A=%.6g B=%.6g G=%.6g mode=%d vt90=%x' %
|
||||
(time.time()-t0,v,A,B,G,m,p90), flush=True)
|
||||
else:
|
||||
print('t=%.2f [ctx+180]=%x (not ptr)' % (time.time()-t0,v), flush=True)
|
||||
time.sleep(0.05)
|
||||
os.close(fd)
|
||||
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env python3
|
||||
import struct, subprocess, time, os, glob
|
||||
def find_host():
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid=int(os.path.basename(p))
|
||||
try:
|
||||
cmd=open('/proc/%d/cmdline'%pid,'rb').read().replace(b'\0',b' ').decode('utf8','replace')
|
||||
maps=open('/proc/%d/maps'%pid).read()
|
||||
except Exception: continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd: return pid
|
||||
return None
|
||||
subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; sleep 1; "
|
||||
"rm -rf /run/user/1000/yabridge-soothe2_x64-*", shell=True)
|
||||
proc=subprocess.Popen(['/usr/bin/reaper','-nosplash','-ignoreerrors','-renderproject','/tmp/opencode/multi.rpp'],
|
||||
stdout=subprocess.DEVNULL,stderr=subprocess.STDOUT)
|
||||
t0=time.time();host=None
|
||||
while time.time()-t0<30 and not host: host=find_host();time.sleep(0.002)
|
||||
print('host',host)
|
||||
fd=os.open('/proc/%d/mem'%host,os.O_RDONLY)
|
||||
for addr,nm in ((0x1824ac210,'vtbl'),(0x182617508,'bk-table'),(0x180140ad0,'stub-code'),(0x180533340,'iir-gen')):
|
||||
try:
|
||||
b=os.pread(fd,16,addr)
|
||||
print('%-10s %x OK: %s' % (nm,addr,b[:8].hex()))
|
||||
except OSError as e:
|
||||
print('%-10s %x FAIL: %s' % (nm,addr,e))
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env python3
|
||||
"""probe_states.py — read IIR state headers ([base+8]) for the three
|
||||
FUN_180533340-generated states during render."""
|
||||
import struct, subprocess, sys, time
|
||||
import glob, os
|
||||
|
||||
def find_host():
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid=int(os.path.basename(p))
|
||||
try:
|
||||
cmd=open(f'/proc/{pid}/cmdline','rb').read().replace(b'\0',b' ').decode('utf8','replace')
|
||||
maps=open(f'/proc/{pid}/maps').read()
|
||||
except Exception: continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd: return pid
|
||||
return None
|
||||
|
||||
subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; "
|
||||
"rm -rf /run/user/1000/yabridge-soothe2_x64-*; sleep 1", shell=True)
|
||||
rpp=sys.argv[1] if len(sys.argv)>1 else '/home/m/soothe-bt/dual_b1q_0.5.rpp'
|
||||
proc=subprocess.Popen(['/usr/bin/reaper','-nosplash','-ignoreerrors','-renderproject',rpp],
|
||||
stdout=open('/dev/null','w'),stderr=subprocess.STDOUT)
|
||||
t0=time.time(); host=None
|
||||
while time.time()-t0<30 and not host:
|
||||
host=find_host(); time.sleep(0.002)
|
||||
print('host',host,flush=True)
|
||||
fd=os.open(f'/proc/{host}/mem',os.O_RDONLY)
|
||||
def rd(a,n):
|
||||
try: return os.pread(fd,n,a)
|
||||
except OSError: return None
|
||||
ctx=0x2370040
|
||||
STATES=[('st1',0x2404e8),('st2',0x340500),('st3',0x440518)]
|
||||
seen=set()
|
||||
while time.time()-t0<10:
|
||||
vals=[]
|
||||
for nm,base in STATES:
|
||||
b=rd(ctx+base+8,4)
|
||||
f=struct.unpack('<f',b)[0] if b else float('nan')
|
||||
n=struct.unpack('<i',rd(ctx+base,4) or b'\xff\xff\xff\xff')[0]
|
||||
vals.append((nm,n,f))
|
||||
key=tuple(round(v[2],4) for v in vals)
|
||||
if key not in seen:
|
||||
seen.add(key)
|
||||
print(' '.join('%s:n=%d val=%.6g'%v for v in vals), flush=True)
|
||||
time.sleep(0.05)
|
||||
os.close(fd)
|
||||
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env python3
|
||||
"""qseries.py — run rendersnap across dual_b1q_*.rpp configs, extract steady
|
||||
scratch/FIR at bins 43/171 into one table vs the real cuts from NOTES 22x."""
|
||||
import glob
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
QS = ['0.1', '0.2', '0.3', '0.5', '0.7', '1.0', '1.5', '2.0', '3.0', '5.0', '10.0']
|
||||
REAL = { # from NOTES_LEVEL 22x table: cut@500, cut@2000
|
||||
'0.1': (10.32, 15.33), '0.5': (10.32, 11.82), '1.0': (10.32, 10.78),
|
||||
'3.0': (10.29, 10.32), '10': (9.94, 10.25),
|
||||
}
|
||||
RES2000 = {'0.1': 0.216, '0.5': 0.839, '1.0': 1.353, '3.0': 1.880, '10': 1.988}
|
||||
|
||||
|
||||
def steady_scratch(tag):
|
||||
fs = sorted(glob.glob(f'/tmp/opencode/rendersnap/phase*.npz'))
|
||||
best = None
|
||||
for f in fs[::-1]:
|
||||
z = np.load(f)
|
||||
sc = z['0x540628']
|
||||
if abs(sc[43]) > 1e-6 and abs(sc[171] - sc[43]) > 1e-6 or (abs(sc[43]) > 1e-6):
|
||||
best = (sc[43], sc[171])
|
||||
if abs(sc[171] - sc[43]) > 1e-4:
|
||||
break
|
||||
return best
|
||||
|
||||
|
||||
def main():
|
||||
rows = []
|
||||
for q in QS:
|
||||
rpp = f'/home/m/soothe-bt/dual_b1q_{q}.rpp'
|
||||
if not os.path.exists(rpp):
|
||||
continue
|
||||
subprocess.run(
|
||||
['timeout', '100', 'python3', '/home/m/re-tools/scripts/rendersnap.py',
|
||||
rpp], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
st = steady_scratch(q)
|
||||
if not st:
|
||||
print(q, 'NO DATA')
|
||||
continue
|
||||
s43, s171 = st
|
||||
f43 = -20 * np.log10(np.exp(0.984 * s43))
|
||||
f171 = -20 * np.log10(np.exp(0.984 * s171))
|
||||
rc = REAL.get(q.rstrip('.0') if q.endswith('.0') else q)
|
||||
row = dict(q=q, scr43=round(s43, 4), scr171=round(s171, 4),
|
||||
fir43=round(f43, 2), fir171=round(f171, 2),
|
||||
x18_43=round(f43 * 1.805, 2), x18_171=round(f171 * 1.805, 2))
|
||||
if rc:
|
||||
row['real43'], row['real171'] = rc
|
||||
row['ratio'] = round(rc[0] / f43, 3), round(rc[1] / f171, 3)
|
||||
if q in RES2000:
|
||||
row['res2000'] = RES2000[q]
|
||||
rows.append(row)
|
||||
print(row, flush=True)
|
||||
np.save('/tmp/opencode/qseries.npy', rows, allow_pickle=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Quick VLAW parameter grid search - test fewer combos per case.
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import json
|
||||
|
||||
sys.path.insert(0, '/home/m/re-tools/scripts')
|
||||
import corpus
|
||||
|
||||
corpus.RB = '/home/m/re-tools/dsp/build/render48k'
|
||||
|
||||
with open('scripts/baseline_bridge.json') as f:
|
||||
REF_ERRORS = json.load(f)
|
||||
|
||||
def structural_cases():
|
||||
out = []
|
||||
for name, inp, args, ref, f in corpus.build_cases():
|
||||
joined = [','.join(args)] if len(args) == 3 else args
|
||||
out.append((name, inp, joined, ref, f))
|
||||
return out
|
||||
|
||||
def run_vlaw(inp, args, alpha, beta, c, delta):
|
||||
out = f'/tmp/vlaw_{alpha}_{beta}_{c}_{delta}_{os.path.basename(inp)}.wav'
|
||||
env = {
|
||||
**os.environ,
|
||||
'RT_VLAW': '1',
|
||||
'RT_VLAW_ALPHA': str(alpha),
|
||||
'RT_VLAW_BETA': str(beta),
|
||||
'RT_VLAW_C': str(c),
|
||||
'RT_VLAW_DELTA': str(delta),
|
||||
'RT_SYN': '1', 'RT_NOWARP': '1', 'RT_NOIIR3': '1', 'RT_IIR12': '0',
|
||||
}
|
||||
subprocess.run([corpus.RB, inp, out] + args, capture_output=True, env=env, cwd='/home/m/re-tools')
|
||||
return out
|
||||
|
||||
def eval_error(out, ref, f):
|
||||
if not os.path.exists(out) or os.path.getsize(out) == 0:
|
||||
return None
|
||||
ref_sig = corpus.load_mono(ref)
|
||||
out_sig = corpus.load_mono(out)
|
||||
min_len = min(len(ref_sig), len(out_sig))
|
||||
ref_sig = ref_sig[-min_len:]
|
||||
out_sig = out_sig[-min_len:]
|
||||
ref_ta = corpus.ta(ref_sig, f)
|
||||
out_ta = corpus.ta(out_sig, f)
|
||||
return corpus.db(out_ta / ref_ta)
|
||||
|
||||
def group_key(name):
|
||||
return name.split('_')[0]
|
||||
|
||||
all_cases = structural_cases()
|
||||
groups = {}
|
||||
for name, inp, args, ref, f in all_cases:
|
||||
g = group_key(name)
|
||||
groups.setdefault(g, []).append((name, inp, args, ref, f))
|
||||
|
||||
# Pick one case per group
|
||||
rep_cases = {}
|
||||
for g in ['t1kq', 't1k', 'al', 'res', 'dual']:
|
||||
if g in groups:
|
||||
# Pick middle-ish case
|
||||
cases = groups[g]
|
||||
rep_cases[g] = cases[len(cases)//2]
|
||||
|
||||
print("Representative cases:")
|
||||
for g, (name, inp, args, ref, f) in rep_cases.items():
|
||||
print(f" {g}: {name}")
|
||||
|
||||
# Test a small grid around dual params
|
||||
dual_params = (3.2193, 0.4927, 0.5423, 6.9177)
|
||||
|
||||
print("\n=== Grid search per group ===")
|
||||
results = {}
|
||||
|
||||
for g, (name, inp, args, ref, f) in rep_cases.items():
|
||||
print(f"\n--- {g} ({name}) ---")
|
||||
best = None
|
||||
best_err = float('inf')
|
||||
|
||||
# Coarse grid
|
||||
alphas = np.linspace(1.0, 5.0, 5)
|
||||
betas = np.linspace(0.2, 0.8, 5)
|
||||
cs = np.linspace(-0.5, 2.0, 5)
|
||||
deltas = np.linspace(0.0, 12.0, 5)
|
||||
|
||||
for alpha in alphas:
|
||||
for beta in betas:
|
||||
for c in cs:
|
||||
for delta in deltas:
|
||||
out = run_vlaw(inp, args, alpha, beta, c, delta)
|
||||
err = eval_error(out, ref, f)
|
||||
if err is not None and abs(err) < best_err:
|
||||
best_err = abs(err)
|
||||
best = (alpha, beta, c, delta, err)
|
||||
print(f' {name}: α={alpha:.3f}, β={beta:.3f}, c={c:.3f}, Δ={delta:.3f} => {err:.3f} dB')
|
||||
|
||||
if best:
|
||||
results[g] = best[:4]
|
||||
print(f' BEST {g}: α={best[0]:.4f}, β={best[1]:.4f}, c={best[2]:.4f}, Δ={best[3]:.4f} => {best[4]:.3f} dB')
|
||||
|
||||
print("\n=== SUMMARY ===")
|
||||
for g, (a, b, c, d) in results.items():
|
||||
print(f'{g}: α={a:.4f}, β={b:.4f}, c={c:.4f}, Δ={d:.4f}')
|
||||
|
||||
with open('/tmp/opencode/vlaw_params.json', 'w') as f:
|
||||
json.dump({g: {'alpha': a, 'beta': b, 'c': c, 'delta': d}
|
||||
for g, (a, b, c, d) in results.items()}, f, indent=2)
|
||||
print('\nSaved to /tmp/opencode/vlaw_params.json')
|
||||
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Quick VLAW parameter test - just evaluate a few configs per group.
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
sys.path.insert(0, '/home/m/re-tools/scripts')
|
||||
import corpus
|
||||
|
||||
corpus.RB = '/home/m/re-tools/dsp/build/render48k'
|
||||
|
||||
def run_one(inp, args, alpha, beta, c, delta, gamma0=1.79):
|
||||
out = f'/tmp/vlaw_test_{alpha}_{beta}_{c}.wav'
|
||||
env = {
|
||||
**os.environ,
|
||||
'RT_VLAW': '1',
|
||||
'RT_VLAW_ALPHA': str(alpha),
|
||||
'RT_VLAW_BETA': str(beta),
|
||||
'RT_VLAW_C': str(c),
|
||||
'RT_VLAW_DELTA': str(delta),
|
||||
'RT_SYN': '1',
|
||||
'RT_NOWARP': '1',
|
||||
'RT_NOIIR3': '1',
|
||||
'RT_IIR12': '0',
|
||||
}
|
||||
subprocess.run(
|
||||
[corpus.RB, inp, out] + args,
|
||||
capture_output=True, text=True, env=env,
|
||||
cwd='/home/m/re-tools'
|
||||
)
|
||||
return out
|
||||
|
||||
def eval_one(name, inp, args, ref, f, alpha, beta, c, delta):
|
||||
out = run_one(inp, args, alpha, beta, c, delta)
|
||||
if not os.path.exists(out) or os.path.getsize(out) == 0:
|
||||
return None
|
||||
ref_sig = corpus.load_mono(ref)
|
||||
out_sig = corpus.load_mono(out)
|
||||
min_len = min(len(ref_sig), len(out_sig))
|
||||
ref_sig = ref_sig[-min_len:]
|
||||
out_sig = out_sig[-min_len:]
|
||||
ref_ta = corpus.ta(ref_sig, f)
|
||||
out_ta = corpus.ta(out_sig, f)
|
||||
return corpus.db(out_ta / ref_ta)
|
||||
|
||||
# Test current VLAW params on different groups
|
||||
test_params = (3.2193, 0.4927, 0.5423, 6.9177)
|
||||
|
||||
all_cases = []
|
||||
for name, inp, args, ref, f in corpus.build_cases():
|
||||
joined = [','.join(args)] if len(args) == 3 else args
|
||||
all_cases.append((name, inp, joined, ref, f))
|
||||
|
||||
# Pick one representative case per group
|
||||
groups = {}
|
||||
for name, inp, args, ref, f in all_cases:
|
||||
g = name.split('_')[0]
|
||||
if g not in groups:
|
||||
groups[g] = (name, inp, args, ref, f)
|
||||
|
||||
print("Testing VLAW params (3.2193, 0.4927, 0.5423, 6.9177) on each group:")
|
||||
for g, (name, inp, args, ref, f) in groups.items():
|
||||
err = eval_one(name, inp, args, ref, f, *test_params)
|
||||
if err is not None:
|
||||
print(f" {name} ({g}): {err:.3f} dB")
|
||||
else:
|
||||
print(f" {name} ({g}): FAILED")
|
||||
@@ -0,0 +1,192 @@
|
||||
#!/usr/bin/env python3
|
||||
"""rendersnap.py — SIGSTOP-sampling of the plugin state DURING offline render
|
||||
(-renderproject): processing is back-to-back, so random stops land inside the
|
||||
DSP with high probability. Saves every snapshot where FIR != complex identity.
|
||||
"""
|
||||
import os
|
||||
import signal
|
||||
import struct
|
||||
import hashlib
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
|
||||
SLOTS = [0x540548, 0x540550, 0x540598, 0x540628, 0x540668, 0x540678, 0x540688,
|
||||
0x540698, 0x5406a8, 0x5406b8, 0x5406c8, 0x5406d8, 0x5406e8, 0x5406f8,
|
||||
0x540708, 0x540718, 0x540728, 0x540738, 0x540748, 0x540758,
|
||||
0x540768, 0x540778, 0x540788, 0x540798, 0x5407a8, 0x5407b8,
|
||||
0x5407c8, 0x5407d8, 0x5407e8, 0x5407f8, 0x540808, 0x540818,
|
||||
0x540828, 0x540838, 0x540848]
|
||||
NARR = 8194
|
||||
OUT = '/tmp/opencode/rendersnap'
|
||||
|
||||
|
||||
def find_host():
|
||||
import glob
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
cmd = open(f'/proc/{pid}/cmdline', 'rb').read().replace(b'\0', b' ').decode('utf8', 'replace')
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd:
|
||||
return pid
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
rpp = sys.argv[1] if len(sys.argv) > 1 else '/home/m/soothe-bt/dual_b1q_0.5.rpp'
|
||||
nattempts = int(sys.argv[2]) if len(sys.argv) > 2 else 300
|
||||
os.makedirs(OUT, exist_ok=True)
|
||||
subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; sleep 1", shell=True)
|
||||
wav = rpp.replace('.rpp', '.wav')
|
||||
if os.path.exists(wav):
|
||||
os.remove(wav)
|
||||
proc = subprocess.Popen(['/usr/bin/reaper', '-nosplash', '-ignoreerrors',
|
||||
'-renderproject', rpp],
|
||||
stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
host = None
|
||||
t0 = time.time()
|
||||
while time.time() - t0 < 30 and not host:
|
||||
host = find_host()
|
||||
time.sleep(0.001)
|
||||
if not host:
|
||||
print('NO HOST')
|
||||
return 1
|
||||
print('host %d at %.3fs' % (host, time.time() - t0), flush=True)
|
||||
|
||||
fd = os.open(f'/proc/{host}/mem', os.O_RDONLY)
|
||||
|
||||
def rd(a, n):
|
||||
try:
|
||||
return os.pread(fd, n, a)
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
ctx = None
|
||||
vt = struct.pack('<Q', 0x1824AC210)
|
||||
m48 = struct.pack('<I', 0x473b8000)
|
||||
|
||||
def scan_ctx():
|
||||
for line in open(f'/proc/{host}/maps'):
|
||||
parts = line.split()
|
||||
if 'rw' not in parts[1]:
|
||||
continue
|
||||
lo, hi = (int(x, 16) for x in parts[0].split('-'))
|
||||
CH = 16 * 1024 * 1024
|
||||
a = lo
|
||||
while a < hi:
|
||||
d = rd(a, min(CH + 4096, hi - a))
|
||||
if not d:
|
||||
break
|
||||
j = d.find(vt)
|
||||
while j >= 0:
|
||||
cand = a + j
|
||||
sb = rd(cand + 0x540870, 4)
|
||||
if sb and struct.unpack('<f', sb)[0] > 100:
|
||||
return cand
|
||||
j = d.find(vt, j + 1)
|
||||
j = d.find(m48)
|
||||
while j >= 0:
|
||||
cand = a + j - 0x24
|
||||
sb = rd(cand + 0x540870, 4)
|
||||
if sb and struct.unpack('<f', sb)[0] > 100:
|
||||
return cand
|
||||
j = d.find(m48, j + 1)
|
||||
a += CH
|
||||
return None
|
||||
|
||||
# find-loop: stop-scan-resume until instance exists (render lasts ~0.5s)
|
||||
while ctx is None and time.time() - t0 < 25:
|
||||
try:
|
||||
os.kill(host, signal.SIGSTOP)
|
||||
except ProcessLookupError:
|
||||
break
|
||||
try:
|
||||
ctx = scan_ctx()
|
||||
finally:
|
||||
if ctx is None:
|
||||
try:
|
||||
os.kill(host, signal.SIGCONT)
|
||||
except ProcessLookupError:
|
||||
break
|
||||
if ctx is None:
|
||||
time.sleep(0.004)
|
||||
print('ctx %#x' % ctx if ctx else 'NO CTX', flush=True)
|
||||
if not ctx:
|
||||
return 1
|
||||
print('ctx %#x' % ctx if ctx else 'NO CTX', flush=True)
|
||||
if not ctx:
|
||||
return 1
|
||||
|
||||
hits = saved = 0
|
||||
rng = np.random.default_rng(3)
|
||||
prev_sig = None
|
||||
phases = []
|
||||
while True:
|
||||
try:
|
||||
os.kill(host, signal.SIGSTOP)
|
||||
except ProcessLookupError:
|
||||
break
|
||||
try:
|
||||
pb = rd(ctx + 0x540668, 8)
|
||||
if not pb:
|
||||
continue
|
||||
p = struct.unpack('<Q', pb)[0]
|
||||
fb = rd(p, NARR * 4)
|
||||
if not fb:
|
||||
continue
|
||||
arr = np.frombuffer(fb[:2049 * 8], dtype='<f4').astype(np.float32)
|
||||
sig = arr.tobytes()[:4096]
|
||||
rb = rd(struct.unpack('<Q', rd(ctx + 0x5407f8, 8))[0], 2049 * 4)
|
||||
rsig = rb[:512] if rb else b''
|
||||
key = hashlib.md5(sig + rsig).digest()
|
||||
if key != prev_sig:
|
||||
prev_sig = key
|
||||
mag = np.hypot(arr[0::2], arr[1::2])
|
||||
rv = np.frombuffer(rb, dtype='<f4') if rb else None
|
||||
phase = dict(t=round(time.time() - t0, 3),
|
||||
firMax=float(np.abs(arr[1:2049]).max()),
|
||||
fir43=float(mag[43]), fir171=float(mag[171]),
|
||||
r43=float(rv[43]) if rv is not None else -1,
|
||||
r171=float(rv[171]) if rv is not None else -1)
|
||||
phases.append(phase)
|
||||
store = {}
|
||||
for off in SLOTS:
|
||||
q = rd(ctx + off, 8)
|
||||
if not q:
|
||||
continue
|
||||
ptr = struct.unpack('<Q', q)[0]
|
||||
if ptr < 0x10000:
|
||||
continue
|
||||
ab = rd(ptr, NARR * 4)
|
||||
if ab:
|
||||
store[hex(off)] = np.frombuffer(ab, dtype='<f4').astype(np.float32)
|
||||
fn = f'{OUT}/phase{saved:03d}.npz'
|
||||
np.savez_compressed(fn, **store)
|
||||
saved += 1
|
||||
print('PHASE %s -> %s' % (phase, fn), flush=True)
|
||||
if saved >= 24:
|
||||
break
|
||||
finally:
|
||||
try:
|
||||
os.kill(host, signal.SIGCONT)
|
||||
except ProcessLookupError:
|
||||
pass
|
||||
time.sleep(float(rng.uniform(0.001, 0.01)))
|
||||
try:
|
||||
os.kill(host, 0)
|
||||
except ProcessLookupError:
|
||||
print('host exited at %.2fs' % (time.time() - t0), flush=True)
|
||||
break
|
||||
print('phases=%d' % saved)
|
||||
os.close(fd)
|
||||
proc.kill()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,218 @@
|
||||
#!/usr/bin/env python3
|
||||
"""rendersnap2.py — non-destructive variant of rendersnap.py.
|
||||
|
||||
Differences (24j):
|
||||
- does NOT kill the host: lets -renderproject finish naturally so the output
|
||||
wav is complete (partial-wav hazard, NOTES 24c);
|
||||
- additionally dumps the ctx SCALAR bank 0x540860..0x5408c0 every phase
|
||||
(goal: wet/FIR scalar [ctx+0x540888], BLOCKMAP 23b line 52b832);
|
||||
- keeps sampling until host exit or phase cap, dedupe by FIR+scalar md5.
|
||||
"""
|
||||
import hashlib
|
||||
import os
|
||||
import signal
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
|
||||
SLOTS = [0x540668, 0x540548, 0x540550, 0x540598, 0x540628, 0x5406f8,
|
||||
0x540678, 0x540688, 0x5406c8, 0x5406e8, 0x540768,
|
||||
0x540788, 0x5407f8,
|
||||
# 24mm9: ACC-таблица указателей (шаг 10 combine) и WINfreq
|
||||
# (окно FIR-цепи; падающий Hann — контроль формы)
|
||||
0x5407c8, 0x540658]
|
||||
NARR = 8194
|
||||
SCAL_OFF = 0x540860
|
||||
SCAL_N = 24 # floats -> 0x540860..0x5408c0
|
||||
OUT = '/tmp/opencode/rendersnap2'
|
||||
|
||||
|
||||
def find_host():
|
||||
import glob
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
cmd = open(f'/proc/{pid}/cmdline', 'rb').read().replace(b'\0', b' ').decode('utf8', 'replace')
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd:
|
||||
return pid
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
rpp = sys.argv[1] if len(sys.argv) > 1 else '/home/m/soothe-bt/dual_b1q_0.5.rpp'
|
||||
cap = int(sys.argv[2]) if len(sys.argv) > 2 else 200
|
||||
global OUT
|
||||
OUT = sys.argv[3] if len(sys.argv) > 3 else OUT
|
||||
os.makedirs(OUT, exist_ok=True)
|
||||
subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; "
|
||||
"rm -rf /run/user/1000/yabridge-soothe2_x64-*; sleep 1", shell=True)
|
||||
# wav path = RENDER_FILE from the project (NOT rpp.replace!) — deleting the
|
||||
# wrong file destroyed corpus refs once (24k-3 hazard).
|
||||
wav = None
|
||||
for ln in open(rpp, 'r', errors='replace'):
|
||||
if 'RENDER_FILE' in ln and '"' in ln:
|
||||
wav = ln.split('"')[1]
|
||||
break
|
||||
if wav and os.path.exists(wav):
|
||||
os.remove(wav)
|
||||
proc = subprocess.Popen(['/usr/bin/reaper', '-nosplash', '-ignoreerrors',
|
||||
'-renderproject', rpp],
|
||||
stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
t0 = time.time()
|
||||
host = None
|
||||
while time.time() - t0 < 30 and not host:
|
||||
host = find_host()
|
||||
time.sleep(0.001)
|
||||
if not host:
|
||||
print('NO HOST')
|
||||
return 1
|
||||
print('host %d at %.3fs' % (host, time.time() - t0), flush=True)
|
||||
|
||||
fd = os.open(f'/proc/{host}/mem', os.O_RDONLY)
|
||||
|
||||
def rd(a, n):
|
||||
try:
|
||||
return os.pread(fd, n, a)
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
vt = struct.pack('<Q', 0x1824AC210)
|
||||
m48 = struct.pack('<I', 0x473b8000)
|
||||
|
||||
def scan_ctx():
|
||||
for line in open(f'/proc/{host}/maps'):
|
||||
parts = line.split()
|
||||
if 'rw' not in parts[1]:
|
||||
continue
|
||||
lo, hi = (int(x, 16) for x in parts[0].split('-'))
|
||||
CH = 16 * 1024 * 1024
|
||||
a = lo
|
||||
while a < hi:
|
||||
d = rd(a, min(CH + 4096, hi - a))
|
||||
if not d:
|
||||
break
|
||||
j = d.find(vt)
|
||||
while j >= 0:
|
||||
cand = a + j
|
||||
sb = rd(cand + 0x540870, 4)
|
||||
if sb and struct.unpack('<f', sb)[0] > 100:
|
||||
return cand
|
||||
j = d.find(vt, j + 1)
|
||||
j = d.find(m48)
|
||||
while j >= 0:
|
||||
cand = a + j - 0x24
|
||||
sb = rd(cand + 0x540870, 4)
|
||||
if sb and struct.unpack('<f', sb)[0] > 100:
|
||||
return cand
|
||||
j = d.find(m48, j + 1)
|
||||
a += CH
|
||||
return None
|
||||
|
||||
ctx = None
|
||||
while ctx is None and time.time() - t0 < 25:
|
||||
try:
|
||||
os.kill(host, signal.SIGSTOP)
|
||||
except ProcessLookupError:
|
||||
break
|
||||
try:
|
||||
ctx = scan_ctx()
|
||||
finally:
|
||||
if ctx is None:
|
||||
try:
|
||||
os.kill(host, signal.SIGCONT)
|
||||
except ProcessLookupError:
|
||||
break
|
||||
if ctx is None:
|
||||
time.sleep(0.004)
|
||||
if not ctx:
|
||||
print('NO CTX')
|
||||
return 1
|
||||
print('ctx %#x' % ctx, flush=True)
|
||||
|
||||
rng = np.random.default_rng(11)
|
||||
prev = None
|
||||
saved = 0
|
||||
while True:
|
||||
try:
|
||||
os.kill(host, signal.SIGSTOP)
|
||||
except ProcessLookupError:
|
||||
print('host exited at %.2fs' % (time.time() - t0), flush=True)
|
||||
break
|
||||
try:
|
||||
pb = rd(ctx + 0x540668, 8)
|
||||
if not pb:
|
||||
continue
|
||||
p = struct.unpack('<Q', pb)[0]
|
||||
fb = rd(p, NARR * 4)
|
||||
if not fb:
|
||||
continue
|
||||
scal = rd(ctx + SCAL_OFF, SCAL_N * 4)
|
||||
if scal is None:
|
||||
continue
|
||||
key = hashlib.md5(fb[:2049 * 8] + scal).digest()
|
||||
if key != prev:
|
||||
prev = key
|
||||
arr = np.frombuffer(fb[:2049 * 8], dtype='<f4')
|
||||
mag = np.hypot(arr[0::2], arr[1::2])
|
||||
sv = np.frombuffer(scal, dtype='<f4')
|
||||
store = {'fir_re': arr[0::2].copy(), 'fir_im': arr[1::2].copy(),
|
||||
'scal': sv.copy()}
|
||||
# LUT params: sub-object pointer at [ctx+0x180] (24z: 563a60 uses
|
||||
# r15=rcx -> [r15+0x180]); A=[sub+0] B=[sub+4] G=[sub+0xc]
|
||||
sb = rd(ctx + 0x180, 8)
|
||||
if sb:
|
||||
sub = struct.unpack('<Q', sb)[0]
|
||||
if sub > 0x10000:
|
||||
fb4 = rd(sub, 0x18)
|
||||
if fb4:
|
||||
store['lut_A'] = struct.unpack('<f', fb4[0:4])[0]
|
||||
store['lut_B'] = struct.unpack('<f', fb4[4:8])[0]
|
||||
store['lut_G'] = struct.unpack('<f', fb4[12:16])[0]
|
||||
store['lut_mode'] = fb4[16]
|
||||
for off in SLOTS[1:]:
|
||||
q = rd(ctx + off, 8)
|
||||
if not q:
|
||||
continue
|
||||
ptr = struct.unpack('<Q', q)[0]
|
||||
if ptr < 0x10000:
|
||||
continue
|
||||
ab = rd(ptr, NARR * 4)
|
||||
if ab:
|
||||
store[hex(off)] = np.frombuffer(ab, dtype='<f4').astype(np.float32)
|
||||
np.savez_compressed(f'{OUT}/ph{saved:03d}.npz', t_snap=time.time() - t0,
|
||||
**store)
|
||||
print('PH%03d t=%.2f fir43=%.4f fir171=%.4f | s888=%.6f s88c=%.6f s874=%.6f s87c=%.6f s870=%.3f' %
|
||||
(saved, time.time() - t0, mag[43], mag[171],
|
||||
sv[10], sv[11], sv[5], sv[7], sv[4]), flush=True)
|
||||
saved += 1
|
||||
if saved >= cap:
|
||||
break
|
||||
finally:
|
||||
try:
|
||||
os.kill(host, signal.SIGCONT)
|
||||
except ProcessLookupError:
|
||||
pass
|
||||
time.sleep(float(rng.uniform(0.0005, 0.006)))
|
||||
try:
|
||||
os.kill(host, 0)
|
||||
except ProcessLookupError:
|
||||
print('host exited at %.2fs' % (time.time() - t0), flush=True)
|
||||
break
|
||||
# wait for natural finish so wav completes
|
||||
for _ in range(300):
|
||||
if proc.poll() is not None:
|
||||
break
|
||||
time.sleep(0.1)
|
||||
print('saved=%d reaper_rc=%s wav=%s' % (saved, proc.poll(),
|
||||
os.path.getsize(wav) if wav and os.path.exists(wav) else 'NONE'))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
Executable
+241
@@ -0,0 +1,241 @@
|
||||
#!/usr/bin/env python3
|
||||
"""scan3.py — Multi-instance DSP context scanner for soothe2.
|
||||
|
||||
Fixes over scan2.py:
|
||||
1. Pre-scans ALL processes for ctx (no host-finding delay)
|
||||
2. Scans for ALL instances (GUI/DSP pair hypothesis from 24c)
|
||||
3. Captures full state per instance for comparison
|
||||
4. Uses rendersnap-style sampling for FIR/slot captures
|
||||
"""
|
||||
import glob
|
||||
import hashlib
|
||||
import os
|
||||
import signal
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
|
||||
OUT = '/tmp/opencode/scan3'
|
||||
NARR = 8194
|
||||
|
||||
SLOTS_FULL = [
|
||||
0x540548, 0x540550, 0x540598, 0x540628, 0x540668, 0x540678, 0x540688,
|
||||
0x540698, 0x5406a8, 0x5406b8, 0x5406c8, 0x5406d8, 0x5406e8, 0x5406f8,
|
||||
0x540708, 0x540718, 0x540728, 0x540738, 0x540748, 0x540758,
|
||||
0x540768, 0x540778, 0x540788, 0x540798, 0x5407a8, 0x5407b8,
|
||||
0x5407c8, 0x5407d8, 0x5407e8, 0x5407f8, 0x540808, 0x540818,
|
||||
0x540828, 0x540838, 0x540848,
|
||||
]
|
||||
|
||||
VTQ = struct.pack('<Q', 0x1824AC210)
|
||||
M48 = struct.pack('<I', 0x473b8000)
|
||||
|
||||
|
||||
def pre_scan_all(max_region=50*1024*1024):
|
||||
"""Scan ALL processes for DSP ctx instances (no host needed)."""
|
||||
instances = {} # pid -> [(ctx_addr, sens)]
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' not in maps:
|
||||
continue
|
||||
try:
|
||||
fd = os.open(f'/proc/{pid}/mem', os.O_RDONLY)
|
||||
except Exception:
|
||||
continue
|
||||
pid_insts = []
|
||||
for line in maps.split('\n'):
|
||||
parts = line.split()
|
||||
if len(parts) < 2 or 'rw' not in parts[1]:
|
||||
continue
|
||||
lo, hi = (int(x, 16) for x in parts[0].split('-'))
|
||||
if hi - lo > max_region:
|
||||
continue
|
||||
try:
|
||||
data = os.pread(fd, min(hi - lo, 4*1024*1024), lo)
|
||||
except Exception:
|
||||
continue
|
||||
for pat, off in ((VTQ, 0), (M48, -0x24)):
|
||||
j = data.find(pat)
|
||||
while j >= 0:
|
||||
cand = lo + j + off
|
||||
try:
|
||||
sb = os.pread(fd, 4, cand + 0x540870)
|
||||
if sb and struct.unpack('<f', sb)[0] > 100:
|
||||
pid_insts.append(cand)
|
||||
except Exception:
|
||||
pass
|
||||
j = data.find(pat, j + 1)
|
||||
os.close(fd)
|
||||
if pid_insts:
|
||||
instances[pid] = list(set(pid_insts))
|
||||
return instances
|
||||
|
||||
|
||||
def read_state(fd, ctx):
|
||||
"""Read key DSP state from a context."""
|
||||
state = {'ctx': ctx}
|
||||
for off, name, fmt in [
|
||||
(0x540870, 'sens', '<f'),
|
||||
(0x540874, 'depth', '<f'),
|
||||
(0x54087c, 'mix', '<f'),
|
||||
(0x540888, 'att_coeff', '<f'),
|
||||
(0x54088c, 'rel_coeff', '<f'),
|
||||
(0x1a0, 'nfft', '<i'),
|
||||
]:
|
||||
try:
|
||||
sb = os.pread(fd, 4, ctx + off)
|
||||
state[name] = struct.unpack(fmt, sb)[0]
|
||||
except Exception:
|
||||
state[name] = None
|
||||
|
||||
try:
|
||||
pb = os.pread(fd, 8, ctx + 0x540668)
|
||||
p = struct.unpack('<Q', pb)[0]
|
||||
if p > 0x10000:
|
||||
fb = os.pread(fd, 2049*8, p)
|
||||
arr = np.frombuffer(fb, dtype='<f4')
|
||||
mag = np.hypot(arr[0::2], arr[1::2])
|
||||
state['fir_mag0'] = float(mag[0])
|
||||
state['fir_mag43'] = float(mag[43]) if len(mag) > 43 else -1
|
||||
state['fir_mag171'] = float(mag[171]) if len(mag) > 171 else -1
|
||||
state['fir_is_identity'] = bool(np.all(np.abs(mag[:50] - 1.0) < 0.01))
|
||||
except Exception:
|
||||
pass
|
||||
return state
|
||||
|
||||
|
||||
def sampling_phase(fd, host, ctx, t_start):
|
||||
"""Rendersnap-style FIR sampling."""
|
||||
rng = np.random.default_rng(3)
|
||||
prev_sig = None
|
||||
saved = 0
|
||||
while time.time() - t_start < 20:
|
||||
try:
|
||||
os.kill(host, signal.SIGSTOP)
|
||||
except ProcessLookupError:
|
||||
break
|
||||
try:
|
||||
pb = os.pread(fd, 8, ctx + 0x540668)
|
||||
p = struct.unpack('<Q', pb)[0]
|
||||
if p < 0x10000:
|
||||
continue
|
||||
fb = os.pread(fd, NARR * 4, p)
|
||||
arr = np.frombuffer(fb[:2049*8], dtype='<f4').astype(np.float32)
|
||||
sig = arr.tobytes()[:4096]
|
||||
|
||||
rb_ptr = os.pread(fd, 8, ctx + 0x5407f8)
|
||||
rp = struct.unpack('<Q', rb_ptr)[0]
|
||||
rb = os.pread(fd, 2049*4, rp) if rp > 0x10000 else None
|
||||
rsig = rb[:512] if rb else b''
|
||||
|
||||
key = hashlib.md5(sig + rsig).digest()
|
||||
if key != prev_sig:
|
||||
prev_sig = key
|
||||
mag = np.hypot(arr[0::2], arr[1::2])
|
||||
rv = np.frombuffer(rb, dtype='<f4') if rb else None
|
||||
phase = dict(
|
||||
t=round(time.time() - t_start, 3),
|
||||
fir43=float(mag[43]),
|
||||
fir171=float(mag[171]),
|
||||
r43=float(rv[43]) if rv is not None else -1,
|
||||
r171=float(rv[171]) if rv is not None else -1,
|
||||
)
|
||||
store = {}
|
||||
for off in SLOTS_FULL:
|
||||
try:
|
||||
q = os.pread(fd, 8, ctx + off)
|
||||
ptr = struct.unpack('<Q', q)[0]
|
||||
if ptr > 0x10000:
|
||||
ab = os.pread(fd, NARR * 4, ptr)
|
||||
store[hex(off)] = np.frombuffer(ab, dtype='<f4').astype(np.float32)
|
||||
except Exception:
|
||||
pass
|
||||
fn = f'{OUT}/scan{saved:03d}.npz'
|
||||
np.savez_compressed(fn, **store)
|
||||
saved += 1
|
||||
print(f' PHASE {phase} -> {fn}', flush=True)
|
||||
if saved >= 24:
|
||||
break
|
||||
finally:
|
||||
try:
|
||||
os.kill(host, signal.SIGCONT)
|
||||
except ProcessLookupError:
|
||||
pass
|
||||
time.sleep(float(rng.uniform(0.001, 0.01)))
|
||||
try:
|
||||
os.kill(host, 0)
|
||||
except ProcessLookupError:
|
||||
print(f' host exited at {time.time()-t_start:.2f}s')
|
||||
break
|
||||
return saved
|
||||
|
||||
|
||||
def main():
|
||||
rpp = sys.argv[1] if len(sys.argv) > 1 else '/home/m/soothe-bt/dual_b1q_0.5.rpp'
|
||||
os.makedirs(OUT, exist_ok=True)
|
||||
|
||||
subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; sleep 1", shell=True)
|
||||
wav = rpp.replace('.rpp', '.wav')
|
||||
if os.path.exists(wav):
|
||||
os.remove(wav)
|
||||
|
||||
proc = subprocess.Popen(['/usr/bin/reaper', '-nosplash', '-ignoreerrors',
|
||||
'-renderproject', rpp],
|
||||
stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
|
||||
t0 = time.time()
|
||||
all_instances = {} # pid -> [ctx_addrs]
|
||||
|
||||
# Phase 1: aggressive pre-scan (no host needed)
|
||||
print('Pre-scanning for DSP contexts...', flush=True)
|
||||
for att in range(100):
|
||||
found = pre_scan_all()
|
||||
for pid, ctxs in found.items():
|
||||
if pid not in all_instances:
|
||||
all_instances[pid] = ctxs
|
||||
print(f' pid={pid} ctx={[hex(c) for c in ctxs]} at {time.time()-t0:.3f}s', flush=True)
|
||||
if all_instances:
|
||||
break
|
||||
time.sleep(0.0002)
|
||||
|
||||
if not all_instances:
|
||||
print('NO CTX FOUND')
|
||||
proc.kill()
|
||||
return 1
|
||||
|
||||
# Phase 2: read state of each instance
|
||||
for pid, ctxs in all_instances.items():
|
||||
for ctx in ctxs:
|
||||
fd = os.open(f'/proc/{pid}/mem', os.O_RDONLY)
|
||||
state = read_state(fd, ctx)
|
||||
os.close(fd)
|
||||
print(f'\n=== Instance pid={pid} ctx={hex(ctx)} ===')
|
||||
for k, v in sorted(state.items()):
|
||||
if isinstance(v, float):
|
||||
print(f' {k}: {v:.6f}')
|
||||
else:
|
||||
print(f' {k}: {v}')
|
||||
|
||||
# Phase 3: rendersnap-style sampling on the primary
|
||||
primary_pid = min(all_instances.keys())
|
||||
primary_ctx = min(all_instances[primary_pid])
|
||||
print(f'\n--- Sampling primary {hex(primary_ctx)} (pid={primary_pid}) ---')
|
||||
|
||||
fd = os.open(f'/proc/{primary_pid}/mem', os.O_RDONLY)
|
||||
saved = sampling_phase(fd, primary_pid, primary_ctx, time.time())
|
||||
os.close(fd)
|
||||
|
||||
print(f'\ntotal samples={saved}')
|
||||
proc.kill()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env python3
|
||||
"""scan_lutsub.py v2 — range-filtered scan for detector-LUT param subs.
|
||||
Filter: -60<A<-1, 1<B<100, 0.2<G<8, mode in {0,1}, [+0x90] valid pointer.
|
||||
Prints unique (A,B,G,mode) tuples with addresses.
|
||||
"""
|
||||
import struct, subprocess, sys, time
|
||||
import glob, os
|
||||
import numpy as np
|
||||
|
||||
def find_host():
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
cmd = open(f'/proc/{pid}/cmdline','rb').read().replace(b'\0',b' ').decode('utf8','replace')
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd:
|
||||
return pid
|
||||
return None
|
||||
|
||||
subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; "
|
||||
"rm -rf /run/user/1000/yabridge-soothe2_x64-*; sleep 1", shell=True)
|
||||
rpp = sys.argv[1] if len(sys.argv) > 1 else '/home/m/soothe-bt/dual_b1q_0.5.rpp'
|
||||
proc = subprocess.Popen(['/usr/bin/reaper','-nosplash','-ignoreerrors','-renderproject', rpp],
|
||||
stdout=open('/dev/null','w'), stderr=subprocess.STDOUT)
|
||||
t0=time.time(); host=None
|
||||
while time.time()-t0<30 and not host:
|
||||
host = find_host(); time.sleep(0.002)
|
||||
print('host', host, flush=True)
|
||||
if not host:
|
||||
sys.exit(1)
|
||||
fd = os.open(f'/proc/{host}/mem', os.O_RDONLY)
|
||||
|
||||
def rd(a,n):
|
||||
try: return os.pread(fd,n,a)
|
||||
except OSError: return None
|
||||
|
||||
seen={}
|
||||
alive=True
|
||||
t_end=time.time()+12
|
||||
while time.time()<t_end and alive:
|
||||
try:
|
||||
for line in open(f'/proc/{host}/maps'):
|
||||
parts=line.split()
|
||||
if 'rw' not in parts[1]: continue
|
||||
lo,hi=(int(x,16) for x in parts[0].split('-'))
|
||||
CH=8*1024*1024
|
||||
a=lo
|
||||
while a<hi:
|
||||
d=rd(a,min(CH+64,hi-a))
|
||||
if not d:
|
||||
alive=False; break
|
||||
n=len(d)//4
|
||||
arr=np.frombuffer(d[:n*4],dtype='<f4')
|
||||
# vectorized filter on A at even offsets
|
||||
m=(arr>-60)&(arr<-1)
|
||||
for i in np.nonzero(m)[0]:
|
||||
Bv=float(arr[i+1]) if i+1<n else 0
|
||||
if not (1<Bv<100): continue
|
||||
addr=a+i*4
|
||||
s=rd(addr,0x98)
|
||||
if not s or len(s)<0x98: continue
|
||||
G=struct.unpack('<f',s[12:16])[0]
|
||||
if not (0.2<G<8): continue
|
||||
mode=s[16]
|
||||
if mode>1: continue
|
||||
p=struct.unpack('<Q',s[0x90:0x98])[0]
|
||||
if not (0x10000<p<0x7ffff0000000): continue
|
||||
key=(round(float(arr[i]),2),round(Bv,2),round(G,3),mode)
|
||||
if key not in seen:
|
||||
seen[key]=(addr,p)
|
||||
print('NEW sub@%x vt=%x A=%.3f B=%.3f G=%.4f mode=%d' %
|
||||
(addr,p,arr[i],Bv,G,mode), flush=True)
|
||||
a+=CH
|
||||
except (FileNotFoundError, ProcessLookupError):
|
||||
alive=False
|
||||
break
|
||||
print('done; unique tuples:', len(seen))
|
||||
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env python3
|
||||
"""scan_pairs.py — dump ALL unique adjacent float pairs (A<0<B) seen in rw-mem
|
||||
during a render window. Diagnostic for LUT param location."""
|
||||
import struct, subprocess, sys, time
|
||||
import glob, os
|
||||
import numpy as np
|
||||
|
||||
def find_host():
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
pid = int(os.path.basename(p))
|
||||
try:
|
||||
cmd = open(f'/proc/{pid}/cmdline','rb').read().replace(b'\0',b' ').decode('utf8','replace')
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd:
|
||||
return pid
|
||||
return None
|
||||
|
||||
subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; "
|
||||
"rm -rf /run/user/1000/yabridge-soothe2_x64-*; sleep 1", shell=True)
|
||||
rpp = sys.argv[1] if len(sys.argv) > 1 else '/home/m/soothe-bt/dual_b1q_0.5.rpp'
|
||||
proc = subprocess.Popen(['/usr/bin/reaper','-nosplash','-ignoreerrors','-renderproject', rpp],
|
||||
stdout=open('/dev/null','w'), stderr=subprocess.STDOUT)
|
||||
t0=time.time(); host=None
|
||||
while time.time()-t0<30 and not host:
|
||||
host = find_host(); time.sleep(0.002)
|
||||
print('host', host, flush=True)
|
||||
if not host:
|
||||
sys.exit(1)
|
||||
fd = os.open(f'/proc/{host}/mem', os.O_RDONLY)
|
||||
|
||||
def rd(a,n):
|
||||
try: return os.pread(fd,n,a)
|
||||
except OSError: return None
|
||||
|
||||
seen={}
|
||||
t_end=time.time()+8
|
||||
while time.time()<t_end:
|
||||
try:
|
||||
alive=True
|
||||
for line in open(f'/proc/{host}/maps'):
|
||||
parts=line.split()
|
||||
if 'rw' not in parts[1]: continue
|
||||
lo,hi=(int(x,16) for x in parts[0].split('-'))
|
||||
CH=16*1024*1024
|
||||
a=lo
|
||||
while a<hi:
|
||||
d=rd(a,min(CH+64,hi-a))
|
||||
if not d:
|
||||
alive=False; break
|
||||
n=len(d)//8*2
|
||||
arr=np.frombuffer(d[:n*4],dtype='<f4').reshape(-1,2)
|
||||
m=(arr[:,0]>-60)&(arr[:,0]<-1)&(arr[:,1]>1)&(arr[:,1]<100)
|
||||
for i in np.nonzero(m)[0]:
|
||||
key=(round(float(arr[i,0]),3),round(float(arr[i,1]),3))
|
||||
if key not in seen:
|
||||
seen[key]=a+i*8
|
||||
print('pair A=%.4f B=%.4f @%x' % (key[0],key[1],a+i*8), flush=True)
|
||||
a+=CH
|
||||
if not alive: break
|
||||
except (FileNotFoundError, ProcessLookupError):
|
||||
break
|
||||
print('unique pairs:', len(seen))
|
||||
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env python3
|
||||
"""two-tone drive series at fc500/q0.5/s12: renders+captures+fit."""
|
||||
import subprocess, os, sys, time, glob
|
||||
import numpy as np, wave
|
||||
|
||||
def sh(cmd): return subprocess.run(cmd,shell=True,capture_output=True,text=True).stdout
|
||||
def find_host():
|
||||
import glob as g
|
||||
for p in g.glob('/proc/[0-9]*'):
|
||||
pid=int(os.path.basename(p))
|
||||
try:
|
||||
cmd=open('/proc/%d/cmdline'%pid,'rb').read().replace(b'\0',b' ').decode('utf8','replace')
|
||||
maps=open('/proc/%d/maps'%pid).read()
|
||||
except Exception: continue
|
||||
if 'soothe2' in maps and 'reaper' not in cmd: return pid
|
||||
return None
|
||||
|
||||
# inputs: dual content (500+2000 equal) at drives 0/-6/-12/-18 with probes
|
||||
sr=44100; T=4.0; n=int(sr*T); t=np.arange(n)/sr
|
||||
ph=np.random.default_rng(41).uniform(0,2*np.pi,7)
|
||||
drives=(0,6,12,18)
|
||||
for att in drives:
|
||||
A=0.4248*10**(-att/20)
|
||||
y=A*np.sin(2*np.pi*500*t+ph[0])+A*np.sin(2*np.pi*2000*t+ph[1])
|
||||
for i,f in enumerate((300.,700.,1400.,2800.,5000.)):
|
||||
y+=A*10**(-30/20)*np.sin(2*np.pi*f*t+ph[i+2])
|
||||
y=np.clip(y,-0.999,0.999)
|
||||
nm='tt%d'%att
|
||||
w=wave.open('/tmp/opencode/%s_in.wav'%nm,'wb'); w.setnchannels(1); w.setsampwidth(2); w.setframerate(sr)
|
||||
w.writeframes((y*32767).astype(np.int16).tobytes()); w.close()
|
||||
src=open('/tmp/opencode/multi.rpp').read()
|
||||
import re
|
||||
src=re.sub(r'RENDER_FILE "[^"]*"','RENDER_FILE "/tmp/opencode/%s_ref.wav"'%nm,src)
|
||||
src=src.replace('FILE "/tmp/opencode/multi_in.wav"','FILE "/tmp/opencode/%s_in.wav"'%nm)
|
||||
open('/tmp/opencode/%s.rpp'%nm,'w').write(src)
|
||||
print('inputs+rpps ready')
|
||||
|
||||
sh("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; rm -rf /run/user/1000/yabridge-soothe2_x64-*; sleep 1")
|
||||
for att in drives:
|
||||
wav='/tmp/opencode/tt%d_ref.wav'%att
|
||||
if os.path.exists(wav): os.remove(wav)
|
||||
pr=subprocess.Popen(['/usr/bin/reaper','-nosplash','-ignoreerrors','-renderproject','/tmp/opencode/tt%d.rpp'%att],
|
||||
stdout=subprocess.DEVNULL,stderr=subprocess.STDOUT)
|
||||
t0=time.time(); host=None
|
||||
while time.time()-t0<30 and not host: host=find_host(); time.sleep(0.002)
|
||||
for _ in range(240):
|
||||
if pr.poll() is not None: break
|
||||
time.sleep(0.1)
|
||||
print('tt%d ref rc=%s'%(att,pr.poll()),flush=True)
|
||||
|
||||
# captures + tracts
|
||||
for att in drives:
|
||||
od='/tmp/opencode/sc_tt%d'%att
|
||||
sh('rm -rf %s'%od)
|
||||
sh('cd /home/m/re-tools && timeout 60 python3 scripts/rendersnap2.py /tmp/opencode/tt%d.rpp 400 %s'%(att,od))
|
||||
tf='/tmp/opencode/tract_tt%d.txt'%att
|
||||
if os.path.exists(tf): os.remove(tf)
|
||||
env=dict(os.environ); env['RT_DUMP_BIN']=tf
|
||||
subprocess.run(['/home/m/re-tools/dsp/build/render48k','/tmp/opencode/tt%d_in.wav'%att,
|
||||
'/tmp/o48_tt.wav','500,0.5,12'],capture_output=True,env=env)
|
||||
print('captures+tracts done')
|
||||
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python3
|
||||
"""unify.py — global unified-law fit: cut = alpha*ln1p(am*s/res^p / beta)+c
|
||||
across multi6 (6 peaks) + tt-series (8 points, both peaks)."""
|
||||
import numpy as np, glob, wave
|
||||
from scipy.optimize import least_squares
|
||||
|
||||
def deepest(dirname,b):
|
||||
best=None
|
||||
for fn in sorted(glob.glob(dirname+'/ph*.npz')):
|
||||
d=np.load(fn)
|
||||
if '0x540628' not in d.files: continue
|
||||
s=d['0x540628'].astype(np.float64)
|
||||
if best is None or s[b]<best[0]: best=(s[b],s)
|
||||
return best[1] if best else None
|
||||
|
||||
def loadwav(p):
|
||||
w=wave.open(p,'rb'); n=w.getnframes(); ch=w.getnchannels(); sw=w.getsampwidth()
|
||||
d=w.readframes(n); w.close()
|
||||
if sw==2: return np.frombuffer(d,dtype=np.int16).astype(np.float64).reshape(-1,ch).mean(1)/32768
|
||||
raw=np.frombuffer(d,dtype=np.uint8).reshape(-1,ch,3)
|
||||
s=raw[:,:,0].astype(np.int64)|(raw[:,:,1].astype(np.int64)<<8)|(raw[:,:,2].astype(np.int64)<<16)
|
||||
return np.where(s>=0x800000,s-0x1000000,s).astype(np.float64).reshape(-1,ch).mean(1)/8388608
|
||||
|
||||
def ta(x,f,sr=44100,L=None):
|
||||
x=x[-L:]; t=np.arange(len(x))/sr; c=np.cos(2*np.pi*f*t); sn=np.sin(2*np.pi*f*t)
|
||||
return np.hypot(2*(x*c).sum(),2*(x*sn).sum())/len(x)
|
||||
|
||||
pts=[]
|
||||
# multi6 six peaks
|
||||
S=deepest('/tmp/opencode/sc_multi6',85)
|
||||
cut=np.maximum(-S*8.685889638,0)
|
||||
am=np.zeros(len(S)); rs=np.zeros(len(S))
|
||||
for ln in open('/tmp/opencode/tract_multi6.txt'):
|
||||
if ln.startswith('#'): continue
|
||||
p=ln.split(); kk=int(p[0])
|
||||
if kk<len(S): am[kk]=float(p[1]); rs[kk]=float(p[2])
|
||||
for kk in range(1,len(S)):
|
||||
if cut[kk]>1.0 and am[kk]>0.01:
|
||||
pts.append(('m6',am[kk],rs[kk],cut[kk]))
|
||||
# tt-series 4 drives x 2 peaks (ref-domain cuts via Goertzel)
|
||||
inp0=loadwav('/tmp/opencode/tt0_in.wav')
|
||||
rc={0:(10.34,11.84),6:(8.12,9.57),12:(6.12,7.45),18:(4.40,5.55)}
|
||||
for att,(c1v,c2v) in rc.items():
|
||||
tf='/tmp/opencode/tract_tt%d.txt'%att
|
||||
d43=d171=None; r43=r171=None
|
||||
for ln in open(tf):
|
||||
if ln.startswith('#'): continue
|
||||
p=ln.split(); kk=int(p[0])
|
||||
if kk==43: r43=float(p[2]); d43=am0=None; d43=float(p[1])
|
||||
if kk==171: r171=float(p[2]); d171=float(p[1])
|
||||
pts.append(('tt%d-pk1'%att,d43,r43,c1v))
|
||||
pts.append(('tt%d-pk2'%att,d171,r171,c2v))
|
||||
print('points:',len(pts))
|
||||
|
||||
def resid(p):
|
||||
al,be,cc,pp,ss=p
|
||||
out=[]
|
||||
for nm,a,r,c in pts:
|
||||
X=a*ss/max(r**pp,1e-12)
|
||||
out.append(al*np.log1p(X/be)+cc-c)
|
||||
return np.array(out)
|
||||
|
||||
p0=[3.28,0.56,0.77,1.25,1.0]
|
||||
lb=[0.5,0.01,-5,0.05,0.05]
|
||||
ub=[8,5,5,4,50]
|
||||
r=least_squares(resid,p0,bounds=(lb,ub),max_nfev=8000)
|
||||
mm=-resid(r.x)+np.array([c for _,_,_,c in pts])
|
||||
tgt=np.array([c for _,_,_,c in pts])
|
||||
rms=np.sqrt(((mm-tgt)**2).mean())
|
||||
print('UNIFIED: alpha=%.3f beta=%.4f c=%+.3f p=%.3f s=%.3f ; rms=%.4f max=%.3f' % (
|
||||
*r.x,rms,np.abs(mm-tgt).max()))
|
||||
for (nm,a,rr,c),pv in zip(pts,mm):
|
||||
print(' %-10s am=%.4f res=%.4f cut=%6.2f pred=%6.2f err=%+.2f' % (nm,a,rr,c,pv,c-pv))
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user