summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/lt_path.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/core/lt_path.c b/src/core/lt_path.c
index 3fb0385..cd95e0e 100644
--- a/src/core/lt_path.c
+++ b/src/core/lt_path.c
@@ -605,3 +605,83 @@ const struct lt_dlentry * lt_dlloader_find(const char * ldrname)
(void)ldrname;
return 0;
}
+
+static int lt_dlpreload_remove_locked(const struct lt_symdef * symtbl)
+{
+ struct lt_modctx * pmod;
+
+ for (pmod=lt_modv_head; pmod ; pmod=pmod->mnext) {
+ if (pmod->symtbl == symtbl) {
+ if (pmod->mrefs > 0) {
+ pmod->mrefs--;
+ return 0;
+ }
+
+ return SLTDL_ERR_MODULE_REF_COUNT;
+ }
+ }
+
+ return SLTDL_ERR_MODULE_PTR_INVALID;
+}
+
+static void lt_dlpreload_reset_locked(void)
+{
+ struct lt_modctx * pmod;
+
+ for (pmod=lt_modv_head; pmod ; pmod=pmod->mnext)
+ if (pmod->symtbl && (pmod->mrefs > 0))
+ pmod->mrefs = 0;
+}
+
+static int lt_dlpreload_modctl_locked(
+ const struct lt_symdef * symtbl,
+ enum sltdl_modctl op)
+{
+ struct lt_modctx * modctx;
+ switch (op) {
+ case SLTDL_MODCTL_PRELOAD_ADD:
+ return lt_dlopen_locked(symtbl,0,0,1)
+ ? 0 : -1;
+
+ case SLTDL_MODCTL_PRELOAD_REMOVE:
+ return lt_dlpreload_remove_locked(symtbl)
+ ? 0 : -1;
+
+ case SLTDL_MODCTL_PRELOAD_DEFAULT:
+ if (!(modctx = lt_dlopen_locked(symtbl,0,0,(-1))))
+ return -1;
+
+ modctx->mrefs = -1;
+ return 0;
+
+ case SLTDL_MODCTL_PRELOAD_RESET:
+ lt_dlpreload_reset_locked();
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int lt_dlpreload_modctl_impl(
+ const struct lt_symdef * symtbl,
+ enum sltdl_modctl op)
+{
+ int ret;
+
+ lt_slock();
+
+ ret = lt_dlpreload_modctl_locked(
+ symtbl,op);
+
+ return lt_sunlock((-1)*!!ret,ret);
+}
+
+int lt_dlpreload_modctl(
+ const struct lt_symdef * symtbl,
+ enum sltdl_modctl op)
+{
+ return lt_dlpreload_modctl_impl(symtbl,op);
+}