58 lines
1.5 KiB
Ruby
58 lines
1.5 KiB
Ruby
|
# This file is part of Metasm, the Ruby assembly manipulation suite
|
||
|
# Copyright (C) 2006-2009 Yoann GUILLOT
|
||
|
#
|
||
|
# Licence is LGPL, see LICENCE in the top-level directory
|
||
|
|
||
|
|
||
|
# metasm dasm plugin
|
||
|
# decompose immediate values from C constants, adds a comment with the decomposition
|
||
|
|
||
|
# find immediate exprs in the instruction at addr, yield them
|
||
|
def imm_to_const(addr)
|
||
|
return if not di = di_at(addr)
|
||
|
# TODO enter into memrefs ?
|
||
|
di.instruction.args.grep(Expression).each { |a|
|
||
|
i = a.reduce
|
||
|
next if not i.kind_of? Integer
|
||
|
next if not cstbase = yield(i)
|
||
|
if c = imm_to_const_decompose(i, cstbase)
|
||
|
di.add_comment c
|
||
|
end
|
||
|
}
|
||
|
end
|
||
|
|
||
|
# find the bitwise decomposition of imm into constants whose name include cstbase
|
||
|
def imm_to_const_decompose(imm, cstbase)
|
||
|
cstbase = /#{cstbase}/i if not cstbase.kind_of? Regexp
|
||
|
dict = {}
|
||
|
c_parser.lexer.definition.keys.grep(cstbase).each { |cst|
|
||
|
if i = c_parser.macro_numeric(cst)
|
||
|
dict[cst] = i
|
||
|
end
|
||
|
}
|
||
|
c_parser.toplevel.symbol.each { |k, v|
|
||
|
dict[k] = v if v.kind_of? Integer and k =~ cstbase
|
||
|
}
|
||
|
dict.delete_if { |k, v| imm & v != v }
|
||
|
if cst = dict.index(imm)
|
||
|
cst
|
||
|
else
|
||
|
# a => 1, b => 2, c => 4, all => 7: discard abc, keep 'all'
|
||
|
dict.delete_if { |k, v| dict.find { |kk, vv| vv > v and vv & v == v } }
|
||
|
dict.keys.join(' | ') if not dict.empty?
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if gui
|
||
|
gui.keyboard_callback[?K] = lambda { |*a|
|
||
|
addr = gui.curaddr
|
||
|
imm_to_const(addr) { |i|
|
||
|
gui.inputbox("const name for #{Expression[i]}") { |name|
|
||
|
imm_to_const(addr) { |ii| name if ii == i }
|
||
|
gui.gui_update
|
||
|
}
|
||
|
nil
|
||
|
}
|
||
|
}
|
||
|
end
|