The API is defined in the header file sysroot-*-kos/include/kos/iterable_section.h from the KasperskyOS SDK.
The API lets you put data into specialized loadable ELF image sections while building a program and gain access to this data during execution of the program. A specialized section is an array of single-type data objects, and therefore you can assume that a specialized section has a type that matches the type of data objects comprising the section. The API creates specialized sections of the required types when building a program. During execution of the program, the API provides the capability to get the number of data objects in these sections, gain access to each object based on the index, and traverse objects. It is advisable to utilize this functionality if the program may be built in multiple versions that optionally enable one or more components, such as drivers. In this case, each driver uses the API to add a data object to a specialized ELF image section. For example, this data object may be a structure containing pointers to driver initialization and finalization functions. As a result, the program build process will also create a specialized ELF image section consisting of an array of structures containing pointers to initialization and finalization functions for all drivers included in the program. During execution of the program, the API will let you initialize and finalize all drivers included in the program while traversing the data objects of this section. Building a program with a different set of drivers automatically updates this section, and the code that invokes the driver initialization and finalization functions will not require modification.
Information about API macros is provided in the table below.
Adding a data object to a specialized ELF image section
To add a data object to a specialized ELF image section, use the KOS_ITERABLE_SECTION_REGISTER() macro. This macro adds a data object to the specialized section of the specific type whose name is specified in the type parameter. The name of a specialized section type must consist of one word. To define a type whose name consists of multiple words (for example, unsigned long, const volatile double), in the type parameter, you must specify an alias of this type that is created using typedef. You can define a primitive type or a composite type.
A data object added to a specialized section normally must be initialized. This is technically not required, because you can add uninitialized data objects to the specialized section so that they can later be used together with other global variables or for the purpose of getting the number of data objects in this specialized section. However, this is not the main purpose of the API. The main purpose of the API is to put data into specialized sections when building a program and then gain access to this data during execution of the program.
Example of adding an initialized data object to a specialized section:
typedef struct SFooClientOps
{
Retcode (*init)(void);
void (*fini)(void);
} FooClientOps;
typedef struct SFooClient
{
const FooClientOps *ops;
} FooClient;
static Retcode InitClient(void)
{
...
}
static void FiniClient(void)
{
...
}
static const FooClientOps ops = {
.init = InitClient,
.fini = FiniClient,
};
KOS_ITERABLE_SECTION_REGISTER(FooClient) = {
.ops = &ops
};
If a translation unit in which the KOS_ITERABLE_SECTION_REGISTER() macro is used will be included in the program during the build, the data object will be added to the specialized section. If the required program version will not include this translation unit, the data object will not be added to the specialized section. This automatically ensures that the contents of the specialized section will comply with the required program version.
In the source code file, the KOS_ITERABLE_SECTION_REGISTER() macro must be put into the global scope.
Opening access to a specialized ELF image section
To open access to a specialized ELF image section, use the KOS_ITERABLE_SECTION_DECLARE() macro. This macro opens access to the specialized section of the specific type whose name is specified in the type parameter. Opening access to a specialized section provides the capability to get the number of data objects in this specialized section, gain access to each object based on the index, and traverse objects.
The KOS_ITERABLE_SECTION_DECLARE() macro must be used in each translation unit in which you need to gain access to the specialized section.
In the source code file, the KOS_ITERABLE_SECTION_DECLARE() macro must be put into the global scope.
Getting the number of data objects in a specialized ELF image section
To get the number of data objects in the specialized ELF image section, use the KOS_ITERABLE_SECTION_COUNTOF() macro. This macro has a value that corresponds to the number of data objects in the specialized section of the specific type whose name is specified in the type parameter.
In the source code file, the definitions of functions that use the KOS_ITERABLE_SECTION_COUNTOF() macro must be positioned after the KOS_ITERABLE_SECTION_DECLARE() macro.
Enumerating data objects in a specialized ELF image section
To enumerate data objects in a specialized ELF image section, use the KOS_ITERABLE_SECTION_ENUM() macro. This macro enumerates data objects in a specialized section of the specific type whose name is specified in the type parameter. It has a value corresponding to the pointer to the data object with the index specified in the index parameter.
In the source code file, the definitions of functions that use the KOS_ITERABLE_SECTION_ENUM() macro must be positioned after the KOS_ITERABLE_SECTION_DECLARE() macro.
Traversing data objects in a specialized ELF image section
To traverse data objects in a specialized ELF image section, use the KOS_ITERABLE_SECTION_FOR_EACH() or KOS_ITERABLE_SECTION_FOR_EACH_REVERSE() macro. These macros traverse data objects in a specialized section of the specific type whose name is specified in the type parameter. The KOS_ITERABLE_SECTION_FOR_EACH() macro traverses objects in forward order while the KOS_ITERABLE_SECTION_FOR_EACH_REVERSE() macro traverses objects in reverse order. Both macros are expanded into the header of the for operator. The pointer whose name is defined in the iterator parameter will contain the address of the next data object in each iteration.
Example use of the KOS_ITERABLE_SECTION_FOR_EACH() macro:
static Retcode InitDrivers(void)
{
Retcode rc = rcOk;
KOS_ITERABLE_SECTION_FOR_EACH(ExampleDriverClassDriverImpl, driver)
{
rtl_assert(driver->name != RTL_NULL);
rtl_assert(driver->init != RTL_NULL);
rtl_assert(!driver->isInitialized);
rc = driver->init();
if (rc == rcOk)
{
driver->isInitialized = rtl_true;
}
else
{
ERROR(EXAMPLE_CLASS, "Failed to initialize \"%s\" driver", driver->name);
break;
}
}
if (rc != rcOk)
{
FiniDrivers();
}
return rc;
}
Example use of the KOS_ITERABLE_SECTION_FOR_EACH_REVERSE() macro:
static Retcode FiniDrivers(void)
{
KOS_ITERABLE_SECTION_FOR_EACH_REVERSE(ExampleDriverClassDriverImpl, driver)
{
if (driver->isInitialized && driver->fini != RTL_NULL)
{
driver->fini();
driver->isInitialized = rtl_false;
}
}
return rcOk;
}
In the source code file, the definitions of functions that use the KOS_ITERABLE_SECTION_FOR_EACH() and KOS_ITERABLE_SECTION_FOR_EACH_REVERSE() macros must be positioned after the KOS_ITERABLE_SECTION_DECLARE() macro.
Information about API macros
iterable_section.h macros
Macro |
Macro details |
|---|---|
|
Purpose Adds a data object to a specialized section of the defined type. Parameters
Macro values N/A |
|
Purpose Opens access to a specialized section of the defined type. Parameters
Macro values N/A |
|
Purpose Gets the number of data objects in a specialized section of the defined type. Parameters
Macro values Number of data objects in a specialized section of the defined type. |
|
Purpose Enumerates data objects in a specialized section of the defined type. Parameters
Macro values Pointer to the data object in the specialized section of the defined type, or |
|
Purpose Traverses data objects in a specialized section of the defined type in forward order. Parameters
Macro values N/A |
|
Purpose Traverses data objects in a specialized section of the defined type in reverse order. Parameters
Macro values N/A |