Linux crash native stacks only have 1 line

Alexander Miloslavskiy alexandr.miloslavskiy at gmail.com
Wed Apr 8 15:08:32 UTC 2020


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`.

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