Pull to refresh
118
0
Анатолий Тросиненко @atrosinenko

Программист

Send message

Салат Фибоначчи: ускоряем минимизатор исходников с помощью seccomp и форк-сервера

Reading time 10 min
Views 1.1K

Как говорилось в одном анекдоте, «Салат Фибоначчи готовится из того, что осталось от вчерашнего и позавчерашнего салата Фибоначчи». Вот и сейчас попробуем на практике применить перехват системных вызовов через seccomp для целей ускорения минимизации исходника при сохранении инварианта. До кучи, проблема будет решаться посредством инжектирования форк-сервера, очень похожего на тот, который используется в American Fuzzy Lop. И всё это будет управляться из Java-кода.


Для тех, кто уже настроился почитать про модификацию чужих процессов через ptrace прямо из Java — нет, всё не настолько сурово, я просто на ходу собираю .so из .c и вгружаю через LD_PRELOAD.


Для тех же, кто уже подумал «Знаю я этот AFL — компилятор придётся патчить и пересобирать!», скажу, что в том и смысл использования seccomp: мы на ходу поймаем момент, когда произойдёт первое обращение ко входному файлу.


Есть конечно и ложка дёгтя: компилятор должен быть однопоточным, однопроцессным и на Линуксе, но в реально-тестовой задаче минимизации примера бага в компиляторе из OpenModelica удалось добиться ускорения раз в 5.

Читать дальше →
Total votes 3: ↑3 and ↓0 +3
Comments 5

Часть 6: Портирование MemTest86+ на RISC-V

Reading time 21 min
Views 8.2K

Наверное, мало какому айтишнику нужно объяснять, что такое Memtest86+ — пожалуй, он уже стал более-менее стандартом в тестировании оперативной памяти на ПК. Когда в одной из предыдущих частей я наткнулся на битую планку памяти, пришедшую в комплекте с платой, он (вместе с поддерживающим DDR2 нетбуком) казался очевидным решением. Другой вопрос, что там в принципе нестабильная работа системы была видна невооружённым глазом. В более хитрых случаях, слышал, что кроме банального «простукивания» ячеек памяти до бесконечности, этот инструмент использует некоторые специальные паттерны данных, на которых ошибки в работе DDR выявляются с большей вероятностью. В общем чудесная вещь, жаль, что даже в названии указано: 86 — «Только для x86-совместимых систем». Или нет?


Под катом вы увидите мои попытки портировать MemTest86+ v5.1 на RISC-V и промежуточный итог. Спойлер: оно шевелится!

Читать дальше →
Total votes 52: ↑52 and ↓0 +52
Comments 26

А суть-то в чём, или Минимизация исходников — проще, чем кажется

Reading time 9 min
Views 5.9K

В эти чудесные январские дни всех нас, конечно, волнует вопрос минимизации исходного кода с сохранением инварианта. В смысле, не волнует?!? Зря… Вот упал у вас компилятор, а программа гигантская — как-то неудобно такое разработчикам слать. И тут начинается веселье: а если вот это выкинуть? О, не падает — ладно, оставляем, а если это? — всё ещё падает, и это, и это, и то… Ой, я компилятор на старых исходниках запускал.


В то же время, автоматизация поиска багов — дело-то житейское: git bisect, llvm-bugpoint, creduce,… В статье я опишу yet another способ решения проблемы упрощения тестового случая, более-менее универсальный по отношению к языку программирования, и покажу некоторые примеры использования.

Читать дальше →
Total votes 12: ↑10 and ↓2 +8
Comments 5

Linux Kernel Library: ядро Linux в форм-факторе so или dll

Reading time 13 min
Views 14K

Когда-то читал статью о выборе файловых систем «чтоб везде-везде работало». В ней в очередной раз увидел жалобы, что Ext4 замечательная файловая система, но на Windows есть только кривые неточные проприетарные драйверы. Но отмотаем ленту ещё на пару лет назад: тогда на Хабре (а в те времена — Гиктаймсе) пролетала новость про LibOS — попытку превратить Linux kernel в обычную библиотеку пользовательского режима. Упор там делался на вынос сетевого стека в user space. Как-то раз я решил поглядеть, а жив ли вообще проект, и в их блоге увидел ссылку на своего рода конкурента — проект Linux Kernel Library (LKL). По сути, это порт ядра, так сказать, на аппаратную архитектуру «библиотека пользовательского режима POSIX / Win32».


Чем интересна LKL? Во-первых тем, что она живёт и здравствует, пусть и не в основной кодовой базе ядра. Во-вторых, это более-менее честная поддержка «архитектуры», автоматически делающая доступной бОльшую часть ядра. Более того, прямо в комплекте идут утилиты-примеры: cptofs/cpfromfs, fs2tar, lklfuse. В этой статье мы протестируем LKL на хостовом Linux, заглянем в файл с образом Ext4 (Btrfs, XFS...) без рута и виртуалок и коротко обсудим, как её можно попробовать на Windows.

Читать дальше →
Total votes 22: ↑22 and ↓0 +22
Comments 5

Необычные системные вызовы на Linux

Reading time 17 min
Views 24K

ls /usr/share/man/man2/


Что видит программист, начиная работать с языком C? Он видит fopen, printf, scanf и ещё много других функций. Видит он и всякие open и mmap — казалось бы, зачем их выделять? Но, в отличие от первой группы, эти две функции при выполнении на ядре Linux являются системными вызовами (на самом деле нет, почти никогда системный вызов нельзя просто вызвать как функцию, и поэтому libc содержит обёртки, перепаковывающие аргументы и иногда, как в случае с тем же open, заменяющие старые системные вызовы более общими новыми). Вообще, в отличие от тысяч библиотечных функций, доступных на типичной GNU/Linux системе, интерфейс ядра имеет довольно ограниченное количество точек входа — порядка нескольких сотен, зато то, что для user space — crash (например, обращение к отсутствующей странице), для ядра — default mode of operation.


В этой статье я расскажу некоторые интересные на мой взгляд факты. В ней не будет futex-ов и прочих скучных (наверное) деталей реализации. Будет преимущественно то, что вызывало у меня реакцию «А что, так можно было?!?».

Читать дальше →
Total votes 64: ↑64 and ↓0 +64
Comments 8

Что делать, если для вашего любимого языка нет статического анализатора?

Reading time 12 min
Views 4K

Ну, если под любимым языком подразумевается русский, английский и т. д., то это в другой хаб. А если язык программирования или разметки, то конечно писать анализатор самим! На первый взгляд, это очень сложно, но, к счастью, существуют готовые многоязыковые инструменты, в которые относительно легко добавить поддержку нового языка. Сегодня я покажу, как можно с достаточно незначительными затратами времени добавить поддержку языка Modelica в анализатор PMD.


Кстати, знаете, что может ухудшить качество кодовой базы, полученной из последовательности идеальных pull request-ов? Тот факт, что сторонние программисты копировали в свои патчи куски существующего кода проекта вместо грамотного абстрагирования. Согласитесь, в какой-то мере такую банальность отловить ещё сложнее, чем некачественный код — он же качественный и даже уже тщательно отлаженный, поэтому тут недостаточно локальной проверки, нужно держать в голове всю кодовую базу, а человеку это непросто… Так вот: если на добавление полной поддержки Modelica (без создания конкретных правил) до состояния «может запускать примитивные проверки» у меня ушло около недели, то поддержку только copy-paste detector часто можно вообще добавить за день!

Узнать как...
Total votes 29: ↑29 and ↓0 +29
Comments 0

Обработка системных вызовов посредством LD_PRELOAD с единой точкой входа

Reading time 24 min
Views 2.3K

