Electronic – Can’t get special PIC32 linker section to show up in output file

linker-scriptpic

I am defining a special section for some data that I want to show up at the beginning of my PIC32 binary image, as follows in the SECTIONS part of my elf32pic32mx.ld file:

  .headerdata ORIGIN(kseg0_program_mem)  :
  {
    *(.headerdata)
  } >kseg0_program_mem

and then in my code, I am initializing a structure like so:

const MODULEINFO SER_05_ModuleInfo __attribute__((section (".headerdata"))) = 
{
    sizeof(MODULEINFO),         // UINT16 HeaderSize
    MODULE_TYPE,                // UNIT16 ModuleType
    // etc. etc.
};

When I compile and link the program, the structure shows up in the map file:

.headerdata     0x9d000000       0x48
 *(.headerdata)
 .headerdata    0x9d000000       0x48 DriverHeader.o
                0x9d000000                SER_05_ModuleInfo

but the actual data does not show up in the hex output file.

If I leave off the attribute ((section (".headerdata"))) in the structure, the structure shows up in the .rodata of the map file, and the data does show up in my hex output file.

When defining special sections, is there something else that needs to be done to actually get them to generate output besides the >kseg0_program_mem line?

Best Answer

Given the presented code, an object dump of the headers will show something similar to the following:

pic32-objdump -x main.o

9 .rodata       00000004  00000000  00000000  00000360  2**2
              CONTENTS, ALLOC, LOAD, READONLY, CODE
10 .headerdata   00000004  00000000  00000000  00000364  2**2
              CONTENTS, ALLOC, LOAD, DATA

This shows that the section in which header data is placed does not have the READONLY and CODE attributes and this in turn causes the linker to operate differently on the data from that section. In my limited tests, it would seem that content in .headerdata is treated as other data, meaning that it is put into a special section named .dinit and loaded from flash to RAM on program startup. You mention that the data from the .headerdata section doesn't appear in your hex file - I suspect you'll find it in the .dinit section.

If you are trying to get functionality similar to .rodata but with your own section name, you will need to mark your .headerdata section with an additional r attribute like this:

static const MODULEINFO SER_05_ModuleInfo __attribute__((section (".headerdata,r"))) =

resulting in an object header dump as follows:

  9 .rodata       00000004  00000000  00000000  00000360  2**2
              CONTENTS, ALLOC, LOAD, READONLY, CODE
 10 .headerdata   00000004  00000000  00000000  00000364  2**2
              CONTENTS, ALLOC, LOAD, READONLY, CODE

This will then be treated similar to .rodata in the linker as long as you have added your special linker script snippet as listed.

I presume that you're trying to make your header the first set of data that is present in program space. Although the linker script additions you have listed would appear to work, I usually prefer to just add the additional sections in line with existing sections in the preferred order. Instead of a separate .headerdata ORIGIN(kseg0_program_mem) type section, you could edit the .text section to end up with something like this:

 .text :
 {
   *(.headerdata)
   *(.stub .gnu.linkonce.t.*)
   KEEP (*(.text.*personality*))
   *(.mips16.fn.*)
   *(.mips16.call.*)
   *(.gnu.warning)
 } >kseg0_program_mem

Using pic32-objdump -d main.elf will show a complete disassembly of the final binary in which you should now see your header data at the correct address.

You may want to check that placing your header at the start of program space does not upset operation of other parts of the system such as exception handling.

I found a copy of pic30.c gcc compiler code floating around on the web somewhere and the accepted section attribute flags appear to be:

b - BSS

x - Executable code

r - Read only data

d - Writeable data