我试图从gdb
反汇编输出中仅获取原始二进制数据。我当前的输出如下:
$ gdb -batch -ex "disassemble/r btif_set_adapter_property" libbluetooth_qti.so | column -ts $'\t'
Dump of assembler code for function _Z25btif_set_adapter_propertyPK13bt_property_t:
0x0011e8c1 <+0>: e9 f0 41 c8 b0 jmp 0xb0da2ab6
0x0011e8c6 <+5>: 04 46 add $0x46,%al
0x0011e8c8 <+7>: 67 48 addr16 dec %eax
0x0011e8ca <+9>: c0 ef 50 shr $0x50,%bh
0x0011e8cd <+12>: 00 00 add %al,(%eax)
0x0011e8cf <+14>: 21 78 44 and %edi,0x44(%eax)
0x0011e8d2 <+17>: 07 pop %es
0x0011e8d3 <+18>: 68 38 68 47 90 push $0x90476838
0x0011e8d8 <+23>: 02 a8 40 f9 cd 0a add 0xacdf940(%eax),%ch
0x0011e8de <+29>: 01 60 08 add %esp,0x8(%eax)
0x0011e8e1 <+32>: a8 f9 test $0xf9,%al
0x0011e8e3 <+34>: 21 51 f1 and %edx,-0xf(%ecx)
0x0011e8e6 <+37>: 62 (bad)
0x0011e8e7 <+38>: ea 60 48 d4 e9 00 23 ljmp $0x2300,$0xe9d44860
奇怪的是,它仍然不是通过制表符来分隔列,而是通过看起来像制表符的空格来分隔列。所以我这里无法使用| awk '{print $2}'
。
下一个问题是原始二进制数据具有不同的长度,并且列 2..8 可能包含我需要的原始二进制数据。
也许我想得太复杂了,有一个内置的方法,gdb
但找不到任何方法。
所以我想要的输出是这样的(所有内容都在一行中):
e9 f0 41 c8 b0 04 46 67 48 c0 ef 50 00 00 21 78 44 07 68 38 68 47 90 02 a8 40 f9 cd 0a 01 60 08 a8 f9 21 51 f1 62 ea 60 48 d4 e9 00 23
编辑:gdb
自身的输出:
$ gdb -batch -ex "disassemble/r btif_set_adapter_property" libbluetooth_qti.so
Dump of assembler code for function _Z25btif_set_adapter_propertyPK13bt_property_t:
0x0011e8c1 <+0>: e9 f0 41 c8 b0 jmp 0xb0da2ab6
0x0011e8c6 <+5>: 04 46 add $0x46,%al
0x0011e8c8 <+7>: 67 48 addr16 dec %eax
0x0011e8ca <+9>: c0 ef 50 shr $0x50,%bh
0x0011e8cd <+12>: 00 00 add %al,(%eax)
0x0011e8cf <+14>: 21 78 44 and %edi,0x44(%eax)
0x0011e8d2 <+17>: 07 pop %es
0x0011e8d3 <+18>: 68 38 68 47 90 push $0x90476838
0x0011e8d8 <+23>: 02 a8 40 f9 cd 0a add 0xacdf940(%eax),%ch
0x0011e8de <+29>: 01 60 08 add %esp,0x8(%eax)
0x0011e8e1 <+32>: a8 f9 test $0xf9,%al
0x0011e8e3 <+34>: 21 51 f1 and %edx,-0xf(%ecx)
0x0011e8e6 <+37>: 62 (bad)
0x0011e8e7 <+38>: ea 60 48 d4 e9 00 23 ljmp $0x2300,$0xe9d44860
答案1
看起来您的字段由冒号或空格分隔,后跟附加空格,因此只需相应地设置 FS 即可:
$ awk -F'[: ] +' 'NR>1{o=(o=="" ? "" : o OFS) $3} END{print o}' file
e9 f0 41 c8 b0 04 46 67 48 c0 ef 50 00 00 21 78 44 07 68 38 68 47 90 02 a8 40 f9 cd 0a 01 60 08 a8 f9 21 51 f1 62 ea 60 48 d4 e9 00 23
答案2
您可能会幸运地通过以下程序传输 GDB 输出awk
:
awk '{for (i=1;i<=NF;i++) if ($i~/^[a-f0-9]{2}$/) printf("%s%s",$i,OFS)} END{print ""}'
这将检查 GDB 输出传入行的所有“单词”(以空格分隔的文本块),并检查它们是否是两位数的十六进制数字。如果是这样,它将打印它们。如果没有,它将什么也不做。由此找到的打印的十六进制数字将由输出字段分隔符OFS
(默认为空格)分隔。仅在输入结束时打印换行符(该print
语句自动附加“输出记录分隔符”,默认为换行符,因此打印“无”相当于输出换行符),因此所有这些十六进制数字将出现在一个空间分隔的大流。
它适用于您提供的示例 GDB 输出,但请注意,如果其他地方有“杂散”两位十六进制数字,它们也会最终出现在输出中。
答案3
我们可以使用支持 PCRE 正则表达式的 GNU grep 提取信息,然后使用其他 Linux 实用程序对它们进行后处理。 file 是保存到文件的 gdb 命令的输出。
< file \
grep -Po ':\s*((\s\S+)+)\s{2}' |
paste -s - | tr -s '\t :' ' ' |
sed -E 's/^ | $//g'
Perl 可以为您提取它们:
perl -ne '
print(($"x!!$a++),$1) if /:\s+(\S.*?\S)\s{2}/;
}{printf $/;
' file
输出:
e9 f0 41 c8 b0 04 46 67 48 c0 ef 50 00 00 21 78 44 07 68 38 68 47 90 02 a8 40 f9 cd 0a 01 60 08 a8 f9 21 51 f1 62 ea 60 48 d4 e9 00 23
python3 -c 'import sys
ifile = sys.argv[1]
L = []
with open(ifile) as fh:
for l in fh:
ln = l.rstrip()
if ln.find(":") < 0: continue
f1 = ln.split(":",1)[1].lstrip()
L += f1[0:f1.find(" ")].split()
print(*L)
' file
扩展正则表达式模式下的 GNU sed 流编辑器打开:
sed -En '
s/:\s*((\s[[:xdigit:]]{2})+)\s{2}/\n\1\n/;T
s/.*\n\s(.*)\n.*/\1/;H
$!d;g;s/.//;s/\s+/ /gp
' file