Class: Unicorn::Emulator
- Inherits:
-
Object
- Object
- Unicorn::Emulator
- Includes:
- UnicornBind
- Defined in:
- lib/ncpp/utils.rb,
lib/unicorn/unicorn.rb
Overview
Various utility methods tying Unicorn to the Unarm and Nitro modules
Constant Summary
Constants included from UnicornBind
Instance Method Summary collapse
- #add_region(region) ⇒ Object
- #add_section(sect) ⇒ Object (also: #add_sect)
- #call_func(addr, *args) ⇒ Object
-
#initialize(arch: UC_ARCH_ARM, mode: UC_MODE_ARM946, regions: NDS_REGIONS, sections: [], registers: {}) ⇒ Emulator
constructor
A new instance of Emulator.
- #load_arm9 ⇒ Object
- #load_overlay(ov_id) ⇒ Object (also: #load_ov)
- #read_mem(addr, size) ⇒ Object
- #read_register(reg) ⇒ Object (also: #read_reg)
- #read_registers(reg_names = REG_ID.keys) ⇒ Object (also: #read_regs)
- #run(from: nil, to: -1,, timeout_ms: 0, max_ins: 0) ⇒ Object
- #write_mem(addr, byte_str) ⇒ Object
- #write_register(reg, val) ⇒ Object (also: #write_reg)
- #write_registers(regs_h) ⇒ Object (also: #write_regs)
Constructor Details
#initialize(arch: UC_ARCH_ARM, mode: UC_MODE_ARM946, regions: NDS_REGIONS, sections: [], registers: {}) ⇒ Emulator
Returns a new instance of Emulator.
106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/unicorn/unicorn.rb', line 106 def initialize(arch: UC_ARCH_ARM, mode: UC_MODE_ARM946, regions: NDS_REGIONS, sections: [], registers: {}) FFI::MemoryPointer.new(:pointer, 1) do |ptr| safe_call(:uc_open, arch, mode, ptr) @engine = FFI::AutoPointer.new(ptr.read_pointer, method(:uc_close)) end regions.each { add_region(it) } unless regions.empty? sections.each { add_sect(it) } unless sections.empty? registers.each {|r,v| write_register(r,v) } unless registers.empty? end |
Instance Method Details
#add_region(region) ⇒ Object
126 127 128 |
# File 'lib/unicorn/unicorn.rb', line 126 def add_region(region) safe_call(:uc_mem_map, @engine, region.addr, region.size, region.prot) end |
#add_section(sect) ⇒ Object Also known as: add_sect
130 131 132 |
# File 'lib/unicorn/unicorn.rb', line 130 def add_section(sect) safe_call(:uc_mem_write, @engine, sect.addr, sect.ptr, sect.size) end |
#call_func(addr, *args) ⇒ Object
772 773 774 775 776 777 778 779 |
# File 'lib/ncpp/utils.rb', line 772 def call_func(addr, *args) raise "Calling functions with more than 4 args isn't supported yet" if args.length > 4 args.each_with_index do |arg,i| send(:"write_r#{i}", arg) end run(from: addr, to: read_lr, timeout_ms: 5000) read_r0 end |
#load_arm9 ⇒ Object
747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 |
# File 'lib/ncpp/utils.rb', line 747 def load_arm9 arm = $rom.arm9 main_added = false arm.autoload_entries.sort_by {|e| e[:address] }.each do |e| if e[:address] > arm.end_addr # DTCM found add_region(Uc::Region.new(e[:address], 16*1024)) next end if !main_added && e[:address] > arm.start_addr # Main section found size = e[:address] - arm.start_addr add_section(Uc::Sect.new(arm.start_addr, arm.get_sect_ptr(arm.start_addr,size), size)) main_added = true end next if e[:address]+e[:size] <= e[:address] ptr = arm.get_sect_ptr(e[:address],e[:size]) add_section(Uc::Sect.new(e[:address], ptr, e[:size])) end end |
#load_overlay(ov_id) ⇒ Object Also known as: load_ov
766 767 768 769 |
# File 'lib/ncpp/utils.rb', line 766 def (ov_id) ov = $rom.(ov_id) add_section(Uc::Sect.new(ov.start_addr, ov.get_sect_ptr(ov.start_addr, ov.size), ov.size)) end |
#read_mem(addr, size) ⇒ Object
142 143 144 145 146 147 148 149 |
# File 'lib/unicorn/unicorn.rb', line 142 def read_mem(addr, size) byte_str = nil FFI::MemoryPointer.new(:uint8, size) do |ptr| safe_call(:uc_mem_read, @engine, addr, ptr, size) byte_str = ptr.read_array_of_uint8(size).pack('C*') end byte_str end |
#read_register(reg) ⇒ Object Also known as: read_reg
170 171 172 173 174 175 176 177 |
# File 'lib/unicorn/unicorn.rb', line 170 def read_register(reg) val = nil FFI::MemoryPointer.new(:int32, 1) do |pv| safe_call(:uc_reg_read, @engine, REG_ID[reg], pv) val = pv.read_int32 end val end |
#read_registers(reg_names = REG_ID.keys) ⇒ Object Also known as: read_regs
180 181 182 183 184 |
# File 'lib/unicorn/unicorn.rb', line 180 def read_registers(reg_names = REG_ID.keys) regs_h = {} reg_names.each {|r| regs_h[r] = read_register(r) } regs_h end |
#run(from: nil, to: -1,, timeout_ms: 0, max_ins: 0) ⇒ Object
118 119 120 121 122 123 124 |
# File 'lib/unicorn/unicorn.rb', line 118 def run(from: nil, to: -1, timeout_ms: 0, max_ins: 0) raise "The 'from' parameter must be specified" if from.nil? if to == -1 && timeout_ms == 0 && max_ins == 0 raise "The 'to' parameter must be specified if 'timeout_ms' or 'max_ins' are not" end safe_call(:uc_emu_start, @engine, from, to, timeout_ms, max_ins) end |
#write_mem(addr, byte_str) ⇒ Object
135 136 137 138 139 140 |
# File 'lib/unicorn/unicorn.rb', line 135 def write_mem(addr, byte_str) FFI::MemoryPointer.new(:uint8, byte_str.bytesize) do |ptr| ptr.write_array_of_uint8(byte_str.bytes) safe_call(:uc_mem_write, @engine, addr, ptr, byte_str.bytesize) end end |
#write_register(reg, val) ⇒ Object Also known as: write_reg
151 152 153 154 155 156 |
# File 'lib/unicorn/unicorn.rb', line 151 def write_register(reg, val) FFI::MemoryPointer.new(:int32, 1) do |pv| pv.write_int(val) safe_call(:uc_reg_write, @engine, REG_ID[reg], pv) end end |
#write_registers(regs_h) ⇒ Object Also known as: write_regs
159 160 161 |
# File 'lib/unicorn/unicorn.rb', line 159 def write_registers(regs_h) regs_h.each {|r,v| write_register(r,v) } end |