class Crabstone::Disassembler

Constants

DETAIL
SKIPDATA
SYNTAX

Attributes

arch[R]
csh[R]
decomposer[R]
mode[R]
syntax[R]

Public Class Methods

new(arch, mode) click to toggle source
# File lib/crabstone/disassembler.rb, line 30
def initialize(arch, mode)
  @arch = arch
  @mode = mode
  @p_csh = FFI::MemoryPointer.new(:ulong_long)
  safe { Binding.cs_open(arch, mode, @p_csh) }

  @csh = @p_csh.read_ulong_long
end

Public Instance Methods

close() click to toggle source

After you close the engine, don't use it anymore. Can't believe I even have to write this.

@return [void]

# File lib/crabstone/disassembler.rb, line 43
def close
  safe { Binding.cs_close(@p_csh) }
end
decomposer=(new_val) click to toggle source

@param [Boolean] new_val

# File lib/crabstone/disassembler.rb, line 54
def decomposer=(new_val)
  Crabstone::Error.raise!(ErrOption) unless DETAIL[new_val]
  set_raw_option(OPT_DETAIL, DETAIL[new_val])
  @decomposer = new_val
end
diet?() click to toggle source
# File lib/crabstone/disassembler.rb, line 64
def diet?
  DIET_MODE
end
disasm(code, offset, count = 0) click to toggle source

@return [Array<Crabstone::Instruction>]

# File lib/crabstone/disassembler.rb, line 107
def disasm(code, offset, count = 0)
  return [] if code.empty?

  insn_ptr   = FFI::MemoryPointer.new(:pointer)
  insn_count = Binding.cs_disasm(
    @csh,
    code,
    code.bytesize,
    offset,
    count,
    insn_ptr
  )
  Crabstone::Error.raise_errno!(errno) if insn_count.zero?

  convert_disasm_result(insn_ptr, insn_count).tap { Binding.free(insn_ptr.read_pointer) }
end
errno() click to toggle source
# File lib/crabstone/disassembler.rb, line 68
def errno
  Binding.cs_errno(@csh)
end
reg_name(regid) click to toggle source
# File lib/crabstone/disassembler.rb, line 99
def reg_name(regid)
  Crabstone::Error.raise!(ErrDiet) if DIET_MODE
  name = Binding.cs_reg_name(csh, regid)
  Crabstone::Error.raise!(ErrCsh) unless name
  name
end
set_raw_option(opt, val) click to toggle source
# File lib/crabstone/disassembler.rb, line 124
def set_raw_option(opt, val)
  safe { Binding.cs_option(csh, opt, val) }
end
skipdata(mnemonic = '.byte') { |code, offset| ... } click to toggle source
# File lib/crabstone/disassembler.rb, line 72
def skipdata(mnemonic = '.byte')
  cfg = Binding::SkipdataConfig.new
  cfg[:mnemonic] = FFI::MemoryPointer.from_string(mnemonic.to_s)

  if block_given?
    cfg[:callback] = FFI::Function.new(
      :size_t,
      %i[pointer size_t size_t pointer]
    ) do |code, sz, offset, _|
      code = code.read_array_of_uchar(sz).pack('c*')
      begin
        Integer(yield(code, offset))
      rescue StandardError
        warn "Error in skipdata callback: #{$ERROR_INFO}"
        # It will go on to crash, but now at least there's more info :)
      end
    end
  end

  set_raw_option(OPT_SKIPDATA_SETUP, cfg.pointer.address)
  set_raw_option(OPT_SKIPDATA, SKIPDATA[true])
end
skipdata_off() click to toggle source
# File lib/crabstone/disassembler.rb, line 95
def skipdata_off
  set_raw_option(OPT_SKIPDATA, SKIPDATA[false])
end
syntax=(new_stx) click to toggle source
# File lib/crabstone/disassembler.rb, line 47
def syntax=(new_stx)
  Crabstone::Error.raise!(ErrOption) unless SYNTAX[new_stx]
  set_raw_option(OPT_SYNTAX, SYNTAX[new_stx])
  @syntax = new_stx
end
version() click to toggle source
# File lib/crabstone/disassembler.rb, line 60
def version
  Crabstone.cs_version
end

Private Instance Methods

convert_disasm_result(insn_ptr, insn_count) click to toggle source

Convert the insn_ptr from cs_disasm into Ruby instruction objects. @param [FFI::MemoryPointer] insn_ptr @param [Integer] insn_count @return [Array<Crabstone::Instruction>]

# File lib/crabstone/disassembler.rb, line 134
def convert_disasm_result(insn_ptr, insn_count)
  insn_sz = Binding::Instruction.size
  Array.new(insn_count) do |i|
    cs_insn_ptr = Binding.malloc(insn_sz)
    Binding.memcpy(cs_insn_ptr, insn_ptr.read_pointer + i * insn_sz, insn_sz)
    Crabstone::Instruction.new(@csh, Binding::Instruction.new(cs_insn_ptr), @arch)
  end
end
safe() { || ... } click to toggle source
# File lib/crabstone/disassembler.rb, line 143
def safe
  yield.tap { |res| Crabstone::Error.raise_errno!(res) unless res.zero? }
end