为什么 'ld' 在链接没有“-mthumb”的“-mthumb-only”目标文件时不发出警告?
Why doesn't 'ld' warn when linking '-mthumb-only' object files without '-mthumb'?
在我使用 gcc-arm-none-eabi 4.8
和 binutils 2.26
的设置中,当使用 -mthumb
单独编译目标文件时,我得到了相当不确定的行为,但在最后的链接步骤中使用 ld
而没有从链接器得到任何警告。为什么会这样?
未定义的行为可能是(根据我首先询问的非常有帮助的 FOSS 开发人员的说法)由于缺少标志而链接器选择的默认 multilib 体系结构。但是,为什么链接器不警告这个问题?难道它不能很容易地从对象和库文件中检测到链接函数的 ISA 以确定发生了什么可疑的事情吗?
compiling the object files separately with -mthumb but leaving that flag out in the final linking step using ld without getting any warning from the linker. Why is that the case?
除了微控制器配置文件 (Cortex-M) 之外,生成的可执行文件应该可以在大多数 ARM 平台上正常运行。甚至还有一个很好的理由将拇指代码与 ARM 库混合使用:代码大小。
理想情况下是的,它应该从被 linked 的对象中知道。拆解考察不同对象的函数交互
我最近试图证明 gnu tools/linker 在添加蹦床方面有多好。当它一直惨败时。它会把蹦床放在一个方向而不是另一个方向(拇指 to/from 手臂)。我认为这是一个程序集 to/from C 问题,我没有像编译器那样使用过多的指令,所以可能就是这样。
设置一些测试用例非常简单,用为 arm 构建的函数创建一个对象,用为 thumb 构建的函数创建另一个对象,让它们相互调用。在它周围放置足够的结构以使工具 link 没有错误,然后拆卸并检查。
armstart.s
.global _start
_start:
bl notmain
b hang
hang: b .
notmain.c
extern unsigned int one ( unsigned int );
int notmain ( void )
{
one(1);
return(0);
}
one.c
extern unsigned int two ( unsigned int x );
unsigned int one ( unsigned int x )
{
return(two(x+5));
}
two.c
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
本例中的工具链
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.
(binutils 2.26.20160125)
工作得很好。
对于 gcc 5.4.0 和 binutils 2.26.1 也是如此。
查看我们看到的两个对象的 readelf 之间的差异,例如:
< 00000004 00000a1d R_ARM_JUMP24 00000000 two
---
> 00000004 00000a0a R_ARM_THM_CALL 00000000 one
在我使用 gcc-arm-none-eabi 4.8
和 binutils 2.26
的设置中,当使用 -mthumb
单独编译目标文件时,我得到了相当不确定的行为,但在最后的链接步骤中使用 ld
而没有从链接器得到任何警告。为什么会这样?
未定义的行为可能是(根据我首先询问的非常有帮助的 FOSS 开发人员的说法)由于缺少标志而链接器选择的默认 multilib 体系结构。但是,为什么链接器不警告这个问题?难道它不能很容易地从对象和库文件中检测到链接函数的 ISA 以确定发生了什么可疑的事情吗?
compiling the object files separately with -mthumb but leaving that flag out in the final linking step using ld without getting any warning from the linker. Why is that the case?
除了微控制器配置文件 (Cortex-M) 之外,生成的可执行文件应该可以在大多数 ARM 平台上正常运行。甚至还有一个很好的理由将拇指代码与 ARM 库混合使用:代码大小。
理想情况下是的,它应该从被 linked 的对象中知道。拆解考察不同对象的函数交互
我最近试图证明 gnu tools/linker 在添加蹦床方面有多好。当它一直惨败时。它会把蹦床放在一个方向而不是另一个方向(拇指 to/from 手臂)。我认为这是一个程序集 to/from C 问题,我没有像编译器那样使用过多的指令,所以可能就是这样。
设置一些测试用例非常简单,用为 arm 构建的函数创建一个对象,用为 thumb 构建的函数创建另一个对象,让它们相互调用。在它周围放置足够的结构以使工具 link 没有错误,然后拆卸并检查。
armstart.s
.global _start
_start:
bl notmain
b hang
hang: b .
notmain.c
extern unsigned int one ( unsigned int );
int notmain ( void )
{
one(1);
return(0);
}
one.c
extern unsigned int two ( unsigned int x );
unsigned int one ( unsigned int x )
{
return(two(x+5));
}
two.c
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
本例中的工具链
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.
(binutils 2.26.20160125)
工作得很好。
对于 gcc 5.4.0 和 binutils 2.26.1 也是如此。
查看我们看到的两个对象的 readelf 之间的差异,例如:
< 00000004 00000a1d R_ARM_JUMP24 00000000 two
---
> 00000004 00000a0a R_ARM_THM_CALL 00000000 one