C++ and section attribute

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello freaks,
I have C++ specific question. In ordinary C, to specify the location of function one could specify:

voif func()__attribute__ ((section (".bootloader")));

I can do the same in C++ for every class method, but it is obviously annoying. Can I specify the location of the whole class?
I'd like to share some classes between application code and bootloader, so I try to put some classes in specific section, compile it, and next link with bootloader or application code. So both will share the same code, while gcc should properly initialize classes (copy VMT into SRAM), and so on.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I’d like to share some classes between application code and bootloader,

This is ENTIRELY the wrong way to do it whether you are using C or C++. See the Bootloader FAQ in the Tutorial Forum. As I wrote there ".bootloader" is a misnomer and the last thing it should be used for is actually implementing a bootloader. It's only for adding some SPM routines on the end of a normal application - which therefore must reside above the BLS boundary.

You should build the bootloader and application as two entirely separate programs then if the bootloader wants to share some of its functions to the app (you MUST not do it the other way round) then use a despatch table with a pointer to it as a shared location.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Cliff,

I agree that writing two separate programs is certainly the most common way to go.

However, I disagree in the fact that an application and bootloader can be written at the same time. The ".bootloader" section name is not necessarily a misnomer.

There's a lot of way to implement it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

However, I disagree in the fact that an application and bootloader can be written at the same time.

One of us clearly doesn't understand what the other one is saying. Not sure which way round it is.

The facts are these:

1) boot.h provides "BOOTLOADER_SECTION" (which is just a name for __attribute__((section(".bootloader))) )
2) From the name it sounds like it might be used for implementing a bootloader but this is not the case.
3) BOOTLOADER_SECTION is used to tag a few functions in a "normal" app if they must locate to .bootloader which itself will be positioned to the BLS with a --section-start. This is for an app that wants to save some data into the flash as it runs.
4) A real bootloader and app should always be written as two separate programs - each with their own .text (one repositioned to the BLS with a -Ttext=).
5) The bootloader MUST be able to run completely stand-alone in the case when the app was erased but the replacement was interrupted.
6) The app.hex and boot.hex can easily be joined by srec_cat into everything.hex for factory programming. Another technique is to ISP the bootloader then use it to put the app code in place (that's what it's designed for after all!)
7) The bootloader can share some of it's functions for use by the app (it will always be present). A common way to do this is to fill an array/struct full of function pointers to the routines in the bootloader then it passes the base address to the app at launch time somehow.

Which of these statements do you disagree with?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Clawson, cool down please.
In my case, as always, bootloader and main app are two separate applications, compiled separately. The main app uses bootloader code to save some space. But in C++ I cannot just use a vector table – class must be initialized, gcc must do some magical things, like copying class virtual method table into SRAM (because of stupidity of the compiler) and do some other magical stuff (e.g. initialization of static members and fields). All this stuff is done during executing code in .init sections. That’s why I must link the main app against precompiled obj file, with class code located at the appropriate address. The bootloader code is linked against the same obj file (or library file if you like).
The problem is that I need to use the attribute section with every class member, is it possible to specify the section attribute for the whole class?
Or maybe somebody has a better idea how to create class instance in main app, when class belongs to bootloader app?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Clawson, cool down please.

That suggests I'm heated or even angry. I'm not and I haven't the first clue what makes you think I was. But if you don't want advice just say it - I'm out.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Every advice is appreciated, especially yours.
But please focus on the main problem, the name of the section is not important. But because I must link the app with bootloader code, the boot code cannot be in the .text segment - .bootloader segment is fine.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TFrancuz wrote:
But because I must link the app with bootloader code, the boot code cannot be in the .text segment - .bootloader segment is fine.
So you link the application with the shared code, but you don't export it to the hex file, because it is already in the Flash as part of the bootloader code, right?
TFrancuz wrote:
do some other magical stuff (e.g. initialization of static members and fields).
But your class cannot have static members. It cannot access any static data (global variables, static members, ...).

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sternst wrote:
TFrancuz wrote:
But because I must link the app with bootloader code, the boot code cannot be in the .text segment - .bootloader segment is fine.
So you link the application with the shared code, but you don't export it to the hex file, because it is already in the Flash as part of the bootloader code, right?

