I'm trying to fix an issue after extending a 32 bit global variable to a 64 bit one. unfortunately the program crashes with that extended 64 bits. When I compared the generated outputs elfdump.txt, for both : the generated elfdump.txt before and after the global variable extension. I discovered that the program headers are now 6 rather than 5 with that extended 64 bit variable, while they remain the same when the application is running fine with that 32 bit global variable.
32 bit global variable output:
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x010000 0x00010000 0x00010000 0x34920 0x34920 R E 0x10000
LOAD 0x054010 0x40004010 0x00044920 0x0144f 0x0144f RW 0x10000
LOAD 0x055460 0x40005460 0x00045d6f 0x0000c 0x0000c RW 0x10000
LOAD 0x060000 0x00080000 0x00080000 0x000b0 0x000b0 R 0x10000
LOAD 0x06546c 0x4000546c 0x4000546c 0x00000 0x04c80 RW 0x10000
Section to Segment mapping:
Segment Sections...
00 .rcw .init .FlashProgram .FlashErase .FlashDriver .text .flash_data .rodata .isrvectbl .xcptn
**01** .backupram .adapdata **.data**
02 .ctors
03 calconst
04 .bss
64 bit global variable output:
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x010000 0x00010000 0x00010000 0x34920 0x34920 R E 0x10000
LOAD 0x054010 0x40004010 0x00044920 0x0003c 0x0003c RW 0x10000
LOAD 0x054050 0x40004050 0x0004495c 0x013db 0x013db RW 0x10000
LOAD 0x05542c 0x4000542c 0x00045d37 0x0000c 0x0000c RW 0x10000
LOAD 0x060000 0x00080000 0x00080000 0x000b0 0x000b0 R 0x10000
LOAD 0x065438 0x40005438 0x40005438 0x00000 0x04c7c RW 0x10000
the second LOAD has 0x0003c FileSiz and 0x0003 of cMemSiz which is wrongly mapped. and the following LOAD is an extra LOAD by result.
Section to Segment mapping:
Segment Sections...
00 .rcw .init .FlashProgram .FlashErase .FlashDriver .text .flash_data .rodata .isrvectbl .xcptn
01 .backupram .adapdata
**02 .data**
03 .ctors
04 calconst
05 .bss
segment section 01 has been divided into two segments 01 and 02.
Updates
Initialized global/static variables values get allocated in .data
segment
it turned out that I have an alignment problem, in the beginning, the data section was 4 byte aligned, starting from the address 0x4000404c :
and then when I changed that variable,the alignment has became 8.
Then the .data segment address (0x4000404c) has been shifted by 4 bytes, because of the alignment(0x40004050 mod 8 = 0 )
I'm using the compiler version gcc 8.1.0 , and visual studio 2005 IDE, and an MPC5644A MCU, Power architecture.
This is an answer to my own question. I will write some updates as well and please correct me if I’m saying something wrong.
The variable before was a 32 bit variable.
unsigned int Var1 = 0;
void function (unsigned int var2 )
{
Var1 |= var2;
}
And then I extended it:
unsigned long long Var1 = 0x0ULL;
void function (unsigned long long var2 )
{
Var1 |= var2;
}
Alternatively, the host can read/write the SPRAM by 8-, 16-, or 32-bit accesses in aligned addresses. (Section 24.5.2.3 Parameter access, reference manual MPC5644ARM).
While the compiler automatically sets the type alignment to the largest alignment that can ever be used for any data type on the target machine for which you are compiling, which is our extended variable (8 bytes) boundary, that's why during the compilation, 4 padding bytes were required to align the start of the data segment to perform that 8 bytes alignment. (this is my understanding).
My conclusion:
The (initialized) global data variables are almost by definition in the data section, since the alignment was 4 bytes in the data section, and the VA is 4 bytes aligned, on the other hand, the host can read any 32 bits variable, and everything worked fine. Please find attached a screenshot:
So the alignment was 4 boundaries.
You can see that the small data sections are gathered together in the program header so single-instruction offsets can access them all.
Then we extended that variable
When we extended that global variable, that small data segment split into two, and I found that the VA of data section changed. a 4 bytes padding has been performed by the compiler to ensure the new alignment (8 bytes boundaries).
The compiler automatically sets the type alignment to the largest it can ever use for any data type.
That's why that small data segment split into two:
And then I tried to force that section to be 4 bytes aligned, to ensure that the access to that variable would be fine and no exception will occur, exactly like you said.
.data ALIGN (4): AT (NEXT_LOAD_ADDR)
{
__DATASTART = . ;
*(.data)
*(.data.*)
*(.gnu.linkonce.d*)
CONSTRUCTORS
} > int_sram
NEXT_LOAD_ADDR = NEXT_LOAD_ADDR + SIZEOF(.data);
And the bug has been fixed:
The size of the data section has also been increased by 4 bytes, 1413 - 4 (32 bits global variable) + 8 (64 bits global variable) = 1417 bytes