14

I have ran through code that use __attribute__((section("name"))). I understand that for gcc compiler this allows you to tell the linker to put the object created at a specific section "name" (with "name" absolute address declared in a linker file).

What is the point of doing this instead of just using the .data section?

Daniel Walker
  • 6,380
  • 5
  • 22
  • 45
tll
  • 377
  • 1
  • 3
  • 12
  • It's because that's the platform of the code I'm working on. I am aware of the fact that this ____attribute____ is only available on certain platform so I wanted to include it for clarity. I'm trying to understand what the coder's intention is when he sectioned out certain objects into test objects, tracing objects etc. – tll Aug 21 '13 at 17:22
  • I removed the ARM section so it's clearer that I am not concerned about ARM specifically, just the usage. – tll Aug 22 '13 at 17:29

4 Answers4

13

There are many possible uses. [Edit to add note: this is just a sample of uses I've seen myself or considered, not a complete list.]

The Linux kernel, for instance, marks some code and data sections as used only during kernel bootstrap. These can be jettisoned after the kernel is running, reclaiming the space for other uses.

You can use this to mark code or data values that need patching on a particular processor variant, e.g., with or without a coprocessor.

You can use it to make things live in "special" address spaces that will be burned to PROM or saved on an EEPROM, rather than in ordinary memory.

You can use it to collect together code or data areas for purposes like initialization and cleanup, as with C++ constructors and destructors that run before the program starts and when it ends, or for using shorter addressing modes (I don't know how much that would apply on ARM as I have not written any ARM code myself).

The actual use depends on the linker script(s).

torek
  • 448,244
  • 59
  • 642
  • 775
  • Other uses are **hot** and **cold** for *cache locality*. You may also partition functionality, like interrupt handling, scheduling, etc. Even though routine/functionality may be in one 'C' file, the typical execution path can benefit by grouping *call stacks*. Some code may execute from *flash* or *internal ram*. These resource maybe limited, etc. – artless noise Aug 21 '13 at 03:39
  • @torek On your last point about collecting code/data areas for initialization/cleanup, this essentially means that I can choose to include code before the program starts, but during runtime instead of compile time? Sort of like a better version of #ifdef? – tll Aug 21 '13 at 17:28
  • I'm not sure precisely what you're asking here. If you wrote a linker script that included some sections and discarded others, you could include or exclude pieces at *link* time. Doing stuff at *run* time requires co-ordinating your linker script and your run-time code, and is much harder. – torek Aug 21 '13 at 17:31
  • That was a bad question on me. I understand it now when you say this is done during _link_ time. Thank you. – tll Aug 22 '13 at 17:36
3

From a usecase point of view, there are lots of different types of .data, like:

  • data local to a specific CPU and/or NUMA node
  • data shared between contexts (like user/kernelspace, as are the .vdso or vsyscall pages. Or, another example, bootloader and kernel)
  • readonly data or other data with specific access mode/type restrictions (say, cacheability or cache residency - the latter can be specificed on some ARM SoCs)
  • data that persists "state transitions" (such as hibernation image loads, or crash kernel / fast reboot reinitializations)
  • data with specific lifetimes/lifecycles (only used in specific stages during boot or during operation, write-once data)
  • data specific to a particular kernel subsystem or particular kernel module
  • "code colocated" data (addressing offsets in x64 are plus/minus 2GB so if you want RIP-relative addressing, the data must be within that range of your currently executing code)
  • data mapped to some specific hardware register space VA range

So in the end it's often about attributes (the word here used in a more generic sense than what __attribute__(...) allows you to state from within gcc sourcecode. Whether another section is needed and/or useful is ... in the eye of the beholder - the system designer, that is.

The availabiltiy of the section attribute, therefore, allows for flexibility and that is, IMHO, a good thing.

FrankH.
  • 17,675
  • 3
  • 44
  • 63
2

Years later, I'm going to add a specific detail because it's worth writing down.

If you create your own section, you can manage it yourself. In particular, you can use preprocessor macros to insert certain data items into your special section. If the only thing that uses that special section is your preprocessor macros, then you have the ability to create a data structure in a distributed fashion.

What does this mean? It means you can write a preprocessor macro like ADD_VAR_TO_SPECIAL_SECTION(...) and concatenate a bunch of different values in random order into what amounts to an array (or just a big old pile, if they aren't all the same type) in your section.

This gives you the ability to create a (randomly-ordered) array of data at compile time. There is no initialization, no registration, no overhead. You just compile and link your code, and all the macros that were in all the different source files have added all their values into one big array.

How can you use this? Create a bunch of "modules." Register the init functions and destroy functions in an ad-hoc array. Process the array at startup time. (You can add some kind of topological sort if you need to.) You don't need to have a master list of modules anywhere, it gets built automatically. Or, create a macro to register unit test functions into a test suite. Again, it creates an ad-hoc list with no "registration" required.

aghast
  • 14,785
  • 3
  • 24
  • 56
  • Nice one. A real-life example of this is the `AT_NONCACHEABLE_SECTION(...)` macro defined in the device drivers for i.MXRT processors by NXP: https://github.com/ARMmbed/mbed-os/blob/master/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/drivers/fsl_common.h. – Ed Graham Feb 03 '23 at 11:41
0

On embedded hardware/micro controllers it is used to read and write data to the flash memory.

This is useful for:

  1. Persistent data even on power cycles.
  2. Overwrite the program in flash and do firmware updates.
  3. Make a read-only data storage.

Here some examples on SO for STM32:

Darkproduct
  • 1,062
  • 13
  • 28