Я написал этот код на Clang-совместимом "расширенном ассемблере GNU":
namespace foreign {
extern char magic_pointer[];
}
extern "C" __attribute__((naked)) void get_address_of_x(void)
{
asm volatile("movq %[magic_pointer], %%rax\n\t"
"ret"
: : [magic_pointer] "p"(&foreign::magic_pointer));
}
Я ожидал, что он скомпилируется в следующую сборку:
_get_address_of_x:
## InlineAsm Start
movq $__ZN7foreign13magic_pointerE, %rax
ret
## InlineAsm End
ret /* useless but I don't think there's any way to get rid of it */
Но вместо этого получаю такую "чушь":
_get_address_of_x:
movq __ZN7foreign13magic_pointerE@GOTPCREL(%rip), %rax
movq %rax, -8(%rbp)
## InlineAsm Start
movq -8(%rbp), %rax
ret
## InlineAsm End
ret
Очевидно Clang присваивает значение &foreign::magic_pointer
%rax
(что смертельно опасно для naked
функции), а затем "проливает" его на фрейм стека, которого даже не существует, чтобы он мог тянуть это снова выключено во встроенном блоке asm.
Итак, как я могу заставить Clang генерировать именно тот код, который мне нужен, не прибегая к ручному изменению имен? Я имею в виду, что я мог бы просто написать
extern "C" __attribute__((naked)) void get_address_of_x(void)
{
asm volatile("movq __ZN7foreign13magic_pointerE@GOTPCREL(%rip), %rax\n\t"
"ret");
}
но я действительно не хочу этого делать, если есть какой-то способ помочь.
Прежде чем приступить к "p"
, я попробовал ограничения "i"
и "n"
; но они, похоже, не работали должным образом с операндами 64-битных указателей. Clang продолжал выдавать мне сообщения об ошибках о невозможности выделить операнд в регистр %flags
, что похоже на что-то сумасшедшее, что-то пошло не так.
Для тех, кто заинтересован в решении "проблемы XY" здесь: я действительно пытаюсь написать гораздо более длинную сборочную заглушку, которая вызывает другую функцию foo(void *p, ...)
, где аргумент p
установлен на значение этого магического указателя, а другие аргументы установлены на основе исходные значения регистров ЦП в момент ввода этой заглушки сборки. (Следовательно, naked
функция.) Произвольная политика компании запрещает просто записать эту чертову вещь в .S
файл для начала; кроме того, я действительно хотел бы написать foreign::magic_pointer
вместо __ZN7foreign...etc...
. В любом случае, это должно объяснить, почему передача временных результатов в стек или регистры строго запрещена в данном контексте.
Возможно, есть способ написать
asm volatile(".long %[magic_pointer]" : : [magic_pointer] "???"(&foreign::magic_pointer));
чтобы заставить Clang вставить именно то перемещение, которое я хочу?
-fPIC
) - person John Bartholomew   schedule 12.12.2012...@GOTPCREL(%rip)
нет другой причины быть там - person je4d   schedule 12.12.2012.long %[magic_pointer]
идея улетучивается. Но Clang все еще должен иметь возможность кодогенировать простойleaq
илиmovq
каким-то образом, без всего этого. - person Quuxplusone   schedule 12.12.2012