memo.log

技術情報の雑なメモ

setsocopt探訪のメモ(4)

さて、前回までで、文字列データでオプションを指定しても、mreq 構造体で指定してもシステムコールとしては同じものが実行されるところまでを確認した。 今回は、Cのコードからシステムコールが実行されるまでの流れを追ってみようと思う。

setsockopt は定義としては glibc にあるようなので、glibcの動きをgdb で追ってみる。

glibcをgdbで追う. 不具合調査等で、Linuxのシステムのライブラリをgdbで追いたいことがある。例… | by Kazuhiro Masuda | Medium

の記事を参考に、まずは、GDBの準備とsetsockopt を用いるソースコードコンパイルを行っておく。

gdbを実行し、 setsockoptブレークポイントを設定し、プログラムを実行する。

% sudo gdb ./soc_test 
(gdb) b setsockopt
(gdb) r
(gdb) n
39        setsockopt(sock, 263, 1, mreq2, sizeof(mreq2));
(gdb) n
Breakpoint 2, setsockopt () at ../sysdeps/unix/syscall-template.S:84
84      T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
(gdb) n
85              ret

すると、上記のように syscall-template.S ファイルが実行されていることが分かった。 このファイルはなんだろうと調べてみると、

SyscallWrappers - glibc wiki

によると、システムコールをラップするときに用いられるファイルらしい。

ラッパーを使用するシステムコールのリストは、syscalls.listファイルに保持されます。(日本語訳)

とのことで、手元のファイルを確認してみると、以下にそれっぽいファイルがあり、 setsocopt 関数が見える。

sysdeps/unix/sysv/linux/x86_64/syscalls.list

# File name  Caller  Syscall name    # args  Strong name Weak names

arch_prctl  EXTRA   arch_prctl  i:ii    __arch_prctl    arch_prctl
modify_ldt  EXTRA   modify_ldt  i:ipi   __modify_ldt    modify_ldt
syscall_clock_gettime   EXTRA   clock_gettime   Ei:ip       __syscall_clock_gettime


# proper socket implementations:
bind        -   bind        i:ipi   __bind      bind
getpeername -   getpeername i:ipp   __getpeername   getpeername
getsockname -   getsockname i:ipp   __getsockname   getsockname
getsockopt  -   getsockopt  i:iiiBN __getsockopt    getsockopt
listen      -   listen      i:ii    __listen    listen
setsockopt  -   setsockopt  i:iiibn __setsockopt    setsockopt
shutdown    -   shutdown    i:ii    __shutdown  shutdown
socket      -   socket      i:iii   __socket    socket
socketpair  -   socketpair  i:iiif  __socketpair    socketpair

つまり、glibc的には setsocoptシステムコールをラップしていて、右から左に流しているように見える。 ということで、次はカーネルの中に入って setsocopt を覗いてみることで、 optval 引数をどのように扱っているかを確認していく。

疑問メモ

sysdeps/unix/sysv/linux/setsockopt.c ここにそれっぽいのがあるけど、この辺のコードは経由しないのか?