C++ - 结构打包和 GCC 调试符号不匹配

问题描述

我正在做一个项目,我需要解析编译器的 DWARF 输出。我正在使用带有 GCC 8.3.0 的 Debian x64 (windows WSL)。

我遇到了一个编译器行为,我认为这可能是一个错误,但我不确定是否有我不明白的微妙之处。

为了打包结构,我使用以下指令:#pragma pack(push,1)。我认为 GCC 在出现以下情况时(但不限于)不会产生正确的调试符号:

  • .h 文件中的结构声明
  • pragma 指令仅在 .cpp 文件中,在 include 之前
  • cpp 文件中声明的结构体实例

这是一个结构:

struct StructD
{
    unsigned int bitfieldA : 1;
    unsigned int bitfieldB : 9;
    unsigned int bitfieldC : 3;
    unsigned int bitfieldD;
};

这里有一段代码来测试它:

file1StructDInstance.bitfieldA = 1;
file1StructDInstance.bitfieldB = 0b100111011;
file1StructDInstance.bitfieldC = 0b11;
file1StructDInstance.bitfieldD = 0b101001101;

unsigned char* ptr = (unsigned char*)(&file1StructDInstance);
printf("%02x %02x %02x %02x %02x %02x %02x %02x\n",ptr[0],ptr[1],ptr[2],ptr[3],ptr[4],ptr[5],ptr[6],ptr[7]);

场景 1 - 无编译指示

如果我不在任何地方使用编译指示,我的结构是 32 位对齐的并且调试符号匹配。软件输出是这样的:77 0e 00 00 4d 01 00 00.

<2><150>: Abbrev Number: 3 (DW_TAG_member)
<151>   DW_AT_name        : (indirect string,offset: 0xc2): bitfieldD
<155>   DW_AT_decl_file   : 2
<156>   DW_AT_decl_line   : 33
<157>   DW_AT_decl_column : 15
<158>   DW_AT_type        : <0x83>
<15c>   DW_AT_data_member_location: 4

调试 sumbol 报告 bitfieldD 在结构中的第 4 个字节,没有位偏移。哪个是对的。

场景 2 - 结构体声明前的编译指示

如果我把编译指示放在 .h 文件的顶部,我会得到这个软件输出77 0e 4d 01 00 00 00 00

调试符号如下

 <2><150>: Abbrev Number: 3 (DW_TAG_member)
<151>   DW_AT_name        : (indirect string,offset: 0xc2): bitfieldD
<155>   DW_AT_decl_file   : 2
<156>   DW_AT_decl_line   : 33
<157>   DW_AT_decl_column : 15
<158>   DW_AT_type        : <0x83>
<15c>   DW_AT_data_member_location: 2

所以 bitfieldD 在没有偏移量的字节 2 处,这又是正确的,并且与内存布局相匹配。

场景 3 - .cpp 中的编译指示,但在 .h 中省略

当我将 pragma 放在 .cpp 文件中时,在包含定义 StructD 的 .h 文件之前,但我省略将 pragma 放在 .h 文件中时,我在编译的代码和调试符号。

软件输出77 0e 00 00 4d 01 00 00

和调试符号

 <2><150>: Abbrev Number: 3 (DW_TAG_member)
<151>   DW_AT_name        : (indirect string,offset: 0xc2): bitfieldD
<155>   DW_AT_decl_file   : 2
<156>   DW_AT_decl_line   : 33
<157>   DW_AT_decl_column : 15
<158>   DW_AT_type        : <0x83>
<15c>   DW_AT_data_member_location: 2

现在调试符号说 bitfieldD 在字节 #2,但很明显软件把它放在字节 #4。我认识到 pragma 的用法可能不正确,但我希望 GCC 生成生成代码匹配的调试符号。

这是 GCC 中的错误还是我误解了 DWARF 的工作原理?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)