node/lib/metasm/metasm/disassemble_api.rb
def trace_update_reg_structptr_arg_enum(di, ind, mb, str)
		if ename = mb.has_attribute_var('enum') and enum = c_parser.toplevel.struct[ename] and enum.kind_of?(C::Enum)
			# handle enums: struct moo { int __attribute__((enum(bla))) fld; };
			doit = lambda { |_di|
				if num = _di.instruction.args.grep(Expression).first and num_i = num.reduce and num_i.kind_of?(::Integer)
					# handle enum values on tagged structs
					if enum.members and name = enum.members.index(num_i)
						num.lexpr = nil
						num.op = :+
						num.rexpr = ExpressionString.new(Expression[num_i], name, :enum)
						_di.add_comment "enum::#{ename}" if _di.address != di.address
					end
				end
			}

			doit[di]

			# mov eax, [ptr+struct.enumfield]  =>  trace eax
			if reg = @cpu.instr_args_regs(di).find { |r| v = di.backtrace_binding[r.symbolic] and (v - ind.symbolic) == 0 }
				reg = reg.symbolic
				trace_function_register(di.address, reg => Expression[0]) { |_di, r, val, trace|
					next if r != reg and val != Expression[reg]
					doit[_di]
					val
				}
			end

		elsif mb.untypedef.kind_of?(C::Struct)
			# handle bitfields

			byte_off = 0
			if str =~ /\+(\d+)$/
				# test byte [bitfield+1], 0x1  =>  test dword [bitfield], 0x100
				# XXX little-endian only
				byte_off = $1.to_i
				str[/\+\d+$/] = ''
			end
			cmt = str.split('.')[-2, 2].join('.') if str.count('.') > 1

			doit = lambda { |_di, add|
				if num = _di.instruction.args.grep(Expression).first and num_i = num.reduce and num_i.kind_of?(::Integer)
					# TODO handle ~num_i
					num_left = num_i << add
					s_or = []
					mb.untypedef.members.each { |mm|
						if bo = mb.bitoffsetof(c_parser, mm)
							boff, blen = bo
							if mm.name && blen == 1 && ((num_left >> boff) & 1) > 0
								s_or << mm.name
								num_left &= ~(1 << boff)
							end
						end
					}
					if s_or.first
						if num_left != 0
							s_or << ('0x%X' % num_left)
						end
						s = s_or.join('|')
						num.lexpr = nil
						num.op = :+
						num.rexpr = ExpressionString.new(Expression[num_i], s, :bitfield)
						_di.add_comment cmt if _di.address != di.address
					end
				end
			}

			doit[di, byte_off*8]

			if reg = @cpu.instr_args_regs(di).find { |r| v = di.backtrace_binding[r.symbolic] and (v - ind.symbolic) == 0 }
				reg = reg.symbolic
				trace_function_register(di.address, reg => Expression[0]) { |_di, r, val, trace|
					if r.kind_of?(Expression) and r.op == :&
					       if r.lexpr == reg
						       # test al, 42
						       doit[_di, byte_off*8]
					       elsif r.lexpr.kind_of?(Expression) and r.lexpr.op == :>> and r.lexpr.lexpr == reg
						       # test ah, 42
						       doit[_di, byte_off*8+r.lexpr.rexpr]
					       end
					end
					next if r != reg and val != Expression[reg]
					doit[_di, byte_off*8]
					_di.address == di.address && r == reg ? Expression[0] : val
				}
			end
		end
	end
# found a special member of a struct, check if we can apply
# bitfield/enum name to other constants in the di
found a special member of a struct, check if we can apply
bitfield/enum name to other constants in the di
found a special member of a struct check if we can apply bitfield / enum name to other constants in the di
def trace_update_reg_structptr_arg_enum(di, ind, mb, str)
		if ename = mb.has_attribute_var('enum') and enum = c_parser.toplevel.struct[ename] and enum.kind_of?(C::Enum)
			doit = lambda { |_di|
				if num = _di.instruction.args.grep(Expression).first and num_i = num.reduce and num_i.kind_of?(::Integer)
					if enum.members and name = enum.members.index(num_i)
						num.lexpr = nil
						num.op = :+
						num.rexpr = ExpressionString.new(Expression[num_i], name, :enum)
						_di.add_comment "enum::#{ename}" if _di.address != di.address
					end
				end
			}
			doit[di]
			if reg = @cpu.instr_args_regs(di).find { |r| v = di.backtrace_binding[r.symbolic] and (v - ind.symbolic) == 0 }
				reg = reg.symbolic
				trace_function_register(di.address, reg => Expression[0]) { |_di, r, val, trace|
					next if r != reg and val != Expression[reg]
					doit[_di]
					val
				}
			end
		elsif mb.untypedef.kind_of?(C::Struct)
			byte_off = 0
			if str =~ /\+(\d+)$/
				byte_off = $1.to_i
				str[/\+\d+$/] = ''
			end
			cmt = str.split('.')[-2, 2].join('.') if str.count('.') > 1
			doit = lambda { |_di, add|
				if num = _di.instruction.args.grep(Expression).first and num_i = num.reduce and num_i.kind_of?(::Integer)
					num_left = num_i << add
					s_or = []
					mb.untypedef.members.each { |mm|
						if bo = mb.bitoffsetof(c_parser, mm)
							boff, blen = bo
							if mm.name && blen == 1 && ((num_left >> boff) & 1) > 0
								s_or << mm.name
								num_left &= ~(1 << boff)
							end
						end
					}
					if s_or.first
						if num_left != 0
							s_or << ('0x%X' % num_left)
						end
						s = s_or.join('|')
						num.lexpr = nil
						num.op = :+
						num.rexpr = ExpressionString.new(Expression[num_i], s, :bitfield)
						_di.add_comment cmt if _di.address != di.address
					end
				end
			}
			doit[di, byte_off*8]
			if reg = @cpu.instr_args_regs(di).find { |r| v = di.backtrace_binding[r.symbolic] and (v - ind.symbolic) == 0 }
				reg = reg.symbolic
				trace_function_register(di.address, reg => Expression[0]) { |_di, r, val, trace|
					if r.kind_of?(Expression) and r.op == :&
					       if r.lexpr == reg
						       doit[_di, byte_off*8]
					       elsif r.lexpr.kind_of?(Expression) and r.lexpr.op == :>> and r.lexpr.lexpr == reg
						       doit[_di, byte_off*8+r.lexpr.rexpr]
					       end
					end
					next if r != reg and val != Expression[reg]
					doit[_di, byte_off*8]
					_di.address == di.address && r == reg ? Expression[0] : val
				}
			end
		end
	end
