writing mruby debugger
DESCRIPTION
RubyConf 2014 presentationTRANSCRIPT
Writing mruby debugger
Yurie YamaneMasayoshi Takahashi
(Team Yamanekko)
2014/11/18 RubyConf 2014
Outline● Who are we?● Why debugger?● What's debugger?● Demo● How mruby and debugger works● Debugger UI (Eclipse plugin)● Conclusion and Future works
!!! Notice !!!● Technical talk
● including GDB and Eclipse● less Ruby● not fluent C, Java, English● not finished yet
About us● Yurie Yamane● Masayoshi Takahashi
Yamanekko
http://mrb.h2so5.net/
Tatsu-zine Publishing
Why Debugger?
Why debugger?CRuby programmers are not sofamiliar with debugger
irb / pry are your friend
But we think mruby programmersneed debugger→ Why?
What we had talked
https://www.flickr.com/photos/igaiga/10836637785/
http://www.flickr.com/photos/igaiga/8564676738/
Tools we use now● C● Java
● making our Eclipse Plugin● hacking Eclipse/CDT
● GDB● (a little Ruby)
https://www.gnu.org/software/gdb/mascot/
https://gcc.gnu.org/
http://www.eclipse.org/artwork/
https://www.ruby-lang.org/en/about/logo/
Why we need mrubydebugger
● targets of mruby● application embedded
● apache / nginx● redis
● microcontroller● RTOS● bare metal
Why we need mrubydebugger
*.rb
*.c *.rb
bin/ruby
libruby.a
CRuby
mruby
(Your code)
debugging mruby
C Ruby
(out of focus)
GDB ???
mruby
libruby.a
mruby sample code
CRuby debugger● ruby-debug
● < Ruby 2.0● byebug
● >= Ruby 2.0
porting them to mruby isthe answer?
partially, yes
→ we need another solution
C Ruby
Our approachmruby debugger on GDB
mruby application
GDB
Front-end
mruby Debugger
Pros && Cons● Pros
● support C and Ruby● easy to develop
● on the shoulders of giants
● Cons● need GDB, not standalone● a little complicated
What's Debugger?
Functions of debugger● Control Execution
● breakpoint● step into / step over / continue
● Show Variables● Show Stacktraces
Functions of debugger● Control Execution
● breakpoint● step into / step over / continue
● Show Variables● Show Stacktraces
today's topics
total picture● Eclipse CDT (as frontend)● our library● GDB
● GDB/MI protocol● mrubyVM (libmruby.a)
total picture
mruby app (bytecode)
GDB
Eclipse CDT
mruby debugger (C)
mruby Debugger (plugin)
mrubyVM (libmruby.a)
GDB/MI
Demo
How mruby Works
Control execution● What we want to do is:
● Suspend execution● Resume execution● show internal status
● We should know how mrubyVMworks
GDB Missing Manual
● GDB/MI● Conditional Breakpoint● Calling Program Functions
GDB Missing Manual
● GDB/MI● Conditional Breakpoint● Calling Program Functions
GDB/MI● Machine Interface protocol
● not for humans● easy to parse
● Eclipse/CDT uses thisGDB command GDB/MI command
run -exec-run
show args -exec-show-arguments
info frame -stack-info-frame
GDB/MI
GDB Missing Manual
● GDB/MI● Conditional Breakpoint● Calling Program Functions
Conditional Breakpointadd conditions to breakpoint
normal breakpoint
conditional breakpoint
GDB Missing Manual
● GDB/MI● Conditional Breakpoint● Calling Program Functions
Call function from GDB● GDB can execute C function
● GDB can get return value● CLI: call / print command● GDB/MI: -data-evaluate-expression
How mrubyVM works● like Instruction pipeline steps
Fetch
Decode
Execute
Write(update status)
How mrubyVM works● use CODE_FETCH_HOOK
Fetch
Decode
Execute
Write(update status)
CODE_FETCH_HOOK
CODE_FETCH_HOOK● hook function for debuging● execute after FETCH with each
cycle● when #define ENABLE_DEBUG only
CODE_FETCH_HOOK
src/vm.c
code_fetch_hook
include/mruby.h
ENABLE_DEBUG
include/mrbconf.h
How mrubyVM works● check status at C_F_HOOK
Fetch
Decode
CODE_FETCH_HOOK set a breakpoint here
our code_fetch_hook
set a breakpoint here
Breakpoint: Ruby → C
breakpoint: foo.rb:12Ruby
Cbreakpoint: ???: ???
Breakpoint: Ruby → C
breakpoint: foo.rb:12Ruby
C breakpoint: hoge.c: 116 if line == 12 && filaname == “foo.rb”
condition
mrbc: mruby compiler● mrubyVM uses bytecode● bin/mrbc is bytecode compiler
● only compile; do not execute● mrbc -g option
● “-g produce debugging information”● store source filename and line
number to debug
1 source line != 1 bytecode
v = 2
num = 1
num = v + num
OP_LOADI R1 2 ; R1:v
OP_LOADI R2 1 ; R2:num
OP_MOVE R6 R1OP_MOVE R7 R2OP_ADD R6 :+ 1OP_MOVE R2 R6
source code bytecode
1 source line != 1 bytecodeSolution
save previous filename andline number
if same line in same file,ignore (do not stop)
Show Variables● calling C function from GDB● add new functions
● getlocals(mrb): return list of localvars● getlocalValue(mrb, sym): return a localvar
● never called by mruby itself● called by GDB only
Debugger UI
Eclipse● Eclipse supports C programming
● CDT● DSF and DSF-GDB (with GDB/MI)
Eclipse
Eclipse Platform
DSF-GDBDSFC
DT
mruby debugger plugin
debug.uidebug.core
Eclipse CDT● C/C++ Development Tooling● Parser, Indexer, Editor, Builder, …● Using Eclipse standard
packages/frameworks● Debugger: Eclipse Debug
Framework
DSF / DSF-GDB● Debugger Service Framework● new framework of CDT● more flexible than old framework
(CDI)● DSF-GDB: GDB debugger using DSF● we use/modify DSF-GDB
Eclipse mruby debugger
Breakpoint Managerfor mruby
mruby editor(experimental)
mruby variable view GDB Adapterfor mruby
……
mruby Variable View
mruby Editor
mruby BreakpointMarker
Marker on *.rb →breakpoint on *.c
linenum: 12path: foo.rb
Marker
foo.rb *.c
CODE_FETCH_HOOK breakpoint
line == 12 &&md_strcmp(filename, “foo.rb”)
Condition
Breakpoint Manager
mrubyBreakpoint Manager GDB
Breakpoint Manager GDB
C
Ruby
linenum: 12path: foo.rb
Marker
linenum: 12path: foo.c
Marker
break foo.c:12
break XXX.c:YYYif line ==12 && path == “foo.rb”
mruby Variable View show Name, Type and Value ofvariables
mruby Variable View hilighting updated values
get list of variables
C
Ruby
Eclipse
mruby app
GDB
Eclipse GDB
“info locals”
“call getlocals(mrb)” exec getlocals()
return locals (as string)return locals
return locals
get variable info● get a list of local variables
command
GDB CLI info locals
GDB/MI -stack-list-locals
mruby -data-evaluate-expression getlocals
variable list format
321,018 25-data-evaluate-expression getlocals(mrb)
321,040 25^done,value=”0x10008c640 \”locals=[{name=\\\”v\\\”,value=\\\”2\\\”,type=\\\”Fixnum\\\”},{name=\\\”num\\\”,value=\\\”1\\\”,type=\\\”Fixnum\\\”},...
-stack-list-locals 1^done,locals=[{name="i",value="0"},{name="k",value="1"}]
for C:
for mruby (command):
for mruby (result):
get variable info● get a value of variable by name
command
GDB CLI print foo
GDB/MI (using variable object; -var-***)
mruby -data-evaluate-expression getlocalvalue
Start mruby Debugger
Stop at Breakpoint
Show Variables ● org
● Breakpoint marker filename,line● break
● mruby variable view● GDB Adapter for mruby● ...
update value of num
Change Type of v
Symbol and Hash
Show arguments ● get local variables● ...
create new object● get local variables● ...
call RubyConf#prev● get local variables● ...
console
Conclusion
Conclusion● mruby debugger on GDB
● breakpoints on *.rb● execution control● show variables
Future Works● mruby stacktrace view● making mrbgem● support step execution● support instance variables &&
class variables
Thank you!