Linux crash native stacks only have 1 line

Volker Simonis volker.simonis at gmail.com
Wed Apr 8 18:49:53 UTC 2020


On Wed, Apr 8, 2020 at 5:08 PM Alexander Miloslavskiy
<alexandr.miloslavskiy at gmail.com> wrote:
>
> On 08.04.2020 16:25, Volker Simonis wrote:
> > Libjvm.so is already linked against libgcc anyway (either statically
> > or dynamically, depending on the "--with-stdc++lib" configure option".
>
> I understand that this means that yes, libgcc is fine to use.
>
> > But the man page for "backtrace()" mentions;
> >
> > These functions make some assumptions about how a function's return
> > address is stored on the stack.  Note the following:
> >   * Omission  of  the frame pointers (as implied by any of gcc(1)'s
> > nonzero optimization levels) may cause these assumptions to be
> > violated.
> >   * Inlined functions do not have stack frames.
> >   * Tail-call optimization causes one stack frame to replace another.
> >
> > So I'm not sure if the result will be really better.
>
> Luckily, 'backtrace()' is good enough. In fact, I would be surprised if
> it was too dumb.
>
> Try it yourself:
> ----------------
> #include <gtk/gtk.h>
> #include <stdio.h>
> #include <csignal>
> #include <execinfo.h>
>
> void OnButtonClicked(GtkWidget*, gpointer*) {
>         void* myBacktrace[256];
>         int length = backtrace(myBacktrace, 256);
>         for (int i = 0; i < length; i++) {
>                 printf("backtrace[%d] = %p\n", i, myBacktrace[i]);
>         }
>
>         std::raise(SIGINT);
> }
>
> int main(int argc, char **argv) {
>         gtk_init(&argc, &argv);
>         GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
>         g_signal_connect(window, "delete_event", gtk_main_quit, NULL);
>         gtk_window_resize(GTK_WINDOW(window), 200, 100);
>
>         GtkWidget *button = gtk_button_new_with_label("Test");
>         gtk_container_add(GTK_CONTAINER(window), button);
>         g_signal_connect(button, "clicked", G_CALLBACK(OnButtonClicked), 0);
>
>         gtk_widget_show_all(window);
>         gtk_main();
>         return 0;
> }
> ----------------
>
> Compile with -O2:
> g++ -O2 -g Snippet.cpp -o Snippet `pkg-config --cflags gtk+-3.0`
> `pkg-config --libs gtk+-3.0`
>
> Run under GDB. When it stops, run gdb `bt`.
>

Are you sure that the "backtrace" command in gdb is using the
"backtrace()" function from libgcc?

Just asking because I'm not sure. I thought gdb has its own stack
unwinding logic and applies some extra tricks but it's actually quite
a while since I've last looked into the sources :)

> I see that `backtrace()` is almost perfect!
>
> It's easy to verify that there are no frame pointers, either by
> inspecting stack with `x/32a $rsp` or by disassembling like `disas
> g_signal_emit`.
>
> >
> > Also notice that "VMError::print_native_stack()" prints a mixed
> > Native/Java stack which ideally looks something like:
>
> > If you use a helper function like "backtrace()", it will only unwind
> > native frames until it reaches the first Java frame because it won't
> > be able to unwind Java frames. Even gdb can not do that , because it
> > doesn't know the frame layout of HotSpots JIT compiled or interpreted
> > frames.
>
> Right, that's why I intend to use `_Unwind_Backtrace` directly instead
> of `backtrace()`. The first is a powerful iterator-like API, second is
> simple to use but without any advanced stuff.
>
> How does that sound to you?


More information about the hotspot-dev mailing list