Initial vendor packages

Signed-off-by: Valentin Popov <valentin@popov.link>
This commit is contained in:
2024-01-08 01:21:28 +04:00
parent 5ecd8cf2cb
commit 1b6a04ca55
7309 changed files with 2160054 additions and 0 deletions

View File

@ -0,0 +1,15 @@
#[inline(never)]
pub fn callback<F>(f: F)
where
F: FnOnce((&'static str, u32)),
{
f((file!(), line!()))
}
#[inline(always)]
pub fn callback_inlined<F>(f: F)
where
F: FnOnce((&'static str, u32)),
{
f((file!(), line!()))
}

117
vendor/backtrace/tests/accuracy/main.rs vendored Normal file
View File

@ -0,0 +1,117 @@
mod auxiliary;
macro_rules! pos {
() => {
(file!(), line!())
};
}
macro_rules! check {
($($pos:expr),*) => ({
verify(&[$($pos,)* pos!()]);
})
}
type Pos = (&'static str, u32);
#[test]
fn doit() {
if
// Skip musl which is by default statically linked and doesn't support
// dynamic libraries.
!cfg!(target_env = "musl")
// Skip Miri, since it doesn't support dynamic libraries.
&& !cfg!(miri)
{
// TODO(#238) this shouldn't have to happen first in this function, but
// currently it does.
let mut dir = std::env::current_exe().unwrap();
dir.pop();
if cfg!(windows) {
dir.push("dylib_dep.dll");
} else if cfg!(target_os = "macos") {
dir.push("libdylib_dep.dylib");
} else {
dir.push("libdylib_dep.so");
}
unsafe {
let lib = libloading::Library::new(&dir).unwrap();
let api = lib.get::<extern "C" fn(Pos, fn(Pos, Pos))>(b"foo").unwrap();
api(pos!(), |a, b| {
check!(a, b);
});
}
}
outer(pos!());
}
#[inline(never)]
fn outer(main_pos: Pos) {
inner(main_pos, pos!());
inner_inlined(main_pos, pos!());
}
#[inline(never)]
#[rustfmt::skip]
fn inner(main_pos: Pos, outer_pos: Pos) {
check!(main_pos, outer_pos);
check!(main_pos, outer_pos);
let inner_pos = pos!(); auxiliary::callback(|aux_pos| {
check!(main_pos, outer_pos, inner_pos, aux_pos);
});
let inner_pos = pos!(); auxiliary::callback_inlined(|aux_pos| {
check!(main_pos, outer_pos, inner_pos, aux_pos);
});
}
#[inline(always)]
#[rustfmt::skip]
fn inner_inlined(main_pos: Pos, outer_pos: Pos) {
check!(main_pos, outer_pos);
check!(main_pos, outer_pos);
#[inline(always)]
fn inner_further_inlined(main_pos: Pos, outer_pos: Pos, inner_pos: Pos) {
check!(main_pos, outer_pos, inner_pos);
}
inner_further_inlined(main_pos, outer_pos, pos!());
let inner_pos = pos!(); auxiliary::callback(|aux_pos| {
check!(main_pos, outer_pos, inner_pos, aux_pos);
});
let inner_pos = pos!(); auxiliary::callback_inlined(|aux_pos| {
check!(main_pos, outer_pos, inner_pos, aux_pos);
});
// this tests a distinction between two independent calls to the inlined function.
// (un)fortunately, LLVM somehow merges two consecutive such calls into one node.
inner_further_inlined(main_pos, outer_pos, pos!());
}
fn verify(filelines: &[Pos]) {
let trace = backtrace::Backtrace::new();
println!("-----------------------------------");
println!("looking for:");
for (file, line) in filelines.iter().rev() {
println!("\t{}:{}", file, line);
}
println!("found:\n{:?}", trace);
let mut symbols = trace.frames().iter().flat_map(|frame| frame.symbols());
let mut iter = filelines.iter().rev();
while let Some((file, line)) = iter.next() {
loop {
let sym = match symbols.next() {
Some(sym) => sym,
None => panic!("failed to find {}:{}", file, line),
};
if let Some(filename) = sym.filename() {
if let Some(lineno) = sym.lineno() {
if filename.ends_with(file) && lineno == *line {
break;
}
}
}
}
}
}

14
vendor/backtrace/tests/common/mod.rs vendored Normal file
View File

@ -0,0 +1,14 @@
/// Some tests only make sense in contexts where they can re-exec the test
/// itself. Not all contexts support this, so you can call this method to find
/// out which case you are in.
pub fn cannot_reexec_the_test() -> bool {
// These run in docker containers on CI where they can't re-exec the test,
// so just skip these for CI. No other reason this can't run on those
// platforms though.
// Miri does not have support for re-execing a file
cfg!(unix)
&& (cfg!(target_arch = "arm")
|| cfg!(target_arch = "aarch64")
|| cfg!(target_arch = "s390x"))
|| cfg!(miri)
}

View File

@ -0,0 +1,72 @@
use std::env;
use std::panic;
use std::process::Command;
use std::sync::atomic::{AtomicBool, Ordering::SeqCst};
use std::sync::Arc;
use std::thread;
const PANICS: usize = 100;
const THREADS: usize = 8;
const VAR: &str = "__THE_TEST_YOU_ARE_LUKE";
mod common;
fn main() {
// If we cannot re-exec this test, there's no point in trying to do it.
if common::cannot_reexec_the_test() {
println!("test result: ok");
return;
}
if env::var(VAR).is_err() {
parent();
} else {
child();
}
}
fn parent() {
let me = env::current_exe().unwrap();
let result = Command::new(&me)
.env("RUST_BACKTRACE", "1")
.env(VAR, "1")
.output()
.unwrap();
if result.status.success() {
println!("test result: ok");
return;
}
println!("stdout:\n{}", String::from_utf8_lossy(&result.stdout));
println!("stderr:\n{}", String::from_utf8_lossy(&result.stderr));
println!("code: {}", result.status);
panic!();
}
fn child() {
let done = Arc::new(AtomicBool::new(false));
let done2 = done.clone();
let a = thread::spawn(move || {
while !done2.load(SeqCst) {
format!("{:?}", backtrace::Backtrace::new());
}
});
let threads = (0..THREADS)
.map(|_| {
thread::spawn(|| {
for _ in 0..PANICS {
assert!(panic::catch_unwind(|| {
panic!();
})
.is_err());
}
})
})
.collect::<Vec<_>>();
for thread in threads {
thread.join().unwrap();
}
done.store(true, SeqCst);
a.join().unwrap();
}

View File

@ -0,0 +1,134 @@
// rust-lang/rust#101913: when you run your program explicitly via `ld.so`,
// `std::env::current_exe` will return the path of *that* program, and not
// the Rust program itself.
use std::io::{BufRead, BufReader};
use std::path::{Path, PathBuf};
use std::process::Command;
mod common;
fn main() {
if std::env::var(VAR).is_err() {
// the parent waits for the child; then we then handle either printing
// "test result: ok", "test result: ignored", or panicking.
match parent() {
Ok(()) => {
println!("test result: ok");
}
Err(EarlyExit::IgnoreTest(_)) => {
println!("test result: ignored");
}
Err(EarlyExit::IoError(e)) => {
println!("{} parent encoutered IoError: {:?}", file!(), e);
panic!();
}
}
} else {
// println!("{} running child", file!());
child().unwrap();
}
}
const VAR: &str = "__THE_TEST_YOU_ARE_LUKE";
#[derive(Debug)]
enum EarlyExit {
IgnoreTest(String),
IoError(std::io::Error),
}
impl From<std::io::Error> for EarlyExit {
fn from(e: std::io::Error) -> Self {
EarlyExit::IoError(e)
}
}
fn parent() -> Result<(), EarlyExit> {
// If we cannot re-exec this test, there's no point in trying to do it.
if common::cannot_reexec_the_test() {
return Err(EarlyExit::IgnoreTest("(cannot reexec)".into()));
}
let me = std::env::current_exe().unwrap();
let ld_so = find_interpreter(&me)?;
// use interp to invoke current exe, yielding child test.
//
// (if you're curious what you might compare this against, you can try
// swapping in the below definition for `result`, which is the easy case of
// not using the ld.so interpreter directly that Rust handled fine even
// prior to resolution of rust-lang/rust#101913.)
//
// let result = Command::new(me).env(VAR, "1").output()?;
let result = Command::new(ld_so).env(VAR, "1").arg(&me).output().unwrap();
if result.status.success() {
return Ok(());
}
println!("stdout:\n{}", String::from_utf8_lossy(&result.stdout));
println!("stderr:\n{}", String::from_utf8_lossy(&result.stderr));
println!("code: {}", result.status);
panic!();
}
fn child() -> Result<(), EarlyExit> {
let bt = backtrace::Backtrace::new();
println!("{:?}", bt);
let mut found_my_name = false;
let my_filename = file!();
'frames: for frame in bt.frames() {
let symbols = frame.symbols();
if symbols.is_empty() {
continue;
}
for sym in symbols {
if let Some(filename) = sym.filename() {
if filename.ends_with(my_filename) {
// huzzah!
found_my_name = true;
break 'frames;
}
}
}
}
assert!(found_my_name);
Ok(())
}
// we use the `readelf` command to extract the path to the interpreter requested
// by our binary.
//
// if we cannot `readelf` for some reason, or if we fail to parse its output,
// then we will just give up on this test (and not treat it as a test failure).
fn find_interpreter(me: &Path) -> Result<PathBuf, EarlyExit> {
let result = Command::new("readelf")
.arg("-l")
.arg(me)
.output()
.map_err(|_err| EarlyExit::IgnoreTest("readelf invocation failed".into()))?;
if result.status.success() {
let r = BufReader::new(&result.stdout[..]);
for line in r.lines() {
let line = line?;
let line = line.trim();
let prefix = "[Requesting program interpreter: ";
if let Some((_, suffix)) = line.split_once(prefix) {
if let Some((found_path, _)) = suffix.rsplit_once("]") {
return Ok(found_path.into());
}
}
}
Err(EarlyExit::IgnoreTest(
"could not find interpreter from readelf output".into(),
))
} else {
Err(EarlyExit::IgnoreTest("readelf returned non-success".into()))
}
}

48
vendor/backtrace/tests/long_fn_name.rs vendored Normal file
View File

@ -0,0 +1,48 @@
use backtrace::Backtrace;
// 50-character module name
mod _234567890_234567890_234567890_234567890_234567890 {
// 50-character struct name
#[allow(non_camel_case_types)]
pub struct _234567890_234567890_234567890_234567890_234567890<T>(T);
impl<T> _234567890_234567890_234567890_234567890_234567890<T> {
#[allow(dead_code)]
pub fn new() -> crate::Backtrace {
crate::Backtrace::new()
}
}
}
// Long function names must be truncated to (MAX_SYM_NAME - 1) characters.
// Only run this test for msvc, since gnu prints "<no info>" for all frames.
#[test]
#[cfg(all(windows, target_env = "msvc"))]
fn test_long_fn_name() {
use _234567890_234567890_234567890_234567890_234567890::_234567890_234567890_234567890_234567890_234567890 as S;
// 10 repetitions of struct name, so fully qualified function name is
// atleast 10 * (50 + 50) * 2 = 2000 characters long.
// It's actually longer since it also includes `::`, `<>` and the
// name of the current module
let bt = S::<S<S<S<S<S<S<S<S<S<i32>>>>>>>>>>::new();
println!("{:?}", bt);
let mut found_long_name_frame = false;
for frame in bt.frames() {
let symbols = frame.symbols();
if symbols.is_empty() {
continue;
}
if let Some(function_name) = symbols[0].name() {
let function_name = function_name.as_str().unwrap();
if function_name.contains("::_234567890_234567890_234567890_234567890_234567890") {
found_long_name_frame = true;
assert!(function_name.len() > 200);
}
}
}
assert!(found_long_name_frame);
}

View File

@ -0,0 +1,44 @@
use backtrace::Backtrace;
// This test only works on platforms which have a working `symbol_address`
// function for frames which reports the starting address of a symbol. As a
// result it's only enabled on a few platforms.
const ENABLED: bool = cfg!(all(
// Windows hasn't really been tested, and macOS doesn't support actually
// finding an enclosing frame, so disable this
target_os = "linux",
// On ARM finding the enclosing function is simply returning the ip itself.
not(target_arch = "arm"),
));
#[test]
fn backtrace_new_unresolved_should_start_with_call_site_trace() {
if !ENABLED {
return;
}
let mut b = Backtrace::new_unresolved();
b.resolve();
println!("{:?}", b);
assert!(!b.frames().is_empty());
let this_ip = backtrace_new_unresolved_should_start_with_call_site_trace as usize;
println!("this_ip: {:?}", this_ip as *const usize);
let frame_ip = b.frames().first().unwrap().symbol_address() as usize;
assert_eq!(this_ip, frame_ip);
}
#[test]
fn backtrace_new_should_start_with_call_site_trace() {
if !ENABLED {
return;
}
let b = Backtrace::new();
println!("{:?}", b);
assert!(!b.frames().is_empty());
let this_ip = backtrace_new_should_start_with_call_site_trace as usize;
let frame_ip = b.frames().first().unwrap().symbol_address() as usize;
assert_eq!(this_ip, frame_ip);
}

323
vendor/backtrace/tests/smoke.rs vendored Normal file
View File

@ -0,0 +1,323 @@
use backtrace::Frame;
use std::thread;
#[test]
// FIXME: shouldn't ignore this test on i686-msvc, unsure why it's failing
#[cfg_attr(all(target_arch = "x86", target_env = "msvc"), ignore)]
#[rustfmt::skip] // we care about line numbers here
fn smoke_test_frames() {
frame_1(line!());
#[inline(never)] fn frame_1(start_line: u32) { frame_2(start_line) }
#[inline(never)] fn frame_2(start_line: u32) { frame_3(start_line) }
#[inline(never)] fn frame_3(start_line: u32) { frame_4(start_line) }
#[inline(never)] fn frame_4(start_line: u32) {
let mut v = Vec::new();
backtrace::trace(|cx| {
v.push(cx.clone());
true
});
// Various platforms have various bits of weirdness about their
// backtraces. To find a good starting spot let's search through the
// frames
let target = frame_4 as usize;
let offset = v
.iter()
.map(|frame| frame.symbol_address() as usize)
.enumerate()
.filter_map(|(i, sym)| {
if sym >= target {
Some((sym, i))
} else {
None
}
})
.min()
.unwrap()
.1;
let mut frames = v[offset..].iter();
assert_frame(
frames.next().unwrap(),
frame_4 as usize,
"frame_4",
"tests/smoke.rs",
start_line + 6,
9,
);
assert_frame(
frames.next().unwrap(),
frame_3 as usize,
"frame_3",
"tests/smoke.rs",
start_line + 3,
52,
);
assert_frame(
frames.next().unwrap(),
frame_2 as usize,
"frame_2",
"tests/smoke.rs",
start_line + 2,
52,
);
assert_frame(
frames.next().unwrap(),
frame_1 as usize,
"frame_1",
"tests/smoke.rs",
start_line + 1,
52,
);
assert_frame(
frames.next().unwrap(),
smoke_test_frames as usize,
"smoke_test_frames",
"",
0,
0,
);
}
fn assert_frame(
frame: &Frame,
actual_fn_pointer: usize,
expected_name: &str,
expected_file: &str,
expected_line: u32,
expected_col: u32,
) {
backtrace::resolve_frame(frame, |sym| {
print!("symbol ip:{:?} address:{:?} ", frame.ip(), frame.symbol_address());
if let Some(name) = sym.name() {
print!("name:{} ", name);
}
if let Some(file) = sym.filename() {
print!("file:{} ", file.display());
}
if let Some(lineno) = sym.lineno() {
print!("lineno:{} ", lineno);
}
if let Some(colno) = sym.colno() {
print!("colno:{} ", colno);
}
println!();
});
let ip = frame.ip() as usize;
let sym = frame.symbol_address() as usize;
assert!(ip >= sym);
assert!(
sym >= actual_fn_pointer,
"{:?} < {:?} ({} {}:{}:{})",
sym as *const usize,
actual_fn_pointer as *const usize,
expected_name,
expected_file,
expected_line,
expected_col,
);
// windows dbghelp is *quite* liberal (and wrong) in many of its reports
// right now...
//
// This assertion can also fail for release builds, so skip it there
if cfg!(debug_assertions) {
assert!(sym - actual_fn_pointer < 1024);
}
let mut resolved = 0;
let mut name = None;
let mut addr = None;
let mut col = None;
let mut line = None;
let mut file = None;
backtrace::resolve_frame(frame, |sym| {
resolved += 1;
name = sym.name().map(|v| v.to_string());
addr = sym.addr();
col = sym.colno();
line = sym.lineno();
file = sym.filename().map(|v| v.to_path_buf());
});
assert!(resolved > 0);
let name = name.expect("didn't find a name");
// in release mode names get weird as functions can get merged
// together with `mergefunc`, so only assert this in debug mode
if cfg!(debug_assertions) {
assert!(
name.contains(expected_name),
"didn't find `{}` in `{}`",
expected_name,
name
);
}
addr.expect("didn't find a symbol");
if cfg!(debug_assertions) {
let line = line.expect("didn't find a line number");
let file = file.expect("didn't find a line number");
if !expected_file.is_empty() {
assert!(
file.ends_with(expected_file),
"{:?} didn't end with {:?}",
file,
expected_file
);
}
if expected_line != 0 {
assert!(
line == expected_line,
"bad line number on frame for `{}`: {} != {}",
expected_name,
line,
expected_line
);
}
// dbghelp on MSVC doesn't support column numbers
if !cfg!(target_env = "msvc") {
let col = col.expect("didn't find a column number");
if expected_col != 0 {
assert!(
col == expected_col,
"bad column number on frame for `{}`: {} != {}",
expected_name,
col,
expected_col
);
}
}
}
}
}
#[test]
fn many_threads() {
let threads = (0..16)
.map(|_| {
thread::spawn(|| {
for _ in 0..16 {
backtrace::trace(|frame| {
backtrace::resolve(frame.ip(), |symbol| {
let _s = symbol.name().map(|s| s.to_string());
});
true
});
}
})
})
.collect::<Vec<_>>();
for t in threads {
t.join().unwrap()
}
}
#[test]
#[cfg(feature = "rustc-serialize")]
fn is_rustc_serialize() {
extern crate rustc_serialize;
fn is_encode<T: rustc_serialize::Encodable>() {}
fn is_decode<T: rustc_serialize::Decodable>() {}
is_encode::<backtrace::Backtrace>();
is_decode::<backtrace::Backtrace>();
}
#[test]
#[cfg(feature = "serde")]
fn is_serde() {
extern crate serde;
fn is_serialize<T: serde::ser::Serialize>() {}
fn is_deserialize<T: serde::de::DeserializeOwned>() {}
is_serialize::<backtrace::Backtrace>();
is_deserialize::<backtrace::Backtrace>();
}
#[test]
fn sp_smoke_test() {
let mut refs = vec![];
recursive_stack_references(&mut refs);
return;
#[inline(never)]
fn recursive_stack_references(refs: &mut Vec<usize>) {
assert!(refs.len() < 5);
let x = refs.len();
refs.push(&x as *const _ as usize);
if refs.len() < 5 {
recursive_stack_references(refs);
eprintln!("exiting: {}", x);
return;
}
backtrace::trace(make_trace_closure(refs));
eprintln!("exiting: {}", x);
}
// NB: the following `make_*` functions are pulled out of line, rather than
// defining their results as inline closures at their call sites, so that
// the resulting closures don't have "recursive_stack_references" in their
// mangled names.
fn make_trace_closure<'a>(
refs: &'a mut Vec<usize>,
) -> impl FnMut(&backtrace::Frame) -> bool + 'a {
let mut child_sp = None;
let mut child_ref = None;
move |frame| {
eprintln!("\n=== frame ===================================");
let mut is_recursive_stack_references = false;
backtrace::resolve(frame.ip(), |sym| {
is_recursive_stack_references |=
sym.name()
.and_then(|name| name.as_str())
.map_or(false, |name| {
eprintln!("name = {}", name);
name.contains("recursive_stack_references")
})
});
let sp = frame.sp() as usize;
eprintln!("sp = {:p}", sp as *const u8);
if sp == 0 {
// If the SP is null, then we don't have an implementation for
// getting the SP on this target. Just keep walking the stack,
// but don't make our assertions about the on-stack pointers and
// SP values.
return true;
}
// The stack grows down.
if let Some(child_sp) = child_sp {
assert!(child_sp <= sp);
}
if is_recursive_stack_references {
let r = refs.pop().unwrap();
eprintln!("ref = {:p}", r as *const u8);
if sp != 0 {
assert!(r > sp);
if let Some(child_ref) = child_ref {
assert!(sp >= child_ref);
}
}
child_ref = Some(r);
}
child_sp = Some(sp);
true
}
}
}