|
1 | 1 | use std::collections::hash_map::Entry;
|
2 | 2 | use std::io::Write;
|
| 3 | +use std::iter; |
3 | 4 | use std::path::Path;
|
4 | 5 |
|
5 | 6 | use rustc_abi::{Align, AlignFromBytesError, Size};
|
@@ -501,33 +502,124 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
501 | 502 | }
|
502 | 503 |
|
503 | 504 | // Rust allocation
|
504 |
| - "miri_alloc" => { |
505 |
| - let [size, align] = this.check_shim(abi, Conv::Rust, link_name, args)?; |
506 |
| - let size = this.read_target_usize(size)?; |
507 |
| - let align = this.read_target_usize(align)?; |
| 505 | + "__rust_alloc" | "miri_alloc" => { |
| 506 | + let default = |ecx: &mut MiriInterpCx<'tcx>| { |
| 507 | + // Only call `check_shim` when `#[global_allocator]` isn't used. When that |
| 508 | + // macro is used, we act like no shim exists, so that the exported function can run. |
| 509 | + let [size, align] = ecx.check_shim(abi, Conv::Rust, link_name, args)?; |
| 510 | + let size = ecx.read_target_usize(size)?; |
| 511 | + let align = ecx.read_target_usize(align)?; |
| 512 | + |
| 513 | + ecx.check_rustc_alloc_request(size, align)?; |
| 514 | + |
| 515 | + let memory_kind = match link_name.as_str() { |
| 516 | + "__rust_alloc" => MiriMemoryKind::Rust, |
| 517 | + "miri_alloc" => MiriMemoryKind::Miri, |
| 518 | + _ => unreachable!(), |
| 519 | + }; |
508 | 520 |
|
509 |
| - this.check_rustc_alloc_request(size, align)?; |
| 521 | + let ptr = ecx.allocate_ptr( |
| 522 | + Size::from_bytes(size), |
| 523 | + Align::from_bytes(align).unwrap(), |
| 524 | + memory_kind.into(), |
| 525 | + )?; |
510 | 526 |
|
511 |
| - let ptr = this.allocate_ptr( |
512 |
| - Size::from_bytes(size), |
513 |
| - Align::from_bytes(align).unwrap(), |
514 |
| - MiriMemoryKind::Miri.into(), |
515 |
| - )?; |
| 527 | + ecx.write_pointer(ptr, dest) |
| 528 | + }; |
516 | 529 |
|
517 |
| - this.write_pointer(ptr, dest)?; |
| 530 | + match link_name.as_str() { |
| 531 | + "__rust_alloc" => return this.emulate_allocator(default), |
| 532 | + "miri_alloc" => { |
| 533 | + default(this)?; |
| 534 | + return interp_ok(EmulateItemResult::NeedsReturn); |
| 535 | + } |
| 536 | + _ => unreachable!(), |
| 537 | + } |
518 | 538 | }
|
519 |
| - "miri_dealloc" => { |
520 |
| - let [ptr, old_size, align] = this.check_shim(abi, Conv::Rust, link_name, args)?; |
521 |
| - let ptr = this.read_pointer(ptr)?; |
522 |
| - let old_size = this.read_target_usize(old_size)?; |
523 |
| - let align = this.read_target_usize(align)?; |
| 539 | + "__rust_alloc_zeroed" => { |
| 540 | + return this.emulate_allocator(|this| { |
| 541 | + // See the comment for `__rust_alloc` why `check_shim` is only called in the |
| 542 | + // default case. |
| 543 | + let [size, align] = this.check_shim(abi, Conv::Rust, link_name, args)?; |
| 544 | + let size = this.read_target_usize(size)?; |
| 545 | + let align = this.read_target_usize(align)?; |
524 | 546 |
|
525 |
| - // No need to check old_size/align; we anyway check that they match the allocation. |
526 |
| - this.deallocate_ptr( |
527 |
| - ptr, |
528 |
| - Some((Size::from_bytes(old_size), Align::from_bytes(align).unwrap())), |
529 |
| - MiriMemoryKind::Miri.into(), |
530 |
| - )?; |
| 547 | + this.check_rustc_alloc_request(size, align)?; |
| 548 | + |
| 549 | + let ptr = this.allocate_ptr( |
| 550 | + Size::from_bytes(size), |
| 551 | + Align::from_bytes(align).unwrap(), |
| 552 | + MiriMemoryKind::Rust.into(), |
| 553 | + )?; |
| 554 | + |
| 555 | + // We just allocated this, the access is definitely in-bounds. |
| 556 | + this.write_bytes_ptr( |
| 557 | + ptr.into(), |
| 558 | + iter::repeat(0u8).take(usize::try_from(size).unwrap()), |
| 559 | + ) |
| 560 | + .unwrap(); |
| 561 | + this.write_pointer(ptr, dest) |
| 562 | + }); |
| 563 | + } |
| 564 | + "__rust_dealloc" | "miri_dealloc" => { |
| 565 | + let default = |ecx: &mut MiriInterpCx<'tcx>| { |
| 566 | + // See the comment for `__rust_alloc` why `check_shim` is only called in the |
| 567 | + // default case. |
| 568 | + let [ptr, old_size, align] = |
| 569 | + ecx.check_shim(abi, Conv::Rust, link_name, args)?; |
| 570 | + let ptr = ecx.read_pointer(ptr)?; |
| 571 | + let old_size = ecx.read_target_usize(old_size)?; |
| 572 | + let align = ecx.read_target_usize(align)?; |
| 573 | + |
| 574 | + let memory_kind = match link_name.as_str() { |
| 575 | + "__rust_dealloc" => MiriMemoryKind::Rust, |
| 576 | + "miri_dealloc" => MiriMemoryKind::Miri, |
| 577 | + _ => unreachable!(), |
| 578 | + }; |
| 579 | + |
| 580 | + // No need to check old_size/align; we anyway check that they match the allocation. |
| 581 | + ecx.deallocate_ptr( |
| 582 | + ptr, |
| 583 | + Some((Size::from_bytes(old_size), Align::from_bytes(align).unwrap())), |
| 584 | + memory_kind.into(), |
| 585 | + ) |
| 586 | + }; |
| 587 | + |
| 588 | + match link_name.as_str() { |
| 589 | + "__rust_dealloc" => { |
| 590 | + return this.emulate_allocator(default); |
| 591 | + } |
| 592 | + "miri_dealloc" => { |
| 593 | + default(this)?; |
| 594 | + return interp_ok(EmulateItemResult::NeedsReturn); |
| 595 | + } |
| 596 | + _ => unreachable!(), |
| 597 | + } |
| 598 | + } |
| 599 | + "__rust_realloc" => { |
| 600 | + return this.emulate_allocator(|this| { |
| 601 | + // See the comment for `__rust_alloc` why `check_shim` is only called in the |
| 602 | + // default case. |
| 603 | + let [ptr, old_size, align, new_size] = |
| 604 | + this.check_shim(abi, Conv::Rust, link_name, args)?; |
| 605 | + let ptr = this.read_pointer(ptr)?; |
| 606 | + let old_size = this.read_target_usize(old_size)?; |
| 607 | + let align = this.read_target_usize(align)?; |
| 608 | + let new_size = this.read_target_usize(new_size)?; |
| 609 | + // No need to check old_size; we anyway check that they match the allocation. |
| 610 | + |
| 611 | + this.check_rustc_alloc_request(new_size, align)?; |
| 612 | + |
| 613 | + let align = Align::from_bytes(align).unwrap(); |
| 614 | + let new_ptr = this.reallocate_ptr( |
| 615 | + ptr, |
| 616 | + Some((Size::from_bytes(old_size), align)), |
| 617 | + Size::from_bytes(new_size), |
| 618 | + align, |
| 619 | + MiriMemoryKind::Rust.into(), |
| 620 | + )?; |
| 621 | + this.write_pointer(new_ptr, dest) |
| 622 | + }); |
531 | 623 | }
|
532 | 624 |
|
533 | 625 | // C memory handling functions
|
|
0 commit comments