From 872009336e131fac0d614d904eb2e28ead3ea794 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sun, 22 Mar 2020 22:09:23 -0700 Subject: [PATCH 1/5] OSX fix osdFindSymbol RTLD_DEFAULT isn't zero on OSX --- modules/libcom/src/osi/os/posix/osdFindSymbol.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/libcom/src/osi/os/posix/osdFindSymbol.c b/modules/libcom/src/osi/os/posix/osdFindSymbol.c index acfc405e59..084865341c 100644 --- a/modules/libcom/src/osi/os/posix/osdFindSymbol.c +++ b/modules/libcom/src/osi/os/posix/osdFindSymbol.c @@ -11,6 +11,12 @@ #define epicsExportSharedSymbols #include "epicsFindSymbol.h" +/* non-POSIX extension available on Linux (glibc at least) and OSX. + */ +#ifndef RTLD_DEFAULT +# define RTLD_DEFAULT 0 +#endif + epicsShareFunc void * epicsLoadLibrary(const char *name) { return dlopen(name, RTLD_LAZY | RTLD_GLOBAL); @@ -23,5 +29,5 @@ epicsShareFunc const char *epicsLoadError(void) epicsShareFunc void * epicsShareAPI epicsFindSymbol(const char *name) { - return dlsym(0, name); + return dlsym(RTLD_DEFAULT, name); } From d3b2298bcba2050932998457dbb081917a2752df Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sat, 21 Mar 2020 22:13:53 -0700 Subject: [PATCH 2/5] WIN32 fix epicsFindSymbol() error propagation And use thread local to hold error code/message. --- .../libcom/src/osi/os/WIN32/osdFindSymbol.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/modules/libcom/src/osi/os/WIN32/osdFindSymbol.c b/modules/libcom/src/osi/os/WIN32/osdFindSymbol.c index 6de3c428e1..c7553896d9 100644 --- a/modules/libcom/src/osi/os/WIN32/osdFindSymbol.c +++ b/modules/libcom/src/osi/os/WIN32/osdFindSymbol.c @@ -11,7 +11,16 @@ #define epicsExportSharedSymbols #include "epicsFindSymbol.h" -static int epicsLoadErrorCode = 0; +#ifdef _MSC_VER +# define STORE static __declspec( thread ) +#elif __GNUC__ +# define STORE static __thread +#else +# define STORE static +#endif + +STORE +int epicsLoadErrorCode = 0; epicsShareFunc void * epicsLoadLibrary(const char *name) { @@ -28,7 +37,7 @@ epicsShareFunc void * epicsLoadLibrary(const char *name) epicsShareFunc const char *epicsLoadError(void) { - static char buffer[100]; + STORE char buffer[100]; FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, @@ -42,5 +51,9 @@ epicsShareFunc const char *epicsLoadError(void) epicsShareFunc void * epicsShareAPI epicsFindSymbol(const char *name) { - return GetProcAddress(0, name); + void* ret = GetProcAddress(0, name); + if(!ret) { + epicsLoadErrorCode = GetLastError(); + } + return ret; } From 24df056bcbdc223578ba0f14d9c72755054177fe Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sun, 22 Mar 2020 08:33:42 -0700 Subject: [PATCH 3/5] WIN32 fix epicsFindSymbol() Passing zero as to GetProcAddress is undocumented, but seems to be equivalent to passing GetModuleHandle(NULL) which searches only the address space of the executable file. Emulate the effect of dlsym(0, ...) by searching all loaded modules. Probably not so efficient... --- .../libcom/src/osi/os/WIN32/osdFindSymbol.c | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/modules/libcom/src/osi/os/WIN32/osdFindSymbol.c b/modules/libcom/src/osi/os/WIN32/osdFindSymbol.c index c7553896d9..19dc5e59af 100644 --- a/modules/libcom/src/osi/os/WIN32/osdFindSymbol.c +++ b/modules/libcom/src/osi/os/WIN32/osdFindSymbol.c @@ -5,8 +5,13 @@ \*************************************************************************/ /* osi/os/WIN32/osdFindSymbol.c */ +/* avoid need to link against psapi.dll + * requires windows 7 or later + */ +#define NTDDI_VERSION NTDDI_WIN7 #include +#include #define epicsExportSharedSymbols #include "epicsFindSymbol.h" @@ -51,8 +56,22 @@ epicsShareFunc const char *epicsLoadError(void) epicsShareFunc void * epicsShareAPI epicsFindSymbol(const char *name) { - void* ret = GetProcAddress(0, name); + HMODULE dlls[128]; + DWORD ndlls=0u, i; + void* ret = NULL; + + /* As a handle returned by LoadLibrary() isn't available to us, + * try all loaded modules in arbitrary order. + */ + if(K32EnumProcessModules(GetCurrentProcess(), dlls, sizeof(dlls), &ndlls)) { + for(i=0; !ret && i Date: Sat, 21 Mar 2020 12:21:09 -0700 Subject: [PATCH 4/5] add epicsLoadTest --- modules/libcom/test/Makefile | 10 +++ modules/libcom/test/epicsLoadTest.cpp | 91 +++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 modules/libcom/test/epicsLoadTest.cpp diff --git a/modules/libcom/test/Makefile b/modules/libcom/test/Makefile index cf55760a6d..3457b10578 100755 --- a/modules/libcom/test/Makefile +++ b/modules/libcom/test/Makefile @@ -260,6 +260,16 @@ iocshTest_SRCS += iocshTest.cpp TESTS += iocshTest TESTFILES += $(wildcard ../iocshTest*.cmd) +TESTPROD_HOST += epicsLoadTest +epicsLoadTest_SRCS += epicsLoadTest.cpp +# test linked against static libCom? +epicsLoadTest_CPPFLAGS_STATIC_YES = -DLINKING_STATIC +epicsLoadTest_CPPFLAGS += $(epicsLoadTest_CPPFLAGS_STATIC_$(STATIC_BUILD)) +# are dynamic libraries built? +epicsLoadTest_CPPFLAGS_SHARED_YES = -DBUILDING_SHARED_LIBRARIES +epicsLoadTest_CPPFLAGS += $(epicsLoadTest_CPPFLAGS_SHARED_$(SHARED_LIBRARIES)) +TESTS += epicsLoadTest + # The testHarness runs all the test programs in a known working order. testHarness_SRCS += epicsRunLibComTests.c diff --git a/modules/libcom/test/epicsLoadTest.cpp b/modules/libcom/test/epicsLoadTest.cpp new file mode 100644 index 0000000000..8090810721 --- /dev/null +++ b/modules/libcom/test/epicsLoadTest.cpp @@ -0,0 +1,91 @@ +/*************************************************************************\ +* Copyright (c) 2020 Michael Davidsaver +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#include + +#include + +#include "epicsUnitTest.h" +#include "testMain.h" + +#include "envDefs.h" +#include "epicsFindSymbol.h" +#include "epicsThread.h" + +namespace { + +// lookup a symbol from libCom +// which this executable is linked against (maybe statically) +// Doesn't work for static builds on windows +void loadCom() +{ + testDiag("Lookup symbol from Com"); + +#if defined (_WIN32) && defined(LINKING_STATIC) + testTodoBegin("windows static build"); +#endif + + void* ptr = epicsFindSymbol("epicsThreadGetCPUs"); + testOk(ptr==(void*)&epicsThreadGetCPUs, + "%p == %p (epicsThreadGetCPUs) : %s", + ptr, (void*)&epicsThreadGetCPUs, + epicsLoadError()); + + testTodoEnd(); +} + +void loadCA() +{ + testDiag("Load and lookup symbol from libca"); + + std::string libname; + { + std::ostringstream strm; + // running in eg. modules/libcom/test/O.linux-x86_64-debug +#ifdef _WIN32 + strm<<"..\\..\\..\\..\\bin\\"< Date: Sun, 22 Mar 2020 14:09:27 -0700 Subject: [PATCH 5/5] travis bump dist for mingw jobs older mingw headers omit K32EnumProcessModules() --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1e7d452128..056a460d60 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,11 +31,11 @@ matrix: compiler: gcc env: CMPLR=clang STATIC=YES - sudo: false - dist: trusty + dist: bionic compiler: gcc env: WINE=32 TEST=NO STATIC=YES - sudo: false - dist: trusty + dist: bionic compiler: gcc env: WINE=32 TEST=NO STATIC=NO - sudo: false