gdb says "cannot open shared object file" - c++

I have one binary and one shared library.
The shared library is compiled with:
all:
g++ -g -shared -fpic $(SOURCES) -o libmisc.so
the binary is compiled with:
LIBS=-L../../misc/src
LDFLAGS=-lmisc
all:
g++ -g -o mainx $(INCLUDE) $(SOURCE) $(LIBS) $(LDFLAGS)
I set in ~/.bashrc
export LD_LIBRARY_PATH=/mnt/sda5/Programming/misc/src/
to the libmisc.so output path.
Debugging from console works fine:
gdb mainx
However from Emacs22, launching gdb fails with the following message:
Starting program: /mnt/sda5/Programming/main/src/mainx
/mnt/sda5/Programming/main/src/mainx: error while loading shared libraries: libmisc.so: cannot open shared object file: No such file or directory
This looks very tricky for the moment, and I couldn't solve it. I am not sure if this a emacs's problem, or I should pass a parameter in gdb's command line.

Emacs probably does not read your .bashrc before it invokes gdb. Try to put 'set solib-search-path' and 'set solib-absolute-path in your .gdbinit file instead

Emacs doesn't invoke gdb via bash, but rather invokes it directly, and so .bashrc changes do not take effect and LD_LIBRARY_PATH is not set.
If you quit emacs, open a new shell (so LD_LIBRARY_PATH is set), start emacs in it, and then do M-X gdb, then it would work.
Setting solib-search-path in GDB is a hack.
A much better fix is to build the executable in such a way that it doesn't need LD_LIBRARY_PATH to begin with:
LDFLAGS=-lmisc -Wl,-rpath=/mnt/sda5/Programming/misc/src

