AIX

AIX

Connect with fellow AIX users and experts to gain knowledge, share insights, and solve problems.


#Power
#Power
 View Only
Expand all | Collapse all

C linkable shared library created out of a golang project on AIX 7.2 fails to run with error "The local-exec model was used for thread-local storage, but the module is not the main program."

  • 1.  C linkable shared library created out of a golang project on AIX 7.2 fails to run with error "The local-exec model was used for thread-local storage, but the module is not the main program."

    Posted Tue March 22, 2022 08:45 AM
    Edited by Carl Burnett Wed March 23, 2022 06:38 AM

    Hello everyone, I recently started working with AIX so please bear with me.

    Environment:

    AIX 7.2 64bit, powerpc7 
    go1.16.12 aix/ppc64
    gcc-8


    In our team we are trying to develop more applications with Golang for our AIX 7.2 platform and in one scenario we plan to create a shared object (.so-file) that can be called by a Perl application. So far I have gotten as far as being apparently able to compile it all down into some example C application, but that refuses to run. To showcase this issue I created a simple example described below.

    For testing purposes I created the following simple golang project I want to compile out:
    sharedLibTest.go

    package main
    
    import (
    m   "fmt"
    )
    
    import "C"
    
    func main() {
    }
    
    //export MyPackage_Init
    func MyPackage_Init() {
        fmt.Printf("%s\n", "Golang: MyPackage_Init was called")
    }
    
    //export MyPackage_Create
    func MyPackage_Create() {
        fmt.Printf("%s\n", "Golang: MyPackage_Create was called")
    }


    The functions MyPackage_init() and MyPackage_Create should be callable by a simple C app that currently just consists of this main.c

    #include <stdio.h>
    #include "sharedLibTest.h"
    
    int main() {
        printf("%s\n", "C: main() called");
        MyPackage_Init();
        MyPackage_Create();
    }
    


    Now, while on other platforms the golang toolchain supports the direct creation of a shared object with the build flag -buildmode=c-shared, this is entirely unsupported on AIX at the time of writing. However we can create a static library out of it with -buildmode=c-archive and have that linked with gcc into a shared object.

    I can compile that with

    go build -v -buildmode=c-archive -mod vendor -o /home/myuser/workspace/go_proj/sharedLibTest/sharedLibTest.a /home/myuser/workspace/go_proj/sharedLibTest/sharedLibTest.go

    This successfully creates the sharedLibTest.a file. 
    Because the symbols MyPackage_Init and MyPackage_Create are not exported by default in AIX, I need to manually create an extra symbol file to pass to my gcc compiler to incorporate the exportable symbols with:

    $ cat > file.exp << EOF
    > MyPackage_Init
    > MyPackage_Create
    > EOF

    Source (If there are any ideas how i can omit this file.exp step I'd really appreciate it)

    Now with that I can compile a shared object out of that by running

    gcc -g -O2 -mcpu=power7 -maix64 -shared -lpthread -Wl,-bE:file.exp -o libsharedLibTest.so -Wl,-bnoobjreorder ./sharedLibTest.a


    Because AIX supposedly does not look for .so files but only .a files even if they are shared libraries, I tried appending that .so file to an archive file.

    ar -X64 r libsharedLibTest.a libsharedLibTest.so


    Lastly I want to compile my C applications with

    gcc -L/home/myuser/workspace/go_proj/sharedLibTest -g -O2 -mcpu=power7 -maix64 -Wl,-bnoobjreorder -lsharedLibTest -lpthreads main.c 
    



    This succeeds and I get my a.out file as a result. However, when I try to run this with the following, I only get the error below:

    LD_LIBRARY_PATH=/home/myuser/workspace/go_proj/sharedLibTest ./a.out
    
    $ ./a.out 
    exec(): 0509-036 Cannot load program ./a.out because of the following errors:
            0509-150   Dependent module /home/myuser/workspace/go_proj/sharedLibTest/libsharedLibTest.a(libsharedLibTest.so) could not be loaded.
            0509-187 The local-exec model was used for thread-local
                       storage, but the module is not the main program.
            0509-193 Examine the .loader section header with the
                     'dump -Hv' command.


    Some hours of googling so far have lead me to believe that the .so file created by golang is in fact position dependent code that fails to be usable as a dynamically loaded object because it is expected to be statically linked into some final binary. Using the -fPIC compile option should apparently fix this, however adding the flag to any of the above compilation steps has made no difference whatsoever, all leading to the same error message. 

    Clearly I need to add some compile option to tell the shared object not to use thread-local storage, however I am unclear how or what I am missing or whether I am invoking especially go build correctly or not. 

    Any help would be appreciated.
    Cheers,
    Chris



  • 2.  RE: C linkable shared library created out of a golang project on AIX 7.2 fails to run with error "The local-exec model was used for thread-local storage, but the module is not the main program."

    Posted Wed March 23, 2022 04:27 AM
    Hi Chris,

    as far as I remember Google Go on AIX doesn't support creating shared libraries (but may be I wrong and something changed meanwhile). Another problem with Google Go on AIX is that it requires POWER8 and you compile your C code to POWER7.

    I would suggest, that you try:
    - recompiling your code to POWER8
    - using gcc-go instead of Google Go

    I hope it will help you.

    ------------------------------
    Andrey Klyachkin

    https://www.power-devops.com
    ------------------------------



  • 3.  RE: C linkable shared library created out of a golang project on AIX 7.2 fails to run with error "The local-exec model was used for thread-local storage, but the module is not the main program."

    Posted Wed March 23, 2022 09:18 AM
    Edited by Miecc KN Wed March 23, 2022 09:18 AM

    I am currently awaiting the installation of gcc-go on our development machine. In the meantime I have tried to understand how one can create a shared library out of the go code. On my local machine e.g. I cannot simply pass the same .go file from my original post as the meta package "C" can already not be parsed. If I remove this, and the comment sections, how would I go about producing an appropriate .h header to import that mirrors the "Public API" of my library.
    I saw several posts about how passing the compiler to go build with -compiler=gccgo and then pass any relevant build flags with -gccgoflags, but I am a bit unclear how that invocation would look in my scenario. Would it be something along the lines of this?

    go build -compiler=gccgo -buildmode=c-archive -gccgoflags="-g -O2 -mcpu=power8 -maix64 -fPIC -lpthread -Wl,-bnoobjreorder" -mod vendor -o sharedLibTest.a sharedLibTest.go


    ------------------------------
    Miecc KN
    ------------------------------