Last active
November 6, 2021 02:55
-
-
Save stdrc/0ef27ce80337a797dcfe245944dd6f95 to your computer and use it in GitHub Desktop.
从 wllvm 编出的 binary 获得(重新编译)未优化的 LLVM bitcode
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# 声明 | |
# | |
# 本脚本主要来自 https://blog.xiexun.tech/linux-bc-custom-opt.html, | |
# 这里只是收藏一下(并做了一点点小修改)。 | |
# | |
# 用法 | |
# | |
# 有些代码使用 LLVM 编译的时候不允许修改优化级别(比如 Linux kernel), | |
# 但我们往往需要在未优化的 bitcode 上进行静态分析,下面的脚本可以自动提取 | |
# wllvm 编译出的 binary 中包含的 bitcode,然后重新不带优化地编译所有文件, | |
# 再链接成一个 bitcode 文件: | |
# | |
# make CC=wllvm # 比如产生 abc.ko | |
# ./build_unopt_bc.sh abc.ko # 会重新编译得到 abc.unopt.bc | |
# | |
llvm_linker=llvm-link | |
function get_cmd | |
{ | |
path="$2" | |
# change output file name | |
awk_cmd='{ | |
s = ""; | |
ofile = 0; | |
for (i = 3; i <= NF; i++) | |
{ | |
if (ofile == 1) | |
{ | |
s = s "'"$path"'" " "; | |
ofile = 0; | |
} | |
else | |
{ | |
if ($i == "-o") | |
ofile = 1; | |
s = s $i " "; | |
} | |
} | |
print s }' | |
cmd_line=`head -n 1 $1 | awk "$awk_cmd"` | |
# output LLVM IR | |
cmd_line="${cmd_line} -emit-llvm" | |
# disable opt | |
cmd_line="${cmd_line} -mllvm -disable-llvm-optzns" | |
echo $cmd_line | |
return | |
} | |
function compile_opt | |
{ | |
cmd_path="$1" | |
basepath="$2" | |
tmp_path="${basepath}.tmp.bc" | |
output_path="${basepath}.unopt.bc" | |
cmd=`get_cmd "$cmd_path" "$tmp_path"` | |
cd /lib/modules/`uname -r`/build # change dir to kernel source | |
eval "$cmd" #2> /dev/null | |
cd - | |
cmd_result=$? | |
if [ ! -e "$tmp_path" ] || [ $cmd_result -ne 0 ] | |
then | |
exit 1 | |
fi | |
# opt -always-inline -inline -mem2reg -simplifycfg -instcombine "$tmp_path" -o "$output_path" | |
opt -mem2reg -simplifycfg "$tmp_path" -o "$output_path" | |
cmd_result=$? | |
if [ ! -e "$output_path" ] || [ $cmd_result -ne 0 ] | |
then | |
exit 1 | |
fi | |
} | |
while getopts ":l:" opt; do | |
case $opt in | |
l) llvm_linker=$OPTARG | |
;; | |
\?) echo "Usage: -l <llvm-link>" 1>&2 | |
exit 1 | |
;; | |
esac | |
done | |
shift $((OPTIND-1)) | |
from_file=$1 | |
if [ -z "$from_file" ] | |
then | |
echo "no input file" 1>&2 | |
exit 1 | |
fi | |
extract-bc -l false -m $from_file | |
manifest="${from_file}.llvm.manifest" | |
if [ ! -r "$manifest" ] | |
then | |
echo "no manifest file" 1>&2 | |
exit 1 | |
fi | |
tmpmanifest="${from_file}.tmp.manifest" | |
echo -n "" > "$tmpmanifest" | |
cat "$manifest" | | |
while read o_bc_name; | |
do | |
basename=`basename "${o_bc_name%.o.bc}"` | |
# basename="${basename#.}" | |
dir="${o_bc_name%/*}" | |
basepath="${dir}/${basename}" | |
if [ -z "$dir" ] && [ -z "$basename" ] | |
then | |
continue | |
fi | |
cmd_path="${basepath}.o.cmd" | |
if [ ! -r "${cmd_path}" ] | |
then | |
echo "${cmd_path} not found" | |
continue | |
fi | |
while [ `jobs | wc -l` -ge 8 ] | |
do | |
sleep 0.1 | |
done | |
output_path="${basepath}.unopt.bc" | |
compile_opt "$cmd_path" "$basepath" | |
echo "$output_path" | |
echo "$output_path" >> "${tmpmanifest}" | |
done | |
while [ `jobs | wc -l` -ne 0 ] | |
do | |
sleep 1 | |
done | |
outputfile="${from_file}.unopt.bc" | |
$llvm_linker -o "$outputfile" `cat "${tmpmanifest}"` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment