i686: add single-step debugging
This commit is contained in:
parent
6c30bd062a
commit
0daf7c677c
@ -108,12 +108,13 @@ __i686_switch_and_drop:
|
|||||||
// %esp + 0: return
|
// %esp + 0: return
|
||||||
// %esp + 4: destination
|
// %esp + 4: destination
|
||||||
// %esp + 8: thread to drop
|
// %esp + 8: thread to drop
|
||||||
|
mov 8(%esp), %ecx
|
||||||
mov 4(%esp), %eax
|
mov 4(%esp), %eax
|
||||||
// Switch to stack
|
// Switch to stack
|
||||||
mov (%eax), %esp
|
mov (%eax), %esp
|
||||||
|
|
||||||
LOAD_TASK_STATE
|
LOAD_TASK_STATE
|
||||||
|
|
||||||
// TODO actually drop the thread
|
// TODO actually drop the thread
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
@ -328,8 +328,12 @@ impl TaskFrame for InterruptFrame {
|
|||||||
self.eax = value as u32;
|
self.eax = value as u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_single_step(&mut self, _step: bool) {
|
fn set_single_step(&mut self, step: bool) {
|
||||||
todo!()
|
if step {
|
||||||
|
self.eflags |= 1 << 8;
|
||||||
|
} else {
|
||||||
|
self.eflags &= !(1 << 8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_return_value(&mut self, value: u64) {
|
fn set_return_value(&mut self, value: u64) {
|
||||||
@ -392,8 +396,12 @@ impl TaskFrame for ExceptionFrame {
|
|||||||
self.eax = value as u32;
|
self.eax = value as u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_single_step(&mut self, _step: bool) {
|
fn set_single_step(&mut self, step: bool) {
|
||||||
todo!()
|
if step {
|
||||||
|
self.eflags |= 1 << 8;
|
||||||
|
} else {
|
||||||
|
self.eflags &= !(1 << 8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_return_value(&mut self, value: u64) {
|
fn set_return_value(&mut self, value: u64) {
|
||||||
|
@ -179,7 +179,7 @@ pub fn load_elf_from_file<F: Read + Seek>(
|
|||||||
|
|
||||||
// Find out image size
|
// Find out image size
|
||||||
let (vaddr_min, vaddr_max) = elf_virtual_range(&elf);
|
let (vaddr_min, vaddr_max) = elf_virtual_range(&elf);
|
||||||
let image_load_base = elf_load_address(elf.ehdr.e_type, vaddr_min);
|
let (image_load_base, ip_offset) = elf_load_address(elf.ehdr.e_type, vaddr_min);
|
||||||
let image_load_size = vaddr_max - vaddr_min;
|
let image_load_size = vaddr_max - vaddr_min;
|
||||||
|
|
||||||
log::debug!(
|
log::debug!(
|
||||||
@ -213,6 +213,7 @@ pub fn load_elf_from_file<F: Read + Seek>(
|
|||||||
|
|
||||||
Ok(ProcessImage {
|
Ok(ProcessImage {
|
||||||
entry,
|
entry,
|
||||||
|
ip_offset,
|
||||||
tls,
|
tls,
|
||||||
load_base: image_load_base,
|
load_base: image_load_base,
|
||||||
})
|
})
|
||||||
@ -299,13 +300,14 @@ pub fn elf_virtual_range<F: Read + Seek>(
|
|||||||
(vaddr_min, vaddr_max)
|
(vaddr_min, vaddr_max)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn elf_load_address(elf_type: u16, virtual_address: usize) -> usize {
|
fn elf_load_address(elf_type: u16, virtual_address: usize) -> (usize, usize) {
|
||||||
match elf_type {
|
match elf_type {
|
||||||
elf::abi::ET_EXEC => virtual_address,
|
elf::abi::ET_EXEC => (virtual_address, 0),
|
||||||
// TODO ASLR through random?
|
// TODO ASLR through random?
|
||||||
elf::abi::ET_DYN => {
|
elf::abi::ET_DYN => {
|
||||||
let index = random::range(0x5000, 0x20000);
|
let index = random::range(0x5000, 0x20000);
|
||||||
(index as usize) * 0x1000
|
let base = (index as usize) * 0x1000;
|
||||||
|
(base, base)
|
||||||
}
|
}
|
||||||
// Handled in load_elf_from_file()
|
// Handled in load_elf_from_file()
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -51,6 +51,7 @@ pub struct ProcessManager {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ProcessImage {
|
pub struct ProcessImage {
|
||||||
pub load_base: usize,
|
pub load_base: usize,
|
||||||
|
pub ip_offset: usize,
|
||||||
/// Entry point address
|
/// Entry point address
|
||||||
pub entry: usize,
|
pub entry: usize,
|
||||||
/// Thread-local storage information
|
/// Thread-local storage information
|
||||||
@ -234,8 +235,12 @@ impl Process {
|
|||||||
self.inner.read().space.clone().unwrap()
|
self.inner.read().space.clone().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn map_image<T, F: FnOnce(&ProcessImage) -> T>(&self, f: F) -> Option<T> {
|
||||||
|
self.inner.read().image.as_ref().map(f)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn image_base(&self) -> Option<usize> {
|
pub fn image_base(&self) -> Option<usize> {
|
||||||
self.inner.read().image.as_ref().map(|img| img.load_base)
|
self.map_image(|image| image.load_base)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_single_thread(&self) -> Option<Arc<Thread>> {
|
pub fn as_single_thread(&self) -> Option<Arc<Thread>> {
|
||||||
@ -329,9 +334,10 @@ impl Process {
|
|||||||
let inner = proc.inner.read();
|
let inner = proc.inner.read();
|
||||||
if !proc.has_exited() && inner.group_id == group_id {
|
if !proc.has_exited() && inner.group_id == group_id {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"Deliver group ({}) signal to {}: {:?}",
|
"Deliver group ({}) signal to {} ({:?}): {:?}",
|
||||||
group_id,
|
group_id,
|
||||||
proc.id,
|
proc.id,
|
||||||
|
proc.name,
|
||||||
signal
|
signal
|
||||||
);
|
);
|
||||||
drop(inner);
|
drop(inner);
|
||||||
|
@ -456,6 +456,7 @@ impl CurrentThread {
|
|||||||
|
|
||||||
// Single step cleared
|
// Single step cleared
|
||||||
if !debug.single_step {
|
if !debug.single_step {
|
||||||
|
log::debug!("Clear single step ({} {:?})", self.id, self.name);
|
||||||
frame.set_single_step(false);
|
frame.set_single_step(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -494,9 +495,13 @@ impl CurrentThread {
|
|||||||
|
|
||||||
// Send initial frame
|
// Send initial frame
|
||||||
let saved_frame = frame.store();
|
let saved_frame = frame.store();
|
||||||
|
let (image_base, ip_offset) = process
|
||||||
|
.map_image(|img| (img.load_base, img.ip_offset))
|
||||||
|
.unwrap();
|
||||||
debugger
|
debugger
|
||||||
.send(&DebugFrame::Startup {
|
.send(&DebugFrame::Startup {
|
||||||
image_base: process.image_base().unwrap(),
|
image_base,
|
||||||
|
ip_offset,
|
||||||
frame: saved_frame,
|
frame: saved_frame,
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
|
@ -162,13 +162,16 @@ fn kernel_exception_inner(kind: ExceptionKind, frame: &ExceptionFrame) -> ! {
|
|||||||
panic!("Irrecoverable exception")
|
panic!("Irrecoverable exception")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn user_exception_inner(kind: ExceptionKind, frame: &ExceptionFrame) {
|
fn user_exception_inner(kind: ExceptionKind, frame: &mut ExceptionFrame) {
|
||||||
let thread = Thread::current();
|
let thread = Thread::current();
|
||||||
|
|
||||||
|
if kind != ExceptionKind::Debug {
|
||||||
let cr3 = CR3.get();
|
let cr3 = CR3.get();
|
||||||
|
|
||||||
warnln!("{:?} in {} {:?}", kind, thread.id, thread.name);
|
warnln!("{:?} in {} {:?}", kind, thread.id, thread.name);
|
||||||
warnln!("CS:EIP = {:#02x}:{:#010x}", frame.cs, frame.eip);
|
warnln!("CS:EIP = {:#02x}:{:#010x}", frame.cs, frame.eip);
|
||||||
warnln!("CR3 = {:#x}", cr3);
|
warnln!("CR3 = {:#x}", cr3);
|
||||||
|
}
|
||||||
|
|
||||||
match kind {
|
match kind {
|
||||||
ExceptionKind::PageFault => {
|
ExceptionKind::PageFault => {
|
||||||
@ -183,6 +186,11 @@ fn user_exception_inner(kind: ExceptionKind, frame: &ExceptionFrame) {
|
|||||||
ExceptionKind::InvalidOpcode => {
|
ExceptionKind::InvalidOpcode => {
|
||||||
thread.raise_signal(Signal::Aborted);
|
thread.raise_signal(Signal::Aborted);
|
||||||
}
|
}
|
||||||
|
ExceptionKind::Debug => {
|
||||||
|
// TODO check if the thread was really in single-step mode or has debugging related to
|
||||||
|
// the address in exception description
|
||||||
|
thread.handle_single_step(frame);
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ impl DisplayConsole for TextFramebuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn text_dimensions(&self) -> (usize, usize) {
|
fn text_dimensions(&self) -> (usize, usize) {
|
||||||
(self.width, self.height)
|
(self.height, self.width)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ pub enum DebugOperation<'a> {
|
|||||||
pub enum DebugFrame {
|
pub enum DebugFrame {
|
||||||
Startup {
|
Startup {
|
||||||
image_base: usize,
|
image_base: usize,
|
||||||
|
ip_offset: usize,
|
||||||
frame: SavedFrame,
|
frame: SavedFrame,
|
||||||
},
|
},
|
||||||
Step {
|
Step {
|
||||||
|
@ -94,10 +94,12 @@ where
|
|||||||
current += 1;
|
current += 1;
|
||||||
node = bucket.next;
|
node = bucket.next;
|
||||||
}
|
}
|
||||||
panic!(
|
|
||||||
"BucketList index out of range: contains {} buckets, tried to index {}",
|
loop {}
|
||||||
current, index
|
// panic!(
|
||||||
);
|
// "BucketList index out of range: contains {} buckets, tried to index {}",
|
||||||
|
// current, index
|
||||||
|
// );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
106
userspace/Cargo.lock
generated
106
userspace/Cargo.lock
generated
@ -16,12 +16,55 @@ dependencies = [
|
|||||||
name = "abi-lib"
|
name = "abi-lib"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstream"
|
||||||
|
version = "0.6.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"anstyle-parse",
|
||||||
|
"anstyle-query",
|
||||||
|
"anstyle-wincon",
|
||||||
|
"colorchoice",
|
||||||
|
"is_terminal_polyfill",
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle"
|
name = "anstyle"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
|
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-parse"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
|
||||||
|
dependencies = [
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-query"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-wincon"
|
||||||
|
version = "3.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayvec"
|
name = "arrayvec"
|
||||||
version = "0.7.4"
|
version = "0.7.4"
|
||||||
@ -109,8 +152,10 @@ version = "4.5.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
|
checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"clap_lex",
|
"clap_lex",
|
||||||
|
"strsim",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -131,6 +176,12 @@ version = "0.7.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
|
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorchoice"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colors"
|
name = "colors"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -178,6 +229,12 @@ dependencies = [
|
|||||||
"powerfmt",
|
"powerfmt",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "elf"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@ -282,6 +339,15 @@ dependencies = [
|
|||||||
"libm",
|
"libm",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iced-x86"
|
||||||
|
version = "1.21.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7c447cff8c7f384a7d4f741cfcff32f75f3ad02b406432e8d6c878d56b1edf6b"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
@ -311,6 +377,12 @@ dependencies = [
|
|||||||
"yggdrasil-rt",
|
"yggdrasil-rt",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is_terminal_polyfill"
|
||||||
|
version = "1.70.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.10"
|
version = "1.0.10"
|
||||||
@ -602,6 +674,12 @@ dependencies = [
|
|||||||
"zerocopy",
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rangemap"
|
||||||
|
version = "1.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f60fcc7d6849342eff22c4350c8b9a989ee8ceabc4b481253e8946b9fe83d684"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "raqote"
|
name = "raqote"
|
||||||
version = "0.8.3"
|
version = "0.8.3"
|
||||||
@ -614,6 +692,22 @@ dependencies = [
|
|||||||
"typed-arena",
|
"typed-arena",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rdb"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
"elf",
|
||||||
|
"iced-x86",
|
||||||
|
"libterm",
|
||||||
|
"rangemap",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
"yggdrasil-abi",
|
||||||
|
"yggdrasil-rt",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "red"
|
name = "red"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -749,6 +843,12 @@ version = "1.13.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
|
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sw-composite"
|
name = "sw-composite"
|
||||||
version = "0.7.16"
|
version = "0.7.16"
|
||||||
@ -957,6 +1057,12 @@ dependencies = [
|
|||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8parse"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
|
@ -13,6 +13,6 @@ members = [
|
|||||||
"netutils",
|
"netutils",
|
||||||
"netutils",
|
"netutils",
|
||||||
# "dyn-loader",
|
# "dyn-loader",
|
||||||
# "rdb"
|
"rdb"
|
||||||
]
|
]
|
||||||
exclude = ["dynload-program", "test-kernel-module"]
|
exclude = ["dynload-program", "test-kernel-module"]
|
||||||
|
@ -15,5 +15,8 @@ thiserror = "1.0.58"
|
|||||||
elf = "0.7.4"
|
elf = "0.7.4"
|
||||||
rangemap = "1.5.1"
|
rangemap = "1.5.1"
|
||||||
|
|
||||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
[target.'cfg(any(target_arch = "x86_64", target_arch = "x86"))'.dependencies]
|
||||||
|
iced-x86 = { version = "1.21.0", default-features = false, features = ["gas", "decoder", "std"] }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
iced-x86 = { version = "1.21.0", default-features = false, features = ["gas", "decoder", "std"] }
|
iced-x86 = { version = "1.21.0", default-features = false, features = ["gas", "decoder", "std"] }
|
||||||
|
@ -29,6 +29,7 @@ impl InstructionFormatter<()> for Unsupported {
|
|||||||
impl Target for TargetImpl {
|
impl Target for TargetImpl {
|
||||||
type Instruction = ();
|
type Instruction = ();
|
||||||
type InstructionFormatter = Unsupported;
|
type InstructionFormatter = Unsupported;
|
||||||
|
type Register = usize;
|
||||||
|
|
||||||
fn disassemble(
|
fn disassemble(
|
||||||
_window: &[u8],
|
_window: &[u8],
|
||||||
@ -44,11 +45,11 @@ impl Target for TargetImpl {
|
|||||||
fn flags_register_as_display(frame: &SavedFrame) -> impl Display {
|
fn flags_register_as_display(frame: &SavedFrame) -> impl Display {
|
||||||
FlagFormat(frame.spsr_el1)
|
FlagFormat(frame.spsr_el1)
|
||||||
}
|
}
|
||||||
fn register_list(frame: &SavedFrame, out: &mut Vec<(String, u64)>) {
|
fn register_list(frame: &SavedFrame, out: &mut Vec<(String, Self::Register)>) {
|
||||||
for i in 0..30 {
|
for i in 0..30 {
|
||||||
out.push((format!("x{}", i), frame.gp_regs[i]));
|
out.push((format!("x{}", i), frame.gp_regs[i]));
|
||||||
}
|
}
|
||||||
out.push(("pc".into(), frame.elr_el1));
|
out.push(("pc".into(), frame.elr_el1 as _));
|
||||||
out.push(("lr".into(), frame.gp_regs[30]));
|
out.push(("lr".into(), frame.gp_regs[30]));
|
||||||
}
|
}
|
||||||
fn real_ip(frame: &SavedFrame) -> usize {
|
fn real_ip(frame: &SavedFrame) -> usize {
|
||||||
|
@ -43,8 +43,8 @@ impl<T: Target> Debugger<T> {
|
|||||||
let segment_headers = extract_segments(image)?;
|
let segment_headers = extract_segments(image)?;
|
||||||
|
|
||||||
let file = BufReader::new(File::open(image)?);
|
let file = BufReader::new(File::open(image)?);
|
||||||
let term = Term::open().unwrap();
|
|
||||||
let comm = Comm::open("rdb-1")?;
|
let comm = Comm::open("rdb-1")?;
|
||||||
|
let term = Term::open().unwrap();
|
||||||
let mut poll = PollChannel::new()?;
|
let mut poll = PollChannel::new()?;
|
||||||
|
|
||||||
let comm_fd = comm.as_raw_fd();
|
let comm_fd = comm.as_raw_fd();
|
||||||
@ -80,9 +80,9 @@ impl<T: Target> Debugger<T> {
|
|||||||
|
|
||||||
fn handle_frame(&mut self, frame: DebugFrame) -> Result<(), Error> {
|
fn handle_frame(&mut self, frame: DebugFrame) -> Result<(), Error> {
|
||||||
match frame {
|
match frame {
|
||||||
DebugFrame::Startup { image_base, frame } => {
|
DebugFrame::Startup { image_base, frame, ip_offset } => {
|
||||||
let pid = unsafe { ProcessId::from_raw(self.child.id()) };
|
let pid = unsafe { ProcessId::from_raw(self.child.id()) };
|
||||||
let mut state = State::new(image_base, pid);
|
let mut state = State::new(image_base, ip_offset, pid);
|
||||||
state.update(&frame, true)?;
|
state.update(&frame, true)?;
|
||||||
self.state = Some(state);
|
self.state = Some(state);
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -151,7 +151,7 @@ impl<T: Target> Debugger<T> {
|
|||||||
|
|
||||||
T::disassemble(
|
T::disassemble(
|
||||||
&segment[offset_within_segment..offset_within_segment + amount * 8],
|
&segment[offset_within_segment..offset_within_segment + amount * 8],
|
||||||
state.current_ip + state.image_base,
|
state.current_ip + state.ip_offset,
|
||||||
amount,
|
amount,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -163,7 +163,7 @@ impl<T: Target> Debugger<T> {
|
|||||||
return Ok(0);
|
return Ok(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
let columns = (width - 2) / REG_WIDTH;
|
let columns = (width + REG_WIDTH - 3) / REG_WIDTH;
|
||||||
let mut gpregs = vec![];
|
let mut gpregs = vec![];
|
||||||
T::register_list(&state.last_frame, &mut gpregs);
|
T::register_list(&state.last_frame, &mut gpregs);
|
||||||
let rows = 1 + (gpregs.len() + columns - 1) / columns;
|
let rows = 1 + (gpregs.len() + columns - 1) / columns;
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
#![feature(yggdrasil_os, if_let_guard)]
|
#![feature(yggdrasil_os, if_let_guard)]
|
||||||
use std::{fmt::Display, io, path::PathBuf, process::Command};
|
use std::{fmt::{LowerHex, Display}, io, path::PathBuf, process::Command};
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use debugger::Debugger;
|
use debugger::Debugger;
|
||||||
use imp::TargetImpl;
|
use imp::TargetImpl;
|
||||||
use yggdrasil_abi::arch::SavedFrame;
|
use yggdrasil_abi::arch::SavedFrame;
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(any(target_arch = "x86_64", target_arch = "x86", rust_analyzer))]
|
||||||
#[path = "x86_64.rs"]
|
#[path = "x86.rs"]
|
||||||
pub mod imp;
|
pub mod imp;
|
||||||
|
#[cfg(any(target_arch = "aarch64", rust_analyzer))]
|
||||||
#[cfg(target_arch = "aarch64")]
|
|
||||||
#[path = "aarch64.rs"]
|
#[path = "aarch64.rs"]
|
||||||
pub mod imp;
|
pub mod imp;
|
||||||
|
|
||||||
@ -32,6 +31,7 @@ pub enum Error {
|
|||||||
pub trait Target {
|
pub trait Target {
|
||||||
type Instruction;
|
type Instruction;
|
||||||
type InstructionFormatter: InstructionFormatter<Self::Instruction>;
|
type InstructionFormatter: InstructionFormatter<Self::Instruction>;
|
||||||
|
type Register: LowerHex;
|
||||||
|
|
||||||
fn disassemble(
|
fn disassemble(
|
||||||
window: &[u8],
|
window: &[u8],
|
||||||
@ -40,7 +40,7 @@ pub trait Target {
|
|||||||
) -> Result<Vec<(usize, Self::Instruction)>, Error>;
|
) -> Result<Vec<(usize, Self::Instruction)>, Error>;
|
||||||
fn new_instruction_formatter() -> Self::InstructionFormatter;
|
fn new_instruction_formatter() -> Self::InstructionFormatter;
|
||||||
|
|
||||||
fn register_list(frame: &SavedFrame, out: &mut Vec<(String, u64)>);
|
fn register_list(frame: &SavedFrame, out: &mut Vec<(String, Self::Register)>);
|
||||||
fn flags_register_as_display(frame: &SavedFrame) -> impl Display;
|
fn flags_register_as_display(frame: &SavedFrame) -> impl Display;
|
||||||
fn real_ip(frame: &SavedFrame) -> usize;
|
fn real_ip(frame: &SavedFrame) -> usize;
|
||||||
}
|
}
|
||||||
|
@ -12,18 +12,20 @@ pub struct State<T: Target> {
|
|||||||
pub last_frame: SavedFrame,
|
pub last_frame: SavedFrame,
|
||||||
|
|
||||||
pub image_base: usize,
|
pub image_base: usize,
|
||||||
|
pub ip_offset: usize,
|
||||||
|
|
||||||
_pd: PhantomData<T>,
|
_pd: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Target> State<T> {
|
impl<T: Target> State<T> {
|
||||||
pub fn new(image_base: usize, pid: ProcessId) -> Self {
|
pub fn new(image_base: usize, ip_offset: usize, pid: ProcessId) -> Self {
|
||||||
Self {
|
Self {
|
||||||
current_ip: 0,
|
current_ip: 0,
|
||||||
last_frame: SavedFrame::default(),
|
last_frame: SavedFrame::default(),
|
||||||
|
|
||||||
pid,
|
pid,
|
||||||
image_base,
|
image_base,
|
||||||
|
ip_offset,
|
||||||
|
|
||||||
_pd: PhantomData,
|
_pd: PhantomData,
|
||||||
}
|
}
|
||||||
@ -37,7 +39,7 @@ impl<T: Target> State<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, frame: &SavedFrame, _refresh: bool) -> Result<(), Error> {
|
pub fn update(&mut self, frame: &SavedFrame, _refresh: bool) -> Result<(), Error> {
|
||||||
let ip = T::real_ip(frame) - self.image_base;
|
let ip = T::real_ip(frame) - self.ip_offset;
|
||||||
self.last_frame = frame.clone();
|
self.last_frame = frame.clone();
|
||||||
self.current_ip = ip;
|
self.current_ip = ip;
|
||||||
|
|
||||||
|
123
userspace/rdb/src/x86.rs
Normal file
123
userspace/rdb/src/x86.rs
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
use std::fmt::{self, Display};
|
||||||
|
|
||||||
|
use iced_x86::{Decoder, DecoderOptions, Formatter, GasFormatter, Instruction};
|
||||||
|
use yggdrasil_abi::arch::SavedFrame;
|
||||||
|
|
||||||
|
use crate::{InstructionFormatter, Target};
|
||||||
|
|
||||||
|
#[cfg(any(target_pointer_width = "32", rust_analyzer))]
|
||||||
|
const BITNESS: u32 = 32;
|
||||||
|
#[cfg(any(target_pointer_width = "64", rust_analyzer))]
|
||||||
|
const BITNESS: u32 = 64;
|
||||||
|
|
||||||
|
pub struct FlagsDisplay(usize);
|
||||||
|
|
||||||
|
pub struct TargetImpl;
|
||||||
|
|
||||||
|
pub struct NoopFormatter;
|
||||||
|
|
||||||
|
impl fmt::Display for FlagsDisplay {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
const FLAGS: &[(usize, &str)] = &[
|
||||||
|
(0, "CF"),
|
||||||
|
(2, "PF"),
|
||||||
|
(4, "AF"),
|
||||||
|
(5, "ZF"),
|
||||||
|
(6, "SF"),
|
||||||
|
(9, "IF"),
|
||||||
|
(10, "DF"),
|
||||||
|
(11, "OF"),
|
||||||
|
];
|
||||||
|
write!(f, " {: <#8x} [ ", self.0)?;
|
||||||
|
for (bit, flag) in FLAGS {
|
||||||
|
if self.0 & (1 << bit) != 0 {
|
||||||
|
write!(f, "{} ", flag)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write!(f, "]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InstructionFormatter<Instruction> for GasFormatter {
|
||||||
|
fn format_instruction(&mut self, insn: &Instruction, out: &mut String) {
|
||||||
|
self.format(insn, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Target for TargetImpl {
|
||||||
|
type Instruction = Instruction;
|
||||||
|
type InstructionFormatter = GasFormatter;
|
||||||
|
type Register = usize;
|
||||||
|
|
||||||
|
fn disassemble(
|
||||||
|
window: &[u8],
|
||||||
|
ip: usize,
|
||||||
|
limit: usize,
|
||||||
|
) -> Result<Vec<(usize, Self::Instruction)>, crate::Error> {
|
||||||
|
let mut instructions = vec![];
|
||||||
|
let mut decoder = Decoder::with_ip(BITNESS, window, ip as _, DecoderOptions::NONE);
|
||||||
|
|
||||||
|
while decoder.can_decode() && instructions.len() < limit {
|
||||||
|
let insn = decoder.decode();
|
||||||
|
instructions.push((insn.ip() as usize, insn));
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_trace!("{}", instructions.len());
|
||||||
|
Ok(instructions)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_instruction_formatter() -> Self::InstructionFormatter {
|
||||||
|
let mut formatter = GasFormatter::new();
|
||||||
|
formatter.options_mut().set_uppercase_hex(false);
|
||||||
|
formatter.options_mut().set_branch_leading_zeros(false);
|
||||||
|
formatter
|
||||||
|
}
|
||||||
|
|
||||||
|
fn register_list(frame: &SavedFrame, out: &mut Vec<(String, Self::Register)>) {
|
||||||
|
#[cfg(any(target_arch = "x86", rust_analyzer))]
|
||||||
|
{
|
||||||
|
out.push(("eax".into(), frame.eax as _));
|
||||||
|
out.push(("ecx".into(), frame.ecx as _));
|
||||||
|
out.push(("edx".into(), frame.edx as _));
|
||||||
|
out.push(("ebx".into(), frame.ebx as _));
|
||||||
|
out.push(("esp".into(), frame.user_sp as _));
|
||||||
|
out.push(("ebp".into(), frame.ebp as _));
|
||||||
|
out.push(("esi".into(), frame.esi as _));
|
||||||
|
out.push(("edi".into(), frame.edi as _));
|
||||||
|
}
|
||||||
|
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
||||||
|
{
|
||||||
|
out.push(("rax".into(), frame.rax as _));
|
||||||
|
out.push(("rcx".into(), frame.rcx as _));
|
||||||
|
out.push(("rdx".into(), frame.rdx as _));
|
||||||
|
out.push(("rbx".into(), frame.rbx as _));
|
||||||
|
out.push(("rdi".into(), frame.rdi as _));
|
||||||
|
out.push(("rsi".into(), frame.rsi as _));
|
||||||
|
out.push(("rsp".into(), frame.user_sp as _));
|
||||||
|
out.push(("rbp".into(), frame.rbp as _));
|
||||||
|
out.push(("r8".into(), frame.r8 as _));
|
||||||
|
out.push(("r9".into(), frame.r9 as _));
|
||||||
|
out.push(("r10".into(), frame.r10 as _));
|
||||||
|
out.push(("r11".into(), frame.r11 as _));
|
||||||
|
out.push(("r12".into(), frame.r12 as _));
|
||||||
|
out.push(("r13".into(), frame.r13 as _));
|
||||||
|
out.push(("r14".into(), frame.r14 as _));
|
||||||
|
out.push(("r15".into(), frame.r15 as _));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flags_register_as_display(frame: &SavedFrame) -> impl Display {
|
||||||
|
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
||||||
|
{
|
||||||
|
FlagsDisplay(frame.rflags as _)
|
||||||
|
}
|
||||||
|
#[cfg(any(target_arch = "x86", rust_analyzer))]
|
||||||
|
{
|
||||||
|
FlagsDisplay(frame.eflags as _)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn real_ip(frame: &SavedFrame) -> usize {
|
||||||
|
frame.user_ip as _
|
||||||
|
}
|
||||||
|
}
|
@ -1,93 +0,0 @@
|
|||||||
use std::fmt::{self, Display};
|
|
||||||
|
|
||||||
use iced_x86::{Decoder, DecoderOptions, Formatter, GasFormatter, Instruction};
|
|
||||||
use yggdrasil_abi::arch::SavedFrame;
|
|
||||||
|
|
||||||
use crate::{InstructionFormatter, Target};
|
|
||||||
|
|
||||||
pub struct RflagsDisplay(u64);
|
|
||||||
|
|
||||||
pub struct TargetImpl;
|
|
||||||
|
|
||||||
impl fmt::Display for RflagsDisplay {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
const FLAGS: &[(u64, &str)] = &[
|
|
||||||
(0, "CF"),
|
|
||||||
(2, "PF"),
|
|
||||||
(4, "AF"),
|
|
||||||
(5, "ZF"),
|
|
||||||
(6, "SF"),
|
|
||||||
(9, "IF"),
|
|
||||||
(10, "DF"),
|
|
||||||
(11, "OF"),
|
|
||||||
];
|
|
||||||
write!(f, " {: <#8x} [ ", self.0)?;
|
|
||||||
for (bit, flag) in FLAGS {
|
|
||||||
if self.0 & (1 << bit) != 0 {
|
|
||||||
write!(f, "{} ", flag)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
write!(f, "]")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InstructionFormatter<Instruction> for GasFormatter {
|
|
||||||
fn format_instruction(&mut self, insn: &Instruction, out: &mut String) {
|
|
||||||
self.format(insn, out)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Target for TargetImpl {
|
|
||||||
type Instruction = Instruction;
|
|
||||||
type InstructionFormatter = GasFormatter;
|
|
||||||
|
|
||||||
fn disassemble(
|
|
||||||
window: &[u8],
|
|
||||||
ip: usize,
|
|
||||||
limit: usize,
|
|
||||||
) -> Result<Vec<(usize, Self::Instruction)>, crate::Error> {
|
|
||||||
let mut instructions = vec![];
|
|
||||||
let mut decoder = Decoder::with_ip(64, window, ip as _, DecoderOptions::NONE);
|
|
||||||
|
|
||||||
while decoder.can_decode() && instructions.len() < limit {
|
|
||||||
let insn = decoder.decode();
|
|
||||||
instructions.push((insn.ip() as usize, insn));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(instructions)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_instruction_formatter() -> Self::InstructionFormatter {
|
|
||||||
let mut formatter = GasFormatter::new();
|
|
||||||
formatter.options_mut().set_uppercase_hex(false);
|
|
||||||
formatter.options_mut().set_branch_leading_zeros(false);
|
|
||||||
formatter
|
|
||||||
}
|
|
||||||
|
|
||||||
fn register_list(frame: &SavedFrame, out: &mut Vec<(String, u64)>) {
|
|
||||||
out.push(("rax".into(), frame.rax));
|
|
||||||
out.push(("rcx".into(), frame.rcx));
|
|
||||||
out.push(("rdx".into(), frame.rdx));
|
|
||||||
out.push(("rbx".into(), frame.rbx));
|
|
||||||
out.push(("rdi".into(), frame.rdi));
|
|
||||||
out.push(("rsi".into(), frame.rsi));
|
|
||||||
out.push(("rsp".into(), frame.user_sp));
|
|
||||||
out.push(("rbp".into(), frame.rbp));
|
|
||||||
out.push(("r8".into(), frame.r8));
|
|
||||||
out.push(("r9".into(), frame.r9));
|
|
||||||
out.push(("r10".into(), frame.r10));
|
|
||||||
out.push(("r11".into(), frame.r11));
|
|
||||||
out.push(("r12".into(), frame.r12));
|
|
||||||
out.push(("r13".into(), frame.r13));
|
|
||||||
out.push(("r14".into(), frame.r14));
|
|
||||||
out.push(("r15".into(), frame.r15));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn flags_register_as_display(frame: &SavedFrame) -> impl Display {
|
|
||||||
RflagsDisplay(frame.rflags)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn real_ip(frame: &SavedFrame) -> usize {
|
|
||||||
frame.user_ip as _
|
|
||||||
}
|
|
||||||
}
|
|
@ -47,7 +47,7 @@ const PROGRAMS: &[(&str, &str)] = &[
|
|||||||
// red
|
// red
|
||||||
("red", "bin/red"),
|
("red", "bin/red"),
|
||||||
// rdb
|
// rdb
|
||||||
// ("rdb", "bin/rdb"),
|
("rdb", "bin/rdb"),
|
||||||
// ("dyn-loader", "libexec/dyn-loader"),
|
// ("dyn-loader", "libexec/dyn-loader"),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user