もがもがしいブログ

もがもがしく生きる

straceをStatic LinkでBuildする

Prerequisites

弊社が提供しているApplianceは基本的にBlack Boxで、開発/Sustaining/QA以外の人間がソースコードを読むことはできません。 自分のようなサポートエンジニアであれば、特殊なライセンスを用いてShell Mode (bash)に入り、一般的なLinuxのコマンドでトラブルシューティングを行うことができます。

今回は、いくつかあるAppliance製品の中で例外的に "ユーザが特殊ライセンス無しでShell Modeに入れるものの、トラブルシュートに有用なコマンドが用意されていない" 製品にstraceをStatic Buildで入れてみました。

Build Env

CentOS 8.1.1911
Linux kernel 4.18.0-147.5.1.el8_1.x86_64
gcc version 8.3.1 20190507 (Red Hat 8.3.1-4) (GCC)
GNU Make 4.2.1

Steps Performed

初めに失敗例から。以下GitHub Issueを参考に: github.com

$ git clone https://github.com/strace/strace.git
$ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking whether to enable maintainer-specific portions of Makefiles... no
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
checking for gcc... gcc
checking whether the C compiler works... no
configure: error: in `/usr/local/src/strace':
configure: error: C compiler cannot create executables
See `config.log' for more details

$ less config.log
...
/usr/bin/ld: cannot find -lpthread
/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
...

どうやら libc.a, libpthread.a がなくて怒られているようです。Yum/RPM packageを探してみても見つからないので、それらのBuildから始めました。 sourceware.org

$ mkdir $HOME/src
$ cd $HOME/src
$ git clone git://sourceware.org/git/glibc.git
$ mkdir -p $HOME/build/glibc
$ cd $HOME/build/glibc
$ $HOME/src/glibc/configure --prefix=/usr
$ make
$ mkdir -p $HOME/lib
$ cp $HOME/build/glibc/libc.a $HOME/lib
$ cp $HOME/build/glibc/rt/librt.a $HOME/lib
$ cp $HOME/build/glibc/nptl/libpthread.a $HOME/lib
$ export LDFLAGS="-L $HOME/lib -static -pthread"

librt.a も必要そうだったので入れました。続いてstraceのBuild。

$ mkdir $HOME/src
$ cd $HOME/src
$ git clone https://github.com/strace/strace.git
$ cd $HOME/src/strace
$ ./bootstrap
$ mkdir -p $HOME/build/strace/
$ cd $HOME/build/strace/
$ $HOME/src/strace/configure
$ make
$ file strace
strace: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=ec5651dd26507ec19b32d8793000d29191b70277, with debug_info, not stripped

無事にBuild完了。SFTPでコピーして動くことが確認できました。