def trace_update_reg_structptr_arg_enum ( di , ind , mb , str ) if ename = mb . has_attribute_var ( 'enum' ) and enum = c_parser . toplevel . struct [ ename ] and enum . kind_of? ( C :: Enum ) doit = lambda { | _di | if num = _di . instruction . args . grep ( Expression ) . first and num_i = num . reduce and num_i . kind_of? ( :: Integer ) if enum . members and name = enum . members . index ( num_i ) num . lexpr = nil num . op = :+ num . rexpr = ExpressionString . new ( Expression [ num_i ] , name , :enum ) _di . add_comment "enum::#{ename}" if _di . address != di . address end end } doit [ di ] if reg = @cpu . instr_args_regs ( di ) . find { | r | v = di . backtrace_binding [ r . symbolic ] and ( v - ind . symbolic ) == 0 } reg = reg . symbolic trace_function_register ( di . address , reg => Expression [ 0 ] ) { | _di , r , val , trace | next if r != reg and val != Expression [ reg ] doit [ _di ] val } end elsif mb . untypedef . kind_of? ( C :: Struct ) byte_off = 0 if str =~ / \+ ( \d +)$ / byte_off = $1 . to_i str [ / \+ \d +$ / ] = '' end cmt = str . split ( '.' ) [ - 2 , 2 ] . join ( '.' ) if str . count ( '.' ) > 1 doit = lambda { | _di , add | if num = _di . instruction . args . grep ( Expression ) . first and num_i = num . reduce and num_i . kind_of? ( :: Integer ) num_left = num_i << add s_or = [ ] mb . untypedef . members . each { | mm | if bo = mb . bitoffsetof ( c_parser , mm ) boff , blen = bo if mm . name && blen == 1 && ( ( num_left >> boff ) & 1 ) > 0 s_or << mm . name num_left &= ~ ( 1 << boff ) end end } if s_or . first if num_left != 0 s_or << ( '0x%X' % num_left ) end s = s_or . join ( '|' ) num . lexpr = nil num . op = :+ num . rexpr = ExpressionString . new ( Expression [ num_i ] , s , :bitfield ) _di . add_comment cmt if _di . address != di . address end end } doit [ di , byte_off * 8 ] if reg = @cpu . instr_args_regs ( di ) . find { | r | v = di . backtrace_binding [ r . symbolic ] and ( v - ind . symbolic ) == 0 } reg = reg . symbolic trace_function_register ( di . address , reg => Expression [ 0 ] ) { | _di , r , val , trace | if r . kind_of? ( Expression ) and r . op == :& if r . lexpr == reg doit [ _di , byte_off * 8 ] elsif r . lexpr . kind_of? ( Expression ) and r . lexpr . op == :>> and r . lexpr . lexpr == reg doit [ _di , byte_off * 8 + r . lexpr . rexpr ] end end next if r != reg and val != Expression [ reg ] doit [ _di , byte_off * 8 ] _di . address == di . address && r == reg ? Expression [ 0 ] : val } end end end
found a special member of a struct, check if we can apply
bitfield/enum name to other constants in the di
found a special member of a struct check if we can apply bitfield / enum name to other constants in the di
# handle enums: struct moo { int __attribute__((enum(bla))) fld; }; # handle enum values on tagged structs # mov eax, [ptr+struct.enumfield]  =>  trace eax # handle bitfields # test byte [bitfield+1], 0x1  =>  test dword [bitfield], 0x100 # XXX little-endian only # TODO handle ~num_i # test al, 42 # test ah, 42
di
ind
mb
str