golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.97k stars 17.67k forks source link

Building Golang shared library using gccgo on AIX 7.1 and calling the library from a C client. #48670

Closed apm-opentt closed 3 years ago

apm-opentt commented 3 years ago

What version of Go are you using (go version)?

$ go version
go version go1.10.3 gccgo (GCC) 8.5.0 aix/ppc

http://www.bullfreeware.com/pkg?id=7266

Does this issue reproduce with the latest release?

This is the only version for AIX 7.1

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GOARCH="ppc"
GOBIN=""
GOCACHE="/.cache/go-build"
GOEXE=""
GOHOSTARCH="ppc"
GOHOSTOS="aix"
GOOS="aix"
GOPATH="/go"
GORACE=""
GOROOT="/opt/freeware"
GOTMPDIR=""
GOTOOLDIR="/opt/freeware/libexec/gcc/powerpc-ibm-aix7.1.0.0/8"
GCCGO="/opt/freeware/bin/gccgo-8"
CC="gcc-8"
CXX="g++-8"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build571393472=/tmp/go-build -gno-record-gcc-switches -funwind-tables"

What did you do?

I want to create a shared object library on AIX 7.1 by following the instructions in this article: https://medium.com/learning-the-go-programming-language/calling-go-functions-from-other-languages-4c7d8bcc69bf I am trying to compile this file into a shared library: https://github.com/vladimirvivien/go-cshared-examples/blob/master/awesome.go Here is the command I used:

go build -v -compiler=gccgo -gccgoflags="-lgcc_s -lpthread" -o awesome.so -buildmode=c-shared awesome.go

What did you expect to see?

I expect the shared library awesome.so created.

What did you see instead?

I got ERROR: Undefined symbol: __gcc_unwind_dbase. Here is the full output:

# go build -v -compiler=gccgo -gccgoflags="-lgcc_s -lpthread" -o awesome.so -buildmode=c-shared awesome.go
command-line-arguments
# command-line-arguments
ld: 0711-224 WARNING: Duplicate symbol: .__divdi3
ld: 0711-224 WARNING: Duplicate symbol: .__moddi3
ld: 0711-224 WARNING: Duplicate symbol: .__divmoddi4
ld: 0711-224 WARNING: Duplicate symbol: .__udivdi3
ld: 0711-224 WARNING: Duplicate symbol: .__umoddi3
ld: 0711-224 WARNING: Duplicate symbol: .__udivmoddi4
ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information.
ld: 0711-317 ERROR: Undefined symbol: __gcc_unwind_dbase
collect2: error: ld returned 8 exit status

I also try use -L, but I got the same error

go build -v -compiler=gccgo -gccgoflags="-L/opt/freeware/lib -lgcc_s -lpthread" -o awesome.so -buildmode=c-shared awesome.go

Hi @Helflym, I read your article https://techchannel.com/IT-Strategy/09/2019/get-started-with-go. Any idea on how I can resolve this issue? Thanks!

apm-opentt commented 3 years ago

Thanks @cherrymui, I tried using -static-libgcc, but unfortunately it did not work.

# go build -v -compiler=gccgo -gccgoflags="-static-libgcc -lpthread" -o awesome.so -buildmode=c-shared awesome.go
command-line-arguments
# command-line-arguments
ld: 0711-224 WARNING: Duplicate symbol: .__divdi3
ld: 0711-224 WARNING: Duplicate symbol: .__moddi3
ld: 0711-224 WARNING: Duplicate symbol: .__divmoddi4
ld: 0711-224 WARNING: Duplicate symbol: .__udivdi3
ld: 0711-224 WARNING: Duplicate symbol: .__umoddi3
ld: 0711-224 WARNING: Duplicate symbol: .__udivmoddi4
ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information.
ld: 0711-317 ERROR: Undefined symbol: __gcc_unwind_dbase
collect2: error: ld returned 8 exit status
cherrymui commented 3 years ago

Maybe try adding -gccgoflags=-v to see what flags are passed to ld. What happens if you remove -lpthread ?

apm-opentt commented 3 years ago

@cherrymui here is the -v output:

# go build -v -compiler=gccgo -gccgoflags="-v -static-libgcc -lpthread" -o awesome.so -buildmode=c-shared awesome.go
command-line-arguments
# command-line-arguments
Using built-in specs.
COLLECT_GCC=/opt/freeware/bin/gccgo-8
Target: powerpc-ibm-aix7.1.0.0
Configured with: ../gcc-8.5.0/configure --prefix=/opt/freeware --mandir=/opt/freeware/man --infodir=/opt/freeware/info --with-local-prefix=/opt/freeware --with-as=/usr/bin/as --with-ld=/usr/bin/ld --enable-languages=c,c++,fortran,go --enable-version-specific-runtime-libs --disable-nls --disable-libstdcxx-pch --disable-werror --enable-libstdcxx-filesystem-ts --with-gcc-major-version-only --program-suffix=-8 --disable-rpath --host=powerpc-ibm-aix7.1.0.0
Thread model: aix
gcc version 8.5.0 (GCC) 
COLLECT_GCC_OPTIONS='-c' '-g' '-fdebug-prefix-map=/tmp/go-build705049154=/tmp/go-build' '-gno-record-gcc-switches' '-fgo-relative-import-path=_/albert/example' '-o' '/tmp/go-build705049154/b001/_go_.o' '-fPIC' '-I' '/tmp/go-build705049154/b001/_importcfgroot_' '-v' '-static-libgcc'
 /opt/freeware/libexec/gcc/powerpc-ibm-aix7.1.0.0/8/go1 $WORK/b001/_cgo_gotypes.go $WORK/b001/awesome.cgo1.go -quiet -dumpbase _cgo_gotypes.go -auxbase-strip $WORK/b001/_go_.o -g -gno-record-gcc-switches -version -fdebug-prefix-map=/tmp/go-build705049154=/tmp/go-build -fgo-relative-import-path=_/albert/example -fPIC -I $WORK/b001/_importcfgroot_ -L/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8 -L/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/../../.. -o /tmp//cc3jxkXj.s
GNU Go (GCC) version 8.5.0 (powerpc-ibm-aix7.1.0.0)
        compiled by GNU C version 8.5.0, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version none
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
GNU Go (GCC) version 8.5.0 (powerpc-ibm-aix7.1.0.0)
        compiled by GNU C version 8.5.0, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version none
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
COLLECT_GCC_OPTIONS='-c' '-g' '-fdebug-prefix-map=/tmp/go-build705049154=/tmp/go-build' '-gno-record-gcc-switches' '-fgo-relative-import-path=_/albert/example' '-o' '/tmp/go-build705049154/b001/_go_.o' '-fPIC' '-I' '/tmp/go-build705049154/b001/_importcfgroot_' '-v' '-static-libgcc'
 /usr/bin/as -u -mpwr4 -many -o $WORK/b001/_go_.o /tmp//cc3jxkXj.s
