use uuid::Uuid;
use api::protocol::{Context, DebugImage, DeviceContext, OsContext, RuntimeContext};
use api::protocol::debugid::DebugId;
#[cfg(all(feature = "with_device_info", target_os = "macos"))]
mod model_support {
use std::ptr;
use libc;
use libc::c_void;
use regex::Regex;
lazy_static! {
static ref FAMILY_RE: Regex = Regex::new(r#"([a-zA-Z]+)\d"#).unwrap();
}
pub fn get_model() -> Option<String> {
unsafe {
let mut size = 0;
libc::sysctlbyname(
"hw.model\x00".as_ptr() as *const i8,
ptr::null_mut(),
&mut size,
ptr::null_mut(),
0,
);
let mut buf = vec![0u8; size as usize];
libc::sysctlbyname(
"hw.model\x00".as_ptr() as *const i8,
buf.as_mut_ptr() as *mut c_void,
&mut size,
ptr::null_mut(),
0,
);
Some(
String::from_utf8_lossy(match buf.ends_with(b"\x00") {
true => &buf[..size - 1],
false => &buf,
}).to_string(),
)
}
}
pub fn get_family() -> Option<String> {
get_model()
.as_ref()
.and_then(|model| FAMILY_RE.captures(model))
.and_then(|m| m.get(1))
.map(|group| group.as_str().to_string())
}
}
#[cfg(any(not(target_os = "macos"), not(feature = "with_device_info")))]
mod model_support {
pub fn get_model() -> Option<String> {
None
}
pub fn get_family() -> Option<String> {
None
}
}
#[cfg(feature = "with_debug_meta")]
mod findshlibs_support {
use super::*;
use api::protocol::SymbolicDebugImage;
use findshlibs::{Segment, SharedLibrary, SharedLibraryId, TargetSharedLibrary,
TARGET_SUPPORTED};
pub fn find_shlibs() -> Option<Vec<DebugImage>> {
if !TARGET_SUPPORTED {
return None;
}
let mut rv = vec![];
TargetSharedLibrary::each(|shlib| {
let debug_id = match shlib.id() {
Some(SharedLibraryId::Uuid(bytes)) => {
DebugId::from_uuid(Uuid::from_uuid_bytes(bytes))
}
None => return,
};
let mut lowest_addr = !0;
let mut lowest_vmaddr = !0;
let mut highest_addr = 0;
for seg in shlib.segments() {
let svma: u64 = seg.stated_virtual_memory_address().0 as u64;
let avma: u64 = seg.actual_virtual_memory_address(shlib).0 as u64;
if lowest_addr > avma {
lowest_addr = avma;
}
if highest_addr < avma {
highest_addr = avma;
}
if lowest_vmaddr > svma {
lowest_vmaddr = svma;
}
}
rv.push(
SymbolicDebugImage {
name: shlib.name().to_string_lossy().to_string(),
arch: None,
image_addr: lowest_addr.into(),
image_size: highest_addr - lowest_addr,
image_vmaddr: lowest_vmaddr.into(),
id: debug_id,
}.into(),
);
});
Some(rv)
}
}
#[cfg(not(feature = "with_debug_meta"))]
mod findshlibs_support {
use super::*;
pub fn find_shlibs() -> Option<Vec<DebugImage>> {
None
}
}
pub fn device_model() -> Option<String> {
model_support::get_model()
}
pub fn device_family() -> Option<String> {
model_support::get_family()
}
pub fn cpu_arch() -> Option<String> {
use constants::ARCH;
Some(ARCH.into())
}
pub fn server_name() -> Option<String> {
#[cfg(feature = "with_device_info")]
{
use hostname::get_hostname;
get_hostname()
}
#[cfg(not(feature = "with_device_info"))]
{
None
}
}
pub fn os_context() -> Option<Context> {
#[cfg(all(feature = "with_device_info", not(windows)))]
{
use uname::uname;
if let Ok(info) = uname() {
Some(
OsContext {
name: Some(info.sysname.into()),
kernel_version: Some(info.version.into()),
version: Some(info.release.into()),
..Default::default()
}.into(),
)
} else {
None
}
}
#[cfg(all(feature = "with_device_info", windows))]
{
use constants::PLATFORM;
Some(
OsContext {
name: Some(PLATFORM.into()),
..Default::default()
}.into(),
)
}
#[cfg(not(feature = "with_device_info"))]
{
None
}
}
pub fn rust_context() -> Option<Context> {
#[cfg(feature = "with_device_info")]
{
use constants::{RUSTC_CHANNEL, RUSTC_VERSION};
let mut ctx: Context = RuntimeContext {
name: Some("rustc".into()),
version: RUSTC_VERSION.map(|x| x.into()),
}.into();
if let Some(channel) = RUSTC_CHANNEL {
ctx.extra.insert("channel".into(), channel.into());
}
Some(ctx)
}
#[cfg(not(feature = "with_device_info"))]
{
None
}
}
pub fn device_context() -> Option<Context> {
#[cfg(feature = "with_device_info")]
{
let model = device_model();
let family = device_family();
let arch = cpu_arch();
Some(
DeviceContext {
model: model,
family: family,
arch: arch,
..Default::default()
}.into(),
)
}
#[cfg(not(feature = "with_device_info"))]
{
None
}
}
pub fn debug_images() -> Vec<DebugImage> {
findshlibs_support::find_shlibs().unwrap_or_else(|| Vec::new())
}
#[cfg(feature = "with_backtrace")]
pub use backtrace_support::{current_stacktrace, trim_stacktrace};