All Projects → sonots → gdbdump-ruby

sonots / gdbdump-ruby

Licence: MIT license
Dump C level and Ruby level backtrace from living ruby process or core file using gdb

Programming Languages

ruby
36898 projects - #4 most used programming language
shell
77523 projects

Projects that are alternatives of or similar to gdbdump-ruby

stack-inspector
A gdb command to inspect the size of objects on the stack
Stars: ✭ 57 (+280%)
Mutual labels:  gdb, backtrace
Linux Kernel Module Cheat
The perfect emulation setup to study and develop the Linux kernel v5.4.3, kernel modules, QEMU, gem5 and x86_64, ARMv7 and ARMv8 userland and baremetal assembly, ANSI C, C++ and POSIX. GDB step debug and KGDB just work. Powered by Buildroot and crosstool-NG. Highly automated. Thoroughly documented. Automated tests. "Tested" in an Ubuntu 19.10 ho…
Stars: ✭ 2,748 (+18220%)
Mutual labels:  gdb
Gdb Static
Public repository of static GDB and GDBServer
Stars: ✭ 103 (+586.67%)
Mutual labels:  gdb
Angrgdb
Use angr inside GDB. Create an angr state from the current debugger state.
Stars: ✭ 165 (+1000%)
Mutual labels:  gdb
Vscode Amiga Debug
One-stop Visual Studio Code Extension to compile, debug and profile Amiga C/C++ programs compiled by the bundled gcc 10.1 with the bundled WinUAE.
Stars: ✭ 107 (+613.33%)
Mutual labels:  gdb
Heapinspect
🔍Heap analysis tool for CTF pwn.
Stars: ✭ 177 (+1080%)
Mutual labels:  gdb
Neogdb.vim
## Project deprecated in favor of: new.vim + new-gdb.vim
Stars: ✭ 78 (+420%)
Mutual labels:  gdb
Code Debug
Native debugging for VSCode
Stars: ✭ 232 (+1446.67%)
Mutual labels:  gdb
Symgdb
SymGDB - symbolic execution plugin for gdb
Stars: ✭ 202 (+1246.67%)
Mutual labels:  gdb
Dwarfexport
Export dwarf debug information from IDA Pro
Stars: ✭ 164 (+993.33%)
Mutual labels:  gdb
Pygdbmi
A library to parse gdb mi output and interact with gdb subprocesses
Stars: ✭ 139 (+826.67%)
Mutual labels:  gdb
Peda Arm
GDB plugin peda for arm
Stars: ✭ 110 (+633.33%)
Mutual labels:  gdb
Build An Efficient Pwn Environment
How to build an efficient pwn development environment in 2020
Stars: ✭ 191 (+1173.33%)
Mutual labels:  gdb
Gdb Tools
Various tools to improve the gdb experience
Stars: ✭ 105 (+600%)
Mutual labels:  gdb
Awesome Reverse Engineering
Reverse Engineering Resources About All Platforms(Windows/Linux/macOS/Android/iOS/IoT) And Every Aspect! (More than 3500 open source tools and 2300 posts&videos)
Stars: ✭ 2,954 (+19593.33%)
Mutual labels:  gdb
Libcxx Pretty Printers
GDB Pretty Printers for libc++ of Clang/LLVM
Stars: ✭ 89 (+493.33%)
Mutual labels:  gdb
Gdb Frontend
☕ GDBFrontend is an easy, flexible and extensionable gui debugger.
Stars: ✭ 2,104 (+13926.67%)
Mutual labels:  gdb
Docker Clion Dev
Debugging C++ in a Docker Container with CLion IDE
Stars: ✭ 172 (+1046.67%)
Mutual labels:  gdb
Gdbghidra
gdbghidra - a visual bridge between a GDB session and GHIDRA
Stars: ✭ 251 (+1573.33%)
Mutual labels:  gdb
Pyrasite
Inject code into running Python processes
Stars: ✭ 2,586 (+17140%)
Mutual labels:  gdb

gdbdump

Dump C level and Ruby level backtrace from living ruby process or core file using gdb.

Installation

$ gem install gdbdump

Requirements

  • gdb
  • linux
  • sudo gdb must be allowed to dump backtrace of living ruby process

It was verified that gdbdump works with ruby executables built by rbenv/ruby-build.

Usage

Usage: gdbdump [options] [ pid | /path/to/ruby pid | /path/to/ruby core ]
    -d, --[no-]debug                 print debug log (default: false)
    -x, --gdbinit FILE               path to ruby repo's .gdbinit (default: some of ruby repo's .gdbinit is pre-bundle in this gem)
        --gdb PATH                   path to gdb command (default: gdb)

--gdbinit

Default supported ruby versions: 2.1.x - 2.4.x

Ruby repo's .gdbinit file defines useful helper functions and it is maintained by ruby core team. gdbdump uses it. .gdbinit of some versions written on above are pre-bundled in this gem. But, if you want to use gdbdump for older or newer ruby versions:

  1. Download .gdbinit from ruby repo like ruby/2.4.1/.gdbinit, and specify with -x option
  2. Or, send PR to bundle the .gdbinit in gdbdump gem.

Example (live ruby process)

With live ruby process of pid 1897,

$ gdbdump 1897

You will see C and Ruby level backtrace as:

$1 = (rb_vm_t *) 0x7f46bb071f20
* #<Thread:0x7f46bb0a5ee8 rb_thread_t:0x7f46bb0725d0 native_thread:0x7f46ba514740>
0x7f46ba16d700 <thread_join_m at thread.c:980>:in `join'
loop.rb:17:in `<main>'
* #<Thread:0x7f46bb202750 rb_thread_t:0x7f46bb3e03d0 native_thread:0x7f46b89c0700>
0x7f46ba0e4f30 <rb_f_sleep at process.c:4388>:in `sleep'
loop.rb:6:in `block (2 levels) in <main>'
0x7f46ba1a72b0 <rb_f_loop at vm_eval.c:1137>:in `loop'
loop.rb:4:in `block in <main>'
* #<Thread:0x7f46bb202660 rb_thread_t:0x7f46bb3e47e0 native_thread:0x7f46b87be700>
0x7f46ba0e4f30 <rb_f_sleep at process.c:4388>:in `sleep'
loop.rb:13:in `block (2 levels) in <main>'
0x7f46ba1a72b0 <rb_f_loop at vm_eval.c:1137>:in `loop'
loop.rb:11:in `block in <main>'

Example (core file)

With core file, you have to specify path of ruby executable.

$ gdbdump $HOME/.rbenv/versions/2.4.1/bin/ruby core.1897

You can get a core file with gcore command as:

$ sudo gcore 1897

FAQ

  • Q. How this work?
    • A. Attach to the ruby process with gdb, and call rb_ps defined in gdbinit. That's it.
  • Q. Is this available for production process?
    • A. GDB stops the process during printing backtrace, would cause some issues

Comparisons

  • gdb
    • You can print C level backtrace with raw gdb, of course
  • sigdump
    • sigdump enables to print ruby level backtrace with sending CONT signal to living ruby process.
    • The ruby process must pre-install sigdump gem and require 'sigdump/setup' unlike gdbdump.
    • sigdump prints backtrace in signal handler, so blocks main thread, but other threads still work unlike gdbdump.
  • gdbruby
    • gdbruby enables to print C level and ruby level backtrace of living ruby process and core file.
    • gdbruby must follow changes of C level interfaces of CRuby to get backtrace of the core file, it rises fragility that it will be broken on newer ruby versions.
    • gdbruby supports only ruby 2.0 and 2.1 (2017-06-05).
    • I believe gdbdump can replace gdbruby.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake test to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Investigation

Belows are my investigation notes about how to print C level and Ruby level backtrace via gdb.

(1) rb_print_backtrace() and rb_backtrace()

CRuby itself has rb_print_backtrace function to print C level backtrace, and rb_backtrace function to print Ruby level backtrace. I first tried to use them.

However, they print a backtrace of only current thread. Furthermore, rb_print_backtrace supports printing outputs to only STDERR. Also, because it calls C function, it works only for a living process, and does not work for core file.

def print_backtrace
  run do |gdb|
    gdb.cmd_exec('call write(2, "== c backtrace ==\n", 18)')
    gdb.cmd_exec('call rb_print_backtrace()')
    gdb.cmd_exec('call write(2, "== ruby backtrace ==\n", 21)')
    gdb.cmd_exec('call rb_backtrace()')
  end
end

(2) bt and rb_eval_string()

I secondly tried to use GDB's info threads and bt command to print C level backtrace. This was fine.

I also tried to print Ruby level backtrace by calling rb_eval_string with Ruby codes as:

def ruby_backtrace_code
  code = +%Q[File.open('#{dumpfile}', 'a') {|f|]
  code << %q[
    Thread.list.each {|th|
      f.write %Q[  Thread #{th} status=#{th.status} priority=#{th.priority}\n]
      th.backtrace.each {|bt|
        f.write %Q[      #{bt}\n]
      }
    }
  }]
  code.split("\n").map(&:strip).join('; ')
end

def print_backtrace
  run do |gdb|
    gdb.cmd_exec(%Q[call rb_eval_string("#{ruby_backtrace_code}")])
  end
end

However, the debugee (target) process got stuck after call rb_eval_string. It seemed the ruby process will be broken if ruby codes are executed via gdb.

(3) rb_ps from ruby trunk's .gdbinit

I thirdly tried to use rb_ps function defined in .gdbinit of ruby repository to print C level and Ruby level backtrace of all threads.

Since .gdbinit is maintained by ruby core team, I do not need to follow changes of C level interfaces of CRuby as long as I follow .gdbinit.

Because rb_ps does not call any C functions inside, it can print C and Ruby level backtrace for core file.

The drawback of this way is that

  1. I have to follow changes of .gdbinit in newer ruby versions
  2. rb_ps takes somewhat long time like 2.6 seconds to print backtrace.

Currently, I am taking this way.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/sonots/gdbdump. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the Gdbdump project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].