user: Please show me the C implementation that matches the assembly code listed below:

```asm
<eiki_attach_debugger>:
  endbr64
  push   %r12
  pxor   %xmm0,%xmm0
  push   %rbp
  sub    $0x48,%rsp
  mov    %fs:0x28,%rax
  mov    %rax,0x38(%rsp)
  xor    %eax,%eax
  movaps %xmm0,(%rsp)
  movaps %xmm0,0x10(%rsp)
  call   <eiki_is_debugged@plt>
  test   %rax,%rax
  jg     L0
  lea    D12(%rip),%rbp
  mov    %rbp,%rdi
  call   <eiki_strlen@plt>
  lea    0x1(%rax),%edi
  call   <eiki_malloc@plt>
  mov    %rax,(%rsp)
  mov    %rax,%rdi
  test   %rax,%rax
  je     L57
  mov    %rbp,%rsi
  call   <eiki_strcpy@plt>
  mov    $0x20,%edi
  call   <eiki_malloc@plt>
  mov    %rax,0x8(%rsp)
  mov    %rax,%rdi
  test   %rax,%rax
  je     L35
  lea    D7(%rip),%rsi
  lea    0x20(%rsp),%r12
  call   <eiki_strcpy@plt>
  xor    %eax,%eax
  call   <getpid@plt>
  mov    %r12,%rsi
  mov    %eax,%edi
  call   <eiki_pid_to_str@plt>
  mov    0x8(%rsp),%rdi
  mov    %r12,%rsi
  call   <eiki_strcat@plt>
  mov    0x8(%rsp),%rdi
  lea    D10(%rip),%rsi
  call   <eiki_strcat@plt>
  mov    $0x10,%edi
  call   <eiki_malloc@plt>
  mov    %rax,0x10(%rsp)
  mov    %rax,%rdi
  test   %rax,%rax
  je     L35
  mov    %r12,%rsi
  call   <eiki_strcpy@plt>
  mov    %rbp,%rdi
  mov    %rsp,%rsi
  call   <eiki_execv_async@plt>
  mov    %eax,%edi
  cmp    $0xffffffff,%eax
  jne    L51
L35:
  mov    (%rsp),%rdi
L57:
  call   <eiki_free@plt>
  mov    0x8(%rsp),%rdi
  call   <eiki_free@plt>
  mov    0x10(%rsp),%rdi
  call   <eiki_free@plt>
  mov    $0xffffffff,%eax
  nop
L18:
  mov    0x38(%rsp),%rdx
  sub    %fs:0x28,%rdx
  jne    L46
  add    $0x48,%rsp
  pop    %rbp
  pop    %r12
  ret
  nopl   0x0(%rax,%rax,1)
L51:
  xor    %edx,%edx
  xor    %esi,%esi
  call   <waitpid@plt>
  mov    (%rsp),%rdi
  call   <eiki_free@plt>
  mov    0x8(%rsp),%rdi
  call   <eiki_free@plt>
  mov    0x10(%rsp),%rdi
  call   <eiki_free@plt>
  xor    %eax,%eax
  jmp    L18
  nopw   0x0(%rax,%rax,1)
L0:
  mov    $0xfffffffe,%eax
  jmp    L18
L46:
  call   <__stack_chk_fail@plt>
```

tool_calls: name: extract_symbolic_data
arguments: data_label: D12
data_type: string
name: extract_symbolic_data
arguments: data_label: D7
data_type: string
name: extract_symbolic_data
arguments: data_label: D10
data_type: string

tool: D12: /usr/bin/gdb

tool: D7: /proc/

tool: D10: /exe

assistant: ```c
int eiki_attach_debugger() {
  pid_t debugger_pid = -1;
  pid_t pid;
  char pid_str[16];
  char *argv[] = {NULL, NULL, NULL, NULL};
  if (eiki_is_debugged() > 0) {
    return -2;
  }
  argv[0] = eiki_malloc(eiki_strlen("/usr/bin/gdb") + 1);
  if (!argv[0]) {
    goto end;
  }
  eiki_strcpy(argv[0], "/usr/bin/gdb");
  argv[1] = eiki_malloc(32);
  if (!argv[1]) {
    goto end;
  }
  eiki_strcpy(argv[1], "/proc/");
  pid = getpid();
  eiki_pid_to_str(pid, pid_str);
  eiki_strcat(argv[1], pid_str);
  eiki_strcat(argv[1], "/exe");
  argv[2] = eiki_malloc(16);
  if (!argv[2]) {
    goto end;
  }
  eiki_strcpy(argv[2], pid_str);
  debugger_pid = eiki_execv_async("/usr/bin/gdb", argv);
  if (debugger_pid != -1) {
    waitpid(debugger_pid, NULL, 0);
  }
end:
  eiki_free(argv[0]);
  eiki_free(argv[1]);
  eiki_free(argv[2]);
  return (debugger_pid != -1) ? 0 : -1;
}
```