Onde você encontra a tabela syscall para Linux?

13

Eu vejo muitas pessoas fazendo referência on-line

arch/x86/entry/syscalls/syscall_64.tbl

para a tabela syscall, isso funciona bem. Mas muitos outros fazem referência

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

que é comumente encontrado no pacote de cabeçalhos. Como é que os syscall_64.tblshows,

0 common  read      sys_read

A resposta certa e unistd.hmostra,

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

E então mostra __NR_readcomo

#define __NR_read 63
__SYSCALL(__NR_read, sys_read)

Por que isso é 63, e não 1? Como entendo isso /include/uapi/asm-generic/unistd.h? Ainda /usr/include/asm/está lá

/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 unistdarquivos. Explique como unistd.hfunciona? E qual o melhor método para encontrar a tabela syscall?

Evan Carroll
fonte

Respostas:

12

Ao investigar esse tipo de coisa, acho útil perguntar diretamente ao compilador (consulte Impressão de macros predefinidas C / GCC padrão no terminal para obter detalhes):

printf SYS_read | gcc -include sys/syscall.h -E -

Isto mostra que os cabeçalhos envolvidas (em 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 de chamada de 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, é bastante fácil:

printf SYS_read | gcc -include sys/syscall.h -m32 -E -

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

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

uapi/asm-generic/unistd.h lista as chamadas de sistema padrã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 um pouco diferentes e são específicas da arquitetura (novamente, para arquiteturas que não usam a tabela de chamada de sistema genérica). É aqui que arch/x86/entry/syscalls/syscall_64.tblentram os arquivos (e eles acabam produzindo os arquivos de cabeçalho que são usados ​​no espaço do usuário unistd_64.hetc.). Você encontrará muito mais detalhes sobre chamadas de sistema no par de artigos do LWN sobre o tópico Anatomia de uma chamada de sistema, parte 1 e Anatomia de uma chamada de sistema, parte 2 .

Stephen Kitt
fonte
A tabela syscall é estável entre a versão do kernel do Linux e as futuras?
Biswapriyo 3/09/19
@Biswapriyo, isso faz parte da estabilidade da ABI que os desenvolvedores do kernel sempre tentam preservar. Novos syscalls podem ser adicionados, mas os antigos não mudam, exceto em um número muito pequeno de casos extremos (como o tuxsyscall ).
Stephen Kitt
7

63 está readdentro arm64, 0 está readdentrox86_64

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

Os números arm64, por exemplo, são definidos em: o include/uapi/asm-generic/unistd.hque mostra que 63, consulte também: /reverseengineering/16917/arm64-syscalls-table/18834#18834

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

Mas como os números do syscall não podem ser alterados para não interromper a API do syscall, os arcos mais antigos antes desse esforço de unificação mantinham os números antigos.

Esta pergunta solicita uma maneira automatizada de obter a lista completa do syscall, incluindo os parâmetros: /programming/6604007/how-can-i-get-a-list-of-linux-system-calls-and- número-de-args-eles-tomam-automati

strace Código fonte

Confio nessa ferramenta e eles mantêm seus dados organizados linux/, por exemplo:

Note que o aarch64 #includeé o arco agnóstico ao 64/syscallent.hqual me referi anteriormente.

Essas tabelas contêm o número de argumentos, mas não os tipos de argumentos reais, gostaria de saber onde os stracecodifica.

Ciro Santilli adicionou uma nova foto
fonte
3

Esta resposta não tocará na asm-genericversão do unistd.h, porque nada inclui. 1

Conforme observado em syscalls(2):

Grosso modo, o código pertencente à chamada do sistema com o número __NR_xxx definido em /usr/include/asm/unistd.hpode ser encontrado na fonte do kernel Linux na rotina sys_xxx().

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

Os números syscall apropriados para um programa de 64 bits estão dentro asm/unistd_64.he os números para um programa de 32 bits asm/unistd_32.h(ou a _x32.hvariante quase equivalente ). 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ários motivos.

A maioria deles também possui invólucros no idioma C; portanto, raramente você precisará usá-lo syscall(2)diretamente.


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

Raposa
fonte
0

Para adicionar todas as ótimas respostas, existe um utilitário ausyscallque pode ser usado para listar todos os syscalls e seus mapeamentos inteiros para a arquitetura específica.

por exemplo:

$ ausyscall --dump
Using x86_64 syscall table:
0   read
1   write
2   open
3   close
4   stat
...
pikaynu
fonte