You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 13:23:10