]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Fix getrbp()
authorMichał Kępień <michal@isc.org>
Fri, 30 Oct 2020 08:12:50 +0000 (09:12 +0100)
committerMichał Kępień <michal@isc.org>
Fri, 30 Oct 2020 08:12:50 +0000 (09:12 +0100)
The following compiler warning is emitted for the BACKTRACE_X86STACK
part of lib/isc/backtrace.c:

    backtrace.c: In function ‘getrbp’:
    backtrace.c:142:1: warning: no return statement in function returning non-void [-Wreturn-type]

While getrbp() stores the value of the RBP register in the RAX register
and thus does attempt to return a value, this is not enough for an
optimizing compiler to always produce the expected result.  With -O2,
the following machine code may be generated in isc_backtrace_gettrace():

    0x00007ffff7b0ff7a <+10>: mov    %rbp,%rax
    0x00007ffff7b0ff7d <+13>: mov    $0x17,%eax
    0x00007ffff7b0ff82 <+18>: retq

The above is equivalent to:

    sp = (void **)getrbp();
    return (ISC_R_NOTFOUND);

and results in the backtrace never getting printed.

Fix by using an intermediate variable.  With this change in place, the
machine code generated with -O2 becomes something like:

    0x00007ffff7af5638 <+24>: mov    $0x17,%eax
    0x00007ffff7af563d <+29>: mov    %rbp,%rdx
    0x00007ffff7af5640 <+32>: test   %rdx,%rdx
    0x00007ffff7af5643 <+35>: je     0x7ffff7af56bd <isc_backtrace_gettrace+157>
    ...
    0x00007ffff7af56bd <+157>: retq

(Note that this method of grabbing a stack trace is finicky anyway
because in order for RBP to be relied upon, -fno-omit-stack-frame must
be present among CFLAGS.)

lib/isc/backtrace.c

index cf46e6374302440c3a41cc671afc026b254d914d..5560a4d02e6b2b0b1eafbd56e9634e1263864b31 100644 (file)
@@ -138,7 +138,9 @@ isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes) {
 #ifdef __x86_64__
 static unsigned long
 getrbp(void) {
-       __asm("movq %rbp, %rax\n");
+       unsigned long rbp;
+       __asm("movq %%rbp, %0\n" : "=r"(rbp));
+       return rbp;
 }
 #endif /* ifdef __x86_64__ */