Skip to content

Commit f8214ac

Browse files
committed
arch specific stuff
1 parent a3aed40 commit f8214ac

File tree

4 files changed

+80
-18
lines changed

4 files changed

+80
-18
lines changed

src/bin/miri.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
193193
};
194194

195195
#[cfg(target_os = "linux")]
196-
if config.native_lib.is_some() {
196+
if config.native_lib.is_some() && !config.force_old_native_lib {
197197
// FIXME: This should display a diagnostic / warning on error
198198
// SAFETY: No other threads have spawned yet
199199
let _ = unsafe { miri::init_sv() };
@@ -708,6 +708,8 @@ fn main() {
708708
} else {
709709
show_error!("-Zmiri-native-lib `{}` does not exist", filename);
710710
}
711+
} else if arg == "-Zmiri-force-old-native-lib-mode" {
712+
miri_config.force_old_native_lib = true;
711713
} else if let Some(param) = arg.strip_prefix("-Zmiri-num-cpus=") {
712714
let num_cpus = param
713715
.parse::<u32>()

src/diagnostics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,7 +733,7 @@ impl<'tcx> MiriMachine<'tcx> {
733733
),
734734
#[cfg(target_os = "linux")]
735735
note!(
736-
"this is normally partially mitigated by making use of ptrace to monitor memory accesses, but it seems to be unavailable on your system"
736+
"this is normally partially mitigated, but either -Zmiri-force-old-native-lib-mode was passed or ptrace is disabled on your system"
737737
),
738738
]
739739
}

