我需要检查执行给定二进制对象(不是常规二进制,而是gcc -c somefile.s
的输出)所需的x86指令扩展的最小集合。手工操作非常耗时且容易出错。我正在寻找一个自动化的过程。
我需要的是一些二进制文件,给定一个二进制对象作为输入,将返回一个类似于x86指令扩展的objdump
类输出。类似于以下示例:
$ objdump-extended -d someobject.o
...
66 41 0f 38 00 c0 SSSE3 pshufb %xmm8,%xmm0
66 0f 6f d8 SSE2 movdqa %xmm0,%xmm3
66 0f fe 00 SSE2 paddd (%rax),%xmm0
0f 38 cb d1 SHANI sha256rnds2 %xmm0,%xmm1,%xmm2
...
Extensions used: SSE2, SSSE3, SHANI, ...
是否有类似的工具可用?
最简单,最可靠的选项是@PeterCordes提到的一个:使用汇编程序命令行选项来限制可用指令集。
如果在gas
至gcc
中使用不允许的指令扩展名时,如果需要编译时警告/错误,则以下代码片段说明了一个示例,该示例仅允许使用通用x86_64指令以及SSSE3和SHANI扩展名;其他任何东西都会报告错误:
$ gcc -c -Wa,-march=generic64+ssse3+sha somefile.s
对于出色的工具objdump
,我破解了一个简单的脚本,通过每个指令扩展来扩展Zydis输出,这是一个简单的脚本:
#!/bin/bash
REGEX='^([0-9a-f]+)\s+<(.*)>\s+([0-9a-f][0-9a-f]( [0-9a-f][0-9a-f])*)\s+(.*?)$'
EXTS=
while read -r LINE ; do
if [[ $LINE =~ $REGEX ]] ; then
ADDR=${BASH_REMATCH[1]}
LABEL=${BASH_REMATCH[2]}
HEX=${BASH_REMATCH[3]}
INSTR=${BASH_REMATCH[5]}
EXT=$(ZydisInfo -64 $HEX | grep ' ISA-EXT:' | cut -d ' ' -f 6)
[[ " $EXTS " != *" $EXT "* ]] && EXTS="$EXTS $EXT"
echo -e "$LABEL\t$EXT\t$INSTR"
fi
done < <(objdump --disassemble --wide --prefix-addresses --show-raw-insn "$1")
echo "Extensions:$EXTS"
NOTE:先前的代码未尝试检查错误或意外状态。使用风险自负。
您可以使用英特尔的X86 Encoder Decoder (XED)获得类似的输出。
说明:
git clone https://github.com/intelxed/xed.git xed
git clone https://github.com/intelxed/mbuild.git mbuild
cd xed
./mfile.py examples
obj/wkit/examples/obj/xed -A -i someobject.o
这将产生以下输出:
...
XDIS 0: SSE SSSE3 66410F3800C0 pshufb %xmm8, %xmm0
XDIS 6: DATAXFER SSE2 660F6FD8 movdqa %xmm0, %xmm3
XDIS a: SSE SSE2 660FFE00 padddx (%rax), %xmm0
XDIS e: SHA SHA 0F38CBD1 sha256rnds2 %xmm1, %xmm2
...
如果您喜欢Intel语法,则可以省略-A
参数。