Делая пере-реализацию QInst на LLVM, я столкнулся с такой проблемой: QEMU в режиме эмуляции одного процесса естественным образом перехватывает все «гостевые» системные вызовы. В итоге плагин инструментации имеет единую точку входа для их предобработки, где можно по номерам SYS_* и значениям аргументов принимать решения. Это довольно удобно. Проблема в том, что все системные вызовы делает, в основном, libc и, переписывая код статически, мы просто до этой части в большинстве случаев не доберёмся. Конечно, можно было бы использовать ptrace, который как раз предназначен и для этого в том числе. Но тогда не уверен, что получилось бы обойтись без отдельного процесса, а семантика QInst предполагала тривиальный «синхронный» перехват — пришлось бы как-то инжектить вызов обработчика, а это сильно сложнее привычного LD_PRELOAD. Можно оборачивать каждый системный вызов — но это, как минимум, неудобно (к тому же, можем что-нибудь пропустить, ведь в этом случае мы перехватываем на самом не системные вызовы, а их конкретные обёртки).


Под катом — решение, не привязанное к LLVM, но заточенное под Linux на x86_64 (но адаптируемое для Linux на других архитектурах).


Примечание: в этой статье не представлено универсального готового решения — оно лишь подходит для достаточно широкого списка случаев. Зато эту статью можно считать обзорно-пятничной: интересная (надеюсь) новая (для большинства?) информация, щепотка брутфорс-программирования и рабочие примеры. И пусть нашу пятницу не омрачает даже тот факт, что сегодня четверг!

Читать дальше →
Total votes 13: ↑13 and ↓0 +13
Comments 3

Часть 5/2 корп. 1: Перекрёсток проспекта RocketChip и скользкой дорожки инструментации

Reading time 17 min
Views 1.4K

В предыдущих четырёх частях велась подготовка к экспериментам с RISC-V ядром RocketChip, а именно, портирование этого ядра на «нестандартную» для него плату с ПЛИС фирмы Altera (теперь уже Intel). Наконец, в прошлой части на этой плате получилось запустить Linux. Знаете, что меня во всём этом забавляло? То, что одновременно приходилось работать с ассемблером RISC-V, C и Scala, и из всех них Scala была самым низкоуровневым языком (потому что именно на ней написан процессор).


Давайте в этой статье сделаем так, чтобы C тоже не было обидно. Более того, если связка Scala+Chisel использовалась лишь как domain-specific language для явного описания аппаратуры, то сегодня мы научимся «затягивать» простенькие функции на C в процессор в виде инструкций.


Конечная же цель — тривиальная реализация тривиальных AFL-like инструментаций по аналогии с QInst, а реализация отдельностоящих инструкций — лишь побочный продукт.

Читать дальше →
Total votes 19: ↑19 and ↓0 +19
Comments 0

Часть 4: Всё-таки запускаем Linux на RocketChip RISC-V

Reading time 34 min
Views 9.8K

На картинке Linux kernel шлёт вам привет через GPIO.


В этой части истории с портированием RISC-V RocketChip на китайскую плату с Cyclone IV мы всё-таки запустим Linux, а также научимся сами конфигурировать IP Core контроллера памяти и чуть подредактируем dts-описание аппаратуры. Эта статья является продолжением третьей части, но, в отличие от изрядно разросшейся предыдущей, она будет довольно короткой.

Читать дальше →
Total votes 34: ↑32 and ↓2 +30
Comments 3

Часть 3: Почти что грузим Linux с SD-карты на RocketChip

Reading time 23 min
Views 7K

В предыдущей части был реализован более-менее работающий контроллер памяти, а точнее — обёртка над IP Core из Quartus, являющаяся переходником на TileLink. Сегодня же в рубрике «Портируем RocketChip на малоизвестную китайскую плату с Циклоном» вы увидите работающую консоль. Процесс несколько затянулся: я уже было думал, что сейчас по-быстрому запущу Linux, и пойдём дальше, но не тут то было. В этой части предлагаю посмотреть на процесс запуска U-Boot, BBL, и робкие попытки Linux kernel инициализироваться. Но консоль есть — U-Boot-овская, и довольно-таки продвинутая, имеющая многое из того, что вы ожидаете от полноценной консоли.


