How to Debug Java -Jni Using Gdb on Linux

JDK9 Hotspot debug using gdb, causing SIGSEGV Segmentation fault in eclipse/Ubuntu terminal

The HotSpot JVM uses the SEGV signal internally for a few different things (NullPointerException, safepoints, ...) so this is most likely not an error. When debugging HotSpot, it is useful to tell gdb to let the application handle the SEGV signal:

handle SIGSEGV pass noprint nostop

When you are already paused because gdb received the signal, you can resume execution with

continue

You can also use those commands in the debugger console of eclipse.

It might be useful to create a .gdbinit file that contains that command. In Eclipse you can then point your run configuration to that file ("GDB command file" under "Debugger" in the run configuration).
That way you don't need to type that command on every HotSpot debugging session.

How can you debug a process using gdb without pausing it?

There's no way in gdb to attach without some sort of pause.

The Linux kernel provides some support for this via PTRACE_SEIZE, but gdb doesn't use this yet. There's a bug in bugzilla you can track, "Bug 15250 - use PTRACE_SEIZE and PTRACE_INTERRUPT"

Meanwhile you could try setting gdb into "observer mode". Then you could attach and use continue & to continue the process in the background. You may need to set various settings, like target-async, depending on the gdb version.

I am not totally certain if this will work. It is worth a try. Note that there is a window in which the program will be paused. This is unavoidable right now.

Why does Debugging Native code using GDB of a JAR application hangs Ubuntu UI (X11 Process) when breakpoint is hit?

why UI or X11 process hangs during the above scenario

As Mark Plotnick correctly pointed out, the X11 process does not hang. Rather, it grabs the keybard (all keyboard events are dispatched to it), and can not release that grab (it is stopped by GDB before it reaches the release point).

There are two common solutions:

  1. ask the application to not do the keyboard grab (as Mark said), or
  2. debug the application from a separate machine (this can even be done on single physical machine: just run the application inside a VM).

P.S. Why do application menues grab keyboard? Because hitting Esc usually dismisses the menu, and they want to see that Esc regardless of whether the application has input focus or not).

How to do gdb with java -cp myjar.jar class.myclass

From GDB's point of view, the program here is java. It accepts many arguments (-cp , classname etc)

You can set arguments using set args

http://www.delorie.com/gnu/docs/gdb/gdb_19.html

Using pmap and gdb to find native memory leak

A very basic approach: you could try looking at who is calling mmap (and not munmap).

  • attach to the process
  • set breakpoint on mmap, with commands to print arguments and backtrace (maybe 5 frames) and continue
  • similar thing for munmap
  • redirect output
  • let it run for a day
  • detach
  • match mmaps with munmaps in the output

With pmap periodically running on the side, you may be able to match newer anon regions with mmap backtraces (might need playing around with frame count).


There is already this nice little article LINUX GDB: IDENTIFY MEMORY LEAKS to get you started.

Note:

  • you are looking for mmap and munmap, not malloc and free
  • you will have to find out the offset of the return from mmap
  • I have not tried the script from the article but I think it would do what the article claims

Finding mmap return instruction offset (from start of mmap):
Just fire up gdb with any executable on the same host

[ aquila ~ ] $ gdb -q /usr/bin/ls
Reading symbols from /usr/bin/ls...Reading symbols from /usr/bin/ls...(no debugging symbols found)...done
.
(no debugging symbols found)...done.
Missing separate debuginfos, use: dnf debuginfo-install coreutils-8.27-5.fc26.x86_64
(gdb) set pagination off
(gdb) set breakpoint pending on
(gdb) b mmap
Function "mmap" not defined.
Breakpoint 1 (mmap) pending.
(gdb) r
Starting program: /usr/bin/ls

Breakpoint 1, 0x00007ffff7df2940 in mmap64 () from /lib64/ld-linux-x86-64.so.2
(gdb) disassemble
Dump of assembler code for function mmap64:
=> 0x00007ffff7df2940 <+0>: test %rdi,%rdi
0x00007ffff7df2943 <+3>: push %r15
0x00007ffff7df2945 <+5>: mov %r9,%r15
:
:
0x00007ffff7df2973 <+51>: mov $0x9,%eax
:
0x00007ffff7df2982 <+66>: pop %rbx
:
0x00007ffff7df298a <+74>: pop %r15
0x00007ffff7df298c <+76>: retq
0x00007ffff7df298d <+77>: nopl (%rax)
:
:
0x00007ffff7df29d8 <+152>: mov $0xffffffffffffffff,%rax
0x00007ffff7df29df <+159>: jmp 0x7ffff7df2982 <mmap64+66>
End of assembler dump.

Note the return instruction here:

0x00007ffff7df298c <+76>:    retq

So, on my machine, the second breakpoint would have to be set at (mmap+76).

Once you determine this offset, you can verify this offset by attaching to your target process and disassembling what is at that offset. E.g. taking my current shell as my target process:

[ aquila ~ ] $ echo $$
9769
[ aquila ~ ] $ gdb -q
(gdb) attach 9769
Attaching to process 9769
Reading symbols from /usr/bin/bash...Reading symbols from /usr/bin/bash...(no debugging symbols found)..
.done.
(no debugging symbols found)...done.
Reading symbols from /lib64/libtinfo.so.6...Reading symbols from /lib64/libtinfo.so.6...(no debugging sy
mbols found)...done.
(no debugging symbols found)...done.
Reading symbols from /lib64/libdl.so.2...(no debugging symbols found)...done.
Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Reading symbols from /lib64/libnss_files.so.2...(no debugging symbols found)...done.
0x00007fcfc67cc18a in waitpid () from /lib64/libc.so.6
Missing separate debuginfos, use: dnf debuginfo-install bash-4.4.12-5.fc26.x86_64
(gdb) x/i mmap+76
0x7fcfc680375c <mmap64+76>: retq

I'm not very sure hbreak is required, plain old break might work as well.



Related Topics



Leave a reply



Submit