COMPILER_PATH=/opt/freeware/libexec/gcc/powerpc-ibm-aix7.1.0.0/8/:/opt/freeware/libexec/gcc/powerpc-ibm-aix7.1.0.0/8/:/opt/freeware/libexec/gcc/powerpc-ibm-aix7.1.0.0/:/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/:/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/
LIBRARY_PATH=/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/:/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-c' '-g' '-fdebug-prefix-map=/tmp/go-build705049154=/tmp/go-build' '-gno-record-gcc-switches' '-fgo-relative-import-path=_/albert/example' '-o' '/tmp/go-build705049154/b001/_go_.o' '-fPIC' '-I' '/tmp/go-build705049154/b001/_importcfgroot_' '-v' '-static-libgcc'
# command-line-arguments
Using built-in specs.
COLLECT_GCC=/opt/freeware/bin/gccgo-8
COLLECT_LTO_WRAPPER=/opt/freeware/libexec/gcc/powerpc-ibm-aix7.1.0.0/8/lto-wrapper
Target: powerpc-ibm-aix7.1.0.0
Configured with: ../gcc-8.5.0/configure --prefix=/opt/freeware --mandir=/opt/freeware/man --infodir=/opt/freeware/info --with-local-prefix=/opt/freeware --with-as=/usr/bin/as --with-ld=/usr/bin/ld --enable-languages=c,c++,fortran,go --enable-version-specific-runtime-libs --disable-nls --disable-libstdcxx-pch --disable-werror --enable-libstdcxx-filesystem-ts --with-gcc-major-version-only --program-suffix=-8 --disable-rpath --host=powerpc-ibm-aix7.1.0.0
Thread model: aix
gcc version 8.5.0 (GCC) 
COMPILER_PATH=/opt/freeware/libexec/gcc/powerpc-ibm-aix7.1.0.0/8/:/opt/freeware/libexec/gcc/powerpc-ibm-aix7.1.0.0/8/:/opt/freeware/libexec/gcc/powerpc-ibm-aix7.1.0.0/:/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/:/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/
LIBRARY_PATH=/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/:/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-o' '/tmp/go-build705049154/b001/exe/a.out' '-shared' '-nostdlib' '-fPIC' '-v' '-static-libgcc'
 /opt/freeware/libexec/gcc/powerpc-ibm-aix7.1.0.0/8/collect2 -L/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8 -L/opt/freeware/lib/gcc/.. -lgo -bpT:0x10000000 -bpD:0x20000000 -btextro -bM:SRE -bnoentry -o $WORK/b001/exe/a.out -L/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8 -L/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/../../.. $WORK/b001/_pkg1_.a -lgolibbegin -lgo -lgcc_s -lgcc -lc -lgcc -lpthread
ld: 0711-224 WARNING: Duplicate symbol: .__divdi3
ld: 0711-224 WARNING: Duplicate symbol: .__moddi3
ld: 0711-224 WARNING: Duplicate symbol: .__divmoddi4
ld: 0711-224 WARNING: Duplicate symbol: .__udivdi3
ld: 0711-224 WARNING: Duplicate symbol: .__umoddi3
ld: 0711-224 WARNING: Duplicate symbol: .__udivmoddi4
ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information.
ld: 0711-317 ERROR: Undefined symbol: __gcc_unwind_dbase
collect2: error: ld returned 8 exit status
ianlancetaylor commented 3 years ago

Are you able to create a shared library that contains just C code?

apm-opentt commented 3 years ago

Hi @ianlancetaylor, I followed the steps in this article to create a shared library using just C code. https://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html. The steps worked perfectly on a x86_64 system. However, on the AIX 7.1 env, compiling the shared library worked but linking the shared lib with main.c failed

# gcc -c -Wall -Werror -fpic foo.c
# ls
foo.c   foo.h   foo.o   main.c
# gcc -shared -o libfoo.so foo.o
# ls
foo.c      foo.h      foo.o      libfoo.so  main.c
# gcc -v -L`pwd` -Wall -o test main.c -lfoo
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/opt/freeware/libexec/gcc/powerpc-ibm-aix7.1.0.0/8/lto-wrapper
Target: powerpc-ibm-aix7.1.0.0
Configured with: ../gcc-8.5.0/configure --prefix=/opt/freeware --mandir=/opt/freeware/man --infodir=/opt/freeware/info --with-local-prefix=/opt/freeware --with-as=/usr/bin/as --with-ld=/usr/bin/ld --enable-languages=c,c++,fortran,go --enable-version-specific-runtime-libs --disable-nls --disable-libstdcxx-pch --disable-werror --enable-libstdcxx-filesystem-ts --with-gcc-major-version-only --program-suffix=-8 --disable-rpath --host=powerpc-ibm-aix7.1.0.0
Thread model: aix
gcc version 8.5.0 (GCC) 
COLLECT_GCC_OPTIONS='-v' '-L/alberttest' '-Wall' '-o' 'test'
 /opt/freeware/libexec/gcc/powerpc-ibm-aix7.1.0.0/8/cc1 -quiet -v main.c -quiet -dumpbase main.c -auxbase main -Wall -version -o /tmp//cc9qjX4S.s
GNU C17 (GCC) version 8.5.0 (powerpc-ibm-aix7.1.0.0)
        compiled by GNU C version 8.5.0, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version none
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/../../../../powerpc-ibm-aix7.1.0.0/include"
#include "..." search starts here:
#include <...> search starts here:
 /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/include
 /opt/freeware/include
 /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/include-fixed
 /usr/include
End of search list.
GNU C17 (GCC) version 8.5.0 (powerpc-ibm-aix7.1.0.0)
        compiled by GNU C version 8.5.0, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version none
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 67c6592e8f7e62299ec2b7b090ae8741
COLLECT_GCC_OPTIONS='-v' '-L/alberttest' '-Wall' '-o' 'test'
 /usr/bin/as -u -mpwr4 -many -o /tmp//cc4tcfYD.o /tmp//cc9qjX4S.s
COMPILER_PATH=/opt/freeware/libexec/gcc/powerpc-ibm-aix7.1.0.0/8/:/opt/freeware/libexec/gcc/powerpc-ibm-aix7.1.0.0/8/:/opt/freeware/libexec/gcc/powerpc-ibm-aix7.1.0.0/:/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/:/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/
LIBRARY_PATH=/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/:/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-L/alberttest' '-Wall' '-o' 'test'
 /opt/freeware/libexec/gcc/powerpc-ibm-aix7.1.0.0/8/collect2 -bpT:0x10000000 -bpD:0x20000000 -btextro -o test /lib/crt0.o /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/crtcxa.o /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/crtdbase.o -L/alberttest -L/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8 -L/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/../../.. /tmp//cc4tcfYD.o -lfoo /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/libgcc.a /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/libgcc_eh.a -lc -L/opt/freeware/lib /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/libgcc.a /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/libgcc_eh.a
