Перезапись сгенерированной сборки на встроенную сборку GCC - PullRequest
0 голосов
/ 06 февраля 2019

В CI есть:

struct segv_ctrl {
    _Bool volatile*volatile rfaulted_eh_ptr;
    _Bool volatile*volatile wfaulted_eh_ptr;
};
_Thread_local struct segv_ctrl segv_ctrl;
_Bool rfaulted_eh(char volatile*Ptr)
{
    _Bool volatile faulted=0;
    char c; _Bool r;
    segv_ctrl.rfaulted_eh_ptr = &faulted;
    #if 1
    c=*Ptr;
    r = faulted;
    #else
    //I'd like this to produce the same code as the #if block above
    //but I obviously have no idea what I'm doing :D
    __asm__ __volatile__ (
        "mov (%2),%0;\n"
        "mov %3,%1;\n"
        : "=r"(c), "=r"(r)
        : "r" (Ptr), "r"(faulted)

    );
    #endif
    return r;
}
_Bool wfaulted_eh(char volatile*Ptr)
{
    _Bool volatile faulted=0;
    _Bool r;
    segv_ctrl.wfaulted_eh_ptr = &faulted;
    #if 1
    *Ptr=0;
    r = faulted;
    #else
    #endif
    return r;
}

С лязгом от -O1 до -O3 на x86-64 он очень надежно генерирует:

c.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <rfaulted_eh>:
   0:   c6 44 24 ff 00          movb   $0x0,-0x1(%rsp)
   5:   48 8d 44 24 ff          lea    -0x1(%rsp),%rax
   a:   64 48 89 04 25 00 00    mov    %rax,%fs:0x0
  11:   00 00 
  13:   8a 07                   mov    (%rdi),%al
  15:   8a 44 24 ff             mov    -0x1(%rsp),%al
  19:   c3                      retq   
  1a:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

0000000000000020 <wfaulted_eh>:
  20:   c6 44 24 ff 00          movb   $0x0,-0x1(%rsp)
  25:   48 8d 44 24 ff          lea    -0x1(%rsp),%rax
  2a:   64 48 89 04 25 00 00    mov    %rax,%fs:0x0
  31:   00 00 
  33:   c6 07 00                movb   $0x0,(%rdi)
  36:   8a 44 24 ff             mov    -0x1(%rsp),%al
  3a:   c3                      retq   

Я хотел бы взять

mov    (%rdi),%al
mov    -0x1(%rsp),%al

деталь и

movb   $0x0,(%rdi)
mov    -0x1(%rsp),%al

деталь и превращение их в многоразовые, встроенные фрагменты сборки.

Моя очень неудачная попытка показана в блоке #if выше.Не могли бы вы объяснить, почему это не так, и возможно ли это сделать с помощью встроенной сборки?

(я использую это для дешевого обнаружения ошибок segfault (если бы не было segfault). Если я знаю длинуиз возможной инструкции segfaulting, я могу пропустить ее в моем обработчике SIGSEGV без необходимости создавать относительно дорогой sigsetjmp, но gcc не генерирует такой надежный код, поэтому я хотел бы заставить его.)

1 Ответ

0 голосов
/ 06 февраля 2019

Вторая строка просто загружает faulted из стека, вам это не нужно в asm, и оно никогда не будет сбоить (при условии, что предыдущая инициализация не сработала).Вы можете использовать

"mov (%1), %0" : "=a" (c) : "D" (Ptr)

и

"movb $0, (%1)" : "=m" (*Ptr): "D" (Ptr)

, где a - это субрегистр соответствующего размера, равный rax, который равен al для 8 битов.D - это регистр rdi.= означает вывод.m - это общий операнд памяти, используемый для указания компилятору, что asm записывает в память на *Ptr.Здесь можно не указывать, поскольку Ptr равен volatile, поэтому компилятор не будет кэшировать значение, но это не повредит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...