1

I am working on a project where I need to parse the DWARF output of a compiler. I am working a Debian x64 (windows WSL) with GCC 8.3.0.

I face a compiler behaviour that I think might be a bug, but I am unsure if there's a subtlety I don't get.

I order to pack a structure, I use the following directive : #pragma pack(push,1). I think that GCC doesn't produce the right debugging symbol when the following conditions occurs (but not limited to them):

  • struct declaration in .h file
  • pragma directive in the .cpp file only, before the include
  • instance of struct delcared in the cpp file

Here's a structure :

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

And here's a piece of code to test it:

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]);

Scenario 1 - No pragma

If I do not use the pragma anywhere, my struct is 32bits aligned and the debugging symbol matches. The software output is like this: 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

The debugging sumbol report that bitfieldD is at the 4th byte in the structure, no bit offset. Which is right.

Scenario 2 - Pragma before struct declaration

If I put the pragma at the top of the .h file , I get this software output : 77 0e 4d 01 00 00 00 00

And the debugging symbol is as follow

 <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

So bitfieldD is at byte 2 without offset, which is again right and matches the memory layout.

Scenario 3 - Pragma in .cpp, but omitted in .h

When I put the pragma in the .cpp file, before the include of the .h file that define StructD, but I omit to put the pragma in the .h file, I get a mismatch between the compiled code and the debugging symbol.

software output : 77 0e 00 00 4d 01 00 00

And debugging symbol

 <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

Now the debugging symbols says that bitfieldD is at byte #2, but clearly the software put it at byte #4. I recognize that the usage of the pragma might not be proper, but I would expect GCC to produce debugging symbols that matches the generated code.

Is this a bug in GCC or am I misunderstanding how DWARF works?

  • I can't reproduce this. For me, scenario 3 outputs the same bytes as scenario 2 (which is also what I would have expected). – ssbssa May 09 '21 at 12:33
  • Ah, I forgot to mention that the instanciation is done in a different file than the file that prints the memory content. It's intantiated in file1.cpp, struct is declared in file1.h and the code that print the content is in main.cpp which declare the instance as extern and includes file1.h. It might be related to the fact that main.cpp includes file1.h with no pragma. I still don't know if I should consider this a normal behaviour. Probably a known undefined behaviour because of the wrong usage of pragmas – Pier-Yves Lessard May 09 '21 at 12:43
  • Yes, that sounds like UB, you basically get 2 different struct types with the same name. – ssbssa May 09 '21 at 12:58

0 Answers0