В аппаратной части добавится SD-карта, подключённая по интерфейсу SPI, а также UART. В программной части BootROM будет заменён с xip на sdboot и, собственно, добавлены следующие стадии загрузки (на SD-карте).

Читать дальше →
Total votes 22: ↑20 and ↓2 +18
Comments 12

Часть 2: RocketChip: подключаем оперативную память

Reading time 12 min
Views 7.6K

В предыдущей части мы собрали микроконтроллер вообще без оперативной памяти на базе ПЛИС Altera/Intel. Однако на плате есть разъём с установленным SO-DIMM DDR2 1Gb, который, очевидно, хочется использовать. Для этого нам потребуется обернуть DDR2-контроллер с интерфейсом ALTMEMPHY в модуль, понятный для протокола работы с памятью TileLink, используемого повсюду в RocketChip. Под катом — тактильная отладка, брутфорс программирование и ГРАБЛИ.


Как известно, в Computer Science есть две главные проблемы: инвалидация кешей и именование переменных. На КДПВ вы видите редкий момент — две главные проблемы CS встретили друг друга и что-то замышляют.

Читать дальше →
Total votes 16: ↑16 and ↓0 +16
Comments 2

Часть 1: RISC-V / RocketChip в неестественной среде обитания

Reading time 15 min
Views 9.5K
Конфигурирование RocketChip

Недавно на Хабре публиковалась статья о том, как поэкспериментировать с архитектурой RISC-V без затрат на «железо». А что, если сделать подобное на отладочной плате? Помните мемы про генератор игр: штук 20 галочек в стиле «Графика не хуже Кризиса», «Можно грабить корованы» и кнопка «Сгенерировать». Приблизительно так же устроен генератор SoC-ов RocketChip, только там не окно с галочками, а Scala-код и немного ассемблера и Make-файлов. В этой статье я покажу, как просто портировать этот RocketChip с родного для него Xilinx на Altera/Intel.

Читать дальше →
Total votes 22: ↑22 and ↓0 +22
Comments 0

Часть 1. QInst: лучше день потерять, потом за пять минут долететь (пишем инструментацию тривиально)

Reading time 8 min
Views 2.1K

В предыдущей части я приблизительно описал, как можно загрузить eBPF функции из ELF-файла. Теперь пришла пора перейти от фэнтези к советским мультикам, и следуя мудрому совету, потратив один раз некоторое количество усилий, сделать универсальный инструмент инструментации (или, сокращённо, УИИ!!!). При этом я воспользуюсь антипаттерном проектирования «Золотой молоток» и сооружу инструмент из относительно знакомого мне QEMU. Бонусом за это мы получим кросс-архитектурную инструментацию, а также инструментацию на уровне целого виртуального компьютера. Инструментация будет вида «небольшой нативный so-шничек + небольшой .o-файл с eBPF». При этом eBPF-функции будут подставляться перед соответствующими инструкциями внутреннего представления QEMU перед оптимизацией и кодогенерацией.


В итоге сама инструментация, добавляемая при кодогенерации (то есть, не считая пары килобайтов обычного сишного рантайма), выглядит вот так, и это не псевдокод:


#include <stdint.h>

extern uint8_t *__afl_area_ptr;
extern uint64_t prev;

void inst_qemu_brcond_i64(uint64_t tag, uint64_t x, uint64_t y, uint64_t z, uint64_t u)
{
    __afl_area_ptr[((prev >> 1) ^ tag) & 0xFFFF] += 1;
    prev = tag;
}

void inst_qemu_brcond_i32(uint64_t tag, uint64_t x, uint64_t y, uint64_t z, uint64_t u)
{
    __afl_area_ptr[((prev >> 1) ^ tag) & 0xFFFF] += 1;
    prev = tag;
}

Что же, пора загрузить нашего эльфа в Матрицу. Ну, как загрузить, скорее вмазать распылить.

Читать дальше →
Total votes 9: ↑9 and ↓0 +9
Comments 0

