在我使用gcc-arm-none-eabi 4.8
和binutils 2.26
的设置中,当使用-mthumb
单独编译目标文件时,我会得到相当不明确的行为,但在最后的链接步骤中使用{{1}没有从链接器收到任何警告。为什么会这样?
由于缺少标志,链接器选择了默认的multilib架构,因此未定义的行为可能(根据我首先要求的非常有用的FOSS开发人员)。但是,链接器为什么不警告这个问题呢?是否可以轻松地从对象和库文件中检测链接函数的ISA,以确定是否存在可疑的东西?
答案 0 :(得分:2)
理想情况下,它应该从被链接的对象中知道。反汇编并检查不同对象的功能之间的相互作用。
我最近试图证明gnu工具/链接器在添加蹦床方面有多好。当它一直失败的时候。它会把蹦床放在一个方向而不是另一个方向(拇指往/来自手臂)。我认为这是一个来自C问题的汇编,我没有使用编译器使用的指令plethera,所以很可能就是这样。
设置一些测试用例相当简单,用arm构建的函数制作一个对象,用拇指构建另一个函数,让它们互相调用。在它周围放置足够的结构以使工具无错误地连接,然后进行反汇编和检查。
armstart.s
#on the main -------------
temp_obj = []
obj = [
{'name':'a1', 'level':0},
{'name':'a2', 'level':0},
{'name':'a3', 'level':1},
{'name':'a4', 'level':1},
{'name':'a5', 'level':2},
{'name':'a6', 'level':2},
]
the_result = myFunction(obj, temp_obj)
print(temp_obj)
#above print would result to an empty list
#this is my problem
#end of main body -------------
def myFunction(obj, new_temp_obj):
inside_list = []
for x in obj[:]:
if x['level'] == 0:
inside_list.append(x)
obj.remove(x) #removing the element that was added to the inside_list
new_temp_obj = obj[:] #copying the remaining element
print(new_temp_obj)
# the above print would result to
#[{'name': 'a3', 'level': 1}, {'name': 'a4', 'level': 1}, {'name': 'a5', 'level': 2}, {'name': 'a6', 'level': 2}]
return inside_list
notmain.c
.global _start
_start:
bl notmain
b hang
hang: b .
one.c
extern unsigned int one ( unsigned int );
int notmain ( void )
{
one(1);
return(0);
}
two.c
extern unsigned int two ( unsigned int x );
unsigned int one ( unsigned int x )
{
return(two(x+5));
}
生成文件
extern unsigned int one ( unsigned int x );
unsigned int two ( unsigned int x )
{
return(one(x+7));
}
一些反汇编:
ARMGNU = arm-none-eabi
#ARMGNU = arm-linux-gnueabi
AOPS = --warn --fatal-warnings
COPS = -Wall -O2 -nostdlib -nostartfiles -ffreestanding
all : notmain.bin
clean:
rm -f *.bin
rm -f *.o
rm -f *.elf
rm -f *.list
rm -f *.bc
rm -f *.opt.s
rm -f *.norm.s
rm -f *.hex
armstart.o : armstart.s
$(ARMGNU)-as $(AOPS) armstart.s -o armstart.o
notmain.o : notmain.c
$(ARMGNU)-gcc $(COPS) -c notmain.c -o notmain.o
two.o : two.c
$(ARMGNU)-gcc $(COPS) -mthumb -c two.c -o two.o
one.o : one.c
$(ARMGNU)-gcc $(COPS) -c one.c -o one.o
notmain.bin : memmap armstart.o notmain.o one.o two.o
$(ARMGNU)-ld -o notmain.elf -T memmap armstart.o notmain.o one.o two.o
$(ARMGNU)-objdump -D notmain.elf > notmain.list
$(ARMGNU)-objcopy notmain.elf notmain.hex -O ihex
$(ARMGNU)-objcopy notmain.elf notmain.bin -O binary
本例中的工具链
20000024 <one>:
20000024: e92d4010 push {r4, lr}
20000028: e2800005 add r0, r0, #5
2000002c: eb000007 bl 20000050 <__two_from_arm>
20000030: e8bd4010 pop {r4, lr}
20000034: e12fff1e bx lr
20000038 <two>:
20000038: b510 push {r4, lr}
2000003a: 3007 adds r0, #7
2000003c: f000 f804 bl 20000048 <__one_from_thumb>
20000040: bc10 pop {r4}
20000042: bc02 pop {r1}
20000044: 4708 bx r1
20000046: 46c0 nop ; (mov r8, r8)
20000048 <__one_from_thumb>:
20000048: 4778 bx pc
2000004a: 46c0 nop ; (mov r8, r8)
2000004c: eafffff4 b 20000024 <one>
20000050 <__two_from_arm>:
20000050: e59fc000 ldr ip, [pc] ; 20000058 <__two_from_arm+0x8>
20000054: e12fff1c bx ip
20000058: 20000039 andcs r0, r0, r9, lsr r0
2000005c: 00000000 andeq r0, r0, r0
(binutils 2.26.20160125)
工作得非常好。
与gcc 5.4.0和binutils 2.26.1相同。
看看readelf之间我们看到的两个对象之间的差异:
arm-none-eabi-gcc (GCC) 6.1.0
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
答案 1 :(得分:0)
使用-mthumb单独编译目标文件,但在最后的链接步骤中使用ld将该标志保留在外,而不会从链接器收到任何警告。为什么会这样?
生成的可执行文件在大多数ARM平台上都可以正常工作,但微控制器配置文件(Cortex-M)除外。甚至有一个很好的理由将拇指代码与ARM库混合:代码大小。