17. Section reference

Compiler-generated code and data objects are organized into sections within the object file. Understanding these sections is crucial for writing linker placement files and interpreting compiler and linker list files.

17.1. Section overview

Code and data objects occupy space in target memory, either as program-bits (actual data written to memory) or no-bits (sections represented only by their size in the ELF object file).

The Calypsi C compiler tool chain has adapted names that trace back to the origins to the early days of computing. These may not always be the best possible names, but they are widely known and familiar to many.

Sections are broadly categorized into three groups: text, data, and bss. Text sections are read-only program-bits. Data sections are read-write program-bits. BSS sections are read-write no-bits.

Note

If you ever wondered about what bss section stands for, it originally is block started by symbol, a pseudo operation in an assembler for IBM 704 from the mid fifties. Some people suggest it is easier to remember as better save space, as it is a way to save space in the output file by just storing the size of the section without any explicit data bits.

Section names

Each section has a name, and multiple section fragments can share the same name. Section names serve two purposes:

  • To provide a descriptive identifier for the section.

  • To control memory placement through rules that reference these names.

Section types

Each section has a type: text, data, or bss. For embedded systems, rodata (read-only data) and no-init sections are also available. Read-only data sections are similar to text sections but identify data rather than executable code. No-init sections resemble bss but lack the memory-clearing mechanism.

Data sections

From the compiler’s perspective, data sections are read-write program-bits sections, meaning they have initializer values that reside in memory. In a hosted environment, such sections are loaded into memory before program execution. This approach is unsuitable for programs stored in flash memory where execution is expected to begin immediately upon power-on.

To address this, the linker clones data sections. The initializers for the original data section are moved and placed in the clone. The clone has a section name with an “i” prepended (e.g., idata for data) and is intended for flash (read-only) memory.

To initialize data sections on power-on, a copy routine is inserted before the main() function. This routine copies initializers from flash to RAM, initializing data memory and clearing bss sections.

The linker generates a data-init_table describing data to be copied and cleared.

Note

For some targets, the Calypsi C compiler tool chain can cross-compile executables for OS loading. The --hosted option prevents data section cloning, avoiding duplication. However, the table-driven initializer is still needed for BSS sections in such environments.

17.2. Sections used by the compiler

The following sections are sections used by the Calypsi C compiler tool chain.

Table 17.1 Sections

Section name

Type

Memory kind

Description

code

text

ROM

Executable code

compactcode

text

ROM

Executable code

farcode

text

ROM

Executable code

ztiny

bss

RAM

Zero initialized (bss) direct page data

tiny

data

RAM

Initialized direct page data

zdata

bss

RAM

Zero initialized (bss) data, default memory, Small data model only

data

data

RAM

Initialized near data, default memory, Small data model only

cdata

rodata

ROM

Constant near data, default memory, Small data model only

znear

bss

RAM

Zero initialized (bss) near data, not available in Small data model

near

data

RAM

Initialized near data, not available in Small data model

cnear

rodata

ROM

Constant near data, not available in Small data model

zfar

bss

RAM

Zero initialized (bss) far data

far

data

RAM

Initialized far data

cfar

rodata

ROM

Constant far data

zhuge

bss

RAM

Zero initialized (bss) huge data

huge

data

RAM

Initialized huge data

chuge

rodata

ROM

Constant huge data

switch

rodata

ROM

Switch tables

itiny

rodata

ROM

Tiny data initializers

idata

rodata

ROM

Data initializers, default memory, Small data model only

inear

rodata

ROM

Near data initializers, not available in Small data model

ifar

rodata

ROM

Far data initializers

ihuge

rodata

ROM

huge data initializers

data_init_table

rodata

ROM

Data initializer table

registers

noinit

RAM

Pseudo registers in direct page

reset

text

ROM

Reset vector, when used

heap

noinit

RAM

Heap memory, for malloc()

stack

noinit

RAM

CPU stack, anywhere in bank 0

The sections itiny, inear, ifar, ihuge and data_init_table in the table above are linker generated.

Note

It is assumed that there is no ROM in direct page. Constants placed in tiny address space are handled in the same way as non-constant data objects in the tiny address space. The only difference is that they have the const attribute in the C type system.

Note

The table assigns sections to ROM and RAM for ROM-based applications that start on power-up. For hosted systems loading from storage to RAM, this distinction is not applicable. Always consider ROM-marked sections as read-only.

The vector section

An interrupt function will have an associated vector. This is a specially named section for the purpose of holding a single vector. The name looks something like $$interruptVector_0xfffe. The intended address of the vector is encoded in the section name and the linker recognizes these and will place the vector at the address specified. This is handled without the help of any section placement rules.

