-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
libffi - а как это вообще работает? #2
Comments
Я знаю почему может падать, это из-за спекулятивных операций в вызываемой функции, которые помечают регистры как недоступные, и когда они сохраняются в этом месте, то выпадет SIGILL если такие были. Надо подумать, как такое решить. Точно можно решить через проверку rsize на блоки по 4 байта и сделать некрасивый switch на 16 вариантов вызовов (возможно меньше, если структуры выравниваются по 8). |
Можно попробовать сделать так, главное чтобы компилятор не сохранил ret на стек перед switch, а держал на регистрах как получил из функции. Если структура больше 64 байт, то она сразу на стеке сохраняется и на регистрах не передаётся. ret = (*(regs_t(*)(regs_t))fn)(*(regs_t*)frame);
#define COPY4(i) *(int*)(frame + i) = ret.r[i];
#define COPY8(i) frame[i] = ret.r[i];
#define COPY16(i) COPY8(i) COPY8(i+1)
#define COPY32(i) COPY16(i) COPY16(i+2)
if (rvalue)
{
switch((rsize + 3) >> 2)
{
case 1: COPY4(0) break;
case 2: COPY8(0) break;
case 3: COPY8(0) COPY4(1) break;
case 4: COPY16(0) break;
case 5: COPY16(0) COPY4(2) break;
case 6: COPY16(0) COPY8(2) break;
case 7: COPY16(0) COPY8(2) COPY4(3) break;
case 8: COPY32(0) break;
case 9: COPY32(0) COPY4(4) break;
case 10: COPY32(0) COPY8(4) break;
case 11: COPY32(0) COPY8(4) COPY4(5) break;
case 12: COPY32(0) COPY16(4) break;
case 13: COPY32(0) COPY16(4) COPY4(6) break;
case 14: COPY32(0) COPY16(4) COPY8(6) break;
case 15: COPY32(0) COPY16(4) COPY8(6) COPY4(7) break;
case 16: COPY32(0) COPY32(4) break;
}
memcpy(rvalue, frame, rsize);
} |
Первые аргументы передаются на 8-ми регистрах, это просто значит что компилятор инициализирует данные регистры из этой структуры. Тут тонкая игра на том, что компилятор должен правильно это скомпилировать (поэтому важно запускать тесты от libffi для проверки), но видимо ситуация с SIGILL проходит мимо тестов. |
Обновил патч, грануляцию по 4 байта невозможно реализовать на Си, но она и не нужна, потому что возвращаемый результат расширяется компилятором до целого регистра. |
Хм, фикс похоже не помог, потому что падает там же, где и раньше. В оригинальном патче МЦСТ вроде часть вызова функции на ассемблере написана и она вроде рабочая, а вот касты указателей на функцию из одного типа в другой кажется сломаным. Пример нерабочего - blivet из питона для анаконды например или webkit minibrowser. |
Еще про ffi_closure_e2k() забыл, там с приходящими регистрами нужно так же делать. |
Обновил патч, сделал то же самое для ffi_closure, судя по ассемблеру компилятор сделал как надо. |
Нет, на тестах питона падает, похоже нужна инструкция спекулятивного сохранения в память, даже сохранение находится под условным выполнением и условие не выполнено. |
Проблему с "грязными" значениями из спекулятивных вычислений решил, патч обновил. |
libffi так и не работает нормально
|
Пишите что-ли версию компилятора и опции компиляции, и работает ли с либой пропатченной МЦСТ (если у вас есть доступ). Запускали ли тесты в самом libffi после сборки. |
Лог сборки, тут есть и флаги и оции сборки версия компилятора 1.25.24 |
Добавьте проверку в спек, в Альте сделано так:
|
Тесты падают вот таким образом.
Я так понимаю по большей части make check отрабатывает нормально |
Может каких-то пакетов не хватает для сборки с проверкой, вроде С++ компилятора. testsuite/libffi.closures содержит два С++ теста. Также из спеки Альта:
Что один из тестов завис нехорошо. Есть ли в логах ошибки какое-то указание какую функцию вызывает pyanaconda через FFI? |
Вот еще наблюдение я взял libffi_3.3-vd7_e2k-8c.deb из PDK 7.2
опции сборки тоже не хитрые
Подозреваю что в PDK забыли положить патчей по остальным пунктам что не хватает чего типа с++ |
Это в старом спеке нет, который для 3.2 с патчами от МЦСТ (закрытыми под NDA).
Не положили потому что у них патчи закрытые, надо требовать и долго ждать пока выложат и если выложат когда-то. Я пытаюсь делать опенсорсные, но секретных знаний иногда не хватает. Если бы я знал что там вызывается через FFI, было бы понятнее как исправить. Можете через gdb попробовать понять в каком месте падает. |
А вот с gdb большой вопрос
в результате не понятно как вытащит хороший трейс |
А можете выложить libffi.so* собранные на альте 3.3 версии |
Я заметил, что ffi_call вызывают используя для результата тип ffi_arg, равный по размеру 8 байт. Код из теста, для примера:
|
Где исходники вашего pyanaconda? У них код слишком меняется в isys, я нашел две версии со значительными различиями. |
git: https://abf.io/import/anaconda бранч rosa2021.1 rpms: http://abf-downloads.rosalinux.ru/rosa2021.1/container/4105557/e2kv4/main/release/ файл /usr/lib64/python3.8/site-packages/pyanaconda/_isys.so |
мне тут говорят что в альте актуальная версия для e2k |
Для Эльбруса (и для большинства архитектур) не существует такого пакета, только для riscv64 и mipsel: https://packages.altlinux.org/ru/sisyphus_mipsel/srpms/libffi6/specfiles/ И я не знаю зачем он вообще создан, для этих архитектур это старая версия, а не актуальная. |
Лучше дайте мне свой libffi собранный с патчем, я дизассемблирую и посмотрю это место: /usr/lib64/libffi.so.7(ffi_call+0x708)[0x4623bee9e370] |
Я обновил патч на основе моих предположений что это могло быть. Одно из предположений неверное, второе с расширением целых чисел - вряд ли влияет, так что наверное будет падать так же. Мне надо стектрейс падения и библиотеку от одной и той же компиляции библиотеки. |
Обновленный патч сейчас наложу и попробую запустить. Попробовал, не помогло
На всякий случай вот еще работающей libffi.so.7 от м ц с т |
Место падения выглядит странно, это сохранение в стек возвращаемого значения после вызова функции. Указатель неправильным быть не может, значит возвращаемое значение было спекулятивным с тегом указывающим ошибку. Что может случиться когда вызывают функцию что не возвращает аргументов, и от неё приходит какой-то мусор. Да, с кодом МЦСТ это будет работать, потому что они сохраняют возврат инструкцией что не кидает ошибку на тегах указывающих ошибку. Я сейчас переписал кусок ffi_call на ассемблер и тестирую такую версию. В такой ситуации это должно работать так же как в коде МЦСТ. Вот только тут может баг в anaconda. |
Можно мне патч? Я быстро протестирую. |
Вот предварительный патч https://pastebin.com/FSPBatTw |
А помогло!
|
Пару макросов переименовал и закоммитил этот патч. |
А можешь дать свой тг? У меня есть кое-что, что тут выложить не могу. |
Почта в патче написана, если "тг" означает Телеграм, то там меня нет и не будет. |
2 момента:
The text was updated successfully, but these errors were encountered: