0x0000000008001946:  mov    0xa8(%rdx),%rax
   0x000000000800194d:  lea    0x28(%rdx),%rsi
   0x0000000008001951:  lea    0x2(%rax),%rdi
   0x0000000008001955:  add    $0xe,%rax
   0x0000000008001959:  mov    %rax,0xa8(%rdx)
   0x0000000008001960:  jmpq   0x8001ee0

Above is the full disassembly of a signal handler which is customarily set by the program which I'm looking into, i.e., the program registers the signal handler and immediately invokes it by raising a SIGILL using the opcode ud2.

The signal handler is registered here:

   0x8001965:   push   %rbx
   0x8001966:   xor    %eax,%eax
   0x8001968:   mov    $0x26,%ecx
   0x800196d:   sub    $0xa0,%rsp
   0x8001974:   lea    0x8(%rsp),%rdi
   0x8001979:   rep stos %eax,%es:(%rdi)
   0x800197b:   lea    -0x3c(%rip),%rax        # 0x8001946
   0x8001982:   lea    0x10(%rsp),%rdi
   0x8001987:   movl   $0x8000004,0x90(%rsp)
   0x8001992:   mov    %rax,0x8(%rsp)
   0x8001997:   callq  0x8000f60 <sigfillset@plt>
   0x800199c:   xor    %edx,%edx
   0x800199e:   test   %eax,%eax
   0x80019a0:   jne    0x80019bb
   0x80019a2:   lea    0x8(%rsp),%rbx
   0x80019a7:   xor    %edx,%edx
   0x80019a9:   mov    $0x4,%edi
   0x80019ae:   mov    %rbx,%rsi
   0x80019b1:   callq  0x8000f90 <sigaction@plt>

Where 0x8001946 is the address of the handler, as disassembled prior to that in the first code-block.

My question is regarding the first instruction of the signal handler which appears to make no sense at all, and I can't debug it since I can't put a breakpoint on it:

0x0000000008001946:  mov    0xa8(%rdx),%rax

%rdx is defined by the ABI as the third parameter passed to a function, and as defined by sigaction the third argument of sa_sigaction is a void * (a casted ucontext_t structure) but there is no 0xa8th index into the definition of a struct ucontext_t, which leads me to believe it's something else.

I thought it might be an %rdx set before the ud2 instruction is called:

   0x0000000008000fde:  test   %al,%al
   0x0000000008000fe0:  mov    $0x2,%edx
   0x0000000008000fe5:  je     0x8001028
   0x0000000008000fe7:  movslq %ebx,%rdi
   0x0000000008000fea:  mov    %rbp,%rsi
   0x0000000008000fed:  callq  0x8001190

But prior to the call to 0x80001190 (the bug), %rdx only contains $0x2. So I'm even more confused.

Could anyone shed some light on what %rdx could contain at 0x8001946 after a SIGILL is raised, and the signal is passed off to the custom handler defined at that address?

1 Answer 1


It seems to be %rip (the address of the ud2):

#include <signal.h>
#include <stdio.h>
#include <ucontext.h>

void handler(int signo, siginfo_t *info, void *context) {
    ucontext_t *uc = (ucontext_t*)context;
    printf("%llx\n", uc->uc_mcontext.gregs[REG_RIP]);

compiles to:

handler(int, siginfo_t*, void*):
        movq    168(%rdx), %rsi
        movl    $.L.str, %edi
        xorl    %eax, %eax
        jmp     printf
        .asciz  "%llx\n"


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.