Linker-Generated Arrays¶
A linker list is constructed by grouping together linker input sections, each containing one entry of the list. Each input section contains a constant initialized variable which holds the entry’s content. Linker list input sections are constructed from the list and entry names, plus a prefix which allows grouping all lists together. Assuming _list and _entry are the list and entry names, then the corresponding input section name is
.u_boot_list_ + 2_ + @_list + _2_ + @_entry
and the C variable name is
_u_boot_list + _2_ + @_list + _2_ + @_entry
This ensures uniqueness for both input section and C variable name.
Note that the names differ only in the first character, “.” for the section and “_” for the variable, so that the linker cannot confuse section and symbol names. From now on, both names will be referred to as
%u_boot_list_ + 2_ + @_list + _2_ + @_entry
Entry variables need never be referred to directly.
The naming scheme for input sections allows grouping all linker lists into a single linker output section and grouping all entries for a single list.
Note the two ‘_2_’ constant components in the names: their presence allows putting a start and end symbols around a list, by mapping these symbols to sections names with components “1” (before) and “3” (after) instead of “2” (within). Start and end symbols for a list can generally be defined as
%u_boot_list_2_ + @_list + _1_...
%u_boot_list_2_ + @_list + _3_...
Start and end symbols for the whole of the linker lists area can be defined as
%u_boot_list_1_...
%u_boot_list_3_...
Here is an example of the sorted sections which result from a list “array” made up of three entries : “first”, “second” and “third”, iterated at least once.
.u_boot_list_2_array_1
.u_boot_list_2_array_2_first
.u_boot_list_2_array_2_second
.u_boot_list_2_array_2_third
.u_boot_list_2_array_3
If lists must be divided into sublists (e.g. for iterating only on part of a list), one can simply give the list a name of the form ‘outer_2_inner’, where ‘outer’ is the global list name and ‘inner’ is the sub-list name. Iterators for the whole list should use the global list name (“outer”); iterators for only a sub-list should use the full sub-list name (“outer_2_inner”).
Here is an example of the sections generated from a global list named “drivers”, two sub-lists named “i2c” and “pci”, and iterators defined for the whole list and each sub-list:
%u_boot_list_2_drivers_1
%u_boot_list_2_drivers_2_i2c_1
%u_boot_list_2_drivers_2_i2c_2_first
%u_boot_list_2_drivers_2_i2c_2_first
%u_boot_list_2_drivers_2_i2c_2_second
%u_boot_list_2_drivers_2_i2c_2_third
%u_boot_list_2_drivers_2_i2c_3
%u_boot_list_2_drivers_2_pci_1
%u_boot_list_2_drivers_2_pci_2_first
%u_boot_list_2_drivers_2_pci_2_second
%u_boot_list_2_drivers_2_pci_2_third
%u_boot_list_2_drivers_2_pci_3
%u_boot_list_2_drivers_3
-
llsym
(_type, _name, _list)¶ Access a linker-generated array entry
Parameters
_type
- Data type of the entry
_name
- Name of the entry
_list
- name of the list. Should contain only characters allowed in a C variable name!
-
ll_entry_declare
(_type, _name, _list)¶ Declare linker-generated array entry
Parameters
_type
- Data type of the entry
_name
- Name of the entry
_list
- name of the list. Should contain only characters allowed in a C variable name!
Description
This macro declares a variable that is placed into a linker-generated array. This is a basic building block for more advanced use of linker- generated arrays. The user is expected to build their own macro wrapper around this one.
A variable declared using this macro must be compile-time initialized.
Special precaution must be made when using this macro:
- The _type must not contain the “static” keyword, otherwise the entry is generated and can be iterated but is listed in the map file and cannot be retrieved by name.
- In case a section is declared that contains some array elements AND a subsection of this section is declared and contains some elements, it is imperative that the elements are of the same type.
- In case an outer section is declared that contains some array elements AND an inner subsection of this section is declared and contains some elements, then when traversing the outer section, even the elements of the inner sections are present in the array.
Example
ll_entry_declare(struct my_sub_cmd, my_sub_cmd, cmd_sub) = {
.x = 3,
.y = 4,
};
-
ll_entry_declare_list
(_type, _name, _list)¶ Declare a list of link-generated array entries
Parameters
_type
- Data type of each entry
_name
- Name of the entry
_list
- name of the list. Should contain only characters allowed in a C variable name!
Description
This is like ll_entry_declare()
but creates multiple entries. It should
be assigned to an array.
ll_entry_declare_list(struct my_sub_cmd, my_sub_cmd, cmd_sub) = {
{ .x = 3, .y = 4 },
{ .x = 8, .y = 2 },
{ .x = 1, .y = 7 }
};
-
ll_entry_start
(_type, _list)¶ Point to first entry of linker-generated array
Parameters
_type
- Data type of the entry
_list
- Name of the list in which this entry is placed
Description
This function returns (_type *)
pointer to the very first entry of a
linker-generated array placed into subsection of .u_boot_list section
specified by _list argument.
Since this macro defines an array start symbol, its leftmost index must be 2 and its rightmost index must be 1.
Example
struct my_sub_cmd *msc = ll_entry_start(struct my_sub_cmd, cmd_sub);
-
ll_entry_end
(_type, _list)¶ Point after last entry of linker-generated array
Parameters
_type
- Data type of the entry
_list
- Name of the list in which this entry is placed (with underscores instead of dots)
Description
This function returns (_type *)
pointer after the very last entry of
a linker-generated array placed into subsection of .u_boot_list
section specified by _list argument.
Since this macro defines an array end symbol, its leftmost index must be 2 and its rightmost index must be 3.
Example
struct my_sub_cmd *msc = ll_entry_end(struct my_sub_cmd, cmd_sub);
-
ll_entry_count
(_type, _list)¶ Return the number of elements in linker-generated array
Parameters
_type
- Data type of the entry
_list
- Name of the list of which the number of elements is computed
Description
This function returns the number of elements of a linker-generated array placed into subsection of .u_boot_list section specified by _list argument. The result is of an unsigned int type.
Example
int i;
const unsigned int count = ll_entry_count(struct my_sub_cmd, cmd_sub);
struct my_sub_cmd *msc = ll_entry_start(struct my_sub_cmd, cmd_sub);
for (i = 0; i < count; i++, msc++)
printf("Entry ``i``, x=``i`` y=``i``\n", i, msc->x, msc->y);
-
ll_entry_get
(_type, _name, _list)¶ Retrieve entry from linker-generated array by name
Parameters
_type
- Data type of the entry
_name
- Name of the entry
_list
- Name of the list in which this entry is placed
Description
This function returns a pointer to a particular entry in linker-generated array identified by the subsection of u_boot_list where the entry resides and it’s name.
Example
ll_entry_declare(struct my_sub_cmd, my_sub_cmd, cmd_sub) = {
.x = 3,
.y = 4,
};
...
struct my_sub_cmd *c = ll_entry_get(struct my_sub_cmd, my_sub_cmd, cmd_sub);
-
ll_start
(_type)¶ Point to first entry of first linker-generated array
Parameters
_type
- Data type of the entry
Description
This function returns (_type *)
pointer to the very first entry of
the very first linker-generated array.
Since this macro defines the start of the linker-generated arrays, its leftmost index must be 1.
Example
struct my_sub_cmd *msc = ll_start(struct my_sub_cmd);
-
ll_end
(_type)¶ Point after last entry of last linker-generated array
Parameters
_type
- Data type of the entry
Description
This function returns (_type *)
pointer after the very last entry of
the very last linker-generated array.
Since this macro defines the end of the linker-generated arrays, its leftmost index must be 3.
Example
struct my_sub_cmd *msc = ll_end(struct my_sub_cmd);