Class: Crabstone::Instruction

Inherits:
Object
  • Object
show all
Defined in:
lib/crabstone.rb

Overview

Diet mode means:

  • No op_str or mnemonic in Instruction

  • No regs_read, regs_write or groups ( even with detail on )

  • No reg_name or insn_name id2str convenience functions

  • detail mode CAN still be on - so the arch insn operands MAY be available

Constant Summary collapse

ARCHS =
{
  arm: ARCH_ARM,
  arm64: ARCH_ARM64,
  x86: ARCH_X86,
  mips: ARCH_MIPS,
  ppc: ARCH_PPC,
  sparc: ARCH_SPARC,
  sysz: ARCH_SYSZ,
  xcore: ARCH_XCORE
}.invert
ARCH_CLASSES =
{
  ARCH_ARM   => ARM,
  ARCH_ARM64 => ARM64,
  ARCH_X86   => X86,
  ARCH_MIPS  => MIPS,
  ARCH_PPC   => PPC,
  ARCH_SPARC => Sparc,
  ARCH_SYSZ  => SysZ,
  ARCH_XCORE => XCore
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(csh, insn, arch) ⇒ Instruction

Returns a new instance of Instruction.



293
294
295
296
297
298
299
300
301
302
303
304
# File 'lib/crabstone.rb', line 293

def initialize csh, insn, arch
  @arch       = arch
  @csh        = csh
  @raw_insn   = insn
  if detailed?
    @detail     = insn[:detail]
    @arch_insn  = @detail[:arch][ARCHS[arch]]
    @regs_read  = @detail[:regs_read].first( @detail[:regs_read_count] )
    @regs_write = @detail[:regs_write].first( @detail[:regs_write_count] )
    @groups     = @detail[:groups].first( @detail[:groups_count] )
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args) ⇒ Object

So an Instruction should respond to all the methods in Instruction, and all the methods in the Arch specific Instruction class. The methods / members that have special handling for detail mode or diet mode are handled above. The rest is dynamically dispatched below.



393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
# File 'lib/crabstone.rb', line 393

def method_missing meth, *args
  if raw_insn.members.include? meth
    # Dispatch to toplevel Instruction class ( this file )
    raw_insn[meth]
  else
    # Nothing else is available without details.
    if not detailed?
      raise(
        NoMethodError,
        "Either CS_DETAIL is off, or #{self.class} doesn't implement #{meth}"
      )
    end
    # Dispatch to the architecture specific Instruction ( in arch/ )
    if @arch_insn.respond_to? meth
      @arch_insn.send meth, *args
    elsif @arch_insn.members.include? meth
      @arch_insn[meth]
    else
      raise NoMethodError, "Unknown method #{meth} for #{self.class}"
    end
  end
end

Instance Attribute Details

#archObject (readonly)

Returns the value of attribute arch.



269
270
271
# File 'lib/crabstone.rb', line 269

def arch
  @arch
end

#cshObject (readonly)

Returns the value of attribute csh.



269
270
271
# File 'lib/crabstone.rb', line 269

def csh
  @csh
end

#raw_insnObject (readonly)

Returns the value of attribute raw_insn.



269
270
271
# File 'lib/crabstone.rb', line 269

def raw_insn
  @raw_insn
end

Instance Method Details

#bytesObject



385
386
387
# File 'lib/crabstone.rb', line 385

def bytes
  raw_insn[:bytes].first raw_insn[:size]
end

#detailObject



325
326
327
328
# File 'lib/crabstone.rb', line 325

def detail
  raise_unless_detailed
  @detail
end

#detailed?Boolean

It’s more informative to raise if CS_DETAIL is off than just return nil

Returns:

  • (Boolean)


321
322
323
# File 'lib/crabstone.rb', line 321

def detailed?
  not @raw_insn[:detail].pointer.null?
end

#group?(groupid) ⇒ Boolean

Returns:

  • (Boolean)


348
349
350
351
352
# File 'lib/crabstone.rb', line 348

def group? groupid
  raise_unless_detailed
  raise_if_diet
  Binding.cs_insn_group csh, raw_insn, groupid
end

#group_name(grp) ⇒ Object



313
314
315
316
317
318
# File 'lib/crabstone.rb', line 313

def group_name grp
  raise_if_diet
  name = Binding.cs_group_name(csh, Integer(grp))
  Crabstone.raise_errno( ERRNO_KLASS[ErrCsh] ) unless name
  name
end

#groupsObject



342
343
344
345
346
# File 'lib/crabstone.rb', line 342

def groups
  raise_unless_detailed
  raise_if_diet
  @groups
end

#mnemonicObject



366
367
368
369
# File 'lib/crabstone.rb', line 366

def mnemonic
  raise_if_diet
  raw_insn[:mnemonic]
end

#nameObject



306
307
308
309
310
311
# File 'lib/crabstone.rb', line 306

def name
  raise_if_diet
  name = Binding.cs_insn_name(csh, id)
  Crabstone.raise_errno( ERRNO_KLASS[ErrCsh] ) unless name
  name
end

#op_count(op_type = nil) ⇒ Object



376
377
378
379
380
381
382
383
# File 'lib/crabstone.rb', line 376

def op_count op_type=nil
  raise_unless_detailed
  if op_type
    Binding.cs_op_count csh, raw_insn, op_type
  else
    self.operands.size
  end
end

#op_strObject



371
372
373
374
# File 'lib/crabstone.rb', line 371

def op_str
  raise_if_diet
  raw_insn[:op_str]
end

#reads_reg?(reg) ⇒ Boolean

Returns:

  • (Boolean)


354
355
356
357
358
# File 'lib/crabstone.rb', line 354

def reads_reg? reg
  raise_unless_detailed
  raise_if_diet
  Binding.cs_reg_read csh, raw_insn, ARCH_CLASSES[arch].register( reg )
end

#regs_readObject



330
331
332
333
334
# File 'lib/crabstone.rb', line 330

def regs_read
  raise_unless_detailed
  raise_if_diet
  @regs_read
end

#regs_writeObject



336
337
338
339
340
# File 'lib/crabstone.rb', line 336

def regs_write
  raise_unless_detailed
  raise_if_diet
  @regs_write
end

#writes_reg?(reg) ⇒ Boolean

Returns:

  • (Boolean)


360
361
362
363
364
# File 'lib/crabstone.rb', line 360

def writes_reg? reg
  raise_unless_detailed
  raise_if_diet
  Binding.cs_reg_write csh, raw_insn, ARCH_CLASSES[arch].register( reg )
end