gdb tracepoint's action does not work - c++

trace point can be traced, but trace actions does not work normally.
at the last of gdb side below shows trace point is traced.
but "collect $regs" does not work as expected.
my platform is RH6.4.
1. gdbserver side.
gdbserver :10000 ./a.out
Process ./a.out created; pid = 10466
Listening on port 10000
Remote debugging from host 127.0.0.1
2. gdb side.
gdb a.out
(gdb) target remote :10000
Remote debugging using :10000
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
0x00000033b7000b00 in _start () from /lib64/ld-linux-x86-64.so.2
Created trace state variable $trace_timestamp for target's variable 1.
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.107.el6.x86_64
(gdb) trace main
Tracepoint 1 at 0x400541: file a.c, line 12.
(gdb) actions 1
collect $regs
end
(gdb) tstart
(gdb) break 15
Breakpoint 2 at 0x40055f: file a.c, line 15.
Breakpoint 2, main (argc=1, argv=0x7fffca819f08) at a.c:18
18 sleep (1);
(gdb) cont
Continuing.
(gdb) tstop
(gdb) tfind
Found trace frame 0, tracepoint 1
12 c = 2;

I suppose you expected tracepoint to be in actual main declaration line in the source file, am I wrong?
The important part is that it is placed in function's entry point, this is, actually, first function's code line that, looking at the information you provided, it should be c = 2;
On the other hand, this is just a stupid detail, please note that you have no code at line 15 and breakpoint has been set at line 18.
Edit:
According to your comments, you expected tfind to dump all collected registers but you would need an extra step for this: by using tfind with no argument you selected next tracepoint (first one in this case) and, to dump this tracepoint's action collected info, you should call tdump

Related

GDB reading symbols with "symbol-file" command on a core file

I am trying to analyze segfault on a core file on linux. I am not sure if the following behavior is correct, thus i deliberately caused a segfault using
#include <signal.h>
int main() {
raise(SIGSEGV);
}
the binary is build with debug info i.e.
file mainTestFile
mainTestFile: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, with debug_info, not stripped
notice how it does say "with debug_info, not stripped" at the end
when i execute the binary i get a core file generated which is called core-mainTestFile.20474
(In order to generate the core file i hat to set my ulimit to unlimited i.e.
ulimit -c unlimited
)
if i run only the binary under GDB and do backtrace "bt" then i get the segfault and i get all names of the functions involved
printed nicely i.e. notice how the gdb says when starting "reading symbols from ./mainTestFile...done."
gdb ./mainTestFile
GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
....
reading symbols from ./mainTestFile...done.
(gdb) run
Starting program: /src/exe/mainTestFile
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
__GI_raise (sig=<optimized out>) at ../sysdeps/unix/sysv/linux/raise.c:51
51 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 __GI_raise (sig=<optimized out>) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x0000000000402dad in main (argc=1, argv=0x7fffffffda38) at /src/exe/main.cpp:53
(gdb)
however if i try to anaylise only the core file with gdb like that
gdb -c core-mainTestFile.20474
then i get only question marks
the when i execute "bt" then i do not see the names of the methods, instead i get question marks
(gdb) bt
#0 0x00007f34d8842e97 in ?? ()
#1 0x0000000000000000 in ?? ()
they only workaround i found is to supply the binary directly at the command line then it all gets printed nicely.
even if i try to tell GDB to use the symbols file and point that to the binary file which does have the symbols
i.e.
symbol-file /src/exe/mainTestFile
then GDB says
Reading symbols from /src/exe/mainTestFile...done
and when i execute bt i see the question marks again? Why is that. Is GDB not able to get the symbols out of the binary?
it only works if supply the binary directly on the command like like:
gdb /src/exe/mainTestFile -c core-mainTestFile.20474
my question is should the GDB be able to read symbols of the binary when directly supplying him the binary over the "symbol-file" command or not. Why is this working when supping him directly the binary over the command line, what is the difference?
should the GDB be able to read symbols of the binary when directly supplying him the binary over the "symbol-file" command or not.
In theory, using symbol-file and core-file commands in either order in GDB should be equivalent.
But there is a bug: symbol-file followed by core-file works, and the opposite order doesn't.
Since generally the end-user can always rearrange his commands into the order that works, this has never propagated to the top of any GDB developer's queue of things to fix.
Related bug (but not an exact duplicate).

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

call dlopen from 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

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

Stopping at the first machine code instruction in GDB

After loading an executable into gdb, how do I break at the entry point, before the first instruction is executed?
The executable I'm analyzing is a piece of malware that's encrypted so break main does absolutely nothing.
Starting with GDB 8.1, there's a special command for this: starti. Example GDB session:
$ gdb /bin/true
Reading symbols from /bin/true...(no debugging symbols found)...done.
(gdb) starti
Starting program: /bin/true
Program stopped.
0xf7fdd800 in _start () from /lib/ld-linux.so.2
(gdb) x/5i $pc
=> 0xf7fdd800 <_start>: mov eax,esp
0xf7fdd802 <_start+2>: call 0xf7fe2160 <_dl_start>
0xf7fdd807 <_dl_start_user>: mov edi,eax
0xf7fdd809 <_dl_start_user+2>: call 0xf7fdd7f0
0xf7fdd80e <_dl_start_user+7>: add ebx,0x1f7e6
The info files command might give you an address you can break on:
(gdb) info files
...
Entry point: 0x80000000
...
(gdb) break *0x80000000
(gdb) run
This hack was obsoleted by starti, but useful if you're stuck with older GDB.
The no-brainer solution is to use the side-effect of failure to set a breakpoint:
$ gdb /bin/true
Reading symbols from /bin/true...(no debugging symbols found)...done.
(gdb) b *0
Breakpoint 1 at 0x0
(gdb) r
Starting program: /bin/true
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x0
(gdb) disas
Dump of assembler code for function _start:
=> 0xf7fdd800 <+0>: mov eax,esp
0xf7fdd802 <+2>: call 0xf7fe2160 <_dl_start>
End of assembler dump.
(gdb) d 1 # delete the faulty breakpoint
(You need to delete the invalid breakpoint before you can continue or single-step.)
Idea taken from this answer at RE.SE.
"b _start" or "b start" might or might not work. If not, find out the entrypoint address with readelf/objdump and use "b *0x<hex address>".
After loading an executable into gdb, how do I break at the entry point, before the first instruction is executed?
You can find what functions are called before int main() with set backtrace past-main on and after finding them set a breakpoint on them and restart your program:
>gdb -q main
Reading symbols from /home/main...done.
(gdb) set backtrace past-main on
(gdb) b main
Breakpoint 1 at 0x40058a: file main.cpp, line 25.
(gdb) r
Starting program: /home/main
Breakpoint 1, main () at main.cpp:25
25 a();
(gdb) bt
#0 main () at main.cpp:25
#1 0x0000003a1d81ed1d in __libc_start_main () from /lib64/libc.so.6
#2 0x0000000000400499 in _start ()
(gdb) b _start
Breakpoint 2 at 0x400470
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/main
Breakpoint 2, 0x0000000000400470 in _start ()