web-dev-qa-db-ja.com

Linuxのsyscallテーブルはどこにありますか?

オンラインで参照している人がたくさんいる

Arch/x86/entry/syscalls/syscall_64.tbl

syscallテーブルの場合、これは正常に機能します。しかし、他の多くの参照

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

これは一般的にheadersパッケージにあります。どうしてsyscall_64.tblは、

0 common  read      sys_read

正しい答えとunistd.hが示しています、

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

そして、それは__NR_read

#define __NR_read 63
__SYSCALL(__NR_read, sys_read)

なぜ63ではなく1なのですか? /include/uapi/asm-generic/unistd.hを理解するにはどうすればよいですか?まだ/usr/include/asm/にあります

/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          

これらのunistdファイルの違いを誰かに教えてもらえますか? unistd.hの仕組みを説明してください。そして、syscallテーブルを見つけるための最良の方法は何ですか?

12
Evan Carroll

この種のことを調査しているときに、コンパイラに直接問い合わせるのが便利であることがわかります(詳細については、 標準のC/GCC定義済みマクロをターミナルに出力する を参照してください)。

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

これは、(Debianで)関係するヘッダーが/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、および/usr/include/x86_64-linux-gnu/bits/syscall.hであることを示し、readのシステムコール番号を出力します。 x86-64では0です。

(クロスコンパイラ環境で)適切なシステムヘッダーがインストールされている場合は、他のアーキテクチャのシステムコール番号を見つけることができます。 32ビットx86の場合は非常に簡単です。

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

これには、他のヘッダーファイルの中で/usr/include/asm/unistd_32.hが含まれ、数値3が出力されます。

したがって、ユーザー空間の観点からは、32ビットx86システムコールはasm/unistd_32.hで定義され、64ビットx86システムコールはasm/unistd_64.hで定義されます。 asm/unistd_x32.hx32 ABI に使用されます。

uapi/asm-generic/unistd.hは、デフォルトのシステムコールを示しています。これは、アーキテクチャ固有のシステムコールテーブルがないアーキテクチャで使用されます。

カーネルでは、参照は若干異なり、アーキテクチャ固有です(これも、汎用のシステムコールテーブルを使用しないアーキテクチャの場合)。ここにArch/x86/entry/syscalls/syscall_64.tblなどのファイルが入ります(最終的には、ユーザー空間で使用されるヘッダーファイル、unistd_64.hなどが生成されます)。システムコールの詳細については、トピックに関するLWN記事のペア、 システムコールパート1の分析 および システムコールパート2の分析 を参照してください。 。

12
Stephen Kitt

63はarm64readで、0はx86_64readです

Syscall番号は、アーキテクチャごとに異なります。

たとえば、arm64の数値は include/uapi/asm-generic/unistd.h で定義されており、63であることを示しています。以下も参照してください: https://reverseengineering.stackexchange.com/questions/16917/arm64-syscalls-table/18834#18834

その回答で説明されているように、include/uapi/asm-generic/unistd.hは、すべてのアーキテクチャでシステムコール番号を統一するための新しい試みだと思います。

しかし、syscall番号はsyscall APIを壊さないように変更できないため、統合前の古いアーチは古い番号を保持しています。

この質問は、パラメーターを含む完全なsyscallリストを取得する自動化された方法を要求します: -system-calls-and-number-of-args-they-take-automati

straceソースコード

私はそのツールを信頼しており、データはlinux/に整理されています。例:

以前に言及したaarch64 oneは#includes Arch agnostic 64/syscallent.h であることに注意してください。

これらのテーブルには引数の数が含まれていますが、実際の引数の型は含まれていません。straceがそれらをどこにエンコードするのでしょうか。

Linuxでサポートされている各アーキテクチャのすべてのシステムコールをリストするページがあります。

https://Fedora.juszkiewicz.com.pl/syscalls.html

5

_asm-generic_の_unistd.h_バージョンについては、何も含まれていないため、この回答では触れません。1

syscalls(2)で述べたように:

おおまかに言って、_/usr/include/asm/unistd.h_で定義された__NR_xxxのシステムコールに属するコードは、Linuxカーネルソースの_sys_xxx_()ルーチンにあります。

つまり、正しいsyscall番号は_/usr/include/asm/unistd.h_にあります。これで、典型的なx86システムでは、ターゲットに応じて_asm/unistd_*.h_ファイルの1つが含まれます。

64ビットプログラムに適切なsyscall番号は_asm/unistd_64.h_にあり、32ビットプログラムに適切なsyscall番号は_asm/unistd_32.h_(またはほぼ同等の__x32.h_バリアント)にあります。 32ビットと64ビットのアーキテクチャーは、事実上、完全に異なるオペレーティングシステムであるため、2つは異なります。さまざまな理由により、同じシステムコールセットを共有しますが、同じ順序ではありません。

これらのほとんどはC言語のラッパーも備えているため、syscall(2)を直接使用する必要はほとんどありません。


1 それが何のためかわからないからです。

3
Fox

すべての優れた答えを追加するために、特定のアーキテクチャーのすべてのシステムコールとその整数マッピングをリストするために使用できるユーティリティ ausyscall があります。

例えば:

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