How to move gcc debug symbols outside from .so and .a files? - c++

as far as I know, objcopy is able to move debug symbols (compiled with -g flag) outside from an executable binary. I found this question, but there are only generic methods for symbol outsourcing.
But what can I do when my executable is using some really large .so and .a files?
I would like to profile my application in a small environment where is not enough place for the debug symbols. The entire project was built with -g option. The debug symbols are needed later only when the profile log is processed.

You can strip debug symbols:
strip --strip-debug object.so

Related

Debugging C++ library source with Xcode 7 GUI (lldb)

I am using a library installed via cmake in Xcode, and I'd like to allow my debugger to step through that library's code while debugging my application.
After building and installing the dependency cmake project, the cmake project that depends on it would then include that one. When it is run I'd like to step through the code of the dependency library with the Xcode debugger.
Is there a way to tell Xcode for my main application where the headers, source and debug built binaries (if necessary) of the library are so I can step through?
I've found a few relevant questions, but none provides straightforward instructions for configuring your library's source to be found in Xcode with support from the GUI.
LLDB equivalent of gdb “directory” command for specifying source search path?
In Xcode, how to debug with external libraries that you have the source for?
Xcode equivalent of Visual Studio's “Find Source”
Here is an example homebrew formula which installs a cmake project and enables the debug symbols. I can come up with an example that uses the library if needed as well.
If you are linking to the debug version of the library into your application, and you haven't moved or deleted the .o files you used to build it or the source files for those .o files, then you shouldn't have to do anything. lldb will pick up from the loader the location of the library's binary, and that will have a "debug map" that points to the .o files (where, on OS X, the actual debug information is stored) which lldb will then read, and the debug information will contain the path to the source files.
So some part of this chain must have gotten broken if you aren't seeing source in Xcode when you stop in some code in your library.
First make sure you really are building the debug version of the library (the compile lines that build the .o files should have -g in them.)
Next, if your make process is deleting the .o files or stripping the library before installing it, then lldb won't be able to trace from the binary to the debug info. The easiest way to fix this is to make a dSYM as part of the build process, using the dsymutil utility, and install the dSYM somewhere lldb can find (next to the library, or in any location Spotlight searches) or add it explicitly with lldb's add-dsym command. Note if the library is getting stripped you need to make the dSYM before it gets stripped.
Finally, if you are moving the source files from where they are when built, then you can use the source-map as described in the first of your links.

Code::Blocks and boost 1.55: static library is not used when dynamic library is present

