@@ -140,7 +140,7 @@ LM_LoadModule(lm_string_t  path,
140140/********************************/ 
141141
142142lm_bool_t 
143- find_dlopen_module_callback (lm_module_t  * module , lm_void_t  * arg )
143+ find_dlfcn_module_callback (lm_module_t  * module , lm_void_t  * arg )
144144{
145145	static  const  char  * name_matches [] =  {
146146		"libc." , "libc-" , "libdl." , "libdl-" , "ld-musl-" , "ld-musl." 
@@ -194,7 +194,7 @@ LM_LoadModuleEx(const lm_process_t *process,
194194		return  ret ;
195195
196196	dlopen_mod .base  =  LM_ADDRESS_BAD ;
197- 	LM_EnumModulesEx (process , find_dlopen_module_callback , & dlopen_mod );
197+ 	LM_EnumModulesEx (process , find_dlfcn_module_callback , & dlopen_mod );
198198	if  (dlopen_mod .base  ==  LM_ADDRESS_BAD )
199199		return  ret ;
200200
@@ -216,9 +216,9 @@ LM_LoadModuleEx(const lm_process_t *process,
216216	ptlib .args [1 ] =  RTLD_LAZY ;
217217	if  (process -> bits  ==  64 ) {
218218		* (uint64_t  * )& ptlib .stack [0 ] =  (uint64_t )path_addr ;
219- 		* (int32_t  * )& ptlib .stack [4 ] =  (int32_t )RTLD_LAZY ;
219+ 		* (int32_t  * )& ptlib .stack [8 ] =  (int32_t )RTLD_LAZY ;
220220	} else  {
221- 		* (uint32_t  * )& ptlib .stack [0 ] =  (uint64_t )path_addr ;
221+ 		* (uint32_t  * )& ptlib .stack [0 ] =  (uint32_t )path_addr ;
222222		* (int32_t  * )& ptlib .stack [4 ] =  (int32_t )RTLD_LAZY ;
223223	}
224224
@@ -292,3 +292,123 @@ LM_UnloadModule(const lm_module_t *module)
292292
293293	return  LM_TRUE ;
294294}
295+ 
296+ /********************************/ 
297+ 
298+ typedef  struct  {
299+ 	lm_address_t  dlopen_addr ;
300+ 	lm_address_t  dlclose_addr ;
301+ } find_dlfcn_t ;
302+ 
303+ lm_bool_t 
304+ find_dlfcn_symbols_callback (lm_symbol_t  * symbol , lm_void_t  * arg )
305+ {
306+ 	static  const  char  * dlopen_matches [] =  {
307+ 		"__libc_dlopen_mode" , "dlopen" 
308+ 	};
309+ 	static  const  char  * dlclose_matches [] =  {
310+ 		"__libc_dlclose" , "dlclose" 
311+ 	};
312+ 	find_dlfcn_t  * parg  =  (find_dlfcn_t  * )arg ;
313+ 	size_t  i ;
314+ 
315+ 	for  (i  =  0 ; i  <  LM_ARRLEN (dlopen_matches ); ++ i ) {
316+ 		if  (!strcmp (symbol -> name , dlopen_matches [i ])) {
317+ 			parg -> dlopen_addr  =  symbol -> address ;
318+ 		}
319+ 	}
320+ 
321+ 	for  (i  =  0 ; i  <  LM_ARRLEN (dlclose_matches ); ++ i ) {
322+ 		if  (!strcmp (symbol -> name , dlclose_matches [i ])) {
323+ 			parg -> dlclose_addr  =  symbol -> address ;
324+ 		}
325+ 	}
326+ 
327+ 	return  (parg -> dlopen_addr  ==  LM_ADDRESS_BAD  ||  parg -> dlclose_addr  ==  LM_ADDRESS_BAD ) ? LM_TRUE  : LM_FALSE ;
328+ }
329+ 
330+ LM_API  lm_bool_t  LM_CALL 
331+ LM_UnloadModuleEx (const  lm_process_t  * process ,
332+ 		  const  lm_module_t   * module )
333+ {
334+ 	lm_bool_t  ret  =  LM_FALSE ;
335+ 	lm_module_t  dlfcn_mod ;
336+ 	find_dlfcn_t  dlfcn  =  { LM_ADDRESS_BAD , LM_ADDRESS_BAD  };
337+ 	ptrace_libcall_t  ptlib ;
338+ 	long  link_map_iter ;
339+ 	struct  link_map  link_map ;
340+ 	char  path [LM_PATH_MAX ];
341+ 	void  * handle  =  NULL ;
342+ 	long  call_ret ;
343+ 
344+ 	if  (!process  ||  !module )
345+ 		return  ret ;
346+ 
347+ 	dlfcn_mod .base  =  LM_ADDRESS_BAD ;
348+ 	LM_EnumModulesEx (process , find_dlfcn_module_callback , & dlfcn_mod );
349+ 	if  (dlfcn_mod .base  ==  LM_ADDRESS_BAD )
350+ 		return  ret ;
351+ 
352+ 	LM_EnumSymbols (& dlfcn_mod , find_dlfcn_symbols_callback , & dlfcn );
353+ 	if  (dlfcn .dlopen_addr  ==  LM_ADDRESS_BAD  ||  dlfcn .dlclose_addr  ==  LM_ADDRESS_BAD )
354+ 		return  ret ;
355+ 
356+ 	/* Setup arguments both on the stack and on registers to prevent possible issues */ 
357+ 	ptlib .address  =  dlfcn .dlopen_addr ;
358+ 	ptlib .args [0 ] =  (long )NULL ;
359+ 	ptlib .args [1 ] =  RTLD_LAZY ;
360+ 	if  (process -> bits  ==  64 ) {
361+ 		* (uint64_t  * )& ptlib .stack [0 ] =  (uint64_t )NULL ;
362+ 		* (int32_t  * )& ptlib .stack [8 ] =  (int32_t )RTLD_LAZY ;
363+ 	} else  {
364+ 		* (uint32_t  * )& ptlib .stack [0 ] =  (uint32_t )NULL ;
365+ 		* (int32_t  * )& ptlib .stack [4 ] =  (int32_t )RTLD_LAZY ;
366+ 	}
367+ 
368+ 	if  (ptrace_attach (process -> pid ))
369+ 		goto EXIT ;
370+ 
371+ 	link_map_iter  =  ptrace_libcall (process -> pid , process -> bits , & ptlib );
372+ 	if  (link_map_iter  ==  -1  ||  link_map_iter  ==  0 )
373+ 		goto DETACH_EXIT ;
374+ 
375+ 	/* Search for the correct handle, just like in LM_UnloadModule */ 
376+ 	for  (; link_map_iter ; link_map_iter  =  (long )link_map .l_next ) {
377+ 		if  (ptrace_read (process -> pid , link_map_iter , & link_map , sizeof (link_map )) !=  sizeof (link_map ))
378+ 			goto DETACH_EXIT ;
379+ 
380+ 		if  (ptrace_read (process -> pid , (long )link_map .l_name , path , sizeof (path )) ==  0 )
381+ 			goto DETACH_EXIT ;
382+ 		path [sizeof (path ) -  1 ] =  '\0' ;
383+ 
384+ 		if  (!strcmp (path , module -> path )) {
385+ 			handle  =  (void  * )link_map_iter ;
386+ 			break ;
387+ 		}
388+ 	}
389+ 
390+ 	if  (!handle ) {
391+ 		/* If no handle was found, it means that the module is already unloaded */ 
392+ 		ret  =  LM_TRUE ;
393+ 		goto DETACH_EXIT ;
394+ 	}
395+ 
396+ 	/* Call dlclose with the handle we found */ 
397+ 	ptlib .address  =  dlfcn .dlclose_addr ;
398+ 	ptlib .args [0 ] =  (long )handle ;
399+ 	if  (process -> bits  ==  64 ) {
400+ 		* (uint64_t  * )& ptlib .stack [0 ] =  (uint64_t )handle ;
401+ 	} else  {
402+ 		* (uint32_t  * )& ptlib .stack [0 ] =  (uint32_t )handle ;
403+ 	}
404+ 
405+ 	call_ret  =  ptrace_libcall (process -> pid , process -> bits , & ptlib );
406+ 	if  (call_ret  !=  0 )
407+ 		goto DETACH_EXIT ;
408+ 
409+ 	ret  =  LM_TRUE ;
410+ DETACH_EXIT :
411+ 	ptrace_detach (process -> pid );
412+ EXIT :
413+ 	return  ret ;
414+ }
0 commit comments