GDB Shared Object unable to get symbols in current context - c++

I have a piece of software that is compiled with several shared libraries. My code is calling a function inside the shared object and crashing inside. I believe my problem is how the parameters are being constructed for this function. I want to validate this by viewing what is happening inside the .so such that I can make the correct changes for how I am constructing the parameters.
The problem I a am running into is not being able to resolve local variables within the shared object. For instance gdb will print out:
0x<addr> in <function>(int const* , int, int const*)
Based on this I know where I am inside the .so. When I navigate here and try to find what different variables are being set to gdb complains with:
No symbol <var> in current context.
Now I know for a fact where I am within the code. Additionally, I have checked to make sure the .so was compiled with symbols on and I have also made sure gdb is loading these symbols.
Can anyone inform me on why gdb is unable to see these local variables?
As a note - I haven't used gdb in a while and not to this level of debugging so I am sorry in advance is this is just a limitation of gdb that I am unaware of.
GDB Version: 7.7.1
Edit for comment:
Yes the .so was compile with symbols. I have verified this with:
file <.so>
This tells me it was dynamically linked and not stripped.
As for commands, I simply trying to print variables.
Overall I am not sure why gdb is unable to resolve the source/exact function of the .so when I explicitly loaded it and made sure the .so was compiled with symbols.

I have checked to make sure the .so was compiled with symbols on
Every .so is compiled with symbols on -- it would be useless without symbols.
It's the debugging info that you are compiling without. Add -g flag to your compile lines, and make sure to not have -s or --strip anywhere on your link line.
and I have also made sure gdb is loading these symbols.
Yes, this output <function>(int const* , int, int const*) tells us that GDB has read symbols, and also that it did not load debugging info (these are two completely separate things).

Related

Why does the program work after removing the symbol information?

I made one SO file and compiled it with a compile option called "-Xlinker --strip-all " to counter any reverse engineering (use clang).
Thanks to this, most of the symbols of functions other than functions directly exposed to the outside do not appear (objdump -TC test.so). The question is, if a symbol is deleted like this, it should not be used inside the program, so I think it is normal. What am I missing?
You're right, debugging symbols aren't needed by the program itself to execute; the linker computes (and therefore knows at link-time) what the memory-address of each function/global-variable/etc will be at run-time, so it can just place that memory-address directly into the executable where necessary.
The symbols are there for a debugger to use, to make the debugging output easier for a human (or a debugging tool) to use and understand.

Why string shown up in Shared Library file like .so file in Linux?

May I know why the .so file in linux will show up the string value from my cpp code? Even with fvisibility=hidden set in gcc make.
for example, i set "Hello World" and it will show up.
I tried google but found nothing related..
Thanks.
-fvisibility=hidden only affects the linker visibility, i.e. whether symbols are visible when a linker tries to link against your file. It does not specify any active obfuscation.
Your strings are still placed inside a data section and need to be loaded into the memory space of the process when your library is loaded, so they will still need to be visible when inspecting the file. If you need them to be obfuscated, you will need to obfuscate them yourself and decode them at runtime (knowing that a sufficiently determined attacker can still reverse engineer or debug your library).

callgrind no source available for a couple of functions only

I am using linux and I am trying to debug an executable that I launch from the command line. It calls some functions from another custom library that I linked to it. I built both my executable and my library with the debug flags (-g3) then I ran it with callgrind this way:
valgrind --tool=callgrind --trace-children=yes ./my_exe --some_args
For most of the functions, kcachegrind shows the name and the location. But for a couple it just shows the address in hexadecimal format and complains about missing debug information. I just know that the functions come from my custom library.
The functions not being shown call some pthread functions (mainly pthread_mutex_lock and pthread_mutex_unlock) and are themselves called by other functions from the same library that are also not shown.
Despite that, I have some functions from my custom library that are fully displayed (name, file and even source code).
I tried compiling my_exe by linking dynamically my_lib.so:
kcachegrind displays the function location as being in my_lib.so but the name and the file of the function are not shown.
I then tried compiling my_exe by linking statically my_lib.a:
kcachegrind displays the function location as being in my_exe but once again it doesn't show the name nor the file and complains about missing debug infos.
Other functions called from my_exe are also fully displayed as expected (name, file, source code...).
I don't understand why some functions would be displayed and some would not, given that they're in the same executable/library and that I compiled with debug symbols. I expected having either no function names at all or all of them. Am I missing some debug flags from valgrind ? Any ideas ?
Answering my own question in case it helps someone:
I discovered that my custom library A was itself linked with another static library B and that the unsourced functions were arising from B. Since it was static, valgrind considered it as part of A.
I managed to understand that by linking A dynamically with B (B.so), and valgrind told me the function was in libB.so. I could not find the exact name though since I don't have the sources to recompile lib B with debug flags but at least I was able to figure out where the problem was coming from.

can gdb allow to see ALL source code?

I was debugging an application created in C ++ for Linux when I realized that the executables in release version were compiled with the -g flag.
My concern is whether it is possible to read the source code of the executable through gdb using list or backtrace (exploiting some know core dump or antoher method)
No, the source code is not included in the executable, even when compiled with -g. What is included are references to the source code, so there's a mapping between program addresses and file and line numbers.
There will also be information in the debug that describe the functions in your program, so there will be information describing each function, the types taken and returned, and what local variables it contains, there's also information about which addresses correspond to which functions. All your types and global variables will also be described in the debug information.
It is possible to split the debug information out of you program using objcopy, the following is taken from the gdb online manual (https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html)
objcopy --only-keep-debug foo foo.debug
strip -g foo
objcopy --add-gnu-debuglink=foo.debug foo
This takes the debug information out of foo and places it in foo.debug, the strips the debug information out of foo and adds a link between foo.debug back to foo.
Now you, as the developer can debug release builds by loading the additional foo.debug file containing the debug data, while the customer is only given foo and so does not see the debug information.
A more detailed look at creating split debug information can be found here How to generate gcc debug symbol outside the build target?
No, source code is not included in a binary built with -g and therefore it will not be possible to read it using only the binary.
Things that they may be able to read include:
Names of variables and functions
For each intruction: full path of source file, line in the file and name of the function it is in

GCC: how to find why an object file is not discarded

I have an executable which links to a big .a archive that contains lots of functions. The executable only uses a small fraction of the functions in this archive, but for some reason it pulls everything from it and ends up being very big.
My suspicion is that some of the functionality that the executable is using somehow references something it shouldn't and that causes everything else to be pulled.
Is it possible to make gcc tell me what reference causes a specific symbol to be added in the executable? Why else can this happen?
I've tried using --gc-sections with no effect.
I've tried using --version-script to make all the symbols in the executable local with no effect
I'm not interested in -ffunction-sections and -fdata-sections since it is while object files I want to discard, not functions.
Other answers mention -why_live but that seem to be implemented only for darwin and I am in linux x86_64
Use -Wl,-M to pass -M to the linker, causing it to print a link trace. This will show you the reasons (or at least the first-found reason) for every object file that gets linked from an archive.