@@ -66,15 +66,6 @@ FILE *fmemopen (void *buf, size_t size, const char *mode);
6666#include <windows.h>
6767#include <io.h> /* for access */
6868
69- static HMODULE
70- lt_dlopen (const char * x )
71- {
72- if (x == NULL ) {
73- return GetModuleHandle (NULL );
74- }
75- return LoadLibrary (x );
76- }
77-
7869static void *
7970lt_dlsym (HMODULE hmod , const char * p )
8071{
@@ -106,7 +97,6 @@ lt_dlerror (void)
10697/* note: only defined in configure when HAVE_DLFCN_H is true and dlopen can be linked */
10798#include <dlfcn.h>
10899
109- #define lt_dlopen (x ) dlopen(x, RTLD_LAZY | RTLD_GLOBAL)
110100#define lt_dlsym (x ,y ) dlsym(x, y)
111101#define lt_dlclose (x ) dlclose(x)
112102#define lt_dlerror () dlerror()
@@ -171,6 +161,10 @@ static char *call_filename_buff;
171161static lt_dlhandle mainhandle ;
172162#endif
173163
164+ #if !defined(_WIN32 ) && !defined(USE_LIBDL )
165+ static lt_dladvise advise = NULL ;
166+ #endif
167+
174168static size_t call_lastsize ;
175169static size_t resolve_size = 0 ;
176170static unsigned int cob_jmp_primed ;
@@ -279,7 +273,8 @@ set_resolve_error (int module_type)
279273 }
280274}
281275
282- static int last_entry_is_working_directory (const char * buff , const char * pstr )
276+ static int
277+ last_entry_is_working_directory (const char * buff , const char * pstr )
283278{
284279 const size_t pos = pstr - buff ; /* always > 2 */
285280 if (buff [pos - 1 ] == '.'
@@ -289,6 +284,44 @@ static int last_entry_is_working_directory (const char *buff, const char *pstr)
289284 return 0 ;
290285}
291286
287+ static void *
288+ cob_dlopen (const char * filename )
289+ {
290+ #if defined (_WIN32 )
291+ if (filename == NULL ) {
292+ return GetModuleHandle (NULL );
293+ }
294+ return LoadLibrary (filename );
295+ #elif defined(USE_LIBDL )
296+ const int flags = cobsetptr -> cob_load_global
297+ ? RTLD_LAZY | RTLD_GLOBAL
298+ : RTLD_LAZY | RTLD_LOCAL ;
299+
300+ return dlopen (filename , flags );
301+ #else
302+ if (advise != NULL ) {
303+ static int last_cob_load_global = -1 ;
304+
305+ if (cobsetptr -> cob_load_global != last_cob_load_global ) {
306+ int error ;
307+ last_cob_load_global = cobsetptr -> cob_load_global
308+
309+ if (cobsetptr -> cob_load_global ) {
310+ error = lt_dladvise_global (& advise );
311+ } else {
312+ error = lt_dladvise_local (& advise );
313+ }
314+
315+ if (error ) {
316+ cob_runtime_warning ("set link loader hint failed; %s" , lt_dlerror ());
317+ }
318+ }
319+ }
320+
321+ return lt_dlopenadvise (filename , advise );
322+ #endif
323+ }
324+
292325/* resolves the actual library path used from
293326 * COB_LIBRARY_PATH runtime setting
294327 * "." as current working direktory [if not included already: prefixed]
@@ -555,9 +588,20 @@ add_to_preload (const char *path, lt_dlhandle libhandle, struct struct_handle *l
555588 base_preload_ptr = preptr ;
556589 }
557590#else
558- COB_UNUSED (last_elem );
559- preptr -> next = base_preload_ptr ;
560- base_preload_ptr = preptr ;
591+ /* Use the same logic as above in case the cob_load_global is set to local */
592+ if (!cobsetptr -> cob_load_global ) {
593+ if (last_elem ) {
594+ last_elem -> next = preptr ;
595+ } else {
596+ preptr -> next = NULL ;
597+ base_preload_ptr = preptr ;
598+ }
599+ } else {
600+ COB_UNUSED (last_elem );
601+ preptr -> next = base_preload_ptr ;
602+ base_preload_ptr = preptr ;
603+ }
604+
561605#endif
562606
563607 if (!cobsetptr -> cob_preload_str ) {
@@ -595,6 +639,9 @@ cache_preload (const char *path)
595639 /* Save last element of preload list */
596640 if (!preptr -> next ) last_elem = preptr ;
597641#endif
642+ if (!cobsetptr -> cob_load_global ) {
643+ if (!preptr -> next ) last_elem = preptr ;
644+ }
598645 }
599646
600647 /* Check for duplicate in already loaded programs;
@@ -624,7 +671,7 @@ cache_preload (const char *path)
624671 return 0 ;
625672 }
626673
627- libhandle = lt_dlopen (path );
674+ libhandle = cob_dlopen (path );
628675 if (!libhandle ) {
629676 cob_runtime_warning (
630677 _ ("preloading from existing path '%s' failed; %s" ), path , lt_dlerror ());
@@ -854,7 +901,7 @@ cob_resolve_internal (const char *name, const char *dirent,
854901 }
855902
856903#if 0 /* RXWRXW RTLD */
857- #if defined(USE_LIBDL ) && defined (RTLD_DEFAULT )
904+ #if defined(USE_LIBDL ) && defined(RTLD_DEFAULT )
858905 func = lt_dlsym (RTLD_DEFAULT , call_entry_buff );
859906 if (func != NULL ) {
860907 insert (name , func , NULL , NULL , NULL , 1 );
@@ -870,7 +917,7 @@ cob_resolve_internal (const char *name, const char *dirent,
870917 for (p = call_filename_buff ; * p ; ++ p ) {
871918 * p = (cob_u8_t )toupper (* p );
872919 }
873- handle = lt_dlopen (call_filename_buff );
920+ handle = cob_dlopen (call_filename_buff );
874921 if (handle != NULL ) {
875922 /* Candidate for future calls */
876923 cache_dynload (call_filename_buff , handle );
@@ -913,7 +960,7 @@ cob_resolve_internal (const char *name, const char *dirent,
913960 return NULL ;
914961 }
915962 lt_dlerror (); /* clear last error conditions */
916- handle = lt_dlopen (call_filename_buff );
963+ handle = cob_dlopen (call_filename_buff );
917964 if (handle != NULL ) {
918965 /* Candidate for future calls */
919966 cache_dynload (call_filename_buff , handle );
@@ -946,7 +993,7 @@ cob_resolve_internal (const char *name, const char *dirent,
946993 call_filename_buff [COB_NORMAL_MAX ] = 0 ;
947994 if (access (call_filename_buff , R_OK ) == 0 ) {
948995 lt_dlerror (); /* clear last error conditions */
949- handle = lt_dlopen (call_filename_buff );
996+ handle = cob_dlopen (call_filename_buff );
950997 if (handle != NULL ) {
951998 /* Candidate for future calls */
952999 cache_dynload (call_filename_buff , handle );
@@ -1706,6 +1753,15 @@ cob_exit_call (void)
17061753#endif
17071754#endif
17081755
1756+ #if !defined(_WIN32 ) && !defined(USE_LIBDL )
1757+ if (advise != NULL ) {
1758+ if (lt_dladvise_destroy (& advise )) {
1759+ /* not translated as highly unlikely */
1760+ cob_runtime_warning (
1761+ "destroying link loader advise failed; %s" , lt_dlerror ());
1762+ }
1763+ }
1764+ #endif
17091765}
17101766
17111767/* try to load specified module from all entries in COB_LIBRARY_PATH
@@ -1793,12 +1849,20 @@ cob_init_call (cob_global *lptr, cob_settings* sptr, const int check_mainhandle)
17931849
17941850 lt_dlinit ();
17951851
1852+ #if !defined(_WIN32 ) && !defined(USE_LIBDL )
1853+ if (lt_dladvise_init (& advise ) != 0 ) {
1854+ /* not translated as highly unlikely */
1855+ cob_runtime_warning (
1856+ "init link loader advise failed; %s" , lt_dlerror ());
1857+ }
1858+ #endif
1859+
17961860#ifndef COB_BORKED_DLOPEN
17971861 /* only set main handle if not started by cobcrun as this
17981862 saves a check for exported functions in every CALL
17991863 */
18001864 if (check_mainhandle ) {
1801- mainhandle = lt_dlopen (NULL );
1865+ mainhandle = cob_dlopen (NULL );
18021866 } else {
18031867 mainhandle = NULL ;
18041868 }
0 commit comments