Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

314
Visualizações
Diferencia en el comportamiento entre el código ejecutado por un pthread y el hilo principal en x64-assembly

Al escribir un ensamblaje x64, me topé con algo extraño. Una llamada de función funciona bien cuando se ejecuta en un subproceso principal, pero provoca un error de segmentación cuando se ejecuta como pthread. Al principio pensé que estaba invalidando la pila, ya que solo falla en la segunda llamada, pero esto no coincide con el hecho de que funciona correctamente en el subproceso principal pero falla en un subproceso recién generado.

De gdb:

 [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". Value: 1337 Value: 1337 [New Thread 0x7ffff77f6700 (LWP 8717)] Return value: 0 Value: 1337 Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0x7ffff77f6700 (LWP 8717)] __printf (format=0x600570 <fmt> "Value: %d\n") at printf.c:28 28 printf.c: No such file or directory.

¿Alguien tiene una idea de lo que podría estar pasando aquí?

 extern printf extern pthread_create extern pthread_join extern pthread_exit section .data align 4 fmt db "Value: %d", 0x0A, 0 fmt_rval db "Return value: %d", 0x0A, 0 tID dw 0 section .text global _start _start: mov rdi, 1337 call show_value call show_value ; <- this call works fine ; CREATE THREAD mov ecx, 0 ; function argument mov edx, thread_1 ; function pointer mov esi, 0 ; attributes mov rdi, tID ; pointer to threadID call pthread_create mov rdi, rax call show_rval mov rsi, 0 ; return value mov rdi, [tID] ; id to wait on call pthread_join mov rdi, rax call show_rval call exit thread_1: mov rdi, 1337 call show_value call show_value ; <- this additional call causes a segfault ret show_value: push rdi mov rsi, rdi mov rdi, fmt call printf pop rdi ret show_rval: push rdi mov rsi, rdi mov rdi, fmt_rval call printf pop rdi ret exit: mov rax, 60 mov rdi, 0 syscall

El binario se generó en Ubuntu 14.04 (64 bits, por supuesto), con:

 nasm -felf64 -g -o $1.o $1.asm ld -I/lib64/ld-linux-x86-64.so.2 -o $1.out $1.o -lc -lpthread
over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

Las funciones que toman un número variable de parámetros como printf requieren que el registro RAX esté configurado correctamente. Debe establecerlo en la cantidad de registros vectoriales utilizados, que en su caso es 0. De la Sección 3.2.3 Paso de parámetros en el sistema V ABI de 64 bits :

RAX

  • registro temporal;
  • con argumentos variables pasa información sobre el número de registros vectoriales utilizados;
  • registro de 1ra vuelta

La Sección 3.5.7 contiene información más detallada sobre el mecanismo de paso de parámetros de funciones que toman un número variable de argumentos. Esa sección dice:

Cuando se llama a una función que toma argumentos variables, %rax debe establecerse en el número total de parámetros de punto flotante pasados a la función en registros vectoriales.

Modifique su código para establecer RAX en cero en su llamada a printf :

 show_value: push rdi xor rax, rax ; rax = 0 mov rsi, rdi mov rdi, fmt call printf pop rdi ret

Tienes un problema similar con show_rval


Otra observación es que podría simplificar la vinculación de su ejecutable utilizando GCC en lugar de LD

Recomendaría cambiar el nombre de _start a main y simplemente usar GCC para vincular el ejecutable final. El código de tiempo de ejecución de C de GCC proporcionará una etiqueta _start que realiza la inicialización adecuada del tiempo de ejecución de C , lo que podría ser necesario en algunos escenarios. Cuando el código de tiempo de ejecución de C finaliza la inicialización, se transfiere (a través de una LLAMADA ) a la etiqueta main . Luego podría producir su ejecutable con:

 nasm -felf64 -g -o $1.o $1.asm gcc -o $1.out $1.o -lpthread

No creo que esto esté relacionado con su problema, pero fue más como un FYI.


Si no configura correctamente RAX para la llamada printf , en algunos casos puede ocurrir un comportamiento no deseado. En este caso, el valor de RAX que no se establece correctamente para la llamada de printf en un entorno con subprocesos provoca una falla de segmentación. El código sin subprocesos funcionó porque tuviste suerte.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda