GHCi linking with cross-calling dynlibs fails on OSX - macos

Setting
Compiler: GHC 7.10.3
I must use two dynamic libraries (libpetsc and libslepc), one of which uses functions from the other. When linking my application, I encounter the following error, which mentions one such symbol (KSPConvergedReasons). NB. my own code does not use this symbol.
user specified .o/.so/.DLL could not be loaded
(dlopen($SLEPC_DIR/arch-darwin-c-debug/lib/libslepc.dylib, 5): Symbol
not found: _KSPConvergedReasons
Referenced from: $SLEPC_DIR/arch-darwin-c-debug/lib/libslepc.dylib
Expected in: flat namespace
in $SLEPC_DIR/arch-darwin-c-debug/lib/libslepc.dylib)
Surely enough, nm -u shows _KSPConvergedReasons as an undefined
symbol (see below).
I don't understand the reason of this behaviour since I first compile
with all the relevant PETSc and SLEPc headers and link against both
.dylibs.
NB:
The symbol in question (KSPConvergedReasons) does exist in the callee library (libpetsc):
$ nm ${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc.3.7.2.dylib | grep KSPConv
000000000110a652 T _KSPConvergedDefault
0000000001109703 T _KSPConvergedDefaultCreate
000000000110b934 T _KSPConvergedDefaultDestroy
0000000001109a96 T _KSPConvergedDefaultSetUIRNorm
000000000110a074 T _KSPConvergedDefaultSetUMIRNorm
000000000106533d T _KSPConvergedLSQR
0000000001743280 D _KSPConvergedReasons
...
Build + link sequence
Build the C code generated from my own library, which in turn uses headers from the two aforementioned libs:
gcc -c -g -w ${SRCDIR}/Internal/InlineC.c -o ${LIBDIR}/InlineC_c.o -I${PETSC_DIR_ARCH}/include -I${PETSC_DIR}/include -I${SLEPC_DIR_ARCH}/include -I${SLEPC_DIR}/include
Link :
stack exec ghci ${SRCDIR}/Spec.hs ${SRCDIR}/Internal/InlineC.hs ${LIBDIR}/InlineC_c.o -- -isrc/ -L${PETSC_DIR_ARCH}/lib -L${SLEPC_DIR_ARCH}/lib -lpetsc -lmpich -lslepc
Question
Why is this happening and how can I fix this?
Thank you in advance for any pointers,
Marco
Undefined symbols in calling dynlib :
$ nm -u libslepc.3.7.1.dylib | grep KSP
_KSPAppendOptionsPrefix
_KSPConvergedReasons
...

Related

Use --enable-stdcall-fixup to disable these warnings

I am trying to build a dll in C++ in which I use a C dll with prototypes like :
int __stdcall foo();.
When linking, the compiler outputs:
Warning: resolving _foo#0 by linking to _foo
Use --enable-stdcall-fixup to disable these warnings
so I added the option when linking, the command looks like:
g++ -std=c++0x -o fooLib.dll fooObj.o -lfooClib --enable-stdcall-fixup -shared
but seems like the g++ doesn't know this option:
g++.exe: error: unrecognized option '--enable-stdcall-fixup'
when I am adding only -enable-stdcall-fixup (one hyphen), it still shows the warnings (looks like has the option has no effect), and the ouput is kind weird:
g++ -std=c++0x -o fooLib.dll fooObj.o -lfooClib -enable-stdcall-fixup -shared
Warning: resolving _foo#0 by linking to _foo
Use --enable-stdcall-fixup to disable these warnings
Use --disable-stdcall-fixup to disable these fixups
ld.exe: warning: cannot find entry symbol nable-stdcall-fixup; defaulting to 679c1000
so does any body know what I am doing wrong ?
g++ --version
g++ (GCC) 4.6.1
Indeed, --enable-stdcall-fixup is not a g++ option. It's a linker option, and you can find it in the ld(1) manpage:
--enable-stdcall-fixup
--disable-stdcall-fixup
If the link finds a symbol that it cannot resolve, it will attempt
to do "fuzzy linking" by looking for another defined symbol that
differs only in the format of the symbol name (cdecl vs stdcall)
and will resolve that symbol by linking to the match. For example,
the undefined symbol "_foo" might be linked to the function
"_foo#12", or the undefined symbol "_bar#16" might be linked to the
function "_bar". When the linker does this, it prints a warning,
since it normally should have failed to link, but sometimes import
libraries generated from third-party dlls may need this feature to
be usable. If you specify --enable-stdcall-fixup, this feature is
fully enabled and warnings are not printed. If you specify
--disable-stdcall-fixup, this feature is disabled and such
mismatches are considered to be errors. [This option is specific
to the i386 PE targeted port of the linker]
gcc is able to recognize some common linker options and pass them on to ld. For example, gcc passes the -llibrary options used to link in library code directly to the linker, as well as an option -e which will be relevant below. Whenever this is the case, it's documented in the gcc(1) manpage.
As you've discovered, this is not the case with --enable-stdcall-fixup, so you'll need to explicitly pass it. In order to pass arbitrary options to the linker, gcc has -Wl. From gcc(1):
-Wl,option
Pass option as an option to the linker. [...]
So in your case, you would call
g++ -Wl,--enable-stdcall-fixup [...]
I don't have the version of the linker mentioned in the manpage, so it still comes up as an unrecognized option for me. But on your system, given that the linker is telling you to use the option, I can only assume it is the version that recognizes it.
As an aside, when you tried calling the option with only one dash, you ran into a red herring. You were actually invoking the -e gcc option that I mentioned above, with the option argument nable-stdcall-fixup. From gcc(1):
-e entry
--entry=entry
Specify that the program entry point is entry. The argument is
interpreted by the linker; the GNU linker accepts either a symbol
name or an address.
So you actually ended up passing an option to the linker saying that, when you execute your program, you want it to begin execution from a function named nable-stdcall-fixup instead of the usual main.

GnuCOBOL not finding routines in a lib file

I am running GnuCOBOL on Windows from command line to compile and link a COBOL program. I have been able to produce a functioning Hello World program.
The COBOL program I now want to build is quite simple, but calls routines that are available in a C library I have built using another build environment. I have exchanged some names and paths for anonymity.
The lib is called mysrc.lib, and is placed at C:\dev\foo. I compile and link with the command
cobc -x -fword-continuation=ok -ffold-call=LOWER c:\test\MULTI\cobsim.cob -o c:\test\MULTI\cobsim.EXE -LC:\dev\foo -lmysrc
It seems to find the lib file, because if I change the name of the lib file to something that doesn't exist, it complains about not finding it.
cobc -x -fword-continuation=ok -ffold-call=LOWER c:\test\MULTI\cobsim.cob -o c:\test\MULTI\cobsim.EXE -LC:\dev\foo -lmysrc2
C:\GnuCOBOL\bin/ld.exe: cannot find -lmysrc2
collect2.exe: error: ld returned 1 exit status
However, when I run the program, it cannot find the routines in mysrc. The first C routine in mysrc that is called from the program cobsim.cob is named dbadr4. When I try to run the resulting cobsim.exe, I get the following error:
libcob: module 'DBADR4' not found
I can also use the flag -fstatic-call to get the link error already when linking.
cobc -x -fword-continuation=ok -ffold-call=LOWER -fstatic-call c:\test\MULTI\cobsim.cob -o c:\test\MULTI\cobsim.EXE -LC:\dev\foo -lmysrc
.\cob14860_0.o:cob14860_0.c:(.text+0x14f): undefined reference to `dbadr4'
It doesn't seem to matter which order I place the switches and arguments. Including or excluding the -ffold-call=LOWER flag has no effect, apart from the link error complaining about not finding the routine in upper or lower case. I have multiple other programs calling these routines without problem, including C programs and this specific COBOL program compiled and linked with another compiler and linker on another platform.
Any suggestions?
EDIT: Adding requested information.
Output when adding -g -v flags (some information removed or altered for anonymity):
cobc (GnuCOBOL) 3.0-rc1.0
Built May 05 2018 21:41:43 Packaged Apr 22 2018 22:26:37 UTC
C version (MinGW) "6.3.0"
loading standard configuration file 'default.conf'
command line: cobc -x -save-temps -fword-continuation=ok -ffold-call=LOWER -fstatic-call -L C:\dev\foo -l mysrc -o C:\test\MULTI\cobsim.EXE -g -v C:\test\MULTI\cobsim.cob
preprocessing: C:\test\MULTI\cobsim.cob -> cobsim.i
return status: 0
parsing: cobsim.i (C:\test\MULTI\cobsim.cob)
return status: 0
translating: cobsim.i -> cobsim.c (C:\test\MULTI\cobsim.cob)
executing: gcc -c -I"C:\GnuCOBOL\include" -g -o "cobsim.o" "cobsim.c"
return status: 0
executing: gcc -Wl,--export-all-symbols -Wl,--enable-auto-import
-Wl,--enable-auto-image-base -o "C:\test\MULTI\cobsim.EXE"
"cobsim.o" -L"C:\GnuCOBOL\lib"
-L"C:\dev\foo" -L/mingw/lib
-lcob -lm -lgmp -L/mingw/lib -lintl -lpdcurses -l"mysrc"
cobsim.o: In function `simple_':
cobsim.c:112: undefined reference to `dbadr4'
And snippets of the program code, including the call to dbadr4:
DATA DIVISION.
WORKING-STORAGE SECTION.
01 SQL005.
05 SQL005-001 PIC X(1) VALUE " ".
01 SQLPAA.
05 SQLPAA-001 USAGE POINTER.
05 SQLPAA-002 USAGE POINTER.
05 SQLPAA-003 USAGE POINTER.
05 SQLPAA-004 USAGE POINTER.
PROCEDURE DIVISION.
MAIN SECTION.
DO-IT.
CALL "DBADR4" USING SQLPAA-001 SQL005
EDIT 2: Missed adding the DBADR4 function declaration.
void dbadr4(void** addr, const int varibl[1])
The COBOL code is originally Embedded SQL/COBOL code, the call to DBADR4 and the SQL005 and SQLPAA data blocks have been automatically generated. The dbadr4 code is originally Ada code, the C routine declaration has been automatically generated. This generated COBOL code calling this generated C code works fine on HP OpenVMS, where we use HP's COBOL compiler and linker, and has done so for many years.

I want to replace 'ld' with 'gcc' in my Makefile to link my kernel objects

In my project I have makefiles which build Solaris kernel modules, and they use gcc to compile files but use ld to link all .o files together into a kernel module. I am trying to include some coverage options like gcov (-fprofile-arcs) or tcov (-xprofile=tcov) in my build, hence I want to replace ld with gcc during linking also.
But as soon as I use replace gcc with ld, the builds start failing with lot of "undefined symbol" errors, even if I use some compile flags and get rid of these errors, the kernel module will not load into my Solaris kernel at all.
For example:
$ /usr/ccs/bin/ld -r -dy -Nstrmod/rpcmod -Nfs/nfs \
-Nmisc/rpcsec -Nmisc/klmmod -Nfs/zfs \
-o debug64/nfssrv \
debug64/nfs_server.o debug64/nfs_srv.o debug64/nfs3_srv.o \
debug64/nfs_acl_srv.o debug64/nfs_auth.o obj64/nfs41_srv.o \
obj64/ctl_ds_srv.o obj64/dserv_server.o
ld works fine but with gcc I get following errors:
/opt/gcc-4.4.4/bin/gcc -m64 -z muldefs \
-Lmod/rpcmod -Lfs/nfs -Lmisc/rpcsec \
-Lmisc/klmmod -Lfs/zfs \
-o obj64/nfssrv \
obj64/nfs_server.o obj64/nfs_srv.o obj64/nfs3_srv.o
obj64/nfs_acl_srv.o obj64/nfs_auth.o obj64/nfs41_srv.o
obj64/ctl_ds_srv.o obj64/dserv_server.o
Undefined first referenced
symbol in file
hz obj64/nfs_server.o
p0 obj64/nfs_server.o
nfs_range_set obj64/nfs41_srv.o
getf obj64/nfs_server.o
log2 obj64/nfs4_state.o
main /usr/lib/amd64/crt1.o
stoi obj64/ctl_ds_srv.o
dmu_object_alloc obj64/dserv_server.o
nvpair_name obj64/nfs4_srv.o
__dtrace_probe_nfss41__i__destroy_encap_session obj64/nfs41_srv.o
__dtrace_probe_nfssrv__i__dscp_freeing_device_entries obj64/ctl_ds_srv.o
mod_install obj64/nfs_server.o
xdr_faststatfs obj64/nfs_server.o
xdr_WRITE3res obj64/nfs_server.o
svc_pool_control obj64/nfs_server.o
Warning the option -L allows to specify a path where to search for libraries, to specify a library you want to link with you (also) have to use the option -l
So a priori you have to add the options -lrpcmod -lnfs -lrpcsec -lklmmod -lzfs
More details in GCC Linking Options
By default, the GNU linker called through the gcc compiler driver will try to create a standard executable. Consequently, if you don't tell it otherwise, ld will use its default linker script, the C startup code and it will look for a main() routine and everything else that makes a valid executable.
I'm not too familiar with Solaris, but would bet this will not be suitable to build kernel modules. I would expect kernel modules will at least require some options like -ffreestanding, -nostdlibs and most likely a non-default linker script that's probably very different from the default one used for applications.
Even if you manage to link your kernel modules this way, I seriously doubt you will be finished. The gcov instrumentation routines most likely do not expect to live within a kernel driver but expect a proper C execution environment (e.g. it will at least expect to fopen() a file to fwrite() its findings). A kernel driver, however, does not have this comfort. You'll probably find yourself confronted with the problem to get the gcov data somehow out of your kernel modules.
Not saying this is not doable, but it certainly will be a lot of work.

How to statically link a Chicken Scheme program that uses extensions?

I have need to compile and statically link a Chicken program. I expect to use many extensions, most notably http-client.
I can compile the source with the following command:
csc -compile-syntax -static linux-setup.scm
or
csc -R http-client -compile-syntax -static linux-setup.scm
But when I run it, I get the following error:
Error: (require) cannot load extension: http-client
Call history:
##sys#require <--
I have also tried (declare (uses http-client)) in the source, with no success:
linux-setup.o: In function `f_369':
/mnt/data/Documents/Programming/chicken-scheme/linux-setup/linux-setup.c:219:
undefined reference to `C_http_2dclient_toplevel'
collect2: error: ld returned 1 exit status
Error: shell command terminated with non-zero exit status 256: 'gcc' 'linux-setup.o'
-o 'linux-setup' -L"/usr/lib" -Wl,-R"/usr/lib" -static '/usr/lib/libchicken.a' -lm -ldl
Static linking is something I need. This is not an XY problem. I need my executables to run on a freshly-installed Linux system with no dependancies. This is the primary reason I switched from Common Lisp to Scheme in the first place.
What am I doing wrong, please?
Assuming your program is in a-program.scm file:
csc -deploy a-program.scm
cd a-program/
chicken-install -deploy -p $PWD http-client
...et voilĂ !
edit: turns out that the proper answer to the problem posted is solved in this document: http://www.foldling.org/scheme.html#compiling-statically-linked-chicken-scheme-programs-with-extensions

clang plugin compilation error: undefined symbols llvm::Registry<clang::PluginASTAction, llvm::RegistryTraits<clang::PluginASTAction> >

I'm trying to build llvm clang samples.
Everything works fine except the plugin_print_funcnames.cpp plugin compilation. The code is found here: plugin_print_funcnames.cpp
It seems like that the clang++ cannot find the library llvm:Registry<> is not in the llvm library.
I use llvm/clang from brew with the command brew install llvm.
What might be wrong?
This is a command line:
g++ -fpic -fno-rtti -O0 -g `/usr/local/Cellar/llvm/HEAD/bin/llvm-config --cxxflags` -I$HOME/llvm/from_git/llvm/tools/clang/include -I/usr/local/Cellar/llvm/HEAD/tools/clang/include src_clang/plugin_print_funcnames.cpp \
-shared `/usr/local/Cellar/llvm/HEAD/bin/llvm-config --ldflags --libs --system-libs` -o build/plugin_print_funcnames.so
These are part of error messages:
Undefined symbols for architecture x86_64:
"llvm::Registry<clang::PluginASTAction, llvm::RegistryTraits<clang::PluginASTAction> >::ListenerHead", referenced from:
__GLOBAL__I_a in plugin_print_funcnames-342dff.o
"llvm::Registry<clang::PluginASTAction, llvm::RegistryTraits<clang::PluginASTAction> >::Head", referenced from:
I'm sure you're long since past needing this, but I ran into a similar problem. Here's the answer to your specific question as well as the command I use to figure out the answer. Go into the llvm/clang lib directory and type:
$ nm -o *.a |grep Registry |grep PluginASTAction |cut -d ':' -f 1 |uniq
libclangFrontend.a
libclangFrontendTool.a
The -o flag to nm is very important because it tells nm to print the filename on every line, so you have context when grep finds a match.
You add the appropriate library to your link line after you find it using the technique in the answer. Then, if you get another linker error, you repeat the process. Eventually the last one goes away. For instance, in the above case, you'd add -lclangFrontend -lclangFrontendTool.
For me, it was a process of about 10 different libraries I had to find like this.
I believe the list of things I had to add was: -lclangSerialization -lclangASTMatchers -lclangSema -lclangAnalysis -lclangRewriteFrontend -lclangEdit -lclangParse -lclangFrontend -lclangBasic -lclangDriver -lclangAST -lclangLex but that was in addition to the ones from running llvm/bin/llvm-config --ldflags --libs --system-libs. This was on latest OS X at the time of writing.

Resources