I am confused by the commands set solib-search-path and set sysroot, not sure when to use one or another. In my case symbols are only loaded when i used both the commands. Is it always both the commands are required and what does each command does.
For here http://visualgdb.com/gdbreference/commands/, it looks like sysroot looks in subdirectories too, then why is solib-search-path required, if both search for libraries and load symbols from those libraries
gdb searches first for libraries in sysroot (with an absolute path), and then only if it fails to find them it searches into solib-search-path (with a relative path).
For that reason, when using gdb server / remote debugging you probably want to use ONLY gdb's sysroot option. On a Linux system using solib-search-path will NOT work unless you change the value of sysroot, because the default value of sysroot is target, meaning that gdb is loading the so-file found on the filesystem you are debugging. This is also what is indicated in gdb's documentation:
set solib-search-path path
colon-separated list of directories to search for shared libraries.
‘solib-search-path’ is used after ‘sysroot’ fails to locate the
library, or if the path to the library is relative instead of
absolute. If you want to use ‘solib-search-path’ instead of ‘sysroot’,
be sure to set ‘sysroot’ to a nonexistent directory to prevent GDB
from finding your host’s libraries. ‘sysroot’ is preferred; setting it
to a nonexistent directory may interfere with automatic loading of
shared library symbols.
As indicated in this thread, the use-case for solib-search-path is rather:
solib-search-path is there mostly to help targets like Windows that
don't report to the debugger the full path to the shared library.
GNU/Linux always works with full patchs, such as
"/usr/lib/libjpeg.so.8"
Related
Scenario
Dev machine running Ubuntu 20.04 and QtCreator. Qt libs are installed to /home/mark/Qt/6.2.0/gcc_64/lib.
Target machine running Ubuntu 20.04. Qt libs are installed to /home/user/Qt/6.2.0/gcc_64/lib.
Issue
When debugging a remote application from QtCreator I get:
Could not load shared library symbols for 8 libraries, e.g. /home/user/Qt/6.2.0/gcc_64/lib/libQt6Gui.so.6.
Use the "info sharedlibrary" command to see the complete listing.
Do you need "set solib-search-path" or "set sysroot"?
Setup
In Tools > Options > Debugger > GDB > Additional Startup Commands I wrote:
set sysroot /home/user/Qt/6.2.0/gcc_64/
set solib-search-path /home/user/Qt/6.2.0/gcc_64/
Questions
I read somewhere that to speed up the debugging I need to set sysroot to the local libraries (i.e. /home/mark/... instead of /home/user/...). Which is the correct path?
Is it correct to set sysroot to the parent directory of the lib folder that contains the Qt libraries?
where should I run the info sharedlibrary command?
Which is the correct path?
The one where libraries can be found during debugging, i.e. the path on the development machine.
Is it correct to set sysroot
The sysroot should be used when you have a complete set of target libraries (including all system ones).
That is, if you had the complete mirror of target libraries under e.g. /home/mark/target/, then you would use set sysroot /home/mark/target.
Since you don't have such a directory, you should not use sysroot at all.
Instead, you should tell GDB that it can find libraries in /home/mark/Qt/6.2.0/gcc_64/lib with set solib-search-path /home/mark/Qt/6.2.0/gcc_64/lib.
where should I run the info sharedlibrary command?
At the (gdb) prompt.
I have a folder where many Shared Libraries are in. I want to load all of them in my program so iterate them and load them but some got not loaded because it could not find a dependency which lies in the same folder but (at least in windows) it doesn't search the same folder.
I googled and found 'AddDllDirectory' for windows.
Is there a equivalent for this function in Linux and Mac?
If not how could I workaround this problem?
It needs to be runtime because the folder containing the Shared Libraries can change.
For a single, specific program, execute it from the shell (or with a script) like this:
LD_LIBRARY_PATH=path:to:libraries /path/to/program
To set up system wide libraries, adjust the contents of /etc/ld.so.conf.d or /etc/ld.so.conf.
If you just want to make your programs refer to a specific additional path, have a look at the rpath linker flags. E.g.
gcc -o my_program -Wl,-rpath='additional/library/paths'
With rpath take note about the special "variable" ${ORIGIN} which allows you to specify paths relative to the install location of the linked binary. For details read the manual page of ld.so
We are compiling a library with CMAKE under Linux which is then installed per default under /opt/mylib and its sources are placed in this folder as well.
When users try to debug with GDB the library sources are not found by GDB automatically.
How can we compile the library that GDB finds sources without specifying anything?
For example the C++ standard library works like that. I can debug an application and I do not have to tell GDB where to find the sources.
Note: This question is not about how to make GDB find the sources (I know how to do this) but how to adapt the CMakeLists.txt and the compile process that it is not necessary to manually specify the source directory in GDB.
You are likely looking for the -fdebug-prefix-map=old=new GCC flag.
From the manual:
When compiling files residing in directory old, record debugging information describing them as if the files resided in directory new instead. This can be used to replace a build-time path with an install-time path in the debug info. It can also be used to change an absolute path to a relative path by using . for new. This can give more reproducible builds, which are location independent, but may require an extra command to tell GDB where to find the source files. See also -ffile-prefix-map.
The "may require an extra command" part applies if you want to debug as-built binaries without installing them. Debugging installed binaries will just work (TM).
I have a question related to how to install a built executable program with cmake when it relies on some external libraries. Suppose my executable is abc, and it relies on two external libraries: lib1.so and lib2.so. The structure of the codes are as follows:
-.........
|----bin (lib1.so lib2.so)
|----include(lib1.h lib2.h)
|----src(main.cpp)
When the executable program is installed using the following cmake commands:
INSTALL(TARGETS ${Exe_Name}
RUNTIME DESTINATION Path to bin
LIBRARY DESTINATION Path to bin)
I expect that the executable program will be in the same directory with lib1.so and lib2.so. However, when I execute the built program in the installation folder, I met the following error:
error while loading shared libraries: lib1 can not open shared object file No such file or directory
If I use ldd to check the executable, I found lib1.so and lib2.so not found. After searching for possible solutions, I found if I call the executable in this way, then it worked:
LD_LIBRARY_PATH=./ ./my_program_run
Then my question is how I can let my executable program knows the locations of the shared libraries with cmake when it is installed? Thanks.
This is best solved this with the RPATH of the final executable. RPATH is a hardcoded search path for the executable itself, and allows the use of the string $ORIGIN, which expands to the location of the executable at runtime. See this reference: http://man7.org/linux/man-pages/man8/ld.so.8.html
CMake strips the rpath of a binary at installation time, to avoid the binary picking up libraries littered around your development tree. But it also provides a simple way to modify the installation rpath for exactly this reason. Here's the short answer:
IF(UNIX)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:\$ORIGIN/../bin:\$ORIGIN")
ENDIF()
This particular example appends to the existing rpath, and adds . and ../bin to the search path, all relative to the location of the binary.
Some developers claim that adjusting the RPATH of the binary is not a good idea. In the ideal world, all the libraries would live in the system library directories. But if you take this to the extreme, you end up with Windows (at least the older ones), where c:\windows\system32 is full of junk that came from who knows where, and may or may not conflict with other software, etc. Using rpath and installing everything in one place seems like a great solution.
If the application is to be cleanly installed to a standard linux distribution, then you should either install the supporting shared libraries into a standard location (/usr/lib), or you should add the libraries location to the ld.so config, by create an /etc/ld.so.conf.d/myprogram.conf file containing the name of the directory the libraries are in.
If the installation is temporary or more ad-hoc, then a script to set the LD_LIBRARY_PATH is suitable.
The libraries are searched in the predefined locations which includes standard library paths configured with ld.so.conf and LD_LIBRARY_PATH. You can also try to compile your app with -rpath, but it is not recommended by some developers. I suggest you to create a wrapper script which will set LD_LIBRARY_PATH and run the real application like that:
"theapp" script:
#!/bin/sh
dir="`dirname \"$0\"`"
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}"$dir"
exec "$dir/theapp.real" # your real application
The application, script and libraries should be in the same location (under bin/).
I am trying to get my head around the way shared libraries work in the c++ unix environment. I understand we only need header files and no shared libraries specification when compiling code. But if I want to create an executable or shared library from my compiled files, do I need to specify shared library dependencies (those are dynamic)? And do the paths of shared libraries need to match the path at runtime loading?
I am using Linux 2.6.18-164.11.1.el5 #1 SMP x86_64 GNU/Linux
I am having a problem where my code is not able to pick up a library at runtime. I have tried setting LD_LIBRARY_PATH and PATH. But at runtime when I run the executable, I get the following error:
Error: librc.so: cannot open shared object file: No such file or directory
Sam
The headers are only for the compile phase. At link time, you usually have to specify which shared libs you are going to link to. You might see -L options to set locations to where shared libraries reside, and/or -l to specify which libraries to link. There is usually also a switch on the command line to alert the linker as to whether you are using thread-safe versions of the libs or the 'regular' ones, and another switch to specify dynamic linking.
At run time, whether you are starting the program that uses the libs, or running ldd to find out what it needs, the OS has a system for locating .so files, and this can vary from one unix version to another. The LD_LIBRARY_PATH variable specifies where to look for .so files, but may not be the full story, depending on the exact unix version in question. Also, you probably don't want to fiddle around with modifying LD_LIBRARY_PATH except from a throw-away shell, since it has system wide effects. A better option is to check it the 'missing' .so files are or are not on the existing path set by LD_LIBRARY_PATH, and if not, try putting copies of them somewhere on that path.
At run time, dynamic libraries are searched:
in a path recorded in the executable (under linux with -rpath at link time, under Solaris with -R, using $ORIGIN in a directory name allows to specify a directory relative to the directory containing the executable)
in the LD_LIBRARY_PATH (or equivalent, there are sometimes 64/32 bits variant). If a path has been recorded in the executable, LD_LIBRARY_PATH may not searched (under Linux it is searched after the recorded path if the executable has been linked with the option --enable-new-dtags; I don't remember Solaris behavior for now)
in a set of system dependant directories (Linux allows to specify them in /etc/ld.so.conf and has a cache, see ldconfig)