簡體   English   中英

如何僅在目標文件中打印函數的二進制代碼?

[英]How to just print the binary code of a function in an object file?

我能夠反匯編如下的目標文件。 但是我只想將二進制格式的指令的原始數字(如55、48等)以二進制格式轉儲到文件中,用於特定功能,例如add4。

我可以編寫一個程序來解析otool的輸出。 但是,有沒有更簡單的方法呢?

我的操作系統是Mac OSX。

$ cat add.c
long x;
long add2(long num) {
  return num + 2;
}
long add4(long num) {
  return num + 4;
}
$ clang -c -o add.o add.c
$ otool -tvjV add.o 
add.o:
(__TEXT,__text) section
_add4:
0000000000000000    55  pushq   %rbp
0000000000000001    48 89 e5    movq    %rsp, %rbp
0000000000000004    48 89 7d f8     movq    %rdi, -0x8(%rbp)
0000000000000008    48 8b 7d f8     movq    -0x8(%rbp), %rdi
000000000000000c    48 83 c7 04     addq    $0x4, %rdi
0000000000000010    48 89 f8    movq    %rdi, %rax
0000000000000013    5d  popq    %rbp
0000000000000014    c3  retq
0000000000000015    66 2e 0f 1f 84 00 00 00 00 00   nopw    %cs:_add4(%rax,%rax)
000000000000001f    90  nop
_add2:
0000000000000020    55  pushq   %rbp
0000000000000021    48 89 e5    movq    %rsp, %rbp
0000000000000024    48 89 7d f8     movq    %rdi, -0x8(%rbp)
0000000000000028    48 8b 7d f8     movq    -0x8(%rbp), %rdi
000000000000002c    48 83 c7 02     addq    $0x2, %rdi
0000000000000030    48 89 f8    movq    %rdi, %rax
0000000000000033    5d  popq    %rbp
0000000000000034    c3  retq

您可以使用nm -nU add.o獲取符號地址。 您可以搜索感興趣的符號並獲取其地址和后續地址。 這給了您符號的開始和(大約)長度。 然后,您可以使用任何工具從文件進行十六進制轉儲,以僅讀取該部分。

例如:

exec 3< <(nm -nU add.o | grep -A1 -w _add4 | cut -d ' ' -f 1)
read start <&3
read end <&3
3<&-
offset=$(otool -lV add.o | grep -A3 -w "segname __TEXT" | grep -m1 offset | cut -c 12-)
if [ -n "$end" ] ; then length_arg="-n $(( "0x$end" - "0x$start" ))" ; fi
hexdump -C -s $((0x$start + $offset)) $length_arg add.o

您可以使用objdump,然后提取操作碼部分。 可以如下進行。

$ objdump -d add.o | grep add4 -A10 | cut -f 2 | grep -v ':'

grep的-v標志告訴它打印不包含冒號的所有行。

輸出:

    55                   
    48 89 e5             
    48 89 7d f8          
    48 8b 45 f8          
    48 83 c0 04          
    5d                
    c3

-A10告訴grep在比賽后打印10行。

現在要將其輸出到文件中,我們首先將操作碼格式化為十六進制格式,例如“ \\ x45”。 上面的輸出可以有多個空格,並且每行的末尾都有一個空格,因此我們首先將其刪除,因為它可能會干擾我們的sed。

$ objdump -d add.o | grep add4 -A10 | cut -f 2 | grep -v ':' | sed 's/ */ /g' | sed 's/ $//g'

添加“ \\ x”部分,首先添加中間的空格,然后添加每行的第一個十六進制。

$ objdump -d add.o | grep add4 -A10 | cut -f 2 | grep -v ':' | sed 's/ */ /g' | sed 's/ $//g' | sed 's/ /\\\\x/g' | sed 's/^/\\\\x/g'

\x55
\x48\x89\xe5
\x48\x89\x7d\xf8
\x48\x8b\x45\xf8
\x48\x83\xc0\x04
\x5d
\xc3

將其全部折疊成一行並添加引號。

$ objdump -d add.o | grep add4 -A10 | cut -f 2 | grep -v ':' | sed 's/ */ /g' | sed 's/ $//g' | sed 's/ /\\\\x/g' | sed 's/^/\\\\x/g' | tr -d '\\n' | sed 's/^/\\"/g' | sed 's/$/\\"/g'

"\x55\x48\x89\xe5\x48\x89\x7d\xf8\x48\x8b\x45\xf8\x48\x83\xc0\x04\x5d\xc3"

現在我們得到了一個C風格的字符串,我們將其傳遞給printf,然后將輸出重定向到文件。

$ printf $(objdump -d add.o | grep add4 -A10 | cut -f 2 | grep -v ':' | sed 's/ */ /g' | sed 's/ $//g' | sed 's/ /\\\\x/g' | sed 's/^/\\\\x/g' | tr -d '\\n' | sed 's/^/\\"/g' | sed 's/$/\\"/g') | sed 's/^\\"//g' | sed 's/\\"$//g' > add4.bin

printf之后的最后兩個sed將刪除由於某些原因保留在printf輸出中的引號。

十六進制轉儲文件:

$ hexdump -C add4.bin

00000000  55 48 89 e5 48 89 7d f8  48 8b 45 f8 48 83 c0 04  |UH..H.}.H.E.H...|
00000010  5d c3                                             |].|
00000012

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM