Module: NCPP::Utils

Defined in:
lib/ncpp/utils.rb

Constant Summary collapse

DTYPES =
[
  { size: 8, signed: false, str: 'unsigned long long int' },
  { size: 4, signed: false, str: 'unsigned long' },
  { size: 2, signed: false, str: 'unsigned short int' },
  { size: 1, signed: false, str: 'unsigned char' },
  { size: 8, signed: true,  str: 'signed long long int' },
  { size: 4, signed: true,  str: 'signed long' },
  { size: 2, signed: true,  str: 'signed short int' },
  { size: 1, signed: true,  str: 'signed char' }
].freeze
DTYPE_IDS =
{
  u64:  0, u32: 1, u16: 2, u8: 3,
  s64:  4, s32: 5, s16: 6, s8: 7
}.freeze

Class Method Summary collapse

Class Method Details

.addr_in_arm7?(addr) ⇒ Boolean

Returns:



418
419
420
# File 'lib/ncpp/utils.rb', line 418

def self.addr_in_arm7?(addr)
  $rom.arm7.bounds.include? addr
end

.addr_in_arm9?(addr) ⇒ Boolean

Returns:



414
415
416
# File 'lib/ncpp/utils.rb', line 414

def self.addr_in_arm9?(addr)
  $rom.arm9.bounds.include? addr
end

.addr_in_overlay?(addr, ov) ⇒ Boolean

Returns:



404
405
406
407
408
409
410
411
412
# File 'lib/ncpp/utils.rb', line 404

def self.addr_in_overlay?(addr, ov)
  if ov == -1
    $rom.arm9.bounds.include? addr
  elsif ov == -2
    $rom.arm7.bounds.include? addr
  else
    $rom.get_overlay(ov).bounds.include? addr
  end
end

.addr_to_sym(addr, ov = nil) ⇒ Object



67
68
69
70
71
72
73
# File 'lib/ncpp/utils.rb', line 67

def self.addr_to_sym(addr, ov = nil)
  loc = ov.nil? ? Unarm.cpu.to_s : "ov#{ov}"
  syms = Unarm.get_raw_syms(loc)
  sym = UnarmBind.get_sym_for_addr(addr, syms.ptr, syms.count)
  raise "No symbol found for address '#{addr.to_hex}'" if sym.to_i == 0
  UnarmBind::CStr.new(sym).to_s
end

.array_check(arr, meth_name = __callee__) ⇒ Object



39
40
41
# File 'lib/ncpp/utils.rb', line 39

def self.array_check(arr, meth_name = __callee__)
  raise "#{meth_name} expects an Array" unless arr.is_a? Array
end

.assemble_arm(asm, addr: 0) ⇒ Object



450
451
452
453
454
455
456
# File 'lib/ncpp/utils.rb', line 450

def self.assemble_arm(asm, addr: 0)
  if asm.is_a? Array
    asm.map.with_index {|ins,idx| $arm_assembler.assemble(ins,addr+4*idx).unpack('L')[0] }
  else
    $arm_assembler.assemble(asm).unpack('L')[0]
  end
end

.assemble_thumb(asm, addr: 0) ⇒ Object



458
459
460
461
462
463
464
# File 'lib/ncpp/utils.rb', line 458

def self.assemble_thumb(asm, addr: 0)
  if asm.is_a? Array
    asm.map.with_index {|ins,idx| $thumb_assembler.assemble(ins,addr+2*idx).unpack('S')[0] }
  else
    $thumb_assembler.assemble(asm).unpack('S')[0]
  end
end

.block_check(block, meth_name = __callee__) ⇒ Object



47
48
49
# File 'lib/ncpp/utils.rb', line 47

def self.block_check(block, meth_name = __callee__)
  raise "#{meth_name} expects a Block" unless block.is_a? Block
end

.check_response(obj, meth) ⇒ Object



35
36
37
# File 'lib/ncpp/utils.rb', line 35

def self.check_response(obj, meth)
  raise "#{obj.class} does not respond to #{meth}" unless obj.respond_to? meth
end

.disasm_arm_ins(data) ⇒ Object



173
174
175
176
# File 'lib/ncpp/utils.rb', line 173

def self.disasm_arm_ins(data)
  raise "cannot disassemble a String" if data.is_a? String
  Unarm::ArmIns.disasm(data).str
end

.disasm_hex_seq(hex_byte_str, thumb: false) ⇒ Object



183
184
185
186
187
188
189
# File 'lib/ncpp/utils.rb', line 183

def self.disasm_hex_seq(hex_byte_str, thumb: false)
  if thumb
    [hex_byte_str].pack('H*').unpack('S*').map { Utils.disasm_thumb_ins(it) }
  else
    [hex_byte_str].pack('H*').unpack('V*').map { Utils.disasm_arm_ins(it) }
  end
end

.disasm_thumb_ins(data) ⇒ Object



178
179
180
181
# File 'lib/ncpp/utils.rb', line 178

def self.disasm_thumb_ins(data)
  raise "cannot disassemble a String" if data.is_a? String
  Unarm::ThumbIns.disasm(data).str
end

.emu_get_mem(loc, size) ⇒ Object



438
439
440
441
442
# File 'lib/ncpp/utils.rb', line 438

def self.emu_get_mem(loc, size)
  addr, ov = resolve_loc(loc)
  $emu.load_overlay(ov) if !ov.nil? && ov >= 0
  $emu.read_mem(addr, size)
end

.emu_set_mem(loc, byte_str) ⇒ Object



444
445
446
447
448
# File 'lib/ncpp/utils.rb', line 444

def self.emu_set_mem(loc, byte_str)
  addr, ov = resolve_loc(loc)
  $emu.load_overlay(ov) if !ov.nil? && ov >= 0
  $emu.write_mem(addr, byte_str)
end

.emulate_func(func_loc, ov, *args) ⇒ Object



432
433
434
435
436
# File 'lib/ncpp/utils.rb', line 432

def self.emulate_func(func_loc, ov, *args)
  addr, ov, code_bin = resolve_code_loc(func_loc,ov)
  $emu.load_overlay(ov) if !ov.nil? && ov >= 0
  $emu.call_func(addr, *args)
end

.find_branch_to(branch_dest, start_loc, start_ov = nil, from_func: false, find_all: false) ⇒ Object



274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'lib/ncpp/utils.rb', line 274

def self.find_branch_to(branch_dest, start_loc, start_ov=nil, from_func: false, find_all: false)
  start_addr, _ov, code_bin = resolve_code_loc(start_loc, start_ov)
  if branch_dest.is_a? Array
    branch_dests = branch_dest.map {|dest| dest.is_a?(String) ? sym_to_addr(dest) : dest }
  else
    branch_dests = [branch_dest.is_a?(String) ? sym_to_addr(branch_dest) : branch_dest]
  end
  if from_func
    func = code_bin.get_function(start_addr)
    addrs = []
    func[:instructions].each do |ins|
      if branch_dests.include?(ins.branch_dest)
        addrs << ins.addr
        break unless find_all
      end
    end
    if find_all
      return addrs
    else
      return addrs[0] unless addrs.empty?
    end
  else
    code_bin.each_ins(start_addr..) do |ins|
      print_warning "Function end may have been passed in search for branch to " \
                    "#{branch_dests.map(&:to_hex).join(', ')}" if ins.function_end?
      return ins.addr if branch_dests.include?(ins.branch_dest)
    end
  end
  raise "Could not find a branch to #{branch_dests.map(&:to_hex).join(', ')}"
end

.find_hex_bytes(ov, hex_str) ⇒ Object



422
423
424
425
# File 'lib/ncpp/utils.rb', line 422

