LINUX.ORG.RU

Аналог GNU assembly на llvm

 , , ,


0

1

C ассемблером не работаю, но возникла следующая задача. Есть gcc-шная ассемблерная вставка:

void func(int a, int b)
{
__asm__ __volatile__ (
	".asciz \"%n[_SDT_S1]@%[_SDT_A1] %n[_SDT_S2]@%[_SDT_A2]\"\n"
	:: [_SDT_S1] "n" (4),
	   [_SDT_A1] "nor" ((a)), 
	   [_SDT_S2] "n" (4), 
	   [_SDT_A2] "nor" ((b))
); 
}
и нужно ее переписать на llvm assembler. Но я не смог найти аналог InputOperands на llvm.

Основная задача у меня это чтобы аргументы функции a, b преобразовать в их адреса на стеке -4(%rbp) и -8(%rbp) соответственно.

Где можно про это почитать?

★★

Последнее исправление: yetanother (всего исправлений: 1)

Почему бы не создать отдельный asm файл и не извращаться со вставками?

anonymous
()
Ответ на: комментарий от anonymous

Почему бы не создать отдельный asm файл и не извращаться со вставками?

Вариант, конечно, но это все же лишняя стадия при сборке.

yetanother ★★
() автор топика

Всё примерно аналогично GCC, https://llvm.org/docs/LangRef.html#input-constraints

Однако, показанная «ассемблерная вставка» мягко говоря странная. Она предписывает вставить в код ascii-строку, в которой будут координаты операндов (имя регистра, форма адресации памяти или immediate constant), т.е. это не код для исполнения, а некий вариант посмотреть что-куда положил компилятор. Соответственно, положить это в отдельный asm-файл примерно бессмысленно.

При этом input constraints тоже странные: «r» и «n» - регистр и чиселко, а «o» является какой-то дремучей альтернативой «m» для x86 и не поддерживается на большинстве других архитектур или обозначает совсем другое.

Я бы выкинул всё это, если нет понимания зачем оно. Если же хочется оставить, то «nor» следует заменить на «nmr» - тогда clang должен съесть. НО, код генерируемый clang-ом имеет право зависеть от порядка буквочек (потому что каждая может рассматриваться как вариант размещения операндов в предпочитаемом порядке).

Deleted
()
Ответ на: комментарий от hateyoufeel

Ты добавить лишний таргет в Makefile не можешь? Или что?

А почему ты решил что это вообще собирается с помощью make?

yetanother ★★
() автор топика
Ответ на: комментарий от Deleted

О, наконец-то ответ по теме)

Однако, показанная «ассемблерная вставка» мягко говоря странная.

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

Она предписывает вставить в код ascii-строку, в которой будут координаты операндов (имя регистра, форма адресации памяти или immediate constant), т.е. это не код для исполнения, а некий вариант посмотреть что-куда положил компилятор. Соответственно, положить это в отдельный asm-файл примерно бессмысленно.

Опять в точку. Вообще это код dtrace probe из недр gcc-6.3.0. Там вставляется nop, а потом действительно просто в секцию .note.stapsdt добавляется описание этой/этого probe - адрес этой самой nop, координаты операндов и т.д.

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

Можете подсказать, где почитать про работу с координатами операндов в llvm ассемблере? Т.е. здесь

[_SDT_S1] "n" (4)
понятно, что вместо _SDT_S1 будет подставлено непосредственно константа 4 (правда я не знаю играют ли какую роль скобки здесь). А вот здесь
[_SDT_A1] "nor" ((a))
происходит вставка операнда - `-4(%rbp)` (в данном случае). По логике здесь тогда constraint должен быть просто «r» - скорее всего «nor» это потому что макрос на все случаи жизни написан, а в данном конкретном случае достаточно «r». И у меня вопрос по поводу двойных скобок - играют они роль или нет?

yetanother ★★
() автор топика
Ответ на: комментарий от yetanother

К gas это отношение не имеет, точнее ничего кроме «.asciz».

Вам нужно просто немного освоить https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html.

В частности, квадратные скобки это синтаксис определения asmSymbolicName, т.е. назначение «имени» соответствующему параметру.

Deleted
()
Ответ на: комментарий от yetanother

Некоторые ответы только в коде GCC. Насколько помню это относится к «n» в конструкции «%n[_SDT_S1]…». Т.е. некоторые штуки не документируют, потому-что это какие-то костыли сделанные по-месту.

Deleted
()
Ответ на: комментарий от Deleted

Что-то проще выяснить потыкав палочной на https://godbolt.org/

Например, код в ТС генерирует .asciz "-4@edi -4@esi", т.е. модификатор «n» означает «negative».

Deleted
()
Ответ на: комментарий от Deleted

Да, про это «n» я не нашел ничего, но подозреваю что это от negate - по крайней мере у значения знак меняется. В принципе я решил задачу, только у меня почему-то операнды другое значение имеют. Должны быть

.asciz "-4@-4(%rbp) -4@-8(%rbp)"
а получается
.asciz "-4@-12(%rbp) -4@-16(%rbp)"
т.е. откуда-то смещение на 8 байт. Буду дальше разбираться

yetanother ★★
() автор топика
Ответ на: комментарий от yetanother

gcc -O0

func(int, int):
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], edi
        mov     DWORD PTR [rbp-8], esi
        .asciz "-4@DWORD PTR [rbp-4] -4@DWORD PTR [rbp-8]"
        nop
        pop     rbp
        ret

gcc -O3

func(int, int):
        .asciz "-4@edi -4@esi"
        ret

Понятно?

Deleted
()
Ответ на: комментарий от Deleted

Из-за оптимизации предлагается сразу обращаться к регистрам с аргументами без промежуточного копирования их в память, как я понимаю?

