1use std::{
2 collections::HashMap,
3 ops::{
4 BitAnd,
5 BitOrAssign,
6 Not,
7 ShlAssign,
8 },
9};
10
11use num_traits::NumCast;
12use rustc_hash::FxHashMap;
13use thiserror::Error;
14
15use crate::{
16 backends::clang::{
17 perms::*,
18 AOTExecutor,
19 AOTReturnCode,
20 AddressSpace,
21 EventChannel,
22 Heap,
23 HeapChunk,
24 HeapError,
25 Memory,
26 Registers,
27 Symbol,
28 },
29 frontend::VAddr,
30 kernel::linux::LinuxError,
31 riscv::register::{
32 CsrRegister,
33 FpRegister,
34 GpRegister,
35 },
36 runtime::{
37 Runtime,
38 SnapshotId,
39 },
40};
41
42#[allow(missing_docs)]
44#[derive(Error, Debug, Clone)]
45pub enum ClangRuntimeFault {
46 #[error("There was an error with the internal state of the code: {0}")]
47 InternalError(String),
48
49 #[error("Encountered an invalid pc address: {0:#x}")]
50 InvalidPc(VAddr),
51
52 #[error("The given snapshot id does not exist: {0}")]
53 InvalidSnapshotId(SnapshotId),
54
55 #[error("The application tried to read {0} values from the event channel but only {1} were present")]
56 InvalidEventChannel(usize, usize),
57
58 #[error("Reading {1} bytes at address {0:#x} failed")]
59 MemoryReadError(VAddr, usize),
60
61 #[error("Writing {1} bytes at address {0:#x} failed")]
62 MemoryWriteError(VAddr, usize),
63
64 #[error("Target attempted to divide by zero")]
65 DivisionByZero,
66
67 #[error("A memory management error occured: {0}")]
68 MemoryManagementError(String),
69
70 #[error("HeapError: {0}")]
71 HeapError(#[from] HeapError),
72
73 #[error("LinuxError: {0}")]
74 LinuxError(#[from] LinuxError),
75
76 #[error("Timeout")]
77 Timeout,
78
79 #[error("Execution cannot continue")]
80 End,
81
82 #[error("The application had an integer overflow with {0} and {1}")]
83 IntegerOverflow(u64, u64),
84}
85
86pub(crate) trait RiscvType: Sized + Copy {
87 const SIZE: usize;
88
89 #[inline]
90 fn from_slice(data: &[u8]) -> Self {
91 debug_assert_eq!(data.len(), Self::SIZE);
92 unsafe { *std::mem::transmute::<*const u8, *const Self>(data.as_ptr()) }
93 }
94}
95
96impl RiscvType for u64 {
97 const SIZE: usize = 8;
98}
99
100impl RiscvType for u32 {
101 const SIZE: usize = 4;
102}
103
104impl RiscvType for u16 {
105 const SIZE: usize = 2;
106}
107
108impl RiscvType for u8 {
109 const SIZE: usize = 1;
110}
111
112#[inline]
113pub(crate) fn broadcast_perm<T>(perm: u8) -> T
114where
115 T: RiscvType + Default + ShlAssign<i32> + BitOrAssign + NumCast + Copy,
116{
117 let mut ret = T::default();
118 let perms = T::from(perm).unwrap();
119
120 for _ in 0..T::SIZE {
121 ret <<= 8;
122 ret |= perms;
123 }
124
125 ret
126}
127
128fn load_riscv_type<T>(memory: &Memory, offset: usize) -> Option<T>
129where
130 T: RiscvType + Default + ShlAssign<i32> + BitOrAssign + NumCast + Copy + BitAnd,
131 <T as BitAnd>::Output: PartialEq<T>,
132{
133 if !memory.is_in_bounds(offset, T::SIZE) {
134 return None;
135 }
136
137 let perms = T::from_slice(memory.perms(offset, T::SIZE));
139 let uninit_mask = broadcast_perm::<T>(PERM_UNINIT);
140
141 if (perms & uninit_mask) != T::default() {
142 return None;
143 }
144
145 let read_mask = broadcast_perm::<T>(PERM_READ);
146
147 if (perms & read_mask) != read_mask {
148 return None;
149 }
150
151 let content = T::from_slice(memory.content(offset, T::SIZE));
153 Some(content)
154}
155
156#[inline]
157fn load_slice(memory: &Memory, offset: usize, size: usize) -> Option<&[u8]> {
158 if !memory.is_in_bounds(offset, size) {
159 return None;
160 }
161
162 for perm in memory.perms(offset, size) {
164 if (*perm & PERM_UNINIT) != 0 || (*perm & PERM_READ) != PERM_READ {
165 return None;
166 }
167 }
168
169 let content = memory.content(offset, size);
171 Some(content)
172}
173
174fn store_riscv_type<T>(memory: &mut Memory, offset: usize, value: T) -> bool
175where
176 T: RiscvType + Default + ShlAssign<i32> + BitOrAssign + NumCast + Copy + BitAnd<Output = T> + Not<Output = T>,
177 <T as BitAnd>::Output: PartialEq<T>,
178{
179 if !memory.is_in_bounds(offset, T::SIZE) {
180 return false;
181 }
182
183 let perms = T::from_slice(memory.perms(offset, T::SIZE));
185 let write_mask = broadcast_perm::<T>(PERM_WRITE);
186
187 if (perms & write_mask) != write_mask {
188 return false;
189 }
190
191 let uninit_mask = broadcast_perm::<T>(PERM_UNINIT);
192 let perms = perms & !uninit_mask;
193
194 unsafe {
195 *std::mem::transmute::<*mut u8, *mut T>(memory.perms_mut(offset, T::SIZE).as_mut_ptr()) = perms;
196 }
197
198 unsafe {
200 *std::mem::transmute::<*mut u8, *mut T>(memory.content_mut(offset, T::SIZE).as_mut_ptr()) = value;
201 }
202
203 true
204}
205
206#[inline]
207fn store_slice(memory: &mut Memory, offset: usize, value: &[u8]) -> bool {
208 let size = value.len();
209
210 if !memory.is_in_bounds(offset, size) {
211 return false;
212 }
213
214 for perm in memory.perms_mut(offset, size) {
216 if (*perm & PERM_WRITE) != PERM_WRITE {
217 return false;
218 }
219
220 *perm &= !PERM_UNINIT;
221 }
222
223 memory.content_mut(offset, size).copy_from_slice(value);
225
226 true
227}
228
229#[inline]
230fn load_perms(memory: &Memory, offset: usize, size: usize) -> Option<&[u8]> {
231 if !memory.is_in_bounds(offset, size) {
232 return None;
233 }
234
235 Some(memory.perms(offset, size))
236}
237
238#[inline]
239fn load_perms_mut(memory: &mut Memory, offset: usize, size: usize) -> Option<&mut [u8]> {
240 if !memory.is_in_bounds(offset, size) {
241 return None;
242 }
243
244 Some(memory.perms_mut(offset, size))
245}
246
247#[inline]
248fn load_string(memory: &Memory, offset: usize) -> Option<&[u8]> {
249 if !memory.is_in_bounds(offset, 1) {
250 return None;
251 }
252
253 for i in offset..memory.size() {
254 let perm = memory.perms(i, 1)[0];
255
256 if (perm & PERM_UNINIT) != 0 || (perm & PERM_READ) == 0 {
257 return None;
258 }
259
260 let byte = memory.content(i, 1)[0];
261
262 if byte == 0 {
263 let slice = memory.content(offset, i - offset);
264 return Some(slice);
265 }
266 }
267
268 None
269}
270
271#[inline]
272fn store_string(memory: &mut Memory, offset: usize, value: &[u8]) -> bool {
273 let len = value.len() + 1;
274
275 if !memory.is_in_bounds(offset, len) {
276 return false;
277 }
278
279 for perm in memory.perms_mut(offset, len) {
281 if (*perm & PERM_WRITE) != PERM_WRITE {
282 return false;
283 }
284
285 *perm &= !PERM_UNINIT;
286 }
287
288 let target = memory.content_mut(offset, len);
290 target[0..value.len()].copy_from_slice(value);
291 target[value.len()] = 0;
292
293 true
294}
295
296struct SnapshotData {
297 next_pc: VAddr,
298 next_event_channel_length: usize,
299 var_storage: Vec<u64>,
300}
301
302pub struct ClangRuntime {
304 memory: Memory,
305 event_channel: EventChannel,
306 registers: Registers,
307 executor: AOTExecutor,
308 next_pc: VAddr,
309 symbols: HashMap<String, Vec<Symbol>>,
310 next_event_channel_length: usize,
311 snapshots: FxHashMap<SnapshotId, SnapshotData>,
312 var_storage: Vec<u64>,
313 heap_mgr: Heap,
314}
315
316impl ClangRuntime {
317 #[allow(clippy::too_many_arguments)]
318 pub(crate) fn new(
319 memory: Memory,
320 event_channel: EventChannel,
321 registers: Registers,
322 executor: AOTExecutor,
323 next_pc: VAddr,
324 symbols: HashMap<String, Vec<Symbol>>,
325 var_storage: Vec<u64>,
326 ) -> Self {
327 Self {
328 heap_mgr: Heap::new(memory.heap(), memory.heap_end()),
329 memory,
330 event_channel,
331 registers,
332 executor,
333 next_pc,
334 symbols,
335 next_event_channel_length: 0,
336 snapshots: FxHashMap::default(),
337 var_storage,
338 }
339 }
340}
341
342impl Runtime for ClangRuntime {
343 type Error = ClangRuntimeFault;
344 type Event = usize;
345
346 fn set_pc(&mut self, pc: VAddr) {
347 self.registers.set_pc(pc);
348 self.next_pc = pc;
349 }
350
351 fn get_pc(&self) -> VAddr {
352 self.registers.get_pc()
353 }
354
355 fn set_gp_register(&mut self, register: GpRegister, value: u64) {
356 self.registers.set_gp(register as usize, value);
357 }
358
359 fn get_gp_register(&self, register: GpRegister) -> u64 {
360 self.registers.get_gp(register as usize)
361 }
362
363 fn set_fp_register(&mut self, register: FpRegister, value: f64) {
364 self.registers.set_fp(register as usize, value.to_bits());
365 }
366
367 fn get_fp_register(&self, register: FpRegister) -> f64 {
368 f64::from_bits(self.registers.get_fp(register as usize))
369 }
370
371 fn set_csr_register(&mut self, register: CsrRegister, value: u64) {
372 self.registers.set_csr(register, value);
373 }
374
375 fn get_csr_register(&self, register: CsrRegister) -> u64 {
376 self.registers.get_csr(register)
377 }
378
379 fn run(&mut self) -> Result<Self::Event, Self::Error> {
380 self.event_channel.set_length(self.next_event_channel_length);
382 self.registers.set_pc(self.next_pc);
383 self.registers.set_last_instr(0);
384
385 self.next_pc =
387 self.executor.run(&mut self.memory, &mut self.event_channel, &mut self.registers, &mut self.var_storage);
388 self.next_event_channel_length = 0;
389
390 match self.executor.return_code() {
392 AOTReturnCode::Event => {
393 let id = self.executor.return_arg0();
394 Ok(id)
395 },
396 AOTReturnCode::InvalidState => {
397 Err(ClangRuntimeFault::InternalError("AOT code returned but did not set an event or fault".to_string()))
398 },
399 AOTReturnCode::InvalidJumpTarget => {
400 let addr = self.executor.return_arg0() as VAddr;
401 Err(ClangRuntimeFault::InvalidPc(addr))
402 },
403 AOTReturnCode::UninitializedRead | AOTReturnCode::InvalidRead => {
404 let addr = self.executor.return_arg0() as VAddr;
405 let size = self.executor.return_arg1();
406 Err(ClangRuntimeFault::MemoryReadError(addr, size))
407 },
408 AOTReturnCode::End => Err(ClangRuntimeFault::End),
409 AOTReturnCode::InvalidWrite => {
410 let addr = self.executor.return_arg0() as VAddr;
411 let size = self.executor.return_arg1();
412 Err(ClangRuntimeFault::MemoryWriteError(addr, size))
413 },
414 AOTReturnCode::InvalidEventChannel => {
415 let req_size = self.executor.return_arg0();
416 let act_size = self.executor.return_arg1();
417 Err(ClangRuntimeFault::InvalidEventChannel(req_size, act_size))
418 },
419 AOTReturnCode::DivByZero => Err(ClangRuntimeFault::DivisionByZero),
420 AOTReturnCode::Timeout => Err(ClangRuntimeFault::Timeout),
421 AOTReturnCode::IntegerOverflow => {
422 let a = self.executor.return_arg0();
423 let b = self.executor.return_arg1();
424 Err(ClangRuntimeFault::IntegerOverflow(a as u64, b as u64))
425 },
426 }
427 }
428
429 fn take_snapshot(&mut self, id: SnapshotId) {
430 self.snapshots.insert(
431 id,
432 SnapshotData {
433 next_pc: self.next_pc,
434 next_event_channel_length: self.next_event_channel_length,
435 var_storage: self.var_storage.clone(),
436 },
437 );
438 self.memory.take_snapshot(id);
439 self.event_channel.take_snapshot(id);
440 self.registers.take_snapshot(id);
441 self.heap_mgr.take_snapshot(id);
442 }
443
444 fn restore_snapshot(&mut self, id: SnapshotId) -> Result<(), Self::Error> {
445 if let Some(snapshot) = self.snapshots.get(&id) {
446 self.next_pc = snapshot.next_pc;
447 self.next_event_channel_length = snapshot.next_event_channel_length;
448 unsafe {
449 std::ptr::copy_nonoverlapping(
450 snapshot.var_storage.as_ptr(),
451 self.var_storage.as_mut_ptr(),
452 snapshot.var_storage.len(),
453 )
454 };
455 } else {
456 return Err(ClangRuntimeFault::InvalidSnapshotId(id));
457 }
458 self.memory.restore_snapshot_unchecked(id);
459 self.event_channel.restore_snapshot_unchecked(id);
460 self.registers.restore_snapshot_unchecked(id);
461 self.heap_mgr.restore_snapshot_unchecked(id);
462 Ok(())
463 }
464
465 fn delete_snapshot(&mut self, id: SnapshotId) -> Result<(), Self::Error> {
466 if self.snapshots.remove(&id).is_none() {
467 return Err(ClangRuntimeFault::InvalidSnapshotId(id));
468 }
469 self.memory.delete_snapshot_unchecked(id);
470 self.event_channel.delete_snapshot_unchecked(id);
471 self.registers.delete_snapshot_unchecked(id);
472 self.heap_mgr.delete_snapshot_unchecked(id);
473 Ok(())
474 }
475
476 fn has_snapshot(&self, id: SnapshotId) -> bool {
477 self.snapshots.contains_key(&id)
478 }
479
480 fn event_channel(&self) -> &[u64] {
481 let length = self.event_channel.length();
482 self.event_channel.get(length).unwrap()
483 }
484
485 fn event_channel_mut(&mut self, size: usize) -> Result<&mut [u64], Self::Error> {
486 let cap = self.event_channel.capacity();
488
489 if let Some(data) = self.event_channel.get_mut(size) {
490 self.next_event_channel_length = std::cmp::max(self.next_event_channel_length, size);
491 Ok(data)
492 } else {
493 Err(ClangRuntimeFault::InvalidEventChannel(size, cap))
494 }
495 }
496
497 fn load_dword(&self, address: VAddr) -> Result<u64, Self::Error> {
498 let result = match AddressSpace::decode(address) {
499 AddressSpace::Code(_) => None,
500 AddressSpace::Data(offset) => load_riscv_type(&self.memory, offset),
501 };
502 result.ok_or(ClangRuntimeFault::MemoryReadError(address, 8))
503 }
504
505 fn load_word(&self, address: VAddr) -> Result<u32, Self::Error> {
506 let result = match AddressSpace::decode(address) {
507 AddressSpace::Code(_) => None,
508 AddressSpace::Data(offset) => load_riscv_type(&self.memory, offset),
509 };
510 result.ok_or(ClangRuntimeFault::MemoryReadError(address, 4))
511 }
512
513 fn load_hword(&self, address: VAddr) -> Result<u16, Self::Error> {
514 let result = match AddressSpace::decode(address) {
515 AddressSpace::Code(_) => None,
516 AddressSpace::Data(offset) => load_riscv_type(&self.memory, offset),
517 };
518 result.ok_or(ClangRuntimeFault::MemoryReadError(address, 2))
519 }
520
521 fn load_byte(&self, address: VAddr) -> Result<u8, Self::Error> {
522 let result = match AddressSpace::decode(address) {
523 AddressSpace::Code(_) => None,
524 AddressSpace::Data(offset) => load_riscv_type(&self.memory, offset),
525 };
526 result.ok_or(ClangRuntimeFault::MemoryReadError(address, 1))
527 }
528
529 fn load_slice(&self, address: VAddr, size: usize) -> Result<&[u8], Self::Error> {
530 let result = match AddressSpace::decode(address) {
531 AddressSpace::Code(_) => None,
532 AddressSpace::Data(offset) => load_slice(&self.memory, offset, size),
533 };
534 result.ok_or(ClangRuntimeFault::MemoryReadError(address, size))
535 }
536
537 fn store_dword(&mut self, address: VAddr, value: u64) -> Result<(), Self::Error> {
538 let result = match AddressSpace::decode(address) {
539 AddressSpace::Code(_) => false,
540 AddressSpace::Data(offset) => store_riscv_type(&mut self.memory, offset, value),
541 };
542 if result {
543 Ok(())
544 } else {
545 Err(ClangRuntimeFault::MemoryWriteError(address, 8))
546 }
547 }
548 fn store_word(&mut self, address: VAddr, value: u32) -> Result<(), Self::Error> {
549 let result = match AddressSpace::decode(address) {
550 AddressSpace::Code(_) => false,
551 AddressSpace::Data(offset) => store_riscv_type(&mut self.memory, offset, value),
552 };
553 if result {
554 Ok(())
555 } else {
556 Err(ClangRuntimeFault::MemoryWriteError(address, 4))
557 }
558 }
559 fn store_hword(&mut self, address: VAddr, value: u16) -> Result<(), Self::Error> {
560 let result = match AddressSpace::decode(address) {
561 AddressSpace::Code(_) => false,
562 AddressSpace::Data(offset) => store_riscv_type(&mut self.memory, offset, value),
563 };
564 if result {
565 Ok(())
566 } else {
567 Err(ClangRuntimeFault::MemoryWriteError(address, 2))
568 }
569 }
570 fn store_byte(&mut self, address: VAddr, value: u8) -> Result<(), Self::Error> {
571 let result = match AddressSpace::decode(address) {
572 AddressSpace::Code(_) => false,
573 AddressSpace::Data(offset) => store_riscv_type(&mut self.memory, offset, value),
574 };
575 if result {
576 Ok(())
577 } else {
578 Err(ClangRuntimeFault::MemoryWriteError(address, 1))
579 }
580 }
581
582 fn store_slice<S: AsRef<[u8]>>(&mut self, address: VAddr, value: S) -> Result<(), Self::Error> {
583 let value = value.as_ref();
584 let result = match AddressSpace::decode(address) {
585 AddressSpace::Code(_) => false,
586 AddressSpace::Data(offset) => store_slice(&mut self.memory, offset, value),
587 };
588 if result {
589 Ok(())
590 } else {
591 Err(ClangRuntimeFault::MemoryWriteError(address, value.len()))
592 }
593 }
594
595 fn load_string(&self, address: VAddr) -> Result<&[u8], Self::Error> {
596 let result = match AddressSpace::decode(address) {
597 AddressSpace::Code(_) => None,
598 AddressSpace::Data(offset) => load_string(&self.memory, offset),
599 };
600 result.ok_or(ClangRuntimeFault::MemoryReadError(address, 0))
601 }
602
603 fn store_string<S: AsRef<str>>(&mut self, address: VAddr, value: S) -> Result<(), Self::Error> {
604 let value = value.as_ref().as_bytes();
605 let result = match AddressSpace::decode(address) {
606 AddressSpace::Code(_) => false,
607 AddressSpace::Data(offset) => store_string(&mut self.memory, offset, value),
608 };
609 if result {
610 Ok(())
611 } else {
612 Err(ClangRuntimeFault::MemoryWriteError(address, value.len()))
613 }
614 }
615}
616
617impl ClangRuntime {
619 pub fn raw_return_code(&self) -> AOTReturnCode {
621 self.executor.return_code()
622 }
623
624 pub fn permissions(&self, address: VAddr, size: usize) -> Result<&[u8], ClangRuntimeFault> {
626 let result = match AddressSpace::decode(address) {
627 AddressSpace::Code(_) => None,
628 AddressSpace::Data(offset) => load_perms(&self.memory, offset, size),
629 };
630 result.ok_or(ClangRuntimeFault::MemoryReadError(address, size))
631 }
632
633 pub fn permissions_mut(&mut self, address: VAddr, size: usize) -> Result<&mut [u8], ClangRuntimeFault> {
635 let result = match AddressSpace::decode(address) {
636 AddressSpace::Code(_) => None,
637 AddressSpace::Data(offset) => load_perms_mut(&mut self.memory, offset, size),
638 };
639 result.ok_or(ClangRuntimeFault::MemoryWriteError(address, size))
640 }
641
642 pub fn get_last_instruction(&self) -> VAddr {
646 self.registers.get_last_instr()
647 }
648
649 #[allow(clippy::missing_safety_doc)]
651 pub unsafe fn raw_pointer(&self, address: VAddr) -> Result<*const u8, ClangRuntimeFault> {
652 match AddressSpace::decode(address) {
653 AddressSpace::Code(_) => Err(ClangRuntimeFault::MemoryReadError(address, 0)),
654 AddressSpace::Data(offset) => {
655 if !self.memory.is_in_bounds(offset, 1) {
656 return Err(ClangRuntimeFault::MemoryReadError(address, 0));
657 }
658
659 Ok(self.memory.content(offset, 1).as_ptr())
660 },
661 }
662 }
663
664 #[allow(clippy::missing_safety_doc)]
666 pub unsafe fn raw_pointer_mut(&mut self, address: VAddr) -> Result<*mut u8, ClangRuntimeFault> {
667 match AddressSpace::decode(address) {
668 AddressSpace::Code(_) => Err(ClangRuntimeFault::MemoryReadError(address, 0)),
669 AddressSpace::Data(offset) => {
670 if !self.memory.is_in_bounds(offset, 1) {
671 return Err(ClangRuntimeFault::MemoryReadError(address, 0));
672 }
673
674 Ok(self.memory.content_mut(offset, 1).as_mut_ptr())
675 },
676 }
677 }
678
679 pub fn get_executed_instructions(&self) -> usize {
682 self.executor.executed_instructions()
683 }
684}
685
686impl ClangRuntime {
688 pub fn lookup_symbol_from_address(&self, addr: VAddr) -> Vec<(&str, &Symbol)> {
690 let mut ret = Vec::new();
691
692 for (file, symbols) in &self.symbols {
693 for symbol in symbols {
694 if symbol.contains_address(addr) {
695 ret.push((file.as_str(), symbol));
696 }
697 }
698 }
699
700 ret
701 }
702
703 pub fn lookup_symbol_from_private_name<S: AsRef<str>>(&self, name: S) -> Vec<(&str, &Symbol)> {
705 let name = name.as_ref();
706 let mut ret = Vec::new();
707
708 for (file, symbols) in &self.symbols {
709 for symbol in symbols {
710 if symbol.is_private() && symbol.name() == name {
711 ret.push((file.as_str(), symbol));
712 }
713 }
714 }
715
716 ret
717 }
718
719 pub fn lookup_symbol_from_public_name<S: AsRef<str>>(&self, name: S) -> Vec<(&str, &Symbol)> {
721 let name = name.as_ref();
722 let mut ret = Vec::new();
723
724 for (file, symbols) in &self.symbols {
725 for symbol in symbols {
726 if symbol.is_public() && symbol.name() == name {
727 ret.push((file.as_str(), symbol));
728 }
729 }
730 }
731
732 ret
733 }
734}
735
736impl ClangRuntime {
738 pub fn dynstore_allocate(&mut self, size: usize) -> Result<VAddr, ClangRuntimeFault> {
740 let offset = self.heap_mgr.malloc(&mut self.memory, size)?;
741 Ok(AddressSpace::Data(offset).encode())
742 }
743
744 pub fn dynstore_deallocate(&mut self, addr: VAddr) -> Result<(), ClangRuntimeFault> {
746 if addr == 0 {
747 return Ok(());
748 }
749
750 let offset = if let AddressSpace::Data(offset) = AddressSpace::decode(addr) {
751 offset
752 } else {
753 return Err(ClangRuntimeFault::MemoryManagementError(format!(
754 "Tried to deallocate a non-heap address: {:#x}",
755 addr
756 )));
757 };
758
759 self.heap_mgr.free(&mut self.memory, offset)?;
760
761 Ok(())
762 }
763
764 pub fn dynstore_get_all_chunks(&self) -> Vec<HeapChunk> {
766 self.heap_mgr.get_heap_chunks(&self.memory)
767 }
768
769 pub fn dynstore_get_single_chunk(&self, addr: VAddr) -> Result<HeapChunk, ClangRuntimeFault> {
771 let offset = if let AddressSpace::Data(offset) = AddressSpace::decode(addr) {
772 offset
773 } else {
774 return Err(ClangRuntimeFault::MemoryManagementError(format!(
775 "Tried to get a single chunk with a non-heap address: {:#x}",
776 addr
777 )));
778 };
779
780 let chunk = self.heap_mgr.get_heap_chunk(&self.memory, offset)?;
781
782 Ok(chunk)
783 }
784
785 pub fn dynstore_number_of_chunks(&self) -> usize {
787 self.heap_mgr.allocated_chunks()
788 }
789
790 pub fn dynstore_reallocate(&mut self, addr: VAddr, new_size: usize) -> Result<VAddr, ClangRuntimeFault> {
792 if addr == 0 || new_size == 0 {
793 return Err(ClangRuntimeFault::MemoryManagementError(
794 "Called dynstore_reallocate() with invalid parameters".to_string(),
795 ));
796 }
797
798 let offset = if let AddressSpace::Data(offset) = AddressSpace::decode(addr) {
799 offset
800 } else {
801 return Err(ClangRuntimeFault::MemoryManagementError(format!(
802 "Tried to reallocate a non-heap address: {:#x}",
803 addr
804 )));
805 };
806
807 let new_offset = self.heap_mgr.realloc(&mut self.memory, offset, new_size)?;
808 Ok(AddressSpace::Data(new_offset).encode())
809 }
810
811 pub fn dynstore_memory_usage(&self) -> usize {
813 self.heap_mgr.memory_usage(&self.memory)
814 }
815}