Skip to content
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
2 changes: 1 addition & 1 deletion elfcore-sample/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ elfcore = { path = "../elfcore" }

anyhow.workspace = true
tracing.workspace = true
tracing-subscriber.workspace = true
tracing-subscriber.workspace = true
17 changes: 13 additions & 4 deletions elfcore-sample/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,20 @@
//! debug level tracing.
//!

#![cfg(target_os = "linux")]

#[cfg(target_os = "linux")]
use anyhow::Context;
#[cfg(target_os = "linux")]
use elfcore::{CoreDumpBuilder, LinuxProcessMemoryReader, ProcessView};
#[cfg(target_os = "linux")]
use std::path::PathBuf;
#[cfg(target_os = "linux")]
use tracing::Level;

#[cfg(target_os = "linux")]
pub fn main() -> anyhow::Result<()> {
let mut args = std::env::args().skip(1).peekable();

let level = if args.peek().map_or(false, |x| x == "-v") {
let level = if args.peek().is_some_and(|x| x == "-v") {
args.next();
Level::DEBUG
} else {
Expand Down Expand Up @@ -53,7 +57,7 @@ pub fn main() -> anyhow::Result<()> {
.with_max_level(level)
.init();

let mut builder = elfcore::CoreDumpBuilder::new(pid)?;
let mut builder = CoreDumpBuilder::<ProcessView, LinuxProcessMemoryReader>::new(pid)?;

let mut file = note_file_path
.map(|path| {
Expand All @@ -72,3 +76,8 @@ pub fn main() -> anyhow::Result<()> {
tracing::debug!("wrote {} bytes", n);
Ok(())
}

#[cfg(not(target_os = "linux"))]
pub fn main() {
println!("Creating core dumps for a given Pid is only supported on Linux");
}
8 changes: 4 additions & 4 deletions elfcore/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ keywords = ["elf", "coredump", "debugging"]
categories = ["development-tools::debugging", "os::linux-apis"]

[dependencies]

[target.'cfg(unix)'.dependencies]
libc.workspace = true
nix.workspace = true
smallvec.workspace = true
thiserror.workspace = true
tracing.workspace = true
zerocopy.workspace = true

[target.'cfg(unix)'.dependencies]
libc.workspace = true
nix.workspace = true
12 changes: 10 additions & 2 deletions elfcore/src/arch/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@
#![cfg(target_arch = "aarch64")]

use super::ArchComponentState;
use crate::ptrace::ptrace_get_reg_set;
use crate::CoreError;
use nix::unistd::Pid;
use zerocopy::AsBytes;

#[cfg(target_os = "linux")]
use crate::ptrace::ptrace_get_reg_set;
#[cfg(target_os = "linux")]
use nix::unistd::Pid;

// aarch64 machine
pub const EM_AARCH64: u16 = 183;

Expand All @@ -29,19 +32,24 @@ pub struct elf_gregset_t {
pub pstate: u64,
}

#[cfg(target_os = "linux")]
pub fn get_aarch64_tls(pid: Pid) -> Result<Vec<u8>, CoreError> {
ptrace_get_reg_set(pid, NT_ARM_TLS)
}
#[cfg(target_os = "linux")]
pub fn get_aarch64_hw_break(pid: Pid) -> Result<Vec<u8>, CoreError> {
ptrace_get_reg_set(pid, NT_ARM_HW_BREAK)
}
#[cfg(target_os = "linux")]
pub fn get_aarch64_hw_watch(pid: Pid) -> Result<Vec<u8>, CoreError> {
ptrace_get_reg_set(pid, NT_ARM_HW_WATCH)
}
#[cfg(target_os = "linux")]
pub fn get_aarch64_system_call(pid: Pid) -> Result<Vec<u8>, CoreError> {
ptrace_get_reg_set(pid, NT_ARM_SYSTEM_CALL)
}

#[cfg(target_os = "linux")]
pub fn get_arch_components(pid: Pid) -> Result<Vec<ArchComponentState>, CoreError> {
let components = vec![
ArchComponentState {
Expand Down
31 changes: 21 additions & 10 deletions elfcore/src/arch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@

//! A Rust helper library with machine-specific code for ELF core dump files.

use crate::elf::NT_PRFPREG;
#[cfg(target_os = "linux")]
use super::linux::ptrace;
#[cfg(target_os = "linux")]
use crate::{elf::NT_PRFPREG, CoreError};
#[cfg(target_os = "linux")]
use nix::unistd::Pid;

use super::ptrace;
use crate::CoreError;

#[cfg(target_arch = "x86_64")]
mod x86_64;
#[cfg(target_arch = "x86_64")]
Expand All @@ -19,31 +20,40 @@ mod aarch64;
#[cfg(target_arch = "aarch64")]
pub use aarch64::elf_gregset_t;

/// Contains SSE registers on amd64, NEON on arm64,
/// XSAVE state on amd64, etc
#[derive(Debug)]
pub struct ArchComponentState {
/// Name
pub name: &'static str,
/// Note type
pub note_type: u32,
/// Note name
pub note_name: &'static [u8],
/// Data
pub data: Vec<u8>,
}

pub trait Arch {
pub(crate) trait Arch {
const EM_ELF_MACHINE: u16;

#[cfg(target_os = "linux")]
fn new(pid: Pid) -> Result<Box<Self>, CoreError>;
#[allow(dead_code)]
fn name() -> &'static str;
fn greg_set(&self) -> elf_gregset_t;
fn components(&self) -> &Vec<ArchComponentState>;
}

/// Describes CPU state
#[derive(Debug)]
pub struct ArchState {
// GP registers.
gpr_state: Vec<u64>,
/// GP registers.
pub gpr_state: Vec<u64>,

// Contains SSE registers on amd64, NEON on arm64,
// XSAVE state on amd64, etc
components: Vec<ArchComponentState>,
/// Contains SSE registers on amd64, NEON on arm64,
/// XSAVE state on amd64, etc
pub components: Vec<ArchComponentState>,
}

impl Arch for ArchState {
Expand All @@ -52,6 +62,7 @@ impl Arch for ArchState {
#[cfg(target_arch = "aarch64")]
const EM_ELF_MACHINE: u16 = aarch64::EM_AARCH64;

#[cfg(target_os = "linux")]
fn new(pid: Pid) -> Result<Box<Self>, CoreError> {
tracing::debug!("Getting GP registers for #{pid}");
let gpr_state = ptrace::get_gp_reg_set(pid)?;
Expand Down
11 changes: 8 additions & 3 deletions elfcore/src/arch/x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@

//! x86_64 specifics for ELF core dump files.

#![cfg(target_arch = "x86_64")]

#[cfg(target_os = "linux")]
use super::ArchComponentState;
use crate::ptrace::ptrace_get_reg_set;
#[cfg(target_os = "linux")]
use crate::linux::ptrace::ptrace_get_reg_set;
#[cfg(target_os = "linux")]
use crate::CoreError;
#[cfg(target_os = "linux")]
use nix::unistd::Pid;
use zerocopy::AsBytes;

// amd64 machine
pub const EM_X86_64: u16 = 62;

// amd64 notes
#[cfg(target_os = "linux")]
pub const NT_X86_XSTATE: u32 = 0x202;

#[repr(C, packed)]
Expand Down Expand Up @@ -52,10 +55,12 @@ pub struct elf_gregset_t {
//const AT_SYSINFO_X86: u64 = 32;
//const AT_SYSINFO_EHDR_X86: u64 = 33; returns vdso

#[cfg(target_os = "linux")]
pub fn get_x86_xsave_set(pid: Pid) -> Result<Vec<u8>, CoreError> {
ptrace_get_reg_set(pid, NT_X86_XSTATE)
}

#[cfg(target_os = "linux")]
pub fn get_arch_components(pid: Pid) -> Result<Vec<ArchComponentState>, CoreError> {
let components = vec![ArchComponentState {
name: "XSAVE",
Expand Down
Loading