Часть 0. Требуется эльф для работы в Матрице. Возможна релокация

Reading time 8 min
Views 6.6K

Внимание: содержит системное программирование. Да, в сущности, ничего другого и не содержит.


Давайте представим, что вам дали задание написать фэнтезийно-фантастическую игру. Ну там про эльфов. И про виртуальную реальность. Вы с детства мечтали написать что-нибудь эдакое и, не раздумывая, соглашаетесь. Вскоре вы понимаете, что о мире эльфов вы знаете по большей части из анекдотов со старого башорга и прочих разрозненных источников. Упс, неувязочка. Ну, где наша не пропадала… Наученный богатым программистским опытом, вы отправляетесь в Гугл, вводите «Elf specification» и идёте по ссылкам. О! Вот эта ведёт на какую-то PDF-ку… так, что тут у нас… какой-то Elf32_Sword — эльфийские мечи — похоже, то что нужно. 32 — это, по-видимому, уровень персонажа, а две четвёрки в следующих столбцах — это урон, наверное. Точно то, что нужно, да к тому же как систематизировано!..

Ну-с, приступим...
Total votes 24: ↑22 and ↓2 +20
Comments 1

QEMU.js: теперь по-серьёзному и с WASM

Reading time 13 min
Views 13K

Когда-то давно я смеха ради решил доказать обратимость процесса и научиться генерировать JavaScript (а точнее, Asm.js) из машинного кода. Для эксперимента был выбран QEMU, некоторое время спустя была написана статья на Хабр. В комментариях мне посоветовали переделать проект на WebAssembly, да и самому бросать почти законченный проект как-то не хотелось… Работа шла, но уж очень медленно, и вот, недавно в той статье появился комментарий на тему «Так и чем всё закончилось?». На мой развёрнутый ответ я услышал «Это тянет на статью». Ну, раз тянет, то будет статья. Может, кому пригодится. Из неё читатель узнает некоторые факты про устройство бекендов кодогенерации QEMU, а также как написать Just-in-Time компилятор для веб-приложения.

Читать дальше →
Total votes 55: ↑55 and ↓0 +55
Comments 8

Подборка полезностей для программиста под Linux

Reading time 44 min
Views 17K

Думаю, у каждого программиста есть набор любимых утилит, трюков и знаний. Некоторые он даже использует в работе. Скорее всего, у разных программистов они различаются. Значит, пришло время поделиться. Сегодня я расскажу о своей подборке того, что, вероятно, известно не настолько широко, как оно того заслуживает. Речь пойдёт преимущественно про платформу GNU/Linux.

Читать дальше →
Total votes 33: ↑33 and ↓0 +33
Comments 6

Open source: кодоюмор, кодотрюки, НЕ кодобред

Reading time 9 min
Views 11K

Старый GLib vs новый Clang


Ковыряясь в разнообразном СПО, я периодически нахожу всякие интересные штуки: иногда это просто смешной комментарий, иногда — нечто остроумное в более широком смысле. Подобные подборки периодически появляются и в «глобальном Интернете», и на Хабре — есть, скажем, широко известный вопрос на StackOverflow про комментарии в коде, а здесь недавно публиковалась подборка забавных названий юрлиц и топонимов. Попробую и я структурировать и выложить то, что постепенно у меня копилось. Под катом вас ждут цитаты из QEMU, ядра Linux, и не только.

Читать дальше →
Total votes 38: ↑38 and ↓0 +38
Comments 12

Заметки дилетанта, или Сказ о том, как Scala-разработчик ПЛИС конфигурировал

Reading time 18 min
Views 8.4K

Долгое время я мечтал научиться работать с FPGA, присматривался. Потом купил отладочную плату, написал пару hello world-ов и положил плату в ящик, поскольку было непонятно, что с ней делать. Потом пришла идея: а давайте напишем генератор композитного видеосигнала для древнего ЭЛТ-телевизора. Идея, конечно, забавная, но я же Verilog толком не знаю, а так его ещё и вспоминать придётся, да и не настолько этот генератор мне нужен… И вот недавно захотелось посмотреть в сторону RISC-V софт-процессоров. Нужно с чего-то начать, а код Rocket Chip (это одна из реализаций) написан на Chisel — это такой DSL для Scala. Тут я внезапно вспомнил, что два года профессионально разрабатываю на Scala и понял: время пришло...