def self.find_hex_bytes(ov, hex_str)
  code_bin = ov == -1 ? $rom.arm9 : (ov == -2 ? $rom.arm7 : $rom.get_overlay(ov))
  code_bin.find_hex(hex_str.strip.delete(' '))
end

.find_ins_in_func(ins_pattern_str, func_loc, func_ov = nil, find_all: false) ⇒ Object



322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/ncpp/utils.rb', line 322

def self.find_ins_in_func(ins_pattern_str, func_loc, func_ov = nil, find_all: false)
  start_addr, _ov, code_bin = resolve_code_loc(func_loc, func_ov)
  func = code_bin.get_function(start_addr)
  addrs = []
  func[:instructions].each do |ins|
    if ins.str.match?(ins_pattern_str)
      addrs << ins.addr
      break unless find_all
    end
  end
  if find_all
    return addrs
  else
    return addrs[0] unless addrs.empty?
  end
  raise "Could not find instruction pattern in function at #{func_loc}"
end

.gen_c_over_guard(loc, ov = nil) ⇒ Object



141
142
143
144
145
# File 'lib/ncpp/utils.rb', line 141

def self.gen_c_over_guard(loc, ov = nil)
  addr, ov, code_bin = resolve_code_loc(loc, ov)
  "ncp_over(#{addr.to_hex}#{",#{ov}" if ov})\n" \
  "static const unsigned int __over_guard_#{addr.to_hex}#{"_#{ov}" if ov} = #{code_bin.read_word(addr).to_hex};"
end

.gen_hex_edit(ov, og_hex_str, new_hex_str) ⇒ Object



427
428
429
430
# File 'lib/ncpp/utils.rb', line 427

def self.gen_hex_edit(ov, og_hex_str, new_hex_str)
  addr = find_hex_bytes(ov, og_hex_str)
  gen_repl_array(addr, ov, DTYPE_IDS[:u8], [new_hex_str].pack('H*').unpack('C*'))
end

.gen_hook_description(type) ⇒ Object



130
131
132
133
134
# File 'lib/ncpp/utils.rb', line 130

def self.gen_hook_description(type)
    "Generates an NCPatcher '#{type}' hook with an address or symbol and an overlay. Specifying the overlay is " \
    "optional if the address is in arm9 or a symbol is used and the symbols file consistently uses tags like " \
    "these to mark symbol locations: '/* arm9_ovX */' (where X is the overlay number)."
end

.gen_hook_str(type, addr, ov = nil, arg = nil) ⇒ Object

generates an NCPatcher hook



125
126
127
128
# File 'lib/ncpp/utils.rb', line 125

def self.gen_hook_str(type, addr, ov = nil, arg = nil) # generates an NCPatcher hook

  addr, ov = resolve_loc(addr, ov)
  "ncp_#{type}(#{addr.to_hex}#{",#{ov}" if ov}#{",\"#{arg}\"" if arg})"
end

.gen_repl_array(loc, ov, dtype, arr, const: true) ⇒ Object



154
155
156
157
158
# File 'lib/ncpp/utils.rb', line 154

def self.gen_repl_array(loc, ov, dtype, arr, const: true)
  addr, ov = resolve_loc(loc, ov)
  "#{gen_hook_str('over', addr, ov)}\nstatic #{'const' if const} " \
  "#{dtype.is_a?(String) ? dtype : DTYPES[dtype][:str]} __array_#{addr.to_hex}_ov#{ov}[] = #{to_c_array(arr)};"
end

.gen_repl_type_array(loc, ov_or_arr, dtype_sym, arr = nil) ⇒ Object



160
161
162
163
164
165
166
# File 'lib/ncpp/utils.rb', line 160

def self.gen_repl_type_array(loc, ov_or_arr, dtype_sym, arr = nil)
  if arr.nil?
    gen_repl_array(loc, resolve_loc(loc)[1], DTYPE_IDS[dtype_sym], ov_or_arr)
  else
    gen_repl_array(loc, ov_or_arr, DTYPE_IDS[dtype_sym], arr)
  end
