[R-pkg-devel] RFC: C backtraces for R CMD check via just-in-time debugging

Vladimir Dergachev vo|ody@ @end|ng |rom m|nd@pr|ng@com
Tue Mar 12 03:10:20 CET 2024



On Tue, 12 Mar 2024, Ivan Krylov wrote:

> Vladimir,
>
> Thank you for the example and for sharing the ideas regarding
> symbol-relative offsets!
>
> On Thu, 7 Mar 2024 09:38:18 -0500 (EST)
> Vladimir Dergachev <volodya using mindspring.com> wrote:
>
>>          unw_get_reg(&cursor, UNW_REG_IP, &pc);
>
> Is it ever possible for unw_get_reg() to fail (return non-zero) for
> UNW_REG_IP? The documentation isn't being obvious about this. Then
> again, if the process is so damaged it cannot even read the instruction
> pointer from its own stack frame, any attempts at self-debugging must
> be doomed.

Not sure. I think it just returns what is in it, you will get a false 
reading if the stack is corrupted. The way that I see it - some printout 
is better than none, and having signs that stack is badly corrupted is a 
useful debugging clue.

>
>>    * this should work as a package, but I am not sure whether the
>> offsets between package symbols and R symbols would be static or not.
>
> Since package shared objects are mmap()ed into the address space and
> (at least on Linux with ASLR enabled) mmap()s are supposed to be made
> unpredictable, this offset ends up not being static. On Linux, R seems
> to be normally built as a position-independent executable, so no matter
> whether there is a libR.so, both the R base address and the package
> shared object base address are randomised:
>
> $ cat ex.c
> #include <stdint.h>
> #include <R.h>
> void addr_diff(void) {
> ptrdiff_t diff = (char*)&addr_diff - (char*)&Rprintf;
> Rprintf("self - Rprintf = %td\n", diff);
> }
> $ R CMD SHLIB ex.c
> $ R-dynamic -q -s -e 'dyn.load("ex.so"); .C("addr_diff");'
> self - Rprintf = -9900928
> $ R-dynamic -q -s -e 'dyn.load("ex.so"); .C("addr_diff");'
> self - Rprintf = -15561600
> $ R-static -q -s -e 'dyn.load("ex.so"); .C("addr_diff");'
> self - Rprintf = 45537907472976
> $ R-static -q -s -e 'dyn.load("ex.so"); .C("addr_diff");'
> self - Rprintf = 46527711447632
>
>>    * R ought to know where packages are loaded, we might want to be
>> clever and print out information on which package contains which
>> function, or there might be identical R_init_RMVL() printouts.
>
> That's true. Informaion on all registered symbols is available from
> getLoadedDLLs().

Ok, so this is reasonably straighforward.

best

Vladimir Dergachev

>
> -- 
> Best regards,
> Ivan
>



More information about the R-package-devel mailing list