tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: gcc: optimizations, and stack traces
Le 09/02/2018 à 13:32, Joerg Sonnenberger a écrit :
On Fri, Feb 09, 2018 at 11:23:17AM +0100, Maxime Villard wrote:
It implies that if a bug occurs _before_ these two instructions are executed,
we have a %rbp that points to the _previous_ function, the one we got called
from. And therefore, GDB does not display the current function (where the bug
actually happened), but displays its caller.
This analysis is wrong. GDB will first of all look for frame annotation
data, i.e. .eh_frame or the corresponding .debug_frame. Only if it can't
find such annotation will it fall back to guessing from the function
itself. We default to building .eh_frame for all binaries, but I'm not
completely sure if GCC will create async unwind tables by default.
I've investigated the issue. My analysis was only partly incorrect.
In fact, GDB _does_ display the current function: it reads the %rip from which
we faulted, and finds the function name by looking at the symbol table.
However, it may not display the caller of the function. In order to obtain
the caller GDB will iterate as I said:
[the current function was displayed]
uint64_t *rbp = read_rbp();
uint64_t rip;
while (1) {
if (rbp == NULL)
break; /* End of the chain */
rip = *(rbp + 1);
name = find_function_from_rip(rip); /* whatever */
print(name);
rbp = (uint64_t *)*ptr;
}
Here, in the first iteration, %rbp points to the frame the caller pushed, and
therefore it indicates the %rip of the caller of the caller. But the %rip of
the caller itself is skipped.
If you add a global function that dereferences a pointer _before_ pushing a
frame, and then call this function from sys_rasctl(), the GDB trace you get
is:
my_deref_func()
syscall()
sys_rasctl is missing. So we have the same problem, and we need to find a way
to tell GCC to always push the frame at the beginning of the functions.
Le 09/02/2018 à 12:13, Valery Ushakov a écrit :
Does gcc actually generates code like that? I thought that it can
delay frame pointer creation, but only until it needs to make a nested
call, to C in your example, (as in the sample I showed in another mail
to this thread).
Indeed, it can't generate code like that. I was confused, because I had
specific requirements when I first investigated this (getting a trace across
interrupts).
Maxime
Home |
Main Index |
Thread Index |
Old Index