Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion components/libc/posix/libdl/arch/arm.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
Expand Down
2 changes: 1 addition & 1 deletion components/libc/posix/libdl/arch/riscv.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
Expand Down
2 changes: 1 addition & 1 deletion components/libc/posix/libdl/arch/x86.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
Expand Down
11 changes: 10 additions & 1 deletion components/libc/posix/libdl/dlclose.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
Expand All @@ -13,6 +13,15 @@

#include "dlmodule.h"

/**
* @brief close a dynamically loaded shared library.
*
* @param handle the handle which identifies the shared library to be closed.
* @return int it returns RT_TRUE on success.
*
* @note This function is an API of POSIX standard, which is designed to decrease the reference count (nref) for a dynamically loaded module
* and destroy it if no references remain.
*/
int dlclose(void *handle)
{
struct rt_dlmodule *module;
Expand Down
45 changes: 43 additions & 2 deletions components/libc/posix/libdl/dlelf.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
Expand All @@ -14,8 +14,32 @@

#define DBG_TAG "DLMD"
#define DBG_LVL DBG_INFO
#include <rtdbg.h> // must after of DEBUG_ENABLE or some other options
#include <rtdbg.h> /* must after of DEBUG_ENABLE or some other options*/

/**
* @brief Load a shared object file into memory.
*
* @param module A pointer to a rt_dlmodule object for holding the module's information.
* @param module_ptr A pointer to the raw memory of the ELF file (shared object) that is being loaded.
* @return rt_err_t On success, it returns RT_EOK. Otherwise, it returns the error code.
*
* @note This function loads a shared object (ELF file) into memory, broken down into steps:
* 1. Initialization and Validation: it begins by validating the module pointer
* and checking if the ELF file has been linked by comparing its magic number (RTMMAG).
* If matched, the module is considered linked.
* 2. Calculating the ELF Image Size: it iterates over the ELF program headers to compute the total size of the ELF image
* by adding the sizes of loadable segments. It also ensures there are no overlaps or invalid addresses in the segments.
* 3. Allocating Memory for the Module: After determining the module size, the function allocates memory (module->mem_space) for the ELF image
* and initializes it to zero. Then, it copies the relevant program segments from the ELF file into this allocated memory.
* 4. Setting the Module Entry Point: it sets the entry point address (module->entry_addr) based on the ELF entry point adjusted by the calculated base address.
* 5. Handling Relocation Sections: It processes each relocation section in the ELF file.
* For each relocation entry, it either resolves the symbol from the module's own symbol table
* or looks up the symbol in the kernel symbol table if it was not found locally.
* 6. Building the Module's Symbol Table: it looks for the .dynsym section to extract global function symbols.
* It creates a symbol table (module->symtab) and populates it with the function names and addresses for all global symbols of type STT_FUNC.
* 7. Extracting Additional Parameters: It extracts additional parameters, such as thread priority (dlmodule_thread_priority) and stack size (dlmodule_thread_stacksize),
* from the symbol table and assigns them to the module if valid.
*/
rt_err_t dlmodule_load_shared_object(struct rt_dlmodule* module, void *module_ptr)
{
rt_bool_t linked = RT_FALSE;
Expand Down Expand Up @@ -273,6 +297,23 @@ rt_err_t dlmodule_load_shared_object(struct rt_dlmodule* module, void *module_pt
return RT_EOK;
}

/**
* @brief Load a relocatable file into memory.
*
* @param module A pointer to a rt_dlmodule object for holding the module's information.
* @param module_ptr A pointer to the raw memory of the ELF file (relocatable file) that is being loaded.
* @return rt_err_t On success, it returns RT_EOK. Otherwise, it returns the error code.
*
* @note This function loads a relocatable file (ELF file) into memory, broken down step by step:
* 1. Calculate Module Size: iterates over the ELF sections (text, data, rodata, and bss) to calculate the total size of the module
* and identifies the start address for each section.
* 2. Allocate Memory: It allocates memory for the module based on the calculated size. If allocation fails, an error is returned.
* 3. Load Sections into Memory: The function loads the text, rodata, data, and BSS sections into the allocated memory.
* The BSS section is zeroed out, while the others are copied from the ELF image.
* 4. Set Entry Point: The entry point of the module is set by calculating the address relative to the start of the allocated memory.
* 5. Handle Relocation: It processes the relocation entries, resolving symbol addresses and relocating them as needed.
* This includes functions, sections (rodata, bss, data), and external symbols from the kernel symbol table.
*/
rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module_ptr)
{
rt_ubase_t index, rodata_addr = 0, bss_addr = 0, data_addr = 0;
Expand Down
2 changes: 1 addition & 1 deletion components/libc/posix/libdl/dlelf.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
Expand Down
9 changes: 8 additions & 1 deletion components/libc/posix/libdl/dlerror.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
Expand All @@ -11,6 +11,13 @@
#include <rtthread.h>
#include <rtm.h>

/**
* @brief retrieve a string describing the last error that occurred from a dynamic linking operation.
*
* @return const char* a string containing an error message describing the last error.
*
* @note This function is an API of POSIX standard, which is still remaining TBD.
*/
const char *dlerror(void)
{
return "TODO";
Expand Down
2 changes: 1 addition & 1 deletion components/libc/posix/libdl/dlfcn.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
Expand Down
62 changes: 59 additions & 3 deletions components/libc/posix/libdl/dlmodule.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
Expand All @@ -24,7 +24,7 @@

#define DBG_TAG "DLMD"
#define DBG_LVL DBG_INFO
#include <rtdbg.h> // must after of DEBUG_ENABLE or some other options
#include <rtdbg.h> /* must after of DEBUG_ENABLE or some other options*/

static struct rt_module_symtab *_rt_module_symtab_begin = RT_NULL;
static struct rt_module_symtab *_rt_module_symtab_end = RT_NULL;
Expand Down Expand Up @@ -176,6 +176,11 @@ static void _dlmodule_thread_entry(void* parameter)
return ;
}

/**
* @brief create a dynamic module object and initialize it.
*
* @return struct rt_dlmodule* If module create successfully, return the pointer to its rt_dlmodule structure.
*/
struct rt_dlmodule *dlmodule_create(void)
{
struct rt_dlmodule *module = RT_NULL;
Expand Down Expand Up @@ -233,6 +238,12 @@ void dlmodule_destroy_subthread(struct rt_dlmodule *module, rt_thread_t thread)
#endif
}

/**
* @brief destroy dynamic module and cleanup all kernel objects inside it.
*
* @param module Pointer to the module to be destroyed.
* @return rt_err_t On success, it returns RT_EOK. Otherwise, it returns the error code.
*/
rt_err_t dlmodule_destroy(struct rt_dlmodule* module)
{
int i;
Expand All @@ -255,7 +266,7 @@ rt_err_t dlmodule_destroy(struct rt_dlmodule* module)
rt_exit_critical();
}

// list_object(&(module->object_list));
/* list_object(&(module->object_list));*/

/* cleanup for all kernel objects inside module*/
{
Expand Down Expand Up @@ -393,6 +404,11 @@ rt_err_t dlmodule_destroy(struct rt_dlmodule* module)
return RT_EOK;
}

/**
* @brief retrieve the dynamically loaded module that the current thread belongs to.
*
* @return struct rt_dlmodule* On success, it returns a pointer to the module. otherwise, it returns RT_NULL.
*/
struct rt_dlmodule *dlmodule_self(void)
{
rt_thread_t tid;
Expand All @@ -415,6 +431,20 @@ struct rt_dlmodule *rt_module_self(void)
return dlmodule_self();
}

/**
* @brief load an ELF module to memory.
*
* @param filename the path to the module to load.
* @return struct rt_dlmodule* On success, it returns a pointer to the module object. otherwise, RT_NULL is returned.
*
* @note the function is used to load an ELF (Executable and Linkable Format) module from a file, validate it,
* and initialize it as a dynamically loaded module. what it implements are as follows:
* 1. Load and Validate ELF: It loads an ELF file, checks its validity, and identifies it as either a relocatable or shared object.
* 2. Memory Allocation and Cleanup: Uses rt_malloc and rt_free to allocate and free memory for module data.
* Error handling ensures all resources are released if an error occurs.
* 3. Symbol Resolution and Initialization: Sets up init function and cleanup function, and calls the module_init function if it is present.
* 4. Cache Management: Optionally (when RT_USING_CACHE defined) flushes data and invalidates instruction caches to ensure the module is correctly loaded into memory.
*/
struct rt_dlmodule* dlmodule_load(const char* filename)
{
#ifdef RT_USING_POSIX_FS
Expand Down Expand Up @@ -525,6 +555,14 @@ struct rt_dlmodule* dlmodule_load(const char* filename)
return RT_NULL;
}

/**
* @brief load a dynamic module, and create a thread to excute the module main function.
*
* @param pgname path of the module to be loaded.
* @param cmd the command string (with commandline options) for startup module.
* @param cmd_size the command's length.
* @return struct rt_dlmodule* On success, it returns a pointer to the module object. otherwise, RT_NULL is returned.
*/
struct rt_dlmodule* dlmodule_exec(const char* pgname, const char* cmd, int cmd_size)
{
struct rt_dlmodule *module = RT_NULL;
Expand Down Expand Up @@ -742,6 +780,17 @@ struct rt_dlmodule* dlmodule_exec_custom(const char* pgname, const char* cmd, in
}
#endif

/**
* @brief exit a dynamically loaded module.
*
* @param ret_code the return code for module exit.
*
* @note this function is responsible for gracefully exiting a dynamically loaded module, releasing resources associated with the module,
* and handling cleanup operations. what it implements are as follows:
* 1. Thread and Resource Cleanup: The function safely exits a module by deleting its main thread and freeing resources associated with it.
* 2. Status Management: Checks and updates the module's state, setting a return code and calling _dlmodule_exit() to transition to a closing state.
* 3. Critical Sections: Critical sections ensure that the exit process is atomic and free from race conditions.
*/
void dlmodule_exit(int ret_code)
{
rt_thread_t thread;
Expand Down Expand Up @@ -784,6 +833,13 @@ void dlmodule_exit(int ret_code)
rt_exit_critical();
}

/**
* @brief search for a symbol by its name in the kernel symbol table.
*
* @param sym_str the symbol name string.
* @return rt_uint32_t On success, it returns the address of the symbol.
* Otherwise, it returns 0 (indicating the symbol was not found).
*/
rt_uint32_t dlmodule_symbol_find(const char *sym_str)
{
/* find in kernel symbol table */
Expand Down
2 changes: 1 addition & 1 deletion components/libc/posix/libdl/dlmodule.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
Expand Down
15 changes: 14 additions & 1 deletion components/libc/posix/libdl/dlopen.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
Expand All @@ -16,6 +16,19 @@

#define MODULE_ROOT_DIR "/modules"

/**
* @brief dynamically load a shared library at runtime.
*
* @param filename the path to the shared library to load, which shouldn't be set to NULL.
* @param flags options for loading the shared library.
* @return void* on success, it returns a handle (a pointer) to the opened shared library, otherwise it returns NULL.
*
* @note This function is an API of POSIX standard, which is used for dynamically loading shared libraries at runtime.
* the function first tries to check if the module is already loaded, by finding module in module list.
* If module is found in memory (RT_NULL check fails), the reference count (nref) is incremented.
* Otherwise, dlmodule_load() will be called to load the module into memory.
* A handle (a pointer to the module) is returned at last, which can be used with other functions like dlsym().
*/
void* dlopen(const char *filename, int flags)
{
struct rt_dlmodule *module;
Expand Down
13 changes: 12 additions & 1 deletion components/libc/posix/libdl/dlsym.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
Expand All @@ -13,6 +13,17 @@

#include "dlmodule.h"

/**
* @brief look up the address of a symbol in a dynamically loaded shared library.
*
* @param handle the handle returned by dlopen() when the library was previously loaded.
* @param symbol A string containing the name of the symbol to locate.
* @return void* On success, it returns a pointer to the symbol. Otherwise, it returns RT_NULL.
*
* @note This function is an API of POSIX standard, which is commonly used in conjunction with dlopen() to retrieve function pointers from shared libraries.
* the input symbol name, which can be the name of a function or variable, is compared with each symbol
* in the module symbol table. if the same symbol is found, return its address.
*/
void* dlsym(void *handle, const char* symbol)
{
int i;
Expand Down
2 changes: 1 addition & 1 deletion components/libc/posix/libdl/dlsyms.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
Expand Down