end

.gen_set_hook_str(type, addr, ov = nil, arg = nil) ⇒ Object



136
137
138
139
# File 'lib/ncpp/utils.rb', line 136

def self.gen_set_hook_str(type, addr, ov = nil, arg = nil)
  addr, ov = resolve_loc(addr, ov)
  "ncp_#{type}(#{addr.to_hex}#{",#{ov}" if ov}#{",#{arg}" if arg})"
end

.get_array(addr, ov, element_type_id, element_count) ⇒ Object

Raises:

  • (ArgumentError)


254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'lib/ncpp/utils.rb', line 254

def self.get_array(addr, ov, element_type_id, element_count)
  element_size = DTYPES[element_type_id][:size]
  element_signed = DTYPES[element_type_id][:signed]
  raise ArgumentError, 'element size must be 1, 2, 4, or 8 (bytes)' unless [1,2,4,8].include?(element_size)
  addr, ov, code_bin = resolve_code_loc(addr, ov)
    (0...element_count).map do |i|
    offset = addr + i * element_size
    if element_signed
      code_bin.send(:"read#{element_size * 8}", offset).signed(element_size*8)
    else
      code_bin.send(:"read#{element_size * 8}", offset)
    end
  end
end

.get_byte(addr, ov = nil) ⇒ Object Also known as: get_u8



224
225
226
227
# File 'lib/ncpp/utils.rb', line 224

def self.get_byte(addr, ov = nil)
  addr, ov, code_bin = resolve_code_loc(addr, ov)
  code_bin.read_byte(addr).unsigned(8)
end

.get_byte_str(loc, ov, size) ⇒ Object



269
270
271
272
# File 'lib/ncpp/utils.rb', line 269

def self.get_byte_str(loc, ov, size)
  addr, _ov, code_bin = resolve_code_loc(loc, ov)
  code_bin.get_sect_ptr(addr,size).read_array_of_uint8(size).pack('C*')
end

.get_cstring(addr, ov = nil) ⇒ Object Also known as: get_cstr



249
250
251
252
# File 'lib/ncpp/utils.rb', line 249

def self.get_cstring(addr, ov = nil)
  addr, ov, code_bin = resolve_code_loc(addr, ov)
  code_bin.read_cstr(addr)
end

.get_dword(addr, ov = nil) ⇒ Object Also known as: get_u64



209
210
211
212
# File 'lib/ncpp/utils.rb', line 209

def self.get_dword(addr, ov = nil)
  addr, ov, code_bin = resolve_code_loc(addr, ov)
  code_bin.read_dword(addr).unsigned(64)
end

.get_func_literal_pool(loc, ov = nil) ⇒ Object



373
374
375
376
377
# File 'lib/ncpp/utils.rb', line 373

def self.get_func_literal_pool(loc, ov=nil)
  addr, ov, code_bin = resolve_code_loc(loc,ov)
  func = code_bin.get_function(addr)
  func[:literal_pool].map {|_addr,data| data.str }
end

.get_func_literal_pool_addrs(loc, ov = nil) ⇒ Object



385
386
387
388
389
# File 'lib/ncpp/utils.rb', line 385

def self.get_func_literal_pool_addrs(loc, ov=nil)
  addr, ov, code_bin = resolve_code_loc(loc,ov)
  func = code_bin.get_function(addr)
  func[:literal_pool].map {|addr,_data| addr }
end

.get_func_literal_pool_values(loc, ov = nil) ⇒ Object



379
380
381
382
383
# File 'lib/ncpp/utils.rb', line 379

def self.get_func_literal_pool_values(loc, ov=nil)
  addr, ov, code_bin = resolve_code_loc(loc,ov)
  func = code_bin.get_function(addr)
  func[:literal_pool].map {|_addr,data| data.raw }
end