ld: 0706-006 Cannot find or open library file: -l foo
        ld:open(): A file or directory in the path name does not exist.
collect2: error: ld returned 255 exit status

Some how ld:open() could not open the file even though it is right there. Is this a gcc install or gcc binary issue?

ianlancetaylor commented 3 years ago

I'm sorry, I don't know where the issue is. AIX is unlike other Unix systems in several ways.

Helflym commented 3 years ago

Hi @apm-opentt,

On AIX, shared libraries must be archives and not standalone shared objects. That's why your C example doesn't work. The linker when seeing -lfoo, will search for libfoo.a and not libfoo.so. Thus, you have to add your shared object in an archive first:

# ar -X32_64 q libfoo.a libfoo.so
ar: creating an archive file libfoo.a

For the main subject of this issue, the main problem is that c-shared buildmode isn't fully supported. Thus, it seems that some objects are missing when the linker is called. With a C shared library, two object files are being added crtdbase.o and crtcxa_s.o.

# gcc -shared -o libfoo.so foo.c -fpic -v -maix64
/opt/freeware/libexec/gcc/powerpc-ibm-aix7.2.0.0/8/collect2 ... -b64 -o libfoo.so \ 
/opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/ppc64/crtcxa_s.o \
/opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/ppc64/crtdbase.o ...

I have no idea why they aren't added by gccgo when using c-shared. But a workaround for that is to manually add them within gccgoflags.

# go build -v -compiler=gccgo -gccgoflags="-pthread -v -maix64 /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/ppc64/crtcxa_s.o /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/ppc64/crtdbase.o -lpthread" -o awesome.so -buildmode=c-shared awesome.go 

This command should work fine.

