GDB says 'No symbol "putenv" in current context'. But this is a libc function, right? - gdb

I'm using gdb to attach to a program that's already running (ruby).
Strangely, when I try to execute call putenv (...) in gdb, it tells me 'No symbol "putenv" in current context.'
putenv is a libc function, right? Is there a way for me to get this into the current context? Flailingly, I've tried running file /usr/lib/x86_64-linux-gnu/libc.so, but this results in '...not in executable format: file format not recognized'.

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.

Unable to find breakpoint when debugging a cpp source file when invoked from .sh

I need to set breakpoints in a cpp source file. The current setup to call the cpp target is through a shell target, with additional dependencies, which means it's not feasible to directly invoke the cpp target in Linux console.
As I searched online, there are generally two ways:
invoke gdb in shell
pause in cpp, let gdb connect to the process
I don't know how to do the first way, so I choose the second way here.
I insert sleep(30) in cpp file, then in another terminal I open gdb and connect to the running process. I confirm the gdb can stop at the sleep() function in gdb. But the problem is the gdb seems only knowing the sleep function context, without knowing the call site of the sleep function. If I force setting breakpoint in the main program, gdb shows no such file. If I continue in gdb, it will not stop at any breakpoints I set in cpp file.
You need to compile the program with debug symbols. Otherwise GDB will only know of symbols in the dynamic symbol table. Turning off optimizations also helps debugging. So add the flags -O0 -g.
If this is not possible, you'll have have to step through the disassembly (Ctrl+X, 2).

gdb 'call' returns negative value

I am trying to load a shared library in gdb and invoke entry function call from gdb.
For example mylib.so has mylibraryEntryPoint() function.
However, I am getting a negative output. I am curious what does this error code mean.
(gdb) sharedlibrary /usr/home/mylib.so
Symbols already loaded for /usr/home/mylib.so
(gdb) call mylibraryEntryPoint()
$9 = -2048550400 // Here is the problem.
The strange part is this function call works on another Linux VM with same gdb version.
I am expecting the function to be 'executed' on this machine. (It prints some lines as well). Since it is returning the negative value which is not really returned by my function, it is an error code of gdb. It tells gdb was unable to run the function.

Stack Trace in Codeblock

I am using Codeblocks for the first time to run a cpp program. While compling the program an error occurs, I want to know the line number from the program where the error is evoking or in other words I want to see the stack trace of the program.
How can achieve this?
You can also use gdb. To debug, compile with g++ and -g at the end of the command and then run your program with gdb (in linux, gdb ./NameOfYourProgram). Then, you type r to run it, and when an error occurs, just type where and you get the stack. You can also set breakpoints and perform steps with gdb to examine the bug further.

Debug error before main() using GDB

Is there anyway to debug a link error or any kind of error that may occur before the execution of the main() function using GDB?
Is there anyway to debug a link error
Presumably you are asking about runtime link error (e.g. `error: libfoo.so: no such file or directory'), and not about (static) link step of your build process.
The trick is to set a breakpoint on exit or (exit_group on Linux) system call with e.g. catch syscall exit. You will then be stopped inside ld.so at the point where it gives up running your binary.
or any kind of error that may occur before the execution of the main() function using GDB?
Any other kind of error, e.g. SIGSEGV can be debugged "normally" -- for signal you don't need to do anything at all -- GDB will just stop. For other errors, just set a breakpoint as usual.
On way to debug initialization code (even if you don't have symbols) goes like this:
gdb somebinary
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04
etc.
info file
Symbols from "somebinary".
Local exec file:
`/somebinary', file type elf64-x86-64.
Entry point: 0x4045a4, etc.
break *0x4045a4
run
...Breakpoint 1, 0x00000000004045a4 in ?? ()
From here on you can proceed as usual.