почему segmentation fault?

посмотрите перед меткой debug. там вызов функции inet_ntoa. я передаю ей регистр, который int содержит ip адрес клиента. и в этой функции происходит ошибка. но как такое возможно? я же передаю единственный параметр и очищаю на всякий случай rax.

global main

extern socket
extern setsockopt
extern bind
extern listen
extern read
extern perror
extern exit
extern close
extern accept
extern write
extern read
extern inet_ntoa
extern strlen
extern strncpy
extern printf

PF_INET          equ     2
SOL_SOCKET       equ     1
SO_REUSEPORT     equ    15
SOCK_STREAM      equ     1
SIZE_SOCKADDR_IN equ    16

section .text

main:
    push rbp
    mov rbp, rsp
    sub rsp, 128
;[rsp + 0]        int sock
;[rsp + 4]        int optval
;[rsp + 8]       char buffer
;[rsp + 24]       struct sockaddr_in client
;[rsp + 40]       int len of ip
;[rsp + 44]       char *ptr
;[rsp + 52]       size of struct sockaddr_in
;[rsp + 56]       int sock_client
;[rsp + 60]       struct sockaddr_in server
    xor rax, rax
    mov rdi, PF_INET
    mov rsi, SOCK_STREAM
    mov rdx, 0
    call socket
    cmp rax, 0
    jg set_option_socket_reuse_port
error_socket:
    lea rdi, [error_socket_string]
    call perror
    xor rax, rax
    mov rdi, 1
    jmp exit_program
set_option_socket_reuse_port:
    mov [rsp + 0], eax      ; sock
    xor rax, rax
    xor rdi, rdi
    xor rsi, rsi
    xor r8, r8
    xor rcx, rcx
    mov [rsp + 4], dword 1        ; optval
    mov edi, [rsp + 0]      ; sock
    mov esi, SOL_SOCKET
    mov edx, SO_REUSEPORT
    lea rcx, [rsp + 4]      ; optval
    mov r8d, 4
    call setsockopt
    cmp rax, 0
    je bind_socket
error_set_option_reuseport:
    lea rdi, [error_socket_opt_reuseport]
    call perror
    jmp exit_program
bind_socket:
    xor rax, rax
    mov ax, [server_port]
    xchg al, ah
    mov [rsp + 60 + 2], ax
    mov [rsp + 60], word PF_INET
    mov [rsp + 60 + 4], dword 0x0100007f;
    xor rdi, rdi
    mov edi, [rsp + 0]    ; sock
    lea rsi, [rsp + 60]   ; struct sockaddr_in server
    xor rdx, rdx
    mov edx, SIZE_SOCKADDR_IN
    xor rax, rax
    call bind
    cmp rax, 0
    je listen_socket
error_bind_socket:
    lea rdi, [error_socket_bind]
    call perror
    jmp exit_program
listen_socket:
    xor rax, rax
    xor rdi, rdi
    mov edi, [rsp + 0]    ; sock
    mov rsi, 0
    call listen
    cmp rax, 0
    je accept_client
error_listen_socket:
    lea rdi, [error_socket_listen]
    call perror
    jmp exit_program
accept_client:
    xor rdx, rdx
    mov edx, [size_msg_accept_client]
    lea rsi, [msg_accept_client]
    mov rdi, 1  ; sock
    xor rax, rax
    call write
    mov eax, 16
    mov [rsp + 52], eax  ;
    lea rdx, [rsp + 52] ; ptr sizeof sockaddr_in
    lea rsi, [rsp + 24] ; ptr sockaddr_in
    xor rdi, rdi
    mov edi, [rsp + 0] ; sock
    xor rax, rax
    call accept
    cmp rax, 0
    jg new_client
error_accept:
    lea rdi, [error_socket_accept]
    call perror
    jmp exit_program
new_client:
    mov [rsp + 56], dword eax
    xor rdi, rdi
    mov edi, dword [rsp + 24 + 4]
    xor rax, rax
    call inet_ntoa
    mov [rsp + 44], rax
    xor rdi, rdi
    mov rdi, [rsp + 44]
    call strlen
    inc eax
    mov [rsp + 40], eax
    xor rax, rax
    xor rdx, rdx
    mov edx, [rsp + 40]
    mov rsi, [rsp + 44]
    lea rdi, [rsp + 8]
    call strncpy
    xor rax, rax
    lea rsi, [rsp + 8]
    lea rdi, [msg_connect_client]
debug:
    call printf

exit_program:
    call exit
    leave
    ret

section .rodata
; -------------- сообщения об ошибках -----------------------
error_socket_string            db 'Не удалось открыть сокет', 0x0
error_socket_opt_reuseport     db 'Не удалось установить опцию для сокета SO_REUSEPORT', 0x0
error_socket_bind              db 'Не удалось привязать сокет', 0x0
error_socket_listen            db 'Не удалось задать параметр для прослушивания', 0x0
error_socket_accept            db 'Не удалось принять клиента', 0x0
msg_accept_client              db 'Ожидание новых клиентов', 0xa, 0x0
size_msg_accept_client         dd $ - msg_accept_client
msg_connect_client             db 'Подключился клиент: %s', 0xa, 0x0
; -------------- глобальные переменные, которые легко искать ----------
server_port     dd     8020

а вот компиляция

all:
    nasm -f elf64 server.asm -o server.o
    gcc server.o -no-pie -o test

я посмотрел код функции inet_ntoa с помощью objdump -M intel -d /usr/lib/x86_64-linux-gnu/libc-2.31.so | less, и нашел там функцию.

0000000000132aa0 <inet_ntoa@@GLIBC_2.2.5>:
  132aa0:       f3 0f 1e fa             endbr64 
  132aa4:       41 54                   push   r12
  132aa6:       89 f8                   mov    eax,edi
  132aa8:       41 89 f9                mov    r9d,edi
  132aab:       4c 8b 25 de 82 0b 00    mov    r12,QWORD PTR [rip+0xb82de]        # 1ead90 <h_errlist@@GLIBC_2.2.5+0xc70>
  132ab2:       0f b6 d4                movzx  edx,ah
  132ab5:       c1 e8 18                shr    eax,0x18
  132ab8:       40 0f b6 cf             movzx  ecx,dil
  132abc:       be 12 00 00 00          mov    esi,0x12
  132ac1:       64 4c 03 24 25 00 00    add    r12,QWORD PTR fs:0x0
  132ac8:       00 00 
  132aca:       41 c1 e9 10             shr    r9d,0x10
  132ace:       41 89 d0                mov    r8d,edx
  132ad1:       48 8d 15 bc 75 08 00    lea    rdx,[rip+0x875bc]        # 1ba094 <_libc_intl_domainname@@GLIBC_2.2.5+0x2c8f>
  132ad8:       48 83 ec 08             sub    rsp,0x8
  132adc:       4c 89 e7                mov    rdi,r12
  132adf:       45 0f b6 c9             movzx  r9d,r9b
  132ae3:       50                      push   rax
  132ae4:       31 c0                   xor    eax,eax
  132ae6:       e8 f5 23 f3 ff          call   64ee0 <__snprintf@@GLIBC_PRIVATE>
  132aeb:       58                      pop    rax
  132aec:       4c 89 e0                mov    rax,r12
  132aef:       5a                      pop    rdx
  132af0:       41 5c                   pop    r12
  132af2:       c3                      ret 

но что именно не так не могу понять, потому что в отладчике библиотека недосигаема для дизассемблера.


Ответы (0 шт):