From f0934630c46a3111cf06ab2777e368fc04050292 Mon Sep 17 00:00:00 2001 From: ligr Date: Tue, 12 Nov 2024 15:38:28 +0800 Subject: [PATCH] [libc] add comments for libdl APIs. --- components/libc/posix/libdl/arch/arm.c | 2 +- components/libc/posix/libdl/arch/riscv.c | 2 +- components/libc/posix/libdl/arch/x86.c | 2 +- components/libc/posix/libdl/dlclose.c | 11 ++++- components/libc/posix/libdl/dlelf.c | 45 ++++++++++++++++- components/libc/posix/libdl/dlelf.h | 2 +- components/libc/posix/libdl/dlerror.c | 9 +++- components/libc/posix/libdl/dlfcn.h | 2 +- components/libc/posix/libdl/dlmodule.c | 62 ++++++++++++++++++++++-- components/libc/posix/libdl/dlmodule.h | 2 +- components/libc/posix/libdl/dlopen.c | 15 +++++- components/libc/posix/libdl/dlsym.c | 13 ++++- components/libc/posix/libdl/dlsyms.c | 2 +- 13 files changed, 153 insertions(+), 16 deletions(-) diff --git a/components/libc/posix/libdl/arch/arm.c b/components/libc/posix/libdl/arch/arm.c index 2996f2e3c74..7914df28e7d 100644 --- a/components/libc/posix/libdl/arch/arm.c +++ b/components/libc/posix/libdl/arch/arm.c @@ -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 * diff --git a/components/libc/posix/libdl/arch/riscv.c b/components/libc/posix/libdl/arch/riscv.c index 8dd09789c51..13a4edac3ef 100644 --- a/components/libc/posix/libdl/arch/riscv.c +++ b/components/libc/posix/libdl/arch/riscv.c @@ -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 * diff --git a/components/libc/posix/libdl/arch/x86.c b/components/libc/posix/libdl/arch/x86.c index 1987d45508a..7d5914687c2 100644 --- a/components/libc/posix/libdl/arch/x86.c +++ b/components/libc/posix/libdl/arch/x86.c @@ -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 * diff --git a/components/libc/posix/libdl/dlclose.c b/components/libc/posix/libdl/dlclose.c index 876a1576c8d..87638924fa5 100644 --- a/components/libc/posix/libdl/dlclose.c +++ b/components/libc/posix/libdl/dlclose.c @@ -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 * @@ -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; diff --git a/components/libc/posix/libdl/dlelf.c b/components/libc/posix/libdl/dlelf.c index 418ad7539aa..9e8f1c6b2d4 100644 --- a/components/libc/posix/libdl/dlelf.c +++ b/components/libc/posix/libdl/dlelf.c @@ -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 * @@ -14,8 +14,32 @@ #define DBG_TAG "DLMD" #define DBG_LVL DBG_INFO -#include // must after of DEBUG_ENABLE or some other options +#include /* 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; @@ -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; diff --git a/components/libc/posix/libdl/dlelf.h b/components/libc/posix/libdl/dlelf.h index 339e172bb46..6b03271034f 100644 --- a/components/libc/posix/libdl/dlelf.h +++ b/components/libc/posix/libdl/dlelf.h @@ -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 * diff --git a/components/libc/posix/libdl/dlerror.c b/components/libc/posix/libdl/dlerror.c index de948eb16be..7c5ce4593f8 100644 --- a/components/libc/posix/libdl/dlerror.c +++ b/components/libc/posix/libdl/dlerror.c @@ -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 * @@ -11,6 +11,13 @@ #include #include +/** + * @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"; diff --git a/components/libc/posix/libdl/dlfcn.h b/components/libc/posix/libdl/dlfcn.h index f5c9063f2fd..7cbbc7d7701 100644 --- a/components/libc/posix/libdl/dlfcn.h +++ b/components/libc/posix/libdl/dlfcn.h @@ -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 * diff --git a/components/libc/posix/libdl/dlmodule.c b/components/libc/posix/libdl/dlmodule.c index 0d05190f7f5..269e7bc4333 100644 --- a/components/libc/posix/libdl/dlmodule.c +++ b/components/libc/posix/libdl/dlmodule.c @@ -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 * @@ -24,7 +24,7 @@ #define DBG_TAG "DLMD" #define DBG_LVL DBG_INFO -#include // must after of DEBUG_ENABLE or some other options +#include /* 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; @@ -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; @@ -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; @@ -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*/ { @@ -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; @@ -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 @@ -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; @@ -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; @@ -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 */ diff --git a/components/libc/posix/libdl/dlmodule.h b/components/libc/posix/libdl/dlmodule.h index 183faca159e..62a0cdd5d3b 100644 --- a/components/libc/posix/libdl/dlmodule.h +++ b/components/libc/posix/libdl/dlmodule.h @@ -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 * diff --git a/components/libc/posix/libdl/dlopen.c b/components/libc/posix/libdl/dlopen.c index bcb57d78f05..8545bce1180 100644 --- a/components/libc/posix/libdl/dlopen.c +++ b/components/libc/posix/libdl/dlopen.c @@ -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 * @@ -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; diff --git a/components/libc/posix/libdl/dlsym.c b/components/libc/posix/libdl/dlsym.c index f7c1c901fdd..372cec6ab86 100644 --- a/components/libc/posix/libdl/dlsym.c +++ b/components/libc/posix/libdl/dlsym.c @@ -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 * @@ -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; diff --git a/components/libc/posix/libdl/dlsyms.c b/components/libc/posix/libdl/dlsyms.c index e6ca23b393b..8476b10bb14 100644 --- a/components/libc/posix/libdl/dlsyms.c +++ b/components/libc/posix/libdl/dlsyms.c @@ -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 *