nm versus gdb break - gdb

I am working on Ubuntu 14.04 LTS.
I have an executable file exec compiled from file.c. The file.c makes use of functions from a static library. For example, let's says that fubar() is a function of the static library that is used in file.c.
This is something that I have noticed.
nm exec | grep fubar gives a certain value.
(on my system and for my executable, 0808377f)
gdb ./exec and then break fubar gives a different value.
(on my system and for my executable, 0x8083785)
When I do a similar thing for another executable file (exec1 compiled from file1.c, it outputs the same value for both the commands).
Both the commands are supposed to output the same virtual address. Aren't they? I am obviously missing something. Can someone explain what exactly is happening? And what is the difference between both the commands.

Barring unusual things like -fPIE, what is going on here is that the gdb command break function actually means "break after the function prologue for function". This way, arguments are set up properly by the time the breakpoint is hit.
If you want to break exactly at the first instruction of a function, use the * syntax, like:
(gdb) break *function
If you do this the addresses will probably match.

Related

Compiling and injecting code in GDB: C++ rather than C

I am running gdb 10.1.90.20210103-git and gcc/g++ 10.2.1 20210110 on x86-64 Debian 11. My IDE is Codelite, which uses the manual rather than the machine interface to gdb, and enables me to type commands directly to gdb, and see the response (potentially copying the response to the clipboard). This when the inferior is paused after hitting a breakpoiunt, via the gdb console, which is in Codelite's Debugger > Output pane.
I was able to use the instructions at: https://sourceware.org/gdb/current/onlinedocs/gdb#Compiling-and-Injecting-Code "Compiling and injecting code in GDB" to compile simple C code and make it run in the environment of the halted inferior. For instance: compile code blah++; increments a local variable int in the inferior, which I can see via the Locals or Watch panes.
The compile file command worked fine as long as I specified the absolute path of the source file.
I was unable to see console output (to the inferior's or gdb's console) for a simple printf() statement: `printf("xxx");' because the code would not compile if there was such a line
Despite using set debug compile and set debug compile-cplus-types and checking these are set with the show versions of these, I get no error messages or acknowledgements regarding whatever I try to compile.
The blah variable is an integer, which is accessible through C code and so gcc. The ability to increment this was the only indication that my code had compiled and run.
I could not get any responses to set/show compile gcc so I am presumably compiling with gcc. I did give the command set compile gcc /usr/bin/x86_64-linux-gnu-cpp-10, but there was still no response from show compile gcc or any change in the C-only behaviour.
I could not compile the file if it contained a C++ line which incremented a data member of a class object in an vector of such objects. Nor could I compile my code if it contained C++ code such as: #include <fstream> and/or std::fstream oFile;.
The gdb documentation mentioned above is general, but does have C examples.
Is it possible to compile C++ code under gdb, injecting it into the environment of the paused inferior, with any version of gdb and gcc?
I am keen to use this C++ code injection facility, if it exists, for dumping the contents of large, complex, data structures to files and and to modify some elements of same to aid debugging.
Summary: GDB's C++ compilation and injection system does not work for me, and it is reported to be buggy or non-functional. I only tested this compile command with single lines of C code, but it worked fine for these. I was able to run my function, which writes a text dump file containing the values of a vector of class objects' data members, while the inferior was paused after a breakpoint, by including it in a source file and calling it with GDB's print or call commands, giving it the required input argument of the name of the vector to dump.
I haven't tried using GDB on its own, but at present I have no reason to believe that Codelite is interfering with my ability to communicate with GDB via Codelite's "Debugger > Output" console.
I wrote to the GDB Developer list and received what I assume is a well informed reply. I was told that in my respondent's experience "the C++ plugin isn't very functional. It seems to have some bugs and crash pretty frequently as well. Also, it seems like nobody is actively working on it." This is consistent with my experience to date.
Perhaps later versions of GDB would work better. However, there has been minimal change to the library https://github.com/gcc-mirror/gcc/commits/master/libcc1/libcp1.cc since 2017, and I could find no indication of new work on C++ compilation and injection in https://www.sourceware.org/gdb/news/ since the announcement of its introduction:
GDB 8.3.1 was released on 2019-09-20, with: "Experimental support for compilation and injection of C++ source code into the inferior (requires GCC 7.1 or higher, built with libcp1.so)."
It is possible that my problem is related to not having this library. I do have the C equivalent: /usr/lib/x86_64-linux-gnu/libcc1.so.o. I could find no such library in a Debian package. It is possible I could get this going by compiling the latest GCC/G++ and GDB, but that is pretty daunting, involving installing later standard libraries than my current Debian installation has, while making those and the newer G++ and GDB available for Codelite sessions, but not interfering with other software on machine which needs the older compilation system.
The respondent suggested that instead of compiling and injecting fresh code in the middle of a debugging session, I could write it as a library, and run it by using the compile command, on a purely C piece of code which would call it. However, for my purposes, the function needs to be passed one or more C++ constructs, and any code which called a C++ function would be C++ code and so, presumably, not be compiled by GDB.
For my immediate purpose of doing text dumps of large vectors of class objects' data members, I was able to succeed by writing such a function in an existing source file, which also contains the functions I am debugging. Then I could call it with GDB's print or call commands. I imagine this would work if the debugging function was in any other linked source file, or in a linked library. (Perhaps there is a way of writing such a library, compiling and linking it while the inferior is halted.)
I was able to run this, from a debugging session in which the inferior was halted somewhere, with either the print or call command followed by the name of the function, with the name of the vector in brackets. There must be no semicolon. I found the print command better, since GDB would report the return value, which was "void". My function used C++ constructs such as "<<" to write to the text file.
A call within my dump function of the C function system("pwd") resulted in the current directory being output on the inferior's terminal window. Likewise: print system("pwd"). print system("mc") dutifully ran Midnight Commander in the inferior's terminal window.
I altered the function to return a string, which GDB reported in the GDB "Debugger > Output" console. I added a line: std::cout << "xyz"; - but nothing appeared on either the inferior's terminal window or in the GDB console.
My attempts to use the compile command to call my dump function in exactly the same way produced no results, with or without a trailing semicolon.
I found thatprint and call work with C and C++ code while `compile" only works with C code.
I tried print vvv[6].mmm for data members which were integers, floats, and strings and GDB returned their values correctly. Adding a ++ at the end caused it to return the original integer value, but the value itself was incremented.
When I tried print with a compound line of code, with a semicolon between the two logical lines, with and without one at the end, there was no response.
The GDB Developers list is not the place for support requests, but I did not know a better way to find out about the status of this facility.

