考虑以下AVR程序:
#define F_CPU 500000ul
#include <avr/io.h>
#include <util/delay.h>
// Not used, but it has significance. I suspect its presence is causing some undesired behaviour in debug info
void do_nothing() {
_delay_ms(300);
_delay_ms(300);
}
int main(void) {
DDRD = 0xFF; // Line 13
PORTD = 0x00; // Line 14
PORTD = 0x01; // Line 15
PORTD = 0x00; // Line 16
while (1) {
}
}
很直接。如果我们在禁用优化并启用调试信息(-ggdb)的情况下编译,并让GDB反汇编操作码,我们会得到main()
的以下指令:
0x000002dc <main+0>: push r28
0x000002de <main+2>: push r29
0x000002e0 <main+4>: in r28, 0x3d
0x000002e2 <main+6>: in r29, 0x3e
0x000002e4 <main+8>: ldi r24, 0x2A
0x000002e6 <main+10>: ldi r25, 0x00
0x000002e8 <main+12>: ldi r18, 0xFF ; 255
0x000002ea <main+14>: movw r30, r24
0x000002ec <main+16>: st Z, r18
0x000002ee <main+18>: ldi r24, 0x2B
0x000002f0 <main+20>: ldi r25, 0x00
0x000002f2 <main+22>: movw r30, r24
0x000002f4 <main+24>: st Z, r1
0x000002f6 <main+26>: ldi r24, 0x2B
0x000002f8 <main+28>: ldi r25, 0x00
0x000002fa <main+30>: ldi r18, 0x01 ; 1
0x000002fc <main+32>: movw r30, r24
0x000002fe <main+34>: st Z, r18
0x00000300 <main+36>: ldi r24, 0x2B
0x00000302 <main+38>: ldi r25, 0x00
0x00000304 <main+40>: movw r30, r24
0x00000306 <main+42>: st Z, r1
0x00000308 <main+44>: rjmp .-2 ; 0x308 <main+44> (offset in GDB is byte offset, not word offset, so RJMP .-2 is actually RJMP .-1 (infinite loop))
现在,让我们关注第13行。除非我弄错了,该行的PC(字节地址)范围应该是0x 000002 e4(包括)到0x 000002 ee(不包括)。换句话说,我相信第13行由以下指令子集组成:
0x000002e4 <main+8>: ldi r24, 0x2A
0x000002e6 <main+10>: ldi r25, 0x00
0x000002e8 <main+12>: ldi r18, 0xFF ; 255
0x000002ea <main+14>: movw r30, r24
0x000002ec <main+16>: st Z, r18
我们在r24和r25中加载端口D的DDR地址,然后将0xFF加载到r18中,然后将DDR地址复制到Z寄存器,然后将r18的值写入该DDR。所有这些都是为了13号线,除非我弄错了。
问题是DWARF的数据不符合我的观点。从ELF转储DWARF数据(使用dwarfdump),我们得到以下行号信息:
0x000002c8 [ 10, 1] NS uri: "main.c"
0x000002de [ 12,18] NS
0x000002e6 [ 13, 5] NS <-- This seems wrong...
0x000002ea [ 13,10] NS
0x000002f0 [ 14, 5] NS <-- and this...and so on
0x000002f4 [ 14,11] NS
0x000002f8 [ 15, 5] NS
0x000002fc [ 15,11] NS
0x00000302 [ 16, 5] NS
0x00000306 [ 16,11] NS
0x0000030a [ 18,11] NS DI=0x1
0x0000030c [ 18,11] NS ET
因此,根据DWARF数据,main.c的第13行从0x 000002 e6开始,第14行从0x 000002 f0开始,但这似乎不正确。它应该分别为0x 0000002 e4和0x 0000002 ee。
更奇怪的是,未使用的do_nothing()
函数似乎在其中发挥了作用。如果我把这个函数一起删除,DWARF数据是正确的:
0x00000082 <main+0>: push r28
0x00000084 <main+2>: push r29
0x00000086 <main+4>: in r28, 0x3d
0x00000088 <main+6>: in r29, 0x3e
0x0000008a <main+8>: ldi r24, 0x2A
0x0000008c <main+10>: ldi r25, 0x00
0x0000008e <main+12>: ldi r18, 0xFF ; 255
0x00000090 <main+14>: movw r30, r24
0x00000092 <main+16>: st Z, r18
0x00000094 <main+18>: ldi r24, 0x2B
...
0x00000082 [ 12,18] NS uri: "main.c"
0x0000008a [ 13, 5] NS
0x0000008e [ 13,10] NS
0x00000094 [ 14, 5] NS
0x00000098 [ 14,11] NS
0x0000009c [ 15, 5] NS
0x000000a0 [ 15,11] NS
0x000000a6 [ 16, 5] NS
0x000000aa [ 16,11] NS
0x000000ae [ 18,11] NS DI=0x1
0x000000b0 [ 18,11] NS ET
在那里,第13行从0x 000008 a开始(第一个LDI
指令,将DDRD加载到r24和r25中),第14行从0x 0000094开始,这是正确的。
如果我从未使用的函数体中删除一个_delay_ms()
调用,情况也是如此:
void do_nothing() {
_delay_ms(300);
// By removing the other _delay_ms() call, the debug info is no longer incorrect.
}
你知道出什么事了吗
我使用GCC 11.1.0,用于AVR架构。
1条答案
按热度按时间zy1mlcev1#
这似乎是GCC 11.1.0中的一个回归。后来就修好了。我升级到GCC 13.2.0,无法重现这个问题,所以一切都很好。