Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Add a COB_LOAD_GLOBAL config option to modify dlopen behavior #209

Draft
wants to merge 16 commits into
base: gcos4gnucobol-3.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
2025-01-08 Simon Sobisch <[email protected]>

* config/runtime.cfg: Add documentation for COB_LOAD_GLOBAL flag

florianschmidt1994 marked this conversation as resolved.
Show resolved Hide resolved
2025-01-08 Florian Schmidt <[email protected]>

* libcob/call.c, libcob/coblocal.h, libcob/common.c: Introduce a flag
COB_LOAD_GLOBAL (load_global) to toggle if the symbols of CALLed
programs should be made available in the global namespace

florianschmidt1994 marked this conversation as resolved.
Show resolved Hide resolved
2024-12-08 Simon Sobisch <[email protected]>

Expand Down
12 changes: 12 additions & 0 deletions config/runtime.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,18 @@
# Default: false
# Example: PHYSICAL_CANCEL TRUE

# Environment name: COB_LOAD_GLOBAL
# Parameter name: load_global
# Purpose: tell the system loader to provide symbols in CALLed
# programs globally, allowing symbols to be found for linked
# libraries later
# Type: boolean
# Note: COBOL CALLs will always find symbols in already CALLed or
# pre-modules; this setting is mostly an advise to the system,
# not all systems are capable of loading libraries global/local
# Default: false
GitMensch marked this conversation as resolved.
Show resolved Hide resolved
# Example: load_global true

#
## File I/O
#
Expand Down
112 changes: 64 additions & 48 deletions libcob/call.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,65 +60,82 @@ FILE *fmemopen (void *buf, size_t size, const char *mode);
https://wiki.musl-libc.org/functional-differences-from-glibc.html#Unloading_libraries
*/

static cob_settings *cobsetptr = NULL;

