objdump
如何设法从拇指模式指令(16位指令宽)中整理出普通模式指令(32位指令宽)。在CPSR的t
标志处。但是首先,让我们构建一个小示例并对其进行一些实验。
我写了这小块ARM程序集(
gas
语法)作为基础示例:.arm
mov fp, #0
moveq r1, r0
.thumb
mov r0, #0
mov fp, r0
然后,我像这样交叉编译了它:
$> arm-none-eabi-gcc -Wall -Wextra -mlittle-endian -c -o arm_sample arm_sample.s
这是ARM对象文件上
objdump
的输出:$> objdump -d ./arm32_mov
./arm32_mov: file format elf32-littlearm
Disassembly of section .text:
00000000 <.text>:
0: e3a0b000 mov fp, #0
4: 01a01000 moveq r1, r0
8: 2000 movs r0, #0
a: 4683 mov fp, r0
但是,当我运行我的工具时,我得到:
warning: decoder says at (0x8,0):'strmi r2, [r3], r0' : Unknown mnemonic
0: 00 b0 a0 e3 mov fp, #0
4: 00 10 a0 01 moveq r1, r0
8: ...
我的工具基于
libopcodes
(与objdump
一样),因此第三条指令仍被解释为仍在32位模式和两条拇指模式指令仅被解释为一个给出strmi r2, [r3], r0
的32位指令。到拇指模式。在发现这一点之前,我认为尽管CPSR状态寄存器中的objdump
标志的值,该信息仅在执行时可用。看不到任何依赖于体系结构的情况来对待ARM拇指模式的情况。所以,这对我来说仍然是个谜... 任何建议都值得欢迎!
编辑
事实上,我在研究一个物体文件(与
t
选项一起编译),因此没有太多符号。但是,这是通过objdump
获得的更详细的输出:$> objdump -x ./arm32_mov
./arm32_mov: file format elf32-littlearm
./arm32_mov
architecture: armv4t, flags 0x00000010:
HAS_SYMS
start address 0x00000000
private flags = 5000000: [Version5 EABI]
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 0000000c 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 00000000 00000000 00000040 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000040 2**0
ALLOC
3 .ARM.attributes 00000016 00000000 00000000 00000040 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .ARM.attributes 00000000 .ARM.attributes
,这是
-c
的输出:$> readelf -a ./arm32_mov
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: ARM
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 148 (bytes into file)
Flags: 0x5000000, Version5 EABI
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 8
Section header string table index: 5
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 00000c 00 AX 0 0 4
[ 2] .data PROGBITS 00000000 000040 000000 00 WA 0 0 1
[ 3] .bss NOBITS 00000000 000040 000000 00 WA 0 0 1
[ 4] .ARM.attributes ARM_ATTRIBUTES 00000000 000040 000016 00 0 0 1
[ 5] .shstrtab STRTAB 00000000 000056 00003c 00 0 0 1
[ 6] .symtab SYMTAB 00000000 0001d4 000070 10 7 7 4
[ 7] .strtab STRTAB 00000000 000244 000007 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
There are no section groups in this file.
There are no program headers in this file.
There are no relocations in this file.
There are no unwind sections in this file.
Symbol table '.symtab' contains 7 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 SECTION LOCAL DEFAULT 1
2: 00000000 0 SECTION LOCAL DEFAULT 2
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 NOTYPE LOCAL DEFAULT 1 $a
5: 00000008 0 NOTYPE LOCAL DEFAULT 1 $t
6: 00000000 0 SECTION LOCAL DEFAULT 4
No version information found in this file.
Attribute Section: aeabi
File Attributes
Tag_CPU_arch: v4T
Tag_ARM_ISA_use: Yes
Tag_THUMB_ISA_use: Thumb-1
解决方案(Ian Cook)
$ objdump --syms --special-syms ./arm32_mov
./arm32_mov: file format elf32-littlearm
SYMBOL TABLE:
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l .text 00000000 $a <-- ARM code
00000008 l .text 00000000 $t <-- Thumb code
00000000 l d .ARM.attributes 00000000 .ARM.attributes
可以肯定的是,我再次插入了手臂代码,拇指代码和手臂代码。这是转储文件:
$> objdump --syms --special-syms ./arm32_mov
./arm32_mov: file format elf32-littlearm
SYMBOL TABLE:
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l .text 00000000 $a
00000008 l .text 00000000 $t
0000000c l .text 00000000 $a
00000000 l d .ARM.attributes 00000000 .ARM.attributes
您会看到在
objdump
和readelf
上出现了两次ARM符号,这些ARM符号围绕在拇指符号周围。#1 楼
ARM对象文件中应包含用于标识区域的符号,这些符号分别是Arm代码($a
),Thumb代码($t
)和文字数据($d
)。在中,您可以在符号#4和#5中看到它们。您的阅读精灵输出。
ie如果您使用
0
选项,则偏移量8
为手臂,偏移量--special-syms
为拇指obj-dump也会输出这些符号。
阅读ARM ELF ABI将帮助您理解什么
如果您打算尝试在Apple(Mach-O)可执行文件或固件Blob中反汇编ARM代码,那么您将不得不使用另一种技术,因为这些符号不会在场。
评论
优秀的。确实,我在示例文件中找到了您正在谈论的符号。谢谢 !
–恐怖
14年8月16日在9:09
刚知道其他可执行文件格式时,您说过Mach-O没有这样的符号,但是Microsoft Windows PE格式呢?它也将这些信息存储在符号中吗?
–恐怖
14年8月16日在10:26
@perror:IMAGE_FILE_MACHINE_ARMNT假定为Thumb-2。我认为较旧的(用于WinCE)使用位0。
–伊戈尔·斯科钦斯基♦
2014年8月16日14:05
#2 楼
在代码映射符号($a
,$t
,$d
)可用的情况下解决了此问题。但是,即使没有可用的符号,仍然有可能(几乎)完美地拆卸Thumb-2。一种有前途的技术是推测性拆卸,本文已对此进行了讨论。 Spedi这个工具在这里开源。它至少在使用的有限基准测试方面优于IDA Pro。还可以指示Spedi使用ARM代码映射符号(如果有的话)来获得基本事实。
可以利用本文讨论的思想来增强此工具,甚至解决您的混合模式反汇编的情况。当符号不可用时。
#3 楼
编译C / C ++代码时,还可以通过查看符号表来检测功能的ARM /缩略图状态。对于Thumb指令,地址的最低位设置为1;对于ARM指令,地址的最低位设置为0。要查看此内容,可以使用readelf --symWhen using
objdump -t and
readelf`。$ readelf --syms foo.elf |grep strlen$
4460: 08000195 16 FUNC GLOBAL DEFAULT 2 strlen
$ objdump -t foo.elf |grep strlen$
08000194 g F .text 00000010 strlen
请注意,实际地址为8000194(32位对齐),但是符号表条目(如readelf所示)显示9000195(其中LSB设置为指示拇指)。
这种方法只会告诉您函数开始时的ARM /缩略图状态,以查看任何内容。在函数内部进行转换时,您仍然需要查看其他答案中记录的
$t
和$a
符号。此LSB的含义在ARM ELF ABI中定义:
5.5.3符号值
除符号值的常规规则外,以下规则也适用于STT_FUNC类型的符号:
如果该符号寻址一条Arm指令,则其值就是该指令的地址(在可重定位的对象中,该指令与包含该指令的节的开头之间的偏移量)。
如果该符号寻址到Thumb指令, n,其值是设置了位0的指令的地址(在可重定位对象中,设置了位0的节偏移)。
为了重定位,使用的值应是指令的地址(st_value) &〜1)。
注意:这使链接程序无需参考映射即可区分Arm和Thumb代码符号。 Arm符号将始终具有偶数值,而Thumb符号将始终具有奇数值。但是,链接器应在将其用于重定位之前从该值中去除该区分位。
评论
转储符号表实际上,我没有太多符号,因为我只是直接用汇编语言编写的,并且没有链接最终的目标文件(我也这样做了,但结果完全相同。但是,我以最短的工作示例为例)。