[Rd] Why does INT 3 (opcode 0xCC) SIGTRAP break to debugger (gdb) in Rgui.exe and Rterm.exe but NOT in R.exe on Windows (64 bit)?

@osp@m m@iii@g oii @itieid-im@de @osp@m m@iii@g oii @itieid-im@de
Wed Dec 11 21:42:56 CET 2019


I am developing a package to improve the debugging of Rcpp (C++) and SEXP based C code in gdb
by providing convenience print, subset and other functions:

https://github.com/aryoda/R_CppDebugHelper

I also want to solve the Windows-only problem that you can break into the debugger from R
only via Rgui.exe (menu "Misc > break to debugger") by supporting breakpoints for R.exe.

I want breakpoints support in R.exe because debugging in Rgui.exe has an unwanted side effect:

https://stackoverflow.com/questions/59236579/gdb-prints-output-stdout-to-rgui-console-instead-of-gdb-console-on-windows-whe

My idea is to break into the debugger from R.exe by calling a little C(++) code that contains an INT 3 (opcode 0xCC) SIGTRAP code:

// break_to_debugger.cpp
// [[Rcpp::export]]
int break_to_debugger()
{
  int a = 3;
  asm("int $3");  // this code line shall break into the debugger
  // Idea taken from "Rgui > break into debugger":
  // https://github.com/wch/r-source/blob/5a156a0865362bb8381dcd69ac335f5174a4f60c/src/gnuwin32/rui.c#L431
  a++;
  return a;
}

# breakpoint.R
#' breaks the execution into the debugger
#'
#' @return
#' @export
breakpoint <- function() {
  break_to_debugger()
}

Surprisingly this works not only on Linux but also on Windows (v10, x64 architecture = 64 bit) in Rterm.exe,
but NOT for R.exe (64 bit):

- Rgui.exe:    Works
- Rscript.exe: Works
- R.exe:       Does not work: R.exe is exited with:
               [Inferior 1 (process 20704) exited with code 020000000003]

Can you please help me to understand why it works for Rgui.exe and Rscript.exe but not for R.exe?

Why is int 3 exiting R.exe?

And: How could I make it also work with R.exe?

Thanks a lot for sharing your ideas and experiences!

Jürgen

PS 1: My sessionInfo():
        R version 3.6.1 (2019-07-05)
        Platform: x86_64-w64-mingw32/x64 (64-bit)
        Running under: Windows 10 x64 (build 17134)

PS 2: My package "CppDebugHelper" was compiled with -g -o0 -std=c++11

PS 3: Here is my captured gdb output for the three test cases:

1. Rgui.exe ------------------------------------------------------------------------

>gdb --quiet --args Rgui.exe --silent --vanilla
Reading symbols from Rgui.exe...(no debugging symbols found)...done.
(gdb) run
Starting program: C:\R\bin\x64\Rgui.exe --silent --vanilla
[New Thread 14476.0x3710]
[New Thread 14476.0x284c]
[New Thread 14476.0x50ec]
[New Thread 14476.0x2d24]
warning: Invalid parameter passed to C runtime function.
[In RGui's R console:]
library(CppDebugHelper)
breakpoint()
[in gdb again:]
Program received signal SIGTRAP, Trace/breakpoint trap.
break_to_debugger () at break_to_debugger.cpp:33
33        a++;
(gdb) b debug_example_rcpp
Breakpoint 1 at 0x66ac6846: file debug_example_rcpp.cpp, line 13.
(gdb) continue
Continuing.
[In RGui's R console:]
debug_example_rcpp()
[in gdb again:]
Breakpoint 1, debug_example_rcpp () at debug_example_rcpp.cpp:13
13          CharacterVector cv   = CharacterVector::create("foo", "bar", NA_STRING, "hello")  ;
(gdb) next
14          NumericVector nv     = NumericVector::create(0.0, 1.0, NA_REAL, 10) ;
(gdb) n
16          DateVector dv        = DateVector::create( 14974, 14975, 15123, NA_REAL); // TODO how to use real dates instead?
(gdb) n
17          DateVector dv2       = DateVector::create(Date("2010-12-31"), Date("01.01.2011", "%d.%m.%Y"), Date(2011, 05, 29),
NA_REAL);
(gdb) n
18          DatetimeVector dtv   = DatetimeVector::create(1293753600, Datetime("2011-01-01"), Datetime("2011-05-29 10:15:30")
, NA_REAL);
(gdb) n
19          DataFrame df         = DataFrame::create(Named("name1") = cv, _["value1"] = nv, _["dv2"] = dv2);  // Named and _[
] are the same
(gdb) n
20          CharacterVector col1 = df["name1"];          // get the first column
(gdb) call dbg_print(df)
(gdb) call dbg_str(df)
(gdb) continue
Continuing.

[Output for the dbg_* function calls is printed to Rgui's R console (NOT the gdb terminal!):]

  name1 value1        dv2
1   foo      0 2010-12-31
2   bar      1 2011-01-01
3  <NA>     NA 2011-05-29
4 hello     10       <NA>

'data.frame':   4 obs. of  3 variables:
$ name1 : Factor w/ 3 levels "bar","foo","hello": 2 1 NA 3
$ value1: num  0 1 NA 10
$ dv2   : Date, format: "2010-12-31" "2011-01-01" ...



2. R.exe ------------------------------------------------------------------------

>gdb --quiet --args R.exe --silent --vanilla
Reading symbols from R.exe...(no debugging symbols found)...done.
(gdb) r
Starting program: C:\R\bin\x64\R.exe --silent --vanilla
[New Thread 20704.0x2b20]
[New Thread 20704.0x4c08]
[New Thread 20704.0x425c]
[New Thread 20704.0x45f8]
> library(CppDebugHelper)
> breakpoint()
[Thread 20704.0x45f8 exited with code 2147483651]
[Thread 20704.0x425c exited with code 2147483651]
[Thread 20704.0x4c08 exited with code 2147483651]
[Inferior 1 (process 20704) exited with code 020000000003]
(gdb) bt
No stack.
(gdb)



3. Rterm.exe ------------------------------------------------------------------------

gdb --quiet --args Rterm.exe --silent --vanilla
Reading symbols from Rterm.exe...(no debugging symbols found)...done.
(gdb) run
Starting program: C:\R\bin\x64\Rterm.exe --silent --vanilla
[New Thread 8132.0x3ee8]
[New Thread 8132.0x3828]
[New Thread 8132.0x4f1c]
[New Thread 8132.0x4ff4]
warning: Invalid parameter passed to C runtime function.
[New Thread 8132.0x4dc8]
> library(CppDebugHelper)
> breakpoint()
Program received signal SIGTRAP, Trace/breakpoint trap.
break_to_debugger () at break_to_debugger.cpp:33
33        a++;
(gdb) b debug_example_rcpp
Breakpoint 1 at 0x66ac6846: file debug_example_rcpp.cpp, line 13.
(gdb) c
Continuing.
[1] 4
> debug_example_rcpp()
Breakpoint 1, debug_example_rcpp () at debug_example_rcpp.cpp:13
13          CharacterVector cv   = CharacterVector::create("foo", "bar", NA_STRING, "hello")  ;
(gdb) n
14          NumericVector nv     = NumericVector::create(0.0, 1.0, NA_REAL, 10) ;
(gdb) n
16          DateVector dv        = DateVector::create( 14974, 14975, 15123, NA_REAL); // TODO how to use real dates instead?
(gdb) call dbg_print(nv)
[1]  0  1 NA 10
(gdb) call dbg_print(dbg_subset(nv, 1, 2))
[1]  1 NA
(gdb)



More information about the R-devel mailing list