#!/usr/bin/env bash
#
# Copyright (C) 2012 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
SELF=${0##*/}
READELF="${READELF:-readelf}"
OBJCOPY="${OBJCOPY:-objcopy}"
TARGETS=$*
XARGS="${XARGS:-xargs -r}"
[ -z "$TARGETS" ] && {
echo "$SELF: no directories / files specified"
echo "usage: $SELF [PATH...]"
exit 1
}
find $TARGETS -type f -a -exec file {} \; | \
sed -n -e 's/^\(.*\):.*ELF.*\(executable\|shared object\).*,.*/\1/p' | \
$XARGS -n1 $READELF -d | \
awk '$2 ~ /NEEDED/ && $NF !~ /interpreter/ && $NF ~ /^\[?lib.*\.so/ { gsub(/[\[\]]/, "", $NF); print $NF }' | \
sort -u
tmp=`mktemp $TMP_DIR/dep.XXXXXXXX`
for kmod in `find $TARGETS -type f -name \*.ko`; do
$OBJCOPY -O binary -j .modinfo $kmod $tmp
sed -e 's,\x00,\n,g' $tmp | \
sed -ne '/^depends=.\+/ { s/^depends=//; s/,/.ko\n/g; s/$/.ko/p; q }'
done | sort -u
rm -f $tmp
用于查找给定目录或文件中的共享库(shared object)和内核模块(kernel module)的依赖关系。让我们一步一步来解释脚本:
-
#!/usr/bin/env bash
- 指定使用Bash作为解释器来执行脚本。
-
脚本版权信息和许可证说明:
- 脚本版权归OpenWrt.org所有。
- 脚本使用GNU General Public License v2进行许可,详情见
/LICENSE
文件。
-
定义变量和设置默认值:
SELF=${0##*/}
:获取脚本文件名。READELF="${READELF:-readelf}"
:定义READELF
变量,如果未设置,默认值为readelf
。OBJCOPY="${OBJCOPY:-objcopy}"
:定义OBJCOPY
变量,如果未设置,默认值为objcopy
。TARGETS=$*
:定义TARGETS
变量,用于存储要搜索的目录或文件路径。XARGS="${XARGS:-xargs -r}"
:定义XARGS
变量,如果未设置,默认值为xargs -r
,其中-r
选项表示当没有输入时不运行命令。
-
检查是否指定了搜索目标:
[ -z "$TARGETS" ]
:检查变量TARGETS
是否为空,即是否没有指定搜索目标。- 如果没有指定搜索目标,则输出用法说明并退出脚本。
-
查找 ELF 文件并提取 NEEDED 依赖:
find $TARGETS -type f -a -exec file {} \;
:使用find
命令找到指定目录或文件下的所有文件,并对每个文件执行file
命令来识别文件类型。sed -n -e 's/^\(.*\):.*ELF.*\(executable\|shared object\).*,.*/\1/p'
:使用sed
命令提取ELF格式的可执行文件和共享对象(shared object)的文件路径。$XARGS -n1 $READELF -d
:使用xargs
命令将上一步得到的文件路径传递给readelf
命令来提取依赖信息。awk '$2 ~ /NEEDED/ && $NF !~ /interpreter/ && $NF ~ /^\[?lib.*\.so/ { gsub(/[\[\]]/, "", $NF); print $NF }'
:使用awk
命令过滤输出,只保留包含NEEDED
的行,且文件名以"lib"开头且以".so"结尾(共享库文件)的行。它还去除了行中的方括号[]
,以及在共享库文件名前面的可能的问号。
-
查找内核模块文件并提取依赖:
tmp=
mktemp $TMP_DIR/dep.XXXXXXXX``:创建一个临时文件用于处理内核模块。for kmod in
find $TARGETS -type f -name *.ko; do ... done
:使用find
命令查找指定目录或文件中的内核模块(以".ko"结尾的文件)。$OBJCOPY -O binary -j .modinfo $kmod $tmp
:使用objcopy
命令提取内核模块的模块信息(.modinfo)并保存到临时文件。sed -e 's,\x00,\n,g' $tmp
:使用sed
命令将临时文件中的空字符(\x00)替换为换行符,以便处理依赖关系。sed -ne '/^depends=.\+/ { s/^depends=//; s/,/.ko\n/g; s/$/.ko/p; q }'
:使用sed
命令提取依赖信息。它在匹配行中找到以depends=
开头的依赖列表,并将逗号,
替换为换行符,最后输出.ko
结尾的依赖文件名。sort -u
:对输出进行排序并去重。
-
删除临时文件:
rm -f $tmp
综上所述,该脚本查找指定目录或文件中的 ELF 可执行文件和共享对象文件,并提取它们的依赖项。同时,它还查找指定目录或文件中的内核模块文件,并提取它们的依赖项。最后,将所有提取到的依赖项输出到标准输出,并去重排序。这个脚本可能用于在构建系统中解析软件包之间的依赖关系。