Skip to content

Commit 8a99de1

Browse files
CopilotBernardXiong
andcommitted
[libc][libdl] Fix dlopen() failing to find already-loaded modules
Fix name mismatch between dlmodule_find() and _dlmodule_set_name() that caused dlopen() to always reload modules instead of reusing them: 1. In dlopen(): Extract module name from full path before calling dlmodule_find(), matching the stripped name stored by _dlmodule_set_name(). This allows dlopen() to properly find and reuse already-loaded modules. 2. In _dlmodule_set_name(): Fix bug where extension detection searched the entire path instead of just the filename portion. For paths like "/mnt/v1.2/app.so", it would incorrectly find "." in "v1.2" directory name instead of the ".so" extension. Fixes: Module reloading on every dlopen() call, memory leaks from duplicate module instances, and dlclose() cleanup issues. Co-authored-by: BernardXiong <1241087+BernardXiong@users.noreply.github.com>
1 parent ec3b2a2 commit 8a99de1

2 files changed

Lines changed: 64 additions & 11 deletions

File tree

components/libc/posix/libdl/dlmodule.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,29 @@ static void _dlmodule_set_name(struct rt_dlmodule *module, const char *path)
4444
ptr = first = (char *)path;
4545
end = path + rt_strlen(path);
4646

47+
/* find the start of filename (after last '/') */
4748
while (*ptr != '\0')
4849
{
4950
if (*ptr == '/')
5051
first = ptr + 1;
51-
if (*ptr == '.')
52-
end = ptr - 1;
52+
ptr++;
53+
}
5354

54-
ptr ++;
55+
/* find extension in filename portion only (after last '/') */
56+
ptr = first;
57+
while (*ptr != '\0')
58+
{
59+
if (*ptr == '.')
60+
end = ptr;
61+
ptr++;
5562
}
5663

57-
size = end - first + 1;
64+
size = end - first;
65+
if (size <= 0)
66+
{
67+
/* no extension found, use entire filename */
68+
size = rt_strlen(first);
69+
}
5870
if (size >= RT_NAME_MAX) size = RT_NAME_MAX - 1;
5971

6072
rt_strncpy(object->name, first, size);

components/libc/posix/libdl/dlopen.c

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ void* dlopen(const char *filename, int flags)
3333
{
3434
struct rt_dlmodule *module;
3535
char *fullpath;
36-
const char*def_path = MODULE_ROOT_DIR;
36+
const char *def_path = MODULE_ROOT_DIR;
37+
char module_name[RT_NAME_MAX];
3738

3839
/* check parameters */
3940
RT_ASSERT(filename != RT_NULL);
@@ -48,15 +49,55 @@ void* dlopen(const char *filename, int flags)
4849
}
4950
else
5051
{
51-
fullpath = (char*)filename; /* absolute path, use it directly */
52+
fullpath = (char *)filename; /* absolute path, use it directly */
53+
}
54+
55+
/* Extract module name from path (strip directory and extension)
56+
* This matches the logic in _dlmodule_set_name() so that dlmodule_find()
57+
* can properly locate already-loaded modules by their stored name.
58+
*/
59+
{
60+
const char *first, *end, *ptr;
61+
int size;
62+
63+
ptr = first = fullpath;
64+
end = fullpath + strlen(fullpath);
65+
66+
while (*ptr != '\0')
67+
{
68+
if (*ptr == '/')
69+
first = ptr + 1;
70+
ptr++;
71+
}
72+
73+
/* find extension in filename portion only (after last '/') */
74+
ptr = first;
75+
while (*ptr != '\0')
76+
{
77+
if (*ptr == '.')
78+
end = ptr;
79+
ptr++;
80+
}
81+
82+
size = end - first;
83+
if (size <= 0)
84+
{
85+
/* no extension found, use entire filename */
86+
size = strlen(first);
87+
}
88+
if (size >= RT_NAME_MAX)
89+
size = RT_NAME_MAX - 1;
90+
91+
rt_strncpy(module_name, first, size);
92+
module_name[size] = '\0';
5293
}
5394

5495
rt_enter_critical();
5596

56-
/* find in module list */
57-
module = dlmodule_find(fullpath);
97+
/* find in module list using the stripped module name */
98+
module = dlmodule_find(module_name);
5899

59-
if(module != RT_NULL)
100+
if (module != RT_NULL)
60101
{
61102
rt_exit_critical();
62103
module->nref++;
@@ -67,11 +108,11 @@ void* dlopen(const char *filename, int flags)
67108
module = dlmodule_load(fullpath);
68109
}
69110

70-
if(fullpath != filename)
111+
if (fullpath != filename)
71112
{
72113
rt_free(fullpath);
73114
}
74115

75-
return (void*)module;
116+
return (void *)module;
76117
}
77118
RTM_EXPORT(dlopen);

0 commit comments

Comments
 (0)