オンラインで参照している人がたくさんいる
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テーブルを見つけるための最良の方法は何ですか?
この種のことを調査しているときに、コンパイラに直接問い合わせるのが便利であることがわかります(詳細については、 標準の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.h
は x32 ABI に使用されます。
uapi/asm-generic/unistd.h
は、デフォルトのシステムコールを示しています。これは、アーキテクチャ固有のシステムコールテーブルがないアーキテクチャで使用されます。
カーネルでは、参照は若干異なり、アーキテクチャ固有です(これも、汎用のシステムコールテーブルを使用しないアーキテクチャの場合)。ここにArch/x86/entry/syscalls/syscall_64.tbl
などのファイルが入ります(最終的には、ユーザー空間で使用されるヘッダーファイル、unistd_64.h
などが生成されます)。システムコールの詳細については、トピックに関するLWN記事のペア、 システムコールパート1の分析 および システムコールパート2の分析 を参照してください。 。
63はarm64
のread
で、0はx86_64
のread
です
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は#include
s Arch agnostic 64/syscallent.h
であることに注意してください。
これらのテーブルには引数の数が含まれていますが、実際の引数の型は含まれていません。strace
がそれらをどこにエンコードするのでしょうか。
Linuxでサポートされている各アーキテクチャのすべてのシステムコールをリストするページがあります。
_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 それが何のためかわからないからです。
すべての優れた答えを追加するために、特定のアーキテクチャーのすべてのシステムコールとその整数マッピングをリストするために使用できるユーティリティ ausyscall
があります。
例えば:
$ ausyscall --dump
Using x86_64 syscall table:
0 read
1 write
2 open
3 close
4 stat
...