Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

syscalls (mmap) for MIPS #21

Merged
merged 1 commit into from
Sep 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions omo/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ fn main() -> Result<(), EmulatorError> {

let mips_profile = MipsProfile::default();
let arch = MIPS::new(mips_profile.pointer_size());
let runner = LinuxRunner::new();
let runner = LinuxRunner::new(config.os.mmap_address);
let mut emu =
Emulator::<_, LinuxRunner>::new(config, arch, mips_profile.mode(), runner)?;

Expand All @@ -99,7 +99,7 @@ fn main() -> Result<(), EmulatorError> {

let mips_profile = MipsProfile::default();
let arch = MIPS::new(mips_profile.pointer_size());
let runner = LinuxRunner::new();
let runner = LinuxRunner::new(config.os.mmap_address);
let mut emu =
Emulator::<_, LinuxRunner>::new(config, arch, mips_profile.mode(), runner)?;

Expand Down
10 changes: 10 additions & 0 deletions omo/src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ pub trait Memory {
}
fn mem_map(&mut self, region: MemRegion, info: Option<String>) -> Result<(), uc_error>;
fn mem_unmap(&mut self, addr: u64, size: usize) -> Result<(), uc_error>;
fn is_mapped(&self, addr: u64, size: usize) -> Result<bool, uc_error>;
fn mprotect(&mut self, addr: u64, size: usize, perm: Permission) -> Result<(), uc_error>;
fn read(&self, addr: u64, size: usize) -> Result<Vec<u8>, uc_error>;
fn read_ptr(&self, address: u64, pointersize: Option<PointerSizeT>) -> Result<u64, uc_error>;

Expand Down Expand Up @@ -79,6 +81,14 @@ impl<'a, A> Memory for Unicorn<'a, Machine<A>> {
// TODO: manage map_info
Unicorn::mem_unmap(self, addr, size)
}
fn mprotect(&mut self, addr: u64, size: usize, perm: Permission) -> Result<(), uc_error> {
// TODO: manage map_info
Unicorn::mem_protect(self, addr, size, perm)
}
fn is_mapped(&self, _addr: u64, _size: usize) -> Result<bool, uc_error> {
// FIXME: impl it.
Ok(false)
}

fn read(&self, addr: u64, len: usize) -> Result<Vec<u8>, uc_error> {
self.mem_read_as_vec(addr, len)
Expand Down
214 changes: 197 additions & 17 deletions omo/src/os/linux/mod.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
use crate::{
arch::{ArchInfo, ArchT},
cc::CallingConvention,
engine::Engine,
};

use crate::{
errors::EmulatorError,
loader::LoadInfo,
memory::Memory,
os::{linux::syscall::SysCalls, Runner},
registers::{Registers, StackRegister},
utils::{align_up, Packer},
};
use std::{
cell::RefCell,
collections::HashMap,
io::{stderr, stdout, Write},
rc::Rc,
str::FromStr,
};

use crate::rand::{RAND_SOURCE, RAND_SOURCE_LEN};
use std::{rc::Rc, str::FromStr};
use unicorn_engine::{
unicorn_const::{uc_error, Arch, MemRegion, Permission},
RegisterARM, RegisterARM64, RegisterMIPS, RegisterRISCV, RegisterX86,
};

use crate::{
arch::{ArchInfo, ArchT},
cc::CallingConvention,
engine::Engine,
errors::EmulatorError,
loader::LoadInfo,
memory::Memory,
os::{linux::syscall::SysCalls, Runner},
rand::{RAND_SOURCE, RAND_SOURCE_LEN},
registers::{Registers, StackRegister},
utils::{align, align_up, Packer},
};

pub mod syscall;

#[derive(Debug, Default)]
Expand All @@ -35,13 +34,15 @@ pub struct LinuxRunner {
#[derive(Debug, Default)]
struct Inner {
sigaction_act: HashMap<u64, Vec<u64>>,
mmap_address: u64,
brk_address: u64,
}

impl LinuxRunner {
pub fn new() -> Self {
pub fn new(mmap_address: u64) -> Self {
let inner = Inner {
sigaction_act: HashMap::default(),
mmap_address,
brk_address: 0,
};
Self {
Expand Down Expand Up @@ -190,6 +191,40 @@ impl Inner {
let p1 = cc.get_raw_param(core, 0, None)?;
self.clock_gettime(core, p0, p1)?
}
SysCalls::MMAP2 => {
let p0 = cc.get_raw_param(core, 0, None)?;
let p1 = cc.get_raw_param(core, 1, None)?;
let p2 = cc.get_raw_param(core, 2, None)?;
let p3 = cc.get_raw_param(core, 3, None)?;
let p4 = cc.get_raw_param(core, 4, None)?;
let p5 = cc.get_raw_param(core, 5, None)?;
self.mmap2(core, p0, p1, p2, p3, p4, p5, 2)?
}
SysCalls::MREMAP => {
let p0 = cc.get_raw_param(core, 0, None)?;
let p1 = cc.get_raw_param(core, 1, None)?;
let p2 = cc.get_raw_param(core, 2, None)?;
let p3 = cc.get_raw_param(core, 3, None)?;
let p4 = cc.get_raw_param(core, 4, None)?;
self.mremap(core, p0, p1, p2, p3, p4)?
}
SysCalls::MUNMAP => {
let p0 = cc.get_raw_param(core, 0, None)?;
let p1 = cc.get_raw_param(core, 1, None)?;
self.munmap(core, p0, p1)?
}
SysCalls::MPROTECT => {
let p0 = cc.get_raw_param(core, 0, None)?;
let p1 = cc.get_raw_param(core, 1, None)?;
let p2 = cc.get_raw_param(core, 2, None)?;
self.mprotect(core, p0, p1, p2)?
}
SysCalls::MADVISE => {
let p0 = cc.get_raw_param(core, 0, None)?;
let p1 = cc.get_raw_param(core, 1, None)?;
let p2 = cc.get_raw_param(core, 2, None)?;
self.madivse(core, p0, p1, p2)?
}

_ => {
panic!("please handle syscall: {:?}", syscall);
Expand Down Expand Up @@ -506,6 +541,151 @@ impl Inner {
core.mem_write(tp, time.as_slice())?;
Ok(0)
}
fn mmap2<'a, A: ArchT>(
&mut self,
core: &mut Engine<'a, A>,
addr: u64,
length: u64,
prot: u64,
flags: u64,
fd: u64,
pgoffset: u64, // TODO no fd supports yet
_ver: u8,
) -> Result<i64, uc_error> {
log::debug!(
"[mmap2] {}, {}, {}, {}, {}, {}",
&addr,
&length,
&prot,
&flags,
&fd,
&pgoffset
);
const MAP_FAILED: i64 = -1;

const MAP_SHARED: u64 = 0x01;
const MAP_FIXED: u64 = 0x10;
const MAP_ANONYMOUS: u64 = 0x20;
let arch = core.get_arch();
// mask off perms bits that are not supported by unicorn
let perms = Permission::from_bits_truncate(prot as u32);

let page_size = core.pagesize();

let mut mmap_base = align(addr as u32, page_size as u32) as u64;
if flags & MAP_FIXED != 0 && mmap_base != addr {
return Ok(MAP_FAILED);
}

let mmap_size =
align_up((length - (addr & (page_size - 1))) as u32, page_size as u32) as u64;

let mut need_map = true;
if mmap_base != 0 {
// already mapped.
if Memory::is_mapped(core, mmap_base as u64, mmap_size as usize)? {
// if map fixed, we just protect mem
if flags & MAP_FIXED != 0 {
log::debug!("mmap2 - MAP_FIXED, mapping not needed");

Memory::mprotect(core, mmap_base as u64, mmap_size as usize, perms)?;
need_map = false;
} else {
// or else, we need to reallocate mem somewhere else.
mmap_base = 0;
}
}
}
if need_map {
if mmap_base == 0 {
mmap_base = self.mmap_address;
self.mmap_address = mmap_base + mmap_size;
}

log::debug!(
"[mmap2] mapping for [{},{})",
mmap_base,
mmap_size + mmap_size
);
Memory::mem_map(
core,
MemRegion {
begin: mmap_base as u64,
end: (mmap_base + mmap_size) as u64,
perms,
},
Some("[syscall_mmap2]".to_string()),
)?;

// FIXME: MIPS32 Big Endian
if arch == Arch::MIPS {
Memory::write(core, mmap_base as u64, vec![0u8; mmap_size as usize])?;
}
}
// TODO: should handle fd?
log::warn!("[mmap2] fd {} not handled", fd);
Ok(mmap_base as i64)
}
fn mremap<'a, A: ArchT>(
&mut self,
_core: &mut Engine<'a, A>,
old_addr: u64,
old_size: u64,
new_size: u64,
flags: u64,
new_addr: u64,
) -> Result<i64, uc_error> {
log::debug!(
"[mremap] {} {} {} {} {}",
old_addr,
old_size,
new_size,
flags,
new_addr
);
Ok(-1)
}
fn munmap<'a, A: ArchT>(
&mut self,
core: &mut Engine<'a, A>,
addr: u64,
length: u64,
) -> Result<i64, uc_error> {
log::debug!("[munmap] addr: {:#x}, length: {:#x}", addr, length);
let length = align_up(length as u32, core.pagesize() as u32);
Memory::mem_unmap(core, addr, length as usize)?;
Ok(0)
}
fn mprotect<'a, A: ArchT>(
&mut self,
core: &mut Engine<'a, A>,
addr: u64,
size: u64,
prot: u64,
) -> Result<i64, uc_error> {
let page_size = core.pagesize();
let mmap_base = align(addr as u32, page_size as u32) as u64;
let mmap_size = align_up((size - (addr & (page_size - 1))) as u32, page_size as u32) as u64;
let perms = Permission::from_bits_truncate(prot as u32);

log::debug!(
"[mprotect] addr: {:#x}, size: {:#x}, perms: {:#x}",
mmap_base,
mmap_size,
perms
);
Memory::mprotect(core, mmap_base, mmap_size as usize, perms)?;
Ok(0)
}
fn madivse<'a, A: ArchT>(
&mut self,
_core: &mut Engine<'a, A>,
_addr: u64,
_length: u64,
_advice: u64,
) -> Result<i64, uc_error> {
Ok(0)
}
}

const EBADF: u64 = 9;
Expand Down
5 changes: 5 additions & 0 deletions omo/src/os/linux/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ pub enum SysCalls {
GETTIMEOFDAY,
CLOCK_GETTIME,
EXIT,
MUNMAP,
MPROTECT,
MREMAP,
MMAP2,
MADVISE,
}

impl SysCalls {
Expand Down