# ./strace -fttTyyy -s1024 echo "Hello World"
09:32:56.028234 execve("/bin/echo", ["echo", "Hello World"], 0x7ffc789af918 /* 19 vars */) = 0 <0.000462>
09:32:56.029066 brk(NULL)               = 0x22ac000 <0.000022>
09:32:56.029273 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f40c01bf000 <0.000025>
09:32:56.029411 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) <0.000025>
09:32:56.029589 open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3</etc/ld.so.cache> <0.000023>
09:32:56.029748 fstat(3</etc/ld.so.cache>, {st_mode=S_IFREG|0644, st_size=36688, ...}) = 0 <0.000020>
09:32:56.029874 mmap(NULL, 36688, PROT_READ, MAP_PRIVATE, 3</etc/ld.so.cache>, 0) = 0x7f40c01b6000 <0.000021>
09:32:56.029974 close(3</etc/ld.so.cache>) = 0 <0.000015>
09:32:56.030076 open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3</usr/lib64/libc-2.17.so> <0.000024>
09:32:56.030229 read(3</usr/lib64/libc-2.17.so>, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\35\2\0\0\0\0\0@\0\0\0\0\0\0\0(c \0\0\0\0\0\0\0\0\0@\08\0\n\0@\0K\0J\0\6\0\0\0\5\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0000\2\0\0\0\0\0\0000\2\0\0\0\0\0\0\10\0\0\0\0\0\0\0\3\0\0\0\4\0\0\0\240I\30\0\0\0\0\0\240I\30\0\0\0\0\0\240I\30\0\0\0\0\0\34\0\0\0\0\0\0\0\34\0\0\0\0\0\0\0\20\0\0\0\0\0\0\0\1\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\224}\33\0\0\0\0\0\224}\33\0\0\0\0\0\0\0 \0\0\0\0\0\1\0\0\0\6\0\0\0000\207\33\0\0\0\0\0000\207;\0\0\0\0\0000\207;\0\0\0\0\0pQ\0\0\0\0\0\0\220\232\0\0\0\0\0\0\0\0 \0\0\0\0\0\2\0\0\0\6\0\0\0\200\273\33\0\0\0\0\0\200\273;\0\0\0\0\0\200\273;\0\0\0\0\0\360\1\0\0\0\0\0\0\360\1\0\0\0\0\0\0\10\0\0\0\0\0\0\0\4\0\0\0\4\0\0\0p\2\0\0\0\0\0\0p\2\0\0\0\0\0\0p\2\0\0\0\0\0\0D\0\0\0\0\0\0\0D\0\0\0\0\0\0\0\4\0\0\0\0\0\0\0\7\0\0\0\4\0\0\0000\207\33\0\0\0\0\0000\207;\0\0\0\0\0000\207;\0\0\0\0\0\20\0\0\0\0\0\0\0\220\0\0\0\0\0\0\0\20\0\0\0\0\0\0\0P\345td\4\0\0\0\274I\30\0\0\0\0\0\274I\30\0\0\0\0\0\274I\30\0\0\0\0\0004i\0\0\0\0\0\0004i\0\0\0\0\0\0\4\0\0\0\0\0\0\0Q\345td\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\20\0\0\0\0\0\0\0R\345td\4\0\0\0000\207\33\0\0\0\0\0000\207;\0\0\0\0\0000\207;\0\0\0\0\0\3208\0\0\0\0\0\0\3208\0\0\0\0\0\0\1\0\0\0\0\0\0\0\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\225\377\2\244\276\272\274W<x'\246mD\177{\253\335\252D\4\0\0\0\20\0\0\0\1\0\0\0GNU\0\0\0\0\0\2\0\0\0\6\0\0\0 \0\0\0\0\0\0\0\363\3\0\0\t\0\0\0\0\1\0\0\16\0\0\0\0000\20D\240 \2\1\210\3\346\220\305E\214\0\300\0\10\0\5\200\0`\300\200\0\r\212\f\0\4\20\0\210D2\10.@\210T<, \0162H&\204\300\214\4\10\0\2\2\16\241\254\32\4f\300\0\3002\0\300\0P\1 \201\10\204\v  ($\0\4 Z\0\20X\200\312DB(\0\6\200\20\30B\0 @\200\0\tP\0Q\212@\20\0\0\0\0\10\0\0\21\20", 832) = 832 <0.000020>
09:32:56.030404 fstat(3</usr/lib64/libc-2.17.so>, {st_mode=S_IFREG|0755, st_size=2127336, ...}) = 0 <0.000019>
09:32:56.030523 mmap(NULL, 3940800, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3</usr/lib64/libc-2.17.so>, 0) = 0x7f40bfbdc000 <0.000024>
09:32:56.030631 mprotect(0x7f40bfd94000, 2097152, PROT_NONE) = 0 <0.000033>
09:32:56.030729 mmap(0x7f40bff94000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib64/libc-2.17.so>, 0x1b8000) = 0x7f40bff94000 <0.000029>
09:32:56.030857 mmap(0x7f40bff9a000, 16832, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f40bff9a000 <0.000021>
09:32:56.030962 close(3</usr/lib64/libc-2.17.so>) = 0 <0.000016>
09:32:56.031075 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f40c01b5000 <0.000018>
09:32:56.031172 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f40c01b3000 <0.000036>
09:32:56.031285 arch_prctl(ARCH_SET_FS, 0x7f40c01b3740) = 0 <0.000016>
09:32:56.031479 mprotect(0x7f40bff94000, 16384, PROT_READ) = 0 <0.000023>
09:32:56.031579 mprotect(0x606000, 4096, PROT_READ) = 0 <0.000021>
09:32:56.031669 mprotect(0x7f40c01c0000, 4096, PROT_READ) = 0 <0.000024>
09:32:56.031756 munmap(0x7f40c01b6000, 36688) = 0 <0.000031>
09:32:56.031990 brk(NULL)               = 0x22ac000 <0.000016>
09:32:56.032059 brk(0x22cd000)          = 0x22cd000 <0.000019>
09:32:56.032135 brk(NULL)               = 0x22cd000 <0.000027>
09:32:56.032232 open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3</usr/lib/locale/locale-archive> <0.000028>
09:32:56.032362 fstat(3</usr/lib/locale/locale-archive>, {st_mode=S_IFREG|0644, st_size=106070960, ...}) = 0 <0.000018>
09:32:56.032471 mmap(NULL, 106070960, PROT_READ, MAP_PRIVATE, 3</usr/lib/locale/locale-archive>, 0) = 0x7f40b96b3000 <0.000024>
09:32:56.032588 close(3</usr/lib/locale/locale-archive>) = 0 <0.000017>
09:32:56.032763 fstat(1</dev/pts/0<char 136:0>>, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}) = 0 <0.000017>
09:32:56.032872 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f40c01be000 <0.000022>
09:32:56.032968 write(1</dev/pts/0<char 136:0>>, "Hello World\n", 12Hello World
) = 12 <0.000027>
09:32:56.033091 close(1</dev/pts/0<char 136:0>>) = 0 <0.000017>
09:32:56.033207 munmap(0x7f40c01be000, 4096) = 0 <0.000027>
09:32:56.033308 close(2</dev/pts/0<char 136:0>>) = 0 <0.000017>
09:32:56.033404 exit_group(0)           = ?
09:32:56.033586 +++ exited with 0 +++