Onde você encontra a tabela syscall para Linux?

5

Eu vejo muitas pessoas referenciando on-line

arch/x86/entry/syscalls/syscall_64.tbl

para a tabela syscall, que funciona bem. Mas muitas outras referências

/include/uapi/asm-generic/unistd.h

, que é comumente encontrado no pacote de cabeçalhos. Como é que syscall_64.tbl mostra,

0 common  read      sys_read

A resposta certa e unistd.h mostram

#define __NR_io_setup 0
__SC_COMP(__NR_io_setup, sys_io_setup, compat_sys_io_setup)

E, em seguida, mostra __NR_read como

#define __NR_read 63
__SYSCALL(__NR_read, sys_read)

Por que isso é 63 e não 1? Como faço para entender /include/uapi/asm-generic/unistd.h ? Ainda em /usr/include/asm/ existe

/usr/include/asm/unistd_x32.h
#define __NR_read (__X32_SYSCALL_BIT + 0)
#define __NR_write (__X32_SYSCALL_BIT + 1)
#define __NR_open (__X32_SYSCALL_BIT + 2)
#define __NR_close (__X32_SYSCALL_BIT + 3)
#define __NR_stat (__X32_SYSCALL_BIT + 4)

/usr/include/asm/unistd_64.h
#define __NR_read 0
#define __NR_write 1
#define __NR_open 2
#define __NR_close 3
#define __NR_stat 4

/usr/include/asm/unistd_32.h
#define __NR_restart_syscall 0
#define __NR_exit 1           
#define __NR_fork 2           
#define __NR_read 3           
#define __NR_write 4          

Alguém poderia me dizer a diferença entre esses arquivos unistd . Explique como unistd.h funciona? E qual o melhor método para encontrar a tabela syscall?

    
por Evan Carroll 04.02.2018 / 05:40

4 respostas

3

Quando estou investigando esse tipo de coisa, acho útil perguntar ao compilador diretamente (consulte Imprimindo o padrão C / Macros pré-definidas no GCC no terminal para detalhes):

printf "#include <sys/syscall.h>\nSYS_read" | gcc -E -

Isso mostra que os cabeçalhos envolvidos (no Debian) são /usr/include/x86_64-linux-gnu/sys/syscall.h , /usr/include/x86_64-linux-gnu/asm/unistd.h , /usr/include/x86_64-linux-gnu/asm/unistd_64.h e /usr/include/x86_64-linux-gnu/bits/syscall.h e imprime o número da chamada do sistema para read , que é 0 em x86-64.

Você pode encontrar os números de chamada do sistema para outras arquiteturas se tiver os cabeçalhos de sistema apropriados instalados (em um ambiente de compilador cruzado). Para x86 de 32 bits, é muito fácil:

printf "#include <sys/syscall.h>\nSYS_read" | gcc -m32 -E -

que envolve /usr/include/asm/unistd_32.h entre outros arquivos de cabeçalho e imprime o número 3.

Portanto, da perspectiva do espaço de usuário, as chamadas do sistema x86 de 32 bits são definidas em asm/unistd_32.h , chamadas do sistema x86 de 64 bits em asm/unistd_64.h . asm/unistd_x32.h é usado para a x32 ABI .

uapi/asm-generic/unistd.h lista as chamadas de sistema padrão, que são usadas em arquiteturas que não possuem uma tabela de chamada de sistema específica da arquitetura.

No kernel, as referências são ligeiramente diferentes e são específicas da arquitetura (novamente, para arquiteturas que não usam a tabela de chamadas genéricas do sistema). É aqui que entram os arquivos como arch/x86/entry/syscalls/syscall_64.tbl (e eles acabam produzindo os arquivos de cabeçalho que são usados no espaço do usuário, unistd_64.h etc.). Você encontrará muito mais detalhes sobre as chamadas do sistema no par de artigos do LWN sobre o tópico, Anatomia de uma parte da chamada do sistema 1 e Anatomia de uma parte da chamada do sistema 2 .

    
por 08.02.2018 / 19:37
2

Eu tenho uma página que lista todas as chamadas do sistema para cada arquitetura suportada pelo Linux:

link

    
por 05.11.2018 / 10:42
1

Esta resposta não vai tocar na asm-generic versão de unistd.h , porque nada a inclui. 1

Como observado em syscalls(2) :

Roughly speaking, the code belonging to the system call with number __NR_xxx defined in /usr/include/asm/unistd.h can be found in the Linux kernel source in the routine sys_xxx().

Ou seja, os números syscall corretos serão encontrados em /usr/include/asm/unistd.h . Agora, em um sistema x86 típico, isso simplesmente incluirá um dos arquivos asm/unistd_*.h dependendo do destino.

Os números syscall apropriados para um programa de 64 bits estão em asm/unistd_64.h e aqueles para um programa de 32 bits em asm/unistd_32.h (ou a quase equivalente% variante _x32.h ). Os dois são diferentes porque as arquiteturas de 32 e 64 bits são, efetivamente, sistemas operacionais completamente diferentes. Eles compartilham o mesmo conjunto de syscalls, mas não na mesma ordem, por várias razões.

A maioria deles também tem wrappers em linguagem C, então raramente você precisará usar syscall(2) diretamente.

1 E porque eu não sei para que serve.

    
por 05.02.2018 / 00:53
1

63 é read em arm64 , 0 é read em x86_64

Os números syscall são diferentes para cada arquitetura.

Os números arm64, por exemplo, são definidos em: include/uapi/asm-generic/unistd.h que mostra 63, consulte também: link

Como explicado nessa resposta, acho que incluir / uapi / asm-generic / unistd.h é uma tentativa mais recente de unificar os números de syscall em todos os arcos.

Mas como os números syscall não podem mudar para não quebrar a API syscall, os arcos mais antigos antes desse esforço de unificação mantiveram os números antigos.

Esta pergunta pede uma maneira automatizada de obter a lista completa de syscall, incluindo parâmetros:

strace código-fonte

Eu confio nessa ferramenta e eles mantêm seus dados em linux/ , por exemplo:

Observe que o arquivo aarch64 é um #include s agnóstico em arco 64/syscallent.h que me referi anteriormente.

Essas tabelas contêm o número de argumentos, mas não tipos de argumentos reais, pergunto-me onde strace os codifica.

    
por 06.02.2019 / 11:55

Tags