<commit_before>#    This file is part of Metasm, the Ruby assembly manipulation suite
#    Copyright (C) 2007 <NAME>
#
#    Licence is LGPL, see LICENCE in the top-level directory


require 'metasm/os/main'

module Metasm
class PTrace32
	attr_reader :buf, :pid

	def self.open(target)
		ptrace = new(target)
		return ptrace if not block_given?
		ret = yield ptrace
		ptrace.detach
		ret
	end

	# creates a ptraced process (target = path)
	# or opens a running process (target = pid)
	def initialize(target)
		@buf = [0].pack('l')
		@bufptr = [@buf].pack('P').unpack('l').first
		begin
			@pid = Integer(target)
			attach
		rescue ArgumentError
			if not @pid = fork
				traceme
				exec target
			end
		end
		Process.wait(@pid)
		puts "Ptrace: attached to #@pid" if $DEBUG
	end


	# interpret the value turned as an unsigned long
	def bufval
		@buf.unpack('l').first
	end

	# reads a memory range
	def readmem(off, len)
		decal = off & 3
		buf = ''
		if decal > 0
			off -= decal
			peekdata(off)
			off += 4
			buf << @buf[decal..3]
		end
		offend = off + len - 3
		while off < offend
			peekdata(off)
			buf << @buf[0, 4]
			off += 4
		end
		buf[0, len]
	end

	def writemem(off, str)
		decal = off & 3
		if decal > 0
			off -= decal
			peekdata(off)
			str = @buf[0...decal] + str
		end
		decal = str.length & 3
		if decal > 0
			peekdata(off+str.length-decal)
			str += @buf[decal..3]
		end
		i = 0
		while i < str.length
			pokedata(off+i, str[i, 4])
			i += 4
		end
	end

	# linux/ptrace.h
	COMMAND = {
		'TRACEME'         =>   0, 'PEEKTEXT'        =>   1,
		'PEEKDATA'        =>   2, 'PEEKUSR'         =>   3,
		'POKETEXT'        =>   4, 'POKEDATA'        =>   5,
		'POKEUSR'         =>   6, 'CONT'            =>   7,
		'KILL'            =>   8, 'SINGLESTEP'      =>   9,
		'ATTACH'          =>  16, 'DETACH'          =>  17,
		'SYSCALL'         =>  24,

	# i486-asm/ptrace.h
		# Arbitrarily choose the same ptrace numbers as used by the Sparc code.
		'GETREGS'         =>  12, 'SETREGS'         =>  13,
		'GETFPREGS'       =>  14, 'SETFPREGS'       =>  15,
		'GETFPXREGS'      =>  18, 'SETFPXREGS'      =>  19,
		'OLDSETOPTIONS'   =>  21, 'GET_THREAD_AREA' =>  25,
		'SET_THREAD_AREA' =>  26, 'SYSEMU'           => 31,
		'SYSEMU_SINGLESTEP'=> 32,
		# 0x4200-0x4300 are reserved for architecture-independent additions.
		'SETOPTIONS'      => 0x4200, 'GETEVENTMSG'   => 0x4201,
		'GETSIGINFO'      => 0x4202, 'SETSIGINFO'    => 0x4203
	}

	OPTIONS = {
		# options set using PTRACE_SETOPTIONS
		'TRACESYSGOOD'  => 0x01, 'TRACEFORK'     => 0x02,
		'TRACEVFORK'    => 0x04, 'TRACECLONE'    => 0x08,
		'TRACEEXEC'     => 0x10, 'TRACEVFORKDONE'=> 0x20,
		'TRACEEXIT'     => 0x40
	}

	WAIT_EXTENDEDRESULT = {
		# Wait extended result codes for the above trace options.
		'EVENT_FORK'       => 1, 'EVENT_VFORK'      => 2,
		'EVENT_CLONE'      => 3, 'EVENT_EXEC'       => 4,
		'EVENT_VFORK_DONE' => 5, 'EVENT_EXIT'       => 6
	}
	

	REGS_I386 = {
		'EBX' => 0, 'ECX' => 1, 'EDX' => 2, 'ESI' => 3,
		'EDI' => 4, 'EBP' => 5, 'EAX' => 6, 'DS'  => 7,
		'ES'  => 8, 'FS'  => 9, 'GS'  => 10, 'ORIG_EAX' => 11,
		'EIP' => 12, 'CS'  => 13, 'EFL' => 14, 'UESP'=> 15,
		'SS'  => 16, 'FRAME_SIZE' => 17 }<commit_msg>Ptrace: add esp as alias to uesp<commit_after>#    This file is part of Metasm, the Ruby assembly manipulation suite
