Can strace tell me where in my code a syscall is called? - debugging

I'm trying to debug why ngspice prints annoying newlines to stderr while running a simulation. I'm trying to locate it in one of the 2400 source files tracing back to 1993 but it's not as easy as it sounds! It does however mean that I have a binary with all debug information embedded.
My first idea was that strace could help me locate what I believe is the offending call and trace it back to the source code. For example, I'm pretty sure that this is the offending syscall:
brk(0x55d1a84e9000) = 0x55d1a84e9000
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, {tv_sec=0, tv_nsec=61462905}) = 0
>> write(2, "\n", 1) = 1
getrusage(RUSAGE_SELF, {ru_utime={tv_sec=0, tv_usec=26269}, ru_stime={tv_sec=0, tv_usec=35243}, ...}) = 0
openat(AT_FDCWD, "/proc/self/statm", O_RDONLY) = 3
I had hoped that if I traced an executable that had debug information, strace would show me the place in the source code, but that did not happen automatically and the manual is a little overwhelming.
I found a section in the manual called Tracing but couldn't find anything specific.
Is it possible with strace, and if so: How? If not, do you have any other suggestions?

Obvious in hindsight, but one very useful flag is -k. From the man-page:
-k Print the execution stack trace of the traced processes after each system call.
This needs a binary with debug information, and it will get extremely noisy, but combined with a simple filter (-e write in this case) you will eventually get something that looks like this:
write(2, "\n", 1
) = 1
> /lib/x86_64-linux-gnu/libc-2.28.so(__write+0x14) [0xea504]
> /lib/x86_64-linux-gnu/libc-2.28.so(_IO_file_write+0x2d) [0x7b3bd]
> /lib/x86_64-linux-gnu/libc-2.28.so(_IO_file_setbuf+0xef) [0x7a75f]
> /lib/x86_64-linux-gnu/libc-2.28.so(_IO_do_write+0x19) [0x7c509]
> /lib/x86_64-linux-gnu/libc-2.28.so(_IO_file_overflow+0x103) [0x7c8f3]
> /home/pipe/src/ngspice/debug/src/ngspice(OUTendPlot+0x1ae) [0xd7643]
> /home/pipe/src/ngspice/debug/src/ngspice(DCop+0x167) [0x4cd788]
> /home/pipe/src/ngspice/debug/src/ngspice(CKTdoJob+0x428) [0x4c70dd]
> /home/pipe/src/ngspice/debug/src/ngspice(if_run+0x3b9) [0xe5d3e]
> /home/pipe/src/ngspice/debug/src/ngspice(dosim+0x428) [0xe02ee]
From this I could eventually find the right place after tracking some function inline optimizations.

Using gdb, you can set conditional syscall catchpoints based on the args to the system call (analogous to the way you'd set conditional breakpoints on entry to a function based on the args to the function call). Then, when the catchpoint is triggered, you can see where the caller is (file name, line number, and source code).
Here's an example for x86_64.
$ cat gtest.c
#include <unistd.h>
int main()
{
write(1, "text\n", 5);
write(2, "text2\n", 6);
write(2, "\n", 1);
return 0;
}
$ cc gtest.c -g -o gtest
$ gdb -q gtest
Reading symbols from gtest...done.
(gdb) list
1 #include <unistd.h>
2 int main()
3 {
4 write(1, "text\n", 5);
5 write(2, "text2\n", 6);
6 write(2, "\n", 1);
7 return 0;
8 }
(gdb) catch syscall write
Catchpoint 1 (syscall 'write' [1])
(gdb) condition 1 $rdi == 2 && *(char *)$rsi == '\n' && $rdx == 1
(gdb) r
Starting program: /home/mp/gtest
text
text2
Catchpoint 1 (call to syscall write), 0x00007fffff13b970 in __write_nocancel ()
at ../sysdeps/unix/syscall-template.S:84
84 ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) bt
#0 0x00007fffff13b970 in __write_nocancel () at ../sysdeps/unix/syscall-template.S:84
#1 0x00000000080006f6 in main () at gtest.c:6
(gdb) up
#1 0x00000000080006f6 in main () at gtest.c:6
6 write(2, "\n", 1);
(gdb)

My first idea was that strace could help me locate what I believe is the offending call and trace it back to the source code.
You guessed right, but must have overlooked this in the strace manual page:
-i Print the instruction pointer at the time of the system call.

Related

Can a debugger produce a list of all executed lines of source code of an attached process?

