Skip to content

Commit 0c8136b

Browse files
VladimirMakaevfacebook-github-bot
authored andcommitted
decode & trace instructions while single-stepping
Summary: This adds an ability to decode an instruction on top of the safeptrace::Stopped task and enables debug! tracing when single-stepping. Note that performance overhead should not be present when higher tracing level is requested Reviewed By: jasonwhite Differential Revision: D40895393 fbshipit-source-id: 867f237a0517304314f4ac43313c1f26cee3f646
1 parent f33975a commit 0c8136b

File tree

4 files changed

+42
-0
lines changed

4 files changed

+42
-0
lines changed

reverie-ptrace/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ bincode = "1.3.3"
1414
bytes = { version = "1.1", features = ["serde"] }
1515
futures = { version = "0.3.22", features = ["async-await", "compat"] }
1616
goblin = "0.5.2"
17+
iced-x86 = "1.17.0"
1718
lazy_static = "1.4"
1819
libc = "0.2.137"
1920
nix = "0.25"

reverie-ptrace/src/decoder.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
//! Routines for tracing and decoding instructions to a particular architecture
10+
use iced_x86::Decoder;
11+
use iced_x86::DecoderOptions;
12+
use iced_x86::Formatter;
13+
use iced_x86::IntelFormatter;
14+
use reverie::syscalls::MemoryAccess;
15+
16+
use crate::regs::RegAccess;
17+
18+
/// Decodes an instruction on top of the rip
19+
pub fn decode_instruction(task: &safeptrace::Stopped) -> Result<String, safeptrace::Error> {
20+
let mut code = [0u8; 16];
21+
let regs = task.getregs()?;
22+
task.read_exact(regs.ip() as usize, &mut code)?;
23+
let mut decoder = Decoder::with_ip(64, &code, regs.ip(), DecoderOptions::NONE);
24+
let instruction = decoder.decode();
25+
let mut formatter = IntelFormatter::new();
26+
let mut output = String::new();
27+
formatter.format(&instruction, &mut output);
28+
Ok(output)
29+
}

reverie-ptrace/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ mod cp;
3939
#[allow(unused)]
4040
#[cfg(target_arch = "x86_64")]
4141
mod debug;
42+
#[cfg(target_arch = "x86_64")]
43+
pub mod decoder;
4244
mod error;
4345
mod gdbstub;
4446
mod perf;

reverie-ptrace/src/timer.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
3232
use reverie::Errno;
3333
use reverie::Pid;
34+
use reverie::RegDisplay;
35+
use reverie::RegDisplayOptions;
3436
use reverie::Signal;
3537
use reverie::Tid;
3638
use safeptrace::Error as TraceError;
@@ -39,6 +41,7 @@ use safeptrace::Stopped;
3941
use safeptrace::Wait;
4042
use thiserror::Error;
4143
use tracing::debug;
44+
use tracing::trace;
4245
use tracing::warn;
4346

4447
use crate::perf::*;
@@ -604,6 +607,13 @@ impl TimerImpl {
604607
if ctr >= target {
605608
break;
606609
}
610+
#[cfg(target_arch = "x86_64")]
611+
trace!(
612+
"[instruction]\n{}\n{}",
613+
crate::decoder::decode_instruction(&task)?,
614+
task.getregs()?
615+
.display_with_options(RegDisplayOptions { multiline: true })
616+
);
607617
task = match task.step(None)?.next_state().await? {
608618
// a successful single step results in SIGTRAP stop
609619
Wait::Stopped(new_task, TraceEvent::Signal(Signal::SIGTRAP)) => new_task,

0 commit comments

Comments
 (0)