From: Ralf Jung Date: Sun, 21 Apr 2019 12:34:30 +0000 (+0200) Subject: Windows: implement heap functions X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=e4970fe6ffa3052d6b1a880c934d4465bf656df9;p=rust.git Windows: implement heap functions --- diff --git a/src/fn_call.rs b/src/fn_call.rs index ae6aff10ac2..9789a76c639 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -50,6 +50,86 @@ fn find_fn( Ok(Some(this.load_mir(instance.def)?)) } + fn malloc( + &mut self, + size: u64, + zero_init: bool, + ) -> Scalar { + let this = self.eval_context_mut(); + let tcx = &{this.tcx.tcx}; + if size == 0 { + Scalar::from_int(0, this.pointer_size()) + } else { + let align = this.tcx.data_layout.pointer_align.abi; + let ptr = this.memory_mut().allocate(Size::from_bytes(size), align, MiriMemoryKind::C.into()); + if zero_init { + // We just allocated this, the access cannot fail + this.memory_mut() + .get_mut(ptr.alloc_id).unwrap() + .write_repeat(tcx, ptr, 0, Size::from_bytes(size)).unwrap(); + } + Scalar::Ptr(ptr) + } + } + + fn free( + &mut self, + ptr: Scalar, + ) -> EvalResult<'tcx> { + let this = self.eval_context_mut(); + if !ptr.is_null_ptr(this) { + this.memory_mut().deallocate( + ptr.to_ptr()?, + None, + MiriMemoryKind::C.into(), + )?; + } + Ok(()) + } + + fn realloc( + &mut self, + old_ptr: Scalar, + new_size: u64, + ) -> EvalResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + let align = this.tcx.data_layout.pointer_align.abi; + if old_ptr.is_null_ptr(this) { + if new_size == 0 { + Ok(Scalar::from_int(0, this.pointer_size())) + } else { + let new_ptr = this.memory_mut().allocate( + Size::from_bytes(new_size), + align, + MiriMemoryKind::C.into() + ); + Ok(Scalar::Ptr(new_ptr)) + } + } else { + let old_ptr = old_ptr.to_ptr()?; + let memory = this.memory_mut(); + let old_size = Size::from_bytes(memory.get(old_ptr.alloc_id)?.bytes.len() as u64); + if new_size == 0 { + memory.deallocate( + old_ptr, + Some((old_size, align)), + MiriMemoryKind::C.into(), + )?; + Ok(Scalar::from_int(0, this.pointer_size())) + } else { + let new_ptr = memory.reallocate( + old_ptr, + old_size, + align, + Size::from_bytes(new_size), + align, + MiriMemoryKind::C.into(), + )?; + Ok(Scalar::Ptr(new_ptr)) + } + } + } + /// Emulates calling a foreign item, failing if the item is not supported. /// This function will handle `goto_block` if needed. fn emulate_foreign_item( @@ -87,28 +167,15 @@ fn emulate_foreign_item( match link_name { "malloc" => { let size = this.read_scalar(args[0])?.to_usize(this)?; - if size == 0 { - this.write_null(dest)?; - } else { - let align = this.tcx.data_layout.pointer_align.abi; - let ptr = this.memory_mut().allocate(Size::from_bytes(size), align, MiriMemoryKind::C.into()); - this.write_scalar(Scalar::Ptr(ptr), dest)?; - } + let res = this.malloc(size, /*zero_init:*/ false); + this.write_scalar(res, dest)?; } "calloc" => { let items = this.read_scalar(args[0])?.to_usize(this)?; let len = this.read_scalar(args[1])?.to_usize(this)?; - let bytes = items.checked_mul(len).ok_or_else(|| InterpError::Overflow(mir::BinOp::Mul))?; - - if bytes == 0 { - this.write_null(dest)?; - } else { - let size = Size::from_bytes(bytes); - let align = this.tcx.data_layout.pointer_align.abi; - let ptr = this.memory_mut().allocate(size, align, MiriMemoryKind::C.into()); - this.memory_mut().get_mut(ptr.alloc_id)?.write_repeat(tcx, ptr, 0, size)?; - this.write_scalar(Scalar::Ptr(ptr), dest)?; - } + let size = items.checked_mul(len).ok_or_else(|| InterpError::Overflow(mir::BinOp::Mul))?; + let res = this.malloc(size, /*zero_init:*/ true); + this.write_scalar(res, dest)?; } "posix_memalign" => { let ret = this.deref_operand(args[0])?; @@ -136,55 +203,15 @@ fn emulate_foreign_item( } this.write_null(dest)?; } - "free" => { let ptr = this.read_scalar(args[0])?.not_undef()?; - if !ptr.is_null_ptr(this) { - this.memory_mut().deallocate( - ptr.to_ptr()?, - None, - MiriMemoryKind::C.into(), - )?; - } + this.free(ptr)?; } "realloc" => { let old_ptr = this.read_scalar(args[0])?.not_undef()?; let new_size = this.read_scalar(args[1])?.to_usize(this)?; - let align = this.tcx.data_layout.pointer_align.abi; - if old_ptr.is_null_ptr(this) { - if new_size == 0 { - this.write_null(dest)?; - } else { - let new_ptr = this.memory_mut().allocate( - Size::from_bytes(new_size), - align, - MiriMemoryKind::C.into() - ); - this.write_scalar(Scalar::Ptr(new_ptr), dest)?; - } - } else { - let old_ptr = old_ptr.to_ptr()?; - let memory = this.memory_mut(); - let old_size = Size::from_bytes(memory.get(old_ptr.alloc_id)?.bytes.len() as u64); - if new_size == 0 { - memory.deallocate( - old_ptr, - Some((old_size, align)), - MiriMemoryKind::C.into(), - )?; - this.write_null(dest)?; - } else { - let new_ptr = memory.reallocate( - old_ptr, - old_size, - align, - Size::from_bytes(new_size), - align, - MiriMemoryKind::C.into(), - )?; - this.write_scalar(Scalar::Ptr(new_ptr), dest)?; - } - } + let res = this.realloc(old_ptr, new_size)?; + this.write_scalar(res, dest)?; } "__rust_alloc" => { @@ -687,6 +714,35 @@ fn emulate_foreign_item( }, // Windows API stubs. + // HANDLE = isize + // DWORD = ULONG = u32 + "GetProcessHeap" => { + // Just fake a HANDLE + this.write_scalar(Scalar::from_int(1, this.pointer_size()), dest)?; + } + "HeapAlloc" => { + let _handle = this.read_scalar(args[0])?.to_isize(this)?; + let flags = this.read_scalar(args[1])?.to_u32()?; + let size = this.read_scalar(args[2])?.to_usize(this)?; + let zero_init = (flags & 0x00000008) != 0; // HEAP_ZERO_MEMORY + let res = this.malloc(size, zero_init); + this.write_scalar(res, dest)?; + } + "HeapFree" => { + let _handle = this.read_scalar(args[0])?.to_isize(this)?; + let _flags = this.read_scalar(args[1])?.to_u32()?; + let ptr = this.read_scalar(args[2])?.not_undef()?; + this.free(ptr)?; + } + "HeapReAlloc" => { + let _handle = this.read_scalar(args[0])?.to_isize(this)?; + let _flags = this.read_scalar(args[1])?.to_u32()?; + let ptr = this.read_scalar(args[2])?.not_undef()?; + let size = this.read_scalar(args[3])?.to_usize(this)?; + let res = this.realloc(ptr, size)?; + this.write_scalar(res, dest)?; + } + "SetLastError" => { let err = this.read_scalar(args[0])?.to_u32()?; this.machine.last_error = err;