Static linking (on Mac x64)

radekm
radekm Member Posts: 23

Hello,

normally I use dynamic linking with solclient library and it works as expected.

Out of curiosity I tried static linking. I linked following

  • libsolclient.a,
  • libsolclientssl.a,
  • libcrypto.a,
  • libssl.a
  • and Kerberos framework.

When I run my app it fails with EXC_BAD_ACCESS when running solClient_cleanup according to LLDB it calls _solClient_transactedSession_failAllThreads which calls JudyLFirstEmpty.

I use solclient-7.24.0.9 on Mac with x64 architecture.

My question is whether there is some example or tutorial explaining how to do static linking on Mac? For example there's also solClientSSLStaticLinkEnable.o which I don't link because then I have duplicate symbols. So I'm confused why is solClientSSLStaticLinkEnable.o in the package or what should I do with it?

Thanks

Tagged:

Answers

  • marc
    marc Member, Administrator, Moderator, Employee Posts: 889 admin

    Great question @radekm. I don't recall anyone using static linking on Mac before. We'll look into this and get back to you.

  • Ragnar
    Ragnar Member, Employee Posts: 64 Solace Employee

    Hello @radekm .


    Can you provide a small project to demonstrate how you are linking and getting this error?

    Generally I expect problems with static linking to occur at linking not at run time. Once you've successfully created the executable, the run-time exception may be something else entirely.

    That said, I also expect that you need to include solClientSSLStaticLinkEnable.o in your link-edit command and it must occur before libssl.a and libcrypto.a in the command. If you do not include this, it is likely the library is still trying to dynamically load libssl.so/libcrypto.so. This still should not lead to the EXC_BAD_ACCESS but instead to a dynamic loading issue at run-time.

    If you are getting duplicate symbol errors at link-edit time, can you tell us what symbols are duplicated. And again provide a small project/makefile to demonstrate this so we can debug it.

    Finally, just for thoroughness, are you using TLS in your test (libssl/libcrypto) and GSS (Kerberos) both? Do you use Kerberos for authentication and TLS for encryption. I don't think this will lead to a failure in JudyFirstLempty, but I do want to understand your test scenario so I can try to reproduce it.

  • radekm
    radekm Member Posts: 23

    That said, I also expect that you need to include solClientSSLStaticLinkEnable.o in your link-edit command and it must occur before libssl.a and libcrypto.a in the command.

    I tried

    clang solace_lib/solClientSSLStaticLinkEnable.o solace_lib/libssl.a solace_lib/libcrypto.a solace_lib/libsolclient.a -framework kerberos connect.c
    

    but still getting lots of duplicate symbol errors. The first few of them are

    duplicate symbol '__SSL_set_verify' in:
        solace_lib/solClientSSLStaticLinkEnable.o
        solace_lib/libsolclient.a(solClientSSL.o)
    duplicate symbol '__SSL_use_cert_and_key' in:
        solace_lib/solClientSSLStaticLinkEnable.o
        solace_lib/libsolclient.a(solClientSSL.o)
    duplicate symbol '__d2i_PrivateKey' in:
        solace_lib/solClientSSLStaticLinkEnable.o
        solace_lib/libsolclient.a(solClientSSL.o)
    

    It's very basic program. But seems not to link if I omit Kerberos framework.

    #include <stdio.h>
    
    
    #define SOLCLIENT_CONST_PROPERTIES 1
    #include "solclient/solClient.h"
    #include "solclient/solClientMsg.h"
    
    
    solClient_rxMsgCallback_returnCode_t sessionMessageReceiveCallback (
        solClient_opaqueSession_pt session,
        solClient_opaqueMsg_pt msg,
        void *data
    ) {
        return SOLCLIENT_CALLBACK_OK;
    }
    
    
    void sessionEventCallback (
        solClient_opaqueSession_pt opaqueSession_p,
        solClient_session_eventCallbackInfo_pt eventInfo_p,
        void *user_p
    ) {
    }
    
    
    int main()
    {
        printf("Starting\n");
    
    
        solClient_initialize(SOLCLIENT_LOG_INFO, NULL);
    
    
        const char *contextProps[50] = {0, };
        int propIndexC = 0;
    
    
        contextProps[propIndexC++] = SOLCLIENT_CONTEXT_PROP_CREATE_THREAD;
        contextProps[propIndexC++] = SOLCLIENT_PROP_ENABLE_VAL;
    
    
        contextProps[propIndexC++] = NULL;
    
    
        solClient_opaqueContext_pt context;
        solClient_context_createFuncInfo_t contextFuncInfo = SOLCLIENT_CONTEXT_CREATEFUNC_INITIALIZER;
        solClient_context_create(
            //SOLCLIENT_CONTEXT_PROPS_DEFAULT_WITH_CREATE_THREAD,
            contextProps,
            &context,
            &contextFuncInfo,
            sizeof(contextFuncInfo)
        );
    
    
        solClient_opaqueSession_pt session;
    
    
        solClient_session_createFuncInfo_t sessionFuncInfo = SOLCLIENT_SESSION_CREATEFUNC_INITIALIZER;
        sessionFuncInfo.rxMsgInfo.callback_p = sessionMessageReceiveCallback;
        sessionFuncInfo.rxMsgInfo.user_p = NULL;
        sessionFuncInfo.eventInfo.callback_p = sessionEventCallback;
        sessionFuncInfo.eventInfo.user_p = NULL;
    
    
        const char *sessionProps[50] = {0, };
        int propIndex = 0;
    
    
        sessionProps[propIndex++] = SOLCLIENT_SESSION_PROP_HOST;
        sessionProps[propIndex++] = "foo";
    
    
        sessionProps[propIndex++] = SOLCLIENT_SESSION_PROP_USERNAME;
        sessionProps[propIndex++] = "bar";
    
    
        sessionProps[propIndex++] = SOLCLIENT_SESSION_PROP_PASSWORD;
        sessionProps[propIndex++] = "";
    
    
        sessionProps[propIndex++] = SOLCLIENT_SESSION_PROP_VPN_NAME;
        sessionProps[propIndex++] = "default";
    
    
        sessionProps[propIndex++] = SOLCLIENT_SESSION_PROP_CONNECT_BLOCKING;
        sessionProps[propIndex++] = SOLCLIENT_PROP_ENABLE_VAL;
    
    
        sessionProps[propIndex++] = SOLCLIENT_SESSION_PROP_SUBSCRIBE_BLOCKING;
        sessionProps[propIndex++] = SOLCLIENT_PROP_ENABLE_VAL;
    
    
        sessionProps[propIndex++] = SOLCLIENT_SESSION_PROP_RECONNECT_RETRIES;
        sessionProps[propIndex++] = "0";
    
    
        sessionProps[propIndex++] = NULL;
    
    
        solClient_session_create(
            (const char **)sessionProps,
            context,
            &session,
            &sessionFuncInfo,
            sizeof(sessionFuncInfo)
        );
    
    
        solClient_cleanup();
        printf("Finishing\n");
    
    
        return 0;
    }