title: How can I insert int3 with ptrace in Ubuntu x64?
body: <p>I'm trying to follow <a href="http://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints/" rel="nofollow">this guide</a> to achieve the same results with setting breakpoints, the only difference is I'm on x64 system. So, I have this code for "Hello, World!":</p>
  
  <pre><code>; The _start symbol must be declared for the linker (ld)
  global _start
  
  section    .text
  _start:
  
      ; Prepare arguments for the sys_write system call:
      ;   - rax: system call number (sys_write)
      ;   - rdi: file descriptor (stdout)
      ;   - rsi: pointer to string
      ;   - rdx: string length
      mov    rax, 1
      mov    rdi, 1
      mov    rsi, msg1
      mov    rdx, len1
      syscall
  
      ; int3 should be here
  
      mov    rax, 1
      mov    rdi, 1
      mov    rsi, msg2
      mov    rdx, len2
      syscall
  
      ; Execute sys_exit
      mov    rax, 60
      mov    rdi, 0
      syscall
  
  section   .data
      msg1 db    'Hello, ', 0xa
      len1 equ    $ - msg1
      msg2 db    'world!', 0xa
      len2 equ    $ - msg2
  </code></pre>
  
  <p>This code is compiled like this:<code>nasm -f elf64 hello.s &amp;&amp; ld -s -o hello hello.o</code>:</p>
  
  <pre><code>~$ objdump -d hello    
  
  hello:     file format elf64-x86-64
  
  
  Disassembly of section .text:
  
  00000000004000b0 &lt;.text&gt;:
    4000b0:   48 b8 01 00 00 00 00    movabs $0x1,%rax
    4000b7:   00 00 00 
    4000ba:   48 bf 01 00 00 00 00    movabs $0x1,%rdi
    4000c1:   00 00 00 
    4000c4:   48 be 1c 01 60 00 00    movabs $0x60011c,%rsi
    4000cb:   00 00 00 
    4000ce:   48 ba 08 00 00 00 00    movabs $0x8,%rdx
    4000d5:   00 00 00 
    4000d8:   0f 05                   syscall 
    4000da:   48 b8 01 00 00 00 00    movabs $0x1,%rax
    4000e1:   00 00 00 
    4000e4:   48 bf 01 00 00 00 00    movabs $0x1,%rdi
    4000eb:   00 00 00 
    4000ee:   48 be 24 01 60 00 00    movabs $0x600124,%rsi
    4000f5:   00 00 00 
    4000f8:   48 ba 07 00 00 00 00    movabs $0x7,%rdx
    4000ff:   00 00 00 
    400102:   0f 05                   syscall 
    400104:   48 b8 3c 00 00 00 00    movabs $0x3c,%rax
    40010b:   00 00 00 
    40010e:   48 bf 00 00 00 00 00    movabs $0x0,%rdi
    400115:   00 00 00 
    400118:   0f 05                   syscall
  </code></pre>
  
  <p>After that, in a C program I'm trying to set a breakpoint, as it's described in the article.</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdarg.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;signal.h&gt;
  #include &lt;syscall.h&gt;
  #include &lt;sys/ptrace.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;sys/wait.h&gt;
  #include &lt;sys/reg.h&gt;
  #include &lt;sys/user.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;errno.h&gt;
  
  
  void procmsg(const char* format, ...)
  {
      va_list ap;
      fprintf(stdout, "[%d] ", getpid());
      va_start(ap, format);
      vfprintf(stdout, format, ap);
      va_end(ap);
  }
  
  void run_target(const char* programname)
  {
      procmsg("target started. will run '%s'\n", programname);
  
      /* Allow tracing of this process */
      if (ptrace(PTRACE_TRACEME, 0, 0, 0) &lt; 0) {
          perror("ptrace");
          return;
      }
  
      /* Replace this process's image with the given program */
      execl(programname, programname, (char *)NULL);
  }
  
  void run_debugger(pid_t child_pid)
  {
      int wait_status;
      struct user_regs_struct regs;
  
      procmsg("debugger started\n");
  
      /* Wait for child to stop on its first instruction */
      wait(&amp;wait_status);
  
      /* Obtain and show child's instruction pointer */
      ptrace(PTRACE_GETREGS, child_pid, 0, &amp;regs);
      procmsg("Child started. RIP = 0x%08x\n", regs.rip);
  
      unsigned addr = 0x004000da;
      unsigned data = ptrace(PTRACE_PEEKTEXT, child_pid, (void*)addr, 0);
      procmsg("Original data at 0x%08x: 0x%08x\n", addr, data);
  
      /* Write the trap instruction 'int 3' into the address */
      unsigned data_with_trap = (data &amp; 0xFFFFFF00) | 0xCC;
      ptrace(PTRACE_POKETEXT, child_pid, (void*)addr, (void*)data_with_trap);
  
      /* See what's there again... */
      unsigned readback_data = ptrace(PTRACE_PEEKTEXT, child_pid, (void*)addr, 0);
      procmsg("After trap, data at 0x%08x: 0x%08x\n", addr, readback_data);
  
      /* Let the child run to the breakpoint and wait for it to
      ** reach it
      */
      ptrace(PTRACE_CONT, child_pid, 0, 0);
  
      wait(&amp;wait_status);
      if (WIFSTOPPED(wait_status)) {
          procmsg("Child got a signal: %s\n", strsignal(WSTOPSIG(wait_status)));
      }
      else {
          perror("wait");
          return;
      }
  
      /* See where the child is now */
      ptrace(PTRACE_GETREGS, child_pid, 0, &amp;regs);
      procmsg("Child stopped at RIP = 0x%08x\n", regs.rip);
  
      /* Remove the breakpoint by restoring the previous data
      ** at the target address, and unwind the EIP back by 1 to
      ** let the CPU execute the original instruction that was
      ** there.
      */
      ptrace(PTRACE_POKETEXT, child_pid, (void*)addr, (void*)data);
      regs.rip -= 1;
      ptrace(PTRACE_SETREGS, child_pid, 0, &amp;regs);
  
      /* The child can continue running now */
      ptrace(PTRACE_CONT, child_pid, 0, 0);
  
      wait(&amp;wait_status);
  
      if (WIFEXITED(wait_status)) {
          procmsg("Child exited\n");
      }
      else {
          procmsg("Unexpected signal\n");
      }
  }
  
  
  int main(int argc, char** argv)
  {
      pid_t child_pid;
  
      if (argc &lt; 2) {
          fprintf(stderr, "Expected a program name as argument\n");
          return -1;
      }
  
      child_pid = fork();
      if (child_pid == 0)
          run_target(argv[1]);
      else if (child_pid &gt; 0)
          run_debugger(child_pid);
      else {
          perror("fork");
          return -1;
      }
  
      return 0;
  }
  </code></pre>
  
  <p>This code also compiles, but leads to a segmentation fault during execution:</p>
  
  <pre><code>~$ ./ptrace_test_bp hello                         
  [24100] debugger started
  [24101] target started. will run 'hello'
  [24100] Child started. RIP = 0x004000b0
  [24100] Original data at 0x004000da: 0x0001b848
  [24100] After trap, data at 0x004000da: 0x0001b8cc
  Hello, 
  [1]    24100 segmentation fault (core dumped)  ./ptrace_test_bp hello
  </code></pre>
  
  <p>What should I do to make it behave properly (stop on breakpoint and resume) on x64?</p>