call dlopen from gdb - gdb

I want to load shared library (.so) from gdb, I found this command :
(gdb) call dlopen("path/to/lib.so",..)
But it doesn't work, I link my program with -ldl.
The error I get is:
No symbol "dlopen" in current context
what did I miss ?

I found a command that resolve the half of this topic. I explain:
First, you should load the shared object into the process:
(gdb) set environment LD_PRELOAD /usr/lib/libdl.so
After that, we define the file to debbuging
(gdb) file pgm
For testing, we put breakpoint in main i.e
(gdb) break main
Now, we run the program
(gdb) run
and we call dlopen
(gdb) call dlopen("/path/to/lib.so",2)
until now it's work, but when I put the last command, I have:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7de7f09 in ?? () from /lib64/ld-linux-x86-64.so.2
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on".
Evaluation of the expression containing the function
(_gdb_expr) will be abandoned.
When the function is done executing, GDB will silently stop.
nothing changes when I modify 'unwindonsignal to (on/off)'
What did I forget this time ?
useful

Related

GDB is not able to read the core file it produced

I'm debugging a SIGSEGV error on a huge application running on Yocto/ARM64 (iMX8QM).
If I run the application in GDB, I can get the backtrace:
Thread 1 "HmiAppCentral" received signal SIGSEGV, Segmentation fault.
0x0000000000b0a0d0 in kanzi::Node3D::~Node3D() ()
(gdb) bt
#0 0x0000000000b0a0d0 in kanzi::Node3D::~Node3D() ()
#1 0x0000000000cd4e44 in kanzi::Model3D::~Model3D() ()
#2 0x0000000000b09c38 in kanzi::Node3D::removeChild(unsigned long) ()
[...]
Then I export the core dump, quit GDB and restart it:
(gdb) generate-core-file
warning: target file /proc/2279/cmdline contained unexpected null characters
[...]
gdb -c core.2279
Then GDB is not able to print the backtrace anymore:
(gdb) bt full
#0 0x0000000000b0a0d0 in ?? ()
No symbol table info available.
#1 0x0000000000000001 in ?? ()
No symbol table info available.
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
The address of the first frame is correct (0x0000000000b0a0d0), however GDB is not able to find the function name when reloading the core dump. Any hint?
Just like when the OS creates a core file, the original program executable is not included in the core file itself, and it is this executable that contains the debug information (or allows GDB to find the debug information).
What this means is, if you want to debug with the debug information then you need to provide both the executable and the core file, so something like:
gdb my_program.exe -c core.pid

Gdb cannot find assertion failure positions after recompiling