What is lldb's equivalent one of gdb's start command?

I heavily used gdb before, and now give lldb a shot. I like gdb's start command very much, but I can't find the equivalent one from lldb's manual. Now I can only use "b main" followed by run compound instead. So just curious whether there is an equivalent one in lldb? Or I can only use the compound of "b main" and run commands as a work-around.
You are correct, lldb doesn't have a dedicated start command. The stated motivation for that command is that gdb supports lots of runtimes that don't use a "main" symbol. That makes determining where user code begins non-trivial, and it's useful to have a command that figures that out for you. We haven't had a need for that in lldb yet.
If you always use start to run programs in gdb, then you can just set a breakpoint on main in your ~/.lldbinit file. That will get copied to any new targets that get made in your lldb session, and run will behave exactly like start (for runtimes that use a main symbol).
If it's something you would use a lot but not always, you could make your own version fairly easily using the python extension point in the command interpreter:
https://lldb.llvm.org/use/python-reference.html#create-a-new-lldb-command-using-a-python-function
Also, feel free to file an Enhancement Request with http://bugs.llvm.org.

Meaning of a gdb backtrace when there is not source code

I have a gdb backtrace of a crashed process, but I can't see the specific line in which the crash occurred because the source code was not in that moment. I don't understand some of the information given by the mentioned backtrace.
The backtrace is made of lines like the following one:
<path_to_binary_file>(_Z12someFunction+0x18)[0x804a378]
Notice that _Z12someFunction is the mangled name of int someFunction(double ).
My questions are:
Does the +0x18 indicate the offset, starting at _Z12someFunction address, of the assembly instruction that produced the crash?
If the previous question is affirmative, and taking into account that I am working with a 32-bit architecture, does the +0x18 indicates 0x18 * 4 bytes?
If the above is affirmative, I assume that the address 0x804a378 is the _Z12someFunction plus 0x18, am I right?
EDIT:
The error has ocurred in a production machine (no cores enabled), and it seems to be a timing-dependant bug, so it is not easy to reproduce it. That is because the information I am asking for is important to me in this occasion.
Most of your assumptions are correct. The +0x18 indeed means offset (in bytes, regardless of architecture) into the executable.
0x804a378 is the actual address in which the error occurred.
With that said, it is important to understand what you can do about it.
First of all, compiling with -g will produce debug symbols. You, rightfully, strip those for your production build, but all is not lost. If you take your original executable (i.e. - before you striped it), you can run:
addr2line -e executable
You can then feed into stdin the addresses gdb is giving you (0x804a378), and addr2line will give you the precise file and line to which this address refers.
If you have a core file, you can also load this core file with the unstriped executable, and get full debug info. It would still be somewhat mangled, as you're probably building with optimizations, but some variables should, still, be accessible.
Building with debug symbols and stripping before shipping is the best option. Even if you did not, however, if you build the same sources again with the same build tools on the same environment and using the same build options, you should get the same binary with the same symbols locations. If the bug is really difficult to reproduce, it might be worthwhile to try.
EDITED to add
Two more important tools are c++filt. You feed it a mangled symbol, and produces the C++ path to the actual source symbol. It works as a filter, so you can just copy the backtrace and paste it into c++filt, and it will give you the same backtrace, only more readable.
The second tool is gdb remote debugging. This allows you to run gdb on a machine that has the executable with debug symbols, but run the actual code on the production machine. This allows live debugging in production (including attaching to already running processes).
You are confused. What you are seeing is backtrace output from glibc's backtrace function, not gdb's backtrace.
but I can't see the specific line in which the crash occurred because
the source code was not in that moment
Now you can load executable in gdb and examine the address 0x804a378 to get line numbers. You can use list *0x804a378 or info symbol 0x804a378. See Convert a libc backtrace to a source line number and How to use addr2line command in linux.
Run man gcc, there you should see -g option that gives you possibility to add debug information to the binary object file, so when crash happens and the core is dumped gdb can detect exact lines where and why the crash happened, or you can run the process using gdb or attach to it and see the trace directly without searching for the core file.

