find-extlib - 外部関数の呼び出しをリストアップする

目的

あるプログラムからの、外部ライブラリの関数呼び出しをチェックしたい。

たとえば、自作プログラムが多数のオブジェクトから出来ているとして、その中で libc なり libm なりを参照している。
これらをリストアップして、依存を減らしたり、省サイズ化のために置き換えできないかを検討する材料にしたい。

結果

nmを呼び出すスクリプトを作成した。

例)

% find . -name '*.[oa]' | NM=nm xargs find-extlib
./dln.o: __xstat64 dlclose dlerror dlopen dlsym fprintf free fwrite getenv memcpy snprintf stderr strchr strcpy
./version.o: exit fflush puts snprintf stdout
...


以下、詳細。

動機

元々は、glibc への依存を無くすために、glibc 内の関数の呼び出しをリストアップしたかった。
ただ glibc の関数一覧を定義するのが面倒に思えたので、代わりに外部ライブラリ参照をリストアップすることにした。

処理スクリプト

方針に沿って、

  1. 全オブジェクトファイルのグローバルシンボルを抽出
  2. 各オブジェクトファイルで、「収集したシンボル以外への参照」を調べる

の2段階処理で実装。
この方法だと、外部変数の参照などもリストアップされてしまうが、害は無いしこのままで。

find-extlib
https://sssvn.jp/svn/spikelet/utils/find-extlib
#!/bin/sh
# find use of external functions and variables among objs and libs.
# usage: cd somewhere/obj ; ./find-extlib.sh *.o ../release/pap_Er.a
NM=${NM-am33_2.0-linux-gnu-nm}

if [ $# = 0 ]
then
  echo >&2 "usage: $0 <obj-files...>"
  exit 1
fi

TMPFILE1=nm.result1.$$
TMPFILE2=nm.result2.$$
trap 'rm -f $TMPFILE1 $TMPFILE2' 0

## create defined function list
$NM "$@" | awk '/ [A-TV-Z] [^.]/{print $NF}' | sort -u > $TMPFILE1

## check if external function or variable is used in each *.o file
for objfile
do
  case $objfile in
      *.o)
          $NM -u $objfile | awk '{print $NF}' > $TMPFILE2
          result=`fgrep -v -x -f $TMPFILE1 $TMPFILE2`
          [ $? = 0 ] && echo "$objfile": $result
          ;;
  esac
done

実際はクロス環境で実行したいので、使用するnmコマンドをそれ用にしている。
普通の(ストレートビルド)環境で実行したい場合は、4行目を "NM=nm" と変更するか、環境変数 NM を適切に設定しておく。

実行例

ruby-1.8.7-p72 のソースを手元マシンでコンパイルしたものに実行してみる。

% find . -name '*.o' | NM=nm xargs find-extlib | head -10
./dln.o: __xstat64 dlclose dlerror dlopen dlsym fprintf free fwrite getenv memcpy snprintf stderr strchr strcpy
./version.o: exit fflush puts snprintf stdout
./ruby.o: __ctype_b_loc chdir execv exit fclose fopen64 fprintf free getegid getenv geteuid getgid getuid mblen memcpy memset printf puts stderr strchr strcpy strncpy strstr
./dir.o: __ctype_b_loc __ctype_tolower_loc __errno_location __lxstat64 __xstat64 chdir chroot closedir free getenv malloc memcpy memmove mkdir opendir readdir64 rewinddir rmdir seekdir snprintf strcpy telldir
./io.o: _IO_getc __errno_location __fxstat64 _exit clearerr close dup dup2 fchmod fchown fclose fcntl fdopen feof ferror fflush fileno fopen64 fork fprintf fread free freopen64 fseeko64 fsync ftello64 fwrite ioctl isatty lseek64 memchr open64 pipe read rename snprintf stderr stdin stdout strcpy strerror syscall ungetc unlink write
./random.o: __fxstat64 close free getpid gettimeofday open64 read
./gc.o: __udivdi3 _setjmp exit free fwrite getrlimit64 malloc memcpy memset realloc stderr
./bignum.o: __ctype_b_loc __errno_location __isinf __isnan __strtoul_internal __udivdi3 __umoddi3 frexp ldexp memcpy memmove pow
./file.o: __errno_location __fxstat64 __lxstat64 __xstat64 access chmod chown endpwent fchmod fchown fclose fflush fileno flock fopen64 free fseeko64 ftruncate64 getenv geteuid getpwnam getuid group_member lchown link memcpy memset readlink rename snprintf sprintf strchr strcpy strncmp symlink truncate64 umask unlink utimes
./struct.o: snprintf

glibc などの関数呼び出しがリストアップされた。