.get_function_size(loc, ov = nil) ⇒ Object



391
392
393
394
395
396
397
398
399
400
401
402
# File 'lib/ncpp/utils.rb', line 391

def self.get_function_size(loc, ov=nil)
  addr, ov, code_bin = resolve_code_loc(loc,ov)
  func = code_bin.get_function(addr)
  if func[:literal_pool].empty?
    last = func[:instructions].last
    last.address + last.size - func[:instructions].first
  else
    last = func[:literal_pool][func[:literal_pool].keys.max]
    last.address + last.size - func[:instructions].first.address
  end

end

.get_hword(addr, ov = nil) ⇒ Object Also known as: get_u16



219
220
221
222
# File 'lib/ncpp/utils.rb', line 219

def self.get_hword(addr, ov = nil)
  addr, ov, code_bin = resolve_code_loc(addr, ov)
  code_bin.read_hword(addr).unsigned(16)
end

.get_ins_arg(loc, ov, arg_index) ⇒ Object



353
354
355
356
# File 'lib/ncpp/utils.rb', line 353

def self.get_ins_arg(loc, ov, arg_index)
  addr, ov, code_bin = resolve_code_loc(loc,ov)
  code_bin.read_ins(addr).args[arg_index].value
end

.get_ins_branch_dest(loc, ov = nil) ⇒ Object



358
359
360
361
# File 'lib/ncpp/utils.rb', line 358

def self.get_ins_branch_dest(loc, ov=nil)
  addr, ov, code_bin = resolve_code_loc(loc,ov)
  code_bin.read_ins(addr).branch_dest
end

.get_ins_mnemonic(loc, ov = nil) ⇒ Object



348
349
350
351
# File 'lib/ncpp/utils.rb', line 348

def self.get_ins_mnemonic(loc, ov = nil)
  addr, ov, code_bin = resolve_code_loc(loc,ov)
  code_bin.read_ins(addr).mnemonic
end

.get_ins_target_addr(loc, ov = nil) ⇒ Object



363
364
365
366
# File 'lib/ncpp/utils.rb', line 363

def self.get_ins_target_addr(loc, ov=nil)
  addr, ov, code_bin = resolve_code_loc(loc,ov)
  code_bin.read_ins(addr).target_addr
end

.get_instruction(addr, ov = nil) ⇒ Object



191
192
193
194
195
196
197
198
# File 'lib/ncpp/utils.rb', line 191

def self.get_instruction(addr, ov = nil)
  addr, ov, code_bin = resolve_code_loc(addr, ov)
  if addr & 1 != 0
    disasm_thumb_ins(code_bin.read16(addr-1))
  else
    disasm_arm_ins(code_bin.read32(addr))
  end
end

.get_raw_instruction(addr, ov = nil) ⇒ Object



200
201
202
203
204
205
206
207
# File 'lib/ncpp/utils.rb', line 200

def self.get_raw_instruction(addr, ov = nil)
  addr, ov, code_bin = resolve_code_loc(addr, ov)
  if addr & 1 != 0
    code_bin.read_thumb_instruction(addr-1)
  else
    code_bin.read_arm_instruction(addr)
  end
end

.get_reloc_func(addr, ov = nil) ⇒ Object



168
169
170
171
# File 'lib/ncpp/utils.rb', line 168

def self.get_reloc_func(addr, ov = nil)
  addr, ov, code_bin = resolve_code_loc(addr, ov)
  code_bin.reloc_function(addr)
end

.get_signed_byte(addr, ov = nil) ⇒ Object Also known as: get_s8



244
245
246
247
# File 'lib/ncpp/utils.rb', line 244

def self.get_signed_byte(addr, ov = nil)
  addr, ov, code_bin = resolve_code_loc(addr, ov)
  code_bin.read_byte(addr).signed(8)
end

.get_signed_dword(addr, ov = nil) ⇒ Object Also known as: get_s64