Right. The bootloader code is already in FLASH (but I have obj file generated by gcc, so I can link the app code).

sternst wrote:
TFrancuz wrote:
do some other magical stuff (e.g. initialization of static members and fields).
But your class cannot have static members. It cannot access any static data (global variables, static members, ...).

Right, I cannot use static members, only static methods. But still I need to initialize class, because I use virtual methods, so gcc needs to generate a proper startup code.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TFrancuz wrote:
sternst wrote:
TFrancuz wrote:
do some other magical stuff (e.g. initialization of static members and fields).
But your class cannot have static members. It cannot access any static data (global variables, static members, ...).

Right, I cannot use static members, only static methods. But still I need to initialize class, because I use virtual methods, so gcc needs to generate a proper startup code.

Alas, the vtable pretty much is a static member.
Any solution that allows a vtable will allow a static member.
That said, it can be done with just the right linker magic:
Compile and link bootloader, LDFLAGS+= -Wl,-Ttext=...,-Tdata=...,-Tbss=...
objcopy --strip-symbol=... bootloader.elf shoe.elf
Compile and link application,
LDFLAGS+= -Wl,--just-symbols=shoe.elf,-Ttext=...,-Tdata=,-Tbss=...

There is no dispatch table.
The application will depend on the particular bootloader.
The location of -Wl,--just-symbols=shoe.elf will matter.
It should come before any libraries.
Filling in the ...'s is left as an exercise for the reader.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks skeeve, I’ve learnt a lot.
My first tests have shown that your solution works fine, and moreover I don’t need to define additional sections.
I will show what I’ve done, and please tell me if I’ve understood everything right.

First, I compiled the bootloader code, with text section relocated to bootloader address (for example 0x4000), I didn’t specify data nor bss section addresses, because the default ones are ok.
Next, I stripped the main symbol, because it will be redefined by main app, and produce the stripped elf file, which I used for the next step.
Next, I’ve compiled the main app, with stripped bootloader elf file, which provides the symbols necessary to link the application. I didn’t specify the text, data, nor bss section addresses, because the default ones are ok – now text points to address 0.
As result, I’ve obtained the application elf file (or hex) which contains only the app code, and references to bootloader code, but don’t contain the bootloader code itself, because it will be preloaded into AVR FLASH memory.
I’ve inspected the resulting map file, and everything seems to be fine, I have to check if static members and virtual methods will be referenced properly.
Have I done everything right?
Thanks again, you are really great.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, I can see that data sections containing static members must be relocated too, otherwise static members are overlaping global and static variables of main app. Or is there any way to make linker to put bootloader object static member first, so app data will be after static and global bootloader data?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, finally I’ve found a solution – not perfect, but working.
I link everything like in description above, but main app has moved data segment beyond addresses occupied by static members and VMT of bootloader classes. It’s a waste of space if not all bootloader classes are used by app code (only if unused classes are virtual or have static data members), but due to limitations of current gcc version I can’t see any other solution.
The only problem is VMT – it must be copied from FLASH into SRAM, because avr-gcc can only use VMT located in SRAM (a known bug, but developers are resistant to fix it). The code which copies VMT is located in startup scripts, so bootloader must be executed first. From bootloader one can start execution of normal app by jumping to address 0 – so app startup scripts are executed too – the copied data is not overlapping because app’s data segment is moved. So bootloader classes VMT and static members are properly initialized, the same app’s code.
So either app and bootloader can use virtual inheritance and static members, in fact it can use global variables, and even more - global and static members can be shared with app code.
Of course one can modify startup code, so __do_copy_data and __do_clear_bss can be called as a subroutine. In that case the bootloader code can be initialized just by calling these two functions.
Any suggestions are welcome.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Filling in the ...'s is left as an exercise for the reader.
Now you know why.
The bootloader and the application must perform their initializations separately.
To that end, shoe.elf must not contain any symbols referenced by start up code.
Any symbols defined by the start up code will also need to be stripped.

Moderation in all things. -- ancient proverb