node/lib/metasm/metasm/disassemble_api.rb
# define a register as a pointer to a structure
# rename all [reg+off] as [reg+struct.member] in current function
# also trace assignments of pointer members
define a register as a pointer to a structure
rename all [reg+off] as [reg+struct.member] in current function
also trace assignments of pointer members
define a register as a pointer to a structure rename all [ reg + off ] as [ reg + struct . member ] in current function also trace assignments of pointer members
def trace_update_reg_structptr(addr, reg, structname, structoff=0)
		sname = soff = ctx = nil
		expr_to_sname = lambda { |expr|
			if not expr.kind_of?(Expression) or expr.op != :+
				sname = nil
				next
			end
			sname = expr.lexpr || expr.rexpr
			soff = (expr.lexpr ? expr.rexpr : 0)
			if soff.kind_of?(Expression)
				if soff.op == :* and soff.lexpr == @cpu.size/8
					soff = 0
				elsif soff.rexpr.kind_of?(Expression) and soff.rexpr.op == :* and soff.rexpr.lexpr == @cpu.size/8
					soff = soff.lexpr
				elsif soff.lexpr.kind_of?(Expression) and soff.lexpr.op == :* and soff.lexpr.lexpr == @cpu.size/8
					soff = soff.rexpr
				end
			elsif soff.kind_of?(::Symbol)
				if not ctx[soff]
					soff = 0
				end
			end
		}
		lastdi = nil
		trace_function_register(addr, reg => Expression[structname, :+, structoff]) { |di, r, val, trace|
			next if r.to_s =~ /flag/	
			ctx = trace
			@cpu.instr_args_memoryptr(di).each { |ind|
				b = @cpu.instr_args_memoryptr_getbase(ind)
				b = b.symbolic if b
				next unless trace[b]
				imm = @cpu.instr_args_memoryptr_getoffset(ind) || 0
				expr_to_sname[trace[b] + imm]	
				next unless sname.kind_of?(::String) and soff.kind_of?(::Integer)
				next if not st = c_parser.toplevel.struct[sname] or not st.kind_of?(C::Union)
				next if soff == 0 and not di.backtrace_binding.find { |k, v| v-k != 0 }
				str = st.name.dup
				mb = st.expand_member_offset(c_parser, soff, str)
				imm = imm.rexpr if imm.kind_of?(Expression) and not imm.lexpr and imm.rexpr.kind_of?(ExpressionString)
				imm = imm.expr if imm.kind_of?(ExpressionString)
				@cpu.instr_args_memoryptr_setoffset(ind, ExpressionString.new(imm, str, :structoff))
				trace_update_reg_structptr_arg_enum(di, ind, mb, str) if mb
			} if lastdi != di.address
			lastdi = di.address
			next Expression[structname, :+, structoff] if di.address == addr and r == reg
			val = val.reduce_rec if val.kind_of?(Expression)
			val = Expression[val] if val.kind_of?(::String)
			case val
			when Expression
				expr_to_sname[val]
				if sname.kind_of?(::String) and soff.kind_of?(::Integer)
					Expression[sname, :+, soff]
				end
			when Indirection
				expr_to_sname[val.pointer.reduce]
				next unless sname.kind_of?(::String) and soff.kind_of?(::Integer)
				if st = c_parser.toplevel.struct[sname] and st.kind_of?(C::Union)
					pt = st.expand_member_offset(c_parser, soff, '')
					pt = pt.untypedef if pt
					if pt.kind_of?(C::Pointer)
						tt = pt.type.untypedef
						stars = ''
						while tt.kind_of?(C::Pointer)
							stars << '*'
							tt = tt.type.untypedef
						end
						if tt.kind_of?(C::Union) and tt.name
							Expression[tt.name + stars]
						end
					end
				elsif soff == 0 and sname[-1] == ?*
					Expression[sname[0...-1]]
				end
			end
		}
	end