229
230
231
232
# File 'lib/ncpp/utils.rb', line 229

def self.get_signed_dword(addr, ov = nil)
  addr, ov, code_bin = resolve_code_loc(addr, ov)
  code_bin.read_dword(addr).signed(64)
end

.get_signed_hword(addr, ov = nil) ⇒ Object Also known as: get_s16



239
240
241
242
# File 'lib/ncpp/utils.rb', line 239

def self.get_signed_hword(addr, ov = nil)
  addr, ov, code_bin = resolve_code_loc(addr, ov)
  code_bin.read_hword(addr).signed(16)
end

.get_signed_word(addr, ov = nil) ⇒ Object Also known as: get_s32



234
235
236
237
# File 'lib/ncpp/utils.rb', line 234

def self.get_signed_word(addr, ov = nil)
  addr, ov, code_bin = resolve_code_loc(addr, ov)
  code_bin.read_word(addr).signed(32)
end

.get_sym_ov(sym) ⇒ Object



101
102
103
104
105
106
107
108
109
110
# File 'lib/ncpp/utils.rb', line 101

def self.get_sym_ov(sym)
  if sym.start_with?('_Z')
    invalid_sym_error(sym) unless Unarm.sym_map.keys.include?(sym)
  else
    mangled = Unarm.symbols.demangled_map[sym]
    invalid_sym_error(sym, demangled: true) if mangled.nil?
    sym = mangled
  end
  Integer(Unarm.symbols.locs.find {|k,v| v.include?(sym)}[0][2..], exception: false)
end

.get_word(addr, ov = nil) ⇒ Object Also known as: get_u32



214
215
216
217
# File 'lib/ncpp/utils.rb', line 214

def self.get_word(addr, ov = nil)
  addr, ov, code_bin = resolve_code_loc(addr, ov)
  code_bin.read_word(addr).unsigned(32)
end

.integer_check(int, meth_name = __callee__) ⇒ Object



55
56
57
# File 'lib/ncpp/utils.rb', line 55

def self.integer_check(int, meth_name = __callee__)
  raise "#{meth_name} expects an Integer" unless int.is_a? Integer
end

.invalid_sym_error(sym, demangled: false) ⇒ Object



75
76
77
78
# File 'lib/ncpp/utils.rb', line 75

def self.invalid_sym_error(sym, demangled: false)
  alt = demangled ? Unarm.symbols.demangled_map.suggest_similar_key(sym) : Unarm.sym_map.suggest_similar_key(sym)
  raise "'#{sym}' is not a valid symbol#{"\nDid you mean '#{alt}'?" unless alt.nil?}"
end

.modify_ins_immediate(loc, ov, val, thumb: false) ⇒ Object



147
148
149
150
151
152
# File 'lib/ncpp/utils.rb', line 147

def self.modify_ins_immediate(loc, ov, val, thumb: false)
  addr, ov, code_bin = resolve_code_loc(loc, ov)
  asm = thumb ? disasm_thumb_ins(code_bin.read_hword(addr)) : disasm_arm_ins(code_bin.read_word(addr))
  raise 'No immediate found in instruction' if !asm.include? '#'
  gen_hook_str('repl', addr, ov, asm[..asm.index('#')] + val.to_hex )
end

.next_addr(current_loc, ov = nil) ⇒ Object



340
341
342
343
344
345
346
# File 'lib/ncpp/utils.rb', line 340

def self.next_addr(current_loc, ov = nil)
  addr, ov, code_bin = resolve_code_loc(current_loc,ov)
  raise 'Next address is out of range' if addr >= code_bin.end_addr - 4
  is_thumb = addr & 1 != 0
  addr -= 1 if is_thumb
  addr += is_thumb ? 2 : 4
end

.numeric_check(num, meth_name = __callee__) ⇒ Object



51
52
53
# File 'lib/ncpp/utils.rb', line 51