Note that even if it seems to work without it, you should add -maix64 and -pthread to gccgoflags too. The reason for -maix64 is that, by default, go command will want to create 64bit objects while gcc is still 32bit by default. For -pthread is just that it should always be passed for a program using threads on AIX. -lpthread is not enough most of the time (and it should normally be added by -pthread directly but that's not the case here for an whatever reason...).

apm-opentt commented 3 years ago

Thank you so much @Helflym! I ran your command (I changed 7.2 to 7.1 in the path since I have 7.1). Unfortunately, It still didn't build the .so file. Looks like linking issues with the wrong object mode? I am new to AIX, how can I fix this?

go build -v -compiler=gccgo -gccgoflags="-pthread -v -maix64 /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/ppc64/crtcxa_s.o /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/ppc64/crtdbase.o -lpthread" -o awesome.so -buildmode=c-shared awesome.go
command-line-arguments
# command-line-arguments
Using built-in specs.
COLLECT_GCC=/opt/freeware/bin/gccgo-8
Target: powerpc-ibm-aix7.1.0.0
Configured with: ../gcc-8.5.0/configure --prefix=/opt/freeware --mandir=/opt/freeware/man --infodir=/opt/freeware/info --with-local-prefix=/opt/freeware --with-as=/usr/bin/as --with-ld=/usr/bin/ld --enable-languages=c,c++,fortran,go --enable-version-specific-runtime-libs --disable-nls --disable-libstdcxx-pch --disable-werror --enable-libstdcxx-filesystem-ts --with-gcc-major-version-only --program-suffix=-8 --disable-rpath --host=powerpc-ibm-aix7.1.0.0
Thread model: aix
gcc version 8.5.0 (GCC) 
COLLECT_GCC_OPTIONS='-c' '-g' '-fdebug-prefix-map=/tmp/go-build217710626=/tmp/go-build' '-gno-record-gcc-switches' '-fgo-relative-import-path=_/albert/example' '-o' '/tmp/go-build217710626/b001/_go_.o' '-fPIC' '-I' '/tmp/go-build217710626/b001/_importcfgroot_' '-pthread' '-v' '-maix64' '-shared-libgcc'
 /opt/freeware/libexec/gcc/powerpc-ibm-aix7.1.0.0/8/go1 $WORK/b001/_cgo_gotypes.go $WORK/b001/awesome.cgo1.go -quiet -dumpbase _cgo_gotypes.go -maix64 -auxbase-strip $WORK/b001/_go_.o -g -gno-record-gcc-switches -version -fdebug-prefix-map=/tmp/go-build217710626=/tmp/go-build -fgo-relative-import-path=_/albert/example -fPIC -I $WORK/b001/_importcfgroot_ -L/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/pthread/ppc64 -L/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/../../../pthread/ppc64 -L/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8 -L/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/../../.. -o /tmp//ccN1LIip.s
GNU Go (GCC) version 8.5.0 (powerpc-ibm-aix7.1.0.0)
        compiled by GNU C version 8.5.0, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version none
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
GNU Go (GCC) version 8.5.0 (powerpc-ibm-aix7.1.0.0)
        compiled by GNU C version 8.5.0, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version none
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
COLLECT_GCC_OPTIONS='-c' '-g' '-fdebug-prefix-map=/tmp/go-build217710626=/tmp/go-build' '-gno-record-gcc-switches' '-fgo-relative-import-path=_/albert/example' '-o' '/tmp/go-build217710626/b001/_go_.o' '-fPIC' '-I' '/tmp/go-build217710626/b001/_importcfgroot_' '-pthread' '-v' '-maix64' '-shared-libgcc'
 /usr/bin/as -u -a64 -mppc64 -many -o $WORK/b001/_go_.o /tmp//ccN1LIip.s
COMPILER_PATH=/opt/freeware/libexec/gcc/powerpc-ibm-aix7.1.0.0/8/:/opt/freeware/libexec/gcc/powerpc-ibm-aix7.1.0.0/8/:/opt/freeware/libexec/gcc/powerpc-ibm-aix7.1.0.0/:/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/:/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/
LIBRARY_PATH=/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/pthread/ppc64/:/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/../../../pthread/ppc64/:/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/:/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-c' '-g' '-fdebug-prefix-map=/tmp/go-build217710626=/tmp/go-build' '-gno-record-gcc-switches' '-fgo-relative-import-path=_/albert/example' '-o' '/tmp/go-build217710626/b001/_go_.o' '-fPIC' '-I' '/tmp/go-build217710626/b001/_importcfgroot_' '-pthread' '-v' '-maix64' '-shared-libgcc'
gccgo-8: warning: /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/ppc64/crtcxa_s.o: linker input file unused because linking not done
gccgo-8: warning: /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/ppc64/crtdbase.o: linker input file unused because linking not done
# command-line-arguments
ar: 0707-126 $WORK/b001/_go_.o is not valid with the current object file mode.
        Use the -X option to specify the desired object mode.
apm-opentt commented 3 years ago

I was able to overcome the problem above by setting these environment variables: export OBJECT_MODE=64 export GOARCH=ppc64 export CGO_ENABLED=1 The awesome.so and awesome.h files were created. I then created the archive .a file ar -X64 r libawesome.a awesome.so The next step is to compile the C client that use the shared library. client.c However, compiling the client.c failed with Undefined symbols for the functions in the awesome.h file. Hi @Helflym any idea how to fix this problem?

gcc -maix64 -L`pwd` -Wall -Werror -o client client.c -Wl,-b64,-bnoobjreorder,-bloadmap:loadmapfile,-bnoquiet
(ld): setopt 64
(ld): halt 4
(ld): setopt r/o->w 
(ld): setfflag 4
(ld): setopt reorder:by_address
(ld): savename client
(ld): filelist 7 1
(ld): i /lib/crt0_64.o
(ld): i /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/ppc64/crtcxa.o
(ld): i /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/ppc64/crtdbase.o
(ld): i /tmp//cciE7Mbn.o
(ld): i /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/ppc64/libgcc.a
(ld): i /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/ppc64/libgcc_eh.a
(ld): lib /usr/lib/libc.a
LIBRARY: Shared object libc.a[shr_64.o]: 3120 symbols imported.
LIBRARY: Shared object libc.a[posix_aio_64.o]: 20 symbols imported.
LIBRARY: Shared object libc.a[aio_64.o]: 18 symbols imported.
LIBRARY: Shared object libc.a[pse_64.o]: 8 symbols imported.
LIBRARY: Shared object libc.a[dl_64.o]: 4 symbols imported.
LIBRARY: Shared object libc.a[pty_64.o]: 1 symbols imported.
LIBRARY: Shared object libc.a[cthread_64.o]: 25 symbols imported.
LIBRARY: Shared object libc.a[uchar_64.o]: 4 symbols imported.
FILELIST: Number of previously inserted files processed: 7
(ld): resolve
RESOLVE: 42 of 4901 symbols were kept.
(ld): addgl /usr/lib/glink64.o
ADDGL: Glink code added for 6 symbols.
(ld): er full
ld: 0711-318 ERROR: Undefined symbols were found.
        The following symbols are in error:
 Symbol                    Inpndx  TY CL Source-File(Object-File) OR Import-File{Shared-object}
                              RLD: Address  Section  Rld-type Referencing Symbol
 ----------------------------------------------------------------------------------------------
 .Add                      [2]     ER PR client.c(/tmp//cciE7Mbn.o)
                                   0000002c .text    R_RBR    [14]    .main
 .Cosine                   [6]     ER PR client.c(/tmp//cciE7Mbn.o)
                                   00000054 .text    R_RBR    [14]    .main
 .Sort                     [8]     ER PR client.c(/tmp//cciE7Mbn.o)
                                   000000ec .text    R_RBR    [14]    .main
 .Log                      [10]    ER PR client.c(/tmp//cciE7Mbn.o)
                                   00000160 .text    R_RBR    [14]    .main
ER: The return code is 8.
ld: 0711-317 ERROR: Undefined symbol: .Add
ld: 0711-317 ERROR: Undefined symbol: .Cosine
ld: 0711-317 ERROR: Undefined symbol: .Sort
ld: 0711-317 ERROR: Undefined symbol: .Log
collect2: error: ld returned 8 exit status
# gcc -maix64 -L. -Wall -Werror -o client client.c -Wl,-b64,-bnoobjreorder,-bnoquiet
(ld): setopt 64
(ld): halt 4
(ld): setopt r/o->w 
(ld): setfflag 4
(ld): setopt reorder:by_address
(ld): savename client
(ld): filelist 7 1
(ld): i /lib/crt0_64.o
(ld): i /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/ppc64/crtcxa.o
(ld): i /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/ppc64/crtdbase.o
(ld): i /tmp//cc242zbu.o
(ld): i /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/ppc64/libgcc.a
(ld): i /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/8/ppc64/libgcc_eh.a
(ld): lib /usr/lib/libc.a
LIBRARY: Shared object libc.a[shr_64.o]: 3120 symbols imported.
LIBRARY: Shared object libc.a[posix_aio_64.o]: 20 symbols imported.
LIBRARY: Shared object libc.a[aio_64.o]: 18 symbols imported.
LIBRARY: Shared object libc.a[pse_64.o]: 8 symbols imported.
LIBRARY: Shared object libc.a[dl_64.o]: 4 symbols imported.
LIBRARY: Shared object libc.a[pty_64.o]: 1 symbols imported.
LIBRARY: Shared object libc.a[cthread_64.o]: 25 symbols imported.
LIBRARY: Shared object libc.a[uchar_64.o]: 4 symbols imported.
FILELIST: Number of previously inserted files processed: 7
(ld): resolve
RESOLVE: 42 of 4901 symbols were kept.
(ld): addgl /usr/lib/glink64.o
ADDGL: Glink code added for 6 symbols.
(ld): er full
ld: 0711-318 ERROR: Undefined symbols were found.
        The following symbols are in error:
 Symbol                    Inpndx  TY CL Source-File(Object-File) OR Import-File{Shared-object}
                              RLD: Address  Section  Rld-type Referencing Symbol
 ----------------------------------------------------------------------------------------------
 .Add                      [2]     ER PR client.c(/tmp//cc242zbu.o)
                                   0000002c .text    R_RBR    [14]    .main
 .Cosine                   [6]     ER PR client.c(/tmp//cc242zbu.o)
                                   00000054 .text    R_RBR    [14]    .main
 .Sort                     [8]     ER PR client.c(/tmp//cc242zbu.o)
                                   000000ec .text    R_RBR    [14]    .main
 .Log                      [10]    ER PR client.c(/tmp//cc242zbu.o)
                                   00000160 .text    R_RBR    [14]    .main
ER: The return code is 8.
ld: 0711-317 ERROR: Undefined symbol: .Add
ld: 0711-317 ERROR: Undefined symbol: .Cosine
ld: 0711-317 ERROR: Undefined symbol: .Sort
ld: 0711-317 ERROR: Undefined symbol: .Log
collect2: error: ld returned 8 exit status
# 

I can see the symbols in the awesome.so file with nm command:

nm -X64 awesome.so|grep " T "
.Add                 T   268446464         108
.Cosine              T   268446576          92
.Log                 T   268446896         116
.LogPtr              T   268447024         100
.Sort                T   268446672         104
.SortPtr             T   268446784         104
._Errno              T   268448792

Here is the output of the file command:

file awesome.so
awesome.so: 64-bit XCOFF executable or object module not stripped

file libawesome.a
libawesome.a: archive (big format)

Here is the generated awesome.h file. I don't know why client.c could not compile.

cat awesome.h
/* Created by "go tool cgo" - DO NOT EDIT. */

/* package command-line-arguments */

#line 1 "cgo-builtin-prolog"

#include  /* for ptrdiff_t below */

#ifndef GO_CGO_EXPORT_PROLOGUE_H
#define GO_CGO_EXPORT_PROLOGUE_H

typedef struct { const char *p; ptrdiff_t n; } _GoString_;

#endif

/* Start of preamble from import "C" comments.  */

/* End of preamble from import "C" comments.  */

/* Start of boilerplate cgo prologue.  */
#line 1 "cgo-gcc-export-header-prolog"

#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H

typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt64 GoInt;
typedef GoUint64 GoUint;
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;

/*
  static assertion to make sure the file is being used on architecture
  at least with matching size of GoInt.
*/
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];

typedef _GoString_ GoString;
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;

#endif

/* End of boilerplate cgo prologue.  */

#ifdef __cplusplus
extern "C" {
#endif

extern GoInt Add(GoInt p0, GoInt p1);
extern GoFloat64 Cosine(GoFloat64 p0);
extern void Sort(GoSlice p0);
extern void SortPtr(GoSlice* p0);
extern GoInt Log(GoString p0);
extern GoInt LogPtr(GoString* p0);

#ifdef __cplusplus
}
#endif
# 
Helflym commented 3 years ago

AIX is really different than Linux regarding shared libraries. One must export symbols he wants to use from this library whereas on Linux everything is exported by default.

Thus, in your case, you need to create an export file:

$ cat > file.exp << EOF 
Add
Cosine
Sort
Log
EOF

And tell the linker to use it when creating awesome.so with -Wl,-bE:file.exp.

You should normally be able to see them exported, afterward.

$ dump -X64 -Tv awesome.so
...
[112]   0x20000e00    .data      EXP     DS   Ldef        [noIMid] Add
[113]   0x20000e18    .data      EXP     DS   Ldef        [noIMid] Cosine
[114]   0x20000e30    .data      EXP     DS   Ldef        [noIMid] Sort
[115]   0x20000e48    .data      EXP     DS   Ldef        [noIMid] Log

However, I've tried to go further. But as I was expecting it, c-shared buildmode isn't supported by gccgo either. libgo.a is searching for symbols in the main program which aren't being created when this main program comes up from a C file. You'll end up having this error:

$ ./client
Could not load program client:
Symbol resolution failed for /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/10/ppc64/libgo.a[libgo.so.16] because:
        Symbol __go_init_main (number 234) is not exported from dependent
          module client.
        Symbol main.main (number 235) is not exported from dependent
          module client.
        Symbol _etext (number 236) is not exported from dependent
          module client.
        Symbol _edata (number 237) is not exported from dependent
          module client.
Examine .loader section symbols with the 'dump -Tv' command.

These symbols are created by Go programs and not C programs. I don't know if it's possible to create stub of these symbols in client.c to trick libgo.a thinking they are defined.

apm-opentt commented 3 years ago

Thank you @Helflym for confirming -buildmode=c-shared is not supported on AIX. I will use -buildmode=c-archive method shown in your article Get Started With Go Language on AIX. I used these steps to successfully build the shared library, compile client.c and ran the binary a.out.

  1. Set env export OBJECT_MODE=64 export GOARCH=ppc64 export CGO_ENABLED=1
  2. Compile shared library for awesome.go go build -compiler gccgo -buildmode=c-archive -o awesome.a -gccgoflags="-lgo -maix64" awesome.go
  3. Add preprocessor directives and initialize go runtime in client.c as described in Get Started With Go Language on AIX.
  4. Compile client.c with static link to awesome.a gcc -maix64 -Wall -Werror client.c awesome.a -pthread -Wl,-bnoobjreorder -DGCCGO -lgo
apm-opentt commented 3 years ago

Hi @Helflym , I tried the steps above on AIX 7.2 with the latest go version go version go1.17.1 aix/ppc64 and with this gcc version:

bash-5.1# gccgo -v     
Using built-in specs.
COLLECT_GCC=gccgo
COLLECT_LTO_WRAPPER=/opt/freeware/libexec/gcc/powerpc-ibm-aix7.2.0.0/8/lto-wrapper
Target: powerpc-ibm-aix7.2.0.0
Configured with: ../gcc-8.5.0/configure --prefix=/opt/freeware --mandir=/opt/freeware/man --infodir=/opt/freeware/info --with-local-prefix=/opt/freeware --with-as=/usr/bin/as --with-ld=/usr/bin/ld --enable-languages=c,c++,fortran,go --enable-version-specific-runtime-libs --disable-nls --disable-libstdcxx-pch --disable-werror --enable-libstdcxx-filesystem-ts --with-gcc-major-version-only --program-suffix=-8 --disable-rpath --host=powerpc-ibm-aix7.2.0.0
Thread model: aix
gcc version 8.5.0 (GCC) 

On step 4 of the steps in the previous comment. I got the following link error.

bash-5.1# gcc -maix64  -Wall -Werror client.c awesome.a -pthread -Wl,-bnoobjreorder,-bnoquiet -DGCCGO -lgo -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/opt/freeware/libexec/gcc/powerpc-ibm-aix7.2.0.0/8/lto-wrapper
Target: powerpc-ibm-aix7.2.0.0
Configured with: ../gcc-8.5.0/configure --prefix=/opt/freeware --mandir=/opt/freeware/man --infodir=/opt/freeware/info --with-local-prefix=/opt/freeware --with-as=/usr/bin/as --with-ld=/usr/bin/ld --enable-languages=c,c++,fortran,go --enable-version-specific-runtime-libs --disable-nls --disable-libstdcxx-pch --disable-werror --enable-libstdcxx-filesystem-ts --with-gcc-major-version-only --program-suffix=-8 --disable-rpath --host=powerpc-ibm-aix7.2.0.0
Thread model: aix
gcc version 8.5.0 (GCC) 
COLLECT_GCC_OPTIONS='-maix64' '-Wall' '-Werror' '-pthread' '-D' 'GCCGO' '-v'
 /opt/freeware/libexec/gcc/powerpc-ibm-aix7.2.0.0/8/cc1 -quiet -v -imultilib pthread/ppc64 -D__64BIT__ -D_THREAD_SAFE -D GCCGO client.c -quiet -dumpbase client.c -maix64 -auxbase client -Wall -Werror -version -o /tmp//ccCIUHG0.s
GNU C17 (GCC) version 8.5.0 (powerpc-ibm-aix7.2.0.0)
        compiled by GNU C version 8.5.0, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version none
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=32768
ignoring nonexistent directory "/opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/../../../../powerpc-ibm-aix7.2.0.0/include"
#include "..." search starts here:
#include <...> search starts here:
 /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/include
 /opt/freeware/include
 /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/include-fixed
 /usr/include
End of search list.
GNU C17 (GCC) version 8.5.0 (powerpc-ibm-aix7.2.0.0)
        compiled by GNU C version 8.5.0, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version none
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=32768
Compiler executable checksum: 9b08317146c943df0a7a5eedb2533af9
COLLECT_GCC_OPTIONS='-maix64' '-Wall' '-Werror' '-pthread' '-D' 'GCCGO' '-v'
 /usr/bin/as -u -a64 -mppc64 -many -o /tmp//cckrwujT.o /tmp//ccCIUHG0.s
COMPILER_PATH=/opt/freeware/libexec/gcc/powerpc-ibm-aix7.2.0.0/8/:/opt/freeware/libexec/gcc/powerpc-ibm-aix7.2.0.0/8/:/opt/freeware/libexec/gcc/powerpc-ibm-aix7.2.0.0/:/opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/:/opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/
LIBRARY_PATH=/opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/pthread/ppc64/:/opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/../../../pthread/ppc64/:/opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/:/opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-maix64' '-Wall' '-Werror' '-pthread' '-D' 'GCCGO' '-v'
 /opt/freeware/libexec/gcc/powerpc-ibm-aix7.2.0.0/8/collect2 -bpT:0x10000000 -bpD:0x20000000 -btextro -b64 /lib/crt0_64.o /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/pthread/ppc64/crtcxa.o /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/pthread/ppc64/crtdbase.o -L/opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/pthread/ppc64 -L/opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/../../../pthread/ppc64 -L/opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8 -L/opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/../../.. /tmp//cckrwujT.o awesome.a -bnoobjreorder -bnoquiet -lgo /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/pthread/ppc64/libgcc.a /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/pthread/ppc64/libgcc_eh.a -lpthreads -lc -L/opt/freeware/lib /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/pthread/ppc64/libgcc.a /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/pthread/ppc64/libgcc_eh.a
(ld): setopt 64
(ld): halt 4
(ld): setopt r/o->w 
(ld): setfflag 4
(ld): setopt reorder:by_address
(ld): savename a.out
(ld): filelist 10 1
(ld): i /lib/crt0_64.o
(ld): i /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/pthread/ppc64/crtcxa.o
(ld): i /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/pthread/ppc64/crtdbase.o
(ld): i /tmp//cckrwujT.o
(ld): i awesome.a
(ld): lib /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/pthread/ppc64/libgo.a
(ld): i /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/pthread/ppc64/libgcc.a
(ld): i /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8/pthread/ppc64/libgcc_eh.a
(ld): lib /usr/lib/libpthreads.a
(ld): lib /usr/lib/libc.a
LIBRARY: Shared object libgo.a[libgo.so.13]: 42732 symbols imported.
LIBRARY: Shared object libpthreads.a[shr_xpg5_64.o]: 355 symbols imported.
LIBRARY: Shared object libc.a[shr_64.o]: 3149 symbols imported.
LIBRARY: Shared object libc.a[posix_aio_64.o]: 20 symbols imported.
LIBRARY: Shared object libc.a[aio_64.o]: 18 symbols imported.
LIBRARY: Shared object libc.a[pse_64.o]: 8 symbols imported.
LIBRARY: Shared object libc.a[dl_64.o]: 4 symbols imported.
LIBRARY: Shared object libc.a[pty_64.o]: 1 symbols imported.
LIBRARY: Shared object libc.a[cthread_64.o]: 25 symbols imported.
LIBRARY: Shared object libc.a[uchar_64.o]: 4 symbols imported.
FILELIST: Number of previously inserted files processed: 10
(ld): resolve
RESOLVE: 278 of 48321 symbols were kept.
(ld): addgl /usr/lib/glink64.o
ADDGL: Glink code added for 63 symbols.
(ld): er full
ld: 0711-318 ERROR: Undefined symbols were found.
        The following symbols are in error:
 Symbol                    Inpndx  TY CL Source-File(Object-File) OR Import-File{Shared-object}
                              RLD: Address  Section  Rld-type Referencing Symbol
 ----------------------------------------------------------------------------------------------
 .runtime.setmodinfo       [230]   ER PR /tmp/go-build2583312005/b001/_cgo_gotypes.go(awesome.a[a.out.a.o])
                                   10000a10 .text    R_RBR    [524]   .main.main..init0
ER: The return code is 8.
ld: 0711-317 ERROR: Undefined symbol: .runtime.setmodinfo
collect2: error: ld returned 8 exit status
bash-5.1# 

Running nm command on awesome.a

bash-5.1# nm -X64 awesome.a|grep setmodinfo
.runtime.setmodinfo  U           -

I saw a similar issue https://github.com/golang/go/issues/42916. Do you know how I can work around ERROR: Undefined symbol: .runtime.setmodinfo?

ianlancetaylor commented 3 years ago

The runtime.setmodinfo issue doesn't have anything to do with this issue.

The workaround for that issue is to use the go tool that comes with gccgo, not the go tool that comes with the default Go compiler.

apm-opentt commented 3 years ago

Hi @ianlancetaylor , I compiled the shared library with gccgo compiler like this on AIX 7.2 go build -compiler gccgo -buildmode=c-archive -o awesome.a -gccgoflags="-lgo -maix64" awesome.go. If this is wrong, do you mind showing me the correct command? Thank you so much.

ianlancetaylor commented 3 years ago

That is probably the right command, at least it looks plausible.

What I am saying is that there are two go commands. One that comes with the gc compiler and one that comes with the gccgo compiler. If you use the go command that comes with the gccgo compiler, you will not have the runtime.setmodinfo problem.

apm-opentt commented 3 years ago

@ianlancetaylor , compiling the go shared library works fine. However, the runtime.setmodinfo problem comes when trying to build the C client that uses the go shared library.

gcc -maix64  -Wall -Werror client.c awesome.a -pthread -Wl,-bnoobjreorder,-bnoquiet -DGCCGO -lgo -v

See detail output from this comment above.

apm-opentt commented 3 years ago

Turning off go mod seems to worked around it export GO111MODULE=off

ianlancetaylor commented 3 years ago

I understand that the error is only reported when linking the C program. It remains true that If you use the go command that comes with the gccgo compiler, you will not have the runtime.setmodinfo problem

apm-opentt commented 3 years ago

Hi @ianlancetaylor , We are already using the latest go and gccgo versions available from bullfreeware for AIX.
golang download gccgo download I mean, this is the best we can work with until the community updates the versions for AIX.

ianlancetaylor commented 3 years ago

If you do the gccgo download but not the golang download, do you get a command named "go"? If so, that is the one you should be using.

Helflym commented 3 years ago

On BullFreeware (I'm one of the maintainers behind btw), gcc-go packages providing the go command as go.gcc. Golang packages will provide it as go.golang. Normally, the go command itself is pointing to the last one you've installed.

About the gcc version, we are currently having gcc-8 by default. But its gccgo is not in a really good shape, thus I generally recommend to move to gcc-9 or higher. Maybe the runtime.setmodinfo issue comes from the fact that you're using different versions of gcc at the same time. Note that we should be moving to gcc-10 by default about next week. So it might help you.

apm-opentt commented 3 years ago

Thanks @Helflym . Is this the one we should install? gcc10-go 10.3.0-4?

Helflym commented 3 years ago

Yes. Make sur you also download gcc-10. Afterwards, it should work:

$ go.gcc-10 build -buildmode=c-archive -compiler gccgo -gccgoflags="-lgo -maix64" -o awesome_gcc.a awesome.go
$ gcc-10 -maix64 -pthread -o client_gcc awesome_gcc.a client.c -Wl,-bnoobjreorder -I. -DGCCGO -lgo -lm
$ ./client_gcc
Using awesome lib from C:
awesome.Add(12,99) = 111
awesome.Cosine(1) = 0.540302
awesome.Sort(77,12,5,99,28,23): 5,12,23,28,77,99,
Hello from C!
apm-opentt commented 3 years ago

Wonderful. Thank you so much @Helflym!

apm-opentt commented 3 years ago

Hi @Helflym, I wanted to initialize the go runtime in a bare bone C program for AIX. I will add code later to use dlopen() to manually load the go shared library.

extern void __go_init(int argc, char **argv, char** env __attribute__ ((unused)));

int main(int argc, char **argv, char **env) {
  __go_init(argc, argv, env);
}

I compile it with gcc but I got the following error. Do you know how I can get this to work?

bash-5.1# gcc -maix64 main.c -pthread -lgo
ld: 0711-317 ERROR: Undefined symbol: .__go_init
ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information.
collect2: error: ld returned 8 exit status

Thanks!

Helflym commented 3 years ago

That's because __go_init isn't defined in libgo itself but in libgolibbegin which is pulled automatically by -lgo most of the time. Here, as you don't have an Go code, AIX linker thinks that -lgo is useless and thus garbage-collect it. For initialized Go runtime in a C code without any reference to Go, I guess you have to add -lgolibbegin manually. However, I'm wondering why you want to do such things ?

apm-opentt commented 3 years ago

Hi @Helflym, Here is my scenario: We are using IBM MQ and would like to use MQ Exits mechanism to monitor the use of a queue. The MQ Exits is basically custom code that gets invoked by MQ. This custom code must be compiled as a shared library so MQ can load it dynamically. In our case, our main logic is written in Go. Our custom MQ exit is written in C and compiled as a .so file for MQ to load dynamically. To control the loading order (load MQ exit first before go share library), we have C glue code to manually load the Go shared library (i.e. dlopen(mygo.so...)). So the flow is MQ -> MQ Exit share library in C-> Glue code in C -> Go shared library. In this flow, I need to initialize the go runtime in the glue code and dlopen() to load the go library. I tried adding --lgolibbegin manually, it compiled but it could not find another symbol at runtime.

gcc -maix64 mymain.c -pthread -lgo -lgolibbegin
bash-5.1# ./a.out
exec(): 0509-036 Cannot load program a.out because of the following errors:
        0509-130 Symbol resolution failed for /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/10/pthread/ppc64/libgo.a[libgo.so.16] because:
        0509-136   Symbol __go_init_main (number 234) is not exported from
                   dependent module a.out.
        0509-136   Symbol main.main (number 235) is not exported from
                   dependent module a.out.
        0509-192 Examine .loader section symbols with the
                 'dump -Tv' command.

Do you know why __go_init_main symbol is not exported and how can I fix it? Thanks!

Helflym commented 3 years ago

Indeed, I haven't tried to launch a.out. My bad..

The solution is to create "fake" functions in C code which lure libgo to think its being loaded by a Go main program. This is dirty and might have huge side effects. But you can add the below code to your mymain.c:

void main_init() __asm__ ("__go_init_main");
void main_init() {}

void main_main() __asm__ ("main.main");
void main_main() {}

This will create the symbols wanted by libgo, which are supposed to be created by Go compiler. It seems to be enough in order to launch your testcase. But no idea if it'll be enough for your complex project.

apm-opentt commented 3 years ago

Thanks @Helflym ! Yes, when added the above code in mymain.c it does launch the go runtime. However, given that mymain.c maps to MQ in my scenario, I had move the code above to my glue code (a shared lib that invoked my mymain.c). It compiled but at runtime it gave me this error:

rtld: 0712-001 Symbol __go_init_main was referenced
      from module /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/10/pthread/ppc64/libgo.a(libgo.so.16), but a runtime definition
      of the symbol was not found.
rtld: 0712-001 Symbol main.main was referenced
      from module /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/10/pthread/ppc64/libgo.a(libgo.so.16), but a runtime definition
      of the symbol was not found.

I tried export LD_LIBRARY_PATH=/opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/10/pthread/ppc64 but it didn't help. I got the same error.

Helflym commented 3 years ago

I guess the AIX linker have garbage-collected these symbols. As there aren't referenced by any code in your shared library, if you didn't export them manually (or with -bexpall) they won't be added to the shared object. If you have an export file, you should add them otherwise you can try to add -Wl,-u__go_init_main -Wl,-umain.main (I'm not fully sure of the syntax) to the command building your shared object.

apm-opentt commented 3 years ago

Hi @Helflym , I tried adding -Wl,-u__go_init_main -Wl,-umain.main

  1. go build -buildmode=c-archive -compiler gccgo '-gccgoflags=-Wl,-u__go_init_main -Wl,-umain.main -lgo -maix64' -o libfoo.a foo.go
  2. build glue code shared library hello.c xlc_r -q64 -bE:hello.exp -bM:SRE -bnoentry -o shrsub.o hello.o -lfoo -L. -lgo -lgolibbegin -lm -L/opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/10/pthread/ppc64 -lgcc_s /opt/missing_gccgo_object/crtcxa_s.o /opt/missing_gccgo_object/crtdbase.o For some reason crtcxa_s.o and crtdbase.o were missing from gccgo version gcc version 10.3.0. I temporarily worked around it by using the copies from gcc 8.5. This step gave 2 warnings. By the way,I tried adding -Wl,-u__go_init_main -Wl,-umain.main in this step too, but it didn't help.
    ld: 0711-224 WARNING: Duplicate symbol: .__go_init_main
    ld: 0711-224 WARNING: Duplicate symbol: .main.main
    
  3. Create the glue code shared lib ar -X64 qv libsub.a shrsub.o
  4. Build main gcc -maix64 -pthread -o main main.c -L. -lsub. Running ./main returned the same error:
    exec(): 0509-036 Cannot load program main because of the following errors:
        0509-130 Symbol resolution failed for /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/10/pthread/ppc64/libgo.a[libgo.so.16] because:
        0509-136   Symbol __go_init_main (number 234) is not exported from
                   dependent module main.
        0509-136   Symbol main.main (number 235) is not exported from
                   dependent module main.
        0509-192 Examine .loader section symbols with the
                 'dump -Tv' command.
    

    I really appreciate your help so far. This is turning into a quite difficult challenge :-(

Helflym commented 3 years ago

I'm not sure I completely understand what you're trying to achieve. Can you shared me the code of shrsub.c and main.c ? I'll try to reproduce it on my VMs. However, one huge problem I'm seeing right now is that you're trying to use GccGo code with XLC. It might work but it's very unlikely. GCC and XLC aren't fully compatible.

For some reason crtcxa_s.o and crtdbase.o were missing from gccgo version gcc version 10.3.0.

crtcxa_s.o and crtdbase.o for version 10 are inside gcc10 RPM not gcc10-go. But as gcc10-go have a dependency over gcc10, they should be available. Otherwise, there is something wrong with your installation which should be fixed before anything else. Especially because there is no guarantee that crtcxa_s.o and crtdbase.o are compatible across versions.

apm-opentt commented 3 years ago

Hi @Helflym , I apologize, I stated the problem incorrectly. crtcxa_s.o and crtdbase.o are not missing in the 10.3.0 version of gcc. Instead the 32 bit version of these files were found in the ppc64 directory. I ran the file command:

bash-5.1# file /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/10/pthread/ppc64/crtdbase.o
/opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/10/pthread/ppc64/crtdbase.o: executable (RISC System/6000) or object module not stripped
bash-5.1# file /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/10/pthread/ppc64/crtcxa_s.o
/opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/10/pthread/ppc64/crtcxa_s.o: executable (RISC System/6000) or object module not stripped

I believe these file should be 64 bits, file command should produce this output: 64-bit XCOFF executable or object module not stripped The gccgo/gcc was reinstalled but those .o files are still 32 bits files.

To describe the other problems, I am using scenarios to make it easier for discussion. Scenario 0.
This is the base scenario from your article. It works with gccgo toolchain. Here are the files scenario0.tar.gz. You can run ./build.sh to build it. When I use gcc -maix64 main.c wrapper.a -pthread -Wl, -bnoobjreorder, the main hangs. I suppose this is the expected behavior for gccgo toolchain as go runtime needed to be initialized. Can we install both Golang and gccgo on the my AIX7.2? Will it be a problem if I use Golang toolchain to create the .a file then link this .a or .so file with a gccgo's gcc to compile the client? If yes, is this the version we should install? http://bullfreeware.com/pkg?id=7659

Scenario 1. In this scenario, I want to simulate scenario where IBM MQ calls MQ Exits (shared lib) calls glue code (shared lib) calls Go library. In the attached files I have MQ.c -> glue.c -> wrapper.go. The wrapper.go is built with -buildmode=c-archive. MQ.c is the main and it simulates MQ so I can't use it to initialize Go runtime. The initialization is done in glue.c. Here are my files for this scenario. scenario1.tar.gz. When you run ./build.sh, you will see ld: 0711-317 ERROR: Undefined symbol: _end

Scenario 2. In this scenario, instead of using -buildmode=c-archive to build .a Go archive, I am using -buildmode=c-shared to build Go shared library. This is needed for the glue code to load it manually. In order for -buildmode=c-shared to work, I had to include the 64 bit crtcxa_s.o and crtdbase.o files: go build -compiler=gccgo -gccgoflags="-lm -pthread -maix64 /opt/missing_gccgo_object/crtcxa_s.o /opt/missing_gccgo_object/crtdbase.o -lpthread" -o libwrapper.so -buildmode=c-shared wrapper.go Here are files where it builds the .so file then main.c tries to load it manually then invoke the Add function.
scenario2.tar.gz When you run build.sh, you will see Function not implemented (Add).

Hopefully, you can run these scenarios on your vm to reproduce the errors. Thank you so much.

Helflym commented 3 years ago

I apologize, I stated the problem incorrectly. crtcxa_s.o and crtdbase.o are not missing in the 10.3.0 version of gcc. Instead the 32 bit version of these files were found in the ppc64 directory.

That's because 64bit files are now named crtcxa_64_s.o and crtdbase_64.o. This is mandatory for the 64bit build of GCC. That's one of the reason one shouldn't add these files himself but let GCC do it. GccGo should be able to do it on its own, but this isn't the case.

Scenario 0.

You shouldn't be able to build the main without -lgo. If wrapper.a is built with gccgo with c-archive, then it's a static library. Thus, when it's being linked to main, libgo.a must be provided to it. When I'm doing gcc -maix64 main.c wrapper.a -pthread -Wl, -bnoobjreorder, I have a lot of symbols missing but that's the correct behavior for me.

Can we install both Golang and gccgo on the my AIX7.2? Will it be a problem if I use Golang toolchain to create the .a file then link this .a or .so file with a gccgo's gcc to compile the client? If yes, is this the version we should install? http://bullfreeware.com/pkg?id=7659

If your question is "can I use a wrapper.a build with Golang toolchain inside a C file ? The answer is yes. Otherwise, I'm not sure I understand the question.

function go_build() {
    echo "Building with Go."
    go build -buildmode=c-archive -o wrapper_go.a wrapper.go
    if [[ "$?" != 0 ]]; then
    echo "Building wrapper_go.a failed."
    return
    fi
    gcc -maix64 main.c wrapper_go.a -pthread  -Wl,-bnoobjreorder
    if [[ "$?" != 0 ]]; then
    echo "Building a.out failed."
    return
    fi
    ./a.out
}

This is working fine. Note that go command here is the one for Golang toolchain and that I've changed the include in main.c to be wrapper_go.h.

Scenario 1.

In this case, we end up in the same situation that I've described previously. Current libgo.a is looking for symbols in the main program (__go_init_main, main.main, etc) and because of XCOFF format, there is no way to search for these symbols in some loaded library (like libglue). The only way would be to rebuild libgo.a which will mean make it support c-shared buildmode.
Note that there is something wrong in this scenario in all cases. You're using c-archive buildmode to create code aimed for a shared library. It might work with gccgo toolchain but it's not meant to be. And that's the reason why it doesn't work with Golang toolchain. c-archive using code and maybe internal functions only meant to be run in the main program. There is no guarantee that gccgo toolchain won't doing the same too.

Scenario 2.

The Function not implemented (Add). appears because Add isn't exported by libwrapper.so. GccGo isn't able to understand by itself which functions should be exported. You'll need to provide these exported symbol in a export file and pass it with -bE:libwrapper.exp to gccgoflags. However, even with that and after adding -lgolibbegin to the gcc commands in order to find __go_init, there are still some errors. This time inside Go runtime itself which means the problems is not just some compilations failures...

I'm sorry. But you're trying by different approaches to create a c-shared Go library which isn't supported. I'm not sure any workarounds are possible on that. Using Golang toolchain, this is simply impossible: the "shared" version of some code is simply not implemented at all. Using GccGo toolchain, well as you can see there is a lot of problems even before reaching these "shared" mecanisms which might be able to be bypassed, gcc being able to create shared libraries unlike Go. However, if the runtime isn't supported it it won't be possible anyway. It would need much further investigations. You can do it if you wish. However, I don't have the time myself for now.

apm-opentt commented 3 years ago

Hi @Helflym , I understand. It looks like this is not a viable path to continue. I will consider other methods, maybe a client/server path. Thank you so much for your help. Merci beaucoup!