def trace_update_reg_structptr ( addr , reg , structname , structoff = 0 ) sname = soff = ctx = nil expr_to_sname = lambda { | expr | if not expr . kind_of? ( Expression ) or expr . op != :+ sname = nil next end sname = expr . lexpr || expr . rexpr soff = ( expr . lexpr ? expr . rexpr : 0 ) if soff . kind_of? ( Expression ) if soff . op == :* and soff . lexpr == @cpu . size / 8 soff = 0 elsif soff . rexpr . kind_of? ( Expression ) and soff . rexpr . op == :* and soff . rexpr . lexpr == @cpu . size / 8 soff = soff . lexpr elsif soff . lexpr . kind_of? ( Expression ) and soff . lexpr . op == :* and soff . lexpr . lexpr == @cpu . size / 8 soff = soff . rexpr end elsif soff . kind_of? ( :: Symbol ) if not ctx [ soff ] soff = 0 end end } lastdi = nil trace_function_register ( addr , reg => Expression [ structname , :+ , structoff ] ) { | di , r , val , trace | next if r . to_s =~ / flag / ctx = trace @cpu . instr_args_memoryptr ( di ) . each { | ind | b = @cpu . instr_args_memoryptr_getbase ( ind ) b = b . symbolic if b next unless trace [ b ] imm = @cpu . instr_args_memoryptr_getoffset ( ind ) || 0 expr_to_sname [ trace [ b ] + imm ] next unless sname . kind_of? ( :: String ) and soff . kind_of? ( :: Integer ) next if not st = c_parser . toplevel . struct [ sname ] or not st . kind_of? ( C :: Union ) next if soff == 0 and not di . backtrace_binding . find { | k , v | v - k != 0 } str = st . name . dup mb = st . expand_member_offset ( c_parser , soff , str ) imm = imm . rexpr if imm . kind_of? ( Expression ) and not imm . lexpr and imm . rexpr . kind_of? ( ExpressionString ) imm = imm . expr if imm . kind_of? ( ExpressionString ) @cpu . instr_args_memoryptr_setoffset ( ind , ExpressionString . new ( imm , str , :structoff ) ) trace_update_reg_structptr_arg_enum ( di , ind , mb , str ) if mb } if lastdi != di . address lastdi = di . address next Expression [ structname , :+ , structoff ] if di . address == addr and r == reg val = val . reduce_rec if val . kind_of? ( Expression ) val = Expression [ val ] if val . kind_of? ( :: String ) case val when Expression expr_to_sname [ val ] if sname . kind_of? ( :: String ) and soff . kind_of? ( :: Integer ) Expression [ sname , :+ , soff ] end when Indirection expr_to_sname [ val . pointer . reduce ] next unless sname . kind_of? ( :: String ) and soff . kind_of? ( :: Integer ) if st = c_parser . toplevel . struct [ sname ] and st . kind_of? ( C :: Union ) pt = st . expand_member_offset ( c_parser , soff , '' ) pt = pt . untypedef if pt if pt . kind_of? ( C :: Pointer ) tt = pt . type . untypedef stars = '' while tt . kind_of? ( C :: Pointer ) stars << '*' tt = tt . type . untypedef end if tt . kind_of? ( C :: Union ) and tt . name Expression [ tt . name + stars ] end end elsif soff == 0 and sname [ - 1 ] == ?* Expression [ sname [ 0 ... - 1 ] ] end end } end
define a register as a pointer to a structure
rename all [reg+off] as [reg+struct.member] in current function
also trace assignments of pointer members
define a register as a pointer to a structure rename all [ reg + off ] as [ reg + struct . member ] in current function also trace assignments of pointer members
# ignore index in ptr array # array with 1 byte elements / pre-scaled idx? # XXX maybe too ia32-specific? # find the structure dereference in di # check expr has the form 'traced_struct_reg + off' # Expr#+ calls Expr#reduce # ignore lea esi, [esi+0] # TODO if trace[b] offset != 0, we had a lea reg, [struct+substruct_off], tweak str accordingly # resolve struct + off into struct.membername # patch di # check if the type is an enum/bitfield, patch instruction immediates # check if we need to trace 'r' further # only trace trivial structptr+off expressions # di is mov reg, [ptr+struct.offset] # check if the target member is a pointer to a struct, if so, trace it # XXX pointer to pointer to struct # full C type support would be better, but harder to fit in an Expr # in other cases, stop trace
addr
reg
structname
structoff