yetanother ★★
() автор топика
Ответ на: комментарий от yetanother

Слово «предлагается» тут как-то неуместно. Компилятор размещает данные в регистрах по своему усмотрению, что косвенно контролируется опциями компиляции и там можно получить еще массу совсем других результатов.

Короче, генерируется ровно тот «inline assembler» что должен, но что хотели исходно получить авторы и насколько наблюдаемое соответствует их ожиданию - большой вопрос.

Т.е. если что-то не работает, то эти хаки нужно просто переписывать, либо подбирать «правильные» опции компилятора.

Deleted
()
Ответ на: комментарий от Deleted

Короче, генерируется ровно тот «inline assembler» что должен, но что хотели исходно получить авторы и насколько наблюдаемое соответствует их ожиданию - большой вопрос.

Я так и предполагал после ряда экспериментов. Только вот песец подкрался незаметно - собственно инструмент (DTrace), для обеспечения работы которого я занялся погружением в ассемблер, на моей машине не заводится, то ли версия слишком старая, то ли мануалы... В общем, неожиданный поворот(

yetanother ★★
() автор топика
Ответ на: комментарий от Deleted

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

SystemTap мне не нравится тем, что там компиляция, загрузка модулей ядра - более тяжеловесный подход чем у dtrace. А вот оракловый dtrace, как я поняли, это же другой dtrace, не тот что dtrace4linux? и он с дебианом вообще совместим?

yetanother ★★
() автор топика
Ответ на: комментарий от yetanother

Вы как-то талантливо делаете что-то не то.

Работающий DTrace под Linux есть только у Oracle. Соответственно, если вдруг вам нужен именно dtrace, то просто переезжаете на «непокобелимый линупс» (aka unbreakable) от Oracle и пользуете там dtrace «из каробки».

Если же вам нужно чтобы работало на всех линуксах, то вы отказываетесь от dtrace и переезжаете на SystemTap.

Самый беспроигрышный вариант = использовать SystemTap с dtrace-макросами (DTRACE_PROBE) которые есть в sys/sdt.h из systemtap-sdt-dev их предоставляет. Так у вас будет код совместимый и с SystemTap (Linux) и c DTrace (Solaris, BSD, MacOS).

Короче, всё готово и работает «из каробки». А у вас же как-то получилось расставить грабли и ходит по ним кругами )

Deleted
()
Ответ на: комментарий от Deleted

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

Ну теперь понятно, что мне нужно использовать ваш беспроигрышный вариант, еще раз спасибо.

З.Ы. Я еще сижу изучаю eBPF, тоже штука интересная, у меня сложилось впечатление что это более перспективный подход, но хотелось бы послушать более опытных людей?

yetanother ★★
() автор топика
Ответ на: комментарий от yetanother

bpftrace уже предлагали?

Нет еще, но я уже изучаю информацию по ebpf

Из ответов выше следовало что нужно без kernel-mode и попроще. Поэтому bpftrace даже упоминать не стал.

Основная фишка bpftrace - пробники в ядре с условиями и арифметикой, а в user space он бесполезен (но можно получать инфу из ядра по своим процесса и т.п.).

Deleted
()
Ответ на: комментарий от Deleted

В общем, буду разбираться с systemtap, а там уже будет понятнее стоит ли куда-то еще двигаться.

Кстати, меня удивило, что макрос DTRACE_PROBE2 из sys/sdt.h, по факту разворачивается в systemtap probe, а не dtrace probe, что было бы логичнее. Хотя там в этой сфере (инструменты для оценки производительности) кавардак такой, что и не удивительно, с другой стороны.

yetanother ★★
() автор топика
Последнее исправление: yetanother (всего исправлений: 1)
Ответ на: комментарий от yetanother

Кстати, меня удивило, что макрос DTRACE_PROBE2 из sys/sdt.h, по факту разворачивается в systemtap probe, а не dtrace probe, что было бы логичнее.

Вы что-то опять не так поняли. Эти макросы предоставляются для совместимости, т.е. чтобы в Linux с его SystemTap можно было без изменения компилировать софт использующий DTrace.

Хотя там в этой сфере (инструменты для оценки производительности) кавардак такой, что и не удивительно, с другой стороны.

Нет, но «линейка» делается из того-же «куска дерева», который потом меряется. Поэтому много инструментов, разной стоимости, разного удобства/универсальности и для разных подзадач.

Deleted
()
Ответ на: комментарий от Deleted

Эти макросы предоставляются для совместимости,

Как же меня сбило с толку использование словосочетания systemtap/dtrace вместе. У меня отложилось что dtrace это равнозначный инструмент systemtap'у. А по факту dtrace на линуксе не было и вообще не нужно было его смотреть.

Попробовал я systemtap, не завелся он у меня тоже на астра линукс. Хотя судя по слайдам русбиттеха они его используют, подозреваю, что там из-за мрд нужно делать дополнительные телодвижения. В общем на данный момент у меня только получилось что-то более-менее похожее на какой-то результат это скомпилировать и запустить пример для bpf - мониторинг функции memcpy на предмет размера копируемой строки. Буду двигаться в этом направлении.

yetanother ★★
() автор топика
Ответ на: комментарий от anonymous

МРД - мандатное разграничение доступа

А systemtap я в итоге собрал из исходников версию 4.1 и все работает из коробки. Просто пакет systemtap из состава астры слишком старый и содержит баги уже исправленные в последних версия и плюс ядро слишком новое для него.

yetanother ★★
() автор топика
Ответ на: комментарий от yetanother

Охренеть, оказывается, я — мандатное разграничение доступа какое-то… Неприличными словами попрошу не выражаться!

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.