Another way is to create a .gdbinit file in your $HOME and set the LD_LIBRARY_PATH there:
# file .gdbinit
set env LD_LIBRARY_PATH=/mnt/sda5/Programming/misc/src/
This is convenient if you need to debug with that LD_LIBRARY_PATH frequently (and don't want to remember running emacs from your shell every time).

Related

Compile C++ on Windows

I'm trying to compile C++ on Windows.
The command needed to compile on Linux is:
g++ -O3 -Wall -shared -std=c++11 -fPIC `python -m pybind11 --includes` EO_functions_bipartite.cpp -o extremal_bi.so
I installed MinGW but when I try to compile I get the following error:
g++.exe: error: python: No such file or directory
g++.exe: error: pybind11: No such file or directory
g++.exe: error: unrecognized command line option '-m'
g++.exe: error: unrecognized command line option '--includes EO_functions_bipartite.cpp'
g++.exe: fatal error: no input files
compilation terminated.
Assuming you have python in your path.
The backtick escape thing that embeds the python -m pybind11 --includes command within the g++ doesn't work on cmd.exe in Windows.
Run the python -m pybind11 --includes command on its own line in the cmd shell. Take the output of that command and substitute in into the g++ command. It should be a bunch of -I include params.
So if the output of the python command is this:
-IC:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0\Include -IC:\Users\User\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\site-packages\pybind11\include
Expand your g++ command to be this:
g++ -O3 -Wall -shared -std=c++11 -fPIC "-IC:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0\Include" -IC:\Users\User\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\site-packages\pybind11\include EO_functions_bipartite.cpp -o extremal_bi.so
Notice the quotes I put around the first include directory because it has a space in its path.
The easiest way to start on native Windows if you have a Linux background is to install MSYS2 shell with MinGW-w64. This will provide an actual bash that allows you to run commands almost exactly the same way as on Linux, including support for backticks like in the case of your issue.
Though I would always recommend using $( ... ) instead of backticks, as this allows nesting.
Note that MinGW-w64 also exists on Windows to allow cross-building for Windows from Linux, but that may be a bit more difficult if you have never done any cross-building before.
Also -shared ... -o extremal_bi.so in your command should be replaced with -shared ... -o extremal_bi.dll -Wl,--out-implib,libextremal_bi.dll.a as .so files don't exist on Windows as Windows uses .dll files for shared libraries and the compiler uses .dll.a files as library objects for them.
Finally on Windows you need to tell the compiler or linker which symbols you will be exporting by either writing a libextremal_bi.def starting with the line EXPORTS followed all the symbols you want to be exported and include -def libextremal_bi.def in the link command, or using __declspec(dllexport)/__declspec(dllimport) when defining those symbols, which may be a bit complexer as it requires some conditional defines to determine if the code is being compiled for Windows and if it's during the actual build process of the shared library (__declspec(dllexport)) or code that uses it (__declspec(dllimport)). There is also another method to export all symbols, but that's a dirty method that may more easily cause symbol conflicts.

A simpler method to load shared libraries without root

I am trying to compile and run a C++ program on a server where I don't have root access. I am having trouble linkingboost_iostreams library.
I can successfully compile my program by pointing to the boost installation directory using the -L flag as:
g++ -I path/to/boost/build/include -o out prog1.cpp prog2.cpp -L path/to/boost/build/lib -lboost_iostreams
However, if I run the program as ./out I get the error error while loading shared libraries: libboost_iostreams.so.1.67.0: cannot open shared object file: No such file or directory since the linker is not able to locate libboost_iostreams.so.1.67.0 (which DOES exist under path/to/boost/build/lib)
Thanks to this answer, I was able to explicitly specify LD_LIBRARY_PATH and run the program as
LD_LIBRARY_PATH="path/to/boost/build/lib" ./out.
Since I am not root, I can't run ldconfig either. I was wondering if there is a way to load dynamic libraries without having to prefix LD_LIBRARY_PATH when you run the program and no root access.
I have figured out a way to solve this using the method explained here https://amir.rachum.com/blog/2016/09/17/shared-libraries/. The solution is to use rpath during compilation.
According to the article The only difference between rpath and
runpath is the order they are searched in. Specifically, their
relation to LD_LIBRARY_PATH - rpath is searched in before
LD_LIBRARY_PATH while runpath is searched in after. The meaning of
this is that rpath cannot be changed dynamically with environment
variables while runpath can.
In short once you compile with -rpath path/to/boost/build/lib, the directory containing the library libboost_iostreams.so.1.67.0 is searched at runtime without having to prefix LD_LIBRARY_PATH="path/to/boost/build/lib" ./out.
After compiling with
g++ -I path/to/boost/build/include -o out prog1.cpp prog2.cpp -L path/to/boost/build/lib -lboost_iostreams -rpath path/to/boost/build/lib
I was able to run ./out without any issues.
EDIT 1
As pointed by Nikos in the comments, alternatively you can set your LD_LIBRARY_PATH by export LD_LIBRARY_PATH=path/to/boost/build/lib. Add this line to .~/.bashrc file so that it is not lost when you log out.

Compile Pro*C in AIX 7 (64bit)

I try to migrate the old Pro*C program from HP to AIX, after changed some setting, I can make the binary file but fail to execute. Seems I now facing wrong library used (lib32/libclntsh.a).
Here is the error
0509-036 Cannot load program PROGNAME because of the following errors:
0509-150 Dependent module SOMEPATH/lib32/libclntsh.a(shr.o) could not be loaded.
0509-103 The module has an invalid magic number.
I build the program by setting object mode to 64
export OBJECT_MODE=64
Here is the full image when I make the binary
/PATHA/bin/oraxlc -O3 -q64 -DSS_64BIT_SERVER -I. -c MYPROG.c "MYPROG.c", line 2051.25: 1506-342 (W) "/*" detected in comment.
/PATHA/bin/oraxlc -o GLMJLUSB GLMJLUSB.o -L/PATHA/lib/ -lclntsh -lld -lm `cat /PATHA/lib/sysliblist` -lm -lc_r -lpthreads +DD64
/PATHB/bin/.orig/xlc: 1501-228 (W) input file +DD64 not found
Is there any way I can specify not to use the problem library, and use the 64bit version instead?
I don't know much about Pro*C and AIX, so any help is welcome. Thanks.
(Not really an answer yet, expect many edits).
Do you have a Makefile? If not, create one:
.SUFFIXES: .pc
PROC = ${ORACLE_HOME}/bin/proc
PROCFLAGS = code=ansi lines=yes
.pc.c:
${PROC} ${PROCFLAGS} $<
Keep improving it, until you can successfully precompile your *.pc files into *.c files.
Note: it is way easier, if you have GNU!make instead of prehistoric!make

How can I tell GCC to use custom library for -l instead of the system one?

I have a custom build of SQLite3 at /somepath, so /somepath/.libs contains libsqlite3.so.0.8.6 and the symbolic links to it. I wanted to link a program against it and assumed
g++ -O3 -g -fPIC -I /somepath -I /somepath/src -L /somepath/.libs -lsqlite3 -o myfile.so myfile.cpp
would work. It compiles, but I get a segmentation fault due to some problem in my code, and when trying to debug I run into the issues which look like LD_PRELOAD not working with my program and Setting my lib for LD_PRELOAD makes some processes produce loader errors: I can run LD_PRELOAD=myfile.so /somepath/sqlite3 ..., but under GDB I get symbol lookup error and LD_DEBUG=all LD_PRELOAD=myfile.so gdc -c core /somepath/sqlite3 ... reveals symbols are getting looked up in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0 instead of /somepath/libsqlite3.so.0, and unsurprisingly missing the symbols for functions added in the custom build. How can I fix this and debug my code?
The -lsqlite3 argument should be last. Order of arguments to g++ matters a lot. You should read more about runpath and perhaps pass -Wl,-rpath,/somepath/.libs
You may want to pass -v once to g++ to understand what is happening (what programs are actually running). You might also pass -Wl,--verbose to ask a more verbose link.
Then you can use ldd on your executable (and also readelf) to find out more what are its link time dependencies.
With suitable arguments to g++ you should not need additional options to gdb
From http://visualgdb.com/gdbreference/commands/set_solib-search-path
Inside gdb use the commands below.
set solib-search-path [Directories]
show solib-search-path

'.' is not recognized as an internal or external command

I just started learning C++, and I've been trying to run my program from the command line using:
g++ helloworld.cpp
which works, then I typed
./a.out
then it returns the error '.' is not recognized as an internal or external command.
I tried doing a.out, but it returns:
'a.out' is not recognized as an internal or external command.
I'm pretty new to the command line so it might be quite a novice problem. I'm using the gnu gcc compiler. My code is just a simple code for printing "helloworld", and it doesn't seem to be a problem with the code since the line g++ helloworld.cpp doesn't throw up any error. Just to add, I'm using windows 8.
My best guess would be that a.out is not in your directory. Usually, when compiling your program from the command line, add the -o flag and name your executable (like helloworld.exe). Then you'll be sure that an executable of that name is actually being created.
In your case, since you're most likely running Windows, without specifying a -o flag, the default is a.exe and not a.out, so when you used ./a.out that executable didn't exist. In this case, you can run your program by typing a or a.exe. You don't need the leading ./ on Windows.
./a.out
If you are in *NIX world, using linux or any other UNIX related platforms
.(dot) means current directory and a.out is an executable.
ls -l a.out
list its permissions and make sure it has executable permission. If it dont have use following command to give it permission; usually it should have when your generated the a.out file.
chmod 755 a.out
If your file is not in current directory use the absolute path to invoke the executable file
<absolute_path>/a.out
It should work if you have taken care all above criteria.
In the Windows world, "\" is used to separate files and directories:
C:\Windows\System32\Etc
However most other operating systems, and the web, use "/"
file:///c/windows/system32/etc
/etc/motd
In Unix "." refers to the current directory, and Windows/DOS mostly support this.
The Unix-based compilers expect you to specify an output file name for a compilation, and the default is "a.out". But you can override it with "-o"
g++ test.cpp -o test.exe
This creates a file called "test.exe" in the current directory. If you are using MinGW's "bash" command line, you should be able to run the above executable by typing:
./test.exe # note: no spaces!
at a "$" prompt
$ ./test.exe
However, if you are in a directory, say C:\Dev in the DOS command prompt, that won't work. DOS thinks '/' means "start of a parameter":
C:\Dev\> dir /w
outputs "wide" format dir
So, if you're using DOS, you just need to type:
test.exe
or
.\test.exe
e.g.
C:\Dev\> test.exe
C:\Dev\> .\test.exe
C:\Dev\> c:\dev\test.exe
or if you're relying on "a.out"
C:\Dev\> a.out
C:\Dev\> .\a.out