Skip to content

Commit e1264c9

Browse files
committed
Updating permission for mem64
Finish the I-cache
1 parent 37b7a5b commit e1264c9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+833
-155
lines changed

crates/libmwemu/src/console.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use crate::winapi::winapi64;
1414
use std::process::{Command, Stdio};
1515
use std::fs;
1616
use std::io;
17+
use crate::maps::mem64::Permission;
1718

1819
pub struct Console {}
1920

@@ -520,7 +521,7 @@ impl Console {
520521
}
521522
};
522523
emu.maps
523-
.create_map(&name, addr, sz)
524+
.create_map(&name, addr, sz, Permission::READ_WRITE_EXECUTE)
524525
.expect("cannot create map from console mc");
525526
log::info!("allocated {} at 0x{:x} sz: {}", name, addr, sz);
526527
}
@@ -546,7 +547,7 @@ impl Console {
546547
};
547548

548549
emu.maps
549-
.create_map(&name, addr, sz)
550+
.create_map(&name, addr, sz, Permission::READ_WRITE_EXECUTE)
550551
.expect("cannot create map from console mca");
551552
log::info!("allocated {} at 0x{:x} sz: {}", name, addr, sz);
552553
}

crates/libmwemu/src/elf/elf32.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::constants;
22
use crate::err::MwemuError;
3-
use crate::maps::mem64::Mem64;
3+
use crate::maps::mem64::{Mem64, Permission};
44
use crate::maps::Maps;
55
use std::fs::File;
66
use std::io::Read;
@@ -87,12 +87,13 @@ impl Elf32 {
8787
8888
}
8989
}*/
90-
90+
9191
let mem = maps
9292
.create_map(
9393
&"code".to_string(),
9494
phdr.p_vaddr.into(),
9595
phdr.p_memsz.into(),
96+
Permission::from_bits(phdr.p_type as u8)
9697
)
9798
.expect("cannot create code map from load_programs elf32");
9899
if phdr.p_filesz > phdr.p_memsz {

crates/libmwemu/src/elf/elf64.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::constants;
22
use crate::err::MwemuError;
3-
use crate::maps::mem64::Mem64;
3+
use crate::maps::mem64::{Mem64, Permission};
44
use crate::maps::Maps;
55
use std::fs::File;
66
use std::io::Read;
@@ -259,7 +259,7 @@ impl Elf64 {
259259

260260
// elf executable need to map the header.
261261
let hdr = maps
262-
.create_map("elf64.hdr", elf64_base, 512)
262+
.create_map("elf64.hdr", elf64_base, 512, Permission::READ_WRITE)
263263
.expect("cannot create elf64.hdr map");
264264
hdr.write_bytes(elf64_base, &self.bin[..512]);
265265
}
@@ -278,6 +278,7 @@ impl Elf64 {
278278
let sh_offset = self.elf_shdr[i].sh_offset;
279279
let sh_size = self.elf_shdr[i].sh_size;
280280
let mut sh_addr = self.elf_shdr[i].sh_addr;
281+
let permission = Permission::from_bits(self.elf_shdr[i].sh_type as u8);
281282

282283
//TODO: align sh_size to page size by extending the size, something like:
283284
//sh_size = ((sh_size + constants::ELF_PAGE_SIZE - 1) / constants::ELF_PAGE_SIZE) * constants::ELF_PAGE_SIZE;
@@ -347,12 +348,12 @@ impl Elf64 {
347348
if sh_addr < elf64_base {
348349
sh_addr += elf64_base;
349350
}
350-
mem = match maps.create_map(&map_name, sh_addr, sh_size) {
351+
mem = match maps.create_map(&map_name, sh_addr, sh_size, permission) {
351352
Ok(m) => m,
352353
Err(_) => {
353354
println!("elf64 {} overlappss 0x{:x} {}", map_name, sh_addr, sh_size);
354355
sh_addr = maps.alloc(sh_size+10).expect("cannot allocate");
355-
maps.create_map(&map_name, sh_addr, sh_size).expect("cannot create map")
356+
maps.create_map(&map_name, sh_addr, sh_size, permission).expect("cannot create map")
356357
}
357358
};
358359

crates/libmwemu/src/emu/disassemble.rs

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
use crate::emu::Emu;
12
use iced_x86::{Decoder, DecoderOptions, Formatter as _, Instruction};
23
use serde::{Deserialize, Serialize};
3-
use crate::emu::Emu;
44

55
// about 10 mb should be on l3 cache
66
// 8192 cache lines,
@@ -12,7 +12,11 @@ const INSTRUCTION_ARRAY_SIZE: usize = 8192 * 32;
1212
const CACHE_SIZE: usize = 2048 * 16;
1313
const CACHE_MASK: usize = CACHE_SIZE - 1; // Assumes power of 2
1414
const MAX_CACHE_PER_LINE: usize = 16;
15+
16+
// we need INVALID_KEY and INVALID_LEN to be the same as INVALID_LPF_ADDR to optimize for memset
1517
pub const INVALID_LPF_ADDR: u64 = 0xffffffffffffffff;
18+
pub const INVALID_KEY: usize = 0xffffffffffffffff;
19+
pub const INVALID_LEN: usize = 0xffffffffffffffff;
1620

1721
pub fn LPF_OF(addr: u64) -> u64 {
1822
// Implementation of LPF_OF macro/function
@@ -22,16 +26,16 @@ pub fn LPF_OF(addr: u64) -> u64 {
2226
#[derive(Clone, Serialize, Deserialize)]
2327
struct CachedInstruction {
2428
pub lpf: u64,
25-
pub instruction_key : usize,
29+
pub instruction_key: usize,
2630
pub instruction_len: usize,
2731
}
2832

2933
impl Default for CachedInstruction {
3034
fn default() -> Self {
3135
CachedInstruction {
3236
lpf: INVALID_LPF_ADDR,
33-
instruction_key: 0x0,
34-
instruction_len: 0x0,
37+
instruction_key: INVALID_KEY,
38+
instruction_len: INVALID_LEN,
3539
}
3640
}
3741
}
@@ -49,8 +53,7 @@ pub struct InstructionCache {
4953
next_instruction_slot: usize,
5054
pub current_instruction_slot: usize,
5155
current_decode_len: usize,
52-
current_decode_idx: usize
53-
// probe_stats: ProbeStats,
56+
current_decode_idx: usize, // probe_stats: ProbeStats,
5457
}
5558

5659
#[derive(Clone, Serialize, Deserialize, Default)]
@@ -87,7 +90,7 @@ impl InstructionCache {
8790
}
8891

8992
#[inline]
90-
fn flush_cache_line(&mut self, idx: usize) {
93+
pub fn flush_cache_line(&mut self, idx: usize) {
9194
for i in 0..MAX_CACHE_PER_LINE {
9295
self.cache_entries[idx].lpf = INVALID_LPF_ADDR;
9396
}
@@ -99,28 +102,33 @@ impl InstructionCache {
99102

100103
// do a linear probing for each cache line
101104
for i in 0..MAX_CACHE_PER_LINE {
102-
if self.cache_entries[idx+i].lpf == INVALID_LPF_ADDR {
105+
if self.cache_entries[idx + i].lpf == INVALID_LPF_ADDR {
103106
return false;
104107
}
105108
// found the instruction now do initialization and return true
106-
if self.cache_entries[idx+i].lpf == addr {
107-
let key = self.cache_entries[idx+i].instruction_key;
109+
if self.cache_entries[idx + i].lpf == addr {
110+
let key = self.cache_entries[idx + i].instruction_key;
108111
self.current_instruction_slot = key;
109-
self.current_decode_len = self.cache_entries[idx+i].instruction_len;
112+
self.current_decode_len = self.cache_entries[idx + i].instruction_len;
110113
self.current_decode_idx = 0;
111114
return true;
112115
}
113116
}
114117

115118
// the cache_line is full now we flush all the cache line
116119
self.flush_cache_line(idx);
117-
true
120+
false
118121
}
119122

120123
#[inline(always)]
121124
fn flush_cache(&mut self) {
122-
self.cache_entries = vec![CachedInstruction::default(); CACHE_SIZE];
123-
self.instructions = vec![Instruction::default(); INSTRUCTION_ARRAY_SIZE];
125+
self.cache_entries
126+
.iter_mut()
127+
.for_each(|entry| {
128+
entry.lpf = INVALID_LPF_ADDR;
129+
entry.instruction_key = INVALID_KEY;
130+
entry.instruction_len = INVALID_LEN;
131+
});
124132
self.next_instruction_slot = 0;
125133
}
126134

@@ -134,22 +142,38 @@ impl InstructionCache {
134142
// but I think this is simple and good enough
135143
let slot = self.next_instruction_slot;
136144

137-
if self.next_instruction_slot >= INSTRUCTION_ARRAY_SIZE {
145+
let mut count: usize = 0;
146+
let max_position = decoder.max_position();
147+
if max_position + self.next_instruction_slot > INSTRUCTION_ARRAY_SIZE {
138148
self.flush_cache();
139149
}
140-
let mut count: usize = 0;
141-
while decoder.can_decode() && decoder.position() + addition <= decoder.max_position() {
142-
decoder.decode_out(&mut self.instructions[slot+count]);
150+
151+
while decoder.can_decode() && decoder.position() + addition <= max_position {
152+
decoder.decode_out(&mut self.instructions[slot + count]);
153+
let temp = self.instructions[slot + count];
154+
if temp.is_jmp_short_or_near()
155+
|| temp.is_jmp_near_indirect()
156+
|| temp.is_jmp_far()
157+
|| temp.is_jmp_far_indirect()
158+
|| temp.is_jcc_short_or_near()
159+
|| temp.is_call_near_indirect()
160+
|| temp.is_call_near()
161+
|| temp.is_call_far_indirect()
162+
|| temp.is_call_far()
163+
{
164+
count += 1;
165+
break;
166+
}
143167
count += 1;
144168
}
145169
self.next_instruction_slot += count;
146170

147171
// insert to the cache
148172
for i in 0..MAX_CACHE_PER_LINE {
149-
if self.cache_entries[idx+i].lpf == INVALID_LPF_ADDR {
150-
self.cache_entries[idx+i].instruction_key = slot;
151-
self.cache_entries[idx+i].lpf = rip_addr;
152-
self.cache_entries[idx+i].instruction_len = count;
173+
if self.cache_entries[idx + i].lpf == INVALID_LPF_ADDR {
174+
self.cache_entries[idx + i].instruction_key = slot;
175+
self.cache_entries[idx + i].lpf = rip_addr;
176+
self.cache_entries[idx + i].instruction_len = count;
153177
break;
154178
}
155179
}
@@ -172,15 +196,15 @@ impl InstructionCache {
172196
}
173197

174198
for i in 0..instrs.len() {
175-
self.instructions[slot+i] = instrs[i];
199+
self.instructions[slot + i] = instrs[i];
176200
}
177201

178202
// insert to the cache
179203
for i in 0..MAX_CACHE_PER_LINE {
180-
if self.cache_entries[idx+i].lpf == INVALID_LPF_ADDR {
181-
self.cache_entries[idx+i].instruction_key = slot;
182-
self.cache_entries[idx+i].lpf = addr;
183-
self.cache_entries[idx+i].instruction_len = instrs.len();
204+
if self.cache_entries[idx + i].lpf == INVALID_LPF_ADDR {
205+
self.cache_entries[idx + i].instruction_key = slot;
206+
self.cache_entries[idx + i].lpf = addr;
207+
self.cache_entries[idx + i].instruction_len = instrs.len();
184208
break;
185209
}
186210
}
@@ -198,7 +222,7 @@ impl InstructionCache {
198222

199223
impl Emu {
200224
/// Disassemble an amount of instruccions on an specified address.
201-
/// This not used on the emulation engine, just from console,
225+
/// This not used on the emulation engine, just from console,
202226
/// but the api could be used programatilcally.
203227
pub fn disassemble(&mut self, addr: u64, amount: u32) -> String {
204228
let mut out = String::new();

crates/libmwemu/src/emu/execution.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ impl Emu {
359359
/// Automatically dispatches to single or multi-threaded execution based on cfg.enable_threading.
360360
#[allow(deprecated)]
361361
pub fn run(&mut self, end_addr: Option<u64>) -> Result<u64, MwemuError> {
362-
let mut instruction_cache = InstructionCache::new();
362+
let instruction_cache = InstructionCache::new();
363363
self.instruction_cache = instruction_cache;
364364
if self.cfg.enable_threading && self.threads.len() > 1 {
365365
self.run_multi_threaded(end_addr)
@@ -834,7 +834,7 @@ impl Emu {
834834
// the need of Reallocate everytime
835835
let mut block: Vec<u8> = Vec::with_capacity(constants::BLOCK_LEN + 1);
836836
block.resize(constants::BLOCK_LEN, 0x0);
837-
let mut instruction_cache = InstructionCache::new();
837+
self.instruction_cache = InstructionCache::new();
838838
loop {
839839
while self.is_running.load(atomic::Ordering::Relaxed) == 1 {
840840
//log::info!("reloading rip 0x{:x}", self.regs().rip);

crates/libmwemu/src/emu/initialization.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ use crate::emu::Emu;
1212
use crate::peb::{peb32, peb64};
1313
use crate::{get_bit, kuser_shared, set_bit, structures, winapi::winapi32, winapi::winapi64};
1414
use crate::{banzai::Banzai, breakpoint::Breakpoints, colors::Colors, config::Config, global_locks::GlobalLocks, hooks::Hooks, maps::Maps, thread_context::ThreadContext};
15+
use crate::emu::disassemble::InstructionCache;
16+
use crate::maps::mem64::Permission;
1517

1618
impl Emu {
1719
pub fn new() -> Emu {
@@ -63,6 +65,7 @@ impl Emu {
6365
threads: vec![ThreadContext::new(0x1000)],
6466
current_thread_id: 0,
6567
global_locks: GlobalLocks::new(),
68+
instruction_cache: InstructionCache::new(),
6669
}
6770
}
6871

@@ -84,7 +87,7 @@ impl Emu {
8487

8588
let stack = self
8689
.maps
87-
.create_map("stack", self.cfg.stack_addr, 0x030000)
90+
.create_map("stack", self.cfg.stack_addr, 0x030000, Permission::READ_WRITE)
8891
.expect("cannot create stack map");
8992
let stack_base = stack.get_base();
9093
let stack_bottom = stack.get_bottom();
@@ -118,7 +121,7 @@ impl Emu {
118121
// Add extra buffer beyond rbp to ensure it's strictly less than bottom
119122
let stack = self
120123
.maps
121-
.create_map("stack", self.cfg.stack_addr, stack_size + 0x2000) // Increased size
124+
.create_map("stack", self.cfg.stack_addr, stack_size + 0x2000, Permission::READ_WRITE) // Increased size
122125
.expect("cannot create stack map");
123126
let stack_base = stack.get_base();
124127
let stack_bottom = stack.get_bottom();
@@ -259,27 +262,27 @@ impl Emu {
259262
//self.regs_mut().rsp = 0x7fffffffe2b0;
260263
self.regs_mut().rsp = 0x7fffffffe790;
261264
self.maps
262-
.create_map("linux_dynamic_stack", 0x7ffffffde000, 0x100000)
265+
.create_map("linux_dynamic_stack", 0x7ffffffde000, 0x100000, Permission::READ_WRITE)
263266
.expect("cannot create linux_dynamic_stack map");
264267
//self.maps.create_map("dso_dyn").load_at(0x7ffff7ffd0000);
265268
self.maps
266-
.create_map("dso_dyn", 0x7ffff7ffd000, 0x1000)
269+
.create_map("dso_dyn", 0x7ffff7ffd000, 0x1000, Permission::READ_WRITE)
267270
.expect("cannot create dso_dyn map");
268271
self.maps
269-
.create_map("linker", 0x7ffff7ffd000-0x1000-0x10000, 0x10000)
272+
.create_map("linker", 0x7ffff7ffd000-0x1000-0x10000, 0x10000, Permission::READ_WRITE)
270273
.expect("cannot create linker map");
271274
} else {
272275
self.regs_mut().rsp = 0x7fffffffe270;
273276
self.maps
274-
.create_map("linux_static_stack", 0x7ffffffde000, 0x100000)
277+
.create_map("linux_static_stack", 0x7ffffffde000, 0x100000, Permission::READ_WRITE)
275278
.expect("cannot create linux_static_stack map");
276279
self.maps
277-
.create_map("dso", 0x7ffff7ffd000, 0x100000)
280+
.create_map("dso", 0x7ffff7ffd000, 0x100000, Permission::READ_WRITE)
278281
.expect("cannot create dso map");
279282
}
280283
let tls = self
281284
.maps
282-
.create_map("tls", 0x7ffff8fff000, 0xfff)
285+
.create_map("tls", 0x7ffff8fff000, 0xfff, Permission::READ_WRITE)
283286
.expect("cannot create tls map");
284287
tls.load("tls.bin");
285288

@@ -292,7 +295,7 @@ impl Emu {
292295
self.heap_addr = self.maps.alloc(heap_sz).expect("cannot allocate heap");
293296
let heap = self
294297
.maps
295-
.create_map("heap", self.heap_addr, heap_sz) //.create_map("heap", 0x4b5b00, 0x4d8000 - 0x4b5000)
298+
.create_map("heap", self.heap_addr, heap_sz, Permission::READ_WRITE) //.create_map("heap", 0x4b5b00, 0x4d8000 - 0x4b5000)
296299
.expect("cannot create heap map");
297300
heap.load("heap.bin");
298301
}
@@ -351,7 +354,7 @@ impl Emu {
351354
pub fn init_tests(&mut self) {
352355
let mem = self
353356
.maps
354-
.create_map("test", 0, 1024)
357+
.create_map("test", 0, 1024, Permission::READ_WRITE_EXECUTE)
355358
.expect("cannot create test map");
356359
mem.write_qword(0, 0x1122334455667788);
357360
assert!(mem.read_qword(0) == 0x1122334455667788);

0 commit comments

Comments
 (0)