Add generalized stack pointer access

Reviewed By: VladimirMakaev

Differential Revision: D40701834

fbshipit-source-id: 6cad4cedc0d22488117d3d991ae9a80b643ee037
This commit is contained in:
Jason White 2022-10-27 10:56:09 -07:00 committed by Facebook GitHub Bot
parent 4f9ce11c70
commit caf0f12131
3 changed files with 57 additions and 4 deletions

View file

@ -49,6 +49,7 @@ use crate::gdbstub::Inferior;
use crate::gdbstub::InferiorThreadId; use crate::gdbstub::InferiorThreadId;
use crate::gdbstub::ResumeInferior; use crate::gdbstub::ResumeInferior;
use crate::gdbstub::StoppedInferior; use crate::gdbstub::StoppedInferior;
use crate::regs::RegAccess;
mod base; mod base;
mod extended_mode; mod extended_mode;
@ -363,9 +364,9 @@ pub struct ExpediatedRegs(BTreeMap<usize, u64>);
impl From<libc::user_regs_struct> for ExpediatedRegs { impl From<libc::user_regs_struct> for ExpediatedRegs {
fn from(regs: libc::user_regs_struct) -> Self { fn from(regs: libc::user_regs_struct) -> Self {
let mut exp_regs = BTreeMap::new(); let mut exp_regs = BTreeMap::new();
exp_regs.insert(6, regs.rbp); exp_regs.insert(6, regs.frame_ptr());
exp_regs.insert(7, regs.rsp); exp_regs.insert(7, regs.stack_ptr());
exp_regs.insert(0x10, regs.rip); exp_regs.insert(0x10, regs.ip());
ExpediatedRegs(exp_regs) ExpediatedRegs(exp_regs)
} }
} }

View file

@ -26,6 +26,22 @@ pub trait RegAccess {
/// Mutable access to the instruction pointer (aka the program counter). /// Mutable access to the instruction pointer (aka the program counter).
fn ip_mut(&mut self) -> &mut Reg; fn ip_mut(&mut self) -> &mut Reg;
/// Returns the value of the stack pointer.
fn stack_ptr(&self) -> Reg;
/// Mutable access to the stack pointer.
fn stack_ptr_mut(&mut self) -> &mut Reg;
/// Returns the value of the stack frame pointer.
///
/// NOTE: The frame pointer is not guaranteed to be available. For example,
/// if `-fomit-frame-pointer` was used (often the default), this will not
/// return the correct address.
fn frame_ptr(&self) -> Reg;
/// Mutable access to the stack frame pointer.
fn frame_ptr_mut(&mut self) -> &mut Reg;
/// Returns the value of the register where the syscall number is stored. /// Returns the value of the register where the syscall number is stored.
/// ///
/// NOTE: Depending on the context, this may not actually be a syscall /// NOTE: Depending on the context, this may not actually be a syscall
@ -76,6 +92,22 @@ impl RegAccess for libc::user_regs_struct {
&mut self.rip &mut self.rip
} }
fn stack_ptr(&self) -> Reg {
self.rsp
}
fn stack_ptr_mut(&mut self) -> &mut Reg {
&mut self.rsp
}
fn frame_ptr(&self) -> Reg {
self.rbp
}
fn frame_ptr_mut(&mut self) -> &mut Reg {
&mut self.rbp
}
fn syscall(&self) -> Reg { fn syscall(&self) -> Reg {
self.rax self.rax
} }
@ -126,6 +158,24 @@ impl RegAccess for libc::user_regs_struct {
&mut self.pc &mut self.pc
} }
fn stack_ptr(&self) -> Reg {
self.sp
}
fn stack_ptr_mut(&mut self) -> &mut Reg {
&mut self.sp
}
fn frame_ptr(&self) -> Reg {
// aarch64 uses x29 for the frame pointer (unless `-fomit-frame-pointer`
// is used).
self.regs[29]
}
fn frame_ptr_mut(&mut self) -> &mut Reg {
&mut self.regs[29]
}
fn syscall(&self) -> Reg { fn syscall(&self) -> Reg {
self.regs[8] self.regs[8]
} }

View file

@ -19,6 +19,8 @@ use reverie::Stack;
use safeptrace::Error as TraceError; use safeptrace::Error as TraceError;
use safeptrace::Stopped; use safeptrace::Stopped;
use super::regs::RegAccess;
// NB: leaf function can use redzone without explicit stack allocation, as // NB: leaf function can use redzone without explicit stack allocation, as
// a result it is not safe to just adjust stack pointer. 128B of stack // a result it is not safe to just adjust stack pointer. 128B of stack
// space is mostly wasted -- to avoid the corner case when redzone is used. // space is mostly wasted -- to avoid the corner case when redzone is used.
@ -49,7 +51,7 @@ impl GuestStack {
); );
} }
let task = Stopped::new_unchecked(pid); let task = Stopped::new_unchecked(pid);
let rsp = task.getregs()?.rsp as usize; let rsp = task.getregs()?.stack_ptr() as usize;
let top = rsp - REDZONE_SIZE as usize; let top = rsp - REDZONE_SIZE as usize;
Ok(GuestStack { Ok(GuestStack {
top, top,