node/lib/metasm/metasm/cpu/ia32/decode.rb
def backtrace_update_function_binding(dasm, faddr, f, retaddrlist, *wantregs)
		b = f.backtrace_binding

		esp, ebp = register_symbols[4, 2]

		# XXX handle retaddrlist for multiple/mixed thunks
		if retaddrlist and not dasm.decoded[retaddrlist.first] and di = dasm.decoded[faddr]
			# no return instruction, must be a thunk : find the last instruction (to backtrace from it)
			done = []
			while ndi = dasm.decoded[di.block.to_subfuncret.to_a.first] || dasm.decoded[di.block.to_normal.to_a.first] and ndi.kind_of? DecodedInstruction and not done.include? ndi.address
				done << ndi.address
				di = ndi
			end
			if not di.block.to_subfuncret.to_a.first and di.block.to_normal and di.block.to_normal.length > 1
				thunklast = di.block.list.last.address
			end
		end

		bt_val = lambda { |r|
			next if not retaddrlist
			b[r] = Expression::Unknown	# TODO :pending or something ? (for recursive lazy functions)
			bt = []
			retaddrlist.each { |retaddr|
				bt |= dasm.backtrace(Expression[r], (thunklast ? thunklast : retaddr),
					:include_start => true, :snapshot_addr => faddr, :origin => retaddr, :from_subfuncret => thunklast)
			}
			if bt.length != 1
				b[r] = Expression::Unknown
			else
				b[r] = bt.first
			end
		}

		if not wantregs.empty?
			wantregs.each(&bt_val)
		else
			if dasm.function_blocks(faddr, true).length < 20
				register_symbols.each(&bt_val)
			else
				[ebp, esp].each(&bt_val)
			end
		end

		backtrace_update_function_binding_check(dasm, faddr, f, b, &bt_val)

		b
	end
# updates the function backtrace_binding
# if the function is big and no specific register is given, do nothing (the binding will be lazily updated later, on demand)
# XXX assume retaddrlist is either a list of addr of ret or a list with a single entry which is an external function name (thunk)
updates the function backtrace_binding
if the function is big and no specific register is given, do nothing (the binding will be lazily updated later, on demand)
XXX assume retaddrlist is either a list of addr of ret or a list with a single entry which is an external function name (thunk)
updates the function backtrace_binding if the function is big and no specific register is given do nothing ( the binding will be lazily updated later on demand ) XXX assume retaddrlist is either a list of addr of ret or a list with a single entry which is an external function name ( thunk )
def backtrace_update_function_binding(dasm, faddr, f, retaddrlist, *wantregs)
		b = f.backtrace_binding
		esp, ebp = register_symbols[4, 2]
		if retaddrlist and not dasm.decoded[retaddrlist.first] and di = dasm.decoded[faddr]
			done = []
			while ndi = dasm.decoded[di.block.to_subfuncret.to_a.first] || dasm.decoded[di.block.to_normal.to_a.first] and ndi.kind_of? DecodedInstruction and not done.include? ndi.address
				done << ndi.address
				di = ndi
			end
			if not di.block.to_subfuncret.to_a.first and di.block.to_normal and di.block.to_normal.length > 1
				thunklast = di.block.list.last.address
			end
		end
		bt_val = lambda { |r|
			next if not retaddrlist
			b[r] = Expression::Unknown	
			bt = []
			retaddrlist.each { |retaddr|
				bt |= dasm.backtrace(Expression[r], (thunklast ? thunklast : retaddr),
					:include_start => true, :snapshot_addr => faddr, :origin => retaddr, :from_subfuncret => thunklast)
			}
			if bt.length != 1
				b[r] = Expression::Unknown
			else
				b[r] = bt.first
			end
		}
		if not wantregs.empty?
			wantregs.each(&bt_val)
		else
			if dasm.function_blocks(faddr, true).length < 20
				register_symbols.each(&bt_val)
			else
				[ebp, esp].each(&bt_val)
			end
		end
		backtrace_update_function_binding_check(dasm, faddr, f, b, &bt_val)
		b
	end
def backtrace_update_function_binding ( dasm , faddr , f , retaddrlist , * wantregs ) b = f . backtrace_binding esp , ebp = register_symbols [ 4 , 2 ] if retaddrlist and not dasm . decoded [ retaddrlist . first ] and di = dasm . decoded [ faddr ] done = [ ] while ndi = dasm . decoded [ di . block . to_subfuncret . to_a . first ] || dasm . decoded [ di . block . to_normal . to_a . first ] and ndi . kind_of? DecodedInstruction and not done . include? ndi . address done << ndi . address di = ndi end if not di . block . to_subfuncret . to_a . first and di . block . to_normal and di . block . to_normal . length > 1 thunklast = di . block . list . last . address end end bt_val = lambda { | r | next if not retaddrlist b [ r ] = Expression :: Unknown bt = [ ] retaddrlist . each { | retaddr | bt |= dasm . backtrace ( Expression [ r ] , ( thunklast ? thunklast : retaddr ) , :include_start => true , :snapshot_addr => faddr , :origin => retaddr , :from_subfuncret => thunklast ) } if bt . length != 1 b [ r ] = Expression :: Unknown else b [ r ] = bt . first end } if not wantregs . empty? wantregs . each ( & bt_val ) else if dasm . function_blocks ( faddr , true ) . length < 20 register_symbols . each ( & bt_val ) else [ ebp , esp ] . each ( & bt_val ) end end backtrace_update_function_binding_check ( dasm , faddr , f , b , & bt_val ) b end
updates the function backtrace_binding
if the function is big and no specific register is given, do nothing (the binding will be lazily updated later, on demand)
XXX assume retaddrlist is either a list of addr of ret or a list with a single entry which is an external function name (thunk)
updates the function backtrace_binding if the function is big and no specific register is given do nothing ( the binding will be lazily updated later on demand ) XXX assume retaddrlist is either a list of addr of ret or a list with a single entry which is an external function name ( thunk )
# XXX handle retaddrlist for multiple/mixed thunks # no return instruction, must be a thunk : find the last instruction (to backtrace from it) # TODO :pending or something ? (for recursive lazy functions)
dasm
faddr
f
retaddrlist
wantregs