cargo-caps 0.0.1

Audit what a crate is capable of by analyzing what linker symbols it emits
Documentation
rules: [
	{
		// Stuff that anyone is allowed to use:
		caps: []
		patterns: [
			// Anonymous functions… I think these are things LLVM generates, and should be fine.
			// Curiously, they only show up in optimized builds.
			"anon.*"

			// NOTE: cargo-caps ignores leading underscores
			// Simple memory stuff:
			".memset_pattern.*"
			"bzero"
			"memcmp"
			"memcpy"
			"memmove"
			"memset_pattern*"
			"memset"
			"strcmp"
			"strcpy"
			"strlen"
			"abort"
			"error"
			"std::sys::pal::unix::os::errno"
			"strerror_r"

			// Math:
			"acos"
			"acosf"
			"atan2"
			"atan2f"
			"cbrt"
			"cbrtf"
			"cos"
			"cosf"
			"exp"
			"exp10"
			"exp10f"
			"exp2"
			"exp2f"
			"expf"
			"fmod"
			"fmodf"
			"hypot"
			"hypotf"
			"log"
			"log10"
			"log10f"
			"log2"
			"log2f"
			"logf"
			"pow"
			"powf"
			"powidf2"
			"powisf2"
			"sin"
			"sincos_stret"
			"sincosf_stret"
			"sinf"
			"tan"
			"tanf"
			"pthread_cond_*"
			"pthread_mutex_*"
			"close" // Closing a FILE is fine

			// Thread Local Variable
			"tlv_atexit"
			"tlv_bootstrap"
			"divt*"
			"muloti*" // Multiply?
			"sdiv*" // unsigned div
			"smod*" // unsigned modulus
			"udiv*" // unsigned div
			"umod*" // unsigned modulus
			"modti*" // modulus
			"dispatch_semaphore_*"
			"rust_eh_personality" // Rust exception handling
			"rust_no_alloc_shim_is_unstable*"
			"CCRandomGenerateBytes"
			"getentropy"
			"rustc_proc_macro_decls_*"

			// From https://gcc.gnu.org/onlinedocs/gccint/Soft-float-library-routines.html
			"__addsf3"
			"__adddf3"
			"__addtf3"
			"__addxf3"
			"__subsf3"
			"__subdf3"
			"__subtf3"
			"__subxf3"
			"__mulsf3"
			"__muldf3"
			"__multf3"
			"__mulxf3"
			"__divsf3"
			"__divdf3"
			"__divtf3"
			"__divxf3"
			"__negsf2"
			"__negdf2"
			"__negtf2"
			"__negxf2"
			"__extendsfdf2"
			"__extendsftf2"
			"__extendsfxf2"
			"__extenddftf2"
			"__extenddfxf2"
			"__truncxfdf2"
			"__trunctfdf2"
			"__truncxfsf2"
			"__trunctfsf2"
			"__truncdfsf2"
			"__fixsfsi"
			"__fixdfsi"
			"__fixtfsi"
			"__fixxfsi"
			"__fixsfdi"
			"__fixdfdi"
			"__fixtfdi"
			"__fixxfdi"
			"__fixsfti"
			"__fixdfti"
			"__fixtfti"
			"__fixxfti"
			"__fixunssfsi"
			"__fixunsdfsi"
			"__fixunstfsi"
			"__fixunsxfsi"
			"__fixunssfdi"
			"__fixunsdfdi"
			"__fixunstfdi"
			"__fixunsxfdi"
			"__fixunssfti"
			"__fixunsdfti"
			"__fixunstfti"
			"__fixunsxfti"
			"__floatsisf"
			"__floatsidf"
			"__floatsitf"
			"__floatsixf"
			"__floatdisf"
			"__floatdidf"
			"__floatditf"
			"__floatdixf"
			"__floattisf"
			"__floattidf"
			"__floattitf"
			"__floattixf"
			"__floatunsisf"
			"__floatunsidf"
			"__floatunsitf"
			"__floatunsixf"
			"__floatundisf"
			"__floatundidf"
			"__floatunditf"
			"__floatundixf"
			"__floatuntisf"
			"__floatuntidf"
			"__floatuntitf"
			"__floatuntixf"
			"__fixsfbitint"
			"__fixdfbitint"
			"__fixxfbitint"
			"__float80"
			"__fixtfbitint"
			"__floatbitintsf"
			"__floatbitintdf"
			"__float80"
			"__floatbitintxf"
			"__floatbitinttf"
			"__floatbitinthf"
			"__bf16"
			"__floatbitintbf"
			"__cmpsf2"
			"__cmpdf2"
			"__cmptf2"
			"__unordsf2"
			"__unorddf2"
			"__unordtf2"
			"__cmpXf2"
			"__eqsf2"
			"__eqdf2"
			"__eqtf2"
			"__nesf2"
			"__nedf2"
			"__netf2"
			"__gesf2"
			"__gedf2"
			"__getf2"
			"__ltsf2"
			"__ltdf2"
			"__lttf2"
			"__lesf2"
			"__ledf2"
			"__letf2"
			"__gtsf2"
			"__gtdf2"
			"__gttf2"
			"__powisf2"
			"__powidf2"
			"__powitf2"
			"__powixf2"
			"__mulsc3"
			"__muldc3"
			"__multc3"
			"__mulxc3"
			"__divsc3"
			"__divdc3"
			"__divtc3"
			"__divxc3"
		]
	}
	{
		caps: ["sysinfo"]
		patterns: [
			"getcwd"
			"getenv"
			"isatty"
			"mach_task_self_" // Access to own PID
			"NSGetArgc"
			"NSGetArgv"
			"NSGetEnviron"
		]
	}
	{
		caps: ["time"]
		patterns: ["gettimeofday"]
	}
	{
		caps: ["fs"]
		patterns: ["dirfd", "fstat", "mmap"]
	}
	{
		caps: []
		patterns: [
			// core has no capabilities
			"core::*"
		]
	}
	{
		caps: ["alloc"]
		patterns: [
			"calloc"
			"free"
			"malloc"
			"rdl_alloc_zeroed"
			"rdl_alloc"
			"rdl_dealloc"
			"rdl_realloc"
			"realloc"
			"rg_oom"
			"rust_alloc_error_handler"
			"rust_alloc_zeroed"
			"rust_alloc"
			"rust_dealloc"
			"rust_realloc"
		]
	}
	{
		caps: ["panic"]
		patterns: [
			"core::panicking::*"
			"rust_begin_unwind"
			"rust_drop_panic"
			"rust_foreign_exception"
			"rust_panic_cleanup"
			"rust_panic"
			"rust_start_panic"
			"Unwind_*" // Rust exception handling
		]
	}
	{
		caps: ["alloc"]
		patterns: ["alloc::*"]
	}

	// NOTE: Everything in std is generally allowed to allocate and panic
	{
		caps: ["alloc", "panic"]
		patterns: [
			"std::backtrace::*"
			"std::collections::*"
			"std::ffi::os_str::*"
			"std::hash::*"
			"std::os::unix::ffi::os_str::*"
			"std::panic::*"
			"std::panicking::*"
			"std::path::Components"
			"std::path::Path::components"
			"std::path::Path::extension::*"
			"std::path::Path::is_absolute"
			"std::path::PathBuf" // NOT ::*, but just `<std::path::PathBuf as core::clone::Clone>::clone` is OK
			"std::process::abort*" // TODO: consider adding special capability for abort/exit
			"std::process::exit*" // TODO: consider adding special capability for abort/exit
			"std::sync::*"
			"std::sys::os_str::*"
			"std::sys::pal::unix::abort_internal*"
			"std::sys::pal::unix::decode_error_kind"
			"std::sys::pal::unix::decode_error_kind"
			"std::sys::pal::unix::sync::*"
			"std::sys::process::unix::common::cstring_array::*"
			"std::sys::random::*" // TODO: consider adding special capability for random
			"std::sys::sync::*"
			"std::sys::thread_local::*"
			"std::thread::current::current"
			"std::thread::local::*"
			"std::thread::Thread::id"
			"std::thread::ThreadId*"
			"std::thread::park"
			"std::os::fd::owned::OwnedFd"
			"CFStringGetCStringPtr"
			"CFRelease"
			"CFStringGetBytes"
			"CFStringGetLength"

			// I doubt these allocate, but 🤷
			"std::char::*"
			"std::f32::*"
			"std::f64::*"
			"std::i128::*"
			"std::i16::*"
			"std::i32::*"
			"std::i64::*"
			"std::i8::*"
			"std::u128::*"
			"std::u16::*"
			"std::u32::*"
			"std::u64::*"
			"std::u8::*"
		]
	}
	{
		caps: ["alloc", "panic", "sysinfo"]
		patterns: [
			"std::env::*"
			"std::sys::backtrace::*"
			"std::sys::io::is_terminal::*"
		]
	}
	{
		caps: ["alloc", "panic", "thread"]
		patterns: ["std::sys::pal::unix::thread::Thread*", "std::thread::*"]
	}
	{
		caps: ["alloc", "panic", "stdio"]
		patterns: [
			"std::io::*"
			"std::os::fd::owned::AsFd"
			"std::os::fd::owned::BorrowedFd::borrow_raw"
			"std::sys::io::io_slice::*"
			"std::sys::pal::unix::stdio::*"
			"std::sys::stdio::*"
			"std::sys::pal::unix::io::*"
		]
	}
	{
		caps: ["alloc", "panic", "fs"]
		patterns: [
			"fcntl"
			"std::fs::*"
			"std::os::unix::fs::*"
			"std::path::*"
			"std::sys::fs::*"
			"std::sys::pal::unix::fs::*"
		]
	}
	{
		caps: ["alloc", "panic", "net"]
		patterns: ["std::net::*", "std::sys::net::*"]
	}
	{
		caps: ["alloc", "panic", "time"]
		patterns: [
			"std::time::*"
			"std::sys::pal::unix::time::*"
			"CFTimeZoneGetName"
			"CFTimeZoneCopySystem"
		]
	}
	{
		// TODO: categorize the rest of std:: :}
		caps: [
			"*" // conservatively assume the worst
		]
		patterns: ["std::*"]
	}
]