Так что, если хотите почитать историю из жизни кусачек, цифрового мультиметра и осциллографа, который осознал себя, то добро пожаловать под кат.

Читать дальше →
Total votes 32: ↑32 and ↓0 +32
Comments 16

GraalVM: смешались в кучу C и Scala

Reading time 12 min
Views 7.9K

Не знаю, как на вас, а на меня в последнее время производят сильное впечатление статьи про новые Java-технологии — Graal, Truffle и все-все-все. Выглядит так, как будто раньше ты придумал язык, написал интерпретатор, порадовался какой язык хороший и погрустил, какой медленный, написал к нему нативный компилятор и/или JIT, а ведь нужен ещё отладчик… LLVM есть, и на том спасибо. После прочтения этой статьи сложилось (несколько гротескное) впечатление, что после написания интерпретатора специального вида работу можно, в принципе, и завершать. Ощущение, что теперь кнопка "Сделать зашибись" стала доступна и программистам-компиляторщикам. Нет, конечно, JIT-языки медленно стартуют, им нужно время на прогрев. Но, в конце концов, время и квалификация программиста тоже не бесплатные — в каком бы мире информационных технологий мы бы жили, если бы до сих пор писали всё на ассемблере? Нет, может, всё бы, конечно, и летало (это если программист грамотно инструкции разложил), но вот насчёт суммарной сложности активно используемых программ у меня есть некоторые сомнения...


В общем, я прекрасно понимаю, что в дилемме «затраченное программистом время vs идеальность полученного продукта ("ручная работа")» границу можно двигать до скончания веков, поэтому давайте сегодня просто попробуем воспользоваться традиционной библиотекой SQLite без подгрузки нативного кода в чистом виде. Будем использовать уже готовую truffle-реализацию языка для LLVM IR, зовущуюся Sulong.

Читать дальше →
Total votes 17: ↑17 and ↓0 +17
Comments 3

Динамическая инструментация — не просто, а тривиально*: пишем yet another инструментацию для American Fuzzy Lop

Reading time 27 min
Views 12K

(*) На самом деле, не совсем.
Наверное, многие слышали про Valgrind — отладчик, который может сказать, где в вашей нативной программе утечка памяти, где ветвление зависит от неинициализированной переменной и многое другое (а ведь кроме memcheck, у него есть и другие режимы работы). Внутри себя эта чудо-программа перемалывает нативный код в некий промежуточный байткод, инструментирует его и генерирует новый машинный код — уже с run-time проверками. Но есть проблема: Valgrind не умеет работать под Windows. Когда мне это понадобилось, поиски привели меня к аналогичной утилите под названием DrMemory, также с ней в комплекте был аналог strace. Но речь не столько о них, сколько о библиотеке динамической инструментации, на базе которой они построены, DynamoRIO. В какой-то момент я заинтересовался этой библиотекой с точки зрения написания собственной инструментации, начал искать документацию, набрёл на большое количество примеров и был поражён тем, что простенькую, но законченную инструментацию вроде подсчёта инструкций вызова можно написать буквально в 237 строк сишного кода, 32 из которых — лицензия, а 8 — описание. Нет, это, конечно не "пишем убийцу Valgrind в 30 строк кода на JavaScript", но сильно проще, чем то, что можно представить для подобной задачи.


В качестве примера давайте напишем уже четвёртую реализацию инструментации для фаззера American Fuzzy Lop, о котором недавно уже писали на Хабре.

Читать дальше →
Total votes 21: ↑21 and ↓0 +21
Comments 1
1

Information

Rating
Does not participate
Location
Санкт-Петербург, Санкт-Петербург и область, Россия
Date of birth
Registered
Activity