mirror of
https://github.com/servo/servo.git
synced 2025-06-08 08:33:26 +00:00
99 lines
2.8 KiB
Rust
99 lines
2.8 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
|
|
use backtrace;
|
|
use msg::constellation_msg::{HangProfile, HangProfileSymbol};
|
|
use std::ptr;
|
|
|
|
const MAX_NATIVE_FRAMES: usize = 1024;
|
|
|
|
pub trait Sampler: Send {
|
|
fn suspend_and_sample_thread(&self) -> Result<NativeStack, ()>;
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub struct DummySampler;
|
|
|
|
impl DummySampler {
|
|
#[allow(dead_code)]
|
|
pub fn new() -> Box<dyn Sampler> {
|
|
Box::new(DummySampler)
|
|
}
|
|
}
|
|
|
|
impl Sampler for DummySampler {
|
|
fn suspend_and_sample_thread(&self) -> Result<NativeStack, ()> {
|
|
Err(())
|
|
}
|
|
}
|
|
|
|
// Several types in this file are currently not used in a Linux or Windows build.
|
|
#[allow(dead_code)]
|
|
pub type Address = *const libc::uint8_t;
|
|
|
|
/// The registers used for stack unwinding
|
|
#[allow(dead_code)]
|
|
pub struct Registers {
|
|
/// Instruction pointer.
|
|
pub instruction_ptr: Address,
|
|
/// Stack pointer.
|
|
pub stack_ptr: Address,
|
|
/// Frame pointer.
|
|
pub frame_ptr: Address,
|
|
}
|
|
|
|
pub struct NativeStack {
|
|
instruction_ptrs: [*mut std::ffi::c_void; MAX_NATIVE_FRAMES],
|
|
stack_ptrs: [*mut std::ffi::c_void; MAX_NATIVE_FRAMES],
|
|
count: usize,
|
|
}
|
|
|
|
impl NativeStack {
|
|
pub fn new() -> Self {
|
|
NativeStack {
|
|
instruction_ptrs: [ptr::null_mut(); MAX_NATIVE_FRAMES],
|
|
stack_ptrs: [ptr::null_mut(); MAX_NATIVE_FRAMES],
|
|
count: 0,
|
|
}
|
|
}
|
|
|
|
pub fn process_register(
|
|
&mut self,
|
|
instruction_ptr: *mut std::ffi::c_void,
|
|
stack_ptr: *mut std::ffi::c_void,
|
|
) -> Result<(), ()> {
|
|
if !(self.count < MAX_NATIVE_FRAMES) {
|
|
return Err(());
|
|
}
|
|
self.instruction_ptrs[self.count] = instruction_ptr;
|
|
self.stack_ptrs[self.count] = stack_ptr;
|
|
self.count = self.count + 1;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn to_hangprofile(&self) -> HangProfile {
|
|
let mut profile = HangProfile {
|
|
backtrace: Vec::new(),
|
|
};
|
|
for ip in self.instruction_ptrs.iter().rev() {
|
|
if ip.is_null() {
|
|
continue;
|
|
}
|
|
backtrace::resolve(*ip, |symbol| {
|
|
// TODO: use the demangled or C++ demangled symbols if available.
|
|
let name = symbol
|
|
.name()
|
|
.map(|n| String::from_utf8_lossy(&n.as_bytes()).to_string());
|
|
let filename = symbol.filename().map(|n| n.to_string_lossy().to_string());
|
|
let lineno = symbol.lineno();
|
|
profile.backtrace.push(HangProfileSymbol {
|
|
name,
|
|
filename,
|
|
lineno,
|
|
});
|
|
});
|
|
}
|
|
profile
|
|
}
|
|
}
|