def self.numeric_check(num, meth_name = __callee__)
  raise "#{meth_name} expects a Numeric" unless num.is_a? Numeric
end


63
64
65
# File 'lib/ncpp/utils.rb', line 63

def self.print_info(msg)
  puts 'INFO'.underline_blue + ": #{msg}".blue
end


59
60
61
# File 'lib/ncpp/utils.rb', line 59

def self.print_warning(msg)
  puts 'WARNING'.underline_yellow + ": #{msg}".yellow
end

.resolve_code_loc(addr, ov) ⇒ Object



120
121
122
123
# File 'lib/ncpp/utils.rb', line 120

def self.resolve_code_loc(addr, ov)
  addr, ov = resolve_loc(addr, ov)
  [addr, ov, ov.nil? || ov == -1 ? $rom.arm9 : $rom.get_overlay(ov)]
end

.resolve_loc(addr, ov = nil) ⇒ Object



112
113
114
115
116
117
118
# File 'lib/ncpp/utils.rb', line 112

def self.resolve_loc(addr, ov = nil)
  if addr.is_a? String
    ov = get_sym_ov(addr) if ov.nil?
    addr = sym_to_addr(addr)
  end
  [addr, ov]
end

.string_check(arr, meth_name = __callee__) ⇒ Object



43
44
45
# File 'lib/ncpp/utils.rb', line 43

def self.string_check(arr, meth_name = __callee__)
  raise "#{meth_name} expects a String" unless arr.is_a? String
end

.sym_to_addr(sym) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/ncpp/utils.rb', line 80

def self.sym_to_addr(sym)
  if sym.start_with? '_Z'
    addr = Unarm.sym_map[sym]
    if addr.nil?
      invalid_sym_error(sym)
    else
      addr
    end
  else
    # pp Unarm.symbols.ambig_demangled

    overloads = Unarm.symbols.ambig_demangled.filter { it[0] == sym }.map { it[1].to_hex }
    if !overloads.empty?
      print_warning "Demangled symbol name '#{sym}' is ambiguous.\n" \
                    "Overload#{'s' if overloads.length != 1 } found at: #{overloads.join(', ')}"
    end
    mangled = Unarm.symbols.demangled_map[sym]
    invalid_sym_error(sym, demangled: true) if mangled.nil?
    Unarm.sym_map[mangled]
  end
end

.to_c_array(arr) ⇒ Object



368
369
370
371
# File 'lib/ncpp/utils.rb', line 368

def self.to_c_array(arr)
  array_check(arr, 'to_c_array')
  arr.to_s.gsub!('[','{').gsub!(']','}')
end

.track_reg(reg, from_addr, ov, to_addr) ⇒ Object



305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/ncpp/utils.rb', line 305

def self.track_reg(reg, from_addr,ov, to_addr)
  start_addr, _ov, code_bin = resolve_code_loc(from_addr, ov)
  to_addr = sym_to_addr(to_addr) if to_addr.is_a? String
  reg = reg.to_sym
  code_bin.each_ins(from_addr..to_addr) do |ins|
    if ins.mnemonic == 'mov'
      if ins.args[1].kind == :reg && ins.args[1].value.reg == reg
        reg = ins.args[0].value.reg
      elsif ins.args[0].value.reg == reg
        reg = nil
        break
      end
    end
  end
  reg = reg.to_s unless reg.nil?
end

.valid_identifier?(name) ⇒ Boolean

Returns:



27
28
29
# File 'lib/ncpp/utils.rb', line 27

def self.valid_identifier?(name)
  name.start_with?(/[A-Za-z_]/)
end

.valid_identifier_check(name) ⇒ Object

checks if given name is a valid command/variable identifier



31
32
33
# File 'lib/ncpp/utils.rb', line 31

def self.valid_identifier_check(name) # checks if given name is a valid command/variable identifier

  raise "Invalid identifier '#{name}'" unless valid_identifier?(name)
end