src/eval.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ pub struct MiriConfig {
151151
/// The location of a shared object file to load when calling external functions
152152
/// FIXME! consider allowing users to specify paths to multiple files, or to a directory
153153
pub native_lib: Option<PathBuf>,
154+
/// Whether to force using the old native lib behaviour even if ptrace might be supported.
155+
pub force_old_native_lib: bool,
154156
/// Run a garbage collector for BorTags every N basic blocks.
155157
pub gc_interval: u32,
156158
/// The number of CPUs to be reported by miri.
@@ -198,6 +200,7 @@ impl Default for MiriConfig {
198200
report_progress: None,
199201
retag_fields: RetagFields::Yes,
200202
native_lib: None,
203+
force_old_native_lib: false,
201204
gc_interval: 10_000,
202205
num_cpus: 1,
203206
page_size: None,

src/shims/trace/parent.rs

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,26 @@ use crate::helpers::ToU64;
88
use crate::shims::trace::{AccessEvent, FAKE_STACK_SIZE, MemEvents, StartFfiInfo, TraceRequest};
99

1010
/// The flags to use when calling `waitid()`.
11-
/// FIXME: bitwise OR for the `nix` versions of these types is not `const`, but
12-
/// it should be!
11+
/// Since bitwise or on the nix version of these flags is implemented as a trait,
12+
/// this cannot be const directly so we do it this way
1313
const WAIT_FLAGS: wait::WaitPidFlag =
1414
wait::WaitPidFlag::from_bits_truncate(libc::WUNTRACED | libc::WEXITED);
1515

1616
/// Arch-specific maximum size a single access might perform. x86 value is set
1717
/// assuming nothing bigger than AVX-512 is available.
18-
/// FIXME: For certain architectures (e.g. ARM) we may be able to tell apart
19-
/// SIMD from non-SIMD instructions, and thus put a much lower bound on the
20-
/// access size.
2118
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
2219
const ARCH_MAX_ACCESS_SIZE: u64 = 64;
2320
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
2421
const ARCH_MAX_ACCESS_SIZE: u64 = 16;
22+
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
23+
const ARCH_MAX_ACCESS_SIZE: u64 = 16;
24+
25+
/// The default word size on a given platform, in bytes. Only for targets where
26+
/// this is actually used.
27+
#[cfg(target_arch = "arm")]
28+
const ARCH_WORD_SIZE: u64 = 4;
29+
#[cfg(target_arch = "aarch64")]
30+
const ARCH_WORD_SIZE: u64 = 8;
2531

2632
/// The address of the page set to be edited, initialised to a sentinel null
2733
/// pointer.
@@ -37,7 +43,7 @@ static PAGE_COUNT: AtomicU64 = AtomicU64::new(1);
3743
/// consist of functions with a small number of register-sized integer arguments.
3844
/// See <https://man7.org/linux/man-pages/man2/syscall.2.html> for sources
3945
trait ArchIndependentRegs {
40-
/// The instruction pointer.
46+
/// Gets the address of the instruction pointer.
4147
fn ip(&self) -> usize;
4248
/// Set the instruction pointer; remember to also set the stack pointer, or
4349
/// else the stack might get messed up!
@@ -75,7 +81,14 @@ impl ArchIndependentRegs for libc::user_regs_struct {
7581
fn set_sp(&mut self, sp: usize) { self.sp = sp as _ }
7682
}
7783

78-
// TODO: add more architectures!
84+
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
85+
#[expect(clippy::as_conversions)]
86+
#[rustfmt::skip]
87+
impl ArchIndependentRegs for libc::user_regs_struct {
88+
fn ip(&self) -> usize { self.pc as _ }
89+
fn set_ip(&mut self, ip: usize) { self.pc = ip as _ }
90+
fn set_sp(&mut self, sp: usize) { self.sp = sp as _ }
91+
}
7992

8093
/// A unified event representing something happening on the child process. Wraps
8194
/// `nix`'s `WaitStatus` and our custom signals so it can all be done with one
@@ -432,8 +445,8 @@ fn handle_segfault(
432445
};
433446

434447
for op in arch_detail.operands() {
435-
// TODO: cfg() parts out?
436448
match op {
449+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
437450
arch::ArchOperand::X86Operand(x86_operand) => {
438451
match x86_operand.op_type {
439452
// We only care about memory accesses
@@ -463,18 +476,39 @@ fn handle_segfault(
463476
_ => (),
464477
}
465478
}
479+
#[cfg(target_arch = "aarch64")]
466480
arch::ArchOperand::Arm64Operand(arm64_operand) => {
467-
// Annoyingly, we don't get the size here, so just be pessimistic for now
481+
// Annoyingly, we don't always get the size here, so just be pessimistic for now
468482
match arm64_operand.op_type {
469483
arch::arm64::Arm64OperandType::Mem(_) => {
470-
let append = get_ranges(addr, ARCH_MAX_ACCESS_SIZE, page_size);
484+
// B = 1 byte, H = 2 bytes, S = 4 bytes, D = 8 bytes, Q = 16 bytes
485+
let size = match arm64_operand.vas {
486+
// Not an fp/simd instruction
487+
arch::arm64::Arm64Vas::ARM64_VAS_INVALID => ARCH_WORD_SIZE,
488+
// 1 byte
489+
arch::arm64::Arm64Vas::ARM64_VAS_1B => 1,
490+
// 2 bytes
491+
arch::arm64::Arm64Vas::ARM64_VAS_1H => 2,
492+
// 4 bytes
493+
arch::arm64::Arm64Vas::ARM64_VAS_4B
494+
| arch::arm64::Arm64Vas::ARM64_VAS_2H
495+
| arch::arm64::Arm64Vas::ARM64_VAS_1S => 4,
496+
// 8 bytes
497+
arch::arm64::Arm64Vas::ARM64_VAS_8B
498+
| arch::arm64::Arm64Vas::ARM64_VAS_4H
499+
| arch::arm64::Arm64Vas::ARM64_VAS_2S
500+
| arch::arm64::Arm64Vas::ARM64_VAS_1D => 8,
501+
// 16 bytes
502+
arch::arm64::Arm64Vas::ARM64_VAS_16B
503+
| arch::arm64::Arm64Vas::ARM64_VAS_8H
504+
| arch::arm64::Arm64Vas::ARM64_VAS_4S
505+
| arch::arm64::Arm64Vas::ARM64_VAS_2D
506+
| arch::arm64::Arm64Vas::ARM64_VAS_1Q => 16,
507+
};
508+
let append = get_ranges(addr, size, page_size);
471509
// FIXME: This now has access type info in the latest
472510
// git version of capstone because this pissed me off
473511
// and I added it. Change this when it updates
474-
475-
// Also FIXME: We do get some info on whether this
476-
// is a vector instruction, maybe we can limit the
477-
// max size based on that?
478512
acc_events.append(
479513
&mut append.clone().into_iter().map(AccessEvent::Read).collect(),
480514
);
@@ -485,10 +519,18 @@ fn handle_segfault(
485519
_ => (),
486520
}
487521
}
522+
#[cfg(target_arch = "arm")]
488523
arch::ArchOperand::ArmOperand(arm_operand) =>
489524
match arm_operand.op_type {
490525
arch::arm::ArmOperandType::Mem(_) => {
491-
let append = get_ranges(addr, ARCH_MAX_ACCESS_SIZE, page_size);
526+
// We don't get info on the size of the access, but
527+
// we're at least told if it's a vector inssizetruction
528+
let size = if arm_operand.vector_index.is_some() {
529+
ARCH_MAX_ACCESS_SIZE
530+
} else {
531+
ARCH_WORD_SIZE
532+
};
533+
let append = get_ranges(addr, size, page_size);
492534
let acc_ty = arm_operand.access.unwrap();
493535
if acc_ty.is_readable() {
494536
acc_events.append(
@@ -511,7 +553,22 @@ fn handle_segfault(
511553
}
512554
_ => (),
513555
},
514-
arch::ArchOperand::RiscVOperand(_risc_voperand) => todo!(),
556+
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
557+
arch::ArchOperand::RiscVOperand(risc_voperand) => {
558+
match risc_voperand {
559+
arch::riscv::RiscVOperand::Mem(_) => {
560+
// We get basically no info here
561+
let append = get_ranges(addr, ARCH_MAX_ACCESS_SIZE, page_size);
562+
acc_events.append(
563+
&mut append.clone().into_iter().map(AccessEvent::Read).collect(),
564+
);
565+
acc_events.append(
566+
&mut append.clone().into_iter().map(AccessEvent::Write).collect(),
567+
);
568+
}
569+
_ => (),
570+
}
571+
}
515572
_ => unimplemented!(),
516573
}
517574
}

0 commit comments

Comments
 (0)