Section reference

The following goes through the available sections in detail.

code

Holds program code, address range 0x0000-0xffff. This section is intended to be placed in a flash or ROM memory.

compactcode

Holds program code, address range 0xNN0000-0xNNffff. Where NN is some bank, typically not 00. This section is intended to be placed in a flash or ROM memory.

farcode

Holds program code, address range 0x000000-0xffffff. This section is intended to be placed in a flash or ROM memory.

zdata

Holds zero initialized (bss) data in the main memory, address range 0x0000-0xffff and is used in the Small data model only.

In the other data models the znear section is used instead.

data

Holds non-zero initialized data intended to go into RAM in the main memory, address range 0x0000-0xffff.

In the other data models the near section is used instead.

idata

Holds initializers for the data section. This section is intended to be placed in a flash or ROM memory and is copied to the data section before the application starts.

When running in a hosted system this section is not used. In that case the initalizer values are part of the data section and data is initialized by loading the application.

In the other data models the inear section is used instead.

cdata

Holds constant data in the main memory, address range 0x0000-0xffff. This section is intended to be placed in a flash or ROM memory.

In the other data models the cnear section is used instead.

znear

Holds zero initialized (bss) data in the main memory, address range 0xNN0000-0xNNffff in one selected 64K bank page where NN is the bank page.

This section is not used in the Small data model, see zdata.

near

Holds non-zero initialized data in the main memory, address range 0xNN0000-0xNNffff in one selected 64K bank page where NN is the bank page.

This section is not used in the Small data model, see data.

inear

Holds initializers for the near section. This section is intended to be placed in a flash or ROM memory and is copied to the near section before the application starts.

When running in a hosted system this section is not used. In that case the initalizer values are part of the near section and data is initialized by loading the application.

This section is not used in the Small data model, see idata.

cnear

Holds constant data in the main memory, address range 0xNN0000-0xNNffff in one selected 64K bank page where NN is the bank page.

This section is not used in the Small data model, see cdata.

ztiny

Holds zero initialized (bss) data in the main memory, address range 0x00-0xff. This 256 bytes is located somewhere in the first 64K of memory.

tiny

Holds non-zero initialized data intended to go into RAM in the direct page memory, address range 0x00-0xff. This 256 bytes is located somewhere in the first 64K of memory.

itiny

Holds initializers for the tiny section. This section is intended to be placed in a flash or ROM memory and is copied to the tiny section before the application starts.

When running in a hosted system this section is not used. In that case the initalizer values are part of the tiny section and data is initialized by loading the application.

zfar

Holds zero initialized (bss) data in the main memory, address range 0x000000-0xffffff.

far

Holds non-zero initialized data intended to go into RAM in the main memory, address range 0x000000-0xffffff.

ifar

Holds initializers for the far section. This section is intended to be placed in a flash or ROM memory and is copied to the far section before the application starts.

When running in a hosted system this section is not used. In that case the initalizer values are part of the far section and data is initialized by loading the application.

cfar

Holds initialized constant data in the main memory, address range 0x000000-0xffffff. This section is intended to be placed in a flash or ROM memory.

zhuge

Holds zero initialized (bss) data in the main memory, address range 0x000000-0xffffff.

huge

Holds non-zero initialized data intended to go into RAM in the main memory, address range 0x000000-0xffffff.

ihuge

Holds initializers for the huge section. This section is intended to be placed in a flash or ROM memory and is copied to the huge section before the application starts.

When running in a hosted system this section is not used. In that case the initalizer values are part of the huge section and data is initialized by loading the application.

chuge

Holds initialized constant data in the main memory, address range 0x000000-0xffffff. This section is intended to be placed in a flash or ROM memory.

switch

Holds switch tables in the main memory, address range 0x0000-0xffff. This section is intended to be placed in a flash or ROM memory. On a hosted system it is normally placed in the same memory as code.

farswitch

Holds switch tables in the main memory, address range 0x000000-0xffffff. This section is intended to be placed in a flash or ROM memory. On a hosted system it is normally placed in the same memory as code.

idata

Holds initializers for the data section. This section is created by the linker by cloning the data section provided by the compiler. This section is placed in the main memory, address range 0x0000-0xffff and needs to be placed in a flash or ROM. This section is not used when linking for a hosted system.

data_init_table

This section is created by the linker and filled in with information to the C startup code on how to copy and clear memory regions to properly initialize the data object before giving control to main(). This section can be placed anywhere in memory, address range 0x000000-0xffffff. As it is a constant table, it can usually go in the same memory as farcode (or code when using the small Code and Data models).