I have built the boost 1.55 serialzation library with the following command:
b2 --build-dir=build toolset=gcc --with-serialization --layout=tagged link=static threading=multi stage
and got libboost_serialization-mt.a and libboost_wserialization-mt.a in my stage/lib directory - fine. Then I added boost_serialization to my C::B project's linker library list and compiled the boost serialization example and it ran fine from the command line. I then built the dynamic and single thread variants additionally using
b2 --build-dir=build toolset=gcc --with-serialization --layout=tagged link=static,shared threading=multi,single stage
and got more libraries in my stage/lib directory, as expected. What puzzles me is that there is a .so file for every library, even those that should be static. Why is it there? What is it needed for?
When I now compile the project, the executable complains:
error while loading shared libraries: libboost_serialization.so.1.55.0: cannot open shared object file: No such file or directory
The library is definitely there and I might just need to add the path to it to LD_LIBRARY_PATH, but I want to link statically for now. How can I do that?
I also don't quite understand the library naming: I have some libboost_wserialization... libraries in my lib folder and the w prefix to serialization is not described in the library naming section of the current boost getting started page.
Your answers gave me a better understanding of what was going on - now I know where the boost_wserialization libraries came from. I turned out that after doing the second build, all present libraries were shared, and the static libraries were overwritten. That's why I got confused by the "extra" .so files for those libraries which previously were indeed static.
Ok, first question:
Why is there a boost_serialization and boost_wserialization library?
the wserialization library is wchar_t oriented. Put into a separate library because it may not actually be needed.
Why are there multiple shared/static libraries?
The reason you're seeing all those extra shared libraries is because you're invoking b2 with link=static,shared, which instructs boost to build the shared libraries as well as the static libraries. Additionally, adding in the thread=multi causes the building of the mt libraries, which are libraries that should be used when linking to multi-threaded applications.
Why am I getting the run-time link error about libboost_serialization.so.1.55.0?
By default, most unix/linux systems will prefer the use of shared libraries over static libraries when linking, so when you try to link it will prefer to use the shared libraries over the static ones. If you want to force the link of the static library rather than the shared one, you tell the compile-time linker to do that, using:
-Wl,-Bstatic -lboost_serialization -Wl,-Bdynamic
This will cause the linker to look for the static variant of the boost_serialization library, rather than the dynamic one.
Now, because you're using code::blocks, I'd have to look up how to specify these flags on a case-by-case basis, but the most sensible thing to do is to clean the boost build using ./b2 clean and then rebuild, specifying only link=static, then you should end up with only .a files, which will produce stand-alone executables again.
If you want to specify this option for code::blocks, you would need to put them into the Build Settings -> Linker settings -> Other Linker Options field for the project. Simply specifying the library in the libraries field will not work for this case. Additionally, forgetting to pass in the -Wl,-Bdynamic option will cause it to try to link in static versions of some platform libraries, which can lead to build failure if the library in question is not present.
If you want to avoid having to set LD_LIBRARY_PATH to run the binary, you can add the option -Wl,-rpath,/path/to/boost/libraries, to the linker flags which will cause the compiled program to search that directory when trying to resolve the location of libraries.
What puzzles me is that there is a .so file for every library, even
those that should be static. Why is it there? What is it needed for?
You apparently are using someone else's make file. I wrote my own. My build command does not create a ".so" (shared object library). It only creates the ".a" (archive library). The linker knows how to use either.
See man ar. The utility ar builds archives.
See man ld. The utility ld can build shared objects.
You might look for these utility invocations in your build sequence, or ask someone where they are and comment out the use of ld, as you most likely do not need both (and building both will extend your build time unnecessarily). Alternatively, you might temporarily rename the ld command, and try your build. When it can not find the ld command, you might get a useful hint as to where the ld is invoked.
In my make file, the commands look like the following. The comment char is a # at beginning of line. (The string expansions $(AR) and $(LD) allow the use of non-standard utilities.)
$(TARGET_ARCHIVE): $(OBJ)
#echo R10: $(TARGET_ARCHIVE) :from: $(OBJ)
$(AR) crs $(TARGET_ARCHIVE) $(OBJ)
# $(TARGET_OLB) : $(OBJ)
# #echo R00: $(TARGET_OLB) :from: $(OBJ)
# $(LD) -o $(TARGET_OLB) -r $(OBJ)
The archive (.a), when used, is linked directly to and included in your executable. When the executable is loaded, all the referenced symbols of the .a are already in it. (un-referenced symbols and code are not linked in)
The shared object (.so) is not directly linked, but rather your executable gets a handle (or perhaps a file name) to the .so. It is my belief that when your executable is loaded, the .so is not immediately loaded. The .so does not load until the first time your executable references a symbol that is in the .so. At that loading, your app will experience a delay, but probably this late loading is reasonable for most applications.
It is also possible that the .so is already loaded in system memory before you activated your process. In that case, when your executable first references a symbol in the .so, some system code will 'map' the existing in-memory .so to your application -- probably faster than loading it, but I suppose the big benefit is that a .so that is used / referenced by many processes need only be loaded once, saving memory space. The loaded .so has all of its symbols, even if your app does not need all of them.
In either case, your executable will be smaller with .so's, bigger with .a's, but the .so's have some small performance hit for each .so that needs to be loaded or mapped in. With 4 GB in my desktop, the desktop has never felt 'crowded'. It's swap has never been used (afaik). So I generally use .a's.
NOTE: When the linker has access to both an archive (.a) and a shared object (.so) file, the linker will use the .so (and ignore the .a). Probably you can override that preference, but I have not tried. I find it easier to simply move the archive (.a) into a separate (from the .so's) directory, and inform the linker via the -L build option.

Statically linking to libarchive on Windows with MinGW

I've been using libarchive in my project for some time now and it's working great, at the moment I am dynamically linking to it, so on Windows the libarchive.dll file has to present on the system.
I would now like to statically link to the library so I don't have to bother distributing the DLL, but I'm having real trouble trying to achieve this!
Currently, in my make file, I have something like this:
-Lpath/to//libarchive/ -larchive
And this works, but it does a dynamic link. I don't know how to enforce a static link.
I can see in the libarchive directory there are two a files, libarchive.dll.a and libarchive_static.a. I suppose I want to link to libarchive_static.a but I can't seem to specify this, doing -larchive_static in the make file results in linker errors.
I was under the impression that static libraries under windows are lib files, but I get no such file type when I build libarchive.
How can I make a .lib file from libarchive. Also, as an extra question, what is the difference between an a file and a lib file?
Update
To statically link to libarchive, your library command for make should contain:
-Lpath/to//libarchive/ -larchive_static
This will link to the libarchive_static.a file. However, you also need to define LIBARCHIVE_STATIC in your code.
Now the problem is that libarchive depends on the bzip2 libraries (as well as others), and if you do not have a static build of them you will get linker errors something like:
undefined reference to `BZ2_bzCompressInit'
You need a static build of the dependent libraries and a similar command to the linker after the libarchive command:
-Lpath/to/bzip2/ -lbzip2
You can either build bzip2 from source, or do it the easy way and get a pre-built binary from the Gnu32Win project here: http://gnuwin32.sourceforge.net/packages.html
Just add libarchive_static.a explicitly to your link command.
gcc -o YourApp.exe $(OBJS) path/to/libarchive_static.a $(OtherLibs)
".lib" files differ from compiler to compiler (Borland, Microsoft etc.), ".a" is an old "archive" format from UNIX's ar tool. It is now used only for the bundling of static libraries.
Currently, in my make file, I have something ...
And this works, but it does a dynamic link
The .a file actually contains some code for dynamic linking to the .dll file, not the libarchive itself. On the startup the pointers to functions are allocated and dynamic linking is done.

How to link wsock32 library through g++?

I'm using minGW on windows, trying to compile a c++ program. I've used sockets in there, so I'm trying to link (not include... I've already included winsock.h) the wsock32 library. I know that the -L switch is for linking but none of the following commands work:
g++ C:\program.cpp -Lwsock32.lib
g++ C:\program.cpp -LC:\windows\system32\wsock32.dll
g++ C:\program.cpp -lC:\windows\system32\wsock32.dll
g++ C:\program.cpp -LC:\windows\system32\wsock32.lib
what should I do??
The -L option is for setting the directory where the linker should look for libraries/dlls.
The -l option is for naming the libraries/dlls you want to link with.
That would mean
g++ C:\Program.cpp -LC:\Windows\System32 -lwsock32
should be the command to compile your program from your regular windows command prompt.
I suspect your compiler may look in system32 automatically, so you may want to just try to skip the -L option.
As #Joshua commented, you probably want ws2_32.dll.
The GNU Compiler Collection uses ranlib archives (A files) rather than Visual Studio LIB files.
The w32headers project provides gcc- and g++-compatible headers and archives for most standard Windows DLLs, including ws2_32.dll. The name of the archive is usually the name of the DLL minus the .dll extension, prefixed with lib and suffixed with .a (following the *nix archive naming convention). Thus, the symbols for ws2_32.dll are in libws2_32.a, which can be linked with using ‑lws2_32.
By default, the w32headers archives are in the GNU ld library path, so to be able to link with standard Windows DLLs, there is no need to add library directories with an ‑L option. In your case, the only option that you need is ‑lws2_32:
g++ C:\Program.cpp -lws2_32
Assuming that compilation and linking succeed, the output will be a.exe in the current directory. You can override the name of the output binary with the ‑o option.
NOTE: I used non-breaking hyphens in my answer. If you copy & paste the command line options, be sure to replace all hyphen-looking characters with regular hyphens.

prevent compiling from generating dSYM on OS X (using make)

I've got a c++ project (open source) that does not need to strip debugging symbols by default. With a lot of test executables, there are a lot of dSYM files generated on OS X. I've tried -g3 as a g++ flag to no avail. Ideas?
Thanks!
Juan
If you're compiling with the "-g" flag, remove it.
As Ted Mielczarek pointed out, gcc does not produce dSYM files on its own, it simply stores the information needed to produce them in the object files. If you're using make to build your project, it is most likely that there is a separate step in the makefile which runs dsymutil after compiling/linking the executable, see if you can find and remove it.
Are you compiling via XCode? GCC does not produce .dSYM files, XCode runs dsyumutil to generate them. In my (outdated) XCode 3.2.3, under Project Settings, Build Options -> Debug Information Format, you can choose "DWARF with dSYM File" or just "DWARF". The latter should not result in a dSYM being produced.
However, note that with Apple's toolchain, the DWARF resides in the .o files, and does not get linked into the final binary. (GDB knows how to find it, but it needs the .o files laying around on disk.) If you intend to send the binaries to someone else, you really do need to produce a dSYM to send them along with the binary.