Implement support for module symbols (#475)
* **New Features** - Adds module symbol support and per-module symbol tables, including LVGL symbol exports moved into a dedicated table. * **API** - Adds symbol-resolution APIs and an accessor to enable dynamic lookup between modules. * **Bug Fixes / Chores** - Explicitly initializes module symbol pointers across device and platform modules to avoid uninitialized state. * **Tests** - Updates tests to account for symbol pointer initialization.
This commit is contained in:
committed by
GitHub
parent
9f721e6655
commit
1f9e7f82fd
@@ -1,16 +1,28 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#pragma once
|
||||
|
||||
#include "error.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "error.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
struct ModuleParent;
|
||||
struct ModuleParentPrivate;
|
||||
|
||||
#define MODULE_SYMBOL_TERMINATOR { NULL, NULL }
|
||||
#define DEFINE_MODULE_SYMBOL(symbol) { #symbol, (void*)&symbol }
|
||||
|
||||
/** A binary symbol like a function or a variable. */
|
||||
struct ModuleSymbol {
|
||||
/** The name of the symbol. */
|
||||
const char* name;
|
||||
/** The address of the symbol. */
|
||||
const void* symbol;
|
||||
};
|
||||
|
||||
/**
|
||||
* A module is a collection of drivers or other functionality that can be loaded and unloaded at runtime.
|
||||
*/
|
||||
@@ -38,6 +50,13 @@ struct Module {
|
||||
*/
|
||||
error_t (*stop)(void);
|
||||
|
||||
/**
|
||||
* A list of symbols exported by the module.
|
||||
* Should be terminated by MODULE_SYMBOL_TERMINATOR.
|
||||
* Can be a NULL value.
|
||||
*/
|
||||
const struct ModuleSymbol* symbols;
|
||||
|
||||
struct {
|
||||
bool started;
|
||||
struct ModuleParent* parent;
|
||||
@@ -69,6 +88,16 @@ error_t module_parent_construct(struct ModuleParent* parent);
|
||||
*/
|
||||
error_t module_parent_destruct(struct ModuleParent* parent);
|
||||
|
||||
/**
|
||||
* @brief Resolve a symbol from the module parent.
|
||||
* @details This function iterates through all started modules in the parent and attempts to resolve the symbol.
|
||||
* @param parent parent module
|
||||
* @param symbol_name name of the symbol to resolve
|
||||
* @param symbol_address pointer to store the address of the resolved symbol
|
||||
* @return true if the symbol was found, false otherwise
|
||||
*/
|
||||
bool module_parent_resolve_symbol(struct ModuleParent* parent, const char* symbol_name, uintptr_t* symbol_address);
|
||||
|
||||
/**
|
||||
* @brief Set the parent of the module.
|
||||
* @warning must call before module_start()
|
||||
@@ -99,6 +128,16 @@ bool module_is_started(struct Module* module);
|
||||
*/
|
||||
error_t module_stop(struct Module* module);
|
||||
|
||||
/**
|
||||
* @brief Resolve a symbol from the module.
|
||||
* @details The module must be started for symbol resolution to succeed.
|
||||
* @param module module
|
||||
* @param symbol_name name of the symbol to resolve
|
||||
* @param symbol_address pointer to store the address of the resolved symbol
|
||||
* @return true if the symbol was found and the module is started, false otherwise
|
||||
*/
|
||||
bool module_resolve_symbol(struct Module* module, const char* symbol_name, uintptr_t* symbol_address);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <vector>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <tactility/concurrent/mutex.h>
|
||||
#include <tactility/module.h>
|
||||
@@ -41,6 +42,21 @@ error_t module_parent_destruct(struct ModuleParent* parent) {
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
bool module_parent_resolve_symbol(ModuleParent* parent, const char* symbol_name, uintptr_t* symbol_address) {
|
||||
auto* data = static_cast<ModuleParentPrivate*>(parent->module_parent_private);
|
||||
mutex_lock(&data->mutex);
|
||||
for (auto* module : data->modules) {
|
||||
if (!module_is_started(module))
|
||||
continue;
|
||||
if (module_resolve_symbol(module, symbol_name, symbol_address)) {
|
||||
mutex_unlock(&data->mutex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&data->mutex);
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region module
|
||||
@@ -102,6 +118,20 @@ error_t module_stop(struct Module* module) {
|
||||
return error;
|
||||
}
|
||||
|
||||
bool module_resolve_symbol(Module* module, const char* symbol_name, uintptr_t* symbol_address) {
|
||||
if (!module_is_started(module)) return false;
|
||||
auto* symbol_ptr = module->symbols;
|
||||
if (symbol_ptr == nullptr) return false;
|
||||
while (symbol_ptr->name != nullptr) {
|
||||
if (strcmp(symbol_ptr->name, symbol_name) == 0) {
|
||||
*symbol_address = reinterpret_cast<uintptr_t>(symbol_ptr->symbol);
|
||||
return true;
|
||||
}
|
||||
symbol_ptr++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user