It seems that gdb fails finding the code position of an assertion failure, after I recompile my code. More precisely, I expect the position of a signal raise, relative to an assertion failure, to be
0x00007ffff7a5ff00 in raise () from /lib64/libc.so.`6
while instead I obtain
0x00007ffff7a5ff00 in ?? ()
For instance, consider the following code
#include <assert.h>
int main()
{
assert(0);
return 0;
}
compiled with debug symbols and debugged with gdb.
> gcc -g main.c
> gdb a.out
On the first run of gdb, the position is found, and the backtrace is reported correctly:
GNU gdb (Gentoo 8.0.1 p1) 8.0.1
...
(gdb) r
Starting program: /home/myself/a.out
a.out: main.c:5: main: Assertion `0' failed.
Program received signal SIGABRT, Aborted.
0x00007ffff7a5ff00 in raise () from /lib64/libc.so.6
(gdb) bt
#0 0x00007ffff7a5ff00 in raise () from /lib64/libc.so.6
#1 0x00007ffff7a61baa in abort () from /lib64/libc.so.6
#2 0x00007ffff7a57cb7 in ?? () from /lib64/libc.so.6
#3 0x00007ffff7a57d72 in __assert_fail () from /lib64/libc.so.6
#4 0x00005555555546b3 in main () at main.c:5
(gdb)
The problem comes when I recompile the code. After recompiling, I issue the run command in the same gdb instance. Gdb re-reads the symbols, starts the program from the beginning, but does not find the right position:
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
`/home/myself/a.out' has changed; re-reading symbols.
Starting program: /home/myself/a.out
a.out: main.c:5: main: Assertion `0' failed.
Program received signal SIGABRT, Aborted.
0x00007ffff7a5ff00 in ?? ()
(gdb) bt
#0 0x00007ffff7a5ff00 in ?? ()
#1 0x0000000000000000 in ?? ()
(gdb) up
Initial frame selected; you cannot go up.
(gdb) n
Cannot find bounds of current function
At this point the debugger is unusable. One cannot go up, step forward.
As a workaround, I can manually reload the file, and positions are found again.
(gdb) file a.out
Load new symbol table from "a.out"? (y or n) y
Reading symbols from a.out...done.
(gdb) r
Starting program: /home/myself/a.out
a.out: main.c:5: main: Assertion `0' failed.
Program received signal SIGABRT, Aborted.
0x00007ffff7a5ff00 in raise () from /lib64/libc.so.6
(gdb)
Unfortunately, after reloading the file this way, gdb fails resetting the breakpoints.
ERRATA CORRIGE: I was experiencing failure in resetting the breakpoints using gdb 7.12.1. After upgrading to 8.0.1 the problem vanished. Supposedly, this was related to the bugfix https://sourceware.org/bugzilla/show_bug.cgi?id=21555. However, code positions where assertions fail still cannot be found correctly.
Does anybody have any idea about what is going on here?
This has started happening after a system update. The system update recompiled all system libraries, including the glibc, as position independent code, i.e., compiled with -fPIC.
Also, the version of the gcc I am using is 6.4.0
Here is a workaround. Since file re-reads the symbols correctly, while run does not, we can define a hook for the command run so to execute file before:
define hook-run
pi gdb.execute("file %s" % gdb.current_progspace().filename)
end
after you change the source file and recompile u are generating a different file from the one loaded to GDB.
you need to stop the running debug cession and reload the file.
you cant save the previously defined breakpoints and watch points in the file to a changed source, since gdb is actually inserting additional code to your source to support breakpoints and registrar handlers.
if you change the source the the behavior is undefined and you need to reset those breakpoints.
you can refer to gdb manual regarding saving breakpoints in a file as
Mark Plotnick suggested, but it wont work if you change the file(from my experience)
https://sourceware.org/gdb/onlinedocs/gdb/Save-Breakpoints.html

gdb is showing "program exited" during startup

Why is gdb showing that the program exited during its startup, so before to stop at the first breakpoint in the main function ?
Some steps:
$ gdb --cd $programhome -tui -tty $reservedtty --args myprogram
b main
r
gdb shows:
Starting program: myprogram
During startup program exited with code 1.
I already tried to break at exit() function, without success.
Why is gdb exiting before to stop at the first breakpoint in the main function
GDB is not exiting. Your program does.
It does exit before reaching main.
This can happen for a few reasons, such as:
Corrupt binary -- the kernel rejects it in execve system call for some reason and not a single instruction of the program actually runs.
The dynamic linker rejects it (e.g. because some required library or symbol is missing)
Your shell refuses to execute the program (bad ~/.bashrc, bad $PATH, etc).
You can narrow down the actual cause by running the program outside GDB (does it run?), running without ~/.bashrc, using (gdb) catch syscall exit_group (on Linux), etc.
There was a permission issue accessing the secondary terminal port.
The gdb is being started with the parameter -tty which switches the input/output to another tty port (in that case pseudo: pts).
When the two terminals are opened by different users, that problem occurs, even if after the first logon you change the user with su command, the first user logged needed to be the same among the two ttys.

How to set earliest possible breakpoint

I'm trying to stop right after the module is loaded in gdb. Let's assume that the binary is completely stripped out of all symbol informations, so there's no main.
Ideally I'd set the breakpoint on the entry point, but that idea breaks down due to relocations:
(gdb) info target
Symbols from "./application".
Local exec file:
`./application', file type elf64-x86-64.
Entry point: 0xc154
...
(gdb) break *0xc154
Breakpoint 1 at 0xc154
(gdb) r
Starting program: ./application
Warning:
Cannot insert breakpoint 1.
Error accessing memory address 0xc154: Input/output error.
(gdb) info target
Symbols from "./application".
Unix child process:
Using the running image of child process 22835.
While running this, GDB does not access memory from...
Local exec file:
`./application', file type elf64-x86-64.
Entry point: 0x555555560154
Even though that kind-of works (I could set a new breakpoint on the new address and disable the original), it cannot be easily executed via gdb script / batch mode, because it has a failing instruction in the middle.
Is there a way to do that? Ideally something like "run single instruction", rather than "run" would be useful.
Update:
GDB-8.1 implemented starti command, which makes this very easy.
Entry point: 0xc154
This is a dynamically-linked, position-independent (PIE) binary.
You want to stop in the dynamic linker after that binary is loaded and relocated, but before it executed anything.
(gdb) set stop-on-solib-events 1
(gdb) run
Starting program: /tmp/a.out
Stopped due to shared library event (no libraries added or removed)
(gdb) info target
Symbols from "/tmp/a.out".
Unix child process:
Using the running image of child process 13746.
While running this, GDB does not access memory from...
Local exec file:
`/tmp/a.out', file type elf64-x86-64.
Entry point: 0x5555555545f0
...
(gdb) bt
#0 __GI__dl_debug_state () at dl-debug.c:77
#1 0x00007ffff7ddd488 in dl_main (phdr=<optimized out>, phnum=<optimized out>, user_entry=<optimized out>, auxv=0x7ffff7ffe870) at rtld.c:1678
#2 0x00007ffff7defb24 in _dl_sysdep_start (start_argptr=<optimized out>, dl_main=0x7ffff7ddc6e0 <dl_main>) at ../elf/dl-sysdep.c:244
#3 0x00007ffff7ddf365 in _dl_start_final (arg=0x7fffffffe440) at rtld.c:338
#4 _dl_start (arg=0x7fffffffe440) at rtld.c:564
#5 0x00007ffff7ddb6b8 in _start () from /lib64/ld-linux-x86-64.so.2

GDB - how to find out from where program exited

While debugging a program in GDB, I get an unexpected "program exited normally". So I'm wondering if is there a way to find out from where (which line) the program exited.
Program is multi-threaded, if that matters.
You could try the GDB command break exit to set a breakpoint on the exit(2) library call. If that doesn't get you what you need, maybe break _exit. You might need to start your program with 'sta' before getting the latter breakpoint to take. In either case, you should then be able to use the where command to get a stack trace showing where you were when the program decided to exit.
Usually with the command below when the application has finished executing:
(gdb) thread apply all bt
Of course, if you want to know the exact line you must compile your application with debugging symbols, i.e. -g
Set a breakpoint on _exit and then examine the stack.