How can I run a program with additional flags in gdb?

I'm trying to test out this answer:
_dl_runtime_resolve -- When do the shared objects get loaded in to memory?
But when I try various ways to run essentially the same as gdb "LD_BIND_NOW=y binary",it fails.
How can I run my app with this flag on inside gdb?
Two choices. First:
env LD_BIND_NOW=y gdb binary
Or, run gdb binary and then inside gdb:
set env LD_BIND_NOW=y
run
The former will affect the gdb binary itself, which may or may not matter. The latter might not actually work :-)

How can I output a C + Assembly program trace using GDB?

I'm debugging a nasty problem where #includeing a file(not anything I wrote, for the record) causes a crash in my program. This means, I have working and broken, with only one C(++) include statement changed. Some of the libraries I'm using don't have debugging information.
What I would like to do is get GDB to output every line of C++ executed for the program run, and x86 instructions where not available to a textfile in such a format that I can diff the two outputs and hopefully figure out what went wrong.
Is this easily possible in GDB?
You can check the difference between the pre-processed output in each version. For example:
gcc -dD -E a.cc -o a.pre
gcc -dD -E b.cc -o b.pre
diff -u a.pre b.pre
You can experiment with different "-d" settings to make that more verbose/concise. Maybe something in the difference of listings will be obvious. It's usually something like a struct which changes size depending on include files.
Failing that, if you really want to mess with per-instruction or line traces, you could probably use valgrind and see where the paths diverge, but I think you may be in for a world of pain. In fact you'll probably find valgrind finds your bug and then 100 you didn't know about :) I expect the problem is just a struct or other data size difference, and you won't need to bother.
You could get gdb to automate line tracing. It would be quite painful. Basically you'd need to script it to run "n" (next line) repeatedly until a crash, then check the logs. If you can script "b main", then "run", then infinite "n" that would do it. There's probably a built-in command to do it but I'm not aware of it.
I don't think GDB can do this; maybe a profile will help, though? Are you compiling with gcc? Look at the -p and -pf commands, I think those might be useful.
The disassemble command at the gdb prompt will disassemble the current function you are stopped in, but I don't think outputting the entire execution path is feasible.
What library are you including? If it is open source, you can recompile it with debugging symbols enabled. Also, if you're using Linux, most distributions have -dbg versions of packages for common libraries.