1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
//! This module provides methods to retrieve allocation information, such as static variables.
use std::io::Read;
use serde::Serialize;
use crate::mir::mono::{Instance, StaticDef};
use crate::target::{Endian, MachineInfo};
use crate::ty::{Allocation, Binder, ExistentialTraitRef, IndexedVal, Ty};
use crate::{with, Error};
/// An allocation in the SMIR global memory can be either a function pointer,
/// a static, or a "real" allocation with some data in it.
#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
pub enum GlobalAlloc {
/// The alloc ID is used as a function pointer.
Function(Instance),
/// This alloc ID points to a symbolic (not-reified) vtable.
/// The `None` trait ref is used to represent auto traits.
VTable(Ty, Option<Binder<ExistentialTraitRef>>),
/// The alloc ID points to a "lazy" static variable that did not get computed (yet).
/// This is also used to break the cycle in recursive statics.
Static(StaticDef),
/// The alloc ID points to memory.
Memory(Allocation),
}
impl From<AllocId> for GlobalAlloc {
fn from(value: AllocId) -> Self {
with(|cx| cx.global_alloc(value))
}
}
impl GlobalAlloc {
/// Retrieve the allocation id for a global allocation if it exists.
///
/// For `[GlobalAlloc::VTable]`, this will return the allocation for the VTable of the given
/// type for the optional trait if the type implements the trait.
///
/// This method will always return `None` for allocations other than `[GlobalAlloc::VTable]`.
pub fn vtable_allocation(&self) -> Option<AllocId> {
with(|cx| cx.vtable_allocation(self))
}
}
/// A unique identification number for each provenance
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)]
pub struct AllocId(usize);
impl IndexedVal for AllocId {
fn to_val(index: usize) -> Self {
AllocId(index)
}
fn to_index(&self) -> usize {
self.0
}
}
/// Utility function used to read an allocation data into a unassigned integer.
pub(crate) fn read_target_uint(mut bytes: &[u8]) -> Result<u128, Error> {
let mut buf = [0u8; std::mem::size_of::<u128>()];
match MachineInfo::target_endianness() {
Endian::Little => {
bytes.read_exact(&mut buf[..bytes.len()])?;
Ok(u128::from_le_bytes(buf))
}
Endian::Big => {
bytes.read_exact(&mut buf[16 - bytes.len()..])?;
Ok(u128::from_be_bytes(buf))
}
}
}
/// Utility function used to read an allocation data into an assigned integer.
pub(crate) fn read_target_int(mut bytes: &[u8]) -> Result<i128, Error> {
let mut buf = [0u8; std::mem::size_of::<i128>()];
match MachineInfo::target_endianness() {
Endian::Little => {
bytes.read_exact(&mut buf[..bytes.len()])?;
Ok(i128::from_le_bytes(buf))
}
Endian::Big => {
bytes.read_exact(&mut buf[16 - bytes.len()..])?;
Ok(i128::from_be_bytes(buf))
}
}
}