#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <io.h> /* for access */

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <io.h> /* for access */
florianschmidt1994 marked this conversation as resolved.
Show resolved Hide resolved
static void *
lt_dlsym (HMODULE hmod, const char *p)
{
union {
FARPROC modaddr;
void *voidptr;
} modun;

static HMODULE
lt_dlopen (const char *x)
{
if (x == NULL) {
return GetModuleHandle (NULL);
modun.modaddr = GetProcAddress(hmod, p);
return modun.voidptr;
}
return LoadLibrary(x);
}

static void *
lt_dlsym (HMODULE hmod, const char *p)
{
union {
FARPROC modaddr;
void *voidptr;
} modun;

modun.modaddr = GetProcAddress(hmod, p);
return modun.voidptr;
}

#define lt_dlclose(x) FreeLibrary(x)
#define lt_dlinit()
#define lt_dlexit()
#define lt_dlhandle HMODULE
#define lt_dlclose(x) FreeLibrary(x)
#define lt_dlinit()
#define lt_dlexit()
#define lt_dlhandle HMODULE

#if 1 /* RXWRXW - dlerror */
static char errbuf[64];
static char *
lt_dlerror (void)
{
sprintf (errbuf, _("LoadLibrary/GetProcAddress error %d"), (int)GetLastError());
return errbuf;
}
#if 1 /* RXWRXW - dlerror */
static char errbuf[64];
static char *
lt_dlerror (void)
{
sprintf (errbuf, _("LoadLibrary/GetProcAddress error %d"), (int)GetLastError());
return errbuf;
}
#endif

#elif defined(USE_LIBDL)
/* note: only defined in configure when HAVE_DLFCN_H is true and dlopen can be linked */
#include <dlfcn.h>

#define lt_dlopen(x) dlopen(x, RTLD_LAZY | RTLD_GLOBAL)
#define lt_dlsym(x,y) dlsym(x, y)
#define lt_dlclose(x) dlclose(x)
#define lt_dlerror() dlerror()
#define lt_dlinit()
#define lt_dlexit()
#define lt_dlhandle void *

/* note: only defined in configure when HAVE_DLFCN_H is true and dlopen can be linked */
#include <dlfcn.h>

#define lt_dlsym(x,y) dlsym(x, y)
#define lt_dlclose(x) dlclose(x)
#define lt_dlerror() dlerror()
#define lt_dlinit()
#define lt_dlexit()
#define lt_dlhandle void *
#else
#include <ltdl.h>
#endif

#include <ltdl.h>
static void* cob_dlopen(const char* filename) {
#ifdef _WIN32
if (filename == NULL) {
return GetModuleHandle (NULL);
}
return LoadLibrary(filename);
#elif defined(USE_LIBDL)
int flags = cobsetptr->cob_load_global
? RTLD_LAZY | RTLD_GLOBAL
: RTLD_LAZY | RTLD_LOCAL;

return dlopen(filename, flags);
#else
lt_dladvise advise;
lt_dladvise_init(&advise);

if (cobsetptr->cob_load_global) {
lt_dladvise_global(&advise);
} else {
lt_dladvise_local(&advise);
}

void* handle = lt_dlopenadvise(filename, advise);
lt_dladvise_destroy(&advise); // Clean up advise object
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please make the advise static and clean it up in call.c's cleanup function (depending on its preprocessor macro, of course), you can also init it in the init function - just set the advise flag here (the setting for both dlopen and lt_dlopen will be moved out to a config function later - you're welcome to add it (see screenio.c, this may be even explained in the video :-) and call it from the config side if this var or COB_LIBRARY_PATH was adjusted

return handle;
#endif
}

#define lt_dlopen(x) cob_dlopen(x) // TODO: Remove this!
florianschmidt1994 marked this conversation as resolved.
Show resolved Hide resolved

#define COB_MAX_COBCALL_PARMS 16
#define CALL_BUFF_SIZE 256U
Expand Down Expand Up @@ -158,7 +175,6 @@ static struct struct_handle *base_preload_ptr;
static struct struct_handle *base_dynload_ptr;

static cob_global *cobglobptr = NULL;
static cob_settings *cobsetptr = NULL;

static char **resolve_path;
static char *resolve_error;
Expand Down
1 change: 1 addition & 0 deletions libcob/coblocal.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ typedef struct __cob_settings {

/* call.c */
int cob_physical_cancel; /* 0 "= "logical only" (default), 1 "also unload", -1 "never unload" */
unsigned int cob_load_global; /* Wether dlopen should use the global or local namespace */
florianschmidt1994 marked this conversation as resolved.
Show resolved Hide resolved
unsigned int name_convert;
char *cob_preload_str;
char *cob_library_path;
Expand Down
3 changes: 3 additions & 0 deletions libcob/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,9 @@ static struct config_tbl gc_conf[] = {
{"LOGICAL_CANCELS", "logical_cancels", NULL, NULL, GRP_HIDE, ENV_BOOL | ENV_NOT, SETPOS (cob_physical_cancel)},
{"COB_LIBRARY_PATH", "library_path", NULL, NULL, GRP_CALL, ENV_PATH, SETPOS (cob_library_path)}, /* default value set in cob_init_call() */
{"COB_PRE_LOAD", "pre_load", NULL, NULL, GRP_CALL, ENV_STR, SETPOS (cob_preload_str)},
#ifndef _WIN32
{"COB_LOAD_GLOBAL", "load_global", "0", NULL, GRP_CALL, ENV_BOOL, SETPOS(cob_load_global)},
#endif
{"COB_BELL", "bell", "0", beepopts, GRP_SCREEN, ENV_UINT | ENV_ENUMVAL, SETPOS (cob_beep_value)},
{"COB_DEBUG_LOG", "debug_log", NULL, NULL, GRP_HIDE, ENV_FILE, SETPOS (cob_debug_log)},
{"COB_DISABLE_WARNINGS", "disable_warnings", "0", NULL, GRP_MISC, ENV_BOOL | ENV_NOT, SETPOS (cob_display_warn)},
Expand Down
Loading