I am currently trying to dev a firmware for a PIC24F using the whole microchip stack (xc16, mcc, mplab X IDE, etc ...) (not necessarily relevant but i work on a debian 22)
Doesn't really matter why but i want to place some data on a specific section that i will place at specific location on my firmware.
Let's imagine i have a struct my_struct
defined in file.h
as follow :
#pragma pack(push, 1) // using pragma pack to pack the struct and avoid padding
typedef struct {
uint16_t magic;
uint32_t length;
uint32_t crc;
uint16_t word_1;
uint16_t word_2;
uint8_t byte_1;
uint8_t byte_2;
uint8_t byte_3;
uint8_t array[15];
} my_struct;
#pragma pack(pop)
then in my file.c
:
const my_struct __attribute__((section("my_section"))) instance = {
.magic = 0xbaba,
.crc = 0xbabababa,
.length = 0xbabababa,
.byte_1 = 0xba,
.byte_2 = 0xba,
.byte_3 = 0xba,
.word_1 = 0xbaba,
.word_2 = 0xbaba,
.array = {0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba }
};
When I create the object file file.o
,
I expect having a section my_section
of size 32 and filled with 0xBA. So I try to inspect the produced file.o
using objdump to ensure that the data are the one that I want
$ size -A file.o
section size addr
[...]
my_section 64 0
$ objdump -s -j my_section file.o
Contents of section my_section:
0000 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
0010 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
0020 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
0030 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
But it seems like XC16 added a 00
padding for each data byte and that it doubled the size of the section.
I know that padding is to keep data aligned for optimization purpose, but for this specific case, I really need those data to be packed and the size needs to be 32.
The issue is not only in file.o
, even if I go until the end of the compilation process, I manage to have the section located where i want (thanks to an updated linker script) but it still contains the unwanted padding. So i'm pretty sure the issue is not about linker, but about the compilation process itself
I tried a loooot of things, really.
I tried to pack the structure using :
#pragma pack(1)
(with or without push/pop)
I also tried to use __packed
or __atribute__((packed(1)))
I tried to add the aligned(1)
keyword, or the volatile
specifier
I even tried to use some uint32_t arr[8]
, uint16_t arr[16]
and uint8_t arr[32]
instead of a struct.
I tried a lot of mplab project configuration (i can't remember which ones, probably all of them)
I tried all those options separately and together ...
But nothing changes the output. I checked documentation or anything i could, but i can't make it work. Is this even possible under xc16 or should i give up?
=== EDIT ===
Thanks to @pmacfarlane and @thebusybee, I dug a little further and here is what i found:
I declared two identical structs
- one (
s1
) with the__attribute__((used, section("my_section"))
, - the other (
s2
) with no attribute
when i compile and inspect file.o
I got the same output as before for the my_section
output, coming from s1
.
And some data has been added to the .const section, coming from s2
:
$ objdump -s -j .const file.o
Contents of section .const:
0000 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
0010 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
0020 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
0030 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
So nothing new here, but if I inspect the final elf, there is a difference :
$ objdump -s -j .const firmware.elf
Contents of section .const:
82cc baba0000 baba0000 baba0000 baba0000 ................
82dc baba0000 baba0000 baba0000 baba0000 ................
82ec baba0000 baba0000 baba0000 baba0000 ................
82fc baba0000 baba0000 baba0000 baba0000 ................
$ objdump -s -j my_section firmware.elf
Contents of section my_section:
0000 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
0010 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
0020 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
0030 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
Please note that i am using the default linker script for this example.
I tried to add some code in it , even to modify it entirely but, as nothing worked as expected, I went back to the default one.
For minimal reproducible purpose, i even ended up removing everything about section management, and the result stays the same. So i think the behaviors is coming from the xc16 linker default behavior and not from the linker script.
I would gladly add the linker script to the question but it is 3k lines long.
So, it looks like the linking process is packing ba00ba00 into baba0000 for built-in section such as .const
but not for my custom section.
Don't know if it's relevant, but I assumed that this would bring more information. Any hints ?