diff options
| author | Konrad Borowski <konrad@borowski.pw> | 2018-12-23 16:47:11 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-12-23 16:47:11 +0100 |
| commit | 8ac5380ea0204dbdcbc8108d259928b67d5f8ebb (patch) | |
| tree | 174d912756fc2678af50d46ff457f7504750a975 /src/libstd/sys_common | |
| parent | b4a306c1e648c84f289c63e984941b7faad10af1 (diff) | |
| parent | ddab10a692aab2e2984b5c826ed9d78a57e94851 (diff) | |
| download | rust-8ac5380ea0204dbdcbc8108d259928b67d5f8ebb.tar.gz rust-8ac5380ea0204dbdcbc8108d259928b67d5f8ebb.zip | |
Merge branch 'master' into copied
Diffstat (limited to 'src/libstd/sys_common')
| -rw-r--r-- | src/libstd/sys_common/backtrace.rs | 239 | ||||
| -rw-r--r-- | src/libstd/sys_common/gnu/libbacktrace.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys_common/mod.rs | 8 | ||||
| -rw-r--r-- | src/libstd/sys_common/net.rs | 74 | ||||
| -rw-r--r-- | src/libstd/sys_common/util.rs | 7 | ||||
| -rw-r--r-- | src/libstd/sys_common/wtf8.rs | 2 |
6 files changed, 79 insertions, 253 deletions
diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 77371782977..e44113f76f4 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -14,11 +14,12 @@ use env; use io::prelude::*; use io; +use path::{self, Path}; +use ptr; +use rustc_demangle::demangle; use str; use sync::atomic::{self, Ordering}; -use path::{self, Path}; use sys::mutex::Mutex; -use ptr; pub use sys::backtrace::{ unwind_backtrace, @@ -191,7 +192,14 @@ fn output(w: &mut dyn Write, idx: usize, frame: Frame, PrintFormat::Short => write!(w, " {:2}: ", idx)?, } match s { - Some(string) => demangle(w, string, format)?, + Some(string) => { + let symbol = demangle(string); + match format { + PrintFormat::Full => write!(w, "{}", symbol)?, + // strip the trailing hash if short mode + PrintFormat::Short => write!(w, "{:#}", symbol)?, + } + } None => w.write_all(b"<unknown>")?, } w.write_all(b"\n") @@ -235,228 +243,3 @@ fn output_fileline(w: &mut dyn Write, w.write_all(b"\n") } - -// All rust symbols are in theory lists of "::"-separated identifiers. Some -// assemblers, however, can't handle these characters in symbol names. To get -// around this, we use C++-style mangling. The mangling method is: -// -// 1. Prefix the symbol with "_ZN" -// 2. For each element of the path, emit the length plus the element -// 3. End the path with "E" -// -// For example, "_ZN4testE" => "test" and "_ZN3foo3barE" => "foo::bar". -// -// We're the ones printing our backtraces, so we can't rely on anything else to -// demangle our symbols. It's *much* nicer to look at demangled symbols, so -// this function is implemented to give us nice pretty output. -// -// Note that this demangler isn't quite as fancy as it could be. We have lots -// of other information in our symbols like hashes, version, type information, -// etc. Additionally, this doesn't handle glue symbols at all. -pub fn demangle(writer: &mut dyn Write, mut s: &str, format: PrintFormat) -> io::Result<()> { - // During ThinLTO LLVM may import and rename internal symbols, so strip out - // those endings first as they're one of the last manglings applied to - // symbol names. - let llvm = ".llvm."; - if let Some(i) = s.find(llvm) { - let candidate = &s[i + llvm.len()..]; - let all_hex = candidate.chars().all(|c| { - match c { - 'A' ..= 'F' | '0' ..= '9' => true, - _ => false, - } - }); - - if all_hex { - s = &s[..i]; - } - } - - // Validate the symbol. If it doesn't look like anything we're - // expecting, we just print it literally. Note that we must handle non-rust - // symbols because we could have any function in the backtrace. - let mut valid = true; - let mut inner = s; - if s.len() > 4 && s.starts_with("_ZN") && s.ends_with("E") { - inner = &s[3 .. s.len() - 1]; - // On Windows, dbghelp strips leading underscores, so we accept "ZN...E" form too. - } else if s.len() > 3 && s.starts_with("ZN") && s.ends_with("E") { - inner = &s[2 .. s.len() - 1]; - } else { - valid = false; - } - - if valid { - let mut chars = inner.chars(); - while valid { - let mut i = 0; - for c in chars.by_ref() { - if c.is_numeric() { - i = i * 10 + c as usize - '0' as usize; - } else { - break - } - } - if i == 0 { - valid = chars.next().is_none(); - break - } else if chars.by_ref().take(i - 1).count() != i - 1 { - valid = false; - } - } - } - - // Alright, let's do this. - if !valid { - writer.write_all(s.as_bytes())?; - } else { - // remove the `::hfc2edb670e5eda97` part at the end of the symbol. - if format == PrintFormat::Short { - // The symbol in still mangled. - let mut split = inner.rsplitn(2, "17h"); - match (split.next(), split.next()) { - (Some(addr), rest) => { - if addr.len() == 16 && - addr.chars().all(|c| c.is_digit(16)) - { - inner = rest.unwrap_or(""); - } - } - _ => (), - } - } - - let mut first = true; - while !inner.is_empty() { - if !first { - writer.write_all(b"::")?; - } else { - first = false; - } - let mut rest = inner; - while rest.chars().next().unwrap().is_numeric() { - rest = &rest[1..]; - } - let i: usize = inner[.. (inner.len() - rest.len())].parse().unwrap(); - inner = &rest[i..]; - rest = &rest[..i]; - if rest.starts_with("_$") { - rest = &rest[1..]; - } - while !rest.is_empty() { - if rest.starts_with(".") { - if let Some('.') = rest[1..].chars().next() { - writer.write_all(b"::")?; - rest = &rest[2..]; - } else { - writer.write_all(b".")?; - rest = &rest[1..]; - } - } else if rest.starts_with("$") { - macro_rules! demangle { - ($($pat:expr => $demangled:expr),*) => ({ - $(if rest.starts_with($pat) { - writer.write_all($demangled)?; - rest = &rest[$pat.len()..]; - } else)* - { - writer.write_all(rest.as_bytes())?; - break; - } - - }) - } - - // see src/librustc/back/link.rs for these mappings - demangle! ( - "$SP$" => b"@", - "$BP$" => b"*", - "$RF$" => b"&", - "$LT$" => b"<", - "$GT$" => b">", - "$LP$" => b"(", - "$RP$" => b")", - "$C$" => b",", - - // in theory we can demangle any Unicode code point, but - // for simplicity we just catch the common ones. - "$u7e$" => b"~", - "$u20$" => b" ", - "$u27$" => b"'", - "$u5b$" => b"[", - "$u5d$" => b"]", - "$u7b$" => b"{", - "$u7d$" => b"}", - "$u3b$" => b";", - "$u2b$" => b"+", - "$u22$" => b"\"" - ) - } else { - let idx = match rest.char_indices().find(|&(_, c)| c == '$' || c == '.') { - None => rest.len(), - Some((i, _)) => i, - }; - writer.write_all(rest[..idx].as_bytes())?; - rest = &rest[idx..]; - } - } - } - } - - Ok(()) -} - -#[cfg(test)] -mod tests { - use sys_common; - macro_rules! t { ($a:expr, $b:expr) => ({ - let mut m = Vec::new(); - sys_common::backtrace::demangle(&mut m, - $a, - super::PrintFormat::Full).unwrap(); - assert_eq!(String::from_utf8(m).unwrap(), $b); - }) } - - #[test] - fn demangle() { - t!("test", "test"); - t!("_ZN4testE", "test"); - t!("_ZN4test", "_ZN4test"); - t!("_ZN4test1a2bcE", "test::a::bc"); - } - - #[test] - fn demangle_dollars() { - t!("_ZN4$RP$E", ")"); - t!("_ZN8$RF$testE", "&test"); - t!("_ZN8$BP$test4foobE", "*test::foob"); - t!("_ZN9$u20$test4foobE", " test::foob"); - t!("_ZN35Bar$LT$$u5b$u32$u3b$$u20$4$u5d$$GT$E", "Bar<[u32; 4]>"); - } - - #[test] - fn demangle_many_dollars() { - t!("_ZN13test$u20$test4foobE", "test test::foob"); - t!("_ZN12test$BP$test4foobE", "test*test::foob"); - } - - #[test] - fn demangle_windows() { - t!("ZN4testE", "test"); - t!("ZN13test$u20$test4foobE", "test test::foob"); - t!("ZN12test$RF$test4foobE", "test&test::foob"); - } - - #[test] - fn demangle_elements_beginning_with_underscore() { - t!("_ZN13_$LT$test$GT$E", "<test>"); - t!("_ZN28_$u7b$$u7b$closure$u7d$$u7d$E", "{{closure}}"); - t!("_ZN15__STATIC_FMTSTRE", "__STATIC_FMTSTR"); - } - - #[test] - fn demangle_trait_impls() { - t!("_ZN71_$LT$Test$u20$$u2b$$u20$$u27$static$u20$as$u20$foo..Bar$LT$Test$GT$$GT$3barE", - "<Test + 'static as foo::Bar<Test>>::bar"); - } -} diff --git a/src/libstd/sys_common/gnu/libbacktrace.rs b/src/libstd/sys_common/gnu/libbacktrace.rs index 6ad3af6aee1..c2589d477ee 100644 --- a/src/libstd/sys_common/gnu/libbacktrace.rs +++ b/src/libstd/sys_common/gnu/libbacktrace.rs @@ -23,7 +23,7 @@ pub fn foreach_symbol_fileline<F>(frame: Frame, where F: FnMut(&[u8], u32) -> io::Result<()> { // pcinfo may return an arbitrary number of file:line pairs, - // in the order of stack trace (i.e. inlined calls first). + // in the order of stack trace (i.e., inlined calls first). // in order to avoid allocation, we stack-allocate a fixed size of entries. const FILELINE_SIZE: usize = 32; let mut fileline_buf = [(ptr::null(), !0); FILELINE_SIZE]; diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index 4b8cde3d1f4..881794d9f16 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -57,9 +57,11 @@ pub mod bytestring; pub mod process; cfg_if! { - if #[cfg(any(target_os = "cloudabi", target_os = "l4re", target_os = "redox"))] { - pub use sys::net; - } else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] { + if #[cfg(any(target_os = "cloudabi", + target_os = "l4re", + target_os = "redox", + all(target_arch = "wasm32", not(target_os = "emscripten")), + target_env = "sgx"))] { pub use sys::net; } else { pub mod net; diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs index d09a233ed89..dce2bf71cec 100644 --- a/src/libstd/sys_common/net.rs +++ b/src/libstd/sys_common/net.rs @@ -20,6 +20,7 @@ use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t}; use sys::net::netc as c; use sys_common::{AsInner, FromInner, IntoInner}; use time::Duration; +use convert::{TryFrom, TryInto}; #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", @@ -129,6 +130,13 @@ fn to_ipv6mr_interface(value: u32) -> ::libc::c_uint { pub struct LookupHost { original: *mut c::addrinfo, cur: *mut c::addrinfo, + port: u16 +} + +impl LookupHost { + pub fn port(&self) -> u16 { + self.port + } } impl Iterator for LookupHost { @@ -158,17 +166,45 @@ impl Drop for LookupHost { } } -pub fn lookup_host(host: &str) -> io::Result<LookupHost> { - init(); +impl<'a> TryFrom<&'a str> for LookupHost { + type Error = io::Error; - let c_host = CString::new(host)?; - let mut hints: c::addrinfo = unsafe { mem::zeroed() }; - hints.ai_socktype = c::SOCK_STREAM; - let mut res = ptr::null_mut(); - unsafe { - cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res)).map(|_| { - LookupHost { original: res, cur: res } - }) + fn try_from(s: &str) -> io::Result<LookupHost> { + macro_rules! try_opt { + ($e:expr, $msg:expr) => ( + match $e { + Some(r) => r, + None => return Err(io::Error::new(io::ErrorKind::InvalidInput, + $msg)), + } + ) + } + + // split the string by ':' and convert the second part to u16 + let mut parts_iter = s.rsplitn(2, ':'); + let port_str = try_opt!(parts_iter.next(), "invalid socket address"); + let host = try_opt!(parts_iter.next(), "invalid socket address"); + let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value"); + + (host, port).try_into() + } +} + +impl<'a> TryFrom<(&'a str, u16)> for LookupHost { + type Error = io::Error; + + fn try_from((host, port): (&'a str, u16)) -> io::Result<LookupHost> { + init(); + + let c_host = CString::new(host)?; + let mut hints: c::addrinfo = unsafe { mem::zeroed() }; + hints.ai_socktype = c::SOCK_STREAM; + let mut res = ptr::null_mut(); + unsafe { + cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res)).map(|_| { + LookupHost { original: res, cur: res, port } + }) + } } } @@ -181,7 +217,9 @@ pub struct TcpStream { } impl TcpStream { - pub fn connect(addr: &SocketAddr) -> io::Result<TcpStream> { + pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> { + let addr = addr?; + init(); let sock = Socket::new(addr, c::SOCK_STREAM)?; @@ -317,7 +355,9 @@ pub struct TcpListener { } impl TcpListener { - pub fn bind(addr: &SocketAddr) -> io::Result<TcpListener> { + pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> { + let addr = addr?; + init(); let sock = Socket::new(addr, c::SOCK_STREAM)?; @@ -418,7 +458,9 @@ pub struct UdpSocket { } impl UdpSocket { - pub fn bind(addr: &SocketAddr) -> io::Result<UdpSocket> { + pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<UdpSocket> { + let addr = addr?; + init(); let sock = Socket::new(addr, c::SOCK_DGRAM)?; @@ -584,8 +626,8 @@ impl UdpSocket { Ok(ret as usize) } - pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { - let (addrp, len) = addr.into_inner(); + pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> { + let (addrp, len) = addr?.into_inner(); cvt_r(|| unsafe { c::connect(*self.inner.as_inner(), addrp, len) }).map(|_| ()) } } @@ -618,7 +660,7 @@ mod tests { #[test] fn no_lookup_host_duplicates() { let mut addrs = HashMap::new(); - let lh = match lookup_host("localhost") { + let lh = match LookupHost::try_from(("localhost", 0)) { Ok(lh) => lh, Err(e) => panic!("couldn't resolve `localhost': {}", e) }; diff --git a/src/libstd/sys_common/util.rs b/src/libstd/sys_common/util.rs index a373e980b97..fc86a59d17f 100644 --- a/src/libstd/sys_common/util.rs +++ b/src/libstd/sys_common/util.rs @@ -10,14 +10,13 @@ use fmt; use io::prelude::*; -use sys::stdio::{Stderr, stderr_prints_nothing}; +use sys::stdio::panic_output; use thread; pub fn dumb_print(args: fmt::Arguments) { - if stderr_prints_nothing() { - return + if let Some(mut out) = panic_output() { + let _ = out.write_fmt(args); } - let _ = Stderr::new().map(|mut stderr| stderr.write_fmt(args)); } // Other platforms should use the appropriate platform-specific mechanism for diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 19ce932aa12..3530b7af9ad 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -40,7 +40,7 @@ use str; use sync::Arc; use sys_common::AsInner; -const UTF8_REPLACEMENT_CHARACTER: &'static str = "\u{FFFD}"; +const UTF8_REPLACEMENT_CHARACTER: &str = "\u{FFFD}"; /// A Unicode code point: from U+0000 to U+10FFFF. /// |
