AVR程序DWARF行号数据异常:未使用函数引发调试信息问题
AVR GCC 11.1.0未调用函数导致DWARF行号偏移异常问题解析
问题背景
考虑以下AVR程序:
#define F_CPU 500000ul #include <avr/io.h> #include <util/delay.h> // 未被调用,但疑似引发调试信息异常 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) { } }
编译时使用**禁用优化(-O0)**并启用-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字节地址范围为0x000002e4(含)至0x000002ee(不含),对应指令为:
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
但通过dwarfdump导出的DWARF行号数据显示:
0x000002c8 [ 10, 1] NS uri: "main.c" 0x000002de [ 12,18] NS 0x000002e6 [ 13, 5] NS <-- 此处存在异常... 0x000002ea [ 13,10] NS 0x000002f0 [ 14, 5] NS <-- 此处及后续均存在异常... 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
第13行起始地址为0x000002e6,第14行起始地址为0x000002f0,与预期不符。
进一步测试发现:移除未被调用的do_nothing()函数或其中一个_delay_ms(300)调用后,DWARF行号数据恢复正常。使用工具为针对AVR架构的GCC 11.1.0。
异常原因解析
这是AVR GCC 11.1.0版本中DWARF行号生成模块与宏展开代码交互的已知bug,具体细节如下:
_delay_ms是依赖F_CPU的预编译宏,会展开成大量嵌套循环指令以实现软件延时。当do_nothing()中包含两个_delay_ms(300)时,宏展开后会生成超量的机器指令。- 即使函数未被调用,
-O0(无优化)模式下GCC仍会为其生成完整的机器码,并在DWARF调试信息中记录该函数的行号映射。 - GCC 11.1.0针对AVR架构的DWARF行号生成逻辑存在地址偏移计算错误:当某个未被调用的函数包含大量宏展开指令时,会干扰后续函数(如
main)的行号地址映射,导致行号对应的PC地址整体偏移。 - 移除一个
_delay_ms或整个函数后,宏展开的指令量大幅减少,行号生成模块的偏移错误不再触发,因此DWARF行号数据恢复正常。
内容的提问来源于stack exchange,提问作者navnav
相关产品推荐
相关产品推荐