#    Copyright (C) 2007 <NAME>
#
#    Licence is LGPL, see LICENCE in the top-level directory


require 'metasm/os/main'

module Metasm
class PTrace32
	attr_reader :buf, :pid

	def self.open(target)
		ptrace = new(target)
		return ptrace if not block_given?
		ret = yield ptrace
		ptrace.detach
		ret
	end

	# creates a ptraced process (target = path)
	# or opens a running process (target = pid)
	def initialize(target)
		@buf = [0].pack('l')
		@bufptr = [@buf].pack('P').unpack('l').first
		begin
			@pid = Integer(target)
			attach
		rescue ArgumentError
			if not @pid = fork
				traceme
				exec target
			end
		end
		Process.wait(@pid)
		puts "Ptrace: attached to #@pid" if $DEBUG
	end


	# interpret the value turned as an unsigned long
	def bufval
		@buf.unpack('l').first
	end

	# reads a memory range
	def readmem(off, len)
		decal = off & 3
		buf = ''
		if decal > 0
			off -= decal
			peekdata(off)
			off += 4
			buf << @buf[decal..3]
		end
		offend = off + len - 3
		while off < offend
			peekdata(off)
			buf << @buf[0, 4]
			off += 4
		end
		buf[0, len]
	end

	def writemem(off, str)
		decal = off & 3
		if decal > 0
			off -= decal
			peekdata(off)
			str = @buf[0...decal] + str
		end
		decal = str.length & 3
		if decal > 0
			peekdata(off+str.length-decal)
			str += @buf[decal..3]
		end
		i = 0
		while i < str.length
			pokedata(off+i, str[i, 4])
			i += 4
		end
	end

	# linux/ptrace.h
	COMMAND = {
		'TRACEME'         =>   0, 'PEEKTEXT'        =>   1,
		'PEEKDATA'        =>   2, 'PEEKUSR'         =>   3,
		'POKETEXT'        =>   4, 'POKEDATA'        =>   5,
		'POKEUSR'         =>   6, 'CONT'            =>   7,
		'KILL'            =>   8, 'SINGLESTEP'      =>   9,
		'ATTACH'          =>  16, 'DETACH'          =>  17,
		'SYSCALL'         =>  24,

	# i486-asm/ptrace.h
		# Arbitrarily choose the same ptrace numbers as used by the Sparc code.
		'GETREGS'         =>  12, 'SETREGS'         =>  13,
		'GETFPREGS'       =>  14, 'SETFPREGS'       =>  15,
		'GETFPXREGS'      =>  18, 'SETFPXREGS'      =>  19,
		'OLDSETOPTIONS'   =>  21, 'GET_THREAD_AREA' =>  25,
		'SET_THREAD_AREA' =>  26, 'SYSEMU'           => 31,
		'SYSEMU_SINGLESTEP'=> 32,
		# 0x4200-0x4300 are reserved for architecture-independent additions.
		'SETOPTIONS'      => 0x4200, 'GETEVENTMSG'   => 0x4201,
		'GETSIGINFO'      => 0x4202, 'SETSIGINFO'    => 0x4203
	}

	OPTIONS = {
		# options set using PTRACE_SETOPTIONS
		'TRACESYSGOOD'  => 0x01, 'TRACEFORK'     => 0x02,
		'TRACEVFORK'    => 0x04, 'TRACECLONE'    => 0x08,
		'TRACEEXEC'     => 0x10, 'TRACEVFORKDONE'=> 0x20,
		'TRACEEXIT'     => 0x40
	}

	WAIT_EXTENDEDRESULT = {
		# Wait extended result codes for the above trace options.
		'EVENT_FORK'       => 1, 'EVENT_VFORK'      => 2,
		'EVENT_CLONE'      => 3, 'EVENT_EXEC'       => 4,
		'EVENT_VFORK_DONE' => 5, 'EVENT_EXIT'       => 6
	}
	

	REGS_I386 = {
		'EBX' => 0, 'ECX' => 1, 'EDX' => 2, 'ESI' => 3,
		'EDI' => 4, 'EBP' => 5, 'EAX' => 6, 'DS'  => 7,
		'ES'  => 8, 'FS'  => 9, 'GS'  => 10, 'ORIG_EAX' => 11,
		'EIP' => 12, 'CS'  => 13, 'EFL' => 14, 'UESP'=> 15,
		'ESP' => 15,
		'SS'  => 16, 'FRAME_SIZE' => 17 }
{'fraction_non_alphanumeric': 0.15439577508543026, 'fraction_numerical': 0.047530288909599254, 'mean_word_length': 2.281855249745158, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 130, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2051696', 'n_tokens_mistral': 3116, 'n_tokens_neox': 2674, 'n_words': 680}