I'm working for a company, that does not have a habit of adding log entries in their source code.
Hence, if something goes wrong, the amount of logs, explaining what might have happened, is too small to make any real analysis.
Therefore I'm looking for a tool which can do the following:
Attach to a running process and link to the symbols file.
Follow all lines of source code which are executed.
After a certain key is pressed (like "Ctrl+C"), produce a report which looks as follows:
[]
file1.c:010: function1(1, 2, 5)
file1.c:011: sum(1,2)
file1.c:020: return 3;
file1.c:012: sum(3,5);
file1.c:020: return 8;
file1.c:012: return 8;
I can imagine this question sounding very naïve, but if I can have something which just approaches this result, it might be very useful.
Does anybody know if this can be achieved using windbg, cdb, Visual Studio or any other means?
do you have the source code and symbols for your exe
if yes windbg can step and print source lines
demo below for a simple recv sample
start an executable whose pdb with src info is available
:\>cdb recv
Microsoft (R) Windows Debugger Version 10.0.16299.15 X86
windbg breaks on system breakpoint
ntdll!LdrpDoDebuggerBreak+0x2c:
771a05a6 cc int 3
enable loading of line information
enable stepping in source mode
enable printing of src lines
0:000> .lines
Line number information will be loaded
0:000> l+t
Source options are 1:
1/t - Step/trace by source line
0:000> l+s
Source options are 5:
1/t - Step/trace by source line
4/s - List source code at prompt
disallow all other output except src
0:000> .prompt_allow -reg -dis -sym -ea
Allow the following information to be displayed at the prompt:
(Other settings can affect whether the information is actually displayed)
src - Source info for current instruction
Do not allow the following information to be displayed at the prompt:
sym - Symbol for current instruction
dis - Disassembly of current instruction
ea - Effective address for current instruction
reg - Register state
go to main and step 10 times
you will see each step is showing the src
read and use controlling the target in windbg help to know about various
execution methods like step until return , step until branch etc
0:000> g recv!main
ModLoad: 69f50000 69f53000 C:\Windows\system32\api-ms-win-core-synch-l1-2-0.DLL
> 13: int __cdecl main() {
0:000> p 10
> 24: iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
> 25: if (iResult != NO_ERROR) {
> 30: ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
> 31: if (ConnectSocket == INVALID_SOCKET) {
> 38: clientService.sin_family = AF_INET;
> 39: clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
> 40: clientService.sin_port = htons( 27015 );
> 42: iResult = connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) );
> 43: if ( iResult == SOCKET_ERROR) {
> 44: closesocket (ConnectSocket);
> 45: printf("Unable to connect to server: %ld\n", WSAGetLastError());
Unable to connect to server: 0
> 66: WSACleanup();
> 67: return 1;
> 88: }
*** The C++ standard library and CRT step filter can be enabled to skip this fun
ction. Run .settings set Sources.SkipCrtCode = true">.settings set Sources.SkipC
rtCode = true to enable it. ***

Kernel Debugging: Gdb not able to set breakpoints and no effect of SIGINT to bring back in Debugging Session

Linux Kernel : 4.13-rc7 x86_64
Configured Buildroot and Qemu for Linux Kernel Debugging.
Launch Qemu using following Command:
qemu-system-x86_64 -kernel linux-4.13-rc7/arch/x86/boot/bzImage -initrd buildroot-2017.02.5/output/images/rootfs.cpio -append "root=/dev/ram0 console=tty0 kgdboc=ttyS0,9600 kgdbwait" -chardev pty,id=pty -device isa-serial,chardev=pty
Now, In Next terminal window, launch gdb and proceed following gdb commands:
`
gdb-peda$ file vmlinux
Reading symbols from vmlinux...done.
warning: File "/root/drive/linux-4.13-rc7/scripts/gdb/vmlinux-gdb.py" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load".
To enable execution of this file add
add-auto-load-safe-path /root/drive/linux-4.13-rc7/scripts/gdb/vmlinux-gdb.py
line to your configuration file "/root/.gdbinit".
To completely disable this security protection add
set auto-load safe-path /
line to your configuration file "/root/.gdbinit".
For more information about this security protection see the
"Auto-loading safe path" section in the GDB manual. E.g., run from the shell:
info "(gdb)Auto-loading safe path"
gdb-peda$ target remote /dev/pts/3
Remote debugging using /dev/pts/3
Warning: not running or target is remote
0xffffffffbd6f65af in ?? ()
gdb-peda$ b start_kernel
Breakpoint 1 at 0xffffffff81f79ad7: file init/main.c, line 510.
gdb-peda$ c
Continuing.
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0xffffffff81f79ad7
Command aborted.
gdb-peda$ `
I also tried in Qemu machine:
echo "g" > /proc/sysrq-trigger. But, nothing happened .
Also, tried to set Hardware Breakpoints using hbreak on start_kernel, but nothing happened.
I figured out the solution by own , I did the following things to get working solution:
Apply patch to gdb then recompile it with patch in <$GDB_FOLDER>/gdb/remote.c file.
GDB Patch to resize its internal buffer :
`
root# diff -u gdb-8\ \(1\).0/gdb/remote.c gdb-8.0/gdb/remote.c
--- "gdb-8 (1).0/gdb/remote.c" 2017-06-04 21:24:54.000000000 +0530
+++ gdb-8.0/gdb/remote.c 2017-09-05 23:27:46.487820345 +0530
## -7583,7 +7583,27 ##
/* Further sanity checks, with knowledge of the architecture. */
if (buf_len > 2 * rsa->sizeof_g_packet)
- error (_("Remote 'g' packet reply is too long: %s"), rs->buf);
+ //error (_("Remote 'g' packet reply is too long: %s"), rs->buf); #patching
+ {
+ warning (_("Assuming long-mode change. [Remote 'g' packet reply is too long: %s]"), rs->buf);
+ rsa->sizeof_g_packet = buf_len ;
+
+ for (i = 0; i < gdbarch_num_regs (gdbarch); i++)
+ {
+ if (rsa->regs[i].pnum == -1)
+ continue;
+
+ if (rsa->regs[i].offset >= rsa->sizeof_g_packet)
+ rsa->regs[i].in_g_packet = 0;
+ else
+ rsa->regs[i].in_g_packet = 1;
+ }
+
+ // HACKFIX: Make sure at least the lower half of EIP is set correctly, so the proper
+ // breakpoint is recognized (and triggered).
+ rsa->regs[8].offset = 16*8;
+ }
+
/* Save the size of the packet sent to us by the target. It is used
as a heuristic when determining the max size of packets that the`
Build the minimal RootFS by Buildroot.
Launch Qemu by following command and launch new gdb then load vmlinux file .
In one terminal :
root# qemu-system-x86_64 -kernel /root/drive/linux-4.13-rc7/arch/x86/boot/bzImage -initrd /root/drive/buildroot-2017.02.5/output/images/rootfs.cpio -S -s
In another terminal :
gdb -q /root/drive/linux-4.13-rc7/vmlinux -ex "target remote localhost:1234"
Now set break point at start_kernel and continue, It will automatically hit the breakpoint.

How to get c++ enum value in Xcode?

I would like to know if this is possible to get the value of c++ enum item in Xcode.
In Visual Studio you just have to hover the item and you got a tooltip with its value but it does not do the same in Xcode.
I also tried to print the value in lldb console without success.
For instance with this simple enum:
enum Params{
eP1,
eP2,
eP3,
eP4,
eP5,
};
I tried different ways like p eP1 or p Param::eP1.
I also tried with an enum class with the same result.
At present, you have to use enumName:enumElement, but that is working for me:
> cat foo.cpp
#include <stdio.h>
enum Params
{
eP1,
eP2,
eP3,
eP4
};
int main()
{
enum Params elem = eP1;
printf ("%d\n", elem);
return 0;
}
> lldb a.out
(lldb) target create "a.out"
Current executable set to 'a.out' (x86_64).
(lldb) b s -p printf
Breakpoint 1: where = a.out`main + 29 at foo.cpp:14, address = 0x0000000100000f6d
(lldb) run
Process 26752 launched: '/private/tmp/a.out' (x86_64)
Process 26752 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100000f6d a.out`main at foo.cpp:14
11 int main()
12 {
13 enum Params elem = eP1;
-> 14 printf ("%d\n", elem);
^
15 return 0;
16 }
Target 0: (a.out) stopped.
(lldb) expr Params::eP1
(int) $0 = 0
If you still can't get this to work, can you post a more complete example where it fails?
The problem for lldb, BTW, is that the debug information is organized into the full debug information and then a name->info accelerator table. lldb depends on the accelerator tables for lookup (otherwise it would have to go looking through all the debug info which can get pretty slow for big apps). The accelerator tables at present only have the name of the enum, not the element names.

Ruby program halted in gdb fails to resume after writing to any IO using rb_eval_string

I'm using gdb to try to track down a memory leak in a ruby program.
I'm trying to print some debug data (or write it to a file), and it appears that any time anything is printed to any IO, the program fails to resume after I detach.
The simple test case is a program as follows:
#!/usr/bin/env ruby
counter = 0
loop do
puts "#{counter}\n"
counter += 1
sleep 1
end
I then attach gdb to the process via gdb -p PID and run p rb_eval_string("$stderr.puts(\"hi\\n\")") on the gdb console. This causes the failure to resume after detaching. If I run p rb_eval_string("a = 1") and detach, the ruby process resumes as normal.
The same problem happens if I attempt to write to a file or $stdout instead.
The backtrace of the program when it fails to resume looks like this:
(gdb) bt
#0 0x00007fcfb6617414 in pthread_cond_wait##GLIBC_2.3.2 () from /lib/x86_64-linux-gnu/libpthread.so.0
#1 0x0000000000543773 in native_cond_wait (mutex=0x15fcf30, cond=<optimized out>) at thread_pthread.c:309
#2 gvl_acquire_common (vm=0x15fcf20) at thread_pthread.c:64
#3 gvl_acquire (th=0x15fd520, vm=0x15fcf20) at thread_pthread.c:82
#4 native_sleep (timeout_tv=<synthetic pointer>, th=0x15fd520) at thread_pthread.c:918
I'm using gdb version 7.7 on Ubuntu Trusty with ruby 1.9.3.
Can anyone suggest how to get the program to resume?
Thanks!
I don't understand yet what's going on but it might be because of Ruby's sleep and the way rb_thread_sleep uses native_sleep (and I can reproduce your issue locally).
Instead of using sleep I just considered using a method with a high-cost, that would consume almost a second so I decided to just use an unoptimized fibonacci :-)
Here's the code:
# fibo.rb
def fibonacci(n)
return n if (0..1).include?(n)
fibonacci(n-1) + fibonacci(n-2)
end
i = 0
loop do
fibonacci(30)
i += 1
puts "#### i = #{i}"
end
Now, you should be able to (please note I'm using lldb instead of gdb, but it's the same thing (almost :-)) :
➜ ~ lldb ruby
Current executable set to 'ruby' (x86_64).
(lldb) r foo.rb
Process 41134 launched: '/Users/xxx/.rubies/ruby-2.1.0/bin/ruby' (x86_64)
#### i = 1
Process 41134 stopped
* thread #1: tid = 0x72502, 0x00000001000c4820 ruby`range_include + 256, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
frame #0: 0x00000001000c4820 ruby`range_include + 256
ruby`range_include + 256:
-> 0x1000c4820: movq 0x16a691(%rip), %rsi ; id_cmp
0x1000c4827: movq %rbx, %rdi
0x1000c482a: movl $0x1, %edx
0x1000c482f: movq %r12, %rcx
(lldb) call (void)rb_eval_string("puts 42")
42
(lldb) c
Process 41134 resuming
#### i = 2
#### i = 3
...

Using gdb, display multiple vars in one line?

How can I ask to display multiple vars in one line? So I want to get output like:
30 if(s[i] != '\0')
5: s[i] = 101 'e'
4: exp = 14
3: val = 123.45
2: sign = 1
1: i = 6
I've been typing in disp s[i] ENTER disp exp ENTER (etc, etc) and I just know there's got to be a better way to do this in one line of typing.
To establish multiple active "variable displays" without re-typing each of display i, display s[i], etc. every time you restart GDB, use a GDB "canned command sequence".
For example, add this to your ~/.gdbinit:
define disp_vars
disp i
disp sign
disp val
disp exp
disp s[i]
end
Now you can add all the displays at once by typing disp_vars at the GDB prompt.
Employed Russian gave the correct solution but for those that want see it used in an example see below. If you're not sure if you want to commit to putting the .gdbinit in your home directory, you can also put it in the directory you're executing the program from to experiment.
$ gcc -g atof_ex4.2.c
$ gdb ./a.out
(gdb) b 30
Breakpoint 1 at 0x1907: file atof_ex4.2.c, line 30.
(gdb) h user-defined
List of commands:
disp_vars -- User-defined
(gdb) disp_vars #this will enable the user defined canned sequence (but I haven't done run yet! So I'll this actually doesn't work yet.)
No symbol "i" in current context.
(gdb) r
Starting program: a.out
Breakpoint 1, atof (s=0xbffff028 "123.45e-6") at atof_ex4.2.c:30
30 if(s[i] != '\0')
(gdb) s # No disp_vars output yet because I have to do it AFTER 'run' command
32 if(s[i] == 'e' || s[i] == 'E')
(gdb) disp_vars # Now it will work ;)
(gdb) s
35 sign = (s[i] == '-') ? -1 : 1;
5: s[i] = 45 '-'
4: exp = 14
3: val = 123.45
2: sign = 1
1: i = 7
Of course 'r' is for run, 's' is for step, 'b' is for break, etc. I've also omitted some output. Notice that I had to enter the 'disp_vars' command again after 